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,48 @@
|
|
|
1
|
+
import { contextNow, type ContextFact, type ContextNowAnswer, type ContextNowDeps } from './context-now.js';
|
|
2
|
+
|
|
3
|
+
export function readSlashContextNow(args: string[], deps?: ContextNowDeps): ContextNowAnswer {
|
|
4
|
+
return contextNow({ topic: args.join(' ').trim() }, deps);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function factText(fact: ContextFact): string {
|
|
8
|
+
switch (fact.kind) {
|
|
9
|
+
case 'version': return fact.version;
|
|
10
|
+
case 'cell': return `${fact.id} ${fact.title} (${fact.status})`;
|
|
11
|
+
case 'decision': return `${fact.id} ${fact.title} (${fact.status})`;
|
|
12
|
+
case 'seat': return `${fact.seat} ${fact.id ?? ''} ${fact.title ?? ''} (${fact.status})`.trim();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function renderTelegramNow(answer: ContextNowAnswer): string {
|
|
17
|
+
const rows = [
|
|
18
|
+
['판', answer.facts.filter(f => f.kind === 'version')],
|
|
19
|
+
['칸', answer.facts.filter(f => f.kind === 'cell')],
|
|
20
|
+
['결정', answer.facts.filter(f => f.kind === 'decision')],
|
|
21
|
+
['자리', answer.facts.filter(f => f.kind === 'seat')],
|
|
22
|
+
] as const;
|
|
23
|
+
const lines = rows.map(([label, facts]) => `${label}: ${facts.length ? facts.map(f => `${factText(f)} — ${f.source}`).join(' · ') : '없음'}`);
|
|
24
|
+
lines.push(`최근: ${answer.events.length ? answer.events.map(e => `${e.summary} — ${e.source}`).join(' · ') : '없음'}${answer.guide.length ? ` · 안내 ${answer.guide.join(' · ')}` : ''}`);
|
|
25
|
+
return lines.map(line => line.replace(/\s+/g, ' ').trim()).join('\n');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function renderTuiNow(answer: ContextNowAnswer): string[] {
|
|
29
|
+
const rows = [
|
|
30
|
+
...answer.facts.map(f => [f.kind, factText(f), f.source]),
|
|
31
|
+
...answer.events.map(e => [e.kind, e.summary, e.source]),
|
|
32
|
+
...answer.guide.map(guide => ['안내', guide, '']),
|
|
33
|
+
];
|
|
34
|
+
return [
|
|
35
|
+
`지금${answer.topic ? ` · ${answer.topic}` : ''} (${answer.at})`,
|
|
36
|
+
'| 종류 | 사실 | 출처 |',
|
|
37
|
+
'| --- | --- | --- |',
|
|
38
|
+
...rows.map(row => `| ${row.map(cell => cell.replaceAll('|', '\\|').replaceAll(/\r?\n/g, ' ')).join(' | ')} |`),
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function telegramNowSlash(args: string[], deps?: ContextNowDeps): string {
|
|
43
|
+
return renderTelegramNow(readSlashContextNow(args, deps));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function tuiNowSlash(args: string[], deps?: ContextNowDeps): string[] {
|
|
47
|
+
return renderTuiNow(readSlashContextNow(args, deps));
|
|
48
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { debug, redactSecretText } from '../debug/log.js';
|
|
3
|
+
import { DecisionLedger, type DecisionEntry } from '../decisions/decision-ledger.js';
|
|
4
|
+
import { listChecklist, devVersion, type Checklist } from '../release-loop/checklist.js';
|
|
5
|
+
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
6
|
+
import { seatDay, seatLedgerPath, type SeatEntry } from '../seat-loop/seat-loop.js';
|
|
7
|
+
import { listCoordEvents, type CoordEvent } from './coord-events.js';
|
|
8
|
+
|
|
9
|
+
export type ContextFact =
|
|
10
|
+
| { kind: 'version'; version: string; source: string }
|
|
11
|
+
| { kind: 'cell'; version: string; id: string; title: string; status: string; owner: string | null; source: string }
|
|
12
|
+
| { kind: 'decision'; id: string; title: string; status: string; dueAt: string | null; source: string }
|
|
13
|
+
| { kind: 'seat'; seat: string; at: string; status: string; id: string | null; title: string | null; source: string };
|
|
14
|
+
export type ContextEvent = { at: string; kind: string; summary: string; source: string };
|
|
15
|
+
export type ContextNowAnswer = { at: string; topic: string | null; facts: ContextFact[]; events: ContextEvent[]; guide: string[] };
|
|
16
|
+
|
|
17
|
+
export interface ContextNowDeps {
|
|
18
|
+
now?: () => Date;
|
|
19
|
+
version?: () => string;
|
|
20
|
+
checklist?: (version: string) => Checklist;
|
|
21
|
+
decisions?: () => DecisionEntry[];
|
|
22
|
+
seatEntries?: (now: Date) => Array<{ entry: SeatEntry; source: string }>;
|
|
23
|
+
events?: (since: string) => CoordEvent[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function todaySeatEntries(now: Date): Array<{ entry: SeatEntry; source: string }> {
|
|
27
|
+
const root = effectiveInstanceRoot();
|
|
28
|
+
const day = seatDay(now);
|
|
29
|
+
return ['OP', 'TC', 'MK', 'UX'].flatMap(seat => {
|
|
30
|
+
const path = seatLedgerPath(seat, root, now);
|
|
31
|
+
if (!existsSync(path)) return [];
|
|
32
|
+
return readFileSync(path, 'utf8').split('\n').flatMap((line, index) => line.trim() ? [{
|
|
33
|
+
entry: JSON.parse(line) as SeatEntry,
|
|
34
|
+
source: `elanous://seat-loop/${seat}/${day}#${index + 1}`,
|
|
35
|
+
}] : []);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Read a bounded, source-labelled view of current ledgers, never a transcript or decision body. */
|
|
40
|
+
export function contextNow(options: { topic?: string; limit?: number } = {}, deps: ContextNowDeps = {}): ContextNowAnswer {
|
|
41
|
+
const now = (deps.now ?? (() => new Date()))();
|
|
42
|
+
const at = `${now.toISOString().slice(0, 16)}:00.000Z`;
|
|
43
|
+
const topic = options.topic?.trim() || null;
|
|
44
|
+
const limit = typeof options.limit === 'number' && Number.isFinite(options.limit)
|
|
45
|
+
? Math.max(1, Math.min(100, Math.floor(options.limit))) : 20;
|
|
46
|
+
const version = (deps.version ?? devVersion)().replace(/-.*$/, '');
|
|
47
|
+
const next = version.replace(/^(\d+)\.(\d+)\.(\d+)$/, (_, major: string, minor: string, patch: string) => `${major}.${minor}.${Number(patch) + 1}`);
|
|
48
|
+
const facts: ContextFact[] = [];
|
|
49
|
+
for (const v of [...new Set([version, next])]) {
|
|
50
|
+
const checklist = (deps.checklist ?? listChecklist)(v);
|
|
51
|
+
if (v === version) facts.push({ kind: 'version', version: v, source: `elanous://release/${v}/checklist` });
|
|
52
|
+
for (const item of checklist.items) {
|
|
53
|
+
if (item.status === 'done') continue;
|
|
54
|
+
facts.push({ kind: 'cell', version: v, id: item.id, title: redactSecretText(item.title.split(/\r?\n/, 1)[0] ?? '').slice(0, 120),
|
|
55
|
+
status: item.status, owner: item.owner ?? null, source: `elanous://release/${v}/checklist#${encodeURIComponent(item.id)}` });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const item of (deps.decisions ?? (() => new DecisionLedger().list({ status: 'open' })))()) {
|
|
59
|
+
if (item.status !== 'open') continue;
|
|
60
|
+
facts.push({ kind: 'decision', id: item.id, title: redactSecretText(item.title.split(/\r?\n/, 1)[0] ?? '').slice(0, 120),
|
|
61
|
+
status: item.status, dueAt: item.dueAt ?? null, source: `elanous://decisions/${encodeURIComponent(item.id)}` });
|
|
62
|
+
}
|
|
63
|
+
for (const { entry, source } of (deps.seatEntries ?? todaySeatEntries)(now)) {
|
|
64
|
+
facts.push({ kind: 'seat', seat: entry.seat, at: entry.at, status: entry.status,
|
|
65
|
+
id: entry.item?.id ?? null, title: entry.item?.source === 'checklist'
|
|
66
|
+
? redactSecretText(entry.item.title.split(/\r?\n/, 1)[0] ?? '').slice(0, 120) : null, source });
|
|
67
|
+
}
|
|
68
|
+
const rawEvents = (deps.events ?? (since => listCoordEvents({ since })))(new Date(now.getTime() - 7 * 86_400_000).toISOString());
|
|
69
|
+
const chronologicalEvents = rawEvents.slice().sort((a, b) => a.at.localeCompare(b.at) || a.id.localeCompare(b.id));
|
|
70
|
+
const matches = (text: string) => !topic || text.toLocaleLowerCase().includes(topic.toLocaleLowerCase());
|
|
71
|
+
const selectedFacts = facts.filter(f => !topic || (f.kind === 'cell' && matches(`${f.id} ${f.title}`))
|
|
72
|
+
|| (f.kind === 'seat' && matches(`${f.id ?? ''} ${f.title ?? ''}`)));
|
|
73
|
+
const groups = (['version', 'cell', 'decision', 'seat'] as const).map(kind => selectedFacts.filter(f => f.kind === kind));
|
|
74
|
+
groups[3]!.sort((a, b) => (a.kind === 'seat' && b.kind === 'seat' ? b.at.localeCompare(a.at) : 0));
|
|
75
|
+
const nonEmpty = groups.filter(group => group.length > 0);
|
|
76
|
+
const perKind = Math.floor(limit / nonEmpty.length);
|
|
77
|
+
const chosen = groups.map(group => group.splice(0, perKind));
|
|
78
|
+
let remaining = limit - chosen.reduce((total, group) => total + group.length, 0);
|
|
79
|
+
for (const index of [2, 3, 0, 1]) {
|
|
80
|
+
if (remaining <= 0) break;
|
|
81
|
+
if (chosen[index]!.length === 0 && groups[index]!.length > 0) {
|
|
82
|
+
chosen[index]!.push(...groups[index]!.splice(0, 1));
|
|
83
|
+
remaining--;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
for (const index of [1, 2, 3, 0]) {
|
|
87
|
+
if (remaining <= 0) break;
|
|
88
|
+
const extra = groups[index]!.splice(0, remaining);
|
|
89
|
+
chosen[index]!.push(...extra);
|
|
90
|
+
remaining -= extra.length;
|
|
91
|
+
}
|
|
92
|
+
const boundedFacts = chosen.flat();
|
|
93
|
+
const summaries = chronologicalEvents.map(event => ({
|
|
94
|
+
at: event.at, kind: event.kind, summary: redactSecretText(event.summary.split(/\r?\n/, 1)[0] ?? '').slice(0, 120),
|
|
95
|
+
source: event.refs.source ?? event.refs.url ?? `elanous://context/event/${encodeURIComponent(event.id)}`,
|
|
96
|
+
}));
|
|
97
|
+
const selectedEvents = summaries.filter(event => matches(event.summary)).reverse().slice(0, limit);
|
|
98
|
+
const guide = summaries.filter(event => event.kind === 'guide-changed' || event.summary.startsWith('📌안내'))
|
|
99
|
+
.filter(event => matches(event.summary)).reverse().slice(0, limit)
|
|
100
|
+
.map(event => `📌 ${event.summary} — ${event.source}`);
|
|
101
|
+
const answer = { at, topic, facts: boundedFacts, events: selectedEvents, guide };
|
|
102
|
+
debug.log('context.now', 'answer', { topic, facts: answer.facts, events: answer.events });
|
|
103
|
+
return answer;
|
|
104
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { Database } from 'bun:sqlite';
|
|
2
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { debug, redactSecretText } from '../debug/log.js';
|
|
5
|
+
import { openSurfaceEventsDb, recordEvent, surfaceEventsDbPath } from '../domains/surface-events.js';
|
|
6
|
+
|
|
7
|
+
export interface CoordEventInput {
|
|
8
|
+
seat: string;
|
|
9
|
+
recipients: string[];
|
|
10
|
+
all: boolean;
|
|
11
|
+
kind: string | null;
|
|
12
|
+
slot: string | null;
|
|
13
|
+
deadline: string | null;
|
|
14
|
+
url: string | null;
|
|
15
|
+
headline: string;
|
|
16
|
+
at?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface CoordEvent {
|
|
20
|
+
id: string;
|
|
21
|
+
at: string;
|
|
22
|
+
text: string;
|
|
23
|
+
summary: string;
|
|
24
|
+
kind: string;
|
|
25
|
+
refs: Pick<CoordEventInput, 'seat' | 'recipients' | 'all' | 'kind' | 'slot' | 'deadline' | 'url'> & { origin?: string; source?: string };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function seatIds(): Set<string> {
|
|
29
|
+
return new Set((JSON.parse(readFileSync(resolve(import.meta.dir, '../../scripts/coord-tracks.json'), 'utf8')) as
|
|
30
|
+
{ tracks: Array<{ id: string }> }).tracks.map((track) => track.id));
|
|
31
|
+
}
|
|
32
|
+
const kinds = new Set(['요청', '결정', '사고', '보고', '정정']);
|
|
33
|
+
|
|
34
|
+
/** Mirror the sender's ordered envelope fields; only the first line enters this parser. */
|
|
35
|
+
export function parseCoordHeader(seat: string, header: string): Omit<CoordEventInput, 'url' | 'at'> {
|
|
36
|
+
const first = header.split(/\r?\n/, 1)[0] ?? '';
|
|
37
|
+
if (!first.startsWith(`**[${seat}]**`)) throw new Error('조율 글 신원 접두 불일치');
|
|
38
|
+
const headline = first.slice(`**[${seat}]**`.length)
|
|
39
|
+
.replace(/^\s*(?:📌안내\s*)?\d{4}-\d\d-\d\d\s+\d\d:\d\d\s+KST\s*/, '').trim();
|
|
40
|
+
const headerBody = first.slice(`**[${seat}]**`.length);
|
|
41
|
+
const arrow = headerBody.indexOf('→');
|
|
42
|
+
const envelope = arrow >= 0 && !headerBody.slice(0, arrow).includes(' · ') ? headerBody.slice(arrow + 1).trim() : '';
|
|
43
|
+
const fields = envelope ? envelope.split(' · ') : [];
|
|
44
|
+
const ids = seatIds();
|
|
45
|
+
const recipients: string[] = [];
|
|
46
|
+
let all = false;
|
|
47
|
+
let i = 0;
|
|
48
|
+
for (; i < fields.length; i++) {
|
|
49
|
+
const field = fields[i]!.trim().split(' — ')[0]!;
|
|
50
|
+
const tokens = field.replaceAll(',', ' ').split(/\s+/).filter(Boolean);
|
|
51
|
+
if (!tokens.length || !tokens.every((t) => t === '전원' || ids.has(t))) break;
|
|
52
|
+
for (const token of tokens) {
|
|
53
|
+
if (token === '전원') all = true;
|
|
54
|
+
else recipients.push(token);
|
|
55
|
+
}
|
|
56
|
+
if (fields[i]!.includes(' — ')) { i++; break; }
|
|
57
|
+
}
|
|
58
|
+
const candidate = fields[i]?.trim() ?? '';
|
|
59
|
+
const kind = kinds.has(candidate) ? candidate : null;
|
|
60
|
+
const slot = fields[i + 1]?.trim() || null;
|
|
61
|
+
const deadline = fields.slice(i + 1).map((f) => f.trim()).find((f) => /^기한\s+\S/.test(f)) ?? null;
|
|
62
|
+
return { seat, recipients, all, kind, slot, deadline, headline };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Atomic lookup+insert makes retries safe, including URL-less posts in the same minute. */
|
|
66
|
+
export function recordCoordEvent(input: CoordEventInput, deps: { db?: Database } = {}): string {
|
|
67
|
+
const hasUrl = !!input.url;
|
|
68
|
+
let db: Database | undefined;
|
|
69
|
+
try {
|
|
70
|
+
db = deps.db ?? openSurfaceEventsDb();
|
|
71
|
+
const at = input.at ?? new Date().toISOString();
|
|
72
|
+
const first = input.headline.split(/\r?\n/, 1)[0] ?? '';
|
|
73
|
+
const withoutPrefix = first.replace(/^\*\*\[[A-Z]+\]\*\*\s*/, '')
|
|
74
|
+
.replace(/^(?:📌안내\s*)?\d{4}-\d\d-\d\d\s+\d\d:\d\d\s+KST\s*/, '');
|
|
75
|
+
const headline = redactSecretText(withoutPrefix).trim().slice(0, 120);
|
|
76
|
+
const safe = (value: string) => redactSecretText(value.split(/\r?\n/, 1)[0] ?? '');
|
|
77
|
+
const refs = { seat: safe(input.seat), recipients: input.recipients.map(safe), all: input.all,
|
|
78
|
+
kind: input.kind === null ? null : safe(input.kind), slot: input.slot === null ? null : safe(input.slot),
|
|
79
|
+
deadline: input.deadline === null ? null : safe(input.deadline), url: input.url ? safe(input.url) : null };
|
|
80
|
+
const result = db.transaction(() => {
|
|
81
|
+
const prior = (refs.url
|
|
82
|
+
? db!.prepare(`SELECT id FROM events WHERE surface='coord:channel' AND json_extract(refs,'$.url')=? LIMIT 1`).get(refs.url)
|
|
83
|
+
: db!.prepare(`SELECT id FROM events WHERE surface='coord:channel' AND json_extract(refs,'$.url') IS NULL
|
|
84
|
+
AND json_extract(refs,'$.seat')=? AND summary=? AND substr(ts,1,16)=? LIMIT 1`)
|
|
85
|
+
.get(refs.seat, headline, at.slice(0, 16))) as { id: string } | null;
|
|
86
|
+
if (prior) return { id: prior.id, dedup: true };
|
|
87
|
+
return { id: recordEvent(db!, { surface: 'coord:channel', direction: 'outbound', kind: refs.kind ?? 'unknown',
|
|
88
|
+
domain: 'elanous', category: 'coordination', text: headline, summary: headline,
|
|
89
|
+
refs: JSON.stringify(refs), ts: at }), dedup: false };
|
|
90
|
+
}).immediate();
|
|
91
|
+
try { debug.log('context.coord', result.dedup ? 'dedup' : 'recorded', { seat: refs.seat, kind: refs.kind, hasUrl }); }
|
|
92
|
+
catch { /* observation cannot turn a successful write into a failed send */ }
|
|
93
|
+
return result.id;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
try { debug.log('context.coord', 'failed', { seat: redactSecretText(input.seat), kind: input.kind && redactSecretText(input.kind), hasUrl }); }
|
|
96
|
+
catch { /* preserve the original write error */ }
|
|
97
|
+
throw error;
|
|
98
|
+
} finally { if (!deps.db) db?.close(); }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Read-only chronological list; a missing store is an empty ledger, not a newly created one. */
|
|
102
|
+
export function listCoordEvents(opts: { since: string; seat?: string }, deps: { db?: Database } = {}): CoordEvent[] {
|
|
103
|
+
if (!deps.db && !existsSync(surfaceEventsDbPath())) return [];
|
|
104
|
+
const db = deps.db ?? openSurfaceEventsDb();
|
|
105
|
+
try {
|
|
106
|
+
const rows = db.prepare(`SELECT id, ts, text, summary, kind, refs FROM events
|
|
107
|
+
WHERE surface IN ('coord:channel', 'context:external') AND direction='outbound' AND ts>=?
|
|
108
|
+
${opts.seat ? "AND json_extract(refs,'$.seat')=?" : ''} ORDER BY ts ASC, rowid ASC`)
|
|
109
|
+
.all(...(opts.seat ? [opts.since, opts.seat] : [opts.since])) as Array<{
|
|
110
|
+
id: string; ts: string; text: string; summary: string; kind: string; refs: string;
|
|
111
|
+
}>;
|
|
112
|
+
return rows.map((r) => ({ id: r.id, at: r.ts, text: r.text, summary: r.summary, kind: r.kind,
|
|
113
|
+
refs: JSON.parse(r.refs) as CoordEvent['refs'] }));
|
|
114
|
+
} finally { if (!deps.db) db.close(); }
|
|
115
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Database } from 'bun:sqlite';
|
|
2
|
+
import { debug, redactSecretText } from '../debug/log.js';
|
|
3
|
+
import { openSurfaceEventsDb, recordEvent } from '../domains/surface-events.js';
|
|
4
|
+
|
|
5
|
+
export type ExternalEventOrigin = 'claude-code' | 'codex-agent-mission' | 'harness-child';
|
|
6
|
+
export type ContextHookKind = 'claimed' | 'done' | 'asked' | 'guide-changed';
|
|
7
|
+
export type ExternalEventKind = ContextHookKind | 'started' | 'finished';
|
|
8
|
+
export const CONTEXT_SUMMARY_MAX = 120;
|
|
9
|
+
export const CONTEXT_SOURCE_MAX = 512;
|
|
10
|
+
|
|
11
|
+
export interface ExternalEventInput {
|
|
12
|
+
origin: ExternalEventOrigin;
|
|
13
|
+
kind: ExternalEventKind;
|
|
14
|
+
summary: string;
|
|
15
|
+
source: string;
|
|
16
|
+
at?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Only a single, bounded, redacted summary and a locator enter the journal; no prompt or transcript. */
|
|
20
|
+
export function recordExternalEvent(input: ExternalEventInput, deps: { db?: Database } = {}): string {
|
|
21
|
+
if (!['claude-code', 'codex-agent-mission', 'harness-child'].includes(input.origin)) throw new Error('invalid context origin');
|
|
22
|
+
if (input.origin === 'claude-code'
|
|
23
|
+
? !['claimed', 'done', 'asked', 'guide-changed'].includes(input.kind)
|
|
24
|
+
: !['started', 'finished'].includes(input.kind)) throw new Error('invalid context kind');
|
|
25
|
+
const summary = redactSecretText(input.summary.split(/\r?\n/, 1)[0] ?? '').trim().slice(0, CONTEXT_SUMMARY_MAX);
|
|
26
|
+
const source = redactSecretText(input.source.split(/\r?\n/, 1)[0] ?? '').trim();
|
|
27
|
+
if (!summary) throw new Error('context summary must be one nonempty line');
|
|
28
|
+
|
|
29
|
+
if (!/^(?:https?:\/\/|elanous:\/\/)[^\s]+$/.test(source) || source.length > CONTEXT_SOURCE_MAX) {
|
|
30
|
+
throw new Error('context source must be a link (http(s) or elanous://), at most 512 characters');
|
|
31
|
+
}
|
|
32
|
+
const db = deps.db ?? openSurfaceEventsDb();
|
|
33
|
+
try {
|
|
34
|
+
return recordEvent(db, {
|
|
35
|
+
surface: 'context:external', direction: 'outbound', domain: 'elanous', category: 'coordination',
|
|
36
|
+
kind: input.kind, text: summary, summary,
|
|
37
|
+
refs: JSON.stringify({ seat: input.origin, recipients: [], all: false, kind: input.kind,
|
|
38
|
+
slot: null, deadline: null, url: source, origin: input.origin, source }),
|
|
39
|
+
...(input.at ? { ts: input.at } : {}),
|
|
40
|
+
});
|
|
41
|
+
} finally { if (!deps.db) db.close(); }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Instrumentation never changes an agent's result. Failures remain visible without logging untrusted payloads. */
|
|
45
|
+
export function observeExternalEvent(input: ExternalEventInput, record: typeof recordExternalEvent = recordExternalEvent): void {
|
|
46
|
+
try { record(input); }
|
|
47
|
+
catch (error) {
|
|
48
|
+
try { debug.log('context.external', 'record-failed', {
|
|
49
|
+
origin: input.origin, kind: input.kind, reason: error instanceof Error ? error.message : String(error),
|
|
50
|
+
}, { level: 'warn' }); } catch { /* A broken logger cannot change an agent's result. */ }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { redactSecretText } from '../debug/log.js';
|
|
2
|
+
import { DecisionLedger, type DecisionEntry } from '../decisions/decision-ledger.js';
|
|
3
|
+
import { listCoordEvents, type CoordEvent } from './coord-events.js';
|
|
4
|
+
|
|
5
|
+
export interface MemoryItem {
|
|
6
|
+
project: string;
|
|
7
|
+
seat: string;
|
|
8
|
+
topic: string;
|
|
9
|
+
summary: string;
|
|
10
|
+
source: string;
|
|
11
|
+
updatedAt: string;
|
|
12
|
+
status: 'active' | 'retired';
|
|
13
|
+
/** A normalized, comparable assertion supplied by the summarizer; absent means no conflict judgment. */
|
|
14
|
+
claim?: { key: string; value: string };
|
|
15
|
+
conflict?: { owner: 'OP'; sources: [string, string] };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type MemorySource =
|
|
19
|
+
| { kind: 'event'; at: string; seat: string; text: string; source: string }
|
|
20
|
+
| { kind: 'decision'; at: string; seat: string; text: string; source: string };
|
|
21
|
+
|
|
22
|
+
export interface MemorySummary {
|
|
23
|
+
project: string;
|
|
24
|
+
topic: string;
|
|
25
|
+
summary: string;
|
|
26
|
+
/** Only supply this when the two strings identify the same fact and mutually exclusive values. */
|
|
27
|
+
claim?: { key: string; value: string };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface MemoryDeps {
|
|
31
|
+
summarize: (source: MemorySource) => Promise<MemorySummary>;
|
|
32
|
+
events?: (since: string) => CoordEvent[];
|
|
33
|
+
decisions?: () => DecisionEntry[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const DAY_MS = 86_400_000;
|
|
37
|
+
const oneLine = (text: string) => redactSecretText(text.split(/\r?\n/, 1)[0] ?? '').trim();
|
|
38
|
+
|
|
39
|
+
/** Condense one UTC day; callers persist the returned snapshot, not raw transcripts. Read-only ledger access. */
|
|
40
|
+
export async function condenseContextDay(
|
|
41
|
+
day: string, previous: readonly MemoryItem[], deps: MemoryDeps, now: Date = new Date(),
|
|
42
|
+
): Promise<MemoryItem[]> {
|
|
43
|
+
if (!/^\d{4}-\d\d-\d\d$/.test(day) || new Date(`${day}T00:00:00.000Z`).toISOString().slice(0, 10) !== day) {
|
|
44
|
+
throw new Error('day must be a valid UTC YYYY-MM-DD');
|
|
45
|
+
}
|
|
46
|
+
const since = `${day}T00:00:00.000Z`;
|
|
47
|
+
const start = Date.parse(since);
|
|
48
|
+
const until = start + DAY_MS;
|
|
49
|
+
// The store compares timestamp text, so fetch the previous local day too before UTC filtering.
|
|
50
|
+
const events = (deps.events ?? (from => listCoordEvents({ since: from })))(new Date(start - DAY_MS).toISOString());
|
|
51
|
+
const decisions = (deps.decisions ?? (() => new DecisionLedger().list({ status: 'all' })))();
|
|
52
|
+
const sources: MemorySource[] = [
|
|
53
|
+
...events.map(event => ({ kind: 'event' as const, at: event.at, seat: event.refs.seat,
|
|
54
|
+
text: event.summary, source: event.refs.source ?? event.refs.url ?? `elanous://context/event/${encodeURIComponent(event.id)}` })),
|
|
55
|
+
...decisions.map(decision => ({ kind: 'decision' as const,
|
|
56
|
+
at: decision.decidedAt ?? decision.raisedAt ?? decision.importedAt ?? '',
|
|
57
|
+
seat: decision.raisedBy.track ?? 'OP',
|
|
58
|
+
text: decision.status === 'decided' ? `${decision.title}: ${decision.options.find(o => o.key === decision.choice)?.label ?? decision.note ?? decision.scqa.a ?? '결정됨'}` : `${decision.title}: ${decision.status}`,
|
|
59
|
+
source: `elanous://decisions/${encodeURIComponent(decision.id)}` })),
|
|
60
|
+
].filter(source => {
|
|
61
|
+
const at = Date.parse(source.at);
|
|
62
|
+
return Number.isFinite(at) && at >= start && at < until;
|
|
63
|
+
}).sort((a, b) => Date.parse(a.at) - Date.parse(b.at) || a.source.localeCompare(b.source));
|
|
64
|
+
|
|
65
|
+
const items = new Map<string, MemoryItem>();
|
|
66
|
+
const keyFor = (item: Pick<MemoryItem, 'project' | 'seat' | 'topic'>) => JSON.stringify([item.project, item.seat, item.topic]);
|
|
67
|
+
for (const item of previous) items.set(keyFor(item), { ...item });
|
|
68
|
+
for (const source of sources) {
|
|
69
|
+
const summary = await deps.summarize(source);
|
|
70
|
+
const project = oneLine(summary.project);
|
|
71
|
+
const seat = oneLine(source.seat);
|
|
72
|
+
const topic = oneLine(summary.topic);
|
|
73
|
+
const text = oneLine(summary.summary);
|
|
74
|
+
const link = oneLine(source.source);
|
|
75
|
+
if (!project || !seat || !topic || !text || !/^(?:https?:\/\/|elanous:\/\/)[^\s]+$/.test(link)) {
|
|
76
|
+
throw new Error('memory summary needs a project, seat, topic, one-line summary and source link');
|
|
77
|
+
}
|
|
78
|
+
const claim = summary.claim && { key: oneLine(summary.claim.key), value: oneLine(summary.claim.value) };
|
|
79
|
+
if (claim && (!claim.key || !claim.value)) throw new Error('memory claim needs key and value');
|
|
80
|
+
const key = keyFor({ project, seat, topic });
|
|
81
|
+
const old = items.get(key);
|
|
82
|
+
// Equal timestamps are resolved by the source link, so shuffled input does not change the winner.
|
|
83
|
+
if (old && (Date.parse(old.updatedAt) > Date.parse(source.at)
|
|
84
|
+
|| (Date.parse(old.updatedAt) === Date.parse(source.at) && old.source >= link))) continue;
|
|
85
|
+
items.set(key, { project, seat, topic, summary: text, source: link, updatedAt: source.at,
|
|
86
|
+
status: 'active', ...(claim ? { claim } : {}) });
|
|
87
|
+
}
|
|
88
|
+
const cutoff = now.getTime() - 30 * DAY_MS;
|
|
89
|
+
// Compare only the winning, non-retired assertions; a superseded claim cannot keep a decision candidate alive.
|
|
90
|
+
const finalItems: MemoryItem[] = [...items.values()].map(({ conflict: _conflict, ...item }) => ({ ...item,
|
|
91
|
+
status: Date.parse(item.updatedAt) < cutoff ? 'retired' as const : 'active' as const,
|
|
92
|
+
}));
|
|
93
|
+
finalItems.sort((a, b) => Date.parse(a.updatedAt) - Date.parse(b.updatedAt) || a.source.localeCompare(b.source)
|
|
94
|
+
|| a.seat.localeCompare(b.seat));
|
|
95
|
+
for (let index = 0; index < finalItems.length; index++) {
|
|
96
|
+
const item = finalItems[index]!;
|
|
97
|
+
if (item.status !== 'active' || !item.claim) continue;
|
|
98
|
+
const { key, value } = item.claim;
|
|
99
|
+
const conflicting = finalItems.slice(0, index).find(other => other.status === 'active'
|
|
100
|
+
&& other.project === item.project
|
|
101
|
+
&& other.claim?.key === key && other.claim.value !== value);
|
|
102
|
+
if (conflicting) {
|
|
103
|
+
finalItems[index] = { ...item, conflict: { owner: 'OP', sources: [conflicting.source, item.source] } };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return finalItems.sort((a, b) => a.project.localeCompare(b.project) || a.seat.localeCompare(b.seat)
|
|
107
|
+
|| a.topic.localeCompare(b.topic));
|
|
108
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { showDashboard } from './index.js';
|
|
2
|
+
|
|
3
|
+
const expected = process.env.DASHBOARD_BOOT_SUGGESTION;
|
|
4
|
+
if (!expected) throw new Error('DASHBOARD_BOOT_SUGGESTION is required');
|
|
5
|
+
|
|
6
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
7
|
+
let screen = '';
|
|
8
|
+
process.stdout.write = ((chunk: string | Uint8Array, ...args: unknown[]) => {
|
|
9
|
+
screen += typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf8');
|
|
10
|
+
if (screen.includes(expected)) {
|
|
11
|
+
originalWrite(`FIRST_SCREEN_SUGGESTION=${expected}\n`);
|
|
12
|
+
process.exit(0);
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
}) as typeof process.stdout.write;
|
|
16
|
+
|
|
17
|
+
setTimeout(() => {
|
|
18
|
+
originalWrite(`FIRST_SCREEN_TIMEOUT=${screen.slice(-2000)}\n`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}, 20_000).unref();
|
|
21
|
+
|
|
22
|
+
await showDashboard();
|
|
23
|
+
throw new Error('dashboard exited before suggestion appeared');
|
package/src/dashboard/index.ts
CHANGED
|
@@ -17,6 +17,8 @@ import type { CommandRunner } from '../ad-pipeline/higgsfield-backend.js';
|
|
|
17
17
|
import type { ShootRunOptions } from '../ad-pipeline/shoot-run.js';
|
|
18
18
|
import type { QcThresholds } from '../ad-pipeline/qc.js';
|
|
19
19
|
import { elanousStateRoot } from '../autopilot/state-paths.js';
|
|
20
|
+
import { suggestProjectForFolder } from '../project/project-store.js';
|
|
21
|
+
import { createProjectSuggester } from '../project/project-suggestion.js';
|
|
20
22
|
|
|
21
23
|
const dashboardDefaultShootRunOptions: Required<Pick<ShootRunOptions, 'pollIntervalMs' | 'maxPollsPerJob' | 'submitStaggerMs'>> = {
|
|
22
24
|
pollIntervalMs: 3_000,
|
|
@@ -425,7 +427,6 @@ import {
|
|
|
425
427
|
renderTurnTypeaheadEcho,
|
|
426
428
|
} from '../chat/turn-typeahead.js';
|
|
427
429
|
import { dispatchStreamingTurnTypeaheadSubmission } from './input/streaming-turn-typeahead.js';
|
|
428
|
-
import { wireDashboardTurnTypeaheadEcho } from './turn-typeahead-echo.js';
|
|
429
430
|
import { composeVertical, type LayoutZone } from '../layout/composer.js';
|
|
430
431
|
import type { CoreTurnDispatchTool } from '../core-turn/index.js';
|
|
431
432
|
// streamGrok kept as back-compat shim in chat.ts — not imported here
|
|
@@ -2656,6 +2657,41 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
2656
2657
|
}
|
|
2657
2658
|
chatScrollOffset = -1;
|
|
2658
2659
|
};
|
|
2660
|
+
const liveTypeaheadEchoes: { at: number; lines: string[] }[] = [];
|
|
2661
|
+
const restoreLiveTypeaheadEchoes = (): void => {
|
|
2662
|
+
let after = 0;
|
|
2663
|
+
for (const echo of liveTypeaheadEchoes) {
|
|
2664
|
+
let found = -1;
|
|
2665
|
+
for (let i = after; i <= chatLines.length - echo.lines.length; i++) {
|
|
2666
|
+
if (echo.lines.every((line, offset) => chatLines[i + offset] === line)) {
|
|
2667
|
+
found = i;
|
|
2668
|
+
break;
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
if (found < 0) {
|
|
2672
|
+
found = Math.max(after, Math.min(echo.at, chatLines.length));
|
|
2673
|
+
chatLines.splice(found, 0, ...echo.lines);
|
|
2674
|
+
}
|
|
2675
|
+
echo.at = found;
|
|
2676
|
+
after = found + echo.lines.length;
|
|
2677
|
+
}
|
|
2678
|
+
};
|
|
2679
|
+
const echoSubmittedUserText = (text: string, opts?: { live?: boolean }): void => {
|
|
2680
|
+
const echoStart = chatLines.length;
|
|
2681
|
+
chatLines.push('');
|
|
2682
|
+
if (opts?.live) chatLines.push(C.muted(' ↳ 이어서'));
|
|
2683
|
+
const echoWrapCols = Math.max(20, termSize().cols - 6);
|
|
2684
|
+
const echoRows = wrapAnsiByWidth(`❯ ${text}`, echoWrapCols);
|
|
2685
|
+
if (echoRows.length === 0) {
|
|
2686
|
+
chatLines.push(C.accent('❯ '));
|
|
2687
|
+
} else {
|
|
2688
|
+
echoRows.forEach((row, i) => {
|
|
2689
|
+
chatLines.push(C.accent(i === 0 ? row : ` ${row}`));
|
|
2690
|
+
});
|
|
2691
|
+
}
|
|
2692
|
+
if (opts?.live) liveTypeaheadEchoes.push({ at: echoStart, lines: chatLines.slice(echoStart) });
|
|
2693
|
+
chatScrollOffset = -1;
|
|
2694
|
+
};
|
|
2659
2695
|
const pushDebugLine = (line: string): void => {
|
|
2660
2696
|
debugLines.push(line);
|
|
2661
2697
|
const dropCount = trimLogBuffer(debugLines, DEBUG_LOG_BUFFER_SOFT_LIMIT);
|
|
@@ -6907,7 +6943,7 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
6907
6943
|
turnTypeaheadRef.state = r.state;
|
|
6908
6944
|
if (r.submissionDisposition) {
|
|
6909
6945
|
debug.log('dashboard.turn-typeahead', 'submission-classified', {
|
|
6910
|
-
|
|
6946
|
+
length: (r.immediateSubmission ?? turnTypeaheadRef.state.queuedSubmissions.at(-1))?.length ?? 0,
|
|
6911
6947
|
disposition: r.submissionDisposition,
|
|
6912
6948
|
});
|
|
6913
6949
|
// ⭐⭐⭐ `B3`(2026-08-19 · 대표 지시 ②) — FIFO 로 «턴 종료 후» 나가던 것을,
|
|
@@ -6934,6 +6970,11 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
6934
6970
|
// 배수된 만큼을 앞에서부터 떨어낸다(FIFO · 순서 보존).
|
|
6935
6971
|
const remaining = turnTypeaheadRef.state.queuedSubmissions.slice(drained.length);
|
|
6936
6972
|
turnTypeaheadRef.state = { ...turnTypeaheadRef.state, queuedSubmissions: remaining };
|
|
6973
|
+
for (const text of drained) {
|
|
6974
|
+
echoSubmittedUserText(text, { live: true });
|
|
6975
|
+
debug.log('dashboard.turn-typeahead', 'echoed', { path: 'live', length: text.length });
|
|
6976
|
+
}
|
|
6977
|
+
if (drained.length > 0) draw();
|
|
6937
6978
|
debug.log('dashboard.turn-typeahead', 'drained-into-live-turn', {
|
|
6938
6979
|
drained: drained.length, remaining: remaining.length,
|
|
6939
6980
|
});
|
|
@@ -15751,6 +15792,16 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
15751
15792
|
chatLines.push(C.muted(` ${resume.turns} turns restored. Next turn continues this conversation.`));
|
|
15752
15793
|
}
|
|
15753
15794
|
}
|
|
15795
|
+
// 제안은 세션 작업 폴더 기준 — 시작 폴더 한 번이 아니라 폴더가 바뀔 때마다 다시 계산한다(IA1 리뷰 must-fix).
|
|
15796
|
+
const nextProjectSuggestion = createProjectSuggester(suggestProjectForFolder);
|
|
15797
|
+
const pushProjectSuggestion = (folder: string): void => {
|
|
15798
|
+
const project = nextProjectSuggestion(folder);
|
|
15799
|
+
if (project) chatLines.push(C.muted(` Project suggestion: ${project.name} (${project.id})`));
|
|
15800
|
+
};
|
|
15801
|
+
if (dashboardAcpBootResult.mode !== 'resumed' && !chat.history.some((message) => message.role !== 'system')) {
|
|
15802
|
+
pushProjectSuggestion(getSessionCwd());
|
|
15803
|
+
}
|
|
15804
|
+
subscribeSessionCwd((state) => { pushProjectSuggestion(state.cwd); });
|
|
15754
15805
|
chatScrollOffset = -1;
|
|
15755
15806
|
void renderDashboardFirstScreenBand({
|
|
15756
15807
|
history: chat.history,
|
|
@@ -16820,8 +16871,7 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
16820
16871
|
lastTurnFinalStatus = undefined;
|
|
16821
16872
|
turnTypeaheadRef.state = drained.state;
|
|
16822
16873
|
nextInitial = drained.nextInitial;
|
|
16823
|
-
const
|
|
16824
|
-
if (turnTypeaheadEcho) chatLines.push(C.muted(turnTypeaheadEcho));
|
|
16874
|
+
const queuedTurnEndText = drained.injectEnter ? drained.nextInitial : undefined;
|
|
16825
16875
|
if (interrupted && queuedBeforeDrain > 0) {
|
|
16826
16876
|
debug.log('dashboard.turn-typeahead', 'restored-after-interrupt', { count: queuedBeforeDrain });
|
|
16827
16877
|
}
|
|
@@ -18655,25 +18705,11 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
18655
18705
|
// pattern. Without this draw(), the echo sits in the chatLines
|
|
18656
18706
|
// array but doesn't paint until after the skill router's
|
|
18657
18707
|
// classifier LLM call returns (~1-2s of visual silence).
|
|
18658
|
-
|
|
18659
|
-
|
|
18660
|
-
|
|
18661
|
-
// with a `\u2026+N` marker by the log-pane renderer (which keeps a
|
|
18662
|
-
// strict 1-line-per-row invariant and only truncates lines that
|
|
18663
|
-
// weren't pre-wrapped). termCols-6 leaves room for the log
|
|
18664
|
-
// pane's 2-col left margin plus the 2-col hanging indent on
|
|
18665
|
-
// continuation rows; the \u276f marker stays on the first row only.
|
|
18666
|
-
const echoWrapCols = Math.max(20, termSize().cols - 6);
|
|
18667
|
-
const echoRows = wrapAnsiByWidth(`\u276f ${tok.text}`, echoWrapCols);
|
|
18668
|
-
if (echoRows.length === 0) {
|
|
18669
|
-
chatLines.push(C.accent('\u276f '));
|
|
18670
|
-
} else {
|
|
18671
|
-
echoRows.forEach((row, i) => {
|
|
18672
|
-
chatLines.push(C.accent(i === 0 ? row : ` ${row}`));
|
|
18673
|
-
});
|
|
18708
|
+
echoSubmittedUserText(tok.text);
|
|
18709
|
+
if (queuedTurnEndText !== undefined && input.text === queuedTurnEndText) {
|
|
18710
|
+
debug.log('dashboard.turn-typeahead', 'echoed', { path: 'turn-end', length: queuedTurnEndText.length });
|
|
18674
18711
|
}
|
|
18675
18712
|
renderAttachmentSummary(tok.added);
|
|
18676
|
-
chatScrollOffset = -1;
|
|
18677
18713
|
draw();
|
|
18678
18714
|
|
|
18679
18715
|
// Start the animated thinking indicator BEFORE the router so
|
|
@@ -19031,6 +19067,7 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
19031
19067
|
createTurnStreamRuntime: (initialAssistantStart) => {
|
|
19032
19068
|
latestTurnUsage = undefined;
|
|
19033
19069
|
createDashboardTurnStreamRuntimeEscBoundary(escAbortToolState);
|
|
19070
|
+
liveTypeaheadEchoes.length = 0;
|
|
19034
19071
|
const toolRendering = {
|
|
19035
19072
|
...getUserConfig().chat.rendering.tool,
|
|
19036
19073
|
expandHint: false,
|
|
@@ -19070,6 +19107,11 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
19070
19107
|
});
|
|
19071
19108
|
return {
|
|
19072
19109
|
...turnStreamRuntime,
|
|
19110
|
+
onText: (chunk, accumulated) => {
|
|
19111
|
+
turnStreamRuntime.onText(chunk, accumulated);
|
|
19112
|
+
restoreLiveTypeaheadEchoes();
|
|
19113
|
+
draw();
|
|
19114
|
+
},
|
|
19073
19115
|
onToolCall: (call) => {
|
|
19074
19116
|
const toolCall = call as DashboardTurnStreamCall;
|
|
19075
19117
|
trackEscAbortToolCall(escAbortToolState, toolCall);
|
|
@@ -272,6 +272,8 @@
|
|
|
272
272
|
// `../index.ts`) instead of importing the type — keeps this module free
|
|
273
273
|
// of circular dependency on dashboard/index.ts.
|
|
274
274
|
|
|
275
|
+
import { tuiNowSlash } from '../../context-bus/context-now-surfaces.js';
|
|
276
|
+
import type { ContextNowDeps } from '../../context-bus/context-now.js';
|
|
275
277
|
import { runRebindCommand } from '../../input-core/index.js';
|
|
276
278
|
// B4 (TUI half) — /design reuses the CLI's own resolution so the three
|
|
277
279
|
// surfaces (CLI, PWA panel, this) cannot answer differently.
|
|
@@ -1358,9 +1360,13 @@ function emitReplyToChat(ctx: Pick<DashboardSlashContext, 'pushChatLine'>, line:
|
|
|
1358
1360
|
ctx.pushChatLine(line);
|
|
1359
1361
|
}
|
|
1360
1362
|
|
|
1361
|
-
export function buildDashboardSlashRegistry(): SlashCommandRegistry<DashboardSlashContext, DashboardSlashReturn> {
|
|
1363
|
+
export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps): SlashCommandRegistry<DashboardSlashContext, DashboardSlashReturn> {
|
|
1362
1364
|
const registry = new SlashCommandRegistry<DashboardSlashContext, DashboardSlashReturn>();
|
|
1363
1365
|
|
|
1366
|
+
registry.register(['now'], (args, ctx) => {
|
|
1367
|
+
for (const line of tuiNowSlash(args, nowDeps)) ctx.pushChatLine(line);
|
|
1368
|
+
});
|
|
1369
|
+
|
|
1364
1370
|
// ── B-1.a pilot ────────────────────────────────────────────────────
|
|
1365
1371
|
registry.register(['quit', 'q', 'exit'], (_args, ctx) => {
|
|
1366
1372
|
(ctx.exitTui ?? ctx.closeTui)();
|
|
@@ -3995,6 +4001,13 @@ export function buildDashboardSlashRegistry(): SlashCommandRegistry<DashboardSla
|
|
|
3995
4001
|
}
|
|
3996
4002
|
|
|
3997
4003
|
if (seSub === 'new' || seSub === 'clear') {
|
|
4004
|
+
if (seSub === 'new') {
|
|
4005
|
+
try {
|
|
4006
|
+
const { suggestProjectForFolder } = await import('../../project/project-store.js');
|
|
4007
|
+
const project = suggestProjectForFolder(process.cwd());
|
|
4008
|
+
if (project) ctx.chatLines.push(ctx.muted(` Project suggestion: ${project.name} (${project.id})`));
|
|
4009
|
+
} catch { /* suggestions must not interrupt a new conversation */ }
|
|
4010
|
+
}
|
|
3998
4011
|
// Clear the in-memory history and detach if attached. Doesn't
|
|
3999
4012
|
// delete any session files — those stay on disk for
|
|
4000
4013
|
// /session list to enumerate.
|