elanous 0.2.17 → 0.2.19
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/J5H7BvqgSI8DUjtRRcA_S/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1157-cba0e8553d35a980.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{726.83532d69452ee24b.js → 1470.98a6ab61ccb4131c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/171-23a877ed11720de9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2336-e830c777eb6bce04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9247-269e4464cc4b491c.js → 2375-e061bb24cd2b5cde.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2415.ed6428ff334c7ce2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{211-9c9090c59e2c5907.js → 2977-e38442e86289f1d3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → 2ea96958.e8c7e112de50b067.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3094.67339318c7f72a3a.js +2 -0
- package/apps/pwa/out/_next/static/chunks/338-ceb956612dcfaa86.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3395-835e4ceaa6335ba4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +5 -0
- package/apps/pwa/out/_next/static/chunks/3441-be82e3595aef3a20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3689-89905039bf3e7257.js +1 -0
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3822-6f268bc26c6a84ac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 4323.c5dfb6f503304775.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4457-d7df81c90f9d0268.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4551-77dadae76f6cbace.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 4847.56f5bc454fbcc827.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4978.6fd93b974441e87f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5012-f746f6549b869f91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 6062-73e68343a9814f6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/62-5bfed1e23790b745.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6320-9bc8561fde416e07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/649-ca96d1c5d09e02b8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6726-85a7db59b288c53f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6735-33267c4630d0d963.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7633-141682015873beb6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{935.4ddaa99fc1d1126c.js → 7647.2fcd30d894d5ee30.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{f6231284-45726550aba08fca.js → 8046cadf-211ca3c0e00f2b72.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8067-143791231c99bd02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8430-a10cfba8ef282d4e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8870-9614a213b990b10b.js +25 -0
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9454-12c2f30dea62291c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/976-4a9b4ebdca7c739a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9989-15cdf568bafa9fc8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/ae787e4c-e5b1ef00b2dbceca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-deef5ee191830f14.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-b193da485f9a14b2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-b6e1a79df0e214f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-e84df4d907f703c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-a5fb9a5db89ae4ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-1499f481d7fc52d6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-c7cf753aeb648790.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-4118469e514e10fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-e968f7630654332a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-505915052f947022.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c2f962fb4a3b06c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7b5ed0bd8a589ec4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-cf8193250dd42dd4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-cf3f5dfa35dea8e9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-5b29d9b06ceadade.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a15e7fcc283e9ca7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-d2915e7b70ff3d0e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-b70cd005d9169e25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-2595f0eba29f57e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-c776322454156e36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-77bbd17f4435aa10.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-049689e611ecc936.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-85954a4fb09c44eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-e773e552e1068ee6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5633c4bfa7684b4a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d829b92bd01b4994.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-061c317fc771becf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a45ece8865ed4b6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-0be990618c0d56bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-bfea4865dc244b73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d6ba8e337741484.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-76a88b55d816482e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-bba1542df59f61ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-4185c95689bb372e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-b699e1a8d5d34b8b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-c225e338c31bf274.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-449353f70507ca1f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-90b889714102476d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f1ee7fbeb7f96ddc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-d59a95e1434dfaa0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-71491a23414d1a47.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-de7112bdb65fa4fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-feb4d0d88079660d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-f17d887b40dd6b1d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-8da77be2192bcd5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-72c3b9a5e9582b29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c3afe4c8d0c48c39.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-b9308f2d8a931531.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-6f35f9d892fa630b.js +1 -0
- package/apps/pwa/out/_next/static/css/{e99e3cff94ced78a.css → 599369d853c61df7.css} +1 -1
- package/apps/pwa/out/_next/static/css/85f53c6f35d11382.css +1 -0
- package/apps/pwa/out/_next/static/css/d3427996da11e480.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/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- 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/decisions/index.html +1 -0
- package/apps/pwa/out/decisions/index.txt +30 -0
- 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 +25 -24
- 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 -1
- package/apps/pwa/out/inside/index.txt +24 -23
- 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/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +28 -27
- 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 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- 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 -23
- 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 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/ops/guardian.yaml +26 -0
- package/graphs/ops/recipes.yaml +3 -0
- package/package.json +2 -1
- package/samples/workflows/templates/approval-gated-deploy.yaml +30 -0
- package/samples/workflows/templates/chat-driven-research.yaml +35 -0
- package/samples/workflows/templates/discord-listen-and-respond.yaml +29 -0
- package/samples/workflows/templates/http-poll-then-alert.yaml +30 -0
- package/samples/workflows/templates/manual-quickstart.yaml +21 -0
- package/samples/workflows/templates/scheduled-daily-digest.yaml +30 -0
- package/samples/workflows/templates/webhook-deploy-hook.yaml +27 -0
- package/scripts/ci-public-export-import-gate.ts +7 -2
- package/scripts/ci-typecheck-changed.ts +21 -6
- package/scripts/coord-channel-watch.sh +2 -2
- package/scripts/discord-seat-probe.ts +6 -3
- package/scripts/docs/generate-cli-anatomy.ts +162 -0
- package/scripts/goals/authoring-metrics.ts +73 -0
- package/scripts/landing-heal/must-fix-match.ts +7 -7
- package/scripts/landing-heal/run-mission.ts +3 -2
- package/scripts/lib/pch-regress-map.ts +23 -0
- package/scripts/morning-report.ts +18 -4
- package/scripts/pch-regress.ts +88 -0
- package/scripts/public-export-test-run.ts +37 -2
- package/scripts/release-loop/checklist-gate-node.ts +13 -11
- package/scripts/release-loop/cut-branch.ts +2 -1
- package/scripts/release-loop/cutoff.ts +4 -2
- package/scripts/release-loop/docs-land-node.ts +8 -1
- package/scripts/release-loop/docs-node.ts +1 -1
- package/scripts/release-loop/gate-diff.ts +18 -0
- package/scripts/release-loop/gate-node.ts +436 -59
- package/scripts/release-loop/gate-partial.ts +106 -0
- package/scripts/release-loop/gate-timing.ts +120 -0
- package/scripts/release-loop/node-verdict.ts +2 -1
- package/scripts/release-loop/npm-publish-node.ts +11 -7
- package/scripts/release-loop/ops-upgrade-node.ts +8 -1
- package/scripts/release-loop/preflight.ts +246 -0
- package/scripts/release-loop/publish-node.ts +8 -1
- package/scripts/release-loop/release-readiness.ts +11 -6
- package/scripts/release-loop/release-version.ts +48 -0
- package/scripts/release-loop/resume-release.ts +174 -0
- package/scripts/release-loop/shard-plan.ts +65 -0
- package/scripts/release-loop/unattended-release.ts +45 -7
- package/scripts/release-loop/version-node.ts +145 -40
- package/scripts/rhythm/daily.ts +25 -4
- package/scripts/skills/public-check.ts +62 -12
- package/scripts/test-deterministic.ts +51 -33
- package/scripts/test-diet/effectiveness.ts +62 -1
- package/scripts/test-diet/lib.ts +1 -1
- package/scripts/test-diet/node.ts +8 -1
- package/scripts/video/scene-table.ts +159 -0
- package/src/acp/core-turn-bridge.ts +39 -2
- package/src/agent-mission/review-loop.ts +4 -3
- package/src/agent-substrate/pr-comment-meta.ts +20 -0
- package/src/autopilot/build/llm-conflict-merge.ts +28 -8
- package/src/away/presence.ts +40 -0
- package/src/away/release-watch.ts +255 -0
- package/src/briefing/brief-items.ts +86 -17
- package/src/chat/index.ts +2 -1
- package/src/chat/short-question.ts +3 -40
- package/src/cli/autopilot-cli.ts +30 -11
- package/src/cli/away-cli.ts +68 -0
- package/src/cli/brief-cli.ts +36 -2
- package/src/cli/freeze-cli.ts +3 -2
- package/src/cli/guardian-cli.ts +49 -0
- package/src/cli/intake-cli.ts +85 -7
- package/src/cli/log-event-names.ts +1 -0
- package/src/cli/notify-cli.ts +75 -0
- package/src/cli/pod-cli.ts +5 -1
- package/src/cli/provider-cli.ts +12 -2
- package/src/cli/pty-drive-cli.ts +14 -3
- package/src/cli/release-cli.ts +128 -19
- package/src/cli/setup-cli.ts +31 -1
- package/src/cli/tasks-cli.ts +403 -4
- package/src/context-bus/condense.ts +19 -3
- package/src/context-bus/context-day.ts +77 -24
- package/src/context-bus/context-first.ts +33 -0
- package/src/context-bus/context-now-public.ts +1 -1
- package/src/context-bus/context-now-surfaces.ts +16 -6
- package/src/context-bus/context-now.ts +97 -3
- package/src/core-turn/short-question.ts +100 -0
- package/src/dashboard/dashboard-status-lines.ts +24 -4
- package/src/dashboard/index.ts +50 -5
- package/src/dashboard/input/slash-executor.ts +6 -2
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +63 -36
- package/src/dashboard/slash-runtime/decide-slash.ts +60 -0
- package/src/dashboard/slash-runtime/help-from-registry.ts +21 -8
- package/src/dashboard/slash-runtime/help-groups.ts +44 -0
- package/src/dashboard/slash-runtime/model-choices.ts +125 -0
- package/src/discord-self-message.ts +20 -2
- package/src/discord-slash-wire.ts +1 -0
- package/src/domains/guardian-tick.ts +138 -0
- package/src/domains/outbound-alert.ts +244 -40
- package/src/domains/outbound-log-probe.ts +16 -1
- package/src/domains/release-tool.ts +2 -2
- package/src/domains/schedule-registry.ts +23 -0
- package/src/domains/telegram-kind-route.ts +39 -0
- package/src/domains/watch-default-scheduler.ts +95 -0
- package/src/esc-abort-gate.ts +44 -0
- package/src/execution-loop/gates.ts +11 -2
- package/src/flow-loop/split.ts +8 -4
- package/src/git-fs/worktree.ts +23 -3
- package/src/graph-runner/runner.ts +25 -5
- package/src/harness/harness-cli-command.ts +12 -2
- package/src/harness/harness-queue.ts +388 -33
- package/src/harness/harness-salvage-cli.ts +78 -0
- package/src/harness/harness-worktree-add.ts +68 -0
- package/src/harness/helper-scan.ts +10 -3
- package/src/harness/ledger-write-guard.ts +6 -16
- package/src/hq/hq.ts +6 -1
- package/src/hq/seats.ts +369 -0
- package/src/index.ts +185 -18
- package/src/instance/test-write-guard-spy-first.fixture.ts +13 -0
- package/src/instance/test-write-guard.ts +200 -0
- package/src/intake-plane/adopt-gate.ts +49 -0
- package/src/intake-plane/check.ts +3 -0
- package/src/intake-plane/collect-github.ts +57 -25
- package/src/intake-plane/digest.ts +39 -15
- package/src/intake-plane/discord-seat-work.ts +8 -2
- package/src/intake-plane/harness-target.ts +4 -3
- package/src/intake-plane/intake-sources.ts +1 -0
- package/src/intake-plane/items.ts +1 -0
- package/src/intake-plane/requirement-funnel.ts +316 -0
- package/src/knowledge/know-find.ts +10 -1
- package/src/loops/budget.ts +36 -0
- package/src/loops/orchestrator/degradation.ts +57 -0
- package/src/loops/orchestrator/finish-rate.ts +106 -4
- package/src/loops/orchestrator/grid-place.ts +11 -0
- package/src/loops/orchestrator/tick.ts +450 -54
- package/src/maturity/feature-maturity.ts +8 -5
- package/src/maturity/tui-slash-maturity.ts +1 -0
- package/src/mss/logging/log-store.ts +3 -0
- package/src/nexus/api/decisions-route.ts +11 -1
- package/src/nexus/api/http-server.ts +16 -5
- package/src/nexus/api/loop-edges.ts +352 -23
- package/src/nexus/api/ops-api.ts +96 -28
- package/src/nexus/api/ops-seats-sources.ts +2 -2
- package/src/nexus/api/workflow-templates.ts +3 -0
- package/src/nexus/index.ts +7 -0
- package/src/oauth/codex.ts +38 -0
- package/src/onboarding/first-chat-gate.ts +29 -0
- package/src/release-loop/checklist.ts +106 -6
- package/src/release-loop/feature-store.ts +64 -16
- package/src/release-loop/landing-freeze.ts +6 -4
- package/src/release-loop/light-rc.ts +173 -0
- package/src/release-loop/placement.ts +64 -20
- package/src/release-loop/rubric.ts +136 -0
- package/src/seat-dispatch/seat-ask.ts +79 -16
- package/src/seat-loop/seat-loop.ts +12 -6
- package/src/self-dev/ask-launch-flow.ts +24 -3
- package/src/self-dev/ask-path-candidates.ts +68 -0
- package/src/self-dev/dev-cli.ts +36 -0
- package/src/self-dev/dev-pipeline.ts +4 -0
- package/src/self-dev/draft-triage-rules.ts +1 -1
- package/src/self-dev/orchestrate-cli.ts +22 -0
- package/src/self-dev/orchestrate.ts +1 -0
- package/src/self-dev/pr-preview.ts +179 -0
- package/src/self-dev/round-pr-supersede.ts +244 -0
- package/src/self-dev/run-supervisor.ts +14 -0
- package/src/self-dev/shard-run.ts +23 -7
- package/src/self-implement/follow-up-goals.ts +2 -2
- package/src/self-implement/gate-cli.ts +29 -8
- package/src/self-implement/gate-remote.ts +427 -0
- package/src/self-implement/goal-author-clarification.ts +88 -13
- package/src/self-implement/goal-author.ts +8 -3
- package/src/self-implement/goal-clarification-escalation.ts +2 -0
- package/src/self-implement/l8-merge-queue.ts +29 -5
- package/src/self-implement/orchestrator.ts +61 -13
- package/src/self-implement/prior-draft-findings.ts +4 -3
- package/src/self-implement/salvage-branches.ts +254 -0
- package/src/skills/skill-feedback.ts +76 -0
- package/src/task-agent/actions.ts +101 -7
- package/src/task-agent/board.ts +132 -0
- package/src/task-agent/card-evidence.ts +203 -0
- package/src/task-agent/completion-evidence.ts +126 -0
- package/src/task-agent/judge.ts +49 -5
- package/src/task-agent/live-moves.ts +176 -0
- package/src/task-agent/mission.ts +449 -0
- package/src/task-agent/shadow.ts +258 -0
- package/src/task-agent/task-hand.ts +337 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +64 -4
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +10 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +142 -13
- package/src/task-orchestrator/surfaces/pod-pool.ts +13 -5
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +88 -20
- package/src/telegram-away-command.ts +38 -0
- package/src/telegram-commands.ts +11 -0
- package/src/telegram-loops-command.ts +1 -1
- package/src/telegram-report-log-probe.ts +21 -0
- package/src/telegram-report.ts +27 -3
- package/src/telegram.ts +5 -20
- package/src/tui-client/dashboard-session.ts +1 -0
- package/src/user-config.ts +196 -4
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1307-aac7332576c4d6fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1844-9ec4b1d12f6e80eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1866-e7a6999f25548b30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1948.15f356b15a625597.js +0 -5
- package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
- package/apps/pwa/out/_next/static/chunks/224-798346143007ff65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2699-63b73fa4d3bcf6ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2957-96ffab3d521fb08f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4144-a0041c8dc3be57ac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4554-3565eea1f1495ba7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4614-21403aac730d4586.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5135-44008fe8b1f2aa41.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5233-bf28bd6bd7a32099.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5360-be1f1d8f9fcc9755.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5977-c952712c87a1f757.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5994-ae92c0de046ab9ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6158.9c0449a9a8d0064b.js +0 -2
- package/apps/pwa/out/_next/static/chunks/6877-fe94e76a5841ee9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7395-164e238f471b5d7b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7787-02a1c0b04e25e811.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8401-4ce1c42c8d89903f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8868-10a3a4440fb0ccd8.js +0 -25
- package/apps/pwa/out/_next/static/chunks/8949-ecb4128a0858b911.js +0 -1
- package/apps/pwa/out/_next/static/chunks/899-f41be85e8a680651.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9070.067c106528ec1ae6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/a9f2b54d-7865aba0f4d2ee49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-3143b07a817d1da9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-17ba086ef82d339b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-7eb661ff23af7da2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-6b8444914da74ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-6e5c3a867557298b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-7110f732f45bf944.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-9a41d65355fc25b9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-5e77cd1802567c89.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-41afec0b255ed2bb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-4187666132fc98c4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-09328d499162bae4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-29ff3a8f84f03b6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-80ec7401bc83f511.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ab93b240f687d69a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-fc7d86467291ae38.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-de43a186e5ba5683.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-8b08cafad27759c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-0e2d6985fb42cd2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-13e4108999f58d13.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e8296ee284aa1293.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-043a9111e74f6b24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-23a4601ceb7f452e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-1ed1324b1dc36754.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-10d958605a77b3bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-166745e51ac0c7b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-a04260b8ccc968d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-7a1d85e121065cc8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-1f50e3d4e13435f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-12916918988ac97e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d8a3347a9d0c3f4a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-a9117d2cd3093d36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-5a64cb5208c6a8fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-1407ec83ea64c1f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-1d824510df025d18.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-6e878ebbe1737d00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-7f49fe645d5132f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-81a4e7f8dbfe74cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-27d71f131acd9320.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-3ab59d19913b200e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-bf85b2f5bf077925.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-424659bacfb8cdd7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-ab32a8f522a60371.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-fc2df261f8a2c7df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-09461366af82ef13.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-5d4fef9ccd7d406b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ea90a8ac73ce2749.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-5c169757551134ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-539cde99554be20f.js +0 -1
- package/apps/pwa/out/_next/static/css/001d5fbaee388a25.css +0 -1
- package/apps/pwa/out/_next/static/yRA5ur6DcPl0YHSRheH2O/_buildManifest.js +0 -1
- /package/apps/pwa/out/_next/static/{yRA5ur6DcPl0YHSRheH2O → J5H7BvqgSI8DUjtRRcA_S}/_ssgManifest.js +0 -0
|
@@ -283,6 +283,8 @@ import { runRebindCommand } from '../../input-core/index.js';
|
|
|
283
283
|
import { resolveRepositoryDesignCheck } from '../../cli/repo-cli.js';
|
|
284
284
|
import { renderDesignCheckLines, type DesignCheckTone } from '../../design/design-check-render.js';
|
|
285
285
|
import { handleDesignPick } from './design-pick.js';
|
|
286
|
+
import { createDecideSlashHandler } from './decide-slash.js';
|
|
287
|
+
import type { DecisionLedger } from '../../decisions/decision-ledger.js';
|
|
286
288
|
import { listDesignDirections, parseDeclaredDirection } from '../../design/design-directions.js';
|
|
287
289
|
import {
|
|
288
290
|
dashboardDeltaHelpLines,
|
|
@@ -303,8 +305,6 @@ import {
|
|
|
303
305
|
rotateNextProvider, jumpToRotationEntry, rotationEntryLabel,
|
|
304
306
|
currentRotationIndex,
|
|
305
307
|
} from '../../user-config.js';
|
|
306
|
-
import type { LLMProviderName } from '../../user-config.js';
|
|
307
|
-
import { lookupLlmTierSpec } from '../../model-tier/index.js';
|
|
308
308
|
import { listProviders } from '../../llm.js';
|
|
309
309
|
import { enabledModels, loadCatalog } from '../../intelligence-map/model-catalog.js';
|
|
310
310
|
import { selfOrchestrateRuntime } from '../../self-dev/self-orchestrate-runtime.js';
|
|
@@ -343,6 +343,7 @@ import { terminalModalRouter } from '../input/terminal-modal-router.js';
|
|
|
343
343
|
import { termSize, stripAnsi } from '../../tui.js';
|
|
344
344
|
import { SLASH_COMMANDS } from '../../chat/index.js';
|
|
345
345
|
import { buildEssentialHelpLines } from './help-from-registry.js';
|
|
346
|
+
import { HUMAN_MODEL_WORDS, MODEL_CODE_NAMES, modelChangeLine, modelOverviewLines, resolveModelChoice } from './model-choices.js';
|
|
346
347
|
import type { FoldMode } from '../../log-entry.js';
|
|
347
348
|
import { resolveDashboardChatMainLogCommand } from '../input/chat-main-log-command.js';
|
|
348
349
|
import {
|
|
@@ -375,6 +376,7 @@ import { dirname as pathDirname, relative } from 'node:path';
|
|
|
375
376
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
376
377
|
import type { SurfaceUx } from '../../agent/surface-ux/types.js';
|
|
377
378
|
import type { AskUserQuestionRequest } from '../../ask-user-question/types.js';
|
|
379
|
+
import { DASHBOARD_CLARIFICATION_REQUEST } from '../../esc-abort-gate.js';
|
|
378
380
|
import type { GoalDocumentClarification } from '../../self-implement/goal-author-clarification.js';
|
|
379
381
|
import { renderReplayPreviewLines } from '../replay-preview.js';
|
|
380
382
|
import {
|
|
@@ -1295,6 +1297,7 @@ let selfOrchestrateSlashRuntime: SelfOrchestrateSlashRuntime = selfOrchestrateRu
|
|
|
1295
1297
|
export async function readDashboardAskClarification(
|
|
1296
1298
|
clarification: GoalDocumentClarification,
|
|
1297
1299
|
surfaceUx: Pick<SurfaceUx, 'question'> | undefined,
|
|
1300
|
+
notify?: (line: string) => void,
|
|
1298
1301
|
): Promise<string> {
|
|
1299
1302
|
if (!surfaceUx) return '';
|
|
1300
1303
|
const request: AskUserQuestionRequest = {
|
|
@@ -1309,10 +1312,13 @@ export async function readDashboardAskClarification(
|
|
|
1309
1312
|
includeOther: clarification.includeOther,
|
|
1310
1313
|
}],
|
|
1311
1314
|
};
|
|
1315
|
+
Object.defineProperty(request, DASHBOARD_CLARIFICATION_REQUEST, { value: true });
|
|
1312
1316
|
try {
|
|
1313
|
-
const
|
|
1314
|
-
if (!result || result.cancelled) return '';
|
|
1317
|
+
const pending = surfaceUx.question(request);
|
|
1315
1318
|
const id = clarification.questionId;
|
|
1319
|
+
notify?.('하니스가 묻는다 — 창에서 고르거나 Esc 로 답 없이 진행');
|
|
1320
|
+
const result = await pending;
|
|
1321
|
+
if (!result || result.cancelled) return '';
|
|
1316
1322
|
const answer = result.answers[id];
|
|
1317
1323
|
const selectedLabel = Array.isArray(answer) ? answer[0] : answer;
|
|
1318
1324
|
const optionIndex = clarification.options.findIndex((option) => option.label === selectedLabel);
|
|
@@ -1393,8 +1399,14 @@ async function fetchLoopsDaemonJson<T>(url: string, headers: Record<string, stri
|
|
|
1393
1399
|
}
|
|
1394
1400
|
}
|
|
1395
1401
|
|
|
1396
|
-
export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps): SlashCommandRegistry<DashboardSlashContext, DashboardSlashReturn> {
|
|
1402
|
+
export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps, decideLedger?: DecisionLedger): SlashCommandRegistry<DashboardSlashContext, DashboardSlashReturn> {
|
|
1397
1403
|
const registry = new SlashCommandRegistry<DashboardSlashContext, DashboardSlashReturn>();
|
|
1404
|
+
const decide = createDecideSlashHandler(decideLedger);
|
|
1405
|
+
registry.register(['decide', 'dec'], (args, ctx) => {
|
|
1406
|
+
// showDashboard in src/dashboard/index.ts dispatches into this registry.
|
|
1407
|
+
for (const line of decide(args).split('\n')) ctx.pushChatLine(line);
|
|
1408
|
+
ctx.setChatScrollOffset(-1);
|
|
1409
|
+
});
|
|
1398
1410
|
|
|
1399
1411
|
registry.register(['now'], (args, ctx) => {
|
|
1400
1412
|
for (const line of tuiNowSlash(args, nowDeps)) ctx.pushChatLine(line);
|
|
@@ -2436,7 +2448,11 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps): SlashComm
|
|
|
2436
2448
|
print: (line) => { for (const part of line.split('\n')) ctx.chatLines.push(` ${part}`); },
|
|
2437
2449
|
log: (event, data, level) => debug.log('dev-pipeline', event, { ...data, surface: 'tui-slash' }, { level }),
|
|
2438
2450
|
readLine: async () => '',
|
|
2439
|
-
readClarification: (clarification) => readDashboardAskClarification(clarification, ctx.surfaceUx)
|
|
2451
|
+
readClarification: (clarification) => readDashboardAskClarification(clarification, ctx.surfaceUx, (line) => {
|
|
2452
|
+
ctx.pushChatLine(line);
|
|
2453
|
+
ctx.setChatScrollOffset(-1);
|
|
2454
|
+
ctx.draw();
|
|
2455
|
+
}),
|
|
2440
2456
|
readFile: (file) => readFileSync(file, 'utf8'),
|
|
2441
2457
|
writeFile: (file, data) => writeFileSync(file, data, 'utf8'),
|
|
2442
2458
|
cwd: () => process.cwd(),
|
|
@@ -6161,46 +6177,57 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps): SlashComm
|
|
|
6161
6177
|
});
|
|
6162
6178
|
|
|
6163
6179
|
registry.register(['model', 'm'], (args, ctx) => {
|
|
6164
|
-
// /model —
|
|
6165
|
-
// /model
|
|
6180
|
+
// /model — 지금 모델(사람 낱말) + 고르기
|
|
6181
|
+
// /model 빠름|보통|깊음 — 지금 provider 의 budget·better·best 티어 (model-choices.ts)
|
|
6182
|
+
// /model <코드명> — codex·terra·sol·luna·opus·sonnet·grok (그대로 동작)
|
|
6166
6183
|
// effort(low/med/high)는 /reasoning. NL 미지원(대표 OK·slash-only).
|
|
6167
|
-
//
|
|
6168
|
-
// 명시 target 맵(id + provider) — catalog/prefix 추론 대신 확정값. 핵심:
|
|
6169
|
-
// Codex 계열(gpt-5.5/5.6-sol/terra/luna)은 gpt- prefix 라 자동 추론은
|
|
6170
|
-
// 'openai'(Chat Completions)로 오분류하나, 실제론 Responses API 필수라
|
|
6171
|
-
// provider=openai-codex 여야 한다(omni-crawl 2026-07-17 확인). GPT(openai·
|
|
6172
|
-
// Chat Completions)는 노출하지 않는다(대표 지시 — 혼란 방지·codex만).
|
|
6173
|
-
// 비-OpenAI fallback 은 claude(anthropic)·grok.
|
|
6174
|
-
const MODEL_TARGETS: Record<string, { model: string; provider: LLMProviderName }> = {
|
|
6175
|
-
codex: { model: 'gpt-5.5', provider: 'openai-codex' },
|
|
6176
|
-
// 🩸 2026-09-23 — GPT-6 에는 terra 가 없다(결정). 별칭은 남기되 codex 사다리 better 칸(sol 한 칸 아래 자리)을 가리킨다.
|
|
6177
|
-
terra: { model: lookupLlmTierSpec('openai-codex', 'better').model, provider: 'openai-codex' },
|
|
6178
|
-
sol: { model: lookupLlmTierSpec('openai-codex', 'best').model, provider: 'openai-codex' },
|
|
6179
|
-
luna: { model: lookupLlmTierSpec('openai-codex', 'budget').model, provider: 'openai-codex' },
|
|
6180
|
-
opus: { model: 'claude-opus-4-8', provider: 'anthropic' },
|
|
6181
|
-
sonnet: { model: 'claude-sonnet-5', provider: 'anthropic' },
|
|
6182
|
-
// ⭐ 티어 표를 따른다(옆 luna 와 같은 형태) — 하드코딩이면 표를 바꿔도 «안 따라온다»(2026-08-18 대표 4.6 재편)
|
|
6183
|
-
grok: { model: lookupLlmTierSpec('grok', 'best').model, provider: 'grok' },
|
|
6184
|
-
};
|
|
6185
6184
|
const arg = (args[0] ?? '').toLowerCase().trim();
|
|
6186
6185
|
const curCfg = getUserConfig();
|
|
6187
|
-
const
|
|
6188
|
-
const
|
|
6186
|
+
const curProvider = curCfg.llm.provider;
|
|
6187
|
+
const curModel = curCfg.llm.model;
|
|
6188
|
+
const curReasoning = effectiveReasoningLevel(curCfg.llm, curProvider, curModel);
|
|
6189
6189
|
if (!arg) {
|
|
6190
|
-
|
|
6191
|
-
ctx.chatLines.push(
|
|
6190
|
+
const [now, codes] = modelOverviewLines(curProvider, curModel, curReasoning);
|
|
6191
|
+
ctx.chatLines.push(now);
|
|
6192
|
+
ctx.chatLines.push(ctx.muted(codes));
|
|
6192
6193
|
ctx.setChatScrollOffset(-1);
|
|
6193
6194
|
return;
|
|
6194
6195
|
}
|
|
6195
|
-
const
|
|
6196
|
-
if (
|
|
6197
|
-
|
|
6196
|
+
const resolution = resolveModelChoice(arg, curProvider);
|
|
6197
|
+
if (resolution.kind === 'needs-provider') {
|
|
6198
|
+
debug.log('dashboard.model', 'human-word-needs-provider', { word: resolution.word, provider: curProvider });
|
|
6199
|
+
ctx.chatLines.push(ctx.muted(`/model ${resolution.word}: provider 가 auto 라 고를 사다리가 없다 — /provider 로 먼저 하나를 고르거나 코드명(${MODEL_CODE_NAMES.join('/')})을 쓴다.`));
|
|
6198
6200
|
ctx.setChatScrollOffset(-1);
|
|
6199
6201
|
return;
|
|
6200
6202
|
}
|
|
6201
|
-
|
|
6203
|
+
if (resolution.kind === 'unknown') {
|
|
6204
|
+
ctx.chatLines.push(ctx.muted(`/model: "${arg}" 를 모른다. ${HUMAN_MODEL_WORDS.join(' | ')} 또는 ${MODEL_CODE_NAMES.join('/')}.`));
|
|
6205
|
+
ctx.setChatScrollOffset(-1);
|
|
6206
|
+
return;
|
|
6207
|
+
}
|
|
6208
|
+
const { target } = resolution;
|
|
6209
|
+
// A human word picks a whole tier (model ⊕ reasoning, like /reasoning it clears the codex override);
|
|
6210
|
+
// a code name changes the model only.
|
|
6211
|
+
const tierReasoning = resolution.kind === 'human' ? resolution.reasoningLevel : undefined;
|
|
6212
|
+
saveUserConfig({
|
|
6213
|
+
...curCfg,
|
|
6214
|
+
llm: {
|
|
6215
|
+
...curCfg.llm,
|
|
6216
|
+
provider: target.provider,
|
|
6217
|
+
model: target.model,
|
|
6218
|
+
...(tierReasoning ? { reasoningLevel: tierReasoning, codexReasoning: undefined } : {}),
|
|
6219
|
+
},
|
|
6220
|
+
});
|
|
6202
6221
|
reloadUserConfig();
|
|
6203
|
-
|
|
6222
|
+
if (tierReasoning) ctx.refreshReasoningHudSegment();
|
|
6223
|
+
debug.log('dashboard.model', 'switch', {
|
|
6224
|
+
via: resolution.kind,
|
|
6225
|
+
choice: resolution.kind === 'human' ? resolution.tier : resolution.name,
|
|
6226
|
+
from: { provider: curProvider, model: curModel ?? null },
|
|
6227
|
+
to: target,
|
|
6228
|
+
reasoning: tierReasoning ?? null,
|
|
6229
|
+
});
|
|
6230
|
+
ctx.chatLines.push(modelChangeLine({ provider: curProvider, model: curModel, reasoning: curReasoning }, resolution));
|
|
6204
6231
|
ctx.chatLines.push(ctx.muted(' └─ 다음 턴부터 반영 · 실행 뱃지(#4442)로 확인'));
|
|
6205
6232
|
ctx.setChatScrollOffset(-1);
|
|
6206
6233
|
});
|
|
@@ -6453,7 +6480,7 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps): SlashComm
|
|
|
6453
6480
|
{ getStatusLines: ctx.getStatusLines ?? (() => []) },
|
|
6454
6481
|
);
|
|
6455
6482
|
if (!result) {
|
|
6456
|
-
ctx.chatLines.push(ctx.warning(' /status
|
|
6483
|
+
ctx.chatLines.push(ctx.warning(' /status 는 인자 없이 · 자세히는 /status --debug'));
|
|
6457
6484
|
ctx.setChatScrollOffset(-1);
|
|
6458
6485
|
return;
|
|
6459
6486
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { isIrreversible, renderCardText } from '../../decisions/decision-cards.js';
|
|
2
|
+
import { DecisionLedger, type DecisionEntry } from '../../decisions/decision-ledger.js';
|
|
3
|
+
|
|
4
|
+
function ageOf(entry: DecisionEntry, now: Date): string {
|
|
5
|
+
const raised = Date.parse(entry.raisedAt ?? entry.importedAt ?? '');
|
|
6
|
+
if (!Number.isFinite(raised)) return '나이 미상';
|
|
7
|
+
const minutes = Math.max(0, Math.floor((now.getTime() - raised) / 60_000));
|
|
8
|
+
if (minutes < 60) return `${minutes}분 전`;
|
|
9
|
+
if (minutes < 1440) return `${Math.floor(minutes / 60)}시간 전`;
|
|
10
|
+
return `${Math.floor(minutes / 1440)}일 전`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** One handler per dashboard registry: number-to-id mapping refreshes on list open or a successful answer. */
|
|
14
|
+
export function createDecideSlashHandler(ledger: DecisionLedger = new DecisionLedger(), now: () => Date = () => new Date()) {
|
|
15
|
+
let snapshot: DecisionEntry[] | undefined;
|
|
16
|
+
let pendingConfirm: { id: string; key: string } | undefined;
|
|
17
|
+
const openList = (): string => {
|
|
18
|
+
pendingConfirm = undefined;
|
|
19
|
+
snapshot = ledger.list({ status: 'open' });
|
|
20
|
+
if (!snapshot.length) return '열린 결정 없음';
|
|
21
|
+
return [...snapshot.map((entry, index) =>
|
|
22
|
+
`${index + 1}. ${entry.title} [${entry.options.map((option) => option.key).join('/')}] · ${entry.raisedBy.track ?? entry.raisedBy.agent} · ${ageOf(entry, now())}`),
|
|
23
|
+
'답하기: /decide <번호> <선택지 키>'].join('\n');
|
|
24
|
+
};
|
|
25
|
+
return (args: readonly string[]): string => {
|
|
26
|
+
if (!args.length) return openList();
|
|
27
|
+
|
|
28
|
+
const numbers = snapshot?.length ? `1~${snapshot.length}` : '없음 (/decide 로 목록 열기)';
|
|
29
|
+
const invalidNumber = `쓸 수 있는 번호: ${numbers}`;
|
|
30
|
+
const index = /^(?:[1-9]\d*)$/.test(args[0] ?? '') ? Number(args[0]) - 1 : -1;
|
|
31
|
+
const selected = snapshot?.[index];
|
|
32
|
+
if (!selected || !Number.isSafeInteger(index)) return invalidNumber;
|
|
33
|
+
const entry = ledger.list({ status: 'open' }).find((card) => card.id === selected.id);
|
|
34
|
+
if (!entry) return `이미 닫힌 결정입니다 (${args[0]}) — /decide 로 목록을 다시 여세요`;
|
|
35
|
+
if (args.length === 1) {
|
|
36
|
+
pendingConfirm = undefined;
|
|
37
|
+
return renderCardText(entry);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const key = args[1];
|
|
41
|
+
const option = entry.options.find((item) => item.key === key);
|
|
42
|
+
const keys = entry.options.length ? entry.options.map((item) => item.key).join(', ') : '없음';
|
|
43
|
+
if (!option || args.length > 3 || (args.length === 3 && args[2] !== '확인')) return `쓸 수 있는 선택지 키: ${keys}`;
|
|
44
|
+
if (isIrreversible(entry)) {
|
|
45
|
+
if (args[2] !== '확인' || pendingConfirm?.id !== entry.id || pendingConfirm.key !== key) {
|
|
46
|
+
pendingConfirm = { id: entry.id, key: option.key };
|
|
47
|
+
return `${renderCardText(entry, { confirm: option.key })}\n/decide ${args[0]} ${option.key} 확인`;
|
|
48
|
+
}
|
|
49
|
+
pendingConfirm = undefined;
|
|
50
|
+
}
|
|
51
|
+
let acknowledgement: string;
|
|
52
|
+
try {
|
|
53
|
+
const { delivery } = ledger.decideWithDelivery(entry.id, option.key, { kind: 'human' });
|
|
54
|
+
acknowledgement = `✓ ${entry.title} → ${option.label}${delivery && !delivery.ok ? ` · 런 답 전달 실패: decisions retry-answer ${entry.id}` : ''}`;
|
|
55
|
+
} catch {
|
|
56
|
+
return `결정을 기록하지 못했습니다 (${args[0]}) — /decide 로 목록을 다시 여세요`;
|
|
57
|
+
}
|
|
58
|
+
return `${acknowledgement}\n${openList()}`;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -2,6 +2,7 @@ import type { SlashCommand } from '../../chat/index.js';
|
|
|
2
2
|
import { readTuiSlashAudience, slashMaturity, slashVisibleFor } from '../../maturity/tui-slash-maturity.js';
|
|
3
3
|
import type { Role } from '../../maturity/feature-maturity.js';
|
|
4
4
|
import { visibleWidth } from '../../tui.js';
|
|
5
|
+
import { HELP_GROUP_ORDER, helpGroupFor } from './help-groups.js';
|
|
5
6
|
|
|
6
7
|
const ESSENTIAL_KEYS = [
|
|
7
8
|
['Enter', 'Send message'],
|
|
@@ -31,6 +32,11 @@ function fitLine(text: string, width: number): string {
|
|
|
31
32
|
return fitted + '…';
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
/** Head line for one help group (never starts with `/`, so it can't read as a command). */
|
|
36
|
+
export function helpGroupHeading(group: string): string {
|
|
37
|
+
return `▸ ${group}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
34
40
|
/** Plain content for the dashboard modal; registration, not the picker, decides which slash names exist. */
|
|
35
41
|
export function buildEssentialHelpLines({
|
|
36
42
|
names,
|
|
@@ -65,15 +71,22 @@ export function buildEssentialHelpLines({
|
|
|
65
71
|
? Math.max(1, Math.floor(width / (readableCellWidth + 1)))
|
|
66
72
|
: 1;
|
|
67
73
|
const columnWidth = Math.floor(width / columns);
|
|
74
|
+
// Task order (TUI-SLASH-DECIDE-NOW C): group head line, then that group's commands by name.
|
|
75
|
+
// Empty groups print no head; unmapped commands land in «그 밖», so none disappears.
|
|
68
76
|
const commandLines: string[] = [];
|
|
69
|
-
for (
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
for (const group of HELP_GROUP_ORDER) {
|
|
78
|
+
const members = entries.filter(({ name }) => helpGroupFor(name) === group);
|
|
79
|
+
if (members.length === 0) continue;
|
|
80
|
+
commandLines.push(fitLine(helpGroupHeading(group), width));
|
|
81
|
+
for (let start = 0; start < members.length; start += columns) {
|
|
82
|
+
const cells = members.slice(start, start + columns).map(({ label, description }) => {
|
|
83
|
+
const cellWidth = columnWidth - (columns > 1 ? 1 : 0);
|
|
84
|
+
return visibleWidth(`${label} `) > cellWidth ? '' : fitLine(`${label} ${description}`, cellWidth);
|
|
85
|
+
});
|
|
86
|
+
commandLines.push(cells.map((cell, index) =>
|
|
87
|
+
index === cells.length - 1 ? cell : cell + ' '.repeat(columnWidth - visibleWidth(cell)),
|
|
88
|
+
).join('').trimEnd());
|
|
89
|
+
}
|
|
77
90
|
}
|
|
78
91
|
const keyItems = ESSENTIAL_KEYS.map(([key, description]) => `${key} ${description}`);
|
|
79
92
|
const keyLines: string[] = [];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// TUI-SLASH-DECIDE-NOW C · 2026-10-07 — `/help` was one alphabetical block of ~70 commands (F3 · F14:
|
|
2
|
+
// `/model` sat three PgUps deep). Commands are now shown in task order: «시작», then the seven public
|
|
3
|
+
// verbs (내부 문서 `MAP-value-props-to-features` — same words), then «그 밖».
|
|
4
|
+
//
|
|
5
|
+
// The table maps a canonical slash name to its group. A registered command that is not in the table
|
|
6
|
+
// falls into «그 밖» automatically — grouping never hides a command (registration and maturity decide that).
|
|
7
|
+
|
|
8
|
+
export const HELP_START_GROUP = '시작';
|
|
9
|
+
export const HELP_OTHER_GROUP = '그 밖';
|
|
10
|
+
|
|
11
|
+
/** The seven public verbs, in the order the public map uses them. */
|
|
12
|
+
export const HELP_VERB_GROUPS = [
|
|
13
|
+
'지켜보기',
|
|
14
|
+
'조사하기',
|
|
15
|
+
'판단하기',
|
|
16
|
+
'만들기',
|
|
17
|
+
'실행하기',
|
|
18
|
+
'확인하기',
|
|
19
|
+
'기억하기',
|
|
20
|
+
] as const;
|
|
21
|
+
|
|
22
|
+
/** Render order: start, the seven verbs, then everything else. */
|
|
23
|
+
export const HELP_GROUP_ORDER: readonly string[] = [HELP_START_GROUP, ...HELP_VERB_GROUPS, HELP_OTHER_GROUP];
|
|
24
|
+
|
|
25
|
+
const GROUP_MEMBERS: Readonly<Record<string, readonly string[]>> = {
|
|
26
|
+
[HELP_START_GROUP]: ['help', 'status', 'model', 'clear', 'new', 'resume'],
|
|
27
|
+
지켜보기: ['now', 'loops', 'mission', 'log', 'term', 'surface', 'conv', 'capture', 'telegram', 'remaining', 'debug'],
|
|
28
|
+
조사하기: ['research', 'prompt', 'context'],
|
|
29
|
+
판단하기: ['decide', 'plan', 'wish', 'directive'],
|
|
30
|
+
만들기: ['harness', 'ad', 'export'],
|
|
31
|
+
실행하기: ['run-skill', 'claude', 'codex', 'gemini', 'acp', 'agent-room', 'showroom', 'relay', 'lane', 'reply', 'handoff', 'inject', 'control', 'qc', 'default'],
|
|
32
|
+
확인하기: ['delta', 'design', 'rewind'],
|
|
33
|
+
기억하기: ['memory', 'session', 'fork', 'resume-turn', 'history', 'persona'],
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** Canonical slash name → group. */
|
|
37
|
+
export const HELP_GROUP_BY_NAME: ReadonlyMap<string, string> = new Map(
|
|
38
|
+
Object.entries(GROUP_MEMBERS).flatMap(([group, names]) => names.map((name) => [name, group] as const)),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
/** Group for a canonical slash name; anything unmapped is «그 밖». */
|
|
42
|
+
export function helpGroupFor(name: string): string {
|
|
43
|
+
return HELP_GROUP_BY_NAME.get(name) ?? HELP_OTHER_GROUP;
|
|
44
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// TUI-SLASH-DECIDE-NOW C · 2026-10-07 — `/model` offered only code names (terra·sol·luna…), so a first
|
|
2
|
+
// user had nothing to choose by (F14). Three human words now sit in front: 빠름·보통·깊음 resolve to
|
|
3
|
+
// the CURRENT provider's budget·better·best tiers via `lookupLlmTierSpec` (no hard-coded model ids).
|
|
4
|
+
// The seven code names keep going to the same model and provider as before.
|
|
5
|
+
// A tier is «model ⊕ reasoning level» — on several ladders better and best share a model and differ only
|
|
6
|
+
// in reasoning (codex gpt-6-sol medium/high · opus medium/medium), so a human word also carries the tier's
|
|
7
|
+
// reasoning level; otherwise 보통 and 깊음 would be the same choice. Code names leave reasoning alone.
|
|
8
|
+
import type { LLMProviderName, ReasoningLevel } from '../../user-config.js';
|
|
9
|
+
import { lookupLlmTierSpec } from '../../model-tier/index.js';
|
|
10
|
+
import type { ModelTier } from '../../model-tier/types.js';
|
|
11
|
+
|
|
12
|
+
export interface ModelTarget {
|
|
13
|
+
readonly model: string;
|
|
14
|
+
readonly provider: LLMProviderName;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 명시 target 맵(id + provider) — catalog/prefix 추론 대신 확정값. 핵심:
|
|
18
|
+
// Codex 계열(gpt-5.5/5.6-sol/terra/luna)은 gpt- prefix 라 자동 추론은
|
|
19
|
+
// 'openai'(Chat Completions)로 오분류하나, 실제론 Responses API 필수라
|
|
20
|
+
// provider=openai-codex 여야 한다(omni-crawl 2026-07-17 확인). GPT(openai·
|
|
21
|
+
// Chat Completions)는 노출하지 않는다(대표 지시 — 혼란 방지·codex만).
|
|
22
|
+
// 비-OpenAI fallback 은 claude(anthropic)·grok.
|
|
23
|
+
export const MODEL_TARGETS: Readonly<Record<string, ModelTarget>> = {
|
|
24
|
+
codex: { model: 'gpt-5.5', provider: 'openai-codex' },
|
|
25
|
+
// 🩸 2026-09-23 — GPT-6 에는 terra 가 없다(결정). 별칭은 남기되 codex 사다리 better 칸(sol 한 칸 아래 자리)을 가리킨다.
|
|
26
|
+
terra: { model: lookupLlmTierSpec('openai-codex', 'better').model, provider: 'openai-codex' },
|
|
27
|
+
sol: { model: lookupLlmTierSpec('openai-codex', 'best').model, provider: 'openai-codex' },
|
|
28
|
+
luna: { model: lookupLlmTierSpec('openai-codex', 'budget').model, provider: 'openai-codex' },
|
|
29
|
+
opus: { model: 'claude-opus-4-8', provider: 'anthropic' },
|
|
30
|
+
sonnet: { model: 'claude-sonnet-5', provider: 'anthropic' },
|
|
31
|
+
// ⭐ 티어 표를 따른다(옆 luna 와 같은 형태) — 하드코딩이면 표를 바꿔도 «안 따라온다»(2026-08-18 대표 4.6 재편)
|
|
32
|
+
grok: { model: lookupLlmTierSpec('grok', 'best').model, provider: 'grok' },
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const MODEL_CODE_NAMES: readonly string[] = Object.keys(MODEL_TARGETS);
|
|
36
|
+
|
|
37
|
+
export interface HumanModelChoice {
|
|
38
|
+
readonly word: '빠름' | '보통' | '깊음';
|
|
39
|
+
readonly english: 'fast' | 'normal' | 'deep';
|
|
40
|
+
readonly tier: ModelTier;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const HUMAN_MODEL_CHOICES: readonly HumanModelChoice[] = [
|
|
44
|
+
{ word: '빠름', english: 'fast', tier: 'budget' },
|
|
45
|
+
{ word: '보통', english: 'normal', tier: 'better' },
|
|
46
|
+
{ word: '깊음', english: 'deep', tier: 'best' },
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
export const HUMAN_MODEL_WORDS: readonly string[] = HUMAN_MODEL_CHOICES.map(({ word }) => word);
|
|
50
|
+
|
|
51
|
+
export type ModelChoiceResolution =
|
|
52
|
+
| { readonly kind: 'human'; readonly word: HumanModelChoice['word']; readonly tier: ModelTier; readonly target: ModelTarget; readonly reasoningLevel?: ReasoningLevel }
|
|
53
|
+
| { readonly kind: 'code'; readonly name: string; readonly target: ModelTarget }
|
|
54
|
+
/** A human word while the provider is `auto` — there is no single ladder to read. */
|
|
55
|
+
| { readonly kind: 'needs-provider'; readonly word: HumanModelChoice['word'] }
|
|
56
|
+
| { readonly kind: 'unknown'; readonly arg: string };
|
|
57
|
+
|
|
58
|
+
/** Resolve a `/model` argument against the provider that is active right now. */
|
|
59
|
+
export function resolveModelChoice(rawArg: string, currentProvider: LLMProviderName): ModelChoiceResolution {
|
|
60
|
+
const arg = rawArg.trim().toLowerCase();
|
|
61
|
+
const human = HUMAN_MODEL_CHOICES.find(({ word, english }) => arg === word || arg === english);
|
|
62
|
+
if (human) {
|
|
63
|
+
if (currentProvider === 'auto') return { kind: 'needs-provider', word: human.word };
|
|
64
|
+
const spec = lookupLlmTierSpec(currentProvider, human.tier);
|
|
65
|
+
return {
|
|
66
|
+
kind: 'human', word: human.word, tier: human.tier, target: { model: spec.model, provider: currentProvider },
|
|
67
|
+
...(spec.reasoningLevel ? { reasoningLevel: spec.reasoningLevel } : {}),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const target = MODEL_TARGETS[arg];
|
|
71
|
+
if (target) return { kind: 'code', name: arg, target };
|
|
72
|
+
return { kind: 'unknown', arg };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The human word for (`model`, `reasoning`) on `provider`: an exact tier match first; without a reasoning
|
|
77
|
+
* level (or no exact match) only a model that names a single tier counts — an ambiguous model gets no word.
|
|
78
|
+
*/
|
|
79
|
+
export function humanWordForModel(
|
|
80
|
+
provider: LLMProviderName,
|
|
81
|
+
model: string | undefined | null,
|
|
82
|
+
reasoning?: ReasoningLevel,
|
|
83
|
+
): HumanModelChoice['word'] | undefined {
|
|
84
|
+
if (!model || provider === 'auto') return undefined;
|
|
85
|
+
const sameModel = HUMAN_MODEL_CHOICES.filter(({ tier }) => lookupLlmTierSpec(provider, tier).model === model);
|
|
86
|
+
if (reasoning) {
|
|
87
|
+
const exact = sameModel.find(({ tier }) => {
|
|
88
|
+
const level = lookupLlmTierSpec(provider, tier).reasoningLevel;
|
|
89
|
+
return level === undefined || level === reasoning;
|
|
90
|
+
});
|
|
91
|
+
if (exact) return exact.word;
|
|
92
|
+
}
|
|
93
|
+
return sameModel.length === 1 ? sameModel[0]!.word : undefined;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function currentLabel(provider: LLMProviderName, model: string | undefined | null, reasoning?: ReasoningLevel): string {
|
|
97
|
+
return humanWordForModel(provider, model, reasoning) ?? (model?.trim() || '기본 모델');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** `/model` with no argument: the current choice, then how to choose. The second line is muted by the caller. */
|
|
101
|
+
export function modelOverviewLines(
|
|
102
|
+
provider: LLMProviderName,
|
|
103
|
+
model: string | undefined | null,
|
|
104
|
+
reasoning?: ReasoningLevel,
|
|
105
|
+
): [string, string] {
|
|
106
|
+
const word = humanWordForModel(provider, model, reasoning);
|
|
107
|
+
const now = word ? `${word} (${model})` : (model?.trim() || '기본 모델');
|
|
108
|
+
return [
|
|
109
|
+
`지금: ${now} · 고르기: /model ${HUMAN_MODEL_WORDS.join(' | ')}`,
|
|
110
|
+
` 코드명도 됨: ${MODEL_CODE_NAMES.join(' · ')} · provider ${provider} · 생각 깊이: /reasoning`,
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Confirmation after a switch: «보통 → 깊음 (<model>)». */
|
|
115
|
+
export function modelChangeLine(
|
|
116
|
+
before: { provider: LLMProviderName; model: string | undefined | null; reasoning?: ReasoningLevel },
|
|
117
|
+
resolution: Extract<ModelChoiceResolution, { kind: 'human' | 'code' }>,
|
|
118
|
+
): string {
|
|
119
|
+
const after = resolution.kind === 'human'
|
|
120
|
+
? resolution.word
|
|
121
|
+
: humanWordForModel(resolution.target.provider, resolution.target.model) ?? resolution.name;
|
|
122
|
+
const reasoningNote = resolution.kind === 'human' && resolution.reasoningLevel ? ` · 생각 ${resolution.reasoningLevel}` : '';
|
|
123
|
+
const providerNote = resolution.target.provider === before.provider ? '' : ` · provider ${resolution.target.provider}`;
|
|
124
|
+
return `모델: ${currentLabel(before.provider, before.model, before.reasoning)} → ${after} (${resolution.target.model}${reasoningNote})${providerNote}`;
|
|
125
|
+
}
|
|
@@ -65,7 +65,9 @@ import { detectCard, runCardFollowup, NotACardError } from './card-followup/core
|
|
|
65
65
|
import { localOcrText } from './telegram-card-followup.js';
|
|
66
66
|
import type { runGraph } from './graph-runner/runner.js';
|
|
67
67
|
import { readSlashContextNow, renderTelegramNow } from './context-bus/context-now-surfaces.js';
|
|
68
|
-
import type
|
|
68
|
+
import { contextNow, type ContextNowDeps } from './context-bus/context-now.js';
|
|
69
|
+
import { createContextFirstGate, renderContextFirst } from './context-bus/context-first.js';
|
|
70
|
+
import { telegramLoopsStatus, type LoopsSources } from './telegram-loops-command.js';
|
|
69
71
|
import { botUnavailableSlashReply, deriveTuiSlashAvailability, type TuiSlashAvailability } from './maturity/tui-slash-availability.js';
|
|
70
72
|
|
|
71
73
|
const SLASH_FOCUS_TURNS_DEFAULT = 8;
|
|
@@ -143,6 +145,9 @@ export interface DiscordSelfMessageDeps {
|
|
|
143
145
|
log?: (msg: string) => void;
|
|
144
146
|
cardFollowupDeps?: { ocrText?: (path: string) => Promise<string | null>; runGraph?: typeof runGraph; rootDir?: () => string };
|
|
145
147
|
nowDeps?: ContextNowDeps;
|
|
148
|
+
/** Override the clock for the context-first gate in isolated message-path tests. */
|
|
149
|
+
contextFirstNow?: () => number;
|
|
150
|
+
loopsSources?: LoopsSources;
|
|
146
151
|
/** Override the TUI slash projection for isolated message-path tests. */
|
|
147
152
|
tuiSlashAvailability?: readonly TuiSlashAvailability[];
|
|
148
153
|
}
|
|
@@ -151,6 +156,15 @@ export interface DiscordSelfMessageDeps {
|
|
|
151
156
|
export function buildDiscordSelfOnMessage(deps: DiscordSelfMessageDeps): DcMessageHandler {
|
|
152
157
|
const log = deps.log ?? ((): void => {});
|
|
153
158
|
const cfg = deps.userConfig;
|
|
159
|
+
const contextFirstGate = createContextFirstGate({ now: deps.contextFirstNow ?? Date.now });
|
|
160
|
+
const maybeSendContextFirst = async (channelId: string): Promise<void> => {
|
|
161
|
+
if (!contextFirstGate.take(channelId) || cfg.discord?.contextFirst === false) return;
|
|
162
|
+
try {
|
|
163
|
+
await deps.getBot()?.sendMessage(channelId, renderContextFirst(contextNow, deps.nowDeps, renderTelegramNow));
|
|
164
|
+
} catch (err) {
|
|
165
|
+
log(`discord context-first failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
154
168
|
// C2+ (2026-07-12 dogfood): 디스코드 첨부는 메시지 단위라 "사진 먼저,
|
|
155
169
|
// !cdx 명령은 다음 메시지" 패턴에서 위임 턴이 빈손이 된다. 채널별로
|
|
156
170
|
// 마지막 첨부를 기억해 두고, 첨부 없는 위임 명령이 2분 내 같은
|
|
@@ -359,6 +373,7 @@ export function buildDiscordSelfOnMessage(deps: DiscordSelfMessageDeps): DcMessa
|
|
|
359
373
|
|
|
360
374
|
return async (ctx, streamer) => {
|
|
361
375
|
if (deps.channelScope && ctx.channelId !== deps.channelScope) return undefined;
|
|
376
|
+
contextFirstGate.note(ctx.channelId);
|
|
362
377
|
// Voice text commands pass the guild gate for the voice adapter's
|
|
363
378
|
// sake — never route them into the LLM turn (legacy behavior).
|
|
364
379
|
if (/^\/voice-(join|leave|status)\b/.test(ctx.text.trim())) return undefined;
|
|
@@ -367,6 +382,8 @@ export function buildDiscordSelfOnMessage(deps: DiscordSelfMessageDeps): DcMessa
|
|
|
367
382
|
const args = nowCommand[1]?.trim().split(/\s+/).filter(Boolean) ?? [];
|
|
368
383
|
return renderTelegramNow(readSlashContextNow(args, deps.nowDeps));
|
|
369
384
|
}
|
|
385
|
+
if (/^[/!]loops$/.test(ctx.text.trim())) return telegramLoopsStatus([], deps.loopsSources);
|
|
386
|
+
if (/^[/!]loops\s+\S/.test(ctx.text.trim())) return telegramLoopsStatus(['extra'], deps.loopsSources);
|
|
370
387
|
if (!ctx.text.trim() && ctx.attachments.length === 1 && ctx.attachments[0]!.contentType?.startsWith('image/')) {
|
|
371
388
|
const photo = ctx.attachments[0]!;
|
|
372
389
|
if (detectCard({ width: photo.width, height: photo.height, ocrText: null }).decision !== 'skip') {
|
|
@@ -408,6 +425,8 @@ export function buildDiscordSelfOnMessage(deps: DiscordSelfMessageDeps): DcMessa
|
|
|
408
425
|
const unavailable = botUnavailableSlashReply(entry, 'discord');
|
|
409
426
|
if (unavailable) return unavailable;
|
|
410
427
|
}
|
|
428
|
+
const cmd = parseDiscordAcpCommand(ctx.text);
|
|
429
|
+
if (!cmd && !/^[!/]/.test(ctx.text.trim())) await maybeSendContextFirst(ctx.channelId);
|
|
411
430
|
log(`◀ ${ctx.userName ?? ctx.userId}: ${ctx.text.slice(0, 80)}${ctx.attachments.length ? ` (+첨부 ${ctx.attachments.length})` : ''}`);
|
|
412
431
|
debug.log('discord.self.turn', 'inbound', { channelId: ctx.channelId, chars: ctx.text.length, attachments: ctx.attachments.length });
|
|
413
432
|
// C2+ — 첨부 기억(사진만 먼저 올리는 패턴 지원). 명령 여부와 무관.
|
|
@@ -416,7 +435,6 @@ export function buildDiscordSelfOnMessage(deps: DiscordSelfMessageDeps): DcMessa
|
|
|
416
435
|
const delegationKey = delegationChatKey('dc', ctx.channelId);
|
|
417
436
|
|
|
418
437
|
// 1) Explicit text commands — /cc·/cdx·/gem delegate, /brain exits.
|
|
419
|
-
const cmd = parseDiscordAcpCommand(ctx.text);
|
|
420
438
|
if (cmd?.kind === 'brain') {
|
|
421
439
|
clearActiveDelegation(delegationKey);
|
|
422
440
|
return '🧠 브레인 모드로 복귀했습니다 (active delegation 해제).';
|
|
@@ -48,6 +48,7 @@ export const ELANOUS_SLASH_COMMANDS: readonly SlashCommandSchema[] = [
|
|
|
48
48
|
{ name: 'now', description: '지금 판·칸·결정·자리·최근 맥락 보기', options: [
|
|
49
49
|
{ name: 'topic', description: '좁혀 볼 주제 (선택)', type: 3, required: false },
|
|
50
50
|
] },
|
|
51
|
+
{ name: 'loops', description: '루프·크론 현황 (늦음·실패 먼저)' },
|
|
51
52
|
{ name: 'sessions', description: '바인딩된 세션 목록' },
|
|
52
53
|
{ name: 'new', description: '새 세션으로 시작 (이전 대화 보존)' },
|
|
53
54
|
{ name: 'attach', description: '이 채널을 다른 세션에 연결', options: [
|