elanous 0.2.9 → 0.2.11
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/Y4zKzL62sakG5momz3SoQ/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1394-556de6d71bbdb0fb.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/2310-7a59f043f6db207e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2548-6e316138d347cefe.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-a39d1d9921e10d43.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/507-5acd98bd6dab2d8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5445-745eb795c5963d79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5845-e6c003ce8d5fd36a.js +1 -0
- 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/{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/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-ea5bee9dfae512c7.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/app/_not-found/page-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-1dcdc58fc2de2454.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-6a061bd97f0b9398.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-cb95a7432c9ee744.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-f972fc1c00a62e88.js → page-b12b6d2f8d2d1aea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-b9efe868bfd36255.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-7c97dcdfe2e37a60.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-8fd36984f549270a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-5721537ca8a3598c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-b654240a572e4c48.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-b9750abc897508c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-4cd1de371f8ad048.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-d99f89657828421c.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-50cb2a0eb15e6c83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c8b1ccda6ba7ae98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-d6b1d156fb95e74b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-2a9932ddb62d76bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-9688f5b4f1ff950f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6b15dd6456c5df09.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-adfbd2ba9598e59a.js → page-35414e0a007b4082.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-e7a529e0507ac86c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-e001823c35c9dd67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-371423d1a573d64b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4b764b125339ac17.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cdf8e4b01067bcf1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a24072b35470157.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-94c82eb0ae5abb32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-0be8d4b2ced75ba0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d37cb0d52f9b6bd5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-686da0df9bf23e5c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4dc614f3ce043e63.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-53f80edc6b8dc07c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-d02c782fc792e2af.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-239c17b911b84e72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-dc6a79fb003f746c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-0fffb84cafdc9da6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-1218753c82d585f6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-4b5935e67531efb5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-3285bc87caf1eaa5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-ad553b0e06505ecd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-fca096e3e860306f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ebfa78f0d9885c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-3dc5f21f7e39622d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-c6da2b468454532d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-93bc70e36f595414.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/543f56bcb1f79fca.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 -0
- package/apps/pwa/out/ops/seats/index.txt +30 -0
- 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 -0
- package/apps/pwa/out/today/index.txt +33 -0
- 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/drafts/draft-cleanup.yaml +19 -0
- package/graphs/drafts/recipes.yaml +23 -0
- package/graphs/field/field-feed.yaml +2 -0
- package/graphs/implement-loop.yaml +1 -1
- 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/graphs/run-step.ts +48 -13
- package/plugins/doc-draft/graphs/doc-draft.yaml +3 -3
- package/plugins/doc-draft/graphs/run-step.ts +13 -6
- 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/ci-pwa-build-gate.ts +160 -0
- 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 +54 -8
- package/scripts/coord-digest.ts +199 -0
- package/scripts/coord-post.sh +60 -3
- 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/install.ps1 +68 -9
- package/scripts/install.sh +39 -12
- package/scripts/lib/pwa-scenarios/scenarios.ts +20 -0
- package/scripts/lib/tui-regress-checks.ts +146 -0
- package/scripts/marketing/measure-site-numbers.ts +169 -0
- package/scripts/measure-gate-shards.ts +309 -0
- package/scripts/memory-lifecycle-cycle.ts +2 -2
- package/scripts/mission-request-judge.ts +31 -1
- package/scripts/morning-report.ts +2 -2
- package/scripts/opportunity-scan.ts +1 -1
- package/scripts/ops-now-probe.ts +327 -0
- package/scripts/publish-internal-dist.ts +11 -1
- package/scripts/release-loop/auto-approve-node.ts +21 -4
- package/scripts/release-loop/cut-branch.ts +84 -0
- package/scripts/release-loop/cutoff.ts +19 -8
- package/scripts/release-loop/gate-node.ts +14 -13
- 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 +72 -16
- package/scripts/release-loop/release-readiness.ts +9 -0
- 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 +112 -13
- package/scripts/repo-watch-cycle.ts +1 -1
- package/scripts/retro-cycle.ts +2 -2
- package/scripts/schedule-health-report.ts +1 -1
- package/scripts/signal-digest-cycle.ts +2 -7
- package/scripts/signal-digest-photo.ts +11 -0
- package/scripts/storyboard/storyboard.ts +5 -161
- package/scripts/tech1-public-measure.ts +94 -0
- package/scripts/test-diet/lib.ts +30 -1
- package/scripts/test-diet/node.ts +83 -8
- package/scripts/test-timeout-audit.ts +114 -0
- package/scripts/tree-sync-alert.ts +1 -1
- package/scripts/tui-regress.ts +71 -0
- package/scripts/ux/demo-rehearsal.ts +243 -0
- package/scripts/ux/lib/rehearsal-verdict.ts +73 -0
- package/scripts/waitlist-daily-digest.ts +1 -1
- 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/explainer-video/SKILL.md +4 -0
- package/skills/explainer-video/engine/reel.mjs +18 -13
- package/skills/explainer-video/engine/reel.sh +24 -5
- package/skills/explainer-video/engine/stitch.mjs +145 -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 +36 -0
- package/skills/pitch-deck/template.html +80 -0
- 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/codex-approval-adapter.ts +9 -3
- package/src/acp/core-turn-bridge.ts +117 -18
- package/src/acp/fact-question.ts +11 -0
- package/src/acp/server.ts +53 -9
- package/src/acp/tool-approval.ts +126 -0
- package/src/acp/turn-runner.ts +36 -0
- package/src/agent/monad-agent-turn.ts +8 -0
- package/src/agent-mission/driver.ts +80 -10
- package/src/agent-mission/pty-decision.ts +71 -0
- package/src/agent-mission/review-loop.ts +30 -0
- package/src/ask-user-question/pending-questions.ts +25 -10
- package/src/ask-user-question/types.ts +9 -0
- package/src/auth/setup-link-tokens.ts +16 -5
- package/src/autopilot/build/integrity-gate.ts +12 -0
- package/src/autopilot/build/llm-conflict-merge.ts +16 -3
- package/src/autopilot/tool-registry.ts +2 -0
- package/src/boot/daemon-prompt-turn.ts +8 -0
- package/src/boot/daemon-runtime.ts +9 -3
- package/src/boot/daemon-tools/index.ts +8 -0
- package/src/boot/daemon-tools/types.ts +2 -0
- package/src/boot/daemon-tools/web-search.ts +4 -0
- package/src/card-followup/core.ts +109 -0
- package/src/chat/ctrl-c-in-input.ts +14 -0
- package/src/chat/index.ts +53 -0
- package/src/chat/pickers/state.ts +6 -2
- package/src/cli/agent-cli.ts +7 -0
- package/src/cli/decisions-cli.ts +25 -3
- package/src/cli/doctor-bundle-upload.ts +68 -0
- package/src/cli/doctor-cli.ts +38 -4
- 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/ops-cli.ts +20 -0
- package/src/cli/persona-cli.ts +90 -4
- package/src/cli/plugin-cli.ts +31 -22
- package/src/cli/pod-cli.ts +61 -2
- package/src/cli/pr-cli.ts +82 -17
- package/src/cli/pty-drive-cli.ts +41 -7
- package/src/cli/pty-drive-verdict.ts +40 -0
- package/src/cli/pwa-stop.ts +163 -13
- package/src/cli/pwa-test.ts +3 -0
- package/src/cli/release-cli.ts +80 -24
- package/src/cli/self-update.ts +14 -0
- package/src/cli/setup-cli.ts +43 -1
- package/src/cli/skills-cli.ts +17 -1
- package/src/cli/storyboard-cli.ts +37 -0
- package/src/cli/test-state-dir-flag.ts +11 -4
- package/src/connectors/linear.ts +146 -0
- package/src/context-bus/claude-hooks-install.ts +10 -0
- package/src/context-bus/context-now-surfaces.ts +48 -0
- package/src/context-bus/context-now.ts +104 -0
- package/src/context-bus/coord-events.ts +115 -0
- package/src/context-bus/external-events.ts +52 -0
- package/src/context-bus/long-term-memory.ts +108 -0
- package/src/dashboard/dashboard-boot-fixture.ts +23 -0
- package/src/dashboard/index.ts +63 -21
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +14 -1
- package/src/dashboard/slash-runtime/help-from-registry.ts +43 -28
- package/src/decisions/decision-cards.ts +58 -3
- package/src/decisions/decision-ledger.ts +85 -6
- package/src/decisions/decision-linear-projection.ts +157 -0
- package/src/decisions/web-push-decision-cards.ts +50 -0
- package/src/directive/interpretation-card.ts +36 -0
- 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 +19 -2
- package/src/domains/coo-admin-tool.ts +62 -0
- package/src/domains/core-tools.ts +13 -4
- package/src/domains/elanous-card.ts +29 -0
- package/src/domains/ops-facts-tool.ts +76 -0
- package/src/domains/outbound-alert.ts +46 -13
- package/src/domains/release-tool.ts +168 -0
- package/src/domains/telegram-kind-route.ts +65 -9
- package/src/exec-requests/default-outputs.ts +25 -0
- package/src/exec-requests/planner.ts +106 -28
- package/src/exec-requests/runner.ts +123 -12
- package/src/exec-requests/store.ts +11 -2
- package/src/execution-loop/launch-gate.ts +100 -0
- package/src/field/field-media.ts +10 -7
- package/src/field/field-reel.ts +19 -5
- package/src/field-note/index.ts +201 -0
- package/src/field-note/transcribe.ts +248 -0
- package/src/git-fs/worktree.ts +45 -6
- package/src/graph-kinds/registry.ts +3 -3
- package/src/graph-runner/graph-approval-card.ts +113 -0
- package/src/graph-runner/graph-cli.ts +189 -4
- package/src/graph-runner/graph-grow-llm.ts +37 -0
- package/src/graph-runner/graph-grow.ts +47 -0
- package/src/graph-runner/graph-notify.ts +25 -3
- package/src/graph-runner/runner.ts +453 -35
- package/src/grok/agent-search.ts +8 -2
- package/src/guardian/secret-exposure-scan.ts +101 -0
- package/src/harness/browser-verify.ts +25 -2
- package/src/harness/harness-cli-command.ts +478 -42
- package/src/harness/harness-incidents-writer.fixture.ts +24 -0
- package/src/harness/harness-incidents.ts +129 -0
- package/src/harness/harness-pod-dispatch.ts +43 -23
- package/src/harness/harness-seams.ts +38 -4
- package/src/harness/harness-stop.ts +75 -6
- package/src/harness/launch-registry.ts +91 -0
- package/src/harness/process-garbage.ts +5 -3
- package/src/hitl/clarification-policy.ts +3 -1
- 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 +21 -20
- package/src/index.ts +206 -49
- package/src/intake-plane/author-goals.ts +37 -4
- package/src/intake-plane/categorize.ts +18 -46
- package/src/intake-plane/check.ts +3 -0
- package/src/intake-plane/discord-seat-work.ts +57 -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/seat-doc-route.ts +170 -6
- package/src/intake-plane/telegram-seat-work.ts +80 -4
- package/src/intake-plane/telegram-work.ts +1 -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/cli-maturity.ts +34 -0
- package/src/maturity/feature-maturity.ts +120 -1
- package/src/maturity/tui-slash-maturity.ts +31 -0
- package/src/memory.ts +32 -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/exec-requests.ts +33 -3
- 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 +89 -1
- package/src/nexus/api/inside-events.ts +226 -0
- package/src/nexus/api/meta-api.ts +32 -8
- package/src/nexus/api/missions.ts +6 -1
- package/src/nexus/api/ops-api.ts +10 -1
- package/src/nexus/api/ops-seats-sources.ts +37 -7
- package/src/nexus/api/ops-seats.ts +49 -6
- package/src/nexus/api/outputs-route.ts +44 -0
- package/src/nexus/api/seat-requests.ts +132 -10
- package/src/nexus/api/sessions-store.ts +42 -0
- package/src/nexus/api/setup-codex-login.ts +160 -0
- package/src/nexus/api/sub-seat-charters.ts +34 -0
- package/src/nexus/api/tabs-mutations.ts +3 -1
- package/src/nexus/api/trace.ts +18 -6
- package/src/nexus/api/usage-api.ts +102 -0
- package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
- package/src/nexus/api/workflows.ts +80 -6
- package/src/nexus/index.ts +47 -4
- package/src/nexus/kinds/webterm.ts +2 -1
- package/src/nexus/webterm/pty.ts +6 -2
- package/src/onboarding/cli-auth-status.ts +80 -0
- package/src/onboarding/first-run.ts +89 -0
- package/src/onboarding/lan-address.ts +45 -0
- package/src/onboarding/voice-ai.ts +3 -3
- package/src/onboarding/web-first.ts +119 -24
- package/src/onboarding.ts +4 -0
- package/src/ops-now/ops-now-refresh.ts +100 -0
- 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 +116 -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 +109 -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-store.ts +115 -0
- package/src/project/project-suggestion.ts +16 -0
- package/src/project/session-context.ts +24 -0
- package/src/release-loop/checklist.ts +79 -5
- package/src/release-loop/feature-store.ts +159 -24
- package/src/release-loop/next-md-merge.ts +58 -0
- package/src/release-loop/release-note.ts +59 -4
- package/src/release-loop/release-schedule.ts +53 -0
- package/src/repl/index.ts +7 -0
- package/src/seat-dispatch/ceo-commands.ts +41 -8
- package/src/seat-dispatch/ceo-intent.ts +38 -0
- 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 +750 -0
- package/src/seat-loop/seat-report.ts +99 -0
- package/src/self-dev/decompose.ts +66 -11
- 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 +38 -33
- package/src/self-dev/draft-triage-rules.ts +8 -5
- 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/run-store.ts +10 -1
- 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/execution-clarification.ts +115 -0
- package/src/self-implement/gate-baseline.ts +1 -1
- package/src/self-implement/gate-cli.ts +46 -4
- package/src/self-implement/gate-scope.ts +37 -7
- 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 +22 -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 +279 -12
- package/src/self-implement/pipeline-shape.ts +1 -1
- package/src/self-implement/route-consumer-test-index.ts +122 -0
- package/src/self-implement/run-status-mapping.ts +5 -3
- package/src/self-implement/seams.ts +72 -11
- package/src/self-implement/test-seams.ts +1 -0
- package/src/self-implement/uncommitted-work.ts +59 -0
- package/src/session/chat.ts +2 -0
- package/src/session/index.ts +45 -13
- package/src/shell-env-bootstrap.ts +17 -0
- package/src/skills/gift-install.ts +215 -0
- package/src/skills/tools/web-search.ts +4 -1
- package/src/steward/directive.ts +51 -2
- package/src/steward/launch.ts +266 -0
- package/src/steward/outcome-notify.ts +115 -0
- package/src/steward/steward-cards.ts +25 -11
- package/src/steward/triage-plan.ts +32 -4
- package/src/steward/triage.ts +129 -13
- package/src/steward/working-backwards.ts +64 -0
- package/src/storyboard/storyboard.ts +141 -0
- package/src/task-cards/card-cli.ts +25 -1
- package/src/task-cards/card-store.ts +2 -2
- 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 +29 -7
- package/src/task-orchestrator/surfaces/pod-lease.ts +397 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +214 -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 +153 -0
- package/src/telegram-commands.ts +10 -1
- package/src/telegram-project-command.ts +71 -0
- package/src/telegram-report.ts +29 -19
- package/src/telegram-run.ts +7 -0
- package/src/telegram.ts +58 -11
- package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
- package/src/tool-runtime/types.ts +4 -0
- package/src/tui-client/dashboard-session.ts +2 -0
- package/src/user-config.ts +216 -27
- package/src/version/packed-revision.json +1 -1
- package/src/web-push/notify-exec-request.ts +32 -0
- 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/bFI5EEwg7T6aG88ibX4Zq/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
- package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5080-1613752891fcadb4.js +0 -10
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6090-85a3f05f954e5697.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6284-69db415193d5f8bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7032-f4ef698518fba61c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8067-d976b441a104ab74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8519-5632377cce994f86.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8630-cdfc61e82c653ffc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8894-e263b332208e3957.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-139040d37c79dbc9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9740-8f5ff96c522b5f55.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-fb7c2d458f32fcad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-35e2713597dd24d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-918b656f064577ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-5f30e00693527ebd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-7fbae173b3c103a7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3b4edcce364062ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-c5794f484c251f44.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1130d8eefcd87e76.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-973996d584f008c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-016e2bda04eecb1f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-b4d6d9a3b56f2940.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-ec49a466121233ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-f72db356744ceade.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-a6fd9b50d1b85378.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-8b0402a46a749a3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-037f83e2a1edc8e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-46fedff57d4bec67.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-0cf318e9dcee2bbf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-899b327cb8b6845c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6c1e6ba743a29dfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-1a8e4807292f6b17.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-28deba6bcb834916.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-de68e2205794037d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-c71c33a573230672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-0df30e0c7e50148a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-4fc56790fe0d2682.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-59df2aebb38a7c1e.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-4647be5dbcbd0795.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-e025892bda74b743.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-a0955de73b89f078.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-369846d2921af584.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-72cbc1c8cdd0f65d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-77b28bfb0996d5ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-3220c4934f49c6c2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-90670589b87abea8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-7df9243ed021a4cc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-4498c3853f4f688d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-35bedde6d885f08f.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-6870f30ea99f8346.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/f92f63a5df0ba229.css +0 -1
- package/src/dashboard/turn-typeahead-echo.ts +0 -23
- /package/apps/pwa/out/_next/static/{bFI5EEwg7T6aG88ibX4Zq → Y4zKzL62sakG5momz3SoQ}/_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
|
+
}
|
|
@@ -103,6 +103,12 @@ export interface CodexApprovalAdapter {
|
|
|
103
103
|
onMcpToolCall(req: CodexMcpToolCallRequest): Promise<CodexApprovalDecision>;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
/** The 3-way approval question's id and labels — exported so a surface that
|
|
107
|
+
* answers approvals by yes/no (an ACP turn's client) can recognise it. */
|
|
108
|
+
export const CODEX_APPROVAL_QUESTION_ID = 'codex_approval';
|
|
109
|
+
export const CODEX_APPROVAL_OPT_ONCE = 'Allow once';
|
|
110
|
+
export const CODEX_APPROVAL_OPT_REJECT = 'Reject';
|
|
111
|
+
|
|
106
112
|
/** Build a CodexApprovalAdapter. Intentionally minimal in Phase 3.A —
|
|
107
113
|
* the handlers degrade gracefully when no approver is attached, and
|
|
108
114
|
* the Phase 3.B app-server client will hook these methods up with real
|
|
@@ -131,10 +137,10 @@ export function createCodexApprovalAdapter(
|
|
|
131
137
|
// multi-option question path is used. "Allow for session" maps to codex
|
|
132
138
|
// `acceptForSession` so the sub-agent stops re-prompting for the rest of
|
|
133
139
|
// the run.
|
|
134
|
-
const OPT_ONCE =
|
|
140
|
+
const OPT_ONCE = CODEX_APPROVAL_OPT_ONCE;
|
|
135
141
|
const OPT_SESSION = 'Allow for session';
|
|
136
|
-
const OPT_REJECT =
|
|
137
|
-
const APPROVAL_QID =
|
|
142
|
+
const OPT_REJECT = CODEX_APPROVAL_OPT_REJECT;
|
|
143
|
+
const APPROVAL_QID = CODEX_APPROVAL_QUESTION_ID;
|
|
138
144
|
|
|
139
145
|
/** Ask the user via the MULTI-OPTION question channel: Allow once /
|
|
140
146
|
* Allow for session / Reject. Returns the scoped decision. Only called
|
|
@@ -46,7 +46,11 @@ import { getUserConfig } from '../user-config.js';
|
|
|
46
46
|
import { getModelFamily } from '../models/prompts.js';
|
|
47
47
|
import { resolveModelContextWindow } from '../models/context-window.js';
|
|
48
48
|
import type { AcpServerOptions, AcpTurnContext } from './server.js';
|
|
49
|
+
import { acpToolDenialResult } from './tool-approval.js';
|
|
49
50
|
import { readOriginSessionMeta } from './origin-session-meta.js';
|
|
51
|
+
import { isFactQuestion } from './fact-question.js';
|
|
52
|
+
|
|
53
|
+
const FACT_QUESTION_INSTRUCTION = '사실·최신 정보 질문이다. WebSearch 를 1~2회 쓰고 검색 결과(제목·스니펫·URL)로 답하라. 출처 링크를 붙여라. 셸·브라우저·파일 도구는 검색 결과로 부족할 때만. 도구 예산에 닿으면 지금까지 근거로 답하고 끝에 «더 찾아볼까요?»를 붙여라.';
|
|
50
54
|
|
|
51
55
|
export interface CoreTurnBridgeDeps {
|
|
52
56
|
/** Build the seed message list for this ACP prompt. Implementations
|
|
@@ -112,6 +116,28 @@ export interface CoreTurnBridgeDeps {
|
|
|
112
116
|
* pegging the event loop. */
|
|
113
117
|
export const DEFAULT_BRIDGE_ABORT_POLL_MS = 50;
|
|
114
118
|
|
|
119
|
+
/** PCH-2b — ask the ACP client before a write/shell tool runs. A denied,
|
|
120
|
+
* cancelled or timed-out tool is not run; the LLM gets a «not run» result. */
|
|
121
|
+
export function acpApprovalGatedDispatch(
|
|
122
|
+
turnCtx: AcpTurnContext,
|
|
123
|
+
dispatchTool: CoreTurnDispatchTool,
|
|
124
|
+
signal: AbortSignal,
|
|
125
|
+
): CoreTurnDispatchTool {
|
|
126
|
+
const approveTool = turnCtx.approveTool;
|
|
127
|
+
if (!approveTool) return dispatchTool;
|
|
128
|
+
return async (name, args, dispatchCtx) => {
|
|
129
|
+
if (signal.aborted || turnCtx.isAborted()) return acpToolDenialResult(name, 'cancelled');
|
|
130
|
+
const approval = await approveTool({
|
|
131
|
+
toolCallId: dispatchCtx?.callId ?? `${name}-${Date.now().toString(36)}`,
|
|
132
|
+
toolName: name,
|
|
133
|
+
toolArgs: args,
|
|
134
|
+
});
|
|
135
|
+
if (!approval.allowed) return acpToolDenialResult(name, approval.reason);
|
|
136
|
+
if (signal.aborted || turnCtx.isAborted()) return acpToolDenialResult(name, 'cancelled');
|
|
137
|
+
return dispatchTool(name, args, dispatchCtx);
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
115
141
|
/** Extract the trailing assistant message text from runCoreTurn's
|
|
116
142
|
* `newMessages` array. emitTurnComplete (src/llm.ts:3835) appends
|
|
117
143
|
* `{role:'assistant', content:[{type:'text', text:finalAssistantText}]}`
|
|
@@ -173,7 +199,23 @@ export function bridgeCoreTurnToAcp(
|
|
|
173
199
|
}),
|
|
174
200
|
);
|
|
175
201
|
const modelOverride = deps.resolveModel?.({ sessionId: turnCtx.sessionId, userText: turnCtx.userText });
|
|
176
|
-
const
|
|
202
|
+
const factQuestion = isFactQuestion(turnCtx.userText);
|
|
203
|
+
const explicitMaxToolTurns = deps.resolveMaxToolTurns?.({ sessionId: turnCtx.sessionId });
|
|
204
|
+
const maxToolTurns = explicitMaxToolTurns ?? (factQuestion ? getUserConfig().chat.factQuestion.maxToolTurns : undefined);
|
|
205
|
+
const turnMessages: LLMMessage[] = factQuestion
|
|
206
|
+
? [{ role: 'system', content: FACT_QUESTION_INSTRUCTION }, ...messages]
|
|
207
|
+
: messages;
|
|
208
|
+
let toolCallCount = 0;
|
|
209
|
+
const toolKinds = new Set<string>();
|
|
210
|
+
const observeToolBudget = () => {
|
|
211
|
+
try {
|
|
212
|
+
debug.log('chat.turn', 'tool-budget', {
|
|
213
|
+
factQuestion, maxToolTurns: maxToolTurns ?? null,
|
|
214
|
+
count: toolCallCount, kinds: [...toolKinds],
|
|
215
|
+
});
|
|
216
|
+
} catch { /* observation cannot interrupt a turn */ }
|
|
217
|
+
};
|
|
218
|
+
observeToolBudget();
|
|
177
219
|
|
|
178
220
|
// 2026-05-03 PM++ — Track streamed text so onTurnComplete can
|
|
179
221
|
// detect runtime-injected synthesis (W5-E/W5-F/W5-G) and surface
|
|
@@ -235,17 +277,29 @@ export function bridgeCoreTurnToAcp(
|
|
|
235
277
|
} catch {
|
|
236
278
|
// Observability must not prevent the turn from reaching its dispatcher.
|
|
237
279
|
}
|
|
280
|
+
const approvedDispatch = acpApprovalGatedDispatch(turnCtx, deps.dispatchTool, ctrl.signal);
|
|
281
|
+
const dispatchTool: CoreTurnDispatchTool = factQuestion && maxToolTurns !== undefined && maxToolTurns > 0
|
|
282
|
+
? async (name, args, dispatchCtx) => {
|
|
283
|
+
if (toolCallCount >= maxToolTurns) {
|
|
284
|
+
return { error: 'Tool budget reached. Answer using the evidence already collected.' };
|
|
285
|
+
}
|
|
286
|
+
toolCallCount += 1;
|
|
287
|
+
toolKinds.add(name);
|
|
288
|
+
observeToolBudget();
|
|
289
|
+
return approvedDispatch(name, args, dispatchCtx);
|
|
290
|
+
}
|
|
291
|
+
: approvedDispatch;
|
|
238
292
|
await runTurnDispatch({
|
|
239
293
|
sessionId: turnCtx.sessionId,
|
|
240
294
|
...(originSessionId ? { originSessionId } : {}),
|
|
241
295
|
...(turnCtx.userText ? { userText: turnCtx.userText } : {}),
|
|
242
|
-
messages,
|
|
296
|
+
messages: turnMessages,
|
|
243
297
|
tools,
|
|
244
|
-
dispatchTool
|
|
298
|
+
dispatchTool,
|
|
245
299
|
signal: ctrl.signal,
|
|
246
300
|
...(modelOverride !== undefined ? { modelOverride } : {}),
|
|
247
301
|
...(maxToolTurns !== undefined ? { maxToolTurns } : {}),
|
|
248
|
-
...(deps.budgetGrant !== undefined ? { budgetGrant: deps.budgetGrant } : {}),
|
|
302
|
+
...((!factQuestion || explicitMaxToolTurns !== undefined) && deps.budgetGrant !== undefined ? { budgetGrant: deps.budgetGrant } : {}),
|
|
249
303
|
callbacks: {
|
|
250
304
|
onText: (delta) => {
|
|
251
305
|
// Fire-and-forget: ACP `push` is async but the core-turn
|
|
@@ -262,7 +316,14 @@ export function bridgeCoreTurnToAcp(
|
|
|
262
316
|
// callers see today. Fire-and-forget for the same reason
|
|
263
317
|
// onText is: callbacks are synchronous, `turnCtx.push*` is
|
|
264
318
|
// async, ordering is preserved by the SDK.
|
|
265
|
-
onToolCall: (call) => {
|
|
319
|
+
onToolCall: (call) => {
|
|
320
|
+
if (!factQuestion || maxToolTurns === undefined || maxToolTurns <= 0) {
|
|
321
|
+
toolCallCount += 1;
|
|
322
|
+
toolKinds.add(call.name);
|
|
323
|
+
observeToolBudget();
|
|
324
|
+
}
|
|
325
|
+
void turnCtx.pushToolCall(call);
|
|
326
|
+
},
|
|
266
327
|
onToolResult: (call) => { void turnCtx.pushToolResult(call); },
|
|
267
328
|
onUsage: (usage) => { void turnCtx.pushUsage(usage); },
|
|
268
329
|
// Codex Responses API reasoning summary stream. Currently
|
|
@@ -301,26 +362,64 @@ export function bridgeCoreTurnToAcp(
|
|
|
301
362
|
// re-emit would cause the "displayed then deleted then
|
|
302
363
|
// re-displayed" flicker the user reported.
|
|
303
364
|
const finalAssistantText = extractLastAssistantText(newMessages);
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
365
|
+
const budgetReached = factQuestion && maxToolTurns !== undefined
|
|
366
|
+
&& maxToolTurns > 0 && toolCallCount >= maxToolTurns;
|
|
367
|
+
const followup = '더 찾아볼까요?';
|
|
368
|
+
const needsFollowup = budgetReached && finalAssistantText !== null
|
|
369
|
+
&& finalAssistantText.trim().length > 0
|
|
370
|
+
&& !finalAssistantText.trimEnd().endsWith(followup);
|
|
371
|
+
let lastAssistantIndex = -1;
|
|
372
|
+
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
373
|
+
if (newMessages[i]?.role === 'assistant') { lastAssistantIndex = i; break; }
|
|
374
|
+
}
|
|
375
|
+
const followupSuffix = `\n${followup}`;
|
|
376
|
+
const completedMessages: LLMMessage[] = needsFollowup
|
|
377
|
+
? newMessages.map((message, index) => {
|
|
378
|
+
if (index !== lastAssistantIndex) return message;
|
|
379
|
+
if (typeof message.content === 'string') {
|
|
380
|
+
return { ...message, content: message.content + followupSuffix };
|
|
381
|
+
}
|
|
382
|
+
if (Array.isArray(message.content)) {
|
|
383
|
+
let lastTextIndex = -1;
|
|
384
|
+
for (let blockIndex = message.content.length - 1; blockIndex >= 0; blockIndex--) {
|
|
385
|
+
if (message.content[blockIndex]?.type === 'text') { lastTextIndex = blockIndex; break; }
|
|
386
|
+
}
|
|
387
|
+
if (lastTextIndex >= 0) {
|
|
388
|
+
return { ...message, content: message.content.map((block, blockIndex) =>
|
|
389
|
+
blockIndex === lastTextIndex && block.type === 'text'
|
|
390
|
+
? { ...block, text: block.text + followupSuffix }
|
|
391
|
+
: block) };
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return message;
|
|
395
|
+
})
|
|
396
|
+
: newMessages;
|
|
397
|
+
const visibleFinalText = needsFollowup ? extractLastAssistantText(completedMessages) : finalAssistantText;
|
|
398
|
+
const originalFinalStreamed = needsFollowup && finalAssistantText !== null
|
|
307
399
|
&& streamedTextSum.endsWith(finalAssistantText);
|
|
400
|
+
const synthesisAlreadyStreamed =
|
|
401
|
+
visibleFinalText !== null
|
|
402
|
+
&& visibleFinalText.length > 0
|
|
403
|
+
&& streamedTextSum.endsWith(visibleFinalText);
|
|
308
404
|
const needsReSurface =
|
|
309
|
-
|
|
310
|
-
&&
|
|
311
|
-
&& !synthesisAlreadyStreamed
|
|
312
|
-
|
|
405
|
+
visibleFinalText !== null
|
|
406
|
+
&& visibleFinalText !== streamedTextSum
|
|
407
|
+
&& !synthesisAlreadyStreamed
|
|
408
|
+
&& !originalFinalStreamed;
|
|
409
|
+
if (debug.enabled && visibleFinalText !== null) {
|
|
313
410
|
debug.log('llm.synthesis-surface', 'acp-bridge.surface-final-text', {
|
|
314
411
|
streamedChars: streamedTextSum.length,
|
|
315
|
-
finalChars:
|
|
316
|
-
delta:
|
|
412
|
+
finalChars: visibleFinalText.length,
|
|
413
|
+
delta: visibleFinalText.length - streamedTextSum.length,
|
|
317
414
|
startsWithStreamed: streamedTextSum.length > 0
|
|
318
|
-
&&
|
|
415
|
+
&& visibleFinalText.startsWith(streamedTextSum),
|
|
319
416
|
endsWithStreamedTail: synthesisAlreadyStreamed,
|
|
320
417
|
needsReSurface,
|
|
321
418
|
});
|
|
322
419
|
}
|
|
323
|
-
if (
|
|
420
|
+
if (originalFinalStreamed) {
|
|
421
|
+
void turnCtx.push(followupSuffix);
|
|
422
|
+
} else if (needsReSurface) {
|
|
324
423
|
// Emit a clear-then-replace pair so clients that follow
|
|
325
424
|
// the empty-chunk-as-clear convention (dashboard plain
|
|
326
425
|
// chat) reset their per-round buffer before receiving
|
|
@@ -329,12 +428,12 @@ export function bridgeCoreTurnToAcp(
|
|
|
329
428
|
// would only have the new finalAssistantText delta to
|
|
330
429
|
// work with anyway).
|
|
331
430
|
void turnCtx.push('');
|
|
332
|
-
void turnCtx.push(
|
|
431
|
+
void turnCtx.push(visibleFinalText!);
|
|
333
432
|
}
|
|
334
433
|
if (deps.onTurnComplete) {
|
|
335
434
|
await deps.onTurnComplete({
|
|
336
435
|
sessionId: turnCtx.sessionId,
|
|
337
|
-
newMessages,
|
|
436
|
+
newMessages: completedMessages,
|
|
338
437
|
});
|
|
339
438
|
}
|
|
340
439
|
},
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function isFactQuestion(userText: string): boolean {
|
|
2
|
+
const text = userText.trim();
|
|
3
|
+
if (!text || text.length > 120 || /[\r\n]/.test(text)) return false;
|
|
4
|
+
if (/`|\bsrc\/|(?:^|[\s/])[^\s/]+\.(?:ts|tsx|js|jsx|json|md|py|sh|yaml|yml)\b|고쳐|구현|실행|만들어|수정|디버그|파일|읽어|열어|저장|작성|삭제|편집|검색해|찾아줘|보여줘|\/cc\b|delegate_code_agent/i.test(text)) return false;
|
|
5
|
+
// A request («…해줘?», «재시작해», «restart …») is work, not a fact question — even with a «?» or «지금»(round 3: «지금 서버를 재시작해줘?»).
|
|
6
|
+
const request = text.replace(/알려\s*(?:줘|주세요|줄래|주실래요)[??]?$/, '');
|
|
7
|
+
if (/(?:해|해\s*줘|해\s*주세요|하세요|해라|하자|줘|주세요|줄래|주실래요|봐|봐줘)[??]?$/.test(request)) return false;
|
|
8
|
+
if (/재시작|시작|중지|멈춰|꺼|켜|설치|배포|돌려|보내|올려|지워|바꿔|추가|업데이트|재부팅|재실행|정리|등록|\b(?:restart|start|stop|run|install|deploy|delete|remove|create|update|fix|kill|reboot)\b/i.test(text)) return false;
|
|
9
|
+
if (!/[??]$|(?:뭐야|무엇인가요|인가요|나요|입니까|얼마야|언제야|누구야|알려줘|알려주세요)$/.test(text)) return false;
|
|
10
|
+
return /최근|최신|지금|현재|몇|언제|누가|누구|얼마|가격|버전|출시|최저시급|\b(?:latest|current|when|who|how many|how much|price|version|release)\b/i.test(text);
|
|
11
|
+
}
|
package/src/acp/server.ts
CHANGED
|
@@ -101,6 +101,8 @@ import { readOriginSessionMeta } from './origin-session-meta.js';
|
|
|
101
101
|
import type { CodexPlugin } from './codex-plugins.js';
|
|
102
102
|
import { flattenMcpServersToCodexConfig } from './codex-approval-adapter.js';
|
|
103
103
|
import { runAcpTurn } from './turn-runner.js';
|
|
104
|
+
import type { AcpPermissionApprovalRequest } from './client.js';
|
|
105
|
+
import { createAcpSessionApprovalPolicy, type AcpToolApprovalResult } from './tool-approval.js';
|
|
104
106
|
import { projectPwaToolResult, type ToolResultMeta } from '../nexus/api/meta-api.js';
|
|
105
107
|
import type { LlmBrand } from '../llm-vision-capability.js';
|
|
106
108
|
import {
|
|
@@ -233,9 +235,14 @@ export interface AcpServerOptions {
|
|
|
233
235
|
* receives the user message text and a push() for streaming back
|
|
234
236
|
* assistant chunks. When omitted, the server echoes the prompt. */
|
|
235
237
|
runTurn?: (ctx: AcpTurnContext) => Promise<void>;
|
|
238
|
+
/** PCH-2b — ask the client before write/shell tools run ('ask', default).
|
|
239
|
+
* 'off' keeps the host's own approvals (the in-process TUI dashboard). */
|
|
240
|
+
toolApproval?: 'ask' | 'off';
|
|
236
241
|
/** ACP standalone entry: require session cwd or an explicit boot default. */
|
|
237
242
|
requireSessionToolCwd?: boolean;
|
|
238
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;
|
|
239
246
|
/** Test seam for exercising stdio EOF with controlled byte streams. */
|
|
240
247
|
stdioInput?: ReadableStream<Uint8Array>;
|
|
241
248
|
stdioOutput?: WritableStream<Uint8Array>;
|
|
@@ -850,6 +857,8 @@ export interface AcpTurnContext {
|
|
|
850
857
|
toolArgs?: Record<string, unknown>;
|
|
851
858
|
timeoutMs?: number;
|
|
852
859
|
}) => Promise<AcpApprovalDecision>;
|
|
860
|
+
/** The session-scoped gate used by core-turn tool dispatchers. */
|
|
861
|
+
approveTool?: (req: Parameters<AcpTurnContext['requestApproval']>[0]) => Promise<AcpToolApprovalResult>;
|
|
853
862
|
}
|
|
854
863
|
|
|
855
864
|
/** F1 — Phase 3 · resolved decision from `AcpTurnContext.requestApproval`.
|
|
@@ -866,6 +875,14 @@ export type AcpApprovalDecision =
|
|
|
866
875
|
* `_PERMISSION_DEFAULT_TIMEOUT_S`; overrideable per call. */
|
|
867
876
|
export const DEFAULT_APPROVAL_TIMEOUT_MS = 60_000;
|
|
868
877
|
|
|
878
|
+
export {
|
|
879
|
+
acpToolDenialResult,
|
|
880
|
+
createAcpSessionApprovalPolicy,
|
|
881
|
+
requiresAcpToolApproval,
|
|
882
|
+
type AcpToolApprovalResult,
|
|
883
|
+
type AcpToolDenialReason,
|
|
884
|
+
} from './tool-approval.js';
|
|
885
|
+
|
|
869
886
|
/** ACP streaming Phase E (PLAN-pwa-webterm-voice-control v1.2 · 2026-05-07) —
|
|
870
887
|
* module-level handle to the broadcaster owned by the active runAcpServer
|
|
871
888
|
* instance. The chat REST handler (`src/nexus/api/meta-api.ts handlePromptStreamPost`)
|
|
@@ -991,6 +1008,7 @@ interface AcpServerContext {
|
|
|
991
1008
|
/** One skip diagnostic per session, cleared when its last peer leaves. */
|
|
992
1009
|
plainEnvelopeLogged: Set<string>;
|
|
993
1010
|
dualRole: DualRoleManager;
|
|
1011
|
+
approvalPolicy: ReturnType<typeof createAcpSessionApprovalPolicy>;
|
|
994
1012
|
/** Mints the unique suffix of a new session id. Injected so tests can
|
|
995
1013
|
* pin it deterministically — production wires `mintAcpSessionToken`. */
|
|
996
1014
|
nextSessionToken: () => string;
|
|
@@ -1054,7 +1072,7 @@ function wireAcpConnection(
|
|
|
1054
1072
|
stream: ReturnType<typeof ndJsonStream>,
|
|
1055
1073
|
ctx: AcpServerContext,
|
|
1056
1074
|
): AgentSideConnection {
|
|
1057
|
-
const { sessions, sessionPeers, awarePeers, plainEnvelopeLogged, dualRole, opts } = ctx;
|
|
1075
|
+
const { sessions, sessionPeers, awarePeers, plainEnvelopeLogged, dualRole, approvalPolicy, opts } = ctx;
|
|
1058
1076
|
// 2026-05-13 (M2 of AskUserQuestion cross-surface) — bound connection
|
|
1059
1077
|
// widened to expose `extMethod` + `extNotification` (SDK's elanous
|
|
1060
1078
|
// extension escape hatch). pushAskRequest / pushAskCancel route through
|
|
@@ -1771,7 +1789,9 @@ function wireAcpConnection(
|
|
|
1771
1789
|
);
|
|
1772
1790
|
};
|
|
1773
1791
|
const requestApproval: AcpTurnContext['requestApproval'] = async (approvalReq) => {
|
|
1774
|
-
const timeoutMs = approvalReq.timeoutMs
|
|
1792
|
+
const timeoutMs = approvalReq.timeoutMs
|
|
1793
|
+
?? (await import('../user-config.js')).getUserConfig().acp.toolApproval?.timeoutMs
|
|
1794
|
+
?? DEFAULT_APPROVAL_TIMEOUT_MS;
|
|
1775
1795
|
const optionBase = `${approvalReq.toolCallId}-`;
|
|
1776
1796
|
const options = [
|
|
1777
1797
|
{ optionId: `${optionBase}allow-once`, name: 'Allow once', kind: 'allow_once' as const },
|
|
@@ -1787,6 +1807,8 @@ function wireAcpConnection(
|
|
|
1787
1807
|
},
|
|
1788
1808
|
options,
|
|
1789
1809
|
});
|
|
1810
|
+
// A late rejection after the timeout won the race must not go unhandled.
|
|
1811
|
+
permissionPromise.catch(() => undefined);
|
|
1790
1812
|
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
1791
1813
|
const timeoutPromise = new Promise<'timeout'>((resolve) => {
|
|
1792
1814
|
timer = setTimeout(() => resolve('timeout'), timeoutMs);
|
|
@@ -1972,6 +1994,7 @@ function wireAcpConnection(
|
|
|
1972
1994
|
}
|
|
1973
1995
|
}
|
|
1974
1996
|
|
|
1997
|
+
const rejectedThisTurn = new Set<string>();
|
|
1975
1998
|
const turnCtx: AcpTurnContext = {
|
|
1976
1999
|
sessionId: req.sessionId,
|
|
1977
2000
|
cwd: s.cwd,
|
|
@@ -1987,6 +2010,10 @@ function wireAcpConnection(
|
|
|
1987
2010
|
pushSessionUpdate,
|
|
1988
2011
|
pushUsage,
|
|
1989
2012
|
requestApproval,
|
|
2013
|
+
...(opts.toolApproval !== 'off'
|
|
2014
|
+
? { approveTool: (approvalReq: Parameters<AcpTurnContext['requestApproval']>[0]) =>
|
|
2015
|
+
approvalPolicy.resolve(req.sessionId, approvalReq, requestApproval, rejectedThisTurn) }
|
|
2016
|
+
: {}),
|
|
1990
2017
|
};
|
|
1991
2018
|
|
|
1992
2019
|
// RC — intercept hook runs first. Lets the host treat the
|
|
@@ -2020,6 +2047,20 @@ function wireAcpConnection(
|
|
|
2020
2047
|
chatId: req.sessionId,
|
|
2021
2048
|
cwd: s.cwd,
|
|
2022
2049
|
codexArgs: s.codexArgs,
|
|
2050
|
+
...(turnCtx.approveTool ? {
|
|
2051
|
+
// PCH-2b — codex asks this turn's ACP client instead of auto-approving.
|
|
2052
|
+
permissionApprover: async (approvalReq: AcpPermissionApprovalRequest) => {
|
|
2053
|
+
if (s.aborted) return false;
|
|
2054
|
+
const decision = await turnCtx.approveTool!({
|
|
2055
|
+
toolCallId: `codex-${randomBytes(6).toString('hex')}`,
|
|
2056
|
+
// «codex exec» · «codex network» · «codex mcp» — allow-always is per kind.
|
|
2057
|
+
toolName: /^codex [a-z]+/.exec(approvalReq.title)?.[0] ?? `codex ${approvalReq.kind ?? 'action'}`,
|
|
2058
|
+
...(approvalReq.rawInput && typeof approvalReq.rawInput === 'object' && !Array.isArray(approvalReq.rawInput)
|
|
2059
|
+
? { toolArgs: approvalReq.rawInput as Record<string, unknown> } : {}),
|
|
2060
|
+
});
|
|
2061
|
+
return decision.allowed && !s.aborted;
|
|
2062
|
+
},
|
|
2063
|
+
} : {}),
|
|
2023
2064
|
streamer: { edit: (text) => { void push(text); } },
|
|
2024
2065
|
});
|
|
2025
2066
|
} else if (opts.runTurn) {
|
|
@@ -2151,7 +2192,8 @@ function wireAcpConnection(
|
|
|
2151
2192
|
throw new Error('terminal/spawn: sessionId required');
|
|
2152
2193
|
}
|
|
2153
2194
|
const tid = resolveAcpTerminalId(p.terminalId);
|
|
2154
|
-
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();
|
|
2155
2197
|
const cols = typeof p.cols === 'number' && p.cols > 0 ? p.cols : 80;
|
|
2156
2198
|
const rows = typeof p.rows === 'number' && p.rows > 0 ? p.rows : 24;
|
|
2157
2199
|
|
|
@@ -2169,8 +2211,8 @@ function wireAcpConnection(
|
|
|
2169
2211
|
const adopted = matches.find((match) => match.pt.isAlive);
|
|
2170
2212
|
const existing = sameSession?.isAlive ? sameSession : adopted?.pt;
|
|
2171
2213
|
if (existing) {
|
|
2214
|
+
registerPreviewTerminalForWebTap(existing, p.sessionId, tid, handle);
|
|
2172
2215
|
if (existing !== sameSession && adopted) {
|
|
2173
|
-
registerPreviewTerminalForWebTap(existing, p.sessionId, tid, handle);
|
|
2174
2216
|
debug.log('webterm.acp', 'spawn.adopt', {
|
|
2175
2217
|
terminalId: tid, fromSessions: adopted.sessionIds, toSession: p.sessionId,
|
|
2176
2218
|
});
|
|
@@ -2195,7 +2237,7 @@ function wireAcpConnection(
|
|
|
2195
2237
|
}
|
|
2196
2238
|
|
|
2197
2239
|
const { PreviewTerminal } = await import('../preview/terminal.js');
|
|
2198
|
-
const pt = new PreviewTerminal({
|
|
2240
|
+
const pt = (opts.createWebTerminal ?? ((terminalOpts) => new PreviewTerminal(terminalOpts)))({
|
|
2199
2241
|
cols, rows, cwd,
|
|
2200
2242
|
// Web-terminal child shell renders inside the PWA's xterm.js,
|
|
2201
2243
|
// which implements the xterm-256color terminfo. When the daemon
|
|
@@ -2207,10 +2249,10 @@ function wireAcpConnection(
|
|
|
2207
2249
|
// appear duplicated. Pinning TERM to xterm-256color matches
|
|
2208
2250
|
// the actual rendering surface and makes the redraws idempotent.
|
|
2209
2251
|
termName: 'xterm-256color',
|
|
2210
|
-
//
|
|
2211
|
-
//
|
|
2212
|
-
//
|
|
2213
|
-
useRegistry:
|
|
2252
|
+
// The shared PTY bus delivers output to PreviewTerminal's headless
|
|
2253
|
+
// renderer and ACP taps. The direct /dev/fd duplicate can observe
|
|
2254
|
+
// shell exit without ever reading its prompt (black web terminal).
|
|
2255
|
+
useRegistry: true,
|
|
2214
2256
|
...(typeof p.shell === 'string' && p.shell.length > 0 ? { shell: p.shell } : {}),
|
|
2215
2257
|
onExit: () => {
|
|
2216
2258
|
void import('../web-terminal/preview-tap-registry.js')
|
|
@@ -3343,6 +3385,7 @@ function wireAcpConnection(
|
|
|
3343
3385
|
if (remaining === 0) {
|
|
3344
3386
|
sessionPeers.delete(sid);
|
|
3345
3387
|
plainEnvelopeLogged.delete(sid);
|
|
3388
|
+
approvalPolicy.clearSession(sid);
|
|
3346
3389
|
}
|
|
3347
3390
|
if (debug.enabled) {
|
|
3348
3391
|
debug.log('acp.peer.unregister', sid, { remainingPeers: remaining });
|
|
@@ -3487,6 +3530,7 @@ export async function runAcpServer(opts: AcpServerOptions = {}): Promise<void> {
|
|
|
3487
3530
|
awarePeers,
|
|
3488
3531
|
plainEnvelopeLogged,
|
|
3489
3532
|
dualRole,
|
|
3533
|
+
approvalPolicy: createAcpSessionApprovalPolicy(),
|
|
3490
3534
|
nextSessionToken: mintAcpSessionToken,
|
|
3491
3535
|
agentName: opts.agentName ?? 'elanous-agent',
|
|
3492
3536
|
agentVersion: opts.agentVersion ?? readPkgVersion(),
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// PCH-2b (0.2.10 · security D-20261002-08) — ACP turns ask the client before
|
|
2
|
+
// write/shell tools run; «allow always» is remembered per session and tool.
|
|
3
|
+
// Goal: 내부 문서 `ASK-pwa-chat-turns-run-write-and-shell-tools-without-approval-2026-10-02`
|
|
4
|
+
import { debug } from '../debug/log.js';
|
|
5
|
+
import type { AcpApprovalDecision, AcpTurnContext } from './server.js';
|
|
6
|
+
|
|
7
|
+
/** PCH-2b — tools that write files or run shell commands. ACP turns (PWA·iOS·
|
|
8
|
+
* remote TUI) ask the client before these run; everything else runs as before.
|
|
9
|
+
* One list, here, because the daemon catalog has no read-only/mutating flag. */
|
|
10
|
+
const ACP_APPROVAL_TOOLS = new Set([
|
|
11
|
+
'write', 'edit', 'multiedit', 'notebookedit', 'applypatch', 'apply_patch', 'patch',
|
|
12
|
+
'bash', 'shell', 'runshell', 'exec_command',
|
|
13
|
+
'ptyshellstart', 'ptyshellsend', 'webterminalinput',
|
|
14
|
+
'delegate_code_agent',
|
|
15
|
+
]);
|
|
16
|
+
export function requiresAcpToolApproval(toolName: string): boolean {
|
|
17
|
+
const name = toolName.startsWith('functions.') ? toolName.slice('functions.'.length) : toolName;
|
|
18
|
+
// Codex app-server only sends a permission request when it wants to act.
|
|
19
|
+
return ACP_APPROVAL_TOOLS.has(name.toLowerCase()) || name.startsWith('codex ');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type AcpToolDenialReason = 'rejected' | 'cancelled' | 'timeout' | 'error';
|
|
23
|
+
export type AcpToolApprovalResult =
|
|
24
|
+
| { allowed: true }
|
|
25
|
+
| { allowed: false; reason: AcpToolDenialReason };
|
|
26
|
+
|
|
27
|
+
/** The tool result the LLM sees when a protected tool was not run. */
|
|
28
|
+
export function acpToolDenialResult(toolName: string, reason: AcpToolDenialReason): { error: string } {
|
|
29
|
+
if (reason === 'rejected') {
|
|
30
|
+
return { error: `${toolName}: 사람이 이 호출을 거절했다. 같은 턴에서 같은 도구를 다시 요청하지 말고, 이유를 묻거나 다른 길을 제안하라 — 실행하지 않았다 (tool not run: approval ${reason})` };
|
|
31
|
+
}
|
|
32
|
+
if (reason === 'timeout') {
|
|
33
|
+
return { error: `${toolName}: 사람의 답이 없었다(시한 초과) — 실행하지 않았다. 사용자에게 한 줄로 알려라 (tool not run: approval ${reason})` };
|
|
34
|
+
}
|
|
35
|
+
const why = reason === 'cancelled' ? '승인 요청이 취소됐다' : '승인을 받지 못했다';
|
|
36
|
+
return { error: `${toolName}: ${why} — 실행하지 않았다 (tool not run: approval ${reason})` };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** One policy per ACP server: grants are scoped to the session AND exact tool
|
|
40
|
+
* name, not to a turn, connection, argument set, or other session. */
|
|
41
|
+
export function createAcpSessionApprovalPolicy(): {
|
|
42
|
+
resolve: (
|
|
43
|
+
sessionId: string,
|
|
44
|
+
request: Parameters<AcpTurnContext['requestApproval']>[0],
|
|
45
|
+
requestApproval: AcpTurnContext['requestApproval'],
|
|
46
|
+
rejectedThisTurn?: Set<string>,
|
|
47
|
+
) => Promise<AcpToolApprovalResult>;
|
|
48
|
+
clearSession: (sessionId: string) => void;
|
|
49
|
+
} {
|
|
50
|
+
const alwaysAllowed = new Map<string, Set<string>>();
|
|
51
|
+
const sessionGenerations = new Map<string, number>();
|
|
52
|
+
const observe = (event: 'requested' | 'decided' | 'timeout' | 'remembered', sessionId: string, tool: string, outcome?: string) => {
|
|
53
|
+
// Tool arguments are deliberately not logged.
|
|
54
|
+
debug.log('acp.approval', event, { sessionId, tool, ...(outcome !== undefined ? { outcome } : {}) });
|
|
55
|
+
};
|
|
56
|
+
// Same-turn calls to one tool are asked one at a time, so a concurrent second call sees the first's denial
|
|
57
|
+
// instead of opening a second sheet (round 1 should-fix).
|
|
58
|
+
const turnInflight = new WeakMap<Set<string>, Map<string, Promise<void>>>();
|
|
59
|
+
const decide = async (
|
|
60
|
+
sessionId: string,
|
|
61
|
+
request: Parameters<AcpTurnContext['requestApproval']>[0],
|
|
62
|
+
requestApproval: AcpTurnContext['requestApproval'],
|
|
63
|
+
rejectedThisTurn?: Set<string>,
|
|
64
|
+
): Promise<AcpToolApprovalResult> => {
|
|
65
|
+
if (rejectedThisTurn?.has(request.toolName)) {
|
|
66
|
+
debug.log('acp.approval', 'repeat-denied', { sessionId, tool: request.toolName });
|
|
67
|
+
return { allowed: false, reason: 'rejected' };
|
|
68
|
+
}
|
|
69
|
+
if (alwaysAllowed.get(sessionId)?.has(request.toolName)) {
|
|
70
|
+
observe('remembered', sessionId, request.toolName, 'allow-always');
|
|
71
|
+
return { allowed: true };
|
|
72
|
+
}
|
|
73
|
+
const generation = sessionGenerations.get(sessionId) ?? 0;
|
|
74
|
+
observe('requested', sessionId, request.toolName);
|
|
75
|
+
let decision: AcpApprovalDecision;
|
|
76
|
+
try {
|
|
77
|
+
decision = await requestApproval(request);
|
|
78
|
+
} catch {
|
|
79
|
+
observe('decided', sessionId, request.toolName, 'error');
|
|
80
|
+
return { allowed: false, reason: 'error' };
|
|
81
|
+
}
|
|
82
|
+
observe(decision === 'timeout' ? 'timeout' : 'decided', sessionId, request.toolName, decision);
|
|
83
|
+
if (generation !== (sessionGenerations.get(sessionId) ?? 0)) return { allowed: false, reason: 'cancelled' };
|
|
84
|
+
if (decision === 'allow-always') {
|
|
85
|
+
let tools = alwaysAllowed.get(sessionId);
|
|
86
|
+
if (!tools) {
|
|
87
|
+
tools = new Set();
|
|
88
|
+
alwaysAllowed.set(sessionId, tools);
|
|
89
|
+
}
|
|
90
|
+
tools.add(request.toolName);
|
|
91
|
+
}
|
|
92
|
+
if (decision === 'allow-once' || decision === 'allow-always') return { allowed: true };
|
|
93
|
+
if (decision === 'deny-once' || decision === 'deny-always') rejectedThisTurn?.add(request.toolName);
|
|
94
|
+
return {
|
|
95
|
+
allowed: false,
|
|
96
|
+
reason: decision === 'timeout' ? 'timeout' : decision === 'cancelled' ? 'cancelled' : 'rejected',
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
return {
|
|
100
|
+
async resolve(sessionId, request, requestApproval, rejectedThisTurn) {
|
|
101
|
+
if (!requiresAcpToolApproval(request.toolName)) return { allowed: true };
|
|
102
|
+
if (!rejectedThisTurn) return decide(sessionId, request, requestApproval);
|
|
103
|
+
let inflight = turnInflight.get(rejectedThisTurn);
|
|
104
|
+
if (!inflight) {
|
|
105
|
+
inflight = new Map();
|
|
106
|
+
turnInflight.set(rejectedThisTurn, inflight);
|
|
107
|
+
}
|
|
108
|
+
const prior = inflight.get(request.toolName);
|
|
109
|
+
let release!: () => void;
|
|
110
|
+
const mine = new Promise<void>((done) => { release = done; });
|
|
111
|
+
const chained = (prior ?? Promise.resolve()).then(() => mine);
|
|
112
|
+
inflight.set(request.toolName, chained);
|
|
113
|
+
try {
|
|
114
|
+
if (prior) await prior;
|
|
115
|
+
return await decide(sessionId, request, requestApproval, rejectedThisTurn);
|
|
116
|
+
} finally {
|
|
117
|
+
release();
|
|
118
|
+
if (inflight.get(request.toolName) === chained) inflight.delete(request.toolName);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
clearSession(sessionId) {
|
|
122
|
+
alwaysAllowed.delete(sessionId);
|
|
123
|
+
sessionGenerations.set(sessionId, (sessionGenerations.get(sessionId) ?? 0) + 1);
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
package/src/acp/turn-runner.ts
CHANGED
|
@@ -40,6 +40,11 @@ import { unsafeBrandSessionUri } from '../mss/uri/brand.js';
|
|
|
40
40
|
import { debug } from '../debug/log.js';
|
|
41
41
|
import type { AgentStatusStore } from '../agent-status/store.js';
|
|
42
42
|
import type { AcpPermissionApprover, AcpQuestionApprover } from './client.js';
|
|
43
|
+
import {
|
|
44
|
+
CODEX_APPROVAL_OPT_ONCE,
|
|
45
|
+
CODEX_APPROVAL_OPT_REJECT,
|
|
46
|
+
CODEX_APPROVAL_QUESTION_ID,
|
|
47
|
+
} from './codex-approval-adapter.js';
|
|
43
48
|
import type { ConfirmChannel } from '../hitl/confirm.js';
|
|
44
49
|
import type { QuestionChannel } from '../hitl/question.js';
|
|
45
50
|
import {
|
|
@@ -69,6 +74,7 @@ import { getUserConfig } from '../user-config.js';
|
|
|
69
74
|
// ACP `cancelled`), matching the pre-existing default-deny posture for
|
|
70
75
|
// unattended turns — so nothing hangs when a surface opts out.
|
|
71
76
|
const turnHitlChannels = new Map<string, ConfirmChannel[]>();
|
|
77
|
+
const turnPermissionApprovers = new Map<string, AcpPermissionApprover>();
|
|
72
78
|
/** Parallel registry for multi-option question channels (same keying
|
|
73
79
|
* as `turnHitlChannels`). Present ⇒ the question approver fans out
|
|
74
80
|
* real N-option prompts; absent ⇒ it falls back to yes/no collapse
|
|
@@ -81,6 +87,8 @@ const turnHitlQuestionChannels = new Map<string, QuestionChannel[]>();
|
|
|
81
87
|
const HITL_TURN_TIMEOUT_MS = 120_000;
|
|
82
88
|
|
|
83
89
|
const surfacePermissionApprover: AcpPermissionApprover = async (req) => {
|
|
90
|
+
const turnApprover = turnPermissionApprovers.get(req.sessionId);
|
|
91
|
+
if (turnApprover) return turnApprover(req);
|
|
84
92
|
// Autonomous by default: edit/command PERMISSIONS auto-approve. Asking the
|
|
85
93
|
// human to approve every write defeats delegation (the interactive-editor
|
|
86
94
|
// paradigm ACP inherited doesn't fit autonomous telegram delegation).
|
|
@@ -102,7 +110,31 @@ const surfacePermissionApprover: AcpPermissionApprover = async (req) => {
|
|
|
102
110
|
return answer;
|
|
103
111
|
};
|
|
104
112
|
|
|
113
|
+
/** PCH-2b — answer codex's 3-way approval question with a yes/no permission
|
|
114
|
+
* approver. Returns null when the request is not that question. */
|
|
115
|
+
export async function answerCodexApprovalQuestion(
|
|
116
|
+
req: Parameters<AcpQuestionApprover>[0],
|
|
117
|
+
approver: AcpPermissionApprover,
|
|
118
|
+
): Promise<Awaited<ReturnType<AcpQuestionApprover>> | null> {
|
|
119
|
+
const q = req.questions[0];
|
|
120
|
+
if (req.questions.length !== 1 || q?.id !== CODEX_APPROVAL_QUESTION_ID) return null;
|
|
121
|
+
const approved = await approver({
|
|
122
|
+
backendId: req.backendId,
|
|
123
|
+
sessionId: req.sessionId,
|
|
124
|
+
title: q.question,
|
|
125
|
+
options: [],
|
|
126
|
+
});
|
|
127
|
+
return { answers: { [q.id]: approved ? CODEX_APPROVAL_OPT_ONCE : CODEX_APPROVAL_OPT_REJECT } };
|
|
128
|
+
}
|
|
129
|
+
|
|
105
130
|
const surfaceQuestionApprover: AcpQuestionApprover = async (req) => {
|
|
131
|
+
// PCH-2b — an ACP server turn answers codex's approval question through its
|
|
132
|
+
// own client (yes/no), not the messenger HITL channels.
|
|
133
|
+
const turnApprover = turnPermissionApprovers.get(req.sessionId);
|
|
134
|
+
if (turnApprover) {
|
|
135
|
+
const answered = await answerCodexApprovalQuestion(req, turnApprover);
|
|
136
|
+
if (answered) return answered;
|
|
137
|
+
}
|
|
106
138
|
const channels = turnHitlChannels.get(req.sessionId);
|
|
107
139
|
if (!channels || channels.length === 0) return { answers: {}, cancelled: true };
|
|
108
140
|
// When the surface provided real multi-option QuestionChannels, fan
|
|
@@ -306,6 +338,8 @@ export interface RunAcpTurnOpts {
|
|
|
306
338
|
cwd?: string;
|
|
307
339
|
/** Session-scoped Codex app-server configuration arguments. */
|
|
308
340
|
codexArgs?: readonly string[];
|
|
341
|
+
/** ACP server turn's permission request, routed through its client rather than the messenger HITL channel. */
|
|
342
|
+
permissionApprover?: AcpPermissionApprover;
|
|
309
343
|
/** Soft focus budget (tool-turns) for a TARGETED slash invocation
|
|
310
344
|
* (`/cc`·/cdx·/gem). When set, a tight-budget directive is prepended
|
|
311
345
|
* to the prompt so the sub-agent stays focused (minimize re-reads /
|
|
@@ -663,6 +697,7 @@ export async function runAcpTurn(opts: RunAcpTurnOpts): Promise<RunAcpTurnResult
|
|
|
663
697
|
// session id (== the `req.sessionId` seen in requestPermission).
|
|
664
698
|
const hasHitl = !!opts.hitlConfirmChannels && opts.hitlConfirmChannels.length > 0;
|
|
665
699
|
if (hasHitl) turnHitlChannels.set(sessionId, opts.hitlConfirmChannels!);
|
|
700
|
+
if (opts.permissionApprover) turnPermissionApprovers.set(sessionId, opts.permissionApprover);
|
|
666
701
|
const hasHitlQuestions = !!opts.hitlQuestionChannels && opts.hitlQuestionChannels.length > 0;
|
|
667
702
|
if (hasHitlQuestions) turnHitlQuestionChannels.set(sessionId, opts.hitlQuestionChannels!);
|
|
668
703
|
|
|
@@ -784,6 +819,7 @@ export async function runAcpTurn(opts: RunAcpTurnOpts): Promise<RunAcpTurnResult
|
|
|
784
819
|
} finally {
|
|
785
820
|
inFlightTurns.delete(key);
|
|
786
821
|
if (hasHitl) turnHitlChannels.delete(sessionId);
|
|
822
|
+
if (opts.permissionApprover) turnPermissionApprovers.delete(sessionId);
|
|
787
823
|
if (hasHitlQuestions) turnHitlQuestionChannels.delete(sessionId);
|
|
788
824
|
}
|
|
789
825
|
}
|