elanous 0.2.28 → 0.2.29
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/{y1ltt7oCZxVpC6zVPhZ2O → cIpv5nU9AycwYWZI9H589}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{ab4d57c2.e90bc2cb31949045.js → 058a98ba.7eb28d5e6dc03565.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4565-67e4c620597965c8.js → 1015-9cba22a5a4554797.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{1516.83dd2c1b86b4e507.js → 1142.65d002789ab3af7d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +34 -0
- package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1516.dfaceff3fd2d0e0d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +286 -0
- package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +24 -0
- package/apps/pwa/out/_next/static/chunks/1782-59db1b5aa06df38a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1743.563d3168e95825ef.js → 1852.7f7b53991fcb99ef.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +36 -0
- package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +64 -0
- package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +1 -0
- package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{65ebff95.081daeff622d238e.js → 285adb1a.5654e605dddf86d2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +115 -0
- package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3160-95c96f4d2a21dd26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +90 -0
- package/apps/pwa/out/_next/static/chunks/328bb3ab-6628a1114fe3fb3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9917-9e26abc5f7772735.js → 3396-97b97928c49190c9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6196.34d6b229079e9e28.js → 3403.7199205e65124486.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +1 -0
- package/apps/pwa/out/_next/static/chunks/419.736c0d6f426249a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6def8a8e.c81f9ca41028eccf.js → 425cfc4d.fb91158e3971c39f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{16e57f67.3ea19e893461e611.js → 46bd8bea.2f4b4099172fcdb7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5081.a240b63fad28663a.js → 4759.1f76713aefb87db5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +94 -0
- package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +62 -0
- package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +27 -0
- package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{9974.e77b4ff4884557b3.js → 5591.a35e7a217734a8b9.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +93 -0
- package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5492-e05e26a033ba80d2.js → 6013-2f769370d8b4c2c6.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +24 -0
- package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +2 -0
- package/apps/pwa/out/_next/static/chunks/{5408.377c8c543635b81f.js → 6534.1ab00f370db7b105.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +148 -0
- package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +149 -0
- package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +79 -0
- package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8578.dff22d988cc2b106.js → 6767.1fcfc9b8be83975f.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/6776.06ff1e3b464cc607.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9311.24c8f5ea793253dd.js → 6853.cc5174a9dee59593.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +287 -0
- package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{94.4cfed21c0b781a06.js → 7375.050ea0d72968e49f.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +74 -0
- package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7725-4f83d5541fbdb81b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8332.6f0f49df772e163b.js +23 -0
- package/apps/pwa/out/_next/static/chunks/{7483.ba01c6c209b81bba.js → 8398.73a19b39715eda04.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2846.d6a433b8663819a5.js → 8471.8d2a8c74f09c36ff.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{5785-ea8d2c633b6688e3.js → 8767-2f6a634f5abeaa01.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +32 -0
- package/apps/pwa/out/_next/static/chunks/8795.32573a185af18c7b.js +41 -0
- package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4593.10f5b9bd702d4a6c.js → 9143.ff14585db1d275ff.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4204.a409ab6250c0f6a8.js → 9907.49be0fcadaf214b5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{973cbf1b.3bbcf2b41548eca7.js → a435ad95.577add051b4facb2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-fa46d4588e8442c2.js → page-a5635eba0d73b84e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/{page-66ad46ed0279feb9.js → page-86feb08080261a2f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/{page-646b50f63b6fe732.js → page-8aaa6dedc4c10dfb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-6f131b51193a36f9.js → page-33bf667a5fb297bf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-29900ed0011b2c83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9f92737b8766009a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{f4dfbfc0.a69fb12f854882aa.js → bc324b7c.02a09dd93f6a399b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +1 -0
- package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +122 -0
- package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/graphs/release/release-loop.yaml +6 -2
- package/package.json +1 -1
- package/plugins/agent-team/agents/research.md +1 -0
- package/scripts/ci-typecheck-changed.ts +3 -2
- package/scripts/coord-channel-watch.sh +26 -6
- package/scripts/coord-role-pack.ts +143 -0
- package/scripts/lib/morning-report-options.ts +41 -0
- package/scripts/pr-land-extra-remote-gates.ts +49 -0
- package/scripts/release-loop/gate-batch-safe.ts +23 -0
- package/scripts/release-loop/gate-history.ts +422 -0
- package/scripts/release-loop/gate-node.ts +310 -46
- package/scripts/release-loop/gate-triage-node.ts +190 -0
- package/scripts/release-loop/spawn-lane.ts +68 -0
- package/scripts/release-loop/tui-node-checks.ts +23 -0
- package/scripts/release-loop/version-node.ts +62 -4
- package/scripts/test-deterministic.ts +41 -12
- package/scripts/usage-rollup.ts +11 -3
- package/src/acp/core-turn-bridge.ts +98 -22
- package/src/acp/elanous-extensions.ts +2 -0
- package/src/acp/server.ts +2 -0
- package/src/agent/ref-grounding.ts +18 -0
- package/src/agent-substrate/pr-reviewer.ts +29 -21
- package/src/budget/pty-usage-reemit.ts +7 -0
- package/src/budget/run-usage-rollup.ts +9 -0
- package/src/budget/usage-daily-store.ts +98 -0
- package/src/capture/tui-self-report.ts +22 -4
- package/src/chat/index.ts +31 -10
- package/src/chat/pickers/modal-runtime.ts +1 -0
- package/src/chat/pickers/modals.ts +3 -1
- package/src/chat/turn-typeahead.ts +123 -16
- package/src/cli/dashboard-name-flag.ts +48 -0
- package/src/cli/doctor-cli.ts +80 -0
- package/src/cli/log-event-names.ts +12 -0
- package/src/cli/msg-cli.ts +45 -2
- package/src/cli/pr-cli.ts +382 -105
- package/src/cli/pr-land-heavy-remote.ts +233 -0
- package/src/cli/pr-land-overlap-evidence.ts +104 -5
- package/src/cli/pty-takeover-cli.ts +125 -16
- package/src/cli/release-cli.ts +44 -2
- package/src/cli/remote-resolve.ts +2 -1
- package/src/cli/seat-cli.ts +26 -16
- package/src/cli/tasks-cli.ts +8 -2
- package/src/cli/usage-cli.ts +146 -12
- package/src/cli/usage-daily-cli.ts +84 -0
- package/src/context-bus/context-now.ts +82 -5
- package/src/core-turn/auth-rejected-notice.ts +41 -0
- package/src/core-turn/run-core-turn.ts +13 -2
- package/src/core-turn/run-goal-loop.ts +17 -1
- package/src/core-turn/short-question.ts +45 -12
- package/src/core-turn/types.ts +7 -0
- package/src/dashboard/acp-active-model.ts +40 -0
- package/src/dashboard/auto-compact-runtime.ts +2 -0
- package/src/dashboard/boot-banner.ts +80 -0
- package/src/dashboard/dashboard-status-lines.ts +11 -0
- package/src/dashboard/detail-viewer-runtime.ts +15 -2
- package/src/dashboard/event-loop-stall-monitor.ts +4 -0
- package/src/dashboard/goal-loop-thinking.ts +16 -0
- package/src/dashboard/hitl-boot.ts +9 -4
- package/src/dashboard/index.ts +228 -387
- package/src/dashboard/input/chat-main-entry-runtime.ts +2 -0
- package/src/dashboard/input/chat-main-log-actions.ts +4 -0
- package/src/dashboard/input/chat-main-log-command.ts +12 -1
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +172 -3
- package/src/dashboard/input/chat-main-session.ts +6 -2
- package/src/dashboard/input/chat-main-slash-command.ts +7 -0
- package/src/dashboard/input/chat-main-turn.ts +2 -1
- package/src/dashboard/input/compact-prepass-recovery.ts +97 -0
- package/src/dashboard/input/dashboard-chord-actions.ts +10 -1
- package/src/dashboard/input/dashboard-chord-runtime.ts +2 -0
- package/src/dashboard/input/external-input-host.ts +45 -0
- package/src/dashboard/input/log-fold-binding.ts +18 -0
- package/src/dashboard/input/mouse-wiring.ts +17 -4
- package/src/dashboard/input/turn-steer-bridge.ts +94 -0
- package/src/dashboard/log-click-runtime.ts +5 -3
- package/src/dashboard/running-build-status.ts +74 -0
- package/src/dashboard/seat-boot-preamble.ts +113 -0
- package/src/dashboard/seat-local-instructions.ts +305 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +100 -28
- package/src/dashboard/slash-runtime/model-choices.ts +35 -0
- package/src/dashboard/term-slash-runtime.ts +15 -0
- package/src/dashboard/turn-preamble.ts +30 -2
- package/src/dashboard/turn-session-layers.ts +176 -0
- package/src/dashboard/turn-stream-formatter.ts +14 -6
- package/src/dashboard/turn-stream-presentation-applier.ts +8 -0
- package/src/domains/release-tool.ts +8 -9
- package/src/domains/surface-events.ts +4 -1
- package/src/domains/watch-default-scheduler.ts +8 -9
- package/src/fold-stack.ts +24 -1
- package/src/git-fs/dirty.ts +32 -4
- package/src/git-fs/index.ts +43 -1
- package/src/graph-runner/runner.ts +1 -0
- package/src/harness/harness-gc.ts +32 -5
- package/src/index.ts +14 -1
- package/src/input/external-input-queue.ts +219 -0
- package/src/interactive-terminal-modal.ts +13 -0
- package/src/llm/route-decision.ts +25 -0
- package/src/llm-stream-retry-display.ts +59 -0
- package/src/llm.ts +253 -55
- package/src/log-entry.ts +3 -3
- package/src/log-pane/search.ts +29 -4
- package/src/loops/agent-reply.ts +256 -0
- package/src/loops/budget.ts +37 -7
- package/src/loops/loop-cli.ts +3 -2
- package/src/loops/msg-address.ts +57 -0
- package/src/loops/msg-wake.ts +282 -0
- package/src/loops/orchestrator/inbox.ts +60 -3
- package/src/loops/orchestrator/tick.ts +24 -4
- package/src/loops/registry.ts +42 -4
- package/src/memory.ts +20 -5
- package/src/native-tool-catalog.ts +125 -0
- package/src/nexus/api/http-server.ts +5 -0
- package/src/nexus/api/ops-api.ts +2 -0
- package/src/nexus/api/project-autopsy.ts +127 -0
- package/src/nexus/api/terminals.ts +3 -0
- package/src/nexus/api/workflow-approvals.ts +2 -0
- package/src/nexus/onboarding/first-boot-wizard.ts +56 -2
- package/src/oauth/codex-account-store.ts +15 -3
- package/src/oauth/codex-billing-route.ts +31 -0
- package/src/ops/overview-collect.ts +19 -2
- package/src/panes/log-pane.ts +67 -8
- package/src/persona/presets.ts +44 -0
- package/src/plugins/maker/wizard-generate.ts +6 -4
- package/src/preview/terminal.ts +14 -1
- package/src/prompt-cache/types.ts +2 -0
- package/src/prompt-enhance/enhance.ts +24 -8
- package/src/prompt-library/universal-preamble.ts +273 -56
- package/src/pty-shell/pty-control-ipc.ts +4 -1
- package/src/pty-shell/pty-manifest.ts +77 -5
- package/src/pty-shell/registry.ts +19 -2
- package/src/pty-shell/tui-run-state.ts +253 -0
- package/src/release-loop/light-rc.ts +28 -3
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/render.ts +5 -1
- package/src/seat-loop/seat-report.ts +42 -2
- package/src/self-dev/run-supervisor.ts +71 -5
- package/src/self-dev/shard-aggregate.ts +2 -0
- package/src/self-dev/shard-run.ts +23 -2
- package/src/self-health/signatures.ts +132 -0
- package/src/self-implement/doctor-visit.ts +118 -0
- package/src/self-implement/gate-cli.ts +11 -2
- package/src/self-implement/goal-author-decompose.ts +80 -16
- package/src/self-implement/goal-author.ts +114 -72
- package/src/self-implement/goal-authoring-grounding.ts +1 -1
- package/src/self-implement/goal-file-name.ts +65 -0
- package/src/self-implement/ground-goal.ts +2 -1
- package/src/self-implement/host-regate.ts +14 -0
- package/src/self-implement/review-mustfix-class.ts +115 -0
- package/src/self-implement/run-ledger.ts +111 -7
- package/src/self-implement/running-runs.ts +10 -6
- package/src/self-implement/self-implement-runtime.ts +32 -0
- package/src/session/pending-input.ts +62 -11
- package/src/session-runtime/index.ts +7 -1
- package/src/skills/tools/ops-ledger.ts +707 -0
- package/src/skills/tools/persistent-grounding.ts +47 -7
- package/src/skills/tools/shell.ts +117 -1
- package/src/status/bar.ts +32 -2
- package/src/status/status-provider-info.ts +58 -0
- package/src/task-agent/rejudge-on-head.ts +4 -1
- package/src/task-agent/remote-rejudge-bind.ts +34 -5
- package/src/task-agent/repair-cycle.ts +13 -0
- package/src/task-orchestrator/surfaces/kubectl-transient-retry.ts +51 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +63 -7
- package/src/task-orchestrator/surfaces/pod-install-slots.ts +6 -11
- package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +76 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +107 -33
- package/src/terminal/session-registry.ts +6 -0
- package/src/thinking-line.ts +12 -3
- package/src/tool-runtime/index.ts +4 -0
- package/src/tool-runtime/ops-ledger-runtimes.ts +84 -0
- package/src/tool-runtime/ref-consult-runtime.ts +17 -2
- package/src/tool-runtime/run-shell-runtime.ts +4 -1
- package/src/tool-runtime/self-cognition-runtimes.ts +5 -1
- package/src/tui.ts +5 -0
- package/src/user-config.ts +54 -6
- package/src/ux-sim/fake-llm.ts +29 -0
- package/src/ux-sim/in-process-cli.ts +175 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +0 -1
- package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +0 -36
- package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +0 -148
- package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1454-29d1d773d5996a49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +0 -27
- package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +0 -24
- package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +0 -32
- package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +0 -34
- package/apps/pwa/out/_next/static/chunks/3259-86f3be56e43eaf6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +0 -287
- package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4084.15ecaf4240bd9e77.js +0 -286
- package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +0 -8
- package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +0 -104
- package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +0 -149
- package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +0 -1
- package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/599-56f2c0a5cc4a7295.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +0 -23
- package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +0 -77
- package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +0 -64
- package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +0 -2
- package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +0 -62
- package/apps/pwa/out/_next/static/chunks/7752.5cbdd0b433c54af9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8085-1e5fce59500a2cc2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +0 -226
- package/apps/pwa/out/_next/static/chunks/83a80514-b897b64df43ce108.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +0 -93
- package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +0 -24
- package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +0 -115
- package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +0 -41
- package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +0 -74
- package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +0 -94
- package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +0 -90
- package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +0 -79
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-5ab1e47978577c5e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-24453f6a302816b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-6c131d30bb1cf871.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-dc0772b11861af51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-5159dc8752c6cd29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-c5a2478861c08b87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-f722a9dec084e08b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-256ffd365d32e100.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e0de78ae7b99f01c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-cfbdc44b708d9801.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-4c741eb760f2f77c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-e9ba98f5f1440a21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-dafc901bb1b72b5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-2f6f303fa114ec24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-1634081c5272006c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-ced0bcfc6542b3fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-bb1f05cd51c38944.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-db069b48a59c8c00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-f736324afa2117c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-435f5e2faf02bc01.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-497e0eedf20e7890.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-a8d28fdf995e16ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8966452228753c5e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fd5d18656cb432b6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-5663779cb1a37609.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-66a67eb19ebd976b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-3b492aa78cf3c4a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c71267e7681da982.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-a21d1e1797172692.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-cb249e81ed339318.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-781cfc5114e097da.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-478157214db6a023.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-86141f12cf090b7f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-7256c73bb1c36751.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-5c738ca7adef3de5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-0138c8091ec17224.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-cc2f24f16d85e735.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-979d318a534e92da.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-182d394f7e6e096b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-21050928a697ed7a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-44b9d807005a9030.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-601fb77340e63c9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-75d3fb5d47af0edf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-11bf9e5725a72c22.js +0 -1
- package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +0 -1
- package/apps/pwa/out/_next/static/chunks/e117f801.e92bf10242653497.js +0 -1
- package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +0 -122
- package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +0 -1
- package/src/dashboard/bench-slash-runtime.ts +0 -40
- package/src/dashboard/input/search-modal-router.ts +0 -9
- package/src/dashboard/modals/pane-key-router.ts +0 -27
- package/src/dashboard/view-slash-runtime.ts +0 -48
- /package/apps/pwa/out/_next/static/{y1ltt7oCZxVpC6zVPhZ2O → cIpv5nU9AycwYWZI9H589}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
// 🪪 L2-lite — TUI 가 자기 자리 로컬 지시(`AGENTS.local.md`)를 «만들고 이어 쓴다» (TUI-SEAT-CONTINUITY · 2026-10-14).
|
|
2
|
+
//
|
|
3
|
+
// S: 자리(`~/elanous-hq/seats/<자리>`)에서 TUI 를 다시 띄우면 지난 세션에 무엇을 하다 나갔는지 모른다.
|
|
4
|
+
// TUI 는 파일 기억(`buildMemoryInjection`)을 받지 않고 턴·세션 끝 기억 쓰기도 없다 — 연속성 장치가 0 이다.
|
|
5
|
+
// A: 둘을 한다.
|
|
6
|
+
// ① 생성 — 자리 디렉터리에서 뜰 때 로컬 지시 파일이 «하나도» 없으면 템플릿으로 `AGENTS.local.md` 를 만든다.
|
|
7
|
+
// 재료: seat-state/<자리>/README.md 머리 ⊕ 자리 이름 ⊕ 저장소 AGENTS.md §제1원칙 요지(출처 줄) ⊕ «## 시작하면» 기본 절차.
|
|
8
|
+
// ⛔ 사람이 쓴 파일은 절대 덮어쓰지 않는다 — `AGENTS.local.md` 든 `CLAUDE.local.md` 든 있으면 생성 0
|
|
9
|
+
// (`CLAUDE.local.md` 만 있는데 `AGENTS.local.md` 를 만들면 앵커 로더가 사람 파일을 shadowed 로 가린다).
|
|
10
|
+
// ② 이어쓰기 — «지난 세션»은 TUI 가 «통째로 소유하는» 별도 파일(자리 루트 `.AGENTS.local.last-session.md` · git 제외)에
|
|
11
|
+
// 대화가 끝날 때(`/quit`·Ctrl+C·SIGINT/SIGTERM = process 'exit' · `/session new`·`clear`) 5줄 이내로 쓴다(tmp ⊕ rename).
|
|
12
|
+
// ⛔ 사람 지시 파일은 «고치지 않는다» — 사람 파일 안의 블록을 갈아 쓰면 잠금 없이는 경쟁 창을 0 으로 못 만든다(#27505 r1~r4).
|
|
13
|
+
// 재료는 대화 기록(마지막 요청·마지막 답 요지·열린 일 후보·다음 점검 시각 후보) — LLM 호출 없이 동기로(종료 경로).
|
|
14
|
+
// 실패해도 종료를 막지 않는다.
|
|
15
|
+
// ③ 다음 기동 때 L0 앵커 로더(`universal-preamble.ts`)가 그 파일을 층 ④(로컬 지시) 뒤 조각으로 싣는다.
|
|
16
|
+
// 관측: `tui.local-instructions` created / create-skipped / last-session-written / last-session-skipped.
|
|
17
|
+
// ⛔ 생성은 cwd 가 `/seats/<자리>` 일 때만 — `COORD_ID` 만으로는 아무 저장소 디렉터리에 파일을 만들지 않는다.
|
|
18
|
+
|
|
19
|
+
import { existsSync, lstatSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
20
|
+
import { homedir } from 'node:os';
|
|
21
|
+
import { randomBytes } from 'node:crypto';
|
|
22
|
+
import { dirname, join } from 'node:path';
|
|
23
|
+
import { debug } from '../debug/log.js';
|
|
24
|
+
|
|
25
|
+
export const LOCAL_INSTRUCTIONS_FILE = 'AGENTS.local.md';
|
|
26
|
+
const COMPAT_LOCAL_FILE = 'CLAUDE.local.md';
|
|
27
|
+
/** TUI 가 통째로 소유하는 «지난 세션» 파일 — 자리 루트에 둔다. L0 앵커 로더가 같은 이름을 읽는다. */
|
|
28
|
+
export const LAST_SESSION_FILE = '.AGENTS.local.last-session.md';
|
|
29
|
+
const SEAT_DIR_IN_PATH = /^(.*?\/seats\/([A-Za-z][A-Za-z0-9_-]{0,63}))(?:\/|$)/;
|
|
30
|
+
const README_HEAD_MAX = 1200;
|
|
31
|
+
const PRINCIPLE_MAX = 1500;
|
|
32
|
+
const MAX_LAST_SESSION_LINES = 5;
|
|
33
|
+
const LINE_MAX = 200;
|
|
34
|
+
|
|
35
|
+
/** cwd 가 `/seats/<자리>` 아래면 자리 루트 디렉터리와 자리 이름. */
|
|
36
|
+
export function seatDirFromCwd(cwd: string): { seat: string; dir: string } | null {
|
|
37
|
+
const m = SEAT_DIR_IN_PATH.exec(cwd);
|
|
38
|
+
if (!m) return null;
|
|
39
|
+
return { seat: m[2]!.toUpperCase(), dir: m[1]! };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function readHead(path: string, maxChars: number): string | null {
|
|
43
|
+
try {
|
|
44
|
+
if (!statSync(path).isFile()) return null;
|
|
45
|
+
const raw = readFileSync(path, 'utf8');
|
|
46
|
+
if (raw.length <= maxChars) return raw.trim();
|
|
47
|
+
const cut = raw.slice(0, maxChars);
|
|
48
|
+
return `${cut.slice(0, Math.max(0, cut.lastIndexOf('\n'))).trim()}\n…(이하 생략 — 원문을 읽어라)`;
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function findAncestorFile(startDir: string, filename: string): string | null {
|
|
55
|
+
let dir = startDir;
|
|
56
|
+
for (;;) {
|
|
57
|
+
const candidate = join(dir, filename);
|
|
58
|
+
if (existsSync(candidate)) return candidate;
|
|
59
|
+
const parent = dirname(dir);
|
|
60
|
+
if (parent === dir) return null;
|
|
61
|
+
dir = parent;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** 저장소 AGENTS.md 의 «제1원칙» 절에서 요지(북극성·넘버원 룰·SCQA 문법)를 뽑는다. 원문 복제가 아니라 발췌 ⊕ 출처. */
|
|
66
|
+
export function extractFirstPrinciple(agentsMd: string): string | null {
|
|
67
|
+
const lines = agentsMd.split(/\r?\n/);
|
|
68
|
+
const start = lines.findIndex(line => /^##\s.*제1원칙/.test(line));
|
|
69
|
+
if (start < 0) return null;
|
|
70
|
+
let end = lines.length;
|
|
71
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
72
|
+
if (/^##\s/.test(lines[i]!)) { end = i; break; }
|
|
73
|
+
}
|
|
74
|
+
const section = lines.slice(start + 1, end);
|
|
75
|
+
const picked: string[] = [];
|
|
76
|
+
for (let i = 0; i < section.length; i++) {
|
|
77
|
+
const line = section[i]!;
|
|
78
|
+
if (/\*\*북극성\*\*/.test(line)) {
|
|
79
|
+
picked.push(line);
|
|
80
|
+
const next = section[i + 1];
|
|
81
|
+
if (next && next.trim() && !/^\*\*/.test(next.trim())) picked.push(next);
|
|
82
|
+
} else if (/\*\*넘버원 룰\*\*/.test(line) || /\*\*문법 = `SCQA`\*\*/.test(line)) {
|
|
83
|
+
picked.push(line);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const body = (picked.length ? picked : section.filter(l => l.trim() && !l.startsWith('>'))).join('\n').trim();
|
|
87
|
+
if (!body) return null;
|
|
88
|
+
return body.length > PRINCIPLE_MAX ? `${body.slice(0, PRINCIPLE_MAX)}…` : body;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function renderLocalInstructionsTemplate(input: { seat: string; readmeHead: string | null; principle: string | null; at: string }): string {
|
|
92
|
+
const out = [
|
|
93
|
+
`# ${input.seat} 자리 — 로컬 지시 (TUI 가 ${input.at} 에 만들었다 · 사람이 고쳐도 된다)`,
|
|
94
|
+
'',
|
|
95
|
+
`너는 **${input.seat}** 자리의 엘라누스 TUI 다. 이 파일은 git 에 안 올라가는 «이 자리만의» 지시이고, 저장소 공용 지시(AGENTS.md)와 다르면 이 파일이 우선한다.`,
|
|
96
|
+
'',
|
|
97
|
+
'## 자리 정본 (seat-state README 머리)',
|
|
98
|
+
input.readmeHead ?? `- 미관측: ~/elanous-hq/seat-state/${input.seat}/README.md 없음 — 역할은 사람에게 묻고 이 절을 채워라.`,
|
|
99
|
+
'',
|
|
100
|
+
];
|
|
101
|
+
if (input.principle) {
|
|
102
|
+
out.push('## 제1원칙 (요지)', '> 정본 = 저장소 AGENTS.md §제1원칙 — 아래는 발췌다. 어긋나면 정본이 이긴다.', '', input.principle, '');
|
|
103
|
+
}
|
|
104
|
+
out.push(
|
|
105
|
+
'## 시작하면',
|
|
106
|
+
`- 우편함을 읽는다: \`eln msg list --to ${input.seat}\` — 안 읽은 우편 수와 처리할 것을 먼저 말한다.`,
|
|
107
|
+
`- 자리 인계를 읽는다: ~/elanous-hq/seat-state/${input.seat}/HANDOFF.md (있으면).`,
|
|
108
|
+
'- 앵커의 «지난 세션» 조각(TUI 가 `.AGENTS.local.last-session.md` 에 남긴다)의 열린 일을 이어받고, 다음 점검 시각을 정해 말한다.',
|
|
109
|
+
'',
|
|
110
|
+
);
|
|
111
|
+
return out.join('\n');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface SeatLocalDeps {
|
|
115
|
+
home?: string;
|
|
116
|
+
now?: () => Date;
|
|
117
|
+
/** 시험 심 — 생성(wx) 직후, 경쟁 확인 «전»에 불린다(사람이 그 틈에 파일을 만들거나 고치는 경우 재현). */
|
|
118
|
+
afterCreateForTest?: (path: string) => void;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** 자리 디렉터리에서 로컬 지시 파일이 하나도 없으면 템플릿으로 만든다. 결과를 첫 화면 한 줄에 쓴다. */
|
|
122
|
+
/** 경로에 «무엇이든» 있나 — 링크는 대상이 없어도 있다(lstat). */
|
|
123
|
+
function entryPresent(path: string): boolean {
|
|
124
|
+
try { lstatSync(path); return true; } catch { return false; }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function ensureSeatLocalInstructions(cwd: string, deps: SeatLocalDeps = {}): { status: 'created' | 'exists' | 'not-seat' | 'error'; path?: string; missingPrinciple?: boolean } {
|
|
128
|
+
const seatDir = seatDirFromCwd(cwd);
|
|
129
|
+
if (!seatDir) return { status: 'not-seat' };
|
|
130
|
+
const path = join(seatDir.dir, LOCAL_INSTRUCTIONS_FILE);
|
|
131
|
+
try {
|
|
132
|
+
for (const name of [LOCAL_INSTRUCTIONS_FILE, COMPAT_LOCAL_FILE]) {
|
|
133
|
+
const existing = join(seatDir.dir, name);
|
|
134
|
+
// ⛔ «링크 자체»의 존재로 판정한다(lstat) — 대상이 없는 링크도 «있음»이다(existsSync 는 그것을 «없음»으로 본다).
|
|
135
|
+
if (entryPresent(existing)) {
|
|
136
|
+
// ⛔ 덮어쓰기 0 — 제1원칙 절이 없으면 «제안»만 한다(읽을 수 없는 링크면 제안도 안 한다).
|
|
137
|
+
let body = '';
|
|
138
|
+
try { body = readFileSync(existing, 'utf8'); } catch { body = '제1원칙'; }
|
|
139
|
+
const missingPrinciple = !/제1원칙/.test(body);
|
|
140
|
+
debug.log('tui.local-instructions', 'create-skipped', { seat: seatDir.seat, path: existing, reason: 'exists', missingPrinciple });
|
|
141
|
+
return { status: 'exists', path: existing, missingPrinciple };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const home = deps.home ?? homedir();
|
|
145
|
+
const readmeHead = readHead(join(home, 'elanous-hq', 'seat-state', seatDir.seat, 'README.md'), README_HEAD_MAX);
|
|
146
|
+
const agentsPath = findAncestorFile(seatDir.dir, 'AGENTS.md');
|
|
147
|
+
const principle = agentsPath ? extractFirstPrinciple(readFileSync(agentsPath, 'utf8')) : null;
|
|
148
|
+
const text = renderLocalInstructionsTemplate({ seat: seatDir.seat, readmeHead, principle, at: (deps.now?.() ?? new Date()).toISOString() });
|
|
149
|
+
// `wx` = 없을 때만 만든다 — 확인과 쓰기 사이에 사람이 만든 파일도 덮지 않는다.
|
|
150
|
+
writeFileSync(path, text, { flag: 'wx' });
|
|
151
|
+
deps.afterCreateForTest?.(path);
|
|
152
|
+
// 경쟁: 확인과 생성 사이에 사람이 호환 파일을 만들었으면 우리 파일이 그것을 가린다 — 방금 만든 것을 거둔다.
|
|
153
|
+
if (entryPresent(join(seatDir.dir, COMPAT_LOCAL_FILE))) {
|
|
154
|
+
// ⛔ «방금 쓴 내용과 같을 때만» 지운다 — 그 사이 사람이 고쳤으면 사람 문면을 지우지 않고 둘 다 남긴다(관측).
|
|
155
|
+
let unchanged = false;
|
|
156
|
+
try { unchanged = readFileSync(path, 'utf8') === text; } catch { unchanged = false; }
|
|
157
|
+
if (unchanged) rmSync(path, { force: true });
|
|
158
|
+
debug.log('tui.local-instructions', 'create-skipped', { seat: seatDir.seat, path, reason: 'compat-appeared', removedOwn: unchanged });
|
|
159
|
+
return { status: 'exists', path: join(seatDir.dir, COMPAT_LOCAL_FILE), missingPrinciple: false };
|
|
160
|
+
}
|
|
161
|
+
debug.log('tui.local-instructions', 'created', { seat: seatDir.seat, path, chars: text.length, hasReadme: readmeHead !== null, hasPrinciple: principle !== null });
|
|
162
|
+
return { status: 'created', path };
|
|
163
|
+
} catch (err) {
|
|
164
|
+
debug.log('tui.local-instructions', 'create-skipped', { seat: seatDir.seat, path, reason: 'error', error: err instanceof Error ? err.message : String(err) });
|
|
165
|
+
return { status: 'error', path };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ── «지난 세션» 이어쓰기 ────────────────────────────────────────────────
|
|
170
|
+
|
|
171
|
+
export interface SessionMessage {
|
|
172
|
+
role: string;
|
|
173
|
+
content: unknown;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function messageText(content: unknown): string {
|
|
177
|
+
if (typeof content === 'string') return content;
|
|
178
|
+
if (Array.isArray(content)) {
|
|
179
|
+
return content
|
|
180
|
+
.map(block => (block && typeof block === 'object' && (block as { type?: unknown }).type === 'text' ? String((block as { text?: unknown }).text ?? '') : ''))
|
|
181
|
+
.filter(Boolean)
|
|
182
|
+
.join('\n');
|
|
183
|
+
}
|
|
184
|
+
return '';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** 대시보드는 사람 턴을 `Context:\n…\n\nQuestion: <질문>` 으로 감싸 history 에 넣는다(turn-message-runtime.ts) — 질문만 꺼낸다. */
|
|
188
|
+
function userQuestion(text: string): string {
|
|
189
|
+
const marker = '\n\nQuestion: ';
|
|
190
|
+
if (!text.startsWith('Context:') || !text.includes(marker)) return text;
|
|
191
|
+
return text.slice(text.lastIndexOf(marker) + marker.length);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function oneLine(text: string): string {
|
|
195
|
+
const flat = text.replace(/\s+/g, ' ').trim();
|
|
196
|
+
return flat.length > LINE_MAX ? `${flat.slice(0, LINE_MAX - 1)}…` : flat;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** 대화 기록에서 «지난 세션» 5줄 이내. 사람 턴이 없으면 null(쓸 것이 없다). */
|
|
200
|
+
export function summarizeSession(history: readonly SessionMessage[], meta: { endedAt: string; reason: string }): string[] | null {
|
|
201
|
+
const turns = history
|
|
202
|
+
.filter(m => m.role === 'user' || m.role === 'assistant')
|
|
203
|
+
.map(m => ({ role: m.role, text: (m.role === 'user' ? userQuestion(messageText(m.content)) : messageText(m.content)).trim() }))
|
|
204
|
+
.filter(t => t.text);
|
|
205
|
+
const userTurns = turns.filter(t => t.role === 'user');
|
|
206
|
+
if (userTurns.length === 0) return null;
|
|
207
|
+
const lastUserIdx = turns.map(t => t.role).lastIndexOf('user');
|
|
208
|
+
const lastAssistantIdx = turns.map(t => t.role).lastIndexOf('assistant');
|
|
209
|
+
// 마지막 요청에 답하기 «전»에 끝났으면 그 앞 답을 이 요청의 답처럼 적지 않는다.
|
|
210
|
+
const unanswered = lastAssistantIdx < lastUserIdx;
|
|
211
|
+
const lastAnswer = lastAssistantIdx >= 0 ? turns[lastAssistantIdx]!.text : '';
|
|
212
|
+
const answerLines = lastAnswer.split(/\r?\n/).map(l => l.trim()).filter(Boolean);
|
|
213
|
+
const open = answerLines.filter(l => /(다음|남은|열린|후속|미완|대기|TODO|할 일|이어서)/i.test(l)).slice(0, 2);
|
|
214
|
+
const nextCheck = /(\d{1,2}:\d{2})/.exec(open.join(' ') || lastAnswer)?.[1];
|
|
215
|
+
const lines = [
|
|
216
|
+
`- 끝: ${meta.endedAt} · ${meta.reason} · 사람 턴 ${userTurns.length}`,
|
|
217
|
+
unanswered
|
|
218
|
+
? `- 마지막 요청(답 없이 끝남 — 이어서 처리할 일): ${oneLine(userTurns.at(-1)!.text)}`
|
|
219
|
+
: `- 마지막 요청: ${oneLine(userTurns.at(-1)!.text)}`,
|
|
220
|
+
];
|
|
221
|
+
if (answerLines.length) lines.push(`- ${unanswered ? '그 전 답 요지' : '마지막 답 요지'}: ${oneLine(answerLines[0]!)}`);
|
|
222
|
+
const fromPrev = unanswered ? '(그 전 답에서 — 마지막 요청의 후속이 아니다) ' : '';
|
|
223
|
+
lines.push(`- 열린 일: ${open.length ? `${fromPrev}${open.map(oneLine).join(' / ')}` : '미관측(답에 «다음·남은·열린» 줄 없음) — 자리 우편·HANDOFF 로 확인'}`);
|
|
224
|
+
if (nextCheck) lines.push(`- 다음 점검 시각(${unanswered ? '그 전 답에서' : '답에서'}): ${nextCheck}`);
|
|
225
|
+
return lines.slice(0, MAX_LAST_SESSION_LINES);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** «지난 세션» 파일 본문 — 머리 한 줄 ⊕ 요약 줄. */
|
|
229
|
+
export function renderLastSessionFile(lines: readonly string[]): string {
|
|
230
|
+
return `## 지난 세션 (TUI 가 대화 끝마다 갈아 쓴다 · 사람이 고치지 않는 파일)\n${lines.join('\n')}\n`;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** 대화 끝에 «지난 세션»을 TUI 소유 파일에 쓴다(동기 · 종료 경로 · tmp ⊕ rename). 사람 지시 파일은 건드리지 않는다. 실패는 관측만. */
|
|
234
|
+
export function writeLastSession(cwd: string, history: readonly SessionMessage[], reason: string, deps: SeatLocalDeps = {}): 'written' | 'skipped' {
|
|
235
|
+
const seatDir = seatDirFromCwd(cwd);
|
|
236
|
+
if (!seatDir) return 'skipped';
|
|
237
|
+
const path = join(seatDir.dir, LAST_SESSION_FILE);
|
|
238
|
+
let tmp: string | null = null;
|
|
239
|
+
try {
|
|
240
|
+
const lines = summarizeSession(history, { endedAt: (deps.now?.() ?? new Date()).toISOString(), reason });
|
|
241
|
+
if (!lines) {
|
|
242
|
+
debug.log('tui.local-instructions', 'last-session-skipped', { seat: seatDir.seat, reason: 'no-user-turn' });
|
|
243
|
+
return 'skipped';
|
|
244
|
+
}
|
|
245
|
+
// 이 이름이 링크면(누가 심었으면) 따라가 쓰지 않는다.
|
|
246
|
+
if (existsSync(path) && lstatSync(path).isSymbolicLink()) {
|
|
247
|
+
debug.log('tui.local-instructions', 'last-session-skipped', { seat: seatDir.seat, path, reason: 'symlink' });
|
|
248
|
+
return 'skipped';
|
|
249
|
+
}
|
|
250
|
+
const text = renderLastSessionFile(lines);
|
|
251
|
+
tmp = `${path}.tmp-${process.pid}-${randomBytes(6).toString('hex')}`;
|
|
252
|
+
writeFileSync(tmp, text, { flag: 'wx', mode: 0o600 });
|
|
253
|
+
renameSync(tmp, path);
|
|
254
|
+
tmp = null;
|
|
255
|
+
debug.log('tui.local-instructions', 'last-session-written', { seat: seatDir.seat, path, reason, lines: lines.length, chars: text.length });
|
|
256
|
+
return 'written';
|
|
257
|
+
} catch (err) {
|
|
258
|
+
debug.log('tui.local-instructions', 'last-session-skipped', { seat: seatDir.seat, reason: 'error', error: err instanceof Error ? err.message : String(err) });
|
|
259
|
+
return 'skipped';
|
|
260
|
+
} finally {
|
|
261
|
+
if (tmp) { try { if (!lstatSync(tmp).isSymbolicLink()) rmSync(tmp, { force: true }); } catch { /* 없으면 그만 */ } }
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export interface SessionRecorderDeps {
|
|
266
|
+
getCwd: () => string;
|
|
267
|
+
getHistory: () => readonly SessionMessage[];
|
|
268
|
+
onExit?: (fn: () => void) => void;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
let recorder: SessionRecorderDeps | null = null;
|
|
272
|
+
let recordedThisConversation = false;
|
|
273
|
+
// 대화의 기록 대상 디렉터리 — 대화가 «시작될 때» 고정한다(도중 cwd 를 옮겨도 다른 자리 파일에 쓰지 않게).
|
|
274
|
+
let conversationCwd: string | null = null;
|
|
275
|
+
|
|
276
|
+
export function resetSessionRecorderForTest(): void {
|
|
277
|
+
recorder = null;
|
|
278
|
+
recordedThisConversation = false;
|
|
279
|
+
conversationCwd = null;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** 대화 끝 기록 — 같은 대화에서 두 번 쓰지 않는다(`/session new` 뒤 `exit` 등). */
|
|
283
|
+
export function recordSeatSessionEnd(reason: string): void {
|
|
284
|
+
if (!recorder || recordedThisConversation) return;
|
|
285
|
+
const cwd = conversationCwd ?? recorder.getCwd();
|
|
286
|
+
if (writeLastSession(cwd, recorder.getHistory(), reason) === 'written') recordedThisConversation = true;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** 새 대화가 시작됐다 — 기록 대상을 지금 cwd 로 다시 고정하고, 다음 끝에서 다시 쓴다. */
|
|
290
|
+
export function markSeatConversationStarted(): void {
|
|
291
|
+
recordedThisConversation = false;
|
|
292
|
+
conversationCwd = recorder?.getCwd() ?? null;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** 대시보드가 부팅 때 한 번 건다. `/quit`·Ctrl+C·SIGINT/SIGTERM 은 모두 process 'exit' 로 끝난다(tui.ts 핸들러가 process.exit). */
|
|
296
|
+
export function installSeatSessionRecorder(deps: SessionRecorderDeps): void {
|
|
297
|
+
const first = recorder === null;
|
|
298
|
+
recorder = deps;
|
|
299
|
+
conversationCwd = deps.getCwd();
|
|
300
|
+
if (!first) return;
|
|
301
|
+
const onExit = deps.onExit ?? ((fn: () => void) => { process.on('exit', fn); });
|
|
302
|
+
onExit(() => {
|
|
303
|
+
try { recordSeatSessionEnd('exit'); } catch { /* 종료는 언제나 끝까지 간다 */ }
|
|
304
|
+
});
|
|
305
|
+
}
|
|
@@ -272,7 +272,8 @@
|
|
|
272
272
|
// `../index.ts`) instead of importing the type — keeps this module free
|
|
273
273
|
// of circular dependency on dashboard/index.ts.
|
|
274
274
|
|
|
275
|
-
import { tuiNowSlash } from '../../context-bus/context-now-surfaces.js';
|
|
275
|
+
import { renderTuiNow, tuiNowSlash } from '../../context-bus/context-now-surfaces.js';
|
|
276
|
+
import { contextNowInWorker } from '../../context-bus/context-now.js';
|
|
276
277
|
import { handleTuiChatPersona, type TuiChatPersonaSelection } from './chat-persona.js';
|
|
277
278
|
import { createWishCard } from '../../intake-plane/wish-card.js';
|
|
278
279
|
import { CardStore } from '../../task-cards/card-store.js';
|
|
@@ -284,6 +285,8 @@ import { resolveRepositoryDesignCheck } from '../../cli/repo-cli.js';
|
|
|
284
285
|
import { renderDesignCheckLines, type DesignCheckTone } from '../../design/design-check-render.js';
|
|
285
286
|
import { handleDesignPick } from './design-pick.js';
|
|
286
287
|
import { createDecideSlashHandler } from './decide-slash.js';
|
|
288
|
+
import { startSeatBootConversation } from '../seat-boot-preamble.js';
|
|
289
|
+
import { markSeatConversationStarted, recordSeatSessionEnd } from '../seat-local-instructions.js';
|
|
287
290
|
import type { DecisionLedger } from '../../decisions/decision-ledger.js';
|
|
288
291
|
import { listDesignDirections, parseDeclaredDirection } from '../../design/design-directions.js';
|
|
289
292
|
import {
|
|
@@ -343,7 +346,7 @@ import { terminalModalRouter } from '../input/terminal-modal-router.js';
|
|
|
343
346
|
import { termSize, stripAnsi } from '../../tui.js';
|
|
344
347
|
import { SLASH_COMMANDS } from '../../chat/index.js';
|
|
345
348
|
import { buildEssentialHelpLines } from './help-from-registry.js';
|
|
346
|
-
import { HUMAN_MODEL_WORDS, MODEL_CODE_NAMES, humanWordForModel, modelChangeLine, modelOverviewLines, resolveModelChoice } from './model-choices.js';
|
|
349
|
+
import { HUMAN_MODEL_WORDS, MODEL_CODE_NAMES, humanWordForModel, modelChangeLine, modelOverviewLines, modelScopeLine, modelSwitchScope, parseModelSlashArgs, resolveModelChoice } from './model-choices.js';
|
|
347
350
|
import type { FoldMode } from '../../log-entry.js';
|
|
348
351
|
import { resolveDashboardChatMainLogCommand } from '../input/chat-main-log-command.js';
|
|
349
352
|
import {
|
|
@@ -358,7 +361,7 @@ import { debug } from '../../debug/log.js';
|
|
|
358
361
|
import { resolveDebugCompanionTargets } from '../../window/debug-window-consumers.js';
|
|
359
362
|
import { getPromptBankStore, buildPromptInjection } from '../../prompt-bank/index.js';
|
|
360
363
|
import { inspectActiveProvider } from '../../provider-summary.js';
|
|
361
|
-
import { currentRouteDecision, formatRouteDecisionSummary, resolveRouteDecision, type RouteDecision } from '../../llm/route-decision.js';
|
|
364
|
+
import { currentRouteDecision, formatRouteDecisionSummary, resolveRouteDecision, sessionModelPin, setSessionModelPin, type RouteDecision } from '../../llm/route-decision.js';
|
|
362
365
|
import {
|
|
363
366
|
listSessions as sessionListSessions,
|
|
364
367
|
resolveSessionId as sessionResolveId,
|
|
@@ -954,6 +957,8 @@ export interface DashboardSlashContext {
|
|
|
954
957
|
// Fold mode
|
|
955
958
|
getLogFoldMode(): FoldMode;
|
|
956
959
|
setLogFoldMode(mode: FoldMode): void;
|
|
960
|
+
/** #19 — put every static fold in one state; returns how many changed. */
|
|
961
|
+
setAllFolds?(expanded: boolean): number;
|
|
957
962
|
// Solo (chat-only) toggle — flips chatOnlyMode + manages HUD mode segment.
|
|
958
963
|
/** Returns the new chatOnlyMode value after toggle. */
|
|
959
964
|
toggleSolo(): boolean;
|
|
@@ -1071,6 +1076,7 @@ export interface DashboardSlashContext {
|
|
|
1071
1076
|
termSlash: {
|
|
1072
1077
|
/** Line formatters (existing factory output type re-used). */
|
|
1073
1078
|
slashRuntime: DashboardTermSlashRuntime;
|
|
1079
|
+
openNewTerminal(command?: string): void;
|
|
1074
1080
|
|
|
1075
1081
|
/** Terminal session registry (the modal-pty side). */
|
|
1076
1082
|
sessionRegistry: {
|
|
@@ -1413,8 +1419,10 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps, decideLedg
|
|
|
1413
1419
|
ctx.setChatScrollOffset(-1);
|
|
1414
1420
|
});
|
|
1415
1421
|
|
|
1416
|
-
registry.register(['now'], (args, ctx) => {
|
|
1417
|
-
|
|
1422
|
+
registry.register(['now'], async (args, ctx) => {
|
|
1423
|
+
const lines = nowDeps ? tuiNowSlash(args, nowDeps)
|
|
1424
|
+
: renderTuiNow(await contextNowInWorker({ topic: args.join(' ').trim() }));
|
|
1425
|
+
for (const line of lines) ctx.pushChatLine(line);
|
|
1418
1426
|
});
|
|
1419
1427
|
|
|
1420
1428
|
registry.register('loops', async (args, ctx) => {
|
|
@@ -2977,6 +2985,10 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps, decideLedg
|
|
|
2977
2985
|
ctx.setChatScrollOffset(-1);
|
|
2978
2986
|
return;
|
|
2979
2987
|
}
|
|
2988
|
+
if (sub === 'new') {
|
|
2989
|
+
ctx.termSlash.openNewTerminal(args.slice(1).join(' ').trim() || undefined);
|
|
2990
|
+
return;
|
|
2991
|
+
}
|
|
2980
2992
|
if (sub === 'list') {
|
|
2981
2993
|
const alive = sessionRegistry.list();
|
|
2982
2994
|
if (alive.length === 0) {
|
|
@@ -4019,6 +4031,10 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps, decideLedg
|
|
|
4019
4031
|
}
|
|
4020
4032
|
|
|
4021
4033
|
if (seSub === 'new' || seSub === 'clear') {
|
|
4034
|
+
// 🪪 L2-lite — 비우기 «전»에 이 대화의 «지난 세션»을 자리 로컬 지시에 남긴다(실패해도 진행).
|
|
4035
|
+
try {
|
|
4036
|
+
recordSeatSessionEnd(seSub === 'new' ? 'session-new' : 'session-clear');
|
|
4037
|
+
} catch { /* 기록이 새 대화를 막지 않는다 */ }
|
|
4022
4038
|
if (seSub === 'new') {
|
|
4023
4039
|
try {
|
|
4024
4040
|
const { suggestProjectForFolder } = await import('../../project/project-store.js');
|
|
@@ -4044,6 +4060,12 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps, decideLedg
|
|
|
4044
4060
|
ctx.chatLines.push(ctx.success(prev
|
|
4045
4061
|
? ` ✓ cleared history + detached ${prev.slice(0, 8)}`
|
|
4046
4062
|
: ` ✓ cleared history`));
|
|
4063
|
+
// 🪪 L1 — 새 대화 = 새 자리 부트 카드.
|
|
4064
|
+
// ⛔ 정적 import · 동기 호출 — history 를 비운 «같은 틱»에 카드 캐시를 비운다(비동기 대기 틈에 새 턴이 옛 카드를 읽지 않게).
|
|
4065
|
+
try {
|
|
4066
|
+
startSeatBootConversation({ reason: seSub === 'new' ? 'session-new' : 'session-clear' });
|
|
4067
|
+
markSeatConversationStarted();
|
|
4068
|
+
} catch { /* 부트 카드가 새 대화를 막지 않는다 */ }
|
|
4047
4069
|
ctx.setChatScrollOffset(-1);
|
|
4048
4070
|
return;
|
|
4049
4071
|
}
|
|
@@ -4474,6 +4496,22 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps, decideLedg
|
|
|
4474
4496
|
ctx.setChatScrollOffset(-1);
|
|
4475
4497
|
return;
|
|
4476
4498
|
}
|
|
4499
|
+
if (logCommand.kind === 'fold-all') {
|
|
4500
|
+
if (!ctx.logSlash.setAllFolds) {
|
|
4501
|
+
// A host without a fold controller cannot know whether anything is folded — say so, not «nothing».
|
|
4502
|
+
debug.log('log.fold', 'slash-set-all', { expanded: logCommand.expanded, changed: null, reason: 'no-fold-controller' });
|
|
4503
|
+
emitReplyToChat(ctx, ctx.warning(' fold controls are not available in this view'));
|
|
4504
|
+
ctx.setChatScrollOffset(-1);
|
|
4505
|
+
return;
|
|
4506
|
+
}
|
|
4507
|
+
const changed = ctx.logSlash.setAllFolds(logCommand.expanded);
|
|
4508
|
+
debug.log('log.fold', 'slash-set-all', { expanded: logCommand.expanded, changed });
|
|
4509
|
+
emitReplyToChat(ctx, ctx.muted(changed > 0
|
|
4510
|
+
? ` ${logCommand.expanded ? 'unfolded' : 'folded'} ${changed} block${changed === 1 ? '' : 's'}`
|
|
4511
|
+
: ` (nothing to ${logCommand.expanded ? 'unfold' : 'fold'})`));
|
|
4512
|
+
ctx.setChatScrollOffset(-1);
|
|
4513
|
+
return;
|
|
4514
|
+
}
|
|
4477
4515
|
if (logCommand.kind === 'fold') {
|
|
4478
4516
|
const action = resolveDashboardLogFoldAction(logCommand.mode, ctx.logSlash.getLogFoldMode());
|
|
4479
4517
|
if (action.kind === 'set-mode') {
|
|
@@ -5302,9 +5340,10 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps, decideLedg
|
|
|
5302
5340
|
// previews an unpinned request without changing provider/model state.
|
|
5303
5341
|
if (sub === 'route') {
|
|
5304
5342
|
const cfg = getUserConfig();
|
|
5343
|
+
const previewPin = sessionModelPin('dashboard', cfg.llm.provider);
|
|
5305
5344
|
const text = args.slice(1).join(' ').trim();
|
|
5306
5345
|
const decision = text
|
|
5307
|
-
? resolveRouteDecision({ provider: cfg.llm.provider, configuredModel: inspectActiveProvider().model, text, routePolicy: cfg.llm.routePolicy })
|
|
5346
|
+
? resolveRouteDecision({ provider: cfg.llm.provider, configuredModel: inspectActiveProvider().model, text, routePolicy: cfg.llm.routePolicy, ...(previewPin ? { explicitModel: previewPin.model } : {}) })
|
|
5308
5347
|
: currentRouteDecision('dashboard');
|
|
5309
5348
|
ctx.chatLines.push(ctx.accent(`❯ /provider route${text ? '' : ' (current)'}`));
|
|
5310
5349
|
if (!decision) ctx.chatLines.push(ctx.muted(' 아직 이 세션에서 실행된 route가 없습니다. `/provider route <요청>`으로 미리보기 합니다.'));
|
|
@@ -6062,24 +6101,35 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps, decideLedg
|
|
|
6062
6101
|
// /model — 지금 모델(사람 낱말) + 고르기
|
|
6063
6102
|
// /model 빠름|보통|깊음 — 지금 provider 의 budget·better·best 티어 (model-choices.ts)
|
|
6064
6103
|
// /model <코드명> — codex·terra·sol·luna·opus·sonnet·grok (그대로 동작)
|
|
6104
|
+
// /model <x> --global — 설정 파일(전역)에 저장 · /model reset — 세션 핀 해제
|
|
6105
|
+
// ⭐ 기본은 «이 세션» 핀이다(TUI-MODEL-SESSION-SCOPE · 10-14): config 의 llm.model 만 바꾸면 codex 티어 정책이
|
|
6106
|
+
// 그것을 무시해 실제 턴은 그대로 sol 이었다(OPT 21:33). 핀은 다음 턴 explicitModel 로 들어가 정책을 이긴다.
|
|
6065
6107
|
// effort(low/med/high)는 /reasoning. NL 미지원(대표 OK·slash-only).
|
|
6066
|
-
const arg = (args
|
|
6108
|
+
const { arg, global } = parseModelSlashArgs(args);
|
|
6067
6109
|
const curCfg = getUserConfig();
|
|
6068
6110
|
const curProvider = curCfg.llm.provider;
|
|
6069
|
-
const
|
|
6111
|
+
const pin = sessionModelPin('dashboard', curProvider);
|
|
6112
|
+
const curModel = pin?.model ?? curCfg.llm.model;
|
|
6070
6113
|
const curReasoning = effectiveReasoningLevel(curCfg.llm, curProvider, curModel);
|
|
6071
6114
|
if (!arg) {
|
|
6072
6115
|
const [, codes] = modelOverviewLines(curProvider, curModel, curReasoning);
|
|
6073
6116
|
// A model outside the 빠름/보통/깊음 map (codename or custom) says so explicitly instead of dropping the tier slot.
|
|
6074
6117
|
const tierName = humanWordForModel(curProvider, curModel, curReasoning) ?? '단계 밖';
|
|
6075
|
-
ctx.chatLines.push(`지금: ${curModel?.trim() || '기본 모델'} (${tierName} · 생각 ${curReasoning}) · 고르기: /model ${HUMAN_MODEL_WORDS.join(' | ')}`);
|
|
6118
|
+
ctx.chatLines.push(`지금: ${curModel?.trim() || '기본 모델'} (${tierName} · 생각 ${curReasoning}${pin ? ' · 이 세션 핀' : ''}) · 고르기: /model ${HUMAN_MODEL_WORDS.join(' | ')}`);
|
|
6076
6119
|
ctx.chatLines.push(ctx.muted(codes));
|
|
6077
6120
|
ctx.setChatScrollOffset(-1);
|
|
6078
6121
|
return;
|
|
6079
6122
|
}
|
|
6123
|
+
if (arg === 'reset') {
|
|
6124
|
+
setSessionModelPin('dashboard', null);
|
|
6125
|
+
debug.log('llm.model-choice', 'session-pin-cleared', { hadPin: pin !== null, configModel: curCfg.llm.model ?? null }, { level: 'info' });
|
|
6126
|
+
ctx.chatLines.push(ctx.muted(`/model reset: 세션 핀 ${pin ? `해제 (${pin.model})` : '없음'} — 다음 턴은 설정·정책대로`));
|
|
6127
|
+
ctx.setChatScrollOffset(-1);
|
|
6128
|
+
return;
|
|
6129
|
+
}
|
|
6080
6130
|
const resolution = resolveModelChoice(arg, curProvider);
|
|
6081
6131
|
if (resolution.kind === 'needs-provider') {
|
|
6082
|
-
debug.log('
|
|
6132
|
+
debug.log('llm.model-choice', 'human-word-needs-provider', { word: resolution.word, provider: curProvider });
|
|
6083
6133
|
ctx.chatLines.push(ctx.muted(`/model ${resolution.word}: provider 가 auto 라 고를 사다리가 없다 — /provider 로 먼저 하나를 고르거나 코드명(${MODEL_CODE_NAMES.join('/')})을 쓴다.`));
|
|
6084
6134
|
ctx.setChatScrollOffset(-1);
|
|
6085
6135
|
return;
|
|
@@ -6090,29 +6140,51 @@ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps, decideLedg
|
|
|
6090
6140
|
return;
|
|
6091
6141
|
}
|
|
6092
6142
|
const { target } = resolution;
|
|
6143
|
+
const scope = modelSwitchScope(target.provider, curProvider, global);
|
|
6144
|
+
if (scope === 'needs-global') {
|
|
6145
|
+
ctx.chatLines.push(ctx.muted(`/model ${arg}: provider 가 ${curProvider} → ${target.provider} 로 바뀌는 선택은 세션 핀이 안 된다 — /model ${arg} --global 로 설정에 저장한다.`));
|
|
6146
|
+
ctx.setChatScrollOffset(-1);
|
|
6147
|
+
return;
|
|
6148
|
+
}
|
|
6093
6149
|
// A human word picks a whole tier (model ⊕ reasoning, like /reasoning it clears the codex override);
|
|
6094
|
-
// a code name changes the model only.
|
|
6150
|
+
// a code name changes the model only. Reasoning has no per-turn override, so only --global sets it.
|
|
6095
6151
|
const tierReasoning = resolution.kind === 'human' ? resolution.reasoningLevel : undefined;
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6152
|
+
if (scope === 'global') {
|
|
6153
|
+
saveUserConfig({
|
|
6154
|
+
...curCfg,
|
|
6155
|
+
llm: {
|
|
6156
|
+
...curCfg.llm,
|
|
6157
|
+
provider: target.provider,
|
|
6158
|
+
model: target.model,
|
|
6159
|
+
...(tierReasoning ? { reasoningLevel: tierReasoning, codexReasoning: undefined } : {}),
|
|
6160
|
+
},
|
|
6161
|
+
});
|
|
6162
|
+
reloadUserConfig();
|
|
6163
|
+
if (tierReasoning) ctx.refreshReasoningHudSegment();
|
|
6164
|
+
}
|
|
6165
|
+
// --global 도 이 세션은 핀으로 «즉시» 반영한다 — config 만 쓰면 codex 티어 정책이 configuredModel 을
|
|
6166
|
+
// 무시해 다음 턴에 안 먹는다(1R 리뷰 mf). 다른 세션은 그 세션의 routePolicy 를 따른다.
|
|
6167
|
+
setSessionModelPin('dashboard', { provider: target.provider, model: target.model });
|
|
6168
|
+
// 감사 한 줄 — 종전 범주 `dashboard.model` 은 렌더 접두(`dashboard`)라 기본 음소거돼 로그 스토어에 0회였다
|
|
6169
|
+
// (src/mss/logging/render-categories.ts). 판정 이벤트는 렌더 밖 범주에 둔다.
|
|
6170
|
+
debug.log('llm.model-choice', 'switch', {
|
|
6171
|
+
scope,
|
|
6108
6172
|
via: resolution.kind,
|
|
6109
6173
|
choice: resolution.kind === 'human' ? resolution.tier : resolution.name,
|
|
6110
|
-
from: { provider: curProvider, model: curModel ?? null },
|
|
6174
|
+
from: { provider: curProvider, model: curModel ?? null, pinned: pin !== null },
|
|
6111
6175
|
to: target,
|
|
6112
|
-
reasoning: tierReasoning ?? null,
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6176
|
+
reasoning: scope === 'global' ? (tierReasoning ?? null) : null,
|
|
6177
|
+
configWritten: scope === 'global',
|
|
6178
|
+
}, { level: 'info' });
|
|
6179
|
+
// 세션 범위는 생각 깊이를 안 바꾼다 — 모델 줄에 티어의 깊이를 «바뀐 값»처럼 쓰지 않고, 남는 깊이를 말한다
|
|
6180
|
+
// (2R 리뷰 — 한 응답 안의 «생각 medium» 과 «생각 깊이는 그대로 high» 모순).
|
|
6181
|
+
if (scope === 'session' && resolution.kind === 'human') {
|
|
6182
|
+
const { reasoningLevel: _tierReasoning, ...modelOnly } = resolution;
|
|
6183
|
+
ctx.chatLines.push(`${modelChangeLine({ provider: curProvider, model: curModel, reasoning: curReasoning }, modelOnly)} · 생각 ${curReasoning} 그대로`);
|
|
6184
|
+
} else {
|
|
6185
|
+
ctx.chatLines.push(modelChangeLine({ provider: curProvider, model: curModel, reasoning: curReasoning }, resolution));
|
|
6186
|
+
}
|
|
6187
|
+
ctx.chatLines.push(ctx.muted(modelScopeLine(scope, scope === 'session' && tierReasoning ? { tier: tierReasoning, current: curReasoning } : undefined)));
|
|
6116
6188
|
ctx.setChatScrollOffset(-1);
|
|
6117
6189
|
});
|
|
6118
6190
|
|
|
@@ -123,3 +123,38 @@ export function modelChangeLine(
|
|
|
123
123
|
const providerNote = resolution.target.provider === before.provider ? '' : ` · provider ${resolution.target.provider}`;
|
|
124
124
|
return `모델: ${currentLabel(before.provider, before.model, before.reasoning)} → ${after} (${resolution.target.model}${reasoningNote})${providerNote}`;
|
|
125
125
|
}
|
|
126
|
+
|
|
127
|
+
/** `/model` arguments: the choice word plus the `--global` flag (TUI-MODEL-SESSION-SCOPE · 10-14). */
|
|
128
|
+
export function parseModelSlashArgs(args: readonly string[]): { arg: string; global: boolean } {
|
|
129
|
+
const global = args.some((a) => a.trim().toLowerCase() === '--global');
|
|
130
|
+
const arg = args.find((a) => !a.trim().startsWith('--'))?.trim().toLowerCase() ?? '';
|
|
131
|
+
return { arg, global };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Where a `/model` choice lands. The default is this TUI session only (a pin that the next turn sends as an
|
|
136
|
+
* explicit model, so it beats the Codex tier policy); `--global` writes config. A choice on another provider
|
|
137
|
+
* can't be a session pin — the turn carries a model, not a provider — so it needs `--global`.
|
|
138
|
+
*/
|
|
139
|
+
export function modelSwitchScope(
|
|
140
|
+
targetProvider: LLMProviderName,
|
|
141
|
+
currentProvider: LLMProviderName,
|
|
142
|
+
global: boolean,
|
|
143
|
+
): 'session' | 'global' | 'needs-global' {
|
|
144
|
+
if (global) return 'global';
|
|
145
|
+
return targetProvider === currentProvider ? 'session' : 'needs-global';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** The muted line under a switch: what scope it took and when it applies — no promise the code doesn't keep. */
|
|
149
|
+
export function modelScopeLine(
|
|
150
|
+
scope: 'session' | 'global',
|
|
151
|
+
reasoning?: { tier: ReasoningLevel; current: ReasoningLevel },
|
|
152
|
+
): string {
|
|
153
|
+
const where = scope === 'session'
|
|
154
|
+
? ' └─ 이 세션만 · 다음 턴부터 · 설정 파일은 그대로 (전역은 /model <이름> --global · 해제 /model reset)'
|
|
155
|
+
: ' └─ 설정 파일(전역)에 저장 · 이 세션은 다음 턴부터 · 다른 세션은 그 세션의 routePolicy 를 따른다 (codex 기본 정책이면 단계 모델이 이긴다)';
|
|
156
|
+
const think = reasoning && reasoning.tier !== reasoning.current
|
|
157
|
+
? ` · 생각 깊이는 그대로 ${reasoning.current} (이 단계는 ${reasoning.tier} — /reasoning ${reasoning.tier})`
|
|
158
|
+
: '';
|
|
159
|
+
return where + think;
|
|
160
|
+
}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
|
|
3
|
+
/** The workdir is the source of truth for a seat shell; env is only a fallback. */
|
|
4
|
+
export function resolveTuiShellSeat(cwd: string, coordId?: string): string {
|
|
5
|
+
const parts = resolve(cwd).split(/[\\/]/);
|
|
6
|
+
const seatIndex = parts.lastIndexOf('seats');
|
|
7
|
+
const fromPath = seatIndex >= 0 ? parts[seatIndex + 1] : undefined;
|
|
8
|
+
const valid = (value: string | undefined): value is string =>
|
|
9
|
+
value !== undefined && /^[A-Za-z0-9_-]{1,64}$/.test(value);
|
|
10
|
+
if (valid(fromPath)) return fromPath;
|
|
11
|
+
const fromEnv = coordId?.trim();
|
|
12
|
+
return valid(fromEnv) ? fromEnv : 'unknown';
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
export interface DashboardPersistedSessionEntry {
|
|
2
16
|
id: string;
|
|
3
17
|
title: string;
|
|
@@ -109,6 +123,7 @@ export function createDashboardTermSlashRuntime(
|
|
|
109
123
|
'',
|
|
110
124
|
deps.accent('\u276f /term'),
|
|
111
125
|
deps.muted('Usage:'),
|
|
126
|
+
deps.muted(' /term new [command] Open a shell PTY (Ctrl+Shift+T or Alt+T).'),
|
|
112
127
|
deps.muted(' /term list List all alive sessions (fg / bg / exited).'),
|
|
113
128
|
deps.muted(' /term attach <id> Bring a backgrounded session to foreground.'),
|
|
114
129
|
deps.muted(' /term detach Send foreground session to background (PTY survives).'),
|