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
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ContextNowAnswer, ContextNowDeps } from './context-now.js';
|
|
2
|
+
|
|
3
|
+
const CONTEXT_FIRST_GAP_MS = 6 * 60 * 60 * 1000;
|
|
4
|
+
const CONTEXT_UNREADABLE = '맥락 못 읽음';
|
|
5
|
+
|
|
6
|
+
/** Track every allowed utterance, consuming a pending summary only on a normal turn. */
|
|
7
|
+
export function createContextFirstGate({ now, gapMs = CONTEXT_FIRST_GAP_MS }: { now: () => number; gapMs?: number }) {
|
|
8
|
+
const lastUtteranceAt = new Map<string, number>();
|
|
9
|
+
const pending = new Set<string>();
|
|
10
|
+
return {
|
|
11
|
+
note(key: string): void {
|
|
12
|
+
const at = now();
|
|
13
|
+
const previous = lastUtteranceAt.get(key);
|
|
14
|
+
lastUtteranceAt.set(key, at);
|
|
15
|
+
if (previous === undefined || at - previous >= gapMs) pending.add(key);
|
|
16
|
+
},
|
|
17
|
+
take(key: string): boolean {
|
|
18
|
+
return pending.delete(key);
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function renderContextFirst(
|
|
24
|
+
read: (options: {}, deps?: ContextNowDeps) => ContextNowAnswer,
|
|
25
|
+
deps: ContextNowDeps | undefined,
|
|
26
|
+
render: (answer: ContextNowAnswer) => string,
|
|
27
|
+
): string {
|
|
28
|
+
try {
|
|
29
|
+
return render(read({}, deps));
|
|
30
|
+
} catch {
|
|
31
|
+
return CONTEXT_UNREADABLE;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -72,7 +72,7 @@ export function filterPublicDemoContext(answer: ContextNowAnswer, brandCheck: ty
|
|
|
72
72
|
id: fact.id ? (rulesMissing || privateIds.has(fact.id) ? '내부 항목' : safe(fact.id, '공개 항목')) : null,
|
|
73
73
|
title: fact.title === null ? null : rulesMissing ? internalItem(1) : privateIds.has(fact.id ?? '') ? '내부 항목' : safe(fact.title, '공개 항목'),
|
|
74
74
|
source: source(fact.source) });
|
|
75
|
-
} else facts.push({ ...fact, version: safe(fact.version, '공개 판'), source: source(fact.source) });
|
|
75
|
+
} else if (fact.kind === 'version') facts.push({ ...fact, version: safe(fact.version, '공개 판'), source: source(fact.source) });
|
|
76
76
|
}
|
|
77
77
|
for (const kind of ['cell', 'decision'] as const) {
|
|
78
78
|
if (!collapsed[kind]) continue;
|
|
@@ -34,6 +34,9 @@ function factText(fact: ContextFact): string {
|
|
|
34
34
|
case 'cell': return `${fact.id} ${fact.title} (${fact.status})`;
|
|
35
35
|
case 'decision': return `${fact.id} ${fact.title} (${fact.status})`;
|
|
36
36
|
case 'seat': return `${fact.seat} ${fact.id ?? ''} ${fact.title ?? ''} (${fact.status})`.trim();
|
|
37
|
+
case 'run': return fact.unreadable ? `못 읽음 · ${fact.unreadable}` : `${fact.goal} · ${fact.phase} · ${fact.elapsed}`;
|
|
38
|
+
case 'release': return fact.unreadable ? `못 읽음 · ${fact.unreadable}` : `${fact.version} · ${fact.node} · ${fact.status}`;
|
|
39
|
+
case 'schedule-late': return fact.unreadable ? `못 읽음 · ${fact.unreadable}` : `${fact.count}개 · ${fact.names.join(', ') || '없음'}`;
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -61,20 +64,27 @@ export function renderTuiNow(input: ContextNowAnswer, audience: ContextNowAudien
|
|
|
61
64
|
if (source.startsWith('elanous://release/')) return '원장';
|
|
62
65
|
return Array.from(source).slice(0, 40).join('');
|
|
63
66
|
};
|
|
64
|
-
const factLabels = { version: '판', cell: '칸', decision: '결정', seat: '자리' } as const;
|
|
67
|
+
const factLabels = { run: '도는 런', release: '발행 런', 'schedule-late': '지연 스케줄', version: '판', cell: '칸', decision: '결정', seat: '자리' } as const;
|
|
65
68
|
const eventLabels: Record<string, string> = { report: '보고', dispatch: '발사', decision: '결정' };
|
|
66
69
|
const events = answer.events.slice().sort((a, b) => Date.parse(b.at) - Date.parse(a.at));
|
|
67
70
|
const rows = [
|
|
68
|
-
...answer.facts.
|
|
71
|
+
...answer.facts.slice().sort((a, b) => {
|
|
72
|
+
const priority = (kind: ContextFact['kind']) => ({ run: 0, release: 1, 'schedule-late': 2 } as Partial<Record<ContextFact['kind'], number>>)[kind] ?? 3;
|
|
73
|
+
return priority(a.kind) - priority(b.kind);
|
|
74
|
+
}).map(f => [factLabels[f.kind], shortText(factText(f)), shortSource(f.source)]),
|
|
69
75
|
...events.slice(0, 8).map(e => [eventLabels[e.kind] ?? '소식', shortText(e.summary), shortSource(e.source)]),
|
|
70
76
|
...answer.guide.map(guide => ['안내', guide, '']),
|
|
71
77
|
...(events.length > 8 ? [['안내', `… 사건 ${events.length - 8}개 더(/now <주제> 로 좁히기)`, '']] : []),
|
|
72
78
|
];
|
|
79
|
+
const clean = (text: string) => text.replaceAll('|', ' ').replaceAll(/\r?\n/g, ' ');
|
|
80
|
+
const width = (text: string) => Array.from(text).reduce((total, char) => total + (/[\u1100-\u115f\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\ufe10-\ufe6f\uff01-\uff60\uffe0-\uffe6]/u.test(char) ? 2 : 1), 0);
|
|
81
|
+
const data = [['종류', '사실', '출처'], ...rows].map(row => row.map(clean));
|
|
82
|
+
const widths = [0, 1].map(i => Math.max(...data.map(row => width(row[i] ?? ''))));
|
|
83
|
+
const format = (row: string[]) => `${row[0]}${' '.repeat(widths[0]! - width(row[0]!) + 2)}${row[1]}${' '.repeat(widths[1]! - width(row[1]!) + 2)}${row[2]}`;
|
|
84
|
+
const time = new Intl.DateTimeFormat('en-GB', { timeZone: 'Asia/Seoul', hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }).format(new Date(answer.at));
|
|
73
85
|
return [
|
|
74
|
-
`지금${answer.topic ? ` · ${answer.topic}` : ''} (${
|
|
75
|
-
|
|
76
|
-
'| --- | --- | --- |',
|
|
77
|
-
...rows.map(row => `| ${row.map(cell => cell.replaceAll('|', '\\|').replaceAll(/\r?\n/g, ' ')).join(' | ')} |`),
|
|
86
|
+
`지금${answer.topic ? ` · ${answer.topic}` : ''} (${time} KST)`,
|
|
87
|
+
...data.map(format),
|
|
78
88
|
];
|
|
79
89
|
}
|
|
80
90
|
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
1
|
+
import { existsSync, lstatSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { queryRunningRuns, type QueriedRunningRunsResult } from '../self-implement/running-runs.js';
|
|
4
|
+
import { loadRunLedger } from '../self-implement/run-ledger.js';
|
|
5
|
+
import { localLoopRows } from '../dashboard/slash-runtime/loops-table.js';
|
|
2
6
|
import { checkBrand } from '../../scripts/brand/check.js';
|
|
3
7
|
import { debug, redactSecretText } from '../debug/log.js';
|
|
4
8
|
import { DecisionLedger, type DecisionEntry } from '../decisions/decision-ledger.js';
|
|
@@ -12,7 +16,10 @@ export type ContextFact =
|
|
|
12
16
|
| { kind: 'version'; version: string; source: string }
|
|
13
17
|
| { kind: 'cell'; version: string; id: string; title: string; status: string; owner: string | null; source: string }
|
|
14
18
|
| { kind: 'decision'; id: string; title: string; status: string; dueAt: string | null; source: string }
|
|
15
|
-
| { kind: 'seat'; seat: string; at: string; status: string; id: string | null; title: string | null; source: string }
|
|
19
|
+
| { kind: 'seat'; seat: string; at: string; status: string; id: string | null; title: string | null; source: string }
|
|
20
|
+
| { kind: 'run'; goal: string; phase: string; elapsed: string; source: string; unreadable?: string }
|
|
21
|
+
| { kind: 'release'; version: string; node: string; status: string; source: string; unreadable?: string }
|
|
22
|
+
| { kind: 'schedule-late'; count: number | null; names: string[]; source: string; unreadable?: string };
|
|
16
23
|
export type ContextEvent = { at: string; kind: string; summary: string; source: string };
|
|
17
24
|
export type ContextNowAnswer = { at: string; topic: string | null; facts: ContextFact[]; events: ContextEvent[]; guide: string[]; hiddenCount?: number };
|
|
18
25
|
|
|
@@ -23,6 +30,10 @@ export interface ContextNowDeps {
|
|
|
23
30
|
decisions?: () => DecisionEntry[];
|
|
24
31
|
seatEntries?: (now: Date) => Array<{ entry: SeatEntry; source: string }>;
|
|
25
32
|
events?: (since: string) => CoordEvent[];
|
|
33
|
+
runningRuns?: (now: Date) => Extract<ContextFact, { kind: 'run' }>[];
|
|
34
|
+
queryRuns?: () => QueriedRunningRunsResult;
|
|
35
|
+
releaseRun?: () => Extract<ContextFact, { kind: 'release' }> | null;
|
|
36
|
+
lateSchedules?: (now: Date) => Extract<ContextFact, { kind: 'schedule-late' }> | null;
|
|
26
37
|
brandCheck?: typeof checkBrand;
|
|
27
38
|
}
|
|
28
39
|
|
|
@@ -39,6 +50,75 @@ function todaySeatEntries(now: Date): Array<{ entry: SeatEntry; source: string }
|
|
|
39
50
|
});
|
|
40
51
|
}
|
|
41
52
|
|
|
53
|
+
const runSource = 'elanous://self-implement/running-runs';
|
|
54
|
+
const releaseSource = 'elanous://graph-runs/release-loop';
|
|
55
|
+
const scheduleSource = 'elanous://schedules';
|
|
56
|
+
const oneLine = (text: string) => redactSecretText(text.split(/\r?\n/, 1)[0] ?? '').slice(0, 120);
|
|
57
|
+
|
|
58
|
+
function runningRunFacts(now: Date, queryRuns: () => QueriedRunningRunsResult = () => queryRunningRuns({ includeTest: false, caller: 'context-now' })): Extract<ContextFact, { kind: 'run' }>[] {
|
|
59
|
+
const observed = queryRuns();
|
|
60
|
+
const unreadable = observed.completeness === 'partial' || observed.pty.unreadable.length || !!observed.phases?.unreadableTargetCount;
|
|
61
|
+
const facts = observed.entries.filter(entry => observed.countedStatuses.includes(entry.status)).slice(0, 8).flatMap(entry => {
|
|
62
|
+
let ledgerReadFailure = false;
|
|
63
|
+
const starts = entry.ledgerDirectories.flatMap(directory => {
|
|
64
|
+
try { return loadRunLedger(entry.runId, directory)?.filter(record => record.event === 'start') ?? []; }
|
|
65
|
+
catch { ledgerReadFailure = true; return []; }
|
|
66
|
+
});
|
|
67
|
+
const goalRecord = starts.find(record => typeof record.data.feature === 'string' && record.data.feature.trim());
|
|
68
|
+
const goal = typeof goalRecord?.data.feature === 'string' ? goalRecord.data.feature : ledgerReadFailure ? '골 관측 불가' : '골 미기록';
|
|
69
|
+
const started = starts.map(record => record.timestamp ? Date.parse(record.timestamp) : NaN).find(Number.isFinite) ?? NaN;
|
|
70
|
+
const minutes = Number.isFinite(started)
|
|
71
|
+
? Math.max(0, Math.floor((now.getTime() - started) / 60_000)) : null;
|
|
72
|
+
const fact = { kind: 'run' as const, goal: oneLine(goal),
|
|
73
|
+
phase: entry.lastPhase ?? '단계 미관측', elapsed: minutes === null ? ledgerReadFailure ? '경과 관측 불가' : '경과 미관측' : `${minutes}분`,
|
|
74
|
+
source: `${runSource}/${encodeURIComponent(entry.runId)}` };
|
|
75
|
+
return ledgerReadFailure
|
|
76
|
+
? [
|
|
77
|
+
...(goalRecord || minutes !== null ? [fact] : []),
|
|
78
|
+
{ kind: 'run' as const, goal: '', phase: '', elapsed: '', source: fact.source, unreadable: '런 원장 일부 관측 불가' },
|
|
79
|
+
] : [fact];
|
|
80
|
+
});
|
|
81
|
+
return unreadable ? [...facts, { kind: 'run', goal: '', phase: '', elapsed: '', source: runSource, unreadable: '런 원장 또는 관측 대상 일부' }] : facts;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function latestReleaseRun(): Extract<ContextFact, { kind: 'release' }> | null {
|
|
85
|
+
const dir = join(effectiveInstanceRoot(), 'graph-runs', 'release-loop');
|
|
86
|
+
let filenames: string[];
|
|
87
|
+
try { filenames = readdirSync(dir).filter(name => /^[A-Za-z0-9-]+\.json$/.test(name)); }
|
|
88
|
+
catch (error) {
|
|
89
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null;
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
const runs = filenames.flatMap(filename => {
|
|
93
|
+
const path = join(dir, filename);
|
|
94
|
+
let run: { startedAt?: unknown; status?: unknown; input?: { version?: unknown }; path?: unknown; nodes?: unknown };
|
|
95
|
+
try {
|
|
96
|
+
if (!lstatSync(path).isFile()) return [];
|
|
97
|
+
run = JSON.parse(readFileSync(path, 'utf8'));
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT' || error instanceof SyntaxError) return [];
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
if (typeof run.startedAt !== 'string' || typeof run.status !== 'string' || !Array.isArray(run.path) || !Array.isArray(run.nodes)) return [];
|
|
103
|
+
const steps = run.path.filter((step): step is string => typeof step === 'string');
|
|
104
|
+
const nodes = run.nodes.filter((node): node is { nodeId: string } => !!node && typeof node.nodeId === 'string');
|
|
105
|
+
const version = typeof run.input?.version === 'string' && /^\d+\.\d+\.\d+(?:-(?:rc|alpha|beta)\.\d+)?$/.test(run.input.version) ? run.input.version : '판 미기록';
|
|
106
|
+
const index = Math.min(steps.length, nodes.length + (run.status === 'running' || run.status === 'awaiting-approval' ? 1 : 0));
|
|
107
|
+
return [{ startedAt: run.startedAt, fact: { kind: 'release' as const, version, node: `${index}/${steps.length}${steps[index - 1] ? ` ${oneLine(steps[index - 1]!)}` : ''}`,
|
|
108
|
+
status: oneLine(run.status), source: `${releaseSource}/${encodeURIComponent(filename.slice(0, -5))}` } }];
|
|
109
|
+
});
|
|
110
|
+
return runs.sort((a, b) => b.startedAt.localeCompare(a.startedAt))[0]?.fact ?? null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function lateScheduleFact(now: Date): Extract<ContextFact, { kind: 'schedule-late' }> {
|
|
114
|
+
const names = localLoopRows(now).filter(row => row.verdict === 'late').map(row => oneLine(row.name));
|
|
115
|
+
return { kind: 'schedule-late', count: names.length, names, source: scheduleSource };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function unreadableReason(error: unknown): string {
|
|
119
|
+
return oneLine(error instanceof Error ? error.message : String(error)) || '원천 조회 실패';
|
|
120
|
+
}
|
|
121
|
+
|
|
42
122
|
/** Read a bounded, source-labelled view of current ledgers, never a transcript or decision body. */
|
|
43
123
|
export function contextNow(options: { topic?: string; limit?: number; audience?: 'operator' | 'user' | 'public-demo' } = {}, deps: ContextNowDeps = {}): ContextNowAnswer {
|
|
44
124
|
const now = (deps.now ?? (() => new Date()))();
|
|
@@ -71,6 +151,20 @@ export function contextNow(options: { topic?: string; limit?: number; audience?:
|
|
|
71
151
|
const rawEvents = (deps.events ?? (since => listCoordEvents({ since })))(new Date(now.getTime() - 7 * 86_400_000).toISOString());
|
|
72
152
|
const chronologicalEvents = rawEvents.slice().sort((a, b) => a.at.localeCompare(b.at));
|
|
73
153
|
const matches = (text: string) => !topic || text.toLocaleLowerCase().includes(topic.toLocaleLowerCase());
|
|
154
|
+
const operational: ContextFact[] = [];
|
|
155
|
+
if (options.audience !== 'public-demo') {
|
|
156
|
+
try { operational.push(...(deps.runningRuns ?? (date => runningRunFacts(date, deps.queryRuns)))(now)); }
|
|
157
|
+
catch (error) { operational.push({ kind: 'run', goal: '', phase: '', elapsed: '', source: runSource, unreadable: unreadableReason(error) }); }
|
|
158
|
+
try {
|
|
159
|
+
const release = (deps.releaseRun ?? latestReleaseRun)();
|
|
160
|
+
if (release) operational.push(release);
|
|
161
|
+
} catch (error) { operational.push({ kind: 'release', version: '', node: '', status: '', source: releaseSource, unreadable: unreadableReason(error) }); }
|
|
162
|
+
try { const schedules = (deps.lateSchedules ?? lateScheduleFact)(now); if (schedules) operational.push(schedules); }
|
|
163
|
+
catch (error) { operational.push({ kind: 'schedule-late', count: null, names: [], source: scheduleSource, unreadable: unreadableReason(error) }); }
|
|
164
|
+
}
|
|
165
|
+
const selectedOperational = operational.filter(f => !topic || ('unreadable' in f && !!f.unreadable) || (f.kind === 'run' && matches(`${f.goal} ${f.phase}`))
|
|
166
|
+
|| (f.kind === 'release' && matches(`${f.version} ${f.node} ${f.status}`))
|
|
167
|
+
|| (f.kind === 'schedule-late' && matches(f.names.join(' '))));
|
|
74
168
|
const selectedFacts = facts.filter(f => !topic || (f.kind === 'cell' && matches(`${f.id} ${f.title}`))
|
|
75
169
|
|| (f.kind === 'seat' && matches(`${f.id ?? ''} ${f.title ?? ''}`)));
|
|
76
170
|
const groups = (['version', 'cell', 'decision', 'seat'] as const).map(kind => selectedFacts.filter(f => f.kind === kind));
|
|
@@ -92,7 +186,7 @@ export function contextNow(options: { topic?: string; limit?: number; audience?:
|
|
|
92
186
|
chosen[index]!.push(...extra);
|
|
93
187
|
remaining -= extra.length;
|
|
94
188
|
}
|
|
95
|
-
const boundedFacts = chosen.flat();
|
|
189
|
+
const boundedFacts = [...selectedOperational.slice(0, limit), ...chosen.flat()];
|
|
96
190
|
const summaries = chronologicalEvents.map(event => ({
|
|
97
191
|
at: event.at, kind: event.kind, summary: redactSecretText(event.summary.split(/\r?\n/, 1)[0] ?? '').slice(0, 120),
|
|
98
192
|
source: event.refs.source ?? event.refs.url ?? `elanous://context/event/${encodeURIComponent(event.id)}`,
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// B1(UX · 0.2.7) — 짧은 «물음»은 도구 없이 빠른 경로로(첫 글자 ≤2초 · 내부 문서 `EVAL-bot-chat-vs-grok-2026-09-30`).
|
|
2
|
+
// 허용 방식(골 ASK-bot-short-question-fast-path-b1b): 아래가 «모두» 참일 때만 fast — 하나라도 거짓이면 fast 아님(보수 쪽).
|
|
3
|
+
// ⓐ 한 줄 · 80자 이하 · 첨부 없음 ⓑ 인사이거나 «물음 꼴» ⓒ 요청·작업 표지 · 경로·URL·코드 꼴 · 실시간 낱말이 없다.
|
|
4
|
+
// 거부 목록으로 변형을 다 막을 수는 없다 — 오분류 비용은 «확인해 볼까요?» 한 줄로 막힌다(도구가 안 실릴 뿐 대화는 이어진다).
|
|
5
|
+
// 판정 표본 = src/chat/short-question.test.ts 의 고정 표 20개(⊕ 리뷰가 든 변형).
|
|
6
|
+
|
|
7
|
+
export interface ShortQuestionContext {
|
|
8
|
+
hasAttachments?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface ShortQuestionVerdict {
|
|
11
|
+
fast: boolean;
|
|
12
|
+
reason: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const GREETING = /^(?:안녕(?:하세요|하십니까)?|반가워(?:요)?|고마워(?:요)?|감사합니다|하이|hi|hello|hey|thanks|thank you)[!?.~\s]*$/i;
|
|
16
|
+
// «한 줄로» 같은 짧은 꼬리를 떼고 본다.
|
|
17
|
+
const TAIL = /\s*(?:한\s*줄로|짧게|간단히|briefly|in one line)[.!]?\s*$/i;
|
|
18
|
+
const KO_QUESTION_END = /(?:\?|까|니|나요|냐|야|어때|뭐|몇|언제|어디|누구|왜|인가|일까)[?.!~]*$/;
|
|
19
|
+
const EN_QUESTION = /^(?:what|why|how|who|where|when|which|is|are|does|do)\b.*\?$/i;
|
|
20
|
+
const REQUEST_KO = /(?:해\s*줘|해\s*주세요|줘(?:요)?(?=[?.!\s]|$)|주세요|줄래|할래|볼래|줄\s*수\s*있|돌려|실행|고쳐|만들어\s*줘|찾아|검색|확인해|열어|보내|올려|지워|써\s*줘|작성해|요약해|정리해|분석해)/;
|
|
21
|
+
const REQUEST_EN = /\b(?:please|can you|could you|would you|run|test|tests|fix|build|open|search|check|send|create|write|deploy|install|summarize)\b/i;
|
|
22
|
+
const TASK = /(?:작업|파일|폴더|디렉터리|레포|저장소|커밋|브랜치|\bPR\b|코드|스크립트|테스트|빌드|배포|설치|설정|명령어|로그|버그|이슈)/i;
|
|
23
|
+
const PATH_OR_CODE = /(?:https?:\/\/|www\.|[\w.-]+\/[\w./-]+|\.(?:ts|tsx|js|py|md|json|yaml|swift|kt)\b|[`{};=<>])/i;
|
|
24
|
+
const LIVE = /(?:오늘\s*(?:날짜|며칠|무슨\s*요일)|지금\s*몇\s*시|최신|뉴스|속보|주가|시세|환율|날씨|today'?s|latest|news|stock|weather|right now)/i;
|
|
25
|
+
|
|
26
|
+
export type TuiChatRoute = '조회' | '설정 변경' | '조사' | '상시 일' | '코딩·구현';
|
|
27
|
+
|
|
28
|
+
export interface TuiChatVerdict {
|
|
29
|
+
route: TuiChatRoute;
|
|
30
|
+
reason: string;
|
|
31
|
+
goalLoop: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Request verbs a quick lookup/settings/research/scheduling turn can carry out without the repository. */
|
|
35
|
+
const QUICK_REQUEST_VERBS = /^(?:보여|알려|확인해|찾아|찾아봐|조사해|검색해|정리해|요약해|바꿔|변경해|전환해|설정해|맞춰|수정해|고쳐|만들어|등록해|예약해|추가해|보내)$/;
|
|
36
|
+
|
|
37
|
+
/** True when the verb never appears, or each occurrence directly follows an allowed object. */
|
|
38
|
+
function everyVerbTakes(text: string, verb: RegExp, object: RegExp): boolean {
|
|
39
|
+
for (const match of text.matchAll(verb)) {
|
|
40
|
+
if (!object.test(text.slice(0, match.index))) return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Uncertain or mixed requests retain the full coding goal-loop and tool surface. */
|
|
46
|
+
export function classifyTuiChatIntent(text: string, ctx: ShortQuestionContext = {}): TuiChatVerdict {
|
|
47
|
+
const q = text.trim();
|
|
48
|
+
const coding = (reason: string): TuiChatVerdict => ({ route: '코딩·구현', reason, goalLoop: true });
|
|
49
|
+
if (!q || ctx.hasAttachments) return coding(ctx.hasAttachments ? 'attachment' : 'empty');
|
|
50
|
+
if (/(?:하니스|구현|코딩|코드|스크립트|버그|소스|리팩터|커밋|패치|테스트|시험\s*돌|빌드|배포|브랜치|서버|파일|레포|저장소|\bPR\b|\b(?:implement|coding|code|script|refactor|commit|patch|tests?|build|deploy|branch|server|file|repo)\b)/i.test(q)) return coding('coding');
|
|
51
|
+
// Destructive or executing verbs in any form (not only «…줘») are never a quick turn.
|
|
52
|
+
if (/(?:지워|지우|삭제|제거|옮겨|옮기|돌려|실행|설치|되돌려|롤백|재시작|죽여|\b(?:delete|remove|rm|rename|move|run|install|revert|rollback|drop|kill|restart)\b)/i.test(q)) return coding('write-verb');
|
|
53
|
+
// A file path or code shape means the request touches the repository, whatever else it asks.
|
|
54
|
+
if (PATH_OR_CODE.test(q)) return coding('path-or-code');
|
|
55
|
+
// Allowlist, not denylist: every «…줘» request verb must be one a quick turn can do; anything else
|
|
56
|
+
// (지워줘 · 돌려줘 · 옮겨줘 …) keeps the coding goal loop.
|
|
57
|
+
for (const match of q.matchAll(/([가-힣]+?)\s*(?:줘|주세요|줄래|주라)/g)) {
|
|
58
|
+
if (!QUICK_REQUEST_VERBS.test(match[1]!)) return coding('request-verb');
|
|
59
|
+
}
|
|
60
|
+
// Edit and create verbs are coding requests unless every one of them takes a quick object directly
|
|
61
|
+
// («모델 설정 수정해줘» · «알림 만들어줘» stay quick; «… 그리고 화면 고쳐줘» does not).
|
|
62
|
+
if (!everyVerbTakes(q, /(?:수정|고쳐|바꿔|변경|전환|교체|\b(?:edit|fix|modify|change|switch|replace)\b)/gi, /(?:모델|설정|config|provider|예약|일정|알림|리마인더|스케줄|reminder|schedule)\s*(?:을|를|로|으로)?\s*$/i)) return coding('edit');
|
|
63
|
+
if (!everyVerbTakes(q, /(?:만들어|작성|추가해|생성|등록해|\b(?:create|write|make|add)\b)/gi, /(?:알림|일정|예약|리마인더|스케줄|reminder|schedule)\s*(?:을|를)?\s*$/i)) return coding('create');
|
|
64
|
+
|
|
65
|
+
const routes: Array<{ route: Exclude<TuiChatRoute, '코딩·구현'>; reason: string; pattern: RegExp }> = [
|
|
66
|
+
{ route: '조회', reason: 'lookup', pattern: /(?:결정\s*카드|결정\s*대기|상태|현황|로그|알림\s*(?:왔|있|보여)|\b(?:status|logs?|pending decisions?)\b)/i },
|
|
67
|
+
{ route: '설정 변경', reason: 'settings', pattern: /(?:(?:모델|설정|config|provider).*(?:바꿔|변경|전환|설정해|맞춰|수정|고쳐|써\s*줘|set|change|switch|edit|fix|modify)|(?:바꿔|변경|전환).*(?:모델|설정|config|provider)|답변.*빠른\s*모델)/i },
|
|
68
|
+
{ route: '조사', reason: 'research', pattern: /(?:조사|검색|찾아\s*봐|뉴스|업계\s*소식|\b(?:research|search|news)\b)/i },
|
|
69
|
+
{ route: '상시 일', reason: 'recurring', pattern: /(?:매일|매주|매달|매\s*아침|[가-힣]+마다|정기적|반복\s*일정|예약|리마인더|\b(?:daily|weekly|every|schedule|remind)\b)/i },
|
|
70
|
+
];
|
|
71
|
+
const matches = routes.filter(({ pattern }) => pattern.test(q));
|
|
72
|
+
// A recurring job that looks something up or researches it is still a scheduling request.
|
|
73
|
+
if (matches.some(({ route }) => route === '상시 일')
|
|
74
|
+
&& matches.every(({ route }) => route === '상시 일' || route === '조사' || route === '조회')) {
|
|
75
|
+
return { route: '상시 일', reason: matches.length > 1 ? 'recurring-research' : 'recurring', goalLoop: false };
|
|
76
|
+
}
|
|
77
|
+
if (matches.length !== 1) {
|
|
78
|
+
if (matches.length) return coding('mixed');
|
|
79
|
+
const shortQuestion = classifyShortQuestion(q, ctx);
|
|
80
|
+
return coding(shortQuestion.fast ? `short-${shortQuestion.reason}` : 'ambiguous');
|
|
81
|
+
}
|
|
82
|
+
const { route, reason } = matches[0]!;
|
|
83
|
+
return { route, reason, goalLoop: false };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function classifyShortQuestion(text: string, ctx: ShortQuestionContext = {}): ShortQuestionVerdict {
|
|
87
|
+
const q = text.trim();
|
|
88
|
+
if (!q) return { fast: false, reason: 'empty' };
|
|
89
|
+
if (ctx.hasAttachments) return { fast: false, reason: 'attachment' };
|
|
90
|
+
if (/[\r\n\u2028\u2029]/.test(q)) return { fast: false, reason: 'multiline' };
|
|
91
|
+
if ([...q].length > 80) return { fast: false, reason: 'long' };
|
|
92
|
+
if (PATH_OR_CODE.test(q)) return { fast: false, reason: 'path-or-code' };
|
|
93
|
+
if (LIVE.test(q)) return { fast: false, reason: 'live' };
|
|
94
|
+
if (REQUEST_KO.test(q) || REQUEST_EN.test(q)) return { fast: false, reason: 'request' };
|
|
95
|
+
if (TASK.test(q)) return { fast: false, reason: 'task' };
|
|
96
|
+
if (GREETING.test(q)) return { fast: true, reason: 'greeting' };
|
|
97
|
+
const core = q.replace(TAIL, '').trim();
|
|
98
|
+
if (KO_QUESTION_END.test(core) || EN_QUESTION.test(core)) return { fast: true, reason: 'question' };
|
|
99
|
+
return { fast: false, reason: 'not-a-question' };
|
|
100
|
+
}
|
|
@@ -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) {
|