elanous 0.2.10 → 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/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{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-54b32bd27726588d.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-35414e0a007b4082.js +1 -0
- 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 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -0
- package/apps/pwa/out/outputs/index.txt +30 -0
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -24
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -24
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/drafts/draft-cleanup.yaml +19 -0
- package/graphs/drafts/recipes.yaml +23 -0
- package/graphs/intake/intake-daily.yaml +2 -1
- package/graphs/ops/recipes.yaml +3 -0
- package/graphs/ops/secret-exposure.yaml +24 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +4 -1
- package/graphs/video/explainer-line.yaml +2 -2
- package/package.json +2 -1
- package/plugins/elanous-hwp/README.md +25 -0
- package/plugins/elanous-hwp/cli.ts +22 -0
- package/plugins/elanous-hwp/converter.ts +237 -0
- package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
- package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
- package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
- package/plugins/elanous-hwp/plugin.json +16 -0
- package/plugins/elanous-hwp/plugin.ts +40 -0
- package/scripts/ci-public-export-leak-gate.ts +75 -14
- package/scripts/ci-public-leak-gate.ts +44 -9
- package/scripts/context-hooks/claude-stop.sh +4 -0
- package/scripts/context-hooks/emit.ts +24 -0
- package/scripts/context-hooks/post-tool-use.sh +4 -0
- package/scripts/coord-channel-watch.sh +12 -0
- package/scripts/coord-requests-bridge.ts +143 -0
- package/scripts/field-feed/lib.ts +4 -0
- package/scripts/fleet/node-setup.sh +20 -3
- package/scripts/homebrew-formula-bump.ts +69 -0
- package/scripts/marketing/measure-site-numbers.ts +169 -0
- package/scripts/measure-gate-shards.ts +309 -0
- package/scripts/mission-request-judge.ts +31 -1
- package/scripts/morning-report.ts +2 -2
- package/scripts/opportunity-scan.ts +1 -1
- package/scripts/release-loop/auto-approve-node.ts +21 -4
- package/scripts/release-loop/cut-branch.ts +84 -0
- 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/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 +61 -10
- package/scripts/signal-digest-cycle.ts +2 -7
- package/scripts/signal-digest-photo.ts +11 -0
- package/scripts/tech1-public-measure.ts +94 -0
- package/scripts/test-diet/node.ts +1 -1
- package/scripts/tui-regress.ts +2 -2
- package/scripts/ux/demo-rehearsal.ts +243 -0
- package/scripts/ux/lib/rehearsal-verdict.ts +73 -0
- package/skills/diagram-master/SKILL.md +366 -0
- package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
- package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
- package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
- package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
- package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
- package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
- package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
- package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
- package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
- package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
- package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
- package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
- package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
- package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
- package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
- package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
- package/skills/diagram-master/references/examples/README.md +69 -0
- package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
- package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
- package/skills/diagram-master/references/pyproject.toml +16 -0
- package/skills/diagram-master/references/quality-checklist.md +33 -0
- package/skills/diagram-master/references/routing-guide.md +164 -0
- package/skills/diagram-master/references/uv.lock +1356 -0
- package/skills/google-workspace/SKILL.md +33 -0
- package/skills/google-workspace/scripts/gws-safe.sh +177 -0
- package/skills/grill-me/SKILL.md +1 -1
- package/skills/lecture-note-digitizer/SKILL.md +926 -0
- package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
- package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
- package/skills/lecture-note-digitizer/references/html-template.md +167 -0
- package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
- package/skills/omni-crawl/SKILL.md +21 -11
- package/skills/omni-crawl/scripts/main.ts +6 -6
- package/skills/omni-crawl/src/router.ts +3 -3
- package/skills/omni-digest/SKILL.md +17 -9
- package/skills/omni-digest/digest.md +2 -2
- package/skills/omni-digest/src/fetch.ts +30 -3
- package/skills/pitch-deck/SKILL.md +2 -2
- package/skills/pitch-deck/template.html +2 -2
- package/skills/youtube-master/SKILL.md +163 -0
- package/skills/youtube-master/package-lock.json +558 -0
- package/skills/youtube-master/package.json +13 -0
- package/skills/youtube-master/references/study-note-template.md +124 -0
- package/skills/youtube-master/scripts/main.ts +435 -0
- package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
- package/skills/youtube-master/src/audio.ts +63 -0
- package/skills/youtube-master/src/domain-staging.ts +50 -0
- package/skills/youtube-master/src/env.ts +36 -0
- package/skills/youtube-master/src/obsidian.ts +155 -0
- package/skills/youtube-master/src/router.ts +110 -0
- package/skills/youtube-master/src/stt.ts +199 -0
- package/skills/youtube-master/src/study-note.ts +175 -0
- package/skills/youtube-master/src/summarize.ts +358 -0
- package/skills/youtube-master/src/transcript.ts +76 -0
- package/skills/youtube-master/src/types.ts +91 -0
- package/skills/youtube-master/src/util.ts +93 -0
- package/skills/youtube-master/src/youtube.ts +70 -0
- package/skills/youtube-master/tsconfig.json +13 -0
- package/src/acp/server.ts +5 -2
- package/src/agent-mission/driver.ts +80 -10
- package/src/agent-mission/pty-decision.ts +71 -0
- package/src/agent-mission/review-loop.ts +30 -0
- package/src/autopilot/build/llm-conflict-merge.ts +16 -3
- package/src/autopilot/tool-registry.ts +2 -0
- package/src/boot/daemon-prompt-turn.ts +5 -0
- package/src/boot/daemon-runtime.ts +9 -3
- package/src/boot/daemon-tools/web-search.ts +3 -0
- package/src/card-followup/core.ts +109 -0
- package/src/chat/index.ts +1 -0
- package/src/cli/drive-input-jail.ts +101 -0
- package/src/cli/hooks-cli.ts +17 -3
- package/src/cli/make-cli.ts +43 -0
- package/src/cli/persona-cli.ts +90 -4
- package/src/cli/plugin-cli.ts +31 -22
- package/src/cli/pod-cli.ts +19 -9
- package/src/cli/pr-cli.ts +51 -15
- package/src/cli/pty-drive-cli.ts +41 -7
- package/src/cli/pty-drive-verdict.ts +40 -0
- package/src/cli/release-cli.ts +17 -4
- package/src/cli/setup-cli.ts +43 -1
- package/src/cli/skills-cli.ts +17 -1
- package/src/context-bus/claude-hooks-install.ts +10 -0
- package/src/context-bus/context-now-surfaces.ts +48 -0
- package/src/context-bus/context-now.ts +104 -0
- package/src/context-bus/coord-events.ts +2 -2
- package/src/context-bus/external-events.ts +52 -0
- package/src/context-bus/long-term-memory.ts +108 -0
- package/src/dashboard/index.ts +9 -4
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +7 -1
- package/src/decisions/decision-cards.ts +10 -3
- package/src/decisions/decision-ledger.ts +13 -5
- package/src/discord/sprint21-runtime.ts +5 -1
- package/src/discord-self-message.ts +32 -0
- package/src/discord-slash-wire.ts +5 -1
- package/src/discord.ts +17 -1
- package/src/domains/core-tools.ts +3 -2
- package/src/domains/outbound-alert.ts +6 -1
- package/src/domains/telegram-kind-route.ts +51 -13
- package/src/exec-requests/default-outputs.ts +25 -0
- package/src/exec-requests/planner.ts +10 -2
- package/src/exec-requests/runner.ts +20 -6
- package/src/exec-requests/store.ts +3 -0
- package/src/execution-loop/launch-gate.ts +100 -0
- package/src/field/field-reel.ts +5 -1
- package/src/field-note/index.ts +201 -0
- package/src/field-note/transcribe.ts +248 -0
- package/src/graph-kinds/registry.ts +3 -3
- package/src/graph-runner/graph-cli.ts +61 -1
- package/src/graph-runner/graph-grow-llm.ts +37 -0
- package/src/graph-runner/graph-grow.ts +47 -0
- package/src/graph-runner/runner.ts +317 -25
- package/src/grok/agent-search.ts +8 -2
- package/src/guardian/secret-exposure-scan.ts +101 -0
- package/src/harness/harness-cli-command.ts +247 -7
- package/src/harness/harness-pod-dispatch.ts +43 -23
- package/src/harness/harness-seams.ts +38 -4
- package/src/harness/harness-stop.ts +23 -4
- package/src/harness/launch-registry.ts +91 -0
- package/src/harness/process-garbage.ts +5 -3
- package/src/hooks/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 +52 -14
- package/src/intake-plane/categorize.ts +18 -46
- package/src/intake-plane/discord-seat-work.ts +10 -0
- package/src/intake-plane/front-route-classifier.ts +33 -39
- package/src/intake-plane/persona-answer.ts +30 -0
- package/src/intake-plane/runtime-callables.ts +8 -1
- package/src/intake-plane/telegram-seat-work.ts +36 -2
- package/src/intake-plane/wish-folder.ts +67 -0
- package/src/intent-gate/gate.ts +30 -10
- package/src/live/detail-switch.ts +5 -0
- package/src/llm/difficulty.ts +57 -0
- package/src/llm/judge-layer.ts +101 -0
- package/src/llm/mission-router.ts +33 -19
- package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
- package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
- package/src/loops/contract/examples/steward.loop.yaml +50 -0
- package/src/loops/contract/loop-agent.schema.json +138 -0
- package/src/loops/contract/validate.ts +64 -0
- package/src/loops/registry.ts +20 -6
- package/src/market/signed-index.ts +4 -0
- package/src/maturity/bot-command-maturity.ts +45 -0
- package/src/maturity/feature-maturity.ts +26 -4
- package/src/model-tier/index.ts +2 -2
- package/src/model-tier/tier-resolver.ts +20 -20
- package/src/model-tier/types.ts +6 -6
- package/src/mss/logging/log-store.ts +15 -0
- package/src/nexus/api/config-model-tier.ts +5 -4
- package/src/nexus/api/fabric-plans.ts +53 -0
- package/src/nexus/api/harness-api.ts +5 -1
- package/src/nexus/api/health.ts +2 -0
- package/src/nexus/api/http-server.ts +36 -0
- package/src/nexus/api/inside-events.ts +226 -0
- package/src/nexus/api/meta-api.ts +21 -8
- package/src/nexus/api/missions.ts +6 -1
- package/src/nexus/api/ops-seats.ts +33 -0
- package/src/nexus/api/outputs-route.ts +44 -0
- package/src/nexus/api/seat-requests.ts +44 -2
- package/src/nexus/api/sessions-store.ts +17 -38
- package/src/nexus/api/sub-seat-charters.ts +34 -0
- package/src/nexus/api/tabs-mutations.ts +3 -1
- package/src/nexus/api/trace.ts +18 -6
- package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
- package/src/nexus/api/workflows.ts +80 -6
- package/src/nexus/index.ts +2 -0
- 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/voice-ai.ts +3 -3
- package/src/org/seat-budget.ts +48 -0
- package/src/org/stall-escalation.ts +63 -0
- package/src/outputs/ledger.ts +120 -0
- package/src/persona/persona-todo.ts +79 -0
- package/src/persona/presets.ts +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-suggestion.ts +16 -0
- package/src/project/session-context.ts +24 -0
- package/src/release-loop/checklist.ts +2 -2
- package/src/release-loop/feature-store.ts +5 -3
- package/src/release-loop/next-md-merge.ts +58 -0
- package/src/release-loop/release-note.ts +59 -4
- package/src/seat-dispatch/seat-ask.ts +130 -0
- package/src/seat-dispatch/seat-questions.ts +100 -0
- package/src/seat-loop/seat-loop.ts +548 -29
- package/src/seat-loop/seat-report.ts +37 -2
- package/src/self-dev/dev-cli.ts +4 -1
- package/src/self-dev/dev-pipeline.ts +37 -1
- package/src/self-dev/draft-sweep.ts +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/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/gate-baseline.ts +1 -1
- package/src/self-implement/gate-cli.ts +40 -1
- 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 +242 -9
- package/src/self-implement/route-consumer-test-index.ts +122 -0
- package/src/self-implement/seams.ts +72 -11
- package/src/self-implement/test-seams.ts +1 -0
- package/src/self-implement/uncommitted-work.ts +59 -0
- package/src/session/index.ts +36 -13
- package/src/skills/gift-install.ts +215 -0
- package/src/skills/tools/web-search.ts +4 -1
- package/src/steward/launch.ts +42 -26
- package/src/steward/steward-cards.ts +17 -9
- package/src/steward/triage.ts +46 -14
- package/src/task-cards/card-cli.ts +25 -1
- package/src/task-orchestrator/mission.ts +5 -0
- package/src/task-orchestrator/store.ts +12 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +29 -7
- package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
- package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +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 +16 -96
- package/src/telegram-commands.ts +10 -1
- package/src/telegram-project-command.ts +71 -0
- package/src/telegram-report.ts +21 -17
- package/src/telegram.ts +29 -3
- package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
- package/src/user-config.ts +102 -20
- package/src/version/packed-revision.json +1 -1
- package/src/web-search/grok.ts +7 -1
- package/src/web-search/index.ts +28 -1
- package/src/web-search/provider.ts +4 -0
- package/src/web-search/x-intent.ts +5 -0
- package/src/workflow-runtime/executor.ts +277 -47
- package/src/workflow-runtime/index.ts +1 -0
- package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
- package/src/workflow-runtime/plugin-kind-node.ts +1 -1
- package/src/workflow-runtime/schema.ts +79 -4
- package/src/workflow-runtime/types.ts +35 -4
- package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
- package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
- package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
- /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → Y4zKzL62sakG5momz3SoQ}/_ssgManifest.js +0 -0
|
@@ -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
|
+
}
|
|
@@ -22,7 +22,7 @@ export interface CoordEvent {
|
|
|
22
22
|
text: string;
|
|
23
23
|
summary: string;
|
|
24
24
|
kind: string;
|
|
25
|
-
refs: Pick<CoordEventInput, 'seat' | 'recipients' | 'all' | 'kind' | 'slot' | 'deadline' | 'url'
|
|
25
|
+
refs: Pick<CoordEventInput, 'seat' | 'recipients' | 'all' | 'kind' | 'slot' | 'deadline' | 'url'> & { origin?: string; source?: string };
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function seatIds(): Set<string> {
|
|
@@ -104,7 +104,7 @@ export function listCoordEvents(opts: { since: string; seat?: string }, deps: {
|
|
|
104
104
|
const db = deps.db ?? openSurfaceEventsDb();
|
|
105
105
|
try {
|
|
106
106
|
const rows = db.prepare(`SELECT id, ts, text, summary, kind, refs FROM events
|
|
107
|
-
WHERE surface
|
|
107
|
+
WHERE surface IN ('coord:channel', 'context:external') AND direction='outbound' AND ts>=?
|
|
108
108
|
${opts.seat ? "AND json_extract(refs,'$.seat')=?" : ''} ORDER BY ts ASC, rowid ASC`)
|
|
109
109
|
.all(...(opts.seat ? [opts.since, opts.seat] : [opts.since])) as Array<{
|
|
110
110
|
id: string; ts: string; text: string; summary: string; kind: string; refs: string;
|
|
@@ -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
|
+
}
|
package/src/dashboard/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ 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
20
|
import { suggestProjectForFolder } from '../project/project-store.js';
|
|
21
|
+
import { createProjectSuggester } from '../project/project-suggestion.js';
|
|
21
22
|
|
|
22
23
|
const dashboardDefaultShootRunOptions: Required<Pick<ShootRunOptions, 'pollIntervalMs' | 'maxPollsPerJob' | 'submitStaggerMs'>> = {
|
|
23
24
|
pollIntervalMs: 3_000,
|
|
@@ -15791,12 +15792,16 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
15791
15792
|
chatLines.push(C.muted(` ${resume.turns} turns restored. Next turn continues this conversation.`));
|
|
15792
15793
|
}
|
|
15793
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
|
+
};
|
|
15794
15801
|
if (dashboardAcpBootResult.mode !== 'resumed' && !chat.history.some((message) => message.role !== 'system')) {
|
|
15795
|
-
|
|
15796
|
-
const project = suggestProjectForFolder(process.cwd());
|
|
15797
|
-
if (project) chatLines.push(C.muted(` Project suggestion: ${project.name} (${project.id})`));
|
|
15798
|
-
} catch { /* suggestions must not interrupt the dashboard conversation */ }
|
|
15802
|
+
pushProjectSuggestion(getSessionCwd());
|
|
15799
15803
|
}
|
|
15804
|
+
subscribeSessionCwd((state) => { pushProjectSuggestion(state.cwd); });
|
|
15800
15805
|
chatScrollOffset = -1;
|
|
15801
15806
|
void renderDashboardFirstScreenBand({
|
|
15802
15807
|
history: chat.history,
|
|
@@ -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)();
|
|
@@ -43,6 +43,7 @@ export function renderCardText(e: DecisionEntry, extra: { note?: string; confirm
|
|
|
43
43
|
'',
|
|
44
44
|
`상황: ${e.scqa.s}`,
|
|
45
45
|
`문제: ${e.scqa.c}`,
|
|
46
|
+
...(e.pendingQuestion ? ['', `대기 질문 전문:\n${e.pendingQuestion}`] : []),
|
|
46
47
|
...(e.scqa.q ? [`질문: ${e.scqa.q}`] : []),
|
|
47
48
|
...(e.scqa.a ? [`제안: ${e.scqa.a}`] : []),
|
|
48
49
|
'',
|
|
@@ -180,7 +181,8 @@ export class DecisionCardService {
|
|
|
180
181
|
const entry = this.ledger.raise({
|
|
181
182
|
title: question.question.split(/\r?\n/, 1)[0]!.slice(0, 120),
|
|
182
183
|
category: question.impact === 'critical' ? 'irreversible' : 'scope',
|
|
183
|
-
scqa: { s: question.question, c:
|
|
184
|
+
scqa: { s: Array.from(question.question.split(/\r?\n/, 1)[0]!).slice(0, 200).join(''), c: 'The requesting run is waiting for this choice.' },
|
|
185
|
+
pendingQuestion: question.question,
|
|
184
186
|
options: question.options.map((option, index) => ({ key: keys[index]!, label: option.label, consequence: option.description })),
|
|
185
187
|
recommendation: recommended !== undefined && Number.isInteger(recommended) && recommended >= 0 && recommended < question.options.length
|
|
186
188
|
? { option: keys[recommended]!, why: '런이 추천' } : { skipped: true, reason: '추천 없음' },
|
|
@@ -251,9 +253,12 @@ export class DecisionCardService {
|
|
|
251
253
|
return { kind: 'confirm', view: renderCard(entry, { confirm: parsed.key, ...(card?.note ? { note: card.note } : {}) }), toast: '되돌릴 수 없는 결정 — 한 번 더 확인해 주세요' };
|
|
252
254
|
}
|
|
253
255
|
let decided: DecisionEntry;
|
|
256
|
+
let answerDelivery: ReturnType<DecisionLedger['decideWithDelivery']>['delivery'] = null;
|
|
254
257
|
try {
|
|
255
258
|
// Same ledger method the CLI `decide` uses — one record path.
|
|
256
|
-
|
|
259
|
+
const recorded = this.ledger.decideWithDelivery(entry.id, parsed.key, { kind: 'human' }, card?.note);
|
|
260
|
+
decided = recorded.entry;
|
|
261
|
+
answerDelivery = recorded.delivery;
|
|
257
262
|
} catch (error) {
|
|
258
263
|
debug.log('decisions.telegram', 'decide-failed', { platform, id: entry.id, reason: error instanceof Error ? error.message.slice(0, 80) : 'unknown' }, { level: 'warn' });
|
|
259
264
|
try { const now = this.ledger.show(entry.id); if (now.status !== 'open') return { kind: 'closed', view: renderCard(now), toast: '이미 정해진 결정입니다' }; } catch { /* fall through */ }
|
|
@@ -269,7 +274,9 @@ export class DecisionCardService {
|
|
|
269
274
|
await this.opts.replyToRaiser?.(decided, platform).catch((error: unknown) => {
|
|
270
275
|
debug.log('decisions.telegram', 'reply-failed', { platform, id: decided.id, reason: error instanceof Error ? error.message.slice(0, 80) : 'unknown' }, { level: 'warn' });
|
|
271
276
|
});
|
|
272
|
-
return { kind: 'decided', view, toast:
|
|
277
|
+
return { kind: 'decided', view, toast: answerDelivery && !answerDelivery.ok
|
|
278
|
+
? `결정은 기록됐지만 런 답 전달 실패 — decisions retry-answer ${decided.id}`
|
|
279
|
+
: `결정했습니다: ${decided.choice?.toUpperCase()}` };
|
|
273
280
|
}
|
|
274
281
|
|
|
275
282
|
/** Store a memo typed after «메모 달기»; the card shows it and the eventual decision carries it. */
|
|
@@ -7,7 +7,8 @@ import { createVersionResolver, type VersionOptions, type Versions } from '../di
|
|
|
7
7
|
import { getUserConfig } from '../user-config.js';
|
|
8
8
|
|
|
9
9
|
export type DecisionCategory = 'secret' | 'publish' | 'money' | 'security' | 'scope' | 'irreversible' | 'other';
|
|
10
|
-
|
|
10
|
+
/** Old track letters (S·T·F·O) stay readable; seat names (OP·MK·TC·UX) are the current identities. */
|
|
11
|
+
export type DecisionTrack = 'S' | 'T' | 'F' | 'O' | 'OP' | 'MK' | 'TC' | 'UX';
|
|
11
12
|
export interface DecisionOption { key: string; label: string; consequence: string }
|
|
12
13
|
export type Recommendation = { option: string; why: string } | { skipped: true; reason: string };
|
|
13
14
|
export type DecisionActor = { kind: 'human' } | { kind: 'auto'; agent: string; track?: DecisionTrack; delegation: string };
|
|
@@ -17,13 +18,15 @@ export interface DecisionEntry {
|
|
|
17
18
|
raisedBy: { agent: string; track?: DecisionTrack; session?: string }; version?: Versions;
|
|
18
19
|
status: 'open' | 'decided' | 'withdrawn'; refs?: string[];
|
|
19
20
|
resume?: { questionId: string; runId?: string };
|
|
21
|
+
/** Original pending question, including its newlines; SCQA fields are short summaries. */
|
|
22
|
+
pendingQuestion?: string;
|
|
20
23
|
/** DEC-TG — optional deadline (UTC). Cards remind the owner two hours before it. */
|
|
21
24
|
dueAt?: string;
|
|
22
25
|
decidedAt?: string; decidedBy?: DecisionActor; choice?: string; note?: string; versionAtDecision?: Versions;
|
|
23
26
|
withdrawnAt?: string; withdrawReason?: string;
|
|
24
27
|
history: Array<{ type: 'raised' | 'options-added' | 'decided' | 'withdrawn'; at?: string; by: string; version?: Versions; choice?: string; reason?: string }>;
|
|
25
28
|
}
|
|
26
|
-
export type RaiseInput = Pick<DecisionEntry, 'title' | 'category' | 'scqa' | 'options' | 'recommendation' | 'raisedBy' | 'refs' | 'dueAt' | 'resume'> & { raisedAt?: string };
|
|
29
|
+
export type RaiseInput = Pick<DecisionEntry, 'title' | 'category' | 'scqa' | 'options' | 'recommendation' | 'raisedBy' | 'refs' | 'dueAt' | 'resume' | 'pendingQuestion'> & { raisedAt?: string };
|
|
27
30
|
type Event = { type: 'raised'; entry: DecisionEntry } | { type: 'options-added'; id: string; at: string; options: DecisionOption[]; by: string } | { type: 'decided'; id: string; at?: string; by: DecisionActor; choice?: string; version?: Versions; note?: string } | { type: 'withdrawn'; id: string; at: string; reason: string; version: Versions };
|
|
28
31
|
export interface DecisionLedgerOptions extends VersionOptions { stateDir?: string; now?: () => Date; resolveVersion?: (at: string) => Versions; writeAnswer?: typeof writePendingQuestionAnswer }
|
|
29
32
|
|
|
@@ -38,7 +41,7 @@ export class DecisionAnswerDeliveryError extends Error {
|
|
|
38
41
|
}
|
|
39
42
|
}
|
|
40
43
|
const CATEGORIES: readonly string[] = ['secret', 'publish', 'money', 'security', 'scope', 'irreversible', 'other'];
|
|
41
|
-
const TRACKS: readonly string[] = ['S', 'T', 'F', 'O'];
|
|
44
|
+
const TRACKS: readonly string[] = ['S', 'T', 'F', 'O', 'OP', 'MK', 'TC', 'UX'];
|
|
42
45
|
|
|
43
46
|
function required(value: string, name: string): string {
|
|
44
47
|
if (typeof value !== 'string' || !value.trim()) throw new Error(`${name} is required`);
|
|
@@ -86,10 +89,12 @@ function validate(input: RaiseInput, historical = false): RaiseInput {
|
|
|
86
89
|
? { skipped: true as const, reason: safe(single(input.recommendation.reason, 'skip reason')) }
|
|
87
90
|
: { option: input.recommendation.option, why: safe(single(input.recommendation.why, 'recommendation why')) };
|
|
88
91
|
if ('option' in recommendation && !options.some(o => o.key === recommendation.option)) throw new Error('recommended option not found');
|
|
89
|
-
if (input.resume && !/^auq:[0-9a-z]+:[0-9a-z]{5}(?![\s\S])/.test(input.resume.questionId)) throw new Error('invalid resume questionId');
|
|
92
|
+
if (input.resume && !/^(?:auq:[0-9a-z]+:[0-9a-z]{5}|execution:[A-Za-z0-9_-]+:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?![\s\S])/.test(input.resume.questionId)) throw new Error('invalid resume questionId');
|
|
90
93
|
const resume = input.resume ? { questionId: input.resume.questionId,
|
|
91
94
|
...(input.resume.runId === undefined ? {} : { runId: single(input.resume.runId, 'resume runId') }) } : undefined;
|
|
95
|
+
if (input.pendingQuestion !== undefined) required(input.pendingQuestion, 'pending question');
|
|
92
96
|
return { ...input, title, scqa: { s, c, ...(q ? { q } : {}), ...(a ? { a } : {}) }, options, recommendation,
|
|
97
|
+
...(input.pendingQuestion === undefined ? {} : { pendingQuestion: safe(input.pendingQuestion) }),
|
|
93
98
|
...(resume ? { resume } : {}),
|
|
94
99
|
raisedBy: { agent: safe(single(input.raisedBy.agent, 'agent')), ...(input.raisedBy.track ? { track: input.raisedBy.track } : {}), ...(input.raisedBy.session ? { session: safe(single(input.raisedBy.session, 'session')) } : {}) },
|
|
95
100
|
...(input.refs ? { refs: input.refs.map(r => safe(single(r, 'ref'))) } : {}),
|
|
@@ -263,13 +268,16 @@ export class DecisionLedger {
|
|
|
263
268
|
if (!pending.ok) throw new Error(pending.error);
|
|
264
269
|
const target = pending.questions.find(item => item.id === questionId);
|
|
265
270
|
if (!target || target.questions.length !== 1 || !target.questions[0]?.id) throw new Error('pending question target not found or ambiguous');
|
|
271
|
+
if (questionId.startsWith('execution:') && (!runId || target.runId !== runId || !questionId.startsWith(`execution:${runId}:`))) throw new Error('pending question run differs from decision');
|
|
272
|
+
if (!questionId.startsWith('execution:') && runId !== undefined && target.runId !== undefined && target.runId !== runId) throw new Error('pending question run differs from decision');
|
|
273
|
+
if (target.expiresAt && Date.parse(target.expiresAt) <= this.now().getTime()) throw new Error('pending question expired');
|
|
266
274
|
const question = target.questions[0];
|
|
267
275
|
if (question.options.length !== entry.options.length || question.options.some((option, index) =>
|
|
268
276
|
entry.options[index]?.key !== String.fromCharCode(97 + index) || entry.options[index]?.label !== option.label)) {
|
|
269
277
|
throw new Error('pending question options differ from decision');
|
|
270
278
|
}
|
|
271
279
|
const answerKey = question.id;
|
|
272
|
-
const answer = { id: questionId, result: { answers: { [answerKey]: `${entry.choice}) ${label}` },
|
|
280
|
+
const answer = { id: questionId, result: { answers: { [answerKey]: questionId.startsWith('execution:') ? label : `${entry.choice}) ${label}` },
|
|
273
281
|
...(entry.note ? { otherText: { [answerKey]: entry.note } } : {}) } };
|
|
274
282
|
const existing = readPendingQuestionAnswer(questionId, deps);
|
|
275
283
|
if (!existing.ok) throw new Error('existing answer unreadable');
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
// ⏳ Mention parser → persona LLM dispatch wire
|
|
22
22
|
|
|
23
23
|
import { debug } from '../debug/log.js';
|
|
24
|
+
import { botAudienceFor, gateDiscordSchemas } from '../maturity/bot-command-maturity.js';
|
|
24
25
|
import type { DiscordBot } from '../discord.js';
|
|
25
26
|
import {
|
|
26
27
|
loadLayeredPersonaDirs,
|
|
@@ -204,7 +205,10 @@ export async function wireSprint21Runtime(opts: WireSprint21Opts): Promise<Sprin
|
|
|
204
205
|
// 6. Slash command registration
|
|
205
206
|
const cmdRest = makeCommandRest({ token: opts.token, fetchImpl: opts.fetchImpl });
|
|
206
207
|
async function registerSlashCommands(): Promise<number> {
|
|
207
|
-
const
|
|
208
|
+
const allSchemas = router.schemas();
|
|
209
|
+
const audience = botAudienceFor('discord');
|
|
210
|
+
const { schemas, hidden } = gateDiscordSchemas(allSchemas, audience);
|
|
211
|
+
debug.log('discord.command', 'menu-filtered', { total: allSchemas.length, shown: schemas.length - hidden, ...audience });
|
|
208
212
|
if (opts.devGuildId) {
|
|
209
213
|
const out = await cmdRest.bulkOverwriteGuild(opts.appId, opts.devGuildId, schemas);
|
|
210
214
|
log(`[sprint21-wire] registered ${out.length} slash commands to guild ${opts.devGuildId}`);
|
|
@@ -61,6 +61,9 @@ import { executionFooter } from './telegram-exec-footer.js';
|
|
|
61
61
|
import { debug } from './debug/log.js';
|
|
62
62
|
import { makeChunkProducer } from './session/streaming/chunk-producer.js';
|
|
63
63
|
import { getUserConfig } from './user-config.js';
|
|
64
|
+
import { detectCard, runCardFollowup, NotACardError } from './card-followup/core.js';
|
|
65
|
+
import { localOcrText } from './telegram-card-followup.js';
|
|
66
|
+
import type { runGraph } from './graph-runner/runner.js';
|
|
64
67
|
|
|
65
68
|
const SLASH_FOCUS_TURNS_DEFAULT = 8;
|
|
66
69
|
|
|
@@ -135,6 +138,7 @@ export interface DiscordSelfMessageDeps {
|
|
|
135
138
|
* (legacy). */
|
|
136
139
|
questionChannelFor?: (channelId: string) => import('./hitl/question.js').QuestionChannel;
|
|
137
140
|
log?: (msg: string) => void;
|
|
141
|
+
cardFollowupDeps?: { ocrText?: (path: string) => Promise<string | null>; runGraph?: typeof runGraph; rootDir?: () => string };
|
|
138
142
|
}
|
|
139
143
|
|
|
140
144
|
/** Compose the full discord self+interweave onMessage handler. */
|
|
@@ -352,6 +356,34 @@ export function buildDiscordSelfOnMessage(deps: DiscordSelfMessageDeps): DcMessa
|
|
|
352
356
|
// Voice text commands pass the guild gate for the voice adapter's
|
|
353
357
|
// sake — never route them into the LLM turn (legacy behavior).
|
|
354
358
|
if (/^\/voice-(join|leave|status)\b/.test(ctx.text.trim())) return undefined;
|
|
359
|
+
if (!ctx.text.trim() && ctx.attachments.length === 1 && ctx.attachments[0]!.contentType?.startsWith('image/')) {
|
|
360
|
+
const photo = ctx.attachments[0]!;
|
|
361
|
+
if (detectCard({ width: photo.width, height: photo.height, ocrText: null }).decision !== 'skip') {
|
|
362
|
+
const bot = deps.getBot();
|
|
363
|
+
if (bot) {
|
|
364
|
+
let imagePath: string;
|
|
365
|
+
let ocrText: string | null;
|
|
366
|
+
try {
|
|
367
|
+
imagePath = (await bot.downloadAttachment(photo)).localPath;
|
|
368
|
+
ocrText = await (deps.cardFollowupDeps?.ocrText ?? localOcrText)(imagePath);
|
|
369
|
+
} catch {
|
|
370
|
+
return '명함을 읽지 못했습니다';
|
|
371
|
+
}
|
|
372
|
+
if (detectCard({ width: photo.width, height: photo.height, ocrText }).decision === 'card') {
|
|
373
|
+
try {
|
|
374
|
+
const result = await runCardFollowup({ imagePath, ocrText,
|
|
375
|
+
...(deps.cardFollowupDeps?.runGraph ? { runGraph: deps.cardFollowupDeps.runGraph } : {}),
|
|
376
|
+
...(deps.cardFollowupDeps?.rootDir ? { rootDir: deps.cardFollowupDeps.rootDir() } : {}),
|
|
377
|
+
});
|
|
378
|
+
for (const reply of result.replies) await bot.sendMessage(ctx.channelId, reply);
|
|
379
|
+
return streamer ? '명함 정리를 완료했습니다.' : undefined;
|
|
380
|
+
} catch (error) {
|
|
381
|
+
if (!(error instanceof NotACardError)) return '명함을 읽지 못했습니다';
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
355
387
|
// S1 session commands (!sessions·!new·!attach) — before delegation
|
|
356
388
|
// and self-turn routing, mirroring telegram's command precedence.
|
|
357
389
|
const sessionReply = handleSessionCommand(ctx);
|
|
@@ -21,6 +21,7 @@ import { makeCommandRest } from './discord/slash-registry.js';
|
|
|
21
21
|
import { normalizeInteractionPayload } from './discord/slash-router.js';
|
|
22
22
|
import type { SlashCommandSchema } from './discord/slash-types.js';
|
|
23
23
|
import { debug } from './debug/log.js';
|
|
24
|
+
import { gateDiscordSchemas, readBotAudience } from './maturity/bot-command-maturity.js';
|
|
24
25
|
import { resolveChannelBotToken } from './channel-bot-token.js';
|
|
25
26
|
|
|
26
27
|
const REST_BASE = 'https://discord.com/api/v10';
|
|
@@ -121,8 +122,11 @@ export function buildDiscordSlashWire(deps: DiscordSlashWireDeps): DiscordSlashW
|
|
|
121
122
|
if (!app.id) { log('[slash] application id unresolved — skip'); return; }
|
|
122
123
|
const guilds = await (await fetchImpl(`${REST_BASE}/users/@me/guilds`, auth)).json() as Array<{ id: string }>;
|
|
123
124
|
const rest = makeCommandRest({ token, ...(deps.__fetchImpl ? { fetchImpl: deps.__fetchImpl } : {}) });
|
|
125
|
+
const audience = readBotAudience((deps.userConfig.raw?.discord as { commandAudience?: unknown } | undefined)?.commandAudience);
|
|
126
|
+
const { schemas, hidden } = gateDiscordSchemas(ELANOUS_SLASH_COMMANDS, audience);
|
|
127
|
+
debug.log('discord.command', 'menu-filtered', { total: ELANOUS_SLASH_COMMANDS.length, shown: schemas.length - hidden, ...audience });
|
|
124
128
|
for (const g of Array.isArray(guilds) ? guilds : []) {
|
|
125
|
-
const registered = await rest.bulkOverwriteGuild(app.id, g.id,
|
|
129
|
+
const registered = await rest.bulkOverwriteGuild(app.id, g.id, schemas);
|
|
126
130
|
log(`[slash] registered ${registered.length} commands in guild ${g.id}`);
|
|
127
131
|
}
|
|
128
132
|
}
|
package/src/discord.ts
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
import { markdownToTelegramHtml as _unusedMarkdownFn } from './telegram-format.js'; // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
24
24
|
import { debug } from './debug/log.js';
|
|
25
25
|
import { getUserConfig } from './user-config.js';
|
|
26
|
+
import { deliverSeatAnswers } from './seat-dispatch/seat-ask.js';
|
|
26
27
|
import { handleDiscordSeatWork, type DiscordSeatWorkDeps } from './intake-plane/discord-seat-work.js';
|
|
27
28
|
import { parseSeatAddress } from './seat-address/seat-address.js';
|
|
28
29
|
|
|
@@ -226,6 +227,7 @@ export class DiscordBot {
|
|
|
226
227
|
private ws: WebSocket | null = null;
|
|
227
228
|
private running = false;
|
|
228
229
|
private heartbeatTimer: ReturnType<typeof setInterval> | null = null;
|
|
230
|
+
private seatAskTimer: ReturnType<typeof setInterval> | null = null;
|
|
229
231
|
private lastHeartbeatAck = true;
|
|
230
232
|
private lastSeq: number | null = null;
|
|
231
233
|
|
|
@@ -246,7 +248,15 @@ export class DiscordBot {
|
|
|
246
248
|
this.onInteraction = opts.onInteraction ?? null;
|
|
247
249
|
this.onReaction = opts.onReaction ?? null;
|
|
248
250
|
this.onTriggerTap = opts.onTriggerTap ?? null;
|
|
249
|
-
this.seatWorkDeps = opts.seatWorkDeps
|
|
251
|
+
this.seatWorkDeps = { ...opts.seatWorkDeps, askDeps: {
|
|
252
|
+
...opts.seatWorkDeps?.askDeps,
|
|
253
|
+
channel: 'discord',
|
|
254
|
+
send: opts.seatWorkDeps?.askDeps?.send ?? (async (origin, text) => {
|
|
255
|
+
if (origin.channel !== 'discord') throw new Error('seat ask belongs to another surface');
|
|
256
|
+
const posted = await this.sendMessage(origin.threadId ?? origin.channelId, text);
|
|
257
|
+
if (!posted) throw new Error('Discord seat ask reply was not posted');
|
|
258
|
+
}),
|
|
259
|
+
} };
|
|
250
260
|
}
|
|
251
261
|
|
|
252
262
|
/** Send a raw payload on the gateway WebSocket. Voice adapter uses
|
|
@@ -523,8 +533,12 @@ export class DiscordBot {
|
|
|
523
533
|
async start(): Promise<void> {
|
|
524
534
|
this.running = true;
|
|
525
535
|
this.log(`discord bot starting (allowlist size ${this.allowedUsers.size})`);
|
|
536
|
+
this.seatAskTimer = setInterval(() => {
|
|
537
|
+
void deliverSeatAnswers(this.seatWorkDeps.askDeps!).catch((error) => this.log(`seat ask delivery failed: ${String(error)}`));
|
|
538
|
+
}, 10_000);
|
|
526
539
|
while (this.running) {
|
|
527
540
|
try {
|
|
541
|
+
await deliverSeatAnswers(this.seatWorkDeps.askDeps!);
|
|
528
542
|
await this.runConnection();
|
|
529
543
|
} catch (err: any) {
|
|
530
544
|
this.log(`gateway error: ${err?.message ?? String(err)}`);
|
|
@@ -538,6 +552,8 @@ export class DiscordBot {
|
|
|
538
552
|
|
|
539
553
|
stop(): void {
|
|
540
554
|
this.running = false;
|
|
555
|
+
if (this.seatAskTimer) clearInterval(this.seatAskTimer);
|
|
556
|
+
this.seatAskTimer = null;
|
|
541
557
|
if (this.ws) {
|
|
542
558
|
try { this.ws.close(1000, 'client stop'); } catch { /* ignore */ }
|
|
543
559
|
this.ws = null;
|
|
@@ -15,7 +15,7 @@ import { existsSync } from 'node:fs';
|
|
|
15
15
|
import { Database } from 'bun:sqlite';
|
|
16
16
|
import type { LLMToolSpec } from '../llm.js';
|
|
17
17
|
import { debug } from '../debug/log.js';
|
|
18
|
-
import { runRecall, type RecallSearch } from '../tool-runtime/self-cognition-runtimes.js';
|
|
18
|
+
import { runRecall, CONTEXT_NOW_SPEC, type RecallSearch } from '../tool-runtime/self-cognition-runtimes.js';
|
|
19
19
|
import type { ToolRuntimeContext } from '../tool-runtime/types.js';
|
|
20
20
|
import { SCHEDULE_MANAGE_SPEC, dispatchScheduleManage } from './schedule-manage-tool.js';
|
|
21
21
|
import { SESSION_MANAGE_SPEC, dispatchSessionQuery } from './session-query-tool.js';
|
|
@@ -114,6 +114,7 @@ const CORE_TOOL_HANDLERS: Record<string, (args: Record<string, unknown>, onParti
|
|
|
114
114
|
schedule_manage: dispatchScheduleManage,
|
|
115
115
|
session_manage: (args) => dispatchSessionQuery(args), // 대화 세션 검색·열람·목록·삭제(내용/ID/텔레그램)
|
|
116
116
|
memory_recall: dispatchMemoryRecall,
|
|
117
|
+
context_now: async (args) => (await import('../context-bus/context-now.js')).contextNow({ ...(typeof args.topic === 'string' ? { topic: args.topic } : {}) }),
|
|
117
118
|
fact_check: dispatchFactCheck, // 팩트체크 캐스케이드(내부 발송원장→외부 X/레딧/웹)·도메인 무관 코어
|
|
118
119
|
self_recall: dispatchSelfRecall, // self-awareness(elanous 구현 이력)·도메인 무관 코어
|
|
119
120
|
autopilot_missions: dispatchAutopilotMissions, // 오토파일럿 계보 조회(AL3)·도메인 무관 코어
|
|
@@ -141,7 +142,7 @@ const SELF_RECALL_BUDGET_SPEC: LLMToolSpec = {
|
|
|
141
142
|
},
|
|
142
143
|
},
|
|
143
144
|
};
|
|
144
|
-
export const CORE_TOOL_SPECS: LLMToolSpec[] = [SCHEDULE_MANAGE_SPEC, SESSION_MANAGE_SPEC, MEMORY_RECALL_SPEC, FACT_CHECK_SPEC, SELF_RECALL_BUDGET_SPEC, AUTOPILOT_MISSION_SPEC, OPS_STATUS_SPEC, SE_BUILD_SPEC, LOGS_QUERY_SPEC, MISSION_DECIDE_SPEC, COO_ADMIN_SPEC, RELEASE_STATUS_SPEC, RELEASE_CHANGE_SPEC, OPS_SEATS_SPEC, DECISIONS_PENDING_SPEC];
|
|
145
|
+
export const CORE_TOOL_SPECS: LLMToolSpec[] = [SCHEDULE_MANAGE_SPEC, SESSION_MANAGE_SPEC, MEMORY_RECALL_SPEC, FACT_CHECK_SPEC, SELF_RECALL_BUDGET_SPEC, CONTEXT_NOW_SPEC, AUTOPILOT_MISSION_SPEC, OPS_STATUS_SPEC, SE_BUILD_SPEC, LOGS_QUERY_SPEC, MISSION_DECIDE_SPEC, COO_ADMIN_SPEC, RELEASE_STATUS_SPEC, RELEASE_CHANGE_SPEC, OPS_SEATS_SPEC, DECISIONS_PENDING_SPEC];
|
|
145
146
|
|
|
146
147
|
export interface CoreTools {
|
|
147
148
|
specs: LLMToolSpec[];
|