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
|
@@ -107,6 +107,8 @@ export async function runDaemonPromptTurn(opts: {
|
|
|
107
107
|
surfaceResolutionReason?: SurfaceKindResolutionReason;
|
|
108
108
|
/** Optional confirm channels for the triggering chat surface. */
|
|
109
109
|
surfaceHitlChannels?: ConfirmChannel[];
|
|
110
|
+
/** Server-authenticated human owner for this request; absent for delegated or unverified callers. */
|
|
111
|
+
verifiedOwner?: { id: string };
|
|
110
112
|
/** Optional structured-question channels for the triggering chat surface. */
|
|
111
113
|
surfaceQuestionChannels?: QuestionChannel[];
|
|
112
114
|
/** CWD for fs-bound tool dispatch (Read / Grep). Defaults to
|
|
@@ -114,6 +116,8 @@ export async function runDaemonPromptTurn(opts: {
|
|
|
114
116
|
* `--tool-cwd` / `ELANOUS_TOOL_CWD` to keep `/v1/prompt` and ACP WS
|
|
115
117
|
* on the same path-guard boundary. */
|
|
116
118
|
toolCwd?: string;
|
|
119
|
+
/** Per-turn project instructions; unlike the base system preamble these must survive subsequent turns. */
|
|
120
|
+
projectInstructions?: string;
|
|
117
121
|
/** Phase 4 (WT-A-3b) — external abort signal. When provided and
|
|
118
122
|
* fired, the internal AbortController fans the abort through to
|
|
119
123
|
* `runCoreTurn` (LLM stream + tool dispatch). Callers without an
|
|
@@ -226,6 +230,7 @@ export async function runDaemonPromptTurn(opts: {
|
|
|
226
230
|
...(request.source?.kind === 'daemon-api' && request.source.route === '/a2a'
|
|
227
231
|
? { requestOrigin: 'external-agent' as const } : {}),
|
|
228
232
|
...(request.userText ? { userText: request.userText } : {}),
|
|
233
|
+
...(opts.verifiedOwner ? { verifiedOwner: opts.verifiedOwner } : {}),
|
|
229
234
|
...(opts.surface !== undefined || sourceResolution.surface !== 'unknown' ? { surface } : {}),
|
|
230
235
|
...(opts.surfaceHitlChannels ? { surfaceHitlChannels: opts.surfaceHitlChannels } : {}),
|
|
231
236
|
...(opts.surfaceQuestionChannels ? { surfaceQuestionChannels: opts.surfaceQuestionChannels } : {}),
|
|
@@ -283,6 +288,9 @@ export async function runDaemonPromptTurn(opts: {
|
|
|
283
288
|
if (fast && !isFirstTurn) {
|
|
284
289
|
messages.unshift({ role: 'system', content: fastPathGuidance });
|
|
285
290
|
}
|
|
291
|
+
if (!isFirstTurn && opts.projectInstructions) {
|
|
292
|
+
messages.unshift({ role: 'system', content: opts.projectInstructions });
|
|
293
|
+
}
|
|
286
294
|
const result = await runCoreTurn({
|
|
287
295
|
sessionId: request.sessionId,
|
|
288
296
|
userText: request.userText,
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
import type { CoreTurnDispatchTool } from '../core-turn/index.js';
|
|
54
54
|
import { elanousSelfAccessPrompt } from '../agent/self-ambient.js';
|
|
55
55
|
import { createToolCwdResolver, type ToolCwdResolver } from './tool-cwd.js';
|
|
56
|
+
import { resolveSessionProjectContext } from '../project/session-context.js';
|
|
56
57
|
import { debug } from '../debug/log.js';
|
|
57
58
|
|
|
58
59
|
/** C4 (2026-07-12) — arm the non-detached-PTY kill ONCE per turn signal.
|
|
@@ -579,7 +580,9 @@ export function createDaemonRunTurn(
|
|
|
579
580
|
// moved this out of an inline closure to fix the user-message
|
|
580
581
|
// persistence bug uniformly across all daemon paths.
|
|
581
582
|
getMessages: ({ sessionId, userText, promptBlocks, promptMeta }) => {
|
|
582
|
-
const
|
|
583
|
+
const projectInstructions = resolveSessionProjectContext(sessionId)?.instructions;
|
|
584
|
+
const baseSystemPrompt = [composeDaemonSystemPrompt(opts.systemPrompt, promptMeta, sessionId), projectInstructions]
|
|
585
|
+
.filter(Boolean).join('\n\n');
|
|
583
586
|
// Image-pipeline followup #4 (2026-05-05) — append daemon webterm
|
|
584
587
|
// context (current ACP sessionId + active terminal summary) to
|
|
585
588
|
// the system prompt when the webterm surface is active. Helper
|
|
@@ -720,8 +723,11 @@ export function createDaemonRunTurn(
|
|
|
720
723
|
});
|
|
721
724
|
debugBridge.activate();
|
|
722
725
|
}
|
|
723
|
-
|
|
724
|
-
|
|
726
|
+
const projectCwd = resolveSessionProjectContext(turnCtx.sessionId)?.cwd;
|
|
727
|
+
if (projectCwd || opts.acpSessionCwd) {
|
|
728
|
+
// An ACP session's explicit cwd wins; the project folder is only the default when none was given (IA3 review).
|
|
729
|
+
const explicitCwd = opts.acpSessionCwd && turnCtx.cwd ? turnCtx.cwd : undefined;
|
|
730
|
+
const resolver = createToolCwdResolver({ tools: opts.tools ?? 'none', toolCwd: explicitCwd ?? projectCwd ?? turnCtx.cwd });
|
|
725
731
|
await turnToolCwd.run(resolver, () => inner(turnCtx));
|
|
726
732
|
} else {
|
|
727
733
|
await inner(turnCtx);
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
dispatchBrowserRead,
|
|
17
17
|
} from '../../tool-runtime/browser-runtime.js';
|
|
18
18
|
import { askUserQuestionRuntime } from '../../tool-runtime/ask-user-question-runtime.js';
|
|
19
|
+
import { buildElanousHoldTool, buildPtyControlTool, dispatchElanousHold, dispatchPtyControl } from '../../tool-runtime/elanous-control-runtimes.js';
|
|
20
|
+
import { ptyAvailable } from '../../pty-shell/registry.js';
|
|
19
21
|
import { dispatchToolByName, listToolRuntimes } from '../../tool-runtime/registry.js';
|
|
20
22
|
import { ACP_SESSION_RUNTIMES } from '../../tool-runtime/acp-session-runtime.js';
|
|
21
23
|
import { ClaudeSubscriptionNotAllowedError } from '../../policy/claude-subscription-guard.js';
|
|
@@ -340,6 +342,7 @@ export function toolSurface(kind: DaemonToolSurfaceKind, cfg?: import('../../use
|
|
|
340
342
|
askUserQuestionRuntime.spec,
|
|
341
343
|
...ACP_SESSION_RUNTIMES.map((runtime) => runtime.spec),
|
|
342
344
|
...shared.specs, // L2 core + L3 finance(gated) — buildSharedAppTools 단일 출처(전 서피스 공용)
|
|
345
|
+
...(ptyAvailable() ? [buildElanousHoldTool(), buildPtyControlTool()] : []),
|
|
343
346
|
];
|
|
344
347
|
|
|
345
348
|
/** Shared dispatcher for chat-surface tools. Reused by 'chat' AND
|
|
@@ -392,11 +395,16 @@ export function toolSurface(kind: DaemonToolSurfaceKind, cfg?: import('../../use
|
|
|
392
395
|
// L2 core + L3 finance(gated) — buildSharedAppTools 단일 dispatch · B5: 진행 한 줄(emitFeedback)·세션·호출 id 를 넘긴다.
|
|
393
396
|
return shared.dispatch(name, args, {
|
|
394
397
|
surface: 'tui',
|
|
398
|
+
...(ctx.requestOrigin ? { requestOrigin: ctx.requestOrigin } : {}),
|
|
399
|
+
...(ctx.verifiedOwner ? { verifiedOwner: ctx.verifiedOwner } : {}),
|
|
395
400
|
...(ctx.sessionId ? { sessionId: ctx.sessionId } : {}),
|
|
401
|
+
...(ctx.surfaceHitlChannels ? { confirmChannels: ctx.surfaceHitlChannels } : {}),
|
|
396
402
|
...(ctx.toolCallId ? { toolCallId: ctx.toolCallId } : {}),
|
|
397
403
|
...(ctx.emitFeedback ? { emitFeedback: ctx.emitFeedback } : {}),
|
|
398
404
|
});
|
|
399
405
|
}
|
|
406
|
+
if (ptyAvailable() && name === 'ElanousHold') return dispatchElanousHold(args);
|
|
407
|
+
if (ptyAvailable() && name === 'PtyControl') return dispatchPtyControl(args);
|
|
400
408
|
if (name === 'Bash') {
|
|
401
409
|
// PLAN-ios-rich-dev-feedback-hydrate M3 (2026-05-13) — pass
|
|
402
410
|
// sessionId + emitFeedback so dispatchBash emits tool.progress
|
|
@@ -61,6 +61,8 @@ export interface DaemonToolDispatchCtx {
|
|
|
61
61
|
sessionId?: string;
|
|
62
62
|
/** Trusted server-side classification of the current turn, never supplied as a tool argument. */
|
|
63
63
|
requestOrigin?: RequestOrigin;
|
|
64
|
+
/** Owner principal verified at the server request boundary, not from input source metadata. */
|
|
65
|
+
verifiedOwner?: { id: string };
|
|
64
66
|
/** Ingestion entry class. Omit for conservative external-verbatim fallback. */
|
|
65
67
|
entry?: IngestionEntry;
|
|
66
68
|
/** M5 PR 2 (PLAN-rich-dev-feedback-multi-surface · 2026-05-13) —
|
|
@@ -23,6 +23,8 @@ export interface DaemonWebSearchArgs {
|
|
|
23
23
|
export interface DaemonWebSearchResult {
|
|
24
24
|
query: string;
|
|
25
25
|
providerName: string;
|
|
26
|
+
/** Absent for ordinary searches; signals whether X sources were actually cited. */
|
|
27
|
+
xSearch?: 'grok' | 'unavailable';
|
|
26
28
|
hits: Array<{
|
|
27
29
|
url: string;
|
|
28
30
|
title: string;
|
|
@@ -41,6 +43,7 @@ export function buildWebSearchTool(): LLMToolSpec {
|
|
|
41
43
|
'Search the public web via the daemon\'s configured provider (Grok / ' +
|
|
42
44
|
'Firecrawl / etc.). When no key is available, falls back to keyless DuckDuckGo. ' +
|
|
43
45
|
'Returns a ranked list of URLs + titles + snippets. ' +
|
|
46
|
+
'For fact questions, answer directly from the snippets and URLs; read the full body only when insufficient. ' +
|
|
44
47
|
'Pair with a follow-up Read or external WebFetch when the model needs ' +
|
|
45
48
|
'the full article body.',
|
|
46
49
|
parameters: {
|
|
@@ -89,6 +92,7 @@ export async function dispatchWebSearch(
|
|
|
89
92
|
return {
|
|
90
93
|
query,
|
|
91
94
|
providerName: result.providerName,
|
|
95
|
+
...(result.xSearch ? { xSearch: result.xSearch } : {}),
|
|
92
96
|
hits: result.hits.map((h) => ({
|
|
93
97
|
url: h.url,
|
|
94
98
|
title: h.title,
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { chmodSync, mkdirSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
5
|
+
import { lastJsonObject, runGraph as defaultRunGraph, type GraphRunState } from '../graph-runner/runner.js';
|
|
6
|
+
|
|
7
|
+
const GRAPH = resolve(import.meta.dir, '../../plugins/card-followup/graphs/card-followup.yaml');
|
|
8
|
+
export type CardDetectDecision = 'card' | 'skip' | 'ambiguous';
|
|
9
|
+
|
|
10
|
+
export function cardShape(width?: number, height?: number): { decision: 'skip' | 'pass'; signal: string } {
|
|
11
|
+
if (!width || !height) return { decision: 'pass', signal: 'ratio:unknown' };
|
|
12
|
+
const ratio = Math.max(width, height) / Math.min(width, height);
|
|
13
|
+
if (ratio < 1.15) return { decision: 'skip', signal: 'ratio:square' };
|
|
14
|
+
if (ratio > 2.0) return { decision: 'skip', signal: 'ratio:screenshot' };
|
|
15
|
+
return { decision: 'pass', signal: `ratio:${ratio.toFixed(2)}` };
|
|
16
|
+
}
|
|
17
|
+
const EMAIL = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i;
|
|
18
|
+
const PHONE = /(?:\+?\d{1,3}[\s.-]?)?\(?\d{2,4}\)?[\s.-]?\d{3,4}[\s.-]?\d{4}/;
|
|
19
|
+
const WEB = /\b(?:https?:\/\/|www\.)\S+|\b[a-z0-9-]+\.(?:com|co\.kr|kr|io|ai|net|org)\b/i;
|
|
20
|
+
const TITLE = /대표|이사|팀장|부장|과장|실장|매니저|주식회사|\(주\)|\b(?:CEO|CTO|COO|CFO|Director|Manager|Founder|Inc|Ltd|Corp)\b/i;
|
|
21
|
+
export function cardText(ocr: string | null): { decision: CardDetectDecision; signal: string } {
|
|
22
|
+
if (ocr === null) return { decision: 'ambiguous', signal: 'ocr:unavailable' };
|
|
23
|
+
const chars = ocr.replace(/\s+/g, '').length;
|
|
24
|
+
if (chars < 15) return { decision: 'ambiguous', signal: 'ocr:chars<15' };
|
|
25
|
+
if (chars > 700) return { decision: 'skip', signal: 'ocr:document' };
|
|
26
|
+
const hits = ([['email', EMAIL], ['phone', PHONE], ['web', WEB], ['title', TITLE]] as const).filter(([, re]) => re.test(ocr)).map(([name]) => name);
|
|
27
|
+
const signal = `ocr:${hits.join(',') || 'none'}`;
|
|
28
|
+
if (hits.length >= 2) return { decision: 'card', signal };
|
|
29
|
+
return { decision: hits.length === 0 ? 'skip' : 'ambiguous', signal };
|
|
30
|
+
}
|
|
31
|
+
export function detectCard({ width, height, ocrText }: { width?: number; height?: number; ocrText: string | null }): { decision: CardDetectDecision; signal: string } {
|
|
32
|
+
const shape = cardShape(width, height);
|
|
33
|
+
return shape.decision === 'skip' ? { decision: 'skip', signal: shape.signal } : cardText(ocrText);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const obj = (value: unknown): Record<string, unknown> => value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
|
|
37
|
+
const text = (value: unknown): string => typeof value === 'string' ? value.trim() : '';
|
|
38
|
+
const line = (value: unknown): string => (typeof value === 'number' && Number.isFinite(value) ? String(value) : text(value)).replace(/[\r\n]+/g, ' ') || '—';
|
|
39
|
+
|
|
40
|
+
export class NotACardError extends Error {}
|
|
41
|
+
function isNotACard(state: GraphRunState): boolean {
|
|
42
|
+
if (state.status !== 'failed') return false;
|
|
43
|
+
const read = state.nodes.find((node) => node.nodeId === 'read-card');
|
|
44
|
+
if (!read || !read.ok) return false;
|
|
45
|
+
const output = lastJsonObject(read.output);
|
|
46
|
+
if (output?.outcome === 'ok' && output.card && typeof output.card === 'object') {
|
|
47
|
+
const card = obj(output.card);
|
|
48
|
+
return !['name', 'company', 'title', 'email', 'phone', 'url', 'linkedin'].some((field) => text(card[field]));
|
|
49
|
+
}
|
|
50
|
+
return output?.outcome === 'fail' && typeof output.reason === 'string'
|
|
51
|
+
&& /\bnot a (?:business )?card\b|명함이?\s*아님|명함이?\s*아닙니다/i.test(output.reason);
|
|
52
|
+
}
|
|
53
|
+
function validateReport(report: Record<string, unknown>): void {
|
|
54
|
+
const card = obj(report.card), fit = obj(report.fit), approach = obj(report.approach);
|
|
55
|
+
const next = obj(report.nextAction), draft = obj(report.draft);
|
|
56
|
+
const score = fit.score;
|
|
57
|
+
if (report.sent !== false || !text(card.name) || !text(card.company)
|
|
58
|
+
|| !(score === null || (typeof score === 'number' && Number.isFinite(score)))
|
|
59
|
+
|| !text(fit.label) || !text(approach.problem) || !text(approach.proposal)
|
|
60
|
+
|| !text(approach.channel) || !text(next.what) || !text(next.due)
|
|
61
|
+
|| !text(draft.subject) || !text(draft.body)) {
|
|
62
|
+
throw new Error('incomplete or sent card report');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function runCardFollowup({ imagePath, ocrText, runGraph = defaultRunGraph, rootDir = effectiveInstanceRoot(), outDir, runId = randomUUID(), context }: {
|
|
67
|
+
imagePath: string;
|
|
68
|
+
ocrText: string | null;
|
|
69
|
+
runGraph?: typeof defaultRunGraph;
|
|
70
|
+
rootDir?: string;
|
|
71
|
+
outDir?: string;
|
|
72
|
+
runId?: string;
|
|
73
|
+
context?: string;
|
|
74
|
+
}): Promise<{ replies: [string, string, string]; followupPath?: string }> {
|
|
75
|
+
if (ocrText !== null && cardText(ocrText).decision !== 'card') throw new NotACardError('not a card');
|
|
76
|
+
const base = join(rootDir, 'graph-runs', 'card-followup');
|
|
77
|
+
const dir = outDir ?? join(base, runId);
|
|
78
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
79
|
+
chmodSync(base, 0o700);
|
|
80
|
+
chmodSync(dir, 0o700);
|
|
81
|
+
const statePath = join(base, `${runId}.json`);
|
|
82
|
+
const sealState = () => {
|
|
83
|
+
try { chmodSync(statePath, 0o600); } catch { /* runner may not have written state */ }
|
|
84
|
+
const contexts = `${statePath}.contexts`;
|
|
85
|
+
try {
|
|
86
|
+
chmodSync(contexts, 0o700);
|
|
87
|
+
for (const file of readdirSync(contexts)) chmodSync(join(contexts, file), 0o600);
|
|
88
|
+
} catch { /* no contexts yet */ }
|
|
89
|
+
};
|
|
90
|
+
try {
|
|
91
|
+
const state = await runGraph(GRAPH, { runId, deps: { root: rootDir }, input: {
|
|
92
|
+
image: imagePath, outDir: dir, ...(context ? { context } : {}),
|
|
93
|
+
} });
|
|
94
|
+
if (isNotACard(state)) throw new NotACardError('not a card');
|
|
95
|
+
if (state.status !== 'done') throw new Error('graph did not finish');
|
|
96
|
+
const report = obj(JSON.parse(readFileSync(join(dir, 'followup.json'), 'utf8')));
|
|
97
|
+
validateReport(report);
|
|
98
|
+
const card = obj(report.card), fit = obj(report.fit), approach = obj(report.approach);
|
|
99
|
+
const next = obj(report.nextAction), draft = obj(report.draft);
|
|
100
|
+
const summary = `① 요약\n${line(card.name)} · ${line(card.company)} · ${line(card.title)}\n타겟 판정: ${line(fit.score)} · ${line(fit.label)}`;
|
|
101
|
+
const strategy = `② 전략\n${[approach.problem, approach.proposal, approach.channel].map(line).join('\n')}\n다음 행동: ${line(next.what)} · ${line(next.due)}`;
|
|
102
|
+
const mail = `③ 팔로업 초안 (보내지 않았습니다)\n제목: ${line(draft.subject)}\n${text(draft.body)}`;
|
|
103
|
+
const followupPath = join(dir, 'followup.md');
|
|
104
|
+
readFileSync(followupPath);
|
|
105
|
+
return { replies: [summary, strategy, mail], followupPath };
|
|
106
|
+
} finally {
|
|
107
|
+
if (runGraph === defaultRunGraph) sealState();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** U1a — how long an empty-input Ctrl+C stays armed (and its hint stays on screen). */
|
|
2
|
+
export const CTRL_C_ARM_MS = 2_000;
|
|
3
|
+
|
|
4
|
+
export function resolveCtrlCInInput({ text, now, armedAt }: {
|
|
5
|
+
text: string;
|
|
6
|
+
now: number;
|
|
7
|
+
armedAt: number | null;
|
|
8
|
+
}): { action: 'clear-input' | 'arm-exit' | 'exit'; armedAt: number | null; hint: string | null } {
|
|
9
|
+
if (text.length > 0) return { action: 'clear-input', armedAt: null, hint: null };
|
|
10
|
+
if (armedAt !== null && now >= armedAt && now - armedAt <= CTRL_C_ARM_MS) {
|
|
11
|
+
return { action: 'exit', armedAt: null, hint: null };
|
|
12
|
+
}
|
|
13
|
+
return { action: 'arm-exit', armedAt: now, hint: '한 번 더 누르면 나갑니다 · /quit' };
|
|
14
|
+
}
|
package/src/chat/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ import type { ModalSurface } from '../display/modal-stack.js';
|
|
|
19
19
|
import type { ContentBlock } from '../llm.js';
|
|
20
20
|
import { debug } from '../debug/log.js';
|
|
21
21
|
import { matchTextInputGlobalAction } from './global-actions.js';
|
|
22
|
+
import { CTRL_C_ARM_MS, resolveCtrlCInInput } from './ctrl-c-in-input.js';
|
|
22
23
|
import { isTextInputQuitChord } from './input-quit-chord.js';
|
|
23
24
|
// P5 — leader-chord pass-through from input focus. chat.ts swallows
|
|
24
25
|
// plain letters into its textarea buffer, so the resolver never sees
|
|
@@ -436,6 +437,7 @@ export const SLASH_COMMANDS: SlashCommand[] = [
|
|
|
436
437
|
{ name: 'model', aliases: ['m'], description: '모델 바꾸기 — /model <codex|terra|sol|luna|opus|sonnet|grok> (list + current when no arg). OpenAI 는 Codex(Responses API)만. effort 는 /reasoning.', subcommands: ['codex', 'terra', 'sol', 'luna', 'opus', 'sonnet', 'grok'] },
|
|
437
438
|
{ name: 'clear', aliases: ['cls'], description: '대화 기록 지우기' },
|
|
438
439
|
{ name: 'status', aliases: ['st'], description: '지금 상태 — 모델 · 연결 · 계정' },
|
|
440
|
+
{ name: 'now', aliases: [], description: '현재 맥락과 출처 표 — /now [주제]' },
|
|
439
441
|
{ name: 'remaining', aliases: [], description: '계정별 남은 사용량' },
|
|
440
442
|
{ name: 'setup', aliases: [], description: '상세 설정 — /setup · /setup reset(다음 실행 때 마법사 다시)', subcommands: ['help', 'reset'] },
|
|
441
443
|
{ name: 'quit', aliases: ['q', 'exit'], description: '나가기' },
|
|
@@ -896,6 +898,10 @@ export async function textInput(opts: {
|
|
|
896
898
|
let lastReportedLines = -1;
|
|
897
899
|
let lineIdx = 0; // current line
|
|
898
900
|
let colIdx = lines[0]!.length; // cursor at end of initial text
|
|
901
|
+
let ctrlCArmedAt: number | null = null;
|
|
902
|
+
let ctrlCHintTimer: ReturnType<typeof setTimeout> | null = null;
|
|
903
|
+
let ctrlCHint: string | null = null;
|
|
904
|
+
let ctrlCHintPainted = false;
|
|
899
905
|
|
|
900
906
|
// KX2 — picker selection / navigation / async fetch caches live in
|
|
901
907
|
// the shared state machine (chat-picker-state.ts). textInput keeps
|
|
@@ -1173,6 +1179,14 @@ export async function textInput(opts: {
|
|
|
1173
1179
|
}
|
|
1174
1180
|
prevDrawnLines = visibleLines;
|
|
1175
1181
|
|
|
1182
|
+
if (ctrlCHint) {
|
|
1183
|
+
writeTerminal(ansi.moveTo(row + 2, col) + '\x1b[2K' + C.muted(truncate(ctrlCHint, width)));
|
|
1184
|
+
ctrlCHintPainted = true;
|
|
1185
|
+
} else if (ctrlCHintPainted) {
|
|
1186
|
+
writeTerminal(ansi.moveTo(row + 2, col) + '\x1b[2K');
|
|
1187
|
+
ctrlCHintPainted = false;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1176
1190
|
// Cursor — its buffer line is `lineIdx`; its screen row is the
|
|
1177
1191
|
// bottom-anchored offset within the visible window. Critically,
|
|
1178
1192
|
// `textBeforeCursor` reads from `lines[lineIdx]` (the buffer), not
|
|
@@ -1468,6 +1482,11 @@ export async function textInput(opts: {
|
|
|
1468
1482
|
process.exit(0);
|
|
1469
1483
|
}
|
|
1470
1484
|
|
|
1485
|
+
if (!(key.ctrl && (key.name === 'c' || key.name === 'ㅊ') && !key.shift && !key.alt)) {
|
|
1486
|
+
ctrlCArmedAt = null;
|
|
1487
|
+
ctrlCHint = null;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1471
1490
|
// A bracketed-paste envelope is one atomic event. Handle it before
|
|
1472
1491
|
// host routing so embedded newlines cannot reach a submit handler.
|
|
1473
1492
|
if (key.name === 'paste') {
|
|
@@ -1571,6 +1590,40 @@ export async function textInput(opts: {
|
|
|
1571
1590
|
continue;
|
|
1572
1591
|
}
|
|
1573
1592
|
|
|
1593
|
+
if (key.ctrl && (key.name === 'c' || key.name === 'ㅊ') && !key.shift && !key.alt) {
|
|
1594
|
+
const text = lines.join('\n');
|
|
1595
|
+
const result = resolveCtrlCInInput({ text, now: Date.now(), armedAt: ctrlCArmedAt });
|
|
1596
|
+
debug.log('chat.input', 'ctrl-c', { action: result.action, length: text.length });
|
|
1597
|
+
ctrlCArmedAt = result.armedAt;
|
|
1598
|
+
ctrlCHint = result.hint;
|
|
1599
|
+
if (ctrlCHintTimer) clearTimeout(ctrlCHintTimer);
|
|
1600
|
+
ctrlCHintTimer = null;
|
|
1601
|
+
if (result.action === 'arm-exit') {
|
|
1602
|
+
// U1a — the hint promises «one more press exits» only while that is true.
|
|
1603
|
+
const armedAt = result.armedAt;
|
|
1604
|
+
ctrlCHintTimer = setTimeout(() => {
|
|
1605
|
+
ctrlCHintTimer = null;
|
|
1606
|
+
if (ctrlCArmedAt !== armedAt) return;
|
|
1607
|
+
ctrlCArmedAt = null;
|
|
1608
|
+
ctrlCHint = null;
|
|
1609
|
+
drawAll();
|
|
1610
|
+
}, CTRL_C_ARM_MS + 50);
|
|
1611
|
+
ctrlCHintTimer.unref?.();
|
|
1612
|
+
}
|
|
1613
|
+
if (result.action === 'exit') return submitBufferResult('/quit');
|
|
1614
|
+
if (result.action === 'clear-input') {
|
|
1615
|
+
lines = [''];
|
|
1616
|
+
lineIdx = 0;
|
|
1617
|
+
colIdx = 0;
|
|
1618
|
+
historyIdx = -1;
|
|
1619
|
+
savedCurrentInput = '';
|
|
1620
|
+
onUserBufferEdit();
|
|
1621
|
+
await picker.refresh(bufView());
|
|
1622
|
+
}
|
|
1623
|
+
drawAll();
|
|
1624
|
+
continue;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1574
1627
|
const globalDispatcher = dispatchGlobalAction;
|
|
1575
1628
|
const globalAction = globalDispatcher
|
|
1576
1629
|
? matchTextInputGlobalAction(key, {
|
|
@@ -33,6 +33,7 @@ import type {
|
|
|
33
33
|
} from '../index.js';
|
|
34
34
|
import { filterSlashCommands } from '../index.js';
|
|
35
35
|
import { filterInputMatches } from '../../input/query-match.js';
|
|
36
|
+
import { readTuiSlashAudience, slashMaturity, slashVisibleFor } from '../../maturity/tui-slash-maturity.js';
|
|
36
37
|
|
|
37
38
|
/** Read-only snapshot of the textInput buffer handed to state on
|
|
38
39
|
* every public call. The state machine never mutates it; it only
|
|
@@ -234,8 +235,11 @@ export function createPickerState(deps: PickerDeps): PickerState {
|
|
|
234
235
|
let currentAtItems: AtCandidate[] = [];
|
|
235
236
|
let currentSkillItems: SkillCandidate[] = [];
|
|
236
237
|
|
|
237
|
-
const filteredSlash = (buf: PickerBufferView): SlashCommand[] =>
|
|
238
|
-
|
|
238
|
+
const filteredSlash = (buf: PickerBufferView): SlashCommand[] => {
|
|
239
|
+
const { role, showBeta } = readTuiSlashAudience();
|
|
240
|
+
return filterSlashCommands((buf.lines[0] ?? '').slice(1), deps.commands)
|
|
241
|
+
.filter((cmd) => (role === 'owner' && slashMaturity(cmd.name) === undefined) || slashVisibleFor(cmd.name, role, { showBeta }));
|
|
242
|
+
};
|
|
239
243
|
|
|
240
244
|
const refreshArgs = async (buf: PickerBufferView): Promise<ArgSuggestion[]> => {
|
|
241
245
|
const ctx = parseArgContext(buf, deps.commands);
|
package/src/cli/agent-cli.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { resolve } from 'node:path';
|
|
|
3
3
|
import { getUserConfig, reloadUserConfig } from '../user-config.js';
|
|
4
4
|
import { handleOnboardingRefusal, needsOnboarding, runOnboarding } from '../onboarding.js';
|
|
5
5
|
import { runTurn, ensureCliSession, sessionBudget } from '../session/chat.js';
|
|
6
|
+
import { suggestProjectForFolder } from '../project/project-store.js';
|
|
6
7
|
import { NoLlmProviderAvailableError, noProviderAvailableMessage } from '../llm.js';
|
|
7
8
|
import { resolveSessionId, getActiveSessionId, setActiveSessionId } from '../session/index.js';
|
|
8
9
|
import { getHarnessSpace } from '../harness/harness-space.js';
|
|
@@ -433,6 +434,12 @@ export async function runChatTurnCli(opts: {
|
|
|
433
434
|
}
|
|
434
435
|
const session = ensureCliSession(opts.cfg, resolvedSessionIdHint);
|
|
435
436
|
setActiveSessionId(session.id);
|
|
437
|
+
if (!opts.json && (!resolvedSessionIdHint || session.id !== resolvedSessionIdHint)) {
|
|
438
|
+
try {
|
|
439
|
+
const project = suggestProjectForFolder(process.cwd());
|
|
440
|
+
if (project) console.log(`Project suggestion: ${project.name} (${project.id})`);
|
|
441
|
+
} catch { /* suggestions must not interrupt a CLI conversation */ }
|
|
442
|
+
}
|
|
436
443
|
const harnessSpace = getHarnessSpace();
|
|
437
444
|
// Tag the debug log with this session id so every event in this
|
|
438
445
|
// process attributes correctly. enrichDebugRecord picks up the
|
package/src/cli/decisions-cli.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
|
+
import { projectDecisionsToLinear } from '../decisions/decision-linear-projection.js';
|
|
2
3
|
import { DecisionLedger, importDecisionMarkdown, type DecisionCategory, type DecisionLedgerOptions, type DecisionOption, type DecisionTrack, type DecisionEntry } from '../decisions/decision-ledger.js';
|
|
3
4
|
|
|
4
5
|
const repeat = (value: string, values: string[]) => [...values, value];
|
|
@@ -49,22 +50,31 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
|
|
|
49
50
|
const root = program.command('decisions').description('대표 결정 원장 · 로컬 전용');
|
|
50
51
|
const emit = (value: unknown, json?: boolean, text?: string) => out.log(json ? JSON.stringify(value) : text ?? JSON.stringify(value));
|
|
51
52
|
const fail = (action: () => void) => { try { action(); } catch (e) { throw new Error(`decisions: ${e instanceof Error ? e.message : String(e)}`); } };
|
|
53
|
+
root.command('linear-sync').description('열린 결정을 COO Linear 프로젝트에 투영하고 닫힌 결정을 동기화한다')
|
|
54
|
+
.option('--dry-run').option('--json')
|
|
55
|
+
.action(async (o: { dryRun?: boolean; json?: boolean }) => {
|
|
56
|
+
const result = await projectDecisionsToLinear({ stateDir: config.stateDir, dryRun: o.dryRun });
|
|
57
|
+
emit(result, o.json, result.reason ?? `생성 ${result.created} · 닫음 ${result.closed} · 건너뜀 ${result.skipped} · 실패 ${result.failed}${result.plan?.length ? `\n${result.plan.map(p => `${p.action} ${p.decisionId}${p.issue ? ` ${p.issue}` : ''}`).join('\n')}` : ''}`);
|
|
58
|
+
});
|
|
52
59
|
root.command('raise').description('SCQA·선택지와 권고로 결정 항목을 올린다')
|
|
53
60
|
.requiredOption('--title <text>').requiredOption('--category <category>')
|
|
54
61
|
.requiredOption('--s <text>').requiredOption('--c <text>').option('--q <text>').option('--a <text>')
|
|
55
62
|
.requiredOption('--option <key=label:consequence>', '선택지 (두 번 이상)', repeat, [] as string[])
|
|
56
63
|
.option('--recommend <key>').option('--why <text>').option('--skip-recommend <reason>')
|
|
57
64
|
.option('--track <track>').option('--agent <agent>').option('--session <id>')
|
|
65
|
+
.option('--resume-question <qid>').option('--run <runId>')
|
|
58
66
|
.option('--ref <url>', '참조 (반복)', repeat, [] as string[])
|
|
59
67
|
.option('--due <when>', '기한 — UTC ISO(2026-10-04T09:00:00Z) 또는 +Nh(지금부터 N시간) · 기한 2시간 전 텔레그램·디스코드로 다시 알린다')
|
|
60
68
|
.option('--json')
|
|
61
|
-
.action((o: { due?: string; title: string; category: DecisionCategory; s: string; c: string; q?: string; a?: string; option: string[]; recommend?: string; why?: string; skipRecommend?: string; track?: DecisionTrack; agent?: string; session?: string; ref: string[]; json?: boolean }) => fail(() => {
|
|
69
|
+
.action((o: { due?: string; title: string; category: DecisionCategory; s: string; c: string; q?: string; a?: string; option: string[]; recommend?: string; why?: string; skipRecommend?: string; track?: DecisionTrack; agent?: string; session?: string; resumeQuestion?: string; run?: string; ref: string[]; json?: boolean }) => fail(() => {
|
|
70
|
+
if (o.run !== undefined && o.resumeQuestion === undefined) throw new Error('--run requires --resume-question');
|
|
62
71
|
if (o.skipRecommend !== undefined && (o.recommend !== undefined || o.why !== undefined)) throw new Error('choose recommendation or skip, not both');
|
|
63
72
|
if (o.skipRecommend === undefined && (!o.recommend || !o.why)) throw new Error('--recommend and --why required, or --skip-recommend <reason>');
|
|
64
73
|
const options: DecisionOption[] = o.option.map(parseOption);
|
|
65
74
|
const entry = new DecisionLedger(config).raise({ title: o.title, category: o.category, scqa: { s: o.s, c: o.c, ...(o.q ? { q: o.q } : {}), ...(o.a ? { a: o.a } : {}) }, options,
|
|
66
75
|
recommendation: o.skipRecommend !== undefined ? { skipped: true, reason: o.skipRecommend } : { option: o.recommend!, why: o.why! },
|
|
67
76
|
raisedBy: { agent: agent(o.agent), ...(o.track ? { track: o.track } : {}), ...(o.session ? { session: o.session } : {}) }, ...(o.ref.length ? { refs: o.ref } : {}),
|
|
77
|
+
...(o.resumeQuestion !== undefined ? { resume: { questionId: o.resumeQuestion, ...(o.run !== undefined ? { runId: o.run } : {}) } } : {}),
|
|
68
78
|
...(o.due ? { dueAt: dueAt(o.due) } : {}) });
|
|
69
79
|
emit(entry, o.json, `올림: ${formatDecisionRow(entry)}`);
|
|
70
80
|
}));
|
|
@@ -83,8 +93,20 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
|
|
|
83
93
|
if (o.auto && !o.delegation?.trim()) throw new Error('--auto requires --delegation');
|
|
84
94
|
if (!o.auto && (o.delegation || o.track || o.agent)) throw new Error('delegation/track/agent require --auto');
|
|
85
95
|
const by = o.auto ? { kind: 'auto' as const, agent: agent(o.agent), delegation: o.delegation!, ...(o.track ? { track: o.track } : {}) } : { kind: 'human' as const };
|
|
86
|
-
const entry = new DecisionLedger(config).
|
|
87
|
-
|
|
96
|
+
const { entry, delivery } = new DecisionLedger(config).decideWithDelivery(id, choice, by, o.note);
|
|
97
|
+
if (delivery && !delivery.ok) {
|
|
98
|
+
// The decision is recorded; only the answer to the waiting run failed — say so and how to retry, never «success».
|
|
99
|
+
const hint = `⚠ 답 전달 실패(${delivery.questionId} · ${delivery.reason}) — 결정은 기록됐다 · 다시: elanous decisions retry-answer ${entry.id}`;
|
|
100
|
+
emit({ ...entry, delivery }, o.json, `결정: ${formatDecisionDetail(entry)}\n${hint}`);
|
|
101
|
+
process.exitCode = 3;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
emit(delivery ? { ...entry, delivery } : entry, o.json, `결정: ${formatDecisionDetail(entry)}`);
|
|
105
|
+
}));
|
|
106
|
+
root.command('retry-answer <id>').description('기록된 결정의 대기 질문 답 전달만 재시도한다').option('--json')
|
|
107
|
+
.action((id: string, o: { json?: boolean }) => fail(() => {
|
|
108
|
+
const entry = new DecisionLedger(config).retryAnswer(id);
|
|
109
|
+
emit(entry, o.json, `답 전달: ${entry.id} → ${entry.resume?.questionId}`);
|
|
88
110
|
}));
|
|
89
111
|
root.command('add-options <id>').description('선택지가 미기재된 과거 항목에 확인된 선택지를 추가')
|
|
90
112
|
.requiredOption('--option <key=label:consequence>', '선택지 (두 번 이상)', repeat, [] as string[])
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { debug } from '../debug/log.js';
|
|
3
|
+
|
|
4
|
+
export interface DoctorBundleUploadOptions {
|
|
5
|
+
path: string;
|
|
6
|
+
files: readonly string[];
|
|
7
|
+
uploadUrl?: string;
|
|
8
|
+
confirm: (message: string) => Promise<boolean>;
|
|
9
|
+
fetch: typeof globalThis.fetch;
|
|
10
|
+
yes?: boolean;
|
|
11
|
+
/** Present the inventory before either consent or transport; JSON callers can use stderr. */
|
|
12
|
+
announce?: (contents: string) => void;
|
|
13
|
+
/** Pass the size returned by buildDoctorBundle, if available. */
|
|
14
|
+
bytes?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface DoctorBundleUploadResult {
|
|
18
|
+
path: string;
|
|
19
|
+
uploaded: boolean;
|
|
20
|
+
code?: string;
|
|
21
|
+
reason?: string;
|
|
22
|
+
exitCode: number;
|
|
23
|
+
message: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** The bundle is local until both an HTTPS destination and affirmative consent exist. */
|
|
27
|
+
export async function uploadDoctorBundle({ path, files, uploadUrl, confirm, fetch, yes = false, bytes, announce = console.log }: DoctorBundleUploadOptions): Promise<DoctorBundleUploadResult> {
|
|
28
|
+
const size = bytes ?? (() => { try { return statSync(path).size; } catch { return undefined; } })();
|
|
29
|
+
const skipped = (reason: string, message: string): DoctorBundleUploadResult => {
|
|
30
|
+
debug.log('doctor.bundle', 'upload-skipped', { bytes: size, reason });
|
|
31
|
+
return { path, uploaded: false, reason, exitCode: 0, message };
|
|
32
|
+
};
|
|
33
|
+
if (!uploadUrl?.trim()) return skipped('no-recipient', `수신처가 아직 정해지지 않았습니다 — 파일을 지원에 직접 보내 주세요: ${path}`);
|
|
34
|
+
let destination: URL;
|
|
35
|
+
try {
|
|
36
|
+
destination = new URL(uploadUrl.trim());
|
|
37
|
+
if (destination.protocol !== 'https:' || !destination.hostname || destination.username || destination.password) throw new Error('invalid destination');
|
|
38
|
+
} catch {
|
|
39
|
+
return skipped('invalid-recipient', `수신처가 유효한 HTTPS 주소가 아닙니다 — 파일을 지원에 직접 보내 주세요: ${path}`);
|
|
40
|
+
}
|
|
41
|
+
const contents = `내용 목록 (${size === undefined ? '크기 확인 불가' : `${size} bytes`}):\n${files.map((file) => ` ${file}`).join('\n')}`;
|
|
42
|
+
announce(contents);
|
|
43
|
+
if (!yes) {
|
|
44
|
+
let agreed = false;
|
|
45
|
+
try { agreed = await confirm('올릴까요? (y/N) '); } catch { /* An unavailable prompt is a refusal. */ }
|
|
46
|
+
if (!agreed) {
|
|
47
|
+
debug.log('doctor.bundle', 'declined', { bytes: size, reason: 'consent-declined' });
|
|
48
|
+
return { path, uploaded: false, reason: 'consent-declined', exitCode: 0, message: `업로드하지 않았습니다: ${path}` };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const failed = (reason: string): DoctorBundleUploadResult => {
|
|
52
|
+
debug.log('doctor.bundle', 'upload-failed', { bytes: size, reason });
|
|
53
|
+
return { path, uploaded: false, reason, exitCode: 1, message: `업로드 실패 (${reason}) — 파일: ${path} — 다시 시도해 주세요.` };
|
|
54
|
+
};
|
|
55
|
+
try {
|
|
56
|
+
const response = await fetch(destination.href, {
|
|
57
|
+
method: 'POST', headers: { 'Content-Type': 'application/gzip' }, body: readFileSync(path), redirect: 'manual',
|
|
58
|
+
});
|
|
59
|
+
if (!response.ok) return failed(`HTTP ${response.status}`);
|
|
60
|
+
const data: unknown = await response.json();
|
|
61
|
+
const code = data && typeof data === 'object' && !Array.isArray(data) ? (data as { code?: unknown }).code : undefined;
|
|
62
|
+
if (typeof code !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(code)) return failed('진단 코드 응답이 올바르지 않습니다');
|
|
63
|
+
debug.log('doctor.bundle', 'uploaded', { bytes: size, reason: 'success' });
|
|
64
|
+
return { path, uploaded: true, code, exitCode: 0, message: `진단 코드: ${code} — 이 코드만 지원에 알려 주세요` };
|
|
65
|
+
} catch {
|
|
66
|
+
return failed('네트워크 또는 파일 읽기 오류');
|
|
67
|
+
}
|
|
68
|
+
}
|
package/src/cli/doctor-cli.ts
CHANGED
|
@@ -38,6 +38,7 @@ import { describeModes, formatModeLine, type DoctorMode } from './doctor-modes.j
|
|
|
38
38
|
import { formatDoctorLocalLlm, probeDoctorLocalLlm, type DoctorLocalLlm } from './doctor-local-llm.js';
|
|
39
39
|
import type { LlmInventory } from '../llm/local-manager/types.js';
|
|
40
40
|
import { buildDoctorBundle } from './doctor-bundle.js';
|
|
41
|
+
import { uploadDoctorBundle } from './doctor-bundle-upload.js';
|
|
41
42
|
|
|
42
43
|
function defaultCheckPythonEnv(): { status: 'ok' | 'fixable' | 'manual'; evidence: string; remedy?: string } {
|
|
43
44
|
const c = checkPythonEnv(false);
|
|
@@ -193,6 +194,9 @@ export interface DoctorCliDeps extends DoctorOptions, Pick<DoctorFixDeps, 'home'
|
|
|
193
194
|
adviceInteractive?: boolean;
|
|
194
195
|
/** Local-manager inventory seam; default calls getInventory(). */
|
|
195
196
|
localLlmInventory?: () => Promise<LlmInventory>;
|
|
197
|
+
/** Inject the upload transport and consent for isolated CLI tests. */
|
|
198
|
+
uploadFetch?: typeof globalThis.fetch;
|
|
199
|
+
confirmBundleUpload?: (message: string) => Promise<boolean>;
|
|
196
200
|
}
|
|
197
201
|
|
|
198
202
|
const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..');
|
|
@@ -1217,15 +1221,21 @@ export function registerDoctorCommand(program: Command, deps: DoctorCliDeps = {}
|
|
|
1217
1221
|
.option('--json', 'structured output')
|
|
1218
1222
|
.option('--credentials', 'show per-credential details in human-readable output')
|
|
1219
1223
|
.option('--bundle', 'write a redacted diagnostics archive for support')
|
|
1224
|
+
.option('--upload', 'send the bundle to diagnostics.uploadUrl after consent (requires --bundle)')
|
|
1220
1225
|
.option('--out <dir>', 'output directory for --bundle')
|
|
1221
1226
|
.option('--fix', 'show repairs; git installation asks on a TTY (other repairs require --yes)')
|
|
1222
1227
|
.option('--advise', 'ask the configured LLM to rank catalog repairs (read-only advice)')
|
|
1223
|
-
.option('--yes', 'apply planned doctor repairs (
|
|
1228
|
+
.option('--yes', 'apply planned doctor repairs (--fix), or confirm bundle upload (--bundle --upload)')
|
|
1224
1229
|
.option('--sudo', 'also run the planned sudo install lines — only where `sudo -n true` works (requires --fix --yes)')
|
|
1225
1230
|
.option('--restart', 'restart the nexus service when it runs a different version than this installed copy, then verify it (requires --fix --yes · interrupts bots, terminals and running turns)')
|
|
1226
|
-
.action(async (opts: { json?: boolean; credentials?: boolean; bundle?: boolean; out?: string; fix?: boolean; advise?: boolean; yes?: boolean; sudo?: boolean; restart?: boolean }) => {
|
|
1231
|
+
.action(async (opts: { json?: boolean; credentials?: boolean; bundle?: boolean; upload?: boolean; out?: string; fix?: boolean; advise?: boolean; yes?: boolean; sudo?: boolean; restart?: boolean }) => {
|
|
1232
|
+
if (opts.upload && !opts.bundle) {
|
|
1233
|
+
err.error('--upload requires --bundle');
|
|
1234
|
+
setExitCode(1);
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1227
1237
|
if (opts.bundle) {
|
|
1228
|
-
if (opts.fix || opts.advise || opts.
|
|
1238
|
+
if (opts.fix || opts.advise || opts.sudo || opts.restart || (opts.yes && !opts.upload)) {
|
|
1229
1239
|
err.error('--bundle cannot be combined with repair or advice options');
|
|
1230
1240
|
setExitCode(1);
|
|
1231
1241
|
return;
|
|
@@ -1235,7 +1245,31 @@ export function registerDoctorCommand(program: Command, deps: DoctorCliDeps = {}
|
|
|
1235
1245
|
const doctorReport = runDoctor(deps);
|
|
1236
1246
|
if (doctorReport.ok) doctorReport.localLlm = await probeDoctorLocalLlm(deps.localLlmInventory);
|
|
1237
1247
|
const result = buildDoctorBundle({ outDir: opts.out ?? process.cwd(), doctorOptions: deps, doctorReport });
|
|
1238
|
-
|
|
1248
|
+
if (opts.upload) {
|
|
1249
|
+
let uploadUrl: string | undefined;
|
|
1250
|
+
try { uploadUrl = (deps.userConfig ?? (deps.getUserConfig ?? getUserConfig)()).diagnostics?.uploadUrl; }
|
|
1251
|
+
catch {
|
|
1252
|
+
const reason = '설정을 읽을 수 없습니다';
|
|
1253
|
+
debug.log('doctor.bundle', 'upload-failed', { bytes: result.bytes, reason: 'config-read-failed' });
|
|
1254
|
+
if (opts.json) out.log(JSON.stringify({ path: result.path, uploaded: false, reason }));
|
|
1255
|
+
else err.error(`업로드 실패 (${reason}) — 파일: ${result.path} — 다시 시도해 주세요.`);
|
|
1256
|
+
setExitCode(1);
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
const uploaded = await uploadDoctorBundle({
|
|
1260
|
+
...result,
|
|
1261
|
+
uploadUrl,
|
|
1262
|
+
yes: opts.yes,
|
|
1263
|
+
announce: (contents) => { if (opts.json) err.error(contents); else out.log(contents); },
|
|
1264
|
+
confirm: deps.confirmBundleUpload ?? ((message) => confirmDoctorAdvice(message, opts.json === true)),
|
|
1265
|
+
fetch: deps.uploadFetch ?? globalThis.fetch,
|
|
1266
|
+
});
|
|
1267
|
+
if (opts.json) out.log(JSON.stringify({ path: uploaded.path, uploaded: uploaded.uploaded, ...(uploaded.code ? { code: uploaded.code } : {}), ...(uploaded.reason ? { reason: uploaded.reason } : {}) }));
|
|
1268
|
+
else out.log(uploaded.message);
|
|
1269
|
+
if (uploaded.exitCode) setExitCode(uploaded.exitCode);
|
|
1270
|
+
} else {
|
|
1271
|
+
out.log(opts.json ? JSON.stringify(result) : [`Diagnostics: ${result.path} (${result.bytes} bytes)`, 'Contents:', ...result.files.map((file) => ` ${file}`)].join('\n'));
|
|
1272
|
+
}
|
|
1239
1273
|
} catch {
|
|
1240
1274
|
err.error('Could not create diagnostics archive.');
|
|
1241
1275
|
setExitCode(1);
|