elanous 0.2.18 → 0.2.20
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/chunks/{1307-30dff22c9e1f3073.js → 1307-77fad80cf54477c6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1612-f60c0c93ec773f81.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2116-6429c188eb846ab8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/224-e7be8f762fe74986.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2489-ff55a35b202c0f94.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2549-89c518a4c8ed4d00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3857-995ea9f5ef33d71e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5755-ea7ed88eb956f47b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5977-94ed6f78e9814b2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7748-6e51bfe927019f5c.js +25 -0
- package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9247-c1753a059e7bac08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/a9f2b54d-33c0689b70ed8cf3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/{page-d92f7ee3994e84c7.js → page-c855c24de7db74fe.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/{page-4733c967b56a4277.js → page-85b316bb4235980b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/board/{page-d22fd849cc22f104.js → page-9b2b26a33cb2cd42.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-bb742f995c6769e7.js → page-c9955fde67b1bcb5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/{page-02b073a2ac793b83.js → page-7a852956c74015a3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c5a5c621be0e04ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/{page-8a9b3594bc23289b.js → page-4ba4abe096b6c2a8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-575d4a8b4f7becb2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/{page-308111abadf35670.js → page-f5d56ff5f45ad164.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-2260e9eef0357421.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/{page-5d97b2901e0d1ea6.js → page-7c058069c5e7fa63.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-dc5da0b8a2edb8a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/{page-8c3d8e63ae2e1c98.js → page-466bf0ee16ad1432.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/field/{page-9b72a07d424701c6.js → page-a23bc71713bcc08f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ed4a6f799f005d09.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/{page-a572f58cd3ca5864.js → page-9cd565005b93aca6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-55f0f40c6db95f15.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/{page-be5ea965a07fbc41.js → page-474cb5888ea0e8f3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-35bfec2e631d3eae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/{page-fa244bd146a00ae8.js → page-9ca21f9ad3208a61.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-44d56d6391965a6a.js → page-f9ccb1b1adbea14d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-83a700d4c754d802.js → page-ec102c9b8b691e37.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/{not-found-7b3170f374f77b9d.js → not-found-a9c2cfa8dda922a5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-6da35144878feb6d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-f6055495e9ed7ea8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-25204694fa9984a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-a60e035f151d84d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-189c587f36874538.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-c56634bde705a65d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/{page-1467047104141297.js → page-db03ae3589a81c9e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-4a6463b97f0ad94f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/{page-102310930791197a.js → page-75bffecc9aa1004e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a8d2fe0c669e0de4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/{page-6ed0b73bae8351d8.js → page-31d5b875760bb62d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c26fa10aac6c21c4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/{page-43336055451f6e37.js → page-68793c6e10331d66.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/share/{page-3cc47dca0922ab9a.js → page-46d5201d2207a511.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/{page-a77ee355a2304ff0.js → page-d81c07a7b4f618ae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/{page-b17cd46cf0e9b8cf.js → page-be1c4e8697f22360.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-cf0a4b4abead71ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-a4717e2c4bf7a28f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/{page-7bf54c9bb9274af8.js → page-0fd895fab9b62c1b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8b6c1454a8e8f306.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-c6e4364d9de8f717.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-0acc8e198f7b0dfb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/{page-134da468538baf48.js → page-34882c84f84021c5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-0506a1e0e4bdb2f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{webpack-c2782b330447ffb6.js → webpack-c260571513bf43c2.js} +1 -1
- package/apps/pwa/out/_next/static/css/{e99e3cff94ced78a.css → 599369d853c61df7.css} +1 -1
- package/apps/pwa/out/_next/static/css/c23d959d3ee15e57.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 +14 -14
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +14 -14
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +14 -14
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +14 -14
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +14 -14
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +14 -14
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +14 -14
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +14 -14
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +14 -14
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +14 -14
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +14 -14
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +16 -15
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +14 -14
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +14 -14
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +14 -14
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +16 -15
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +14 -14
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +14 -14
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +24 -23
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +14 -14
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +14 -14
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +14 -14
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +14 -14
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +14 -14
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +14 -14
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +14 -14
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +14 -14
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +15 -15
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +14 -14
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +14 -14
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +14 -14
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +14 -14
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +14 -14
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +14 -14
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +14 -14
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +14 -14
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +14 -14
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +14 -14
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +14 -14
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +14 -14
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +14 -14
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +14 -14
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +14 -14
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +14 -14
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +14 -14
- package/graphs/demo/editor-recipes.yaml +22 -0
- package/graphs/ops/guardian.yaml +26 -0
- package/graphs/ops/recipes.yaml +3 -0
- package/graphs/retro/daily.yaml +25 -0
- package/graphs/retro/recipes.yaml +24 -0
- package/package.json +1 -1
- package/scripts/ask-marker-check.ts +3 -1
- package/scripts/coord-channel-watch.sh +2 -2
- package/scripts/discord-seat-probe.ts +3 -1
- package/scripts/land-global-checks.ts +89 -0
- package/scripts/lib/pch-regress-map.ts +24 -0
- package/scripts/morning-report.ts +18 -4
- package/scripts/pch-regress.ts +88 -0
- package/scripts/release-loop/gate-diff.ts +18 -0
- package/scripts/release-loop/gate-node.ts +628 -65
- package/scripts/release-loop/gate-partial.ts +106 -0
- package/scripts/release-loop/gate-timing.ts +229 -0
- package/scripts/release-loop/preflight.ts +6 -4
- package/scripts/release-loop/publish-window.ts +141 -0
- package/scripts/release-loop/release-docs.ts +1 -4
- package/scripts/release-loop/release-universe.ts +38 -0
- package/scripts/release-loop/resume-release.ts +67 -5
- package/scripts/release-loop/shard-plan.ts +65 -0
- package/scripts/release-loop/unattended-release.ts +12 -2
- package/scripts/release-story/draft.ts +5 -1
- package/scripts/retro/shadow-compare.ts +71 -0
- package/scripts/rhythm/daily.ts +6 -1
- package/scripts/video/scene-table.ts +159 -0
- package/src/acp/core-turn-bridge.ts +39 -2
- package/src/agent-mission/driver.ts +34 -6
- package/src/autopilot/build/llm-conflict-merge.ts +132 -7
- package/src/autopilot/build/merge-intent.ts +135 -7
- package/src/away/presence.ts +40 -0
- package/src/away/release-watch.ts +272 -0
- package/src/chat/index.ts +2 -1
- package/src/chat/short-question.ts +3 -40
- package/src/cli/away-cli.ts +68 -0
- package/src/cli/config-drift.ts +513 -0
- package/src/cli/guardian-cli.ts +49 -0
- package/src/cli/intake-cli.ts +13 -7
- package/src/cli/log-event-names.ts +5 -0
- package/src/cli/pod-cli.ts +5 -1
- package/src/cli/pr-cli.ts +20 -0
- package/src/cli/pty-drive-cli.ts +14 -3
- package/src/cli/release-cli.ts +52 -12
- package/src/cli/retro-cli.ts +78 -0
- package/src/cli/setup-cli.ts +31 -1
- package/src/cli/tasks-cli.ts +193 -14
- 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 +68 -40
- package/src/dashboard/slash-runtime/decide-slash.ts +60 -0
- package/src/dashboard/slash-runtime/help-from-registry.ts +62 -23
- package/src/dashboard/slash-runtime/help-groups.ts +44 -0
- package/src/dashboard/slash-runtime/model-choices.ts +125 -0
- package/src/domains/guardian-tick.ts +138 -0
- package/src/domains/outbound-alert.ts +44 -13
- package/src/domains/outbound-log-probe.ts +6 -1
- 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/graph-runner/graph-run-api.ts +205 -0
- package/src/graph-runner/runner.ts +36 -6
- package/src/harness/harness-cli-command.ts +420 -51
- package/src/harness/harness-queue.ts +315 -25
- package/src/harness/harness-salvage-cli.ts +140 -0
- package/src/harness/harness-worktree-add.ts +68 -0
- package/src/harness/ledger-write-guard.ts +6 -16
- package/src/hq/fence-outcomes.ts +63 -0
- package/src/hq/fence-wrapper.ts +33 -0
- package/src/hq/hq.ts +17 -2
- package/src/index.ts +118 -6
- 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/digest.ts +39 -15
- 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/loops/orchestrator/degradation.ts +57 -0
- package/src/loops/orchestrator/finish-rate.ts +33 -3
- package/src/loops/orchestrator/tick.ts +166 -45
- package/src/maturity/feature-maturity.ts +6 -4
- package/src/maturity/tui-slash-maturity.ts +1 -0
- package/src/mss/logging/log-store.ts +3 -0
- package/src/nexus/api/graph-kinds.ts +10 -4
- package/src/nexus/api/graphs-api.ts +178 -6
- package/src/nexus/api/http-server.ts +54 -8
- package/src/nexus/api/loop-edges.ts +292 -17
- package/src/nexus/api/ops-api.ts +112 -29
- package/src/nexus/api/ops-board-route.ts +48 -0
- package/src/nexus/index.ts +7 -0
- package/src/onboarding/entry-hints.ts +5 -0
- package/src/onboarding.ts +24 -6
- package/src/release-loop/checklist.ts +2 -0
- package/src/release-loop/feature-store.ts +68 -18
- package/src/release-loop/gate-shards.ts +158 -0
- package/src/release-loop/light-rc.ts +173 -0
- package/src/release-loop/placement.ts +51 -17
- package/src/release-loop/release-schedule.ts +6 -2
- package/src/release-loop/rubric.ts +57 -1
- package/src/retro/daily.ts +372 -0
- package/src/seat-loop/op-decide.ts +173 -0
- package/src/seat-loop/seat-loop.ts +60 -3
- package/src/seat-loop/seat-report.ts +58 -3
- package/src/self-dev/ask-launch-flow.ts +5 -4
- package/src/self-dev/ask-launch-io.ts +49 -1
- package/src/self-dev/ask-path-candidates.ts +40 -2
- package/src/self-dev/dev-cli.ts +36 -0
- package/src/self-dev/draft-sweep.ts +371 -16
- package/src/self-dev/draft-triage-rules.ts +19 -4
- package/src/self-dev/orchestrate.ts +1 -0
- package/src/self-dev/pr-preview.ts +247 -0
- package/src/self-dev/shard-run.ts +23 -7
- package/src/self-implement/blocked-draft-policy.ts +101 -0
- package/src/self-implement/execution-clarification.ts +11 -0
- package/src/self-implement/gate-cli.ts +29 -8
- package/src/self-implement/gate-env-retry.ts +83 -0
- package/src/self-implement/goal-author-clarification.ts +88 -13
- package/src/self-implement/goal-clarification-escalation.ts +2 -0
- package/src/self-implement/orchestrator.ts +220 -6
- package/src/self-implement/run-stop.ts +123 -0
- package/src/self-implement/run-ttl.ts +258 -0
- package/src/self-implement/salvage-branches.ts +254 -0
- package/src/self-implement/salvage-retention.ts +123 -0
- package/src/self-implement/seams.ts +4 -0
- package/src/self-implement/self-implement-cli.ts +2 -0
- package/src/self-implement/sibling-resync.ts +223 -0
- package/src/self-implement/stop-autoheal.ts +204 -0
- package/src/task-agent/actions.ts +63 -2
- package/src/task-agent/board.ts +132 -0
- package/src/task-agent/card-evidence.ts +292 -0
- package/src/task-agent/completion-evidence.ts +126 -0
- package/src/task-agent/judge.ts +25 -0
- package/src/task-agent/live-moves.ts +276 -0
- package/src/task-agent/mission.ts +33 -7
- package/src/task-agent/shadow.ts +192 -15
- package/src/task-agent/task-hand.ts +124 -17
- package/src/task-orchestrator/surfaces/pod-command-job.ts +82 -8
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +4 -0
- package/src/task-orchestrator/surfaces/pod-install-slots.ts +89 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +233 -21
- package/src/task-orchestrator/surfaces/pod-pool.ts +155 -34
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +21 -5
- package/src/telegram-away-command.ts +38 -0
- package/src/telegram-commands.ts +52 -0
- package/src/telegram-report-log-probe.ts +21 -0
- package/src/telegram-report.ts +27 -3
- package/src/testing/real-cli-spawn.ts +106 -0
- package/src/tui-client/dashboard-session.ts +1 -0
- package/src/user-config.ts +190 -5
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/224-798346143007ff65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3857-4f936cdb30322aa6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4144-a0041c8dc3be57ac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4554-5761612531d0146b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5977-a11f37254196b659.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5994-ae92c0de046ab9ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8401-8615a660c84cdb03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8868-10a3a4440fb0ccd8.js +0 -25
- package/apps/pwa/out/_next/static/chunks/9247-269e4464cc4b491c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/a9f2b54d-7865aba0f4d2ee49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-60c3da708f9a0ccc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-a0eb02638b1e6f31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-6eaf7bac37830c21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-c39554c321576982.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-bd5d586429167fea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-59b7834d497c2255.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-c130b63862437814.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-5f23d0c66a3b4793.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-a3c58f5c72a5f3f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a2c4625596f8d69c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-0e9099531d239f11.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-e8e1ecaea7cd71d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-a1b7ffed710a93e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-2da6f9b8a38c6978.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-f331e38fefc00393.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-44d5f767491692bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-61553851aa606146.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-a1f585e154e61c59.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-5150ef17b5383a57.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b9d8ce70792c1672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-a5a3de231f2cc7d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31ac4afa2dcd915c.js +0 -1
- package/apps/pwa/out/_next/static/css/7fa358fec7da7c47.css +0 -1
- /package/apps/pwa/out/_next/static/{P6YTVgzuZz5oTZhY4Din_ → Bam1YziK2iH9bN4K0utGk}/_buildManifest.js +0 -0
- /package/apps/pwa/out/_next/static/{P6YTVgzuZz5oTZhY4Din_ → Bam1YziK2iH9bN4K0utGk}/_ssgManifest.js +0 -0
|
@@ -16,25 +16,45 @@ export interface DashboardStatusLinesInput {
|
|
|
16
16
|
readonly acp: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/** Detail block marker — everything from the blank line before it on is shown only with `/status --debug`. */
|
|
20
|
+
export const DASHBOARD_STATUS_DETAIL_HEADING = '자세히';
|
|
21
|
+
|
|
22
|
+
// F5 (TUI-COMFORT) — «연결: 데몬 모름 안 붙음» read as broken. Say what is true in plain words.
|
|
23
|
+
function connectionLine(address: string | null, connected: boolean): string {
|
|
24
|
+
if (address) return `연결: 데몬 ${address} ${connected ? '붙음' : '안 붙음'}`;
|
|
25
|
+
return connected ? '연결: 데몬 붙음' : '연결: 혼자 돎(데몬 없음)';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* `/status` default view: the three human lines (⊕ the seats line) only. Internal fields
|
|
30
|
+
* (`surface`·`acp`·`chatOnly`…) stay behind `/status --debug`. Lines without a detail block pass through.
|
|
31
|
+
*/
|
|
32
|
+
export function dashboardStatusSummaryLines(lines: readonly string[]): string[] {
|
|
33
|
+
const detail = lines.indexOf(DASHBOARD_STATUS_DETAIL_HEADING);
|
|
34
|
+
if (detail < 0) return [...lines];
|
|
35
|
+
const end = detail > 0 && lines[detail - 1] === '' ? detail - 1 : detail;
|
|
36
|
+
return [...lines.slice(0, end), ' 자세히: /status --debug'];
|
|
37
|
+
}
|
|
38
|
+
|
|
19
39
|
export function buildDashboardStatusLines(input: DashboardStatusLinesInput): string[] {
|
|
20
40
|
const known = (value?: string | null): string => value?.trim() || '모름';
|
|
21
41
|
// A remote URL can contain credentials or query parameters. Neither belongs in /status.
|
|
22
|
-
let address =
|
|
42
|
+
let address: string | null = null;
|
|
23
43
|
if (input.daemonAddress?.trim()) {
|
|
24
44
|
try {
|
|
25
45
|
const url = new URL(input.daemonAddress);
|
|
26
46
|
address = `${url.protocol}//${url.host}`;
|
|
27
47
|
} catch {
|
|
28
|
-
address =
|
|
48
|
+
address = null;
|
|
29
49
|
}
|
|
30
50
|
}
|
|
31
51
|
return [
|
|
32
52
|
`모델: ${known(input.provider)}/${known(input.model)} (${known(input.reasoning)})`,
|
|
33
|
-
|
|
53
|
+
connectionLine(address, input.daemonConnected),
|
|
34
54
|
`계정: ${input.accountName?.trim() === 'default' ? '기본' : known(input.accountName)}`,
|
|
35
55
|
...(input.seatsNow ? [input.seatsNow] : []),
|
|
36
56
|
'',
|
|
37
|
-
|
|
57
|
+
DASHBOARD_STATUS_DETAIL_HEADING,
|
|
38
58
|
...input.sessionSurfaceLines.map(line => ` ${line}`),
|
|
39
59
|
` view: ${input.view}`,
|
|
40
60
|
` focus: ${input.focus}`,
|
package/src/dashboard/index.ts
CHANGED
|
@@ -1323,7 +1323,7 @@ import {
|
|
|
1323
1323
|
AGENT_ACTIVITY_SEGMENT_KEY,
|
|
1324
1324
|
PULSE_HALF_PERIOD_MS,
|
|
1325
1325
|
} from '../agent-activity-hud.js';
|
|
1326
|
-
import { createEscAbortGate, routeStreamingEscapeKey } from '../esc-abort-gate.js';
|
|
1326
|
+
import { DASHBOARD_CLARIFICATION_REQUEST, consumeStreamingTopModalEscape, createEscAbortGate, createHarnessEscHint, routeStreamingEscapeKey } from '../esc-abort-gate.js';
|
|
1327
1327
|
import { createViEditor, type ViEditorHandle } from '../vi-editor.js';
|
|
1328
1328
|
import { launchEditor, canLaunchEditor } from '../editor-launcher.js';
|
|
1329
1329
|
import { createSshPickerModal } from '../ssh/ssh-picker-modal.js';
|
|
@@ -6700,6 +6700,7 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
6700
6700
|
* this function is invoked.
|
|
6701
6701
|
*/
|
|
6702
6702
|
const escAbortToolState = createEscAbortToolState();
|
|
6703
|
+
let clarificationModalId: string | null = null;
|
|
6703
6704
|
|
|
6704
6705
|
const attachChatStreamingKeys = (abortCtrl: AbortController): () => void => {
|
|
6705
6706
|
const chatLinesStartIndex = chatLines.length;
|
|
@@ -6710,24 +6711,31 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
6710
6711
|
// work is running, pop a confirmation modal before tearing down
|
|
6711
6712
|
// the stream — the running count is visible in the HUD (T3-B1)
|
|
6712
6713
|
// so the user can make an informed call.
|
|
6714
|
+
let abortGateModalId: string | null = null;
|
|
6715
|
+
const showHarnessEscHint = createHarnessEscHint((line) => pushChatLine(line));
|
|
6713
6716
|
const escGate = createEscAbortGate({
|
|
6714
6717
|
abortCtrl,
|
|
6715
6718
|
getRunningCount: () => getEscAbortRunningCount(escAbortToolState),
|
|
6716
6719
|
mountModal: (surface) => {
|
|
6717
6720
|
attachSurfaceToWorkspace(surface, currentWorkspaceOwnerId());
|
|
6721
|
+
abortGateModalId = surface.id;
|
|
6718
6722
|
const h = display.pushModal(surface);
|
|
6719
|
-
return () => { try { h.dispose(); } catch { /* ignore */ } };
|
|
6723
|
+
return () => { abortGateModalId = null; try { h.dispose(); } catch { /* ignore */ } };
|
|
6720
6724
|
},
|
|
6721
6725
|
getViewport: () => termSize(),
|
|
6722
6726
|
requestRedraw: () => draw(),
|
|
6723
6727
|
getTheme: () => currentThemeTokens(),
|
|
6724
6728
|
getWaitingTargetNames: () => getEscAbortWaitingToolNames(escAbortToolState),
|
|
6725
6729
|
onAbortPending: ({ targets }) => {
|
|
6726
|
-
|
|
6730
|
+
if (!showHarnessEscHint(targets)) {
|
|
6731
|
+
pushChatLine(` ⏳ 중단 요청됨 — ${formatEscAbortWaitingTargets(targets)} 종료를 기다리는 중입니다.`);
|
|
6732
|
+
}
|
|
6727
6733
|
chatScrollOffset = -1;
|
|
6728
6734
|
},
|
|
6729
6735
|
onAbortRepeat: ({ repeat, targets }) => {
|
|
6730
|
-
|
|
6736
|
+
if (!showHarnessEscHint(targets)) {
|
|
6737
|
+
pushChatLine(` ⏳ ESC 재시도 ${repeat}회 — ${formatEscAbortWaitingTargets(targets)} 종료를 기다리는 중입니다.`);
|
|
6738
|
+
}
|
|
6731
6739
|
chatScrollOffset = -1;
|
|
6732
6740
|
},
|
|
6733
6741
|
// ⭐⭐⭐ 턴을 멈추기 «전»에 살아남을 자식을 백그라운드 라우팅으로 넘긴다(`R4a` · 2026-08-19).
|
|
@@ -7183,6 +7191,28 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
7183
7191
|
};
|
|
7184
7192
|
return (await inputCoreRouteInputEventAsync(ev, ctx)) === 'consumed';
|
|
7185
7193
|
},
|
|
7194
|
+
() => {
|
|
7195
|
+
const modal = topModalSurface({ focusStack: display.modalStack(), surfaceAt: id => display.surface(id) });
|
|
7196
|
+
if (modal?.windowRole === 'companion') return false;
|
|
7197
|
+
const askHandle = approvalModalRouter.currentKind() === 'askUser' ? approvalModalRouter.current() : null;
|
|
7198
|
+
const topModalId = () => topModalSurface({ focusStack: display.modalStack(), surfaceAt: id => display.surface(id) })?.id ?? null;
|
|
7199
|
+
return consumeStreamingTopModalEscape({
|
|
7200
|
+
modal,
|
|
7201
|
+
abortGateModalId,
|
|
7202
|
+
event: toDashboardKeyEvent(key),
|
|
7203
|
+
question: askHandle ? {
|
|
7204
|
+
id: askHandle.surface.id,
|
|
7205
|
+
dispose: (cancelled) => askHandle.dispose(cancelled),
|
|
7206
|
+
isClarification: askHandle.surface.id === clarificationModalId,
|
|
7207
|
+
} : undefined,
|
|
7208
|
+
onClarificationClosed: () => {
|
|
7209
|
+
pushChatLine('되묻기 창을 닫았다 — 답 없이 진행한다');
|
|
7210
|
+
chatScrollOffset = -1;
|
|
7211
|
+
},
|
|
7212
|
+
topModalId,
|
|
7213
|
+
redraw: draw,
|
|
7214
|
+
});
|
|
7215
|
+
},
|
|
7186
7216
|
);
|
|
7187
7217
|
if (streamingEscapeConsumed) return;
|
|
7188
7218
|
if (routeStreamingApprovalModalKey(key)) return;
|
|
@@ -17649,11 +17679,26 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
|
|
|
17649
17679
|
// it via setExitInputLoop, or exit showDashboard via
|
|
17650
17680
|
// { return: DashboardAction }.
|
|
17651
17681
|
const dashboardSlashSurfaceUx = resolveDashboardSlashSurfaceUx();
|
|
17682
|
+
const clarificationSurfaceUx = dashboardSlashSurfaceUx ? {
|
|
17683
|
+
question: (request: Parameters<typeof dashboardSlashSurfaceUx.question>[0]) => {
|
|
17684
|
+
const pending = dashboardSlashSurfaceUx.question(request);
|
|
17685
|
+
if ((request as typeof request & { [DASHBOARD_CLARIFICATION_REQUEST]?: boolean })[DASHBOARD_CLARIFICATION_REQUEST]) {
|
|
17686
|
+
const handle = approvalModalRouter.current();
|
|
17687
|
+
if (approvalModalRouter.currentKind() === 'askUser' && handle) {
|
|
17688
|
+
clarificationModalId = handle.surface.id;
|
|
17689
|
+
void handle.promise.finally(() => {
|
|
17690
|
+
if (clarificationModalId === handle.surface.id) clarificationModalId = null;
|
|
17691
|
+
});
|
|
17692
|
+
}
|
|
17693
|
+
}
|
|
17694
|
+
return pending;
|
|
17695
|
+
},
|
|
17696
|
+
} : undefined;
|
|
17652
17697
|
const slashCtx: DashboardSlashContext = {
|
|
17653
17698
|
ad: { run: (args) => dispatchDashboardAdSlash(adSlashRuntime, [...args], () => { draw(); }) },
|
|
17654
17699
|
chatLines,
|
|
17655
17700
|
getStatusLines: getDashboardStatusLines,
|
|
17656
|
-
...(
|
|
17701
|
+
...(clarificationSurfaceUx ? { surfaceUx: clarificationSurfaceUx } : {}),
|
|
17657
17702
|
attachmentRowMap,
|
|
17658
17703
|
pushDebugLine,
|
|
17659
17704
|
pushChatLine: (line) => { chatLines.push(line); },
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SlashExecuteRequest, SlashExecuteResult } from '../../skills/tools/dashboard-slash.js';
|
|
2
2
|
import type { PaneFocus } from '../../workspace-types.js';
|
|
3
|
+
import { dashboardStatusSummaryLines } from '../dashboard-status-lines.js';
|
|
3
4
|
|
|
4
5
|
export interface ImmediateDashboardSlashDeps {
|
|
5
6
|
getStatusLines: () => string[];
|
|
@@ -17,12 +18,15 @@ export function executeImmediateDashboardSlash(
|
|
|
17
18
|
req: SlashExecuteRequest,
|
|
18
19
|
deps: ImmediateDashboardSlashDeps,
|
|
19
20
|
): SlashExecuteResult | null {
|
|
20
|
-
|
|
21
|
+
// `/status` = human lines only · `/status --debug` = with the internal detail block (TUI-SLASH-DECIDE-NOW C).
|
|
22
|
+
if ((req.name === 'status' || req.name === 'st')
|
|
23
|
+
&& (req.args.length === 0 || (req.args.length === 1 && req.args[0] === '--debug'))) {
|
|
24
|
+
const lines = deps.getStatusLines();
|
|
21
25
|
return {
|
|
22
26
|
ok: true,
|
|
23
27
|
name: req.name,
|
|
24
28
|
args: req.args,
|
|
25
|
-
logLines:
|
|
29
|
+
logLines: req.args.length === 0 ? dashboardStatusSummaryLines(lines) : lines,
|
|
26
30
|
};
|
|
27
31
|
}
|
|
28
32
|
if ((req.name === 'surface' || req.name === 'surf') && req.args.length >= 1) {
|
|
@@ -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);
|
|
@@ -1493,15 +1505,16 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps): SlashComm
|
|
|
1493
1505
|
|
|
1494
1506
|
registry.register(['help', '?'], (_args, ctx) => {
|
|
1495
1507
|
const { cols, rows } = termSize();
|
|
1508
|
+
// The transient modal paints only height - 2 content rows and does not scroll.
|
|
1509
|
+
// The builder adds columns to fit that budget; only when it still overflows, use the scrollable chat log.
|
|
1510
|
+
const minHeight = Math.min(6, Math.max(3, rows - 2));
|
|
1511
|
+
const modalContentRows = Math.max(minHeight, Math.min(rows - 4, Math.floor(rows * 0.7))) - 2;
|
|
1496
1512
|
const lines = buildEssentialHelpLines({
|
|
1497
1513
|
names: registry.names(),
|
|
1498
1514
|
descriptions: SLASH_COMMANDS,
|
|
1499
1515
|
width: Math.max(1, Math.floor(cols * 0.7) - 2),
|
|
1516
|
+
maxRows: modalContentRows,
|
|
1500
1517
|
});
|
|
1501
|
-
// The transient modal paints only height - 2 content rows and does not scroll.
|
|
1502
|
-
// When the catalog outgrows it, use the scrollable chat log instead of hiding keys.
|
|
1503
|
-
const minHeight = Math.min(6, Math.max(3, rows - 2));
|
|
1504
|
-
const modalContentRows = Math.max(minHeight, Math.min(rows - 4, Math.floor(rows * 0.7))) - 2;
|
|
1505
1518
|
if (ctx.showHelpModal && lines.length <= modalContentRows) {
|
|
1506
1519
|
ctx.showHelpModal({ title: 'Dashboard help', lines });
|
|
1507
1520
|
} else {
|
|
@@ -2436,7 +2449,11 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps): SlashComm
|
|
|
2436
2449
|
print: (line) => { for (const part of line.split('\n')) ctx.chatLines.push(` ${part}`); },
|
|
2437
2450
|
log: (event, data, level) => debug.log('dev-pipeline', event, { ...data, surface: 'tui-slash' }, { level }),
|
|
2438
2451
|
readLine: async () => '',
|
|
2439
|
-
readClarification: (clarification) => readDashboardAskClarification(clarification, ctx.surfaceUx)
|
|
2452
|
+
readClarification: (clarification) => readDashboardAskClarification(clarification, ctx.surfaceUx, (line) => {
|
|
2453
|
+
ctx.pushChatLine(line);
|
|
2454
|
+
ctx.setChatScrollOffset(-1);
|
|
2455
|
+
ctx.draw();
|
|
2456
|
+
}),
|
|
2440
2457
|
readFile: (file) => readFileSync(file, 'utf8'),
|
|
2441
2458
|
writeFile: (file, data) => writeFileSync(file, data, 'utf8'),
|
|
2442
2459
|
cwd: () => process.cwd(),
|
|
@@ -6161,46 +6178,57 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps): SlashComm
|
|
|
6161
6178
|
});
|
|
6162
6179
|
|
|
6163
6180
|
registry.register(['model', 'm'], (args, ctx) => {
|
|
6164
|
-
// /model —
|
|
6165
|
-
// /model
|
|
6181
|
+
// /model — 지금 모델(사람 낱말) + 고르기
|
|
6182
|
+
// /model 빠름|보통|깊음 — 지금 provider 의 budget·better·best 티어 (model-choices.ts)
|
|
6183
|
+
// /model <코드명> — codex·terra·sol·luna·opus·sonnet·grok (그대로 동작)
|
|
6166
6184
|
// 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
6185
|
const arg = (args[0] ?? '').toLowerCase().trim();
|
|
6186
6186
|
const curCfg = getUserConfig();
|
|
6187
|
-
const
|
|
6188
|
-
const
|
|
6187
|
+
const curProvider = curCfg.llm.provider;
|
|
6188
|
+
const curModel = curCfg.llm.model;
|
|
6189
|
+
const curReasoning = effectiveReasoningLevel(curCfg.llm, curProvider, curModel);
|
|
6189
6190
|
if (!arg) {
|
|
6190
|
-
|
|
6191
|
-
ctx.chatLines.push(
|
|
6191
|
+
const [now, codes] = modelOverviewLines(curProvider, curModel, curReasoning);
|
|
6192
|
+
ctx.chatLines.push(now);
|
|
6193
|
+
ctx.chatLines.push(ctx.muted(codes));
|
|
6192
6194
|
ctx.setChatScrollOffset(-1);
|
|
6193
6195
|
return;
|
|
6194
6196
|
}
|
|
6195
|
-
const
|
|
6196
|
-
if (
|
|
6197
|
-
|
|
6197
|
+
const resolution = resolveModelChoice(arg, curProvider);
|
|
6198
|
+
if (resolution.kind === 'needs-provider') {
|
|
6199
|
+
debug.log('dashboard.model', 'human-word-needs-provider', { word: resolution.word, provider: curProvider });
|
|
6200
|
+
ctx.chatLines.push(ctx.muted(`/model ${resolution.word}: provider 가 auto 라 고를 사다리가 없다 — /provider 로 먼저 하나를 고르거나 코드명(${MODEL_CODE_NAMES.join('/')})을 쓴다.`));
|
|
6198
6201
|
ctx.setChatScrollOffset(-1);
|
|
6199
6202
|
return;
|
|
6200
6203
|
}
|
|
6201
|
-
|
|
6204
|
+
if (resolution.kind === 'unknown') {
|
|
6205
|
+
ctx.chatLines.push(ctx.muted(`/model: "${arg}" 를 모른다. ${HUMAN_MODEL_WORDS.join(' | ')} 또는 ${MODEL_CODE_NAMES.join('/')}.`));
|
|
6206
|
+
ctx.setChatScrollOffset(-1);
|
|
6207
|
+
return;
|
|
6208
|
+
}
|
|
6209
|
+
const { target } = resolution;
|
|
6210
|
+
// A human word picks a whole tier (model ⊕ reasoning, like /reasoning it clears the codex override);
|
|
6211
|
+
// a code name changes the model only.
|
|
6212
|
+
const tierReasoning = resolution.kind === 'human' ? resolution.reasoningLevel : undefined;
|
|
6213
|
+
saveUserConfig({
|
|
6214
|
+
...curCfg,
|
|
6215
|
+
llm: {
|
|
6216
|
+
...curCfg.llm,
|
|
6217
|
+
provider: target.provider,
|
|
6218
|
+
model: target.model,
|
|
6219
|
+
...(tierReasoning ? { reasoningLevel: tierReasoning, codexReasoning: undefined } : {}),
|
|
6220
|
+
},
|
|
6221
|
+
});
|
|
6202
6222
|
reloadUserConfig();
|
|
6203
|
-
|
|
6223
|
+
if (tierReasoning) ctx.refreshReasoningHudSegment();
|
|
6224
|
+
debug.log('dashboard.model', 'switch', {
|
|
6225
|
+
via: resolution.kind,
|
|
6226
|
+
choice: resolution.kind === 'human' ? resolution.tier : resolution.name,
|
|
6227
|
+
from: { provider: curProvider, model: curModel ?? null },
|
|
6228
|
+
to: target,
|
|
6229
|
+
reasoning: tierReasoning ?? null,
|
|
6230
|
+
});
|
|
6231
|
+
ctx.chatLines.push(modelChangeLine({ provider: curProvider, model: curModel, reasoning: curReasoning }, resolution));
|
|
6204
6232
|
ctx.chatLines.push(ctx.muted(' └─ 다음 턴부터 반영 · 실행 뱃지(#4442)로 확인'));
|
|
6205
6233
|
ctx.setChatScrollOffset(-1);
|
|
6206
6234
|
});
|
|
@@ -6453,7 +6481,7 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps): SlashComm
|
|
|
6453
6481
|
{ getStatusLines: ctx.getStatusLines ?? (() => []) },
|
|
6454
6482
|
);
|
|
6455
6483
|
if (!result) {
|
|
6456
|
-
ctx.chatLines.push(ctx.warning(' /status
|
|
6484
|
+
ctx.chatLines.push(ctx.warning(' /status 는 인자 없이 · 자세히는 /status --debug'));
|
|
6457
6485
|
ctx.setChatScrollOffset(-1);
|
|
6458
6486
|
return;
|
|
6459
6487
|
}
|
|
@@ -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,17 +32,26 @@ 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,
|
|
37
43
|
descriptions,
|
|
38
44
|
width,
|
|
39
45
|
audience = readTuiSlashAudience(),
|
|
46
|
+
maxRows,
|
|
40
47
|
}: {
|
|
41
48
|
names: readonly string[];
|
|
42
49
|
descriptions: readonly Pick<SlashCommand, 'name' | 'aliases' | 'description'>[];
|
|
43
50
|
width: number;
|
|
44
51
|
audience?: { role: Role; showBeta: boolean };
|
|
52
|
+
/** The modal's row budget. When the readable layout overflows it, add columns (shorter descriptions)
|
|
53
|
+
* before the caller has to fall back to the chat log — TUI-HELP-OVERLAY (0.2.19 tui node «help-closes»). */
|
|
54
|
+
maxRows?: number;
|
|
45
55
|
}): string[] {
|
|
46
56
|
const registered = new Set(names);
|
|
47
57
|
const entries = descriptions
|
|
@@ -61,34 +71,63 @@ export function buildEssentialHelpLines({
|
|
|
61
71
|
// in each cell. Never trade a missing label for a shorter modal.
|
|
62
72
|
const widestLabel = Math.max(0, ...entries.map(({ label }) => visibleWidth(label)));
|
|
63
73
|
const readableCellWidth = widestLabel + 2 + 28 + 1;
|
|
64
|
-
const
|
|
74
|
+
const baseColumns = entries.length >= 40 && width >= 100
|
|
65
75
|
? Math.max(1, Math.floor(width / (readableCellWidth + 1)))
|
|
66
76
|
: 1;
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
// Narrowest cell that still shows the whole label and a few description characters.
|
|
78
|
+
const minCellWidth = widestLabel + 2 + 10 + 1;
|
|
79
|
+
let lines = layout(baseColumns);
|
|
80
|
+
for (let columns = baseColumns + 1; maxRows !== undefined && lines.length > maxRows
|
|
81
|
+
&& Math.floor(width / columns) - 1 >= minCellWidth; columns++) {
|
|
82
|
+
lines = layout(columns);
|
|
83
|
+
}
|
|
84
|
+
return lines;
|
|
85
|
+
|
|
86
|
+
function layout(columns: number): string[] {
|
|
87
|
+
const columnWidth = Math.floor(width / columns);
|
|
88
|
+
// Task order (TUI-SLASH-DECIDE-NOW C): group head line, then that group's commands by name.
|
|
89
|
+
// Empty groups print no head; unmapped commands land in «그 밖», so none disappears.
|
|
90
|
+
const commandLines: string[] = [];
|
|
91
|
+
const cellWidth = columnWidth - (columns > 1 ? 1 : 0);
|
|
92
|
+
const cellOf = ({ label, description }: { label: string; description: string }) =>
|
|
93
|
+
visibleWidth(`${label} `) > cellWidth ? '' : fitLine(`${label} ${description}`, cellWidth);
|
|
94
|
+
const pushRow = (cells: string[]) => commandLines.push(cells.map((cell, index) =>
|
|
75
95
|
index === cells.length - 1 ? cell : cell + ' '.repeat(columnWidth - visibleWidth(cell)),
|
|
76
96
|
).join('').trimEnd());
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
97
|
+
if (columns > 1) {
|
|
98
|
+
// TUI-HELP-OVERLAY · 2026-10-07 — in columns the group head is a cell and groups flow on: a head line plus a
|
|
99
|
+
// half-empty last row per group pushed the catalog past the modal's rows, so /help fell back to the chat log
|
|
100
|
+
// and Esc no longer closed it (0.2.19 release tui node «help-closes»).
|
|
101
|
+
const cells: string[] = [];
|
|
102
|
+
for (const group of HELP_GROUP_ORDER) {
|
|
103
|
+
const members = entries.filter(({ name }) => helpGroupFor(name) === group);
|
|
104
|
+
if (members.length === 0) continue;
|
|
105
|
+
cells.push(fitLine(helpGroupHeading(group), cellWidth), ...members.map(cellOf));
|
|
106
|
+
}
|
|
107
|
+
for (let start = 0; start < cells.length; start += columns) pushRow(cells.slice(start, start + columns));
|
|
108
|
+
} else {
|
|
109
|
+
for (const group of HELP_GROUP_ORDER) {
|
|
110
|
+
const members = entries.filter(({ name }) => helpGroupFor(name) === group);
|
|
111
|
+
if (members.length === 0) continue;
|
|
112
|
+
commandLines.push(fitLine(helpGroupHeading(group), width));
|
|
113
|
+
for (const member of members) pushRow([cellOf(member)]);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const keyItems = ESSENTIAL_KEYS.map(([key, description]) => `${key} ${description}`);
|
|
117
|
+
const keyLines: string[] = [];
|
|
118
|
+
if (entries.length >= 40 && width >= 100) {
|
|
119
|
+
let keyRow = '';
|
|
120
|
+
for (const item of keyItems) {
|
|
121
|
+
if (keyRow && visibleWidth(keyRow) + 2 + visibleWidth(item) > width) {
|
|
122
|
+
keyLines.push(keyRow);
|
|
123
|
+
keyRow = '';
|
|
124
|
+
}
|
|
125
|
+
keyRow += (keyRow ? ' ' : '') + fitLine(item, width);
|
|
86
126
|
}
|
|
87
|
-
|
|
127
|
+
if (keyRow) keyLines.push(keyRow);
|
|
128
|
+
} else {
|
|
129
|
+
keyLines.push(...keyItems.map((item) => fitLine(item, width)));
|
|
88
130
|
}
|
|
89
|
-
|
|
90
|
-
} else {
|
|
91
|
-
keyLines.push(...keyItems.map((item) => fitLine(item, width)));
|
|
131
|
+
return [fitLine('Commands', width), ...commandLines, '', fitLine('Keys', width), ...keyLines];
|
|
92
132
|
}
|
|
93
|
-
return [fitLine('Commands', width), ...commandLines, '', fitLine('Keys', width), ...keyLines];
|
|
94
133
|
}
|
|
@@ -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
|
+
}
|