elanous 0.2.40 → 0.2.41
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/README.md +7 -7
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → GiOLWmt4MqDZePubBjA4Q}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +149 -0
- package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +36 -0
- package/apps/pwa/out/_next/static/chunks/{9184.45afbf44fec87574.js → 1178.1aa9cad0e7695427.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2829-734fe8bf2eee7347.js → 1197-54da59d250a6e476.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6749.0744ce6eb08d40e9.js → 1219.7e17964e0e7cd8e5.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +287 -0
- package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +90 -0
- package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1765.679b29625c8e88d4.js +77 -0
- package/apps/pwa/out/_next/static/chunks/{2226.2cf61ec781827219.js → 1800.f7ff51dc4978a958.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9175.2de5209a5ce6f68a.js → 2073.689dcb2680113d76.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +1 -0
- package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5383.bdfa5d886e39a826.js → 2263.e09b6edea33bad2d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9069.657590a84afb8fac.js → 2743.5d3f76948be32b34.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{6624.981ef7caeb680560.js → 2773.0e80b9d325fb5635.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4864a2ca.1c1c280a7772c5e5.js → 2fdf2931.b431eee4fb468bc3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9189505a.980427ac048c8c60.js → 2fe2c302.41b517f88d6fe502.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9992.07ce73c10bd5e6a1.js → 3097.864e92bdaa2f4d15.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3230-49298c3b73ef2268.js +1 -0
- package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +74 -0
- package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b84cad00.594027ebe0531fe2.js → 385e4574.e9886ab32759eda3.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4133.2056bb4d78f621af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8086.1ab9103c41be884f.js → 4156.ba4de4a3664f04b4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +148 -0
- package/apps/pwa/out/_next/static/chunks/{1281.d81877e35b9068f4.js → 4527.a69f2894d1bc9f4a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{8357.1aaa713b052a78b1.js → 4667.97e31aa38c95c475.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/{5436.fdf6fa8ae3e9588d.js → 4702.4a4adc1f16d7c93b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +94 -0
- package/apps/pwa/out/_next/static/chunks/{4769.9fd582071301f382.js → 5159.115f1c2ca471386c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/530.d26346e18089640a.js +115 -0
- package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{d8de0de2-dd0f4ac8e5ab1832.js → 53aeb4ee-51c92f8d683f5220.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6257.c0037b8949239f5e.js → 5471.1e611302ed3a7c53.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2566.beaffc3a5e1fcd2e.js → 5574.f35accf4f132b29d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{2066.a77257c8c350770a.js → 5744.b9415e18ad623100.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5892.2526d962339662d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4351.0f37a6db2b34d50b.js → 5937.c2df9e3447e1f667.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +286 -0
- package/apps/pwa/out/_next/static/chunks/{6051-0ae955eedb10adb9.js → 5947-135e26537d80a6b9.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{3746-f80a78f220bf37b5.js → 5964-7e21164a8f2cf0ce.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +27 -0
- package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +62 -0
- package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{2047.8f23e210995d4548.js → 6874.d5cf7eb8edb2cabe.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +122 -0
- package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7191.fdc955f7d96064a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8272-025653884f9645d2.js → 8050-9b364bdef8f71927.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/83184dcd-0ee6247ff41eb3f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{2281-b8cede695c6c650e.js → 8464-e24f10451b658aac.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5622.94893f5aea7185d0.js → 8880.64c445592f04acaf.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1452.162bb2d9d699e82a.js → 8981.c706964c8ba27aff.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{470.51a72a2348306455.js → 9048.212083de42d25be3.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2177.df8547f9d7215c4e.js → 9507.7026657a2f47eb64.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +93 -0
- package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7515.1ad6efe157fa4448.js → 9579.4a8169600fff2058.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{2499.02fbfd18126c10c0.js → 9834.63ab2bbc3153172e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9869.81a1e24ca682d5a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{409c787b.e48c5bec8ec10456.js → a0a01613.6d1cca322238d7fe.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6cc1d1d6.9a98dd4622f1afc6.js → addc2b32.8c4ff8f0aefe987d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-ba957ff875a026a0.js → page-14949db884bfa672.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-40f9e19149024298.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a142dfb0331a05f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{c696986b.5dc8bb1143af16d1.js → b2271e54.c1de3347976e90b0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{ca3702f8.2913182e73889fa2.js → c0c1a699.0ba79f97005965d4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.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/bin/elanous.mjs +6 -1
- package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
- package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
- package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
- package/graphs/demo/persona-teacher/recipes.yaml +17 -0
- package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
- package/graphs/overlays/stop-heal-ladder.yaml +23 -2
- package/graphs/release/release-loop.yaml +3 -1
- package/graphs/units/gate/gate.yaml +20 -0
- package/graphs/units/git/git.yaml +26 -0
- package/graphs/units/implement/implement.yaml +19 -0
- package/graphs/units/landing/landing.yaml +18 -0
- package/graphs/units/review/review.yaml +20 -0
- package/graphs/units/verbs/recipes.yaml +3 -0
- package/graphs/units/verbs/research.yaml +20 -0
- package/graphs/work/research-report.yaml +11 -1
- package/package.json +1 -1
- package/scripts/disk-steward.ts +46 -0
- package/scripts/fleet/node-setup.sh +50 -0
- package/scripts/graph-units/verbs/research.ts +55 -0
- package/scripts/llm-cost-ledger.ts +179 -8
- package/scripts/measure-nl-routing-corpus.ts +10 -2
- package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
- package/scripts/public-copy-lint.ts +163 -19
- package/scripts/ratchets/train-side-invariants.sh +0 -1
- package/scripts/release-loop/gate-autoheal.ts +117 -0
- package/scripts/release-loop/gate-baseline-receipt.ts +8 -1
- package/scripts/release-loop/gate-diff.ts +22 -3
- package/scripts/release-loop/gate-node.ts +205 -17
- package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
- package/scripts/release-loop/gate-triage-node.ts +70 -10
- package/scripts/release-loop/resume-release.ts +247 -15
- package/scripts/release-loop/traffic-node.ts +6 -3
- package/scripts/release-loop/unattended-release.ts +4 -2
- package/scripts/shadow-authoring-probe.ts +20 -0
- package/scripts/ux-sim.ts +19 -2
- package/src/acp/core-turn-bridge.ts +86 -4
- package/src/agent-substrate/self-review-cli.ts +91 -29
- package/src/auto-research/research-turn.ts +10 -1
- package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
- package/src/boot/daemon-tools/self-implement.ts +46 -9
- package/src/budget/shadow-arms.ts +52 -0
- package/src/chat/pickers/state.ts +7 -1
- package/src/cli/log-event-names.ts +5 -0
- package/src/cli/mcp-login.ts +8 -18
- package/src/cli/msg-cli.ts +57 -1
- package/src/cli/pr-land-heavy-remote.ts +15 -9
- package/src/cli/release-cli.ts +27 -1
- package/src/cli/sim-cli.ts +7 -1
- package/src/cli/tasks-cli.ts +5 -4
- package/src/codex/models.ts +30 -15
- package/src/core-turn/run-core-turn.ts +3 -0
- package/src/core-turn/run-goal-loop.ts +88 -2
- package/src/dashboard/acp-boot.ts +72 -3
- package/src/dashboard/index.ts +6 -0
- package/src/dashboard/turn-preamble.ts +12 -1
- package/src/disk-steward/judge.ts +73 -0
- package/src/disk-steward/ledger.ts +122 -0
- package/src/disk-steward/steward.ts +373 -0
- package/src/domains/guardian-tick.ts +191 -2
- package/src/graph-runner/graph-cli.ts +21 -0
- package/src/graph-runner/in-process-registry.ts +37 -0
- package/src/graph-runner/runner.ts +33 -3
- package/src/grounding/ref-index.ts +19 -0
- package/src/grounding/sources-cli.ts +9 -1
- package/src/harness/harness-cli-command.ts +267 -14
- package/src/harness/harness-incidents.ts +312 -7
- package/src/harness/harness-space.ts +15 -1
- package/src/harness/progress-worker-entry.ts +59 -0
- package/src/harness/progress-worker-runtime.ts +11 -0
- package/src/index.ts +18 -2
- package/src/instance/dev-project.ts +25 -0
- package/src/intelligence-map/model-alias.ts +6 -5
- package/src/intelligence-map/model-catalog.ts +59 -2
- package/src/llm/model-defaults.ts +4 -4
- package/src/llm.ts +42 -11
- package/src/loops/orchestrator/tick.ts +48 -0
- package/src/mcp/mcp-oauth.ts +3 -1
- package/src/model-tier/llm-tier-map.ts +9 -9
- package/src/model-tier/turn-tier.ts +1 -1
- package/src/msg/msg-mirror-github.ts +80 -0
- package/src/msg/msg-mirror-policy.ts +61 -0
- package/src/msg/msg-mirror-runner.ts +219 -0
- package/src/msg/msg-mirror-state.ts +33 -0
- package/src/msg/msg-store.ts +11 -0
- package/src/output-truncation.ts +41 -12
- package/src/project/project-store.ts +48 -1
- package/src/release-loop/gate-host-reservation.ts +144 -0
- package/src/release-loop/release-schedule.ts +90 -1
- package/src/research/bloom-exemplars.ts +135 -0
- package/src/self-dev/ask-launch-flow.ts +39 -25
- package/src/self-dev/dev-cli.ts +17 -17
- package/src/self-dev/graph-front-nodes.ts +23 -0
- package/src/self-dev/launch-preflight.ts +9 -4
- package/src/self-dev/orchestrate.ts +15 -0
- package/src/self-dev/run-supervisor.ts +185 -3
- package/src/self-dev/run-types.ts +3 -0
- package/src/self-implement/gate-artifacts.ts +13 -0
- package/src/self-implement/gate-cli.ts +54 -24
- package/src/self-implement/gate-remote.ts +23 -5
- package/src/self-implement/goal-author-clarification.ts +31 -12
- package/src/self-implement/goal-author.ts +77 -5
- package/src/self-implement/graph-stage-units.ts +172 -0
- package/src/self-implement/graph-templates.ts +162 -1
- package/src/self-implement/graph-variant.ts +37 -4
- package/src/self-implement/host-regate.ts +4 -4
- package/src/self-implement/knowhow-pack.ts +38 -0
- package/src/self-implement/orchestrator.ts +235 -21
- package/src/self-implement/run-ledger.ts +64 -6
- package/src/self-implement/run-stop.ts +21 -2
- package/src/self-implement/running-runs.ts +35 -12
- package/src/self-implement/self-implement-cli.ts +36 -4
- package/src/self-implement/stop-autoheal-operational.ts +43 -0
- package/src/self-implement/stop-autoheal.ts +15 -6
- package/src/session/chat.ts +31 -54
- package/src/session/request-size-guard.ts +123 -0
- package/src/sidetab-core/model.ts +136 -0
- package/src/task-agent/parent-host.ts +14 -1
- package/src/task-agent/task-hand.ts +4 -1
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +43 -0
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +116 -16
- package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
- package/src/tui/entry.ts +10 -3
- package/src/tui/sidetab/list.ts +45 -0
- package/src/tui/sidetab/nl-tool.ts +2 -136
- package/src/tui/sidetab/peek.ts +52 -0
- package/src/tui-client/dashboard-session.ts +3 -0
- package/src/user-config.ts +11 -5
- package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
- package/src/ux-sim/fault-pod-child-result.ts +42 -0
- package/src/ux-sim/release-sim-rig.ts +262 -0
- package/src/ux-sim/seminar-rehearsal.ts +109 -0
- package/src/ux-sim/subagent-tools-device.ts +2 -2
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1060.014f1f01a17aec26.js +0 -115
- package/apps/pwa/out/_next/static/chunks/1350.59f40e39e02d91b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +0 -286
- package/apps/pwa/out/_next/static/chunks/1537-6bb97b5214928ea9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +0 -90
- package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +0 -104
- package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2522.f2766b76d22c8bdf.js +0 -34
- package/apps/pwa/out/_next/static/chunks/261.0d471e8aded799f3.js +0 -226
- package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +0 -27
- package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2774-719820e3f5b2a3eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +0 -1
- package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3330.7443183b7e6fdbdf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +0 -24
- package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +0 -77
- package/apps/pwa/out/_next/static/chunks/3b355b3d.6f73c98bf6f9c749.js +0 -122
- package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +0 -36
- package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +0 -287
- package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +0 -1
- package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +0 -74
- package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +0 -8
- package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +0 -62
- package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +0 -94
- package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +0 -148
- package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7219-15bdd9a80661af8e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +0 -93
- package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7611.85f045bf232053ac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8099.1cccf31c1baa7e1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8d173e38.18a2f7b4e1848bdb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-4edb8df90f4537ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-83d27757e2b8060a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-fca2e59a81744d9e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-139d722de1dcd6c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-ccde99f07aaf71f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +0 -1
- package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +0 -1
- package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
- /package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → GiOLWmt4MqDZePubBjA4Q}/_ssgManifest.js +0 -0
package/src/user-config.ts
CHANGED
|
@@ -1156,6 +1156,8 @@ export interface HarnessBudgetGateConfig {
|
|
|
1156
1156
|
}
|
|
1157
1157
|
|
|
1158
1158
|
export interface SelfImplementToolConfig {
|
|
1159
|
+
/** Explicit opt-in for the needs-human reason-specific automatic repair goal. Defaults off. */
|
|
1160
|
+
supervisor?: { reasonRepair?: boolean };
|
|
1159
1161
|
/** Absolute root that holds per-repository child worktree directories. */
|
|
1160
1162
|
worktreeRoot: string;
|
|
1161
1163
|
/** Self-implement children receive a derived isolated universe by default; `inherit` keeps the parent's universe. */
|
|
@@ -1292,7 +1294,7 @@ const TOOLS_DEFAULTS: ToolsConfig = {
|
|
|
1292
1294
|
selfOrchestrate: {},
|
|
1293
1295
|
nativeStructure: { enabled: false },
|
|
1294
1296
|
// 대표 결정(2026-07-26): 오토 선호 — 기본 ON.
|
|
1295
|
-
selfImplement: { worktreeRoot: join(homedir(), '.elanous', 'worktrees'), childInstanceMode: 'isolated', prApprovalDelivery: 'terminal' as const, observeOnly: false, goalRecordInDoc: true, fabricDecompose: false, fabricDecomposeAutoPathThreshold: 5, autoOpenPr: true, autoStop: { enabled: true, minRung: 2 }, autoAssist: { enabled: true, minRung: 2 }, screenStallTermination: { enabled: true, minRung: 2 }, reworkBudget: { shadowStop: false, maxRounds: 3 }, decompositionShadow: { enabled: false }, clarificationEscalation: { enabled: false } },
|
|
1297
|
+
selfImplement: { worktreeRoot: join(homedir(), '.elanous', 'worktrees'), childInstanceMode: 'isolated', prApprovalDelivery: 'terminal' as const, observeOnly: false, goalRecordInDoc: true, fabricDecompose: false, fabricDecomposeAutoPathThreshold: 5, autoOpenPr: true, supervisor: { reasonRepair: false }, autoStop: { enabled: true, minRung: 2 }, autoAssist: { enabled: true, minRung: 2 }, screenStallTermination: { enabled: true, minRung: 2 }, reworkBudget: { shadowStop: false, maxRounds: 3 }, decompositionShadow: { enabled: false }, clarificationEscalation: { enabled: false } },
|
|
1296
1298
|
};
|
|
1297
1299
|
|
|
1298
1300
|
// ── Debug ────────────────────────────────────────────────────────────
|
|
@@ -2649,6 +2651,10 @@ function parseToolsConfig(raw: unknown): ToolsConfig {
|
|
|
2649
2651
|
const selfImplRaw = (root.selfImplement && typeof root.selfImplement === 'object' && !Array.isArray(root.selfImplement))
|
|
2650
2652
|
? root.selfImplement as Record<string, unknown>
|
|
2651
2653
|
: {};
|
|
2654
|
+
const supervisorRaw = selfImplRaw.supervisor && typeof selfImplRaw.supervisor === 'object' && !Array.isArray(selfImplRaw.supervisor)
|
|
2655
|
+
? selfImplRaw.supervisor as Record<string, unknown>
|
|
2656
|
+
: {};
|
|
2657
|
+
const supervisor = { reasonRepair: supervisorRaw.reasonRepair === true };
|
|
2652
2658
|
const observeOnly = typeof selfImplRaw.observeOnly === 'boolean'
|
|
2653
2659
|
? selfImplRaw.observeOnly
|
|
2654
2660
|
: TOOLS_DEFAULTS.selfImplement.observeOnly;
|
|
@@ -2807,7 +2813,7 @@ function parseToolsConfig(raw: unknown): ToolsConfig {
|
|
|
2807
2813
|
runDevHarness,
|
|
2808
2814
|
selfOrchestrate,
|
|
2809
2815
|
nativeStructure,
|
|
2810
|
-
selfImplement: { worktreeRoot, childInstanceMode, prApprovalDelivery, observeOnly, goalRecordInDoc, goalAuthorPersistentGrounding, fabricDecompose, fabricDecomposeAutoPathThreshold, autoOpenPr, draftOnStop, salvageRetention, autoStop, autoAssist, screenStallTermination, reworkBudget, decompositionShadow, clarificationEscalation, ...(childLlm ? { childLlm } : {}), ...(escalateChild && Object.keys(escalateChild).length ? { escalateChild } : {}), ...(selfImplRaw.podChildDefault !== undefined ? { podChildDefault: selfImplRaw.podChildDefault } : {}), ...(runTtlHours !== undefined ? { runTtlHours } : {}), ...(draftSweepCloseCap !== undefined ? { draftSweepCloseCap } : {}), ...(runTtl ? { runTtl } : {}), ...(autoheal ? { autoheal } : {}) },
|
|
2816
|
+
selfImplement: { worktreeRoot, childInstanceMode, prApprovalDelivery, observeOnly, goalRecordInDoc, goalAuthorPersistentGrounding, fabricDecompose, fabricDecomposeAutoPathThreshold, autoOpenPr, supervisor, draftOnStop, salvageRetention, autoStop, autoAssist, screenStallTermination, reworkBudget, decompositionShadow, clarificationEscalation, ...(childLlm ? { childLlm } : {}), ...(escalateChild && Object.keys(escalateChild).length ? { escalateChild } : {}), ...(selfImplRaw.podChildDefault !== undefined ? { podChildDefault: selfImplRaw.podChildDefault } : {}), ...(runTtlHours !== undefined ? { runTtlHours } : {}), ...(draftSweepCloseCap !== undefined ? { draftSweepCloseCap } : {}), ...(runTtl ? { runTtl } : {}), ...(autoheal ? { autoheal } : {}) },
|
|
2811
2817
|
};
|
|
2812
2818
|
}
|
|
2813
2819
|
|
|
@@ -6344,11 +6350,11 @@ export const PROVIDER_DEFAULT_MODEL: Record<LLMProviderName, string> = {
|
|
|
6344
6350
|
// ⛔ openai(API 키)는 gpt-4o 그대로 — `gpt-6-*` 는 openai-codex 계열이라 openai 로 부르면 호환 판정이 거부한다(09-23 대표 · 같은 날 되돌림).
|
|
6345
6351
|
anthropic: 'claude-opus-5-5',
|
|
6346
6352
|
openai: 'gpt-4o',
|
|
6347
|
-
//
|
|
6348
|
-
//
|
|
6353
|
+
// 2026-10-28: GPT-6.1 Terra is the current recommended Codex default.
|
|
6354
|
+
// `llm.ts` avoids importing this UI-facing module, so keep its local default aligned here.
|
|
6349
6355
|
// ⚠️ `llm.ts` 에서 import 하지 «않는다» — 이 파일은 UI 소비자가 CLI 표면을 안 끌어오게
|
|
6350
6356
|
// «일부러» 독립돼 있다(이 상수의 머리말). ⇒ 값을 맞추고 «자»로 묶는다.
|
|
6351
|
-
'openai-codex': 'gpt-6-
|
|
6357
|
+
'openai-codex': 'gpt-6.1-terra',
|
|
6352
6358
|
// ⛔ 2026-08-18: 'grok-4-1-fast' 는 «200 OK 로 응답하지만 실제로는 grok-4.3 이 도는»
|
|
6353
6359
|
// 레거시 별칭이었다(xAI 실호출 대조). 실물 flagship 으로 고친다.
|
|
6354
6360
|
grok: 'grok-4.7',
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { debug } from '../debug/log.js';
|
|
5
|
+
import { superviseRun, type SupervisorJobResult, type SupervisorStopReason } from '../self-dev/run-supervisor.js';
|
|
6
|
+
|
|
7
|
+
const CASES = [
|
|
8
|
+
{ reason: 'missing-path', runId: 'run-a4117f90-20261028-0000-4000-8000-000000000001',
|
|
9
|
+
piece: { taskId: 'missing-path-piece', feature: 'missing path piece', status: 'failed', stage: 'error',
|
|
10
|
+
targetPaths: ['src/gone.ts'],
|
|
11
|
+
error: { code: 'ENOENT', message: "ENOENT: no such file or directory, open 'src/gone.ts'" } }, goalText: '없는 경로를 다시 접지한다' },
|
|
12
|
+
{ reason: 'scope-expansion', runId: 'run-b2aa6c1e-20261028-0000-4000-8000-000000000002',
|
|
13
|
+
piece: { taskId: 'scope-expansion-piece', feature: 'scope expansion piece', status: 'failed', stage: 'error',
|
|
14
|
+
error: { code: 'SCOPE_OUTSIDE', message: 'changed files outside the goal target paths' },
|
|
15
|
+
changedFiles: ['src/other/expanded.ts'], targetPaths: ['src/self-dev/run-supervisor.ts'] }, goalText: '범위 확장을 좁힌다' },
|
|
16
|
+
{ reason: 'step-timeout', runId: 'run-c928719f-20261028-0000-4000-8000-000000000003',
|
|
17
|
+
piece: { taskId: 'step-timeout-piece', feature: 'step timeout piece', status: 'failed', stage: 'timed-out',
|
|
18
|
+
targetPaths: ['src/self-dev/run-supervisor.ts'],
|
|
19
|
+
error: { code: 'ETIMEDOUT', message: 'review step exceeded its budget' } }, goalText: '좁은 시험' },
|
|
20
|
+
{ reason: 'no-piece', runId: 'run-d31870a2-20261028-0000-4000-8000-000000000004',
|
|
21
|
+
piece: { taskId: 'no-piece-piece', feature: 'no piece piece', status: 'failed', stage: 'error',
|
|
22
|
+
targetPaths: ['src/self-dev/run-supervisor.ts'],
|
|
23
|
+
error: { code: 'BOOM', message: 'TypeError: undefined is not a function' } }, goalText: '조각 없이 실패했다' },
|
|
24
|
+
] as const;
|
|
25
|
+
|
|
26
|
+
export interface NeedsHumanReasonRepairSimulationCase {
|
|
27
|
+
reason: typeof CASES[number]['reason'];
|
|
28
|
+
runId: string;
|
|
29
|
+
taskId: string;
|
|
30
|
+
goalText: string;
|
|
31
|
+
reruns: number;
|
|
32
|
+
repairGoal?: string;
|
|
33
|
+
stopReason?: SupervisorStopReason;
|
|
34
|
+
why?: string;
|
|
35
|
+
events: Array<{ event: string; data: Record<string, unknown> }>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Runs the production supervisor with one injected failure per repair reason. */
|
|
39
|
+
export async function simulateNeedsHumanReasonRepair(): Promise<NeedsHumanReasonRepairSimulationCase[]> {
|
|
40
|
+
const outcomes: NeedsHumanReasonRepairSimulationCase[] = [];
|
|
41
|
+
const previousStateDir = process.env.ELANOUS_STATE_DIR;
|
|
42
|
+
process.env.ELANOUS_STATE_DIR = join(process.cwd(), '.elanous-test');
|
|
43
|
+
let logStore: import('../mss/logging/log-store.js').LogStore | null = null;
|
|
44
|
+
let logSink: import('../mss/logging/log-store.js').StoreSink | null = null;
|
|
45
|
+
let unregisterLogSink: (() => void) | null = null;
|
|
46
|
+
if (process.env.NODE_ENV === 'test') {
|
|
47
|
+
const storeModule = await import('../mss/logging/log-store.js');
|
|
48
|
+
logStore = new storeModule.LogStore();
|
|
49
|
+
logSink = new storeModule.StoreSink(logStore, 'self-dev.supervisor', { installExitHandlers: false });
|
|
50
|
+
unregisterLogSink = debug.registerSink(logSink);
|
|
51
|
+
} else {
|
|
52
|
+
const { registerStandaloneLogSink } = await import('../domains/standalone-log-sink.js');
|
|
53
|
+
await registerStandaloneLogSink('self-dev.supervisor');
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
for (const fixture of CASES) {
|
|
57
|
+
const operatorDir = mkdtempSync(join(tmpdir(), 'needs-human-reason-repair-sim-'));
|
|
58
|
+
const events: NeedsHumanReasonRepairSimulationCase['events'] = [];
|
|
59
|
+
const decisions: Array<{ action: string; stopReason?: SupervisorStopReason; why: string }> = [];
|
|
60
|
+
let repairGoal: string | undefined;
|
|
61
|
+
let reruns = 0;
|
|
62
|
+
try {
|
|
63
|
+
await superviseRun({
|
|
64
|
+
initial: [fixture.piece as unknown as SupervisorJobResult],
|
|
65
|
+
repairGoalExecution: true,
|
|
66
|
+
needsHumanReasonRepairExecution: true,
|
|
67
|
+
runStore: { runId: fixture.runId, operatorDir },
|
|
68
|
+
rerun: async (_previous, invocation) => {
|
|
69
|
+
reruns++;
|
|
70
|
+
repairGoal = invocation.repairGoals?.[fixture.piece.taskId];
|
|
71
|
+
return [fixture.piece as unknown as SupervisorJobResult];
|
|
72
|
+
},
|
|
73
|
+
onDecision: (decision) => decisions.push(decision),
|
|
74
|
+
observe: (event, data) => {
|
|
75
|
+
events.push({ event, data });
|
|
76
|
+
// Mirror the production single-run observer in self-implement-cli.ts.
|
|
77
|
+
try { debug.log('self-dev.supervisor', event, { ...data, surface: 'single' }); } catch { /* fail-open */ }
|
|
78
|
+
},
|
|
79
|
+
sweepPendingMerges: async () => ({ pending: 0, merged: 0 }),
|
|
80
|
+
taskAgentShadow: false,
|
|
81
|
+
taskAgentRejudge: false,
|
|
82
|
+
});
|
|
83
|
+
const terminal = decisions.at(-1);
|
|
84
|
+
outcomes.push({
|
|
85
|
+
reason: fixture.reason,
|
|
86
|
+
runId: fixture.runId,
|
|
87
|
+
taskId: fixture.piece.taskId,
|
|
88
|
+
goalText: fixture.goalText,
|
|
89
|
+
reruns,
|
|
90
|
+
...(repairGoal === undefined ? {} : { repairGoal }),
|
|
91
|
+
...(terminal?.stopReason === undefined ? {} : { stopReason: terminal.stopReason }),
|
|
92
|
+
...(terminal === undefined ? {} : { why: terminal.why }),
|
|
93
|
+
events,
|
|
94
|
+
});
|
|
95
|
+
} finally {
|
|
96
|
+
rmSync(operatorDir, { recursive: true, force: true });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} finally {
|
|
100
|
+
logSink?.close();
|
|
101
|
+
unregisterLogSink?.();
|
|
102
|
+
logStore?.close();
|
|
103
|
+
if (previousStateDir === undefined) delete process.env.ELANOUS_STATE_DIR;
|
|
104
|
+
else process.env.ELANOUS_STATE_DIR = previousStateDir;
|
|
105
|
+
}
|
|
106
|
+
return outcomes;
|
|
107
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { classifyPodTerminal } from '../self-dev/draft-residue.js';
|
|
2
|
+
import { podChildEvidenceLedgerRow, type PodTermination } from '../task-orchestrator/surfaces/pod-failure-reason.js';
|
|
3
|
+
|
|
4
|
+
export interface PodChildResultScenario {
|
|
5
|
+
firstAttempt: Record<string, unknown>;
|
|
6
|
+
harvestAttempt: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Replays a successful Kubernetes Job carrying a failed/partial child result. */
|
|
10
|
+
export function podChildResultScenario(): PodChildResultScenario {
|
|
11
|
+
const podTermination: PodTermination = {
|
|
12
|
+
job: 'si-task-report-deficit', path: 'result-marker', observedAt: '2026-10-28T09:35:13Z',
|
|
13
|
+
jobLookup: 'ok', jobUid: 'job-uid-1', jobConditionReason: 'CompletionsReached',
|
|
14
|
+
activeDeadlineSeconds: 14400, deadlineExceeded: false, podLookup: 'terminated',
|
|
15
|
+
containerReason: 'Completed', exitCode: 0, finishedAt: '2026-10-28T09:35:13Z', oomKilled: false,
|
|
16
|
+
};
|
|
17
|
+
const firstAttempt = podChildEvidenceLedgerRow({
|
|
18
|
+
job: podTermination.job, childRunId: 'run-first-report-deficit', state: 'complete',
|
|
19
|
+
result: {
|
|
20
|
+
stage: 'aborted', ok: false, failureClassification: 'report-deficit',
|
|
21
|
+
completionDisposition: 'partial', childEvidence: { error: 'report-deficit: missing child result summary' },
|
|
22
|
+
},
|
|
23
|
+
noResultDiagnostic: null, noResultLogEvidence: null, podTermination,
|
|
24
|
+
});
|
|
25
|
+
const harvestAttempt = classifyPodTerminal({
|
|
26
|
+
childRunId: 'run-second-harvest', state: 'complete', env: { ELANOUS_HARNESS_SEAT: 'UX' },
|
|
27
|
+
disposition: { stage: 'pr-opened', ok: true, prNumber: 32614,
|
|
28
|
+
prUrl: 'https://github.com/ElanvitalAI/elanous/pull/32614', branch: 'self-impl/coord-entrance-fold' },
|
|
29
|
+
at: '2026-10-28T09:35:29Z',
|
|
30
|
+
});
|
|
31
|
+
return { firstAttempt: firstAttempt ?? {}, harvestAttempt };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function renderPodChildResult(scenario: PodChildResultScenario): string[] {
|
|
35
|
+
const first = scenario.firstAttempt as { childResult?: Record<string, unknown>; podTermination?: PodTermination };
|
|
36
|
+
return [
|
|
37
|
+
`pod-child-result · child completion=${String(first.childResult?.completionDisposition ?? 'unknown')}`,
|
|
38
|
+
` first: child=${String(first.childResult?.ok)} · stage=${String(first.childResult?.stage)} · failure=${String(first.childResult?.failureClassification)}`,
|
|
39
|
+
` pod: ${String(first.podTermination?.containerReason)} · exit=${String(first.podTermination?.exitCode)} · childRunId=${String(scenario.firstAttempt.childRunId)}`,
|
|
40
|
+
` harvest: PR #${String(scenario.harvestAttempt.prNumber)} · ${String(scenario.harvestAttempt.terminalClass)}`,
|
|
41
|
+
];
|
|
42
|
+
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { parse as parseYaml } from 'yaml';
|
|
4
|
+
import { getTestStateRoot } from '../nexus/paths.js';
|
|
5
|
+
import { listGraphRuns, runGraph, type GraphRunState } from '../graph-runner/runner.js';
|
|
6
|
+
import { resolveScenarioFilePath } from './scenario.js';
|
|
7
|
+
|
|
8
|
+
const REPOSITORY_ROOT = join(import.meta.dir, '../..');
|
|
9
|
+
const RELEASE_GRAPH = join(REPOSITORY_ROOT, 'graphs/release/release-loop.yaml');
|
|
10
|
+
const CUT_TIP = 'a'.repeat(40);
|
|
11
|
+
|
|
12
|
+
export interface ReleaseSimRigCase {
|
|
13
|
+
id: string;
|
|
14
|
+
mode?: 'baseline' | 'cut-tip-moved-after-resume';
|
|
15
|
+
fault?: { node: string; outcome: 'fail' | 'error' | 'timeout'; evidence?: Record<string, unknown> };
|
|
16
|
+
expect: { status: 'done' | 'failed' | 'resume-refused'; mustVisit: string[]; mustNotVisit: string[] };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ReleaseSimRigScenario {
|
|
20
|
+
version: 1;
|
|
21
|
+
kind: 'release-graph';
|
|
22
|
+
id: string;
|
|
23
|
+
isolation: 'test';
|
|
24
|
+
input: { version: string; previousVersion: string };
|
|
25
|
+
cases: ReleaseSimRigCase[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ReleaseSimRigCaseResult {
|
|
29
|
+
id: string;
|
|
30
|
+
pass: boolean;
|
|
31
|
+
status: string;
|
|
32
|
+
path: string[];
|
|
33
|
+
dispatchedNodes: string[];
|
|
34
|
+
unexpectedEdges: Array<{ from: string; to: string; outcome: string; expectedTo?: string }>;
|
|
35
|
+
checks: { status: boolean; mustVisit: boolean; mustNotVisit: boolean; ledgerEvents: boolean };
|
|
36
|
+
injectedEvidence: Record<string, unknown>;
|
|
37
|
+
ledgerEvents: Array<Record<string, unknown>>;
|
|
38
|
+
statePath: string;
|
|
39
|
+
refusal?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function unexpectedEdges(path: string[], state: GraphRunState, edges: Map<string, Record<string, unknown>>): ReleaseSimRigCaseResult['unexpectedEdges'] {
|
|
43
|
+
const nodes = new Map(state.nodes.map((node) => [node.nodeId, node]));
|
|
44
|
+
const issues: ReleaseSimRigCaseResult['unexpectedEdges'] = [];
|
|
45
|
+
for (let index = 0; index + 1 < path.length; index++) {
|
|
46
|
+
const from = path[index]!;
|
|
47
|
+
const to = path[index + 1]!;
|
|
48
|
+
const edge = edges.get(from);
|
|
49
|
+
const output = nodes.get(from)?.output;
|
|
50
|
+
let parsed: Record<string, unknown> = {};
|
|
51
|
+
if (typeof output === 'string') {
|
|
52
|
+
try { parsed = record(JSON.parse(output.trim().split('\n').at(-1) ?? ''), `${from} output`); } catch { /* use runner fallback below */ }
|
|
53
|
+
} else if (output && typeof output === 'object' && !Array.isArray(output)) parsed = output as Record<string, unknown>;
|
|
54
|
+
const named = typeof parsed.outcome === 'string' ? parsed.outcome : nodes.get(from)?.ok ? 'ok' : 'fail';
|
|
55
|
+
const map = edge?.map && typeof edge.map === 'object' ? edge.map as Record<string, unknown> : {};
|
|
56
|
+
const expectedTo = typeof map[named] === 'string' ? map[named] as string : typeof map[named === 'ok' ? 'ok' : 'fail'] === 'string'
|
|
57
|
+
? map[named === 'ok' ? 'ok' : 'fail'] as string : undefined;
|
|
58
|
+
if (expectedTo !== to) issues.push({ from, to, outcome: named, ...(expectedTo ? { expectedTo } : {}) });
|
|
59
|
+
}
|
|
60
|
+
return issues;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function recordObservedEdges(path: string[], events: Array<Record<string, unknown>>): void {
|
|
64
|
+
for (let index = 0; index + 1 < path.length; index++) {
|
|
65
|
+
events.push({ event: 'edge-observed', from: path[index], to: path[index + 1], source: 'release-run-path' });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ReleaseSimRigResult {
|
|
70
|
+
id: string;
|
|
71
|
+
pass: boolean;
|
|
72
|
+
universe: string;
|
|
73
|
+
cases: ReleaseSimRigCaseResult[];
|
|
74
|
+
table: Array<{ scenario: string; path: string; status: string; unexpectedEdges: string }>;
|
|
75
|
+
artifactPath: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function record(value: unknown, where: string): Record<string, unknown> {
|
|
79
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`${where} must be an object`);
|
|
80
|
+
return value as Record<string, unknown>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function exactKeys(value: Record<string, unknown>, allowed: readonly string[], where: string): void {
|
|
84
|
+
const extra = Object.keys(value).filter((key) => !allowed.includes(key));
|
|
85
|
+
if (extra.length) throw new Error(`${where} has unsupported key(s): ${extra.join(', ')}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function stringList(value: unknown, where: string): string[] {
|
|
89
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== 'string' || item.trim() === '')) {
|
|
90
|
+
throw new Error(`${where} must be an array of non-empty strings`);
|
|
91
|
+
}
|
|
92
|
+
return value as string[];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function releaseGraphShape(): { nodeIds: Set<string>; edges: Map<string, Record<string, unknown>> } {
|
|
96
|
+
const graph = record(parseYaml(readFileSync(RELEASE_GRAPH, 'utf8')), 'release graph');
|
|
97
|
+
if (!Array.isArray(graph.nodes) || !Array.isArray(graph.edges)) throw new Error('release graph nodes or edges missing');
|
|
98
|
+
const nodeIds = new Set(graph.nodes.map((value) => record(value, 'release graph node').node_id)
|
|
99
|
+
.filter((id): id is string => typeof id === 'string'));
|
|
100
|
+
const edges = new Map<string, Record<string, unknown>>();
|
|
101
|
+
for (const raw of graph.edges) {
|
|
102
|
+
const edge = record(raw, 'release edge');
|
|
103
|
+
if (typeof edge.from !== 'string' || edge.on !== 'outcome' || !edge.map || typeof edge.map !== 'object') {
|
|
104
|
+
throw new Error('release simulation requires outcome edges with explicit maps');
|
|
105
|
+
}
|
|
106
|
+
if (edges.has(edge.from)) throw new Error(`release graph has multiple outcome edges from ${edge.from}`);
|
|
107
|
+
edges.set(edge.from, edge);
|
|
108
|
+
}
|
|
109
|
+
return { nodeIds, edges };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function parseReleaseSimRigScenario(source: string): ReleaseSimRigScenario {
|
|
113
|
+
const root = record(parseYaml(source), 'release simulation scenario');
|
|
114
|
+
exactKeys(root, ['version', 'kind', 'id', 'isolation', 'input', 'cases'], 'release simulation scenario');
|
|
115
|
+
if (root.version !== 1 || root.kind !== 'release-graph' || root.isolation !== 'test') {
|
|
116
|
+
throw new Error('release simulation scenario requires version: 1, kind: release-graph, isolation: test');
|
|
117
|
+
}
|
|
118
|
+
if (typeof root.id !== 'string' || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(root.id)) throw new Error('scenario.id must be lowercase letters, digits, and hyphens');
|
|
119
|
+
const input = record(root.input, 'scenario.input');
|
|
120
|
+
exactKeys(input, ['version', 'previousVersion'], 'scenario.input');
|
|
121
|
+
if (typeof input.version !== 'string' || !/^\d+\.\d+\.\d+$/.test(input.version)
|
|
122
|
+
|| typeof input.previousVersion !== 'string' || !/^\d+\.\d+\.\d+$/.test(input.previousVersion)) {
|
|
123
|
+
throw new Error('scenario.input requires release version and previousVersion');
|
|
124
|
+
}
|
|
125
|
+
const rawCases = root.cases;
|
|
126
|
+
if (!Array.isArray(rawCases) || rawCases.length === 0 || rawCases.length > 32) throw new Error('scenario.cases must contain 1–32 cases');
|
|
127
|
+
const { nodeIds } = releaseGraphShape();
|
|
128
|
+
const ids = new Set<string>();
|
|
129
|
+
const cases = rawCases.map((raw, index): ReleaseSimRigCase => {
|
|
130
|
+
const row = record(raw, `scenario.cases[${index}]`);
|
|
131
|
+
exactKeys(row, ['id', 'mode', 'fault', 'expect'], `scenario.cases[${index}]`);
|
|
132
|
+
if (typeof row.id !== 'string' || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(row.id) || ids.has(row.id)) throw new Error(`scenario.cases[${index}].id must be unique lowercase text`);
|
|
133
|
+
ids.add(row.id);
|
|
134
|
+
let mode: ReleaseSimRigCase['mode'];
|
|
135
|
+
if (row.mode !== undefined) {
|
|
136
|
+
if (row.mode !== 'baseline' && row.mode !== 'cut-tip-moved-after-resume') throw new Error(`scenario.cases[${index}].mode is unregistered`);
|
|
137
|
+
mode = row.mode;
|
|
138
|
+
}
|
|
139
|
+
let fault: ReleaseSimRigCase['fault'];
|
|
140
|
+
if (row.fault !== undefined) {
|
|
141
|
+
const parsed = record(row.fault, `scenario.cases[${index}].fault`);
|
|
142
|
+
exactKeys(parsed, ['node', 'outcome', 'evidence'], `scenario.cases[${index}].fault`);
|
|
143
|
+
if (typeof parsed.node !== 'string' || !nodeIds.has(parsed.node)) throw new Error(`scenario.cases[${index}].fault.node is not in the release graph`);
|
|
144
|
+
if (parsed.outcome !== 'fail' && parsed.outcome !== 'error' && parsed.outcome !== 'timeout') throw new Error(`scenario.cases[${index}].fault.outcome is unregistered`);
|
|
145
|
+
fault = { node: parsed.node, outcome: parsed.outcome, ...(parsed.evidence === undefined ? {} : { evidence: record(parsed.evidence, `scenario.cases[${index}].fault.evidence`) }) };
|
|
146
|
+
}
|
|
147
|
+
if ((mode === undefined) === (fault === undefined)) throw new Error(`scenario.cases[${index}] requires exactly one of mode or fault`);
|
|
148
|
+
const expected = record(row.expect, `scenario.cases[${index}].expect`);
|
|
149
|
+
exactKeys(expected, ['status', 'mustVisit', 'mustNotVisit'], `scenario.cases[${index}].expect`);
|
|
150
|
+
if (expected.status !== 'done' && expected.status !== 'failed' && expected.status !== 'resume-refused') throw new Error(`scenario.cases[${index}].expect.status is invalid`);
|
|
151
|
+
const mustVisit = stringList(expected.mustVisit, `scenario.cases[${index}].expect.mustVisit`);
|
|
152
|
+
const mustNotVisit = stringList(expected.mustNotVisit, `scenario.cases[${index}].expect.mustNotVisit`);
|
|
153
|
+
for (const id of [...mustVisit, ...mustNotVisit]) if (!nodeIds.has(id)) throw new Error(`scenario.cases[${index}] names unknown release node ${id}`);
|
|
154
|
+
if (mustVisit.some((id) => mustNotVisit.includes(id))) throw new Error(`scenario.cases[${index}] visits and excludes the same node`);
|
|
155
|
+
return { id: row.id, ...(mode ? { mode } : {}), ...(fault ? { fault } : {}), expect: { status: expected.status, mustVisit, mustNotVisit } };
|
|
156
|
+
});
|
|
157
|
+
return { version: 1, kind: 'release-graph', id: root.id, isolation: 'test',
|
|
158
|
+
input: { version: input.version, previousVersion: input.previousVersion }, cases };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function parseContext(env: NodeJS.ProcessEnv): { nodeId: string } {
|
|
162
|
+
const location = env.ELANOUS_GRAPH_CONTEXT;
|
|
163
|
+
if (!location) throw new Error('ELANOUS_GRAPH_CONTEXT missing in release simulation');
|
|
164
|
+
const context = record(JSON.parse(readFileSync(location, 'utf8')), 'release graph context');
|
|
165
|
+
if (typeof context.nodeId !== 'string') throw new Error('release graph context nodeId missing');
|
|
166
|
+
return { nodeId: context.nodeId };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function resultForNode(nodeId: string, fault: ReleaseSimRigCase['fault'], version: string): { exitCode: number; stdout: string; stderr: string; evidence: Record<string, unknown> } {
|
|
170
|
+
const triggeredFault = fault?.node === nodeId ? fault : undefined;
|
|
171
|
+
const outcome = triggeredFault ? triggeredFault.outcome === 'timeout' ? 'error' : triggeredFault.outcome : 'ok';
|
|
172
|
+
const evidence = triggeredFault?.evidence ?? {};
|
|
173
|
+
const commit = nodeId === 'version-release' ? { commit: CUT_TIP, tag: `v${version}` } : {};
|
|
174
|
+
const payload = { outcome, verdict: outcome === 'ok' ? 'pass' : 'fail', summary: triggeredFault ? `simulated ${triggeredFault.outcome}` : `simulated ${nodeId} success`, ...commit,
|
|
175
|
+
simulation: { injected: triggeredFault !== undefined, node: nodeId, evidence } };
|
|
176
|
+
return { exitCode: !triggeredFault ? 0 : triggeredFault.outcome === 'fail' ? 1 : triggeredFault.outcome === 'timeout' ? 124 : 2,
|
|
177
|
+
stdout: `${JSON.stringify(payload)}\n`, stderr: triggeredFault ? `SIMULATED_${triggeredFault.outcome.toUpperCase()}` : '', evidence };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function runCase(scenario: ReleaseSimRigScenario, item: ReleaseSimRigCase, root: string,
|
|
181
|
+
edges: Map<string, Record<string, unknown>>): Promise<ReleaseSimRigCaseResult> {
|
|
182
|
+
const runId = `release-sim-${scenario.id}-${item.id}`;
|
|
183
|
+
const ledgerEvents: Array<Record<string, unknown>> = [];
|
|
184
|
+
const dispatchedNodes: string[] = [];
|
|
185
|
+
const runBash = async (command: string, options: { env?: NodeJS.ProcessEnv }) => {
|
|
186
|
+
const { nodeId } = parseContext(options.env ?? {});
|
|
187
|
+
if (!command.trim()) throw new Error(`empty command at simulated node ${nodeId}`);
|
|
188
|
+
dispatchedNodes.push(nodeId);
|
|
189
|
+
const result = resultForNode(nodeId, item.fault, scenario.input.version);
|
|
190
|
+
return { exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr };
|
|
191
|
+
};
|
|
192
|
+
const capture = (event: string, data: Record<string, unknown>) => ledgerEvents.push({ event, ...data });
|
|
193
|
+
|
|
194
|
+
if (item.mode === 'cut-tip-moved-after-resume') {
|
|
195
|
+
let beforeNode = 0;
|
|
196
|
+
const simulatedStop = new Error('simulated runner stop after cut');
|
|
197
|
+
try {
|
|
198
|
+
await runGraph(RELEASE_GRAPH, { runId, input: scenario.input, pinChildUniverse: true, quiet: true,
|
|
199
|
+
deps: { root, runBash, log: capture, beforeNode: () => { if (++beforeNode === 2) throw simulatedStop; } } });
|
|
200
|
+
} catch (error) {
|
|
201
|
+
if (error !== simulatedStop) throw error;
|
|
202
|
+
}
|
|
203
|
+
let refusal = '';
|
|
204
|
+
try {
|
|
205
|
+
await runGraph(RELEASE_GRAPH, { resumeRunId: runId, pinChildUniverse: true, quiet: true,
|
|
206
|
+
releaseCommandSource: { root: REPOSITORY_ROOT, cutTip: 'b'.repeat(40), git: () => { throw new Error('git must not be consulted after the saved tip differs'); } },
|
|
207
|
+
deps: { root, runBash, log: capture } });
|
|
208
|
+
} catch (error) { refusal = error instanceof Error ? error.message : String(error); }
|
|
209
|
+
const interrupted = listGraphRuns(root).runs.find((run) => run.runId === runId);
|
|
210
|
+
const stateFile = interrupted?.statePath ?? '';
|
|
211
|
+
const path = interrupted?.path ?? [];
|
|
212
|
+
recordObservedEdges(path, ledgerEvents);
|
|
213
|
+
const edgeIssues = interrupted ? unexpectedEdges(path, interrupted, edges) : [];
|
|
214
|
+
const statusOk = item.expect.status === 'resume-refused' && refusal.includes('release command source differs from the saved cut tip');
|
|
215
|
+
const visitOk = item.expect.mustVisit.every((id) => path.includes(id));
|
|
216
|
+
const notVisitOk = item.expect.mustNotVisit.every((id) => !path.includes(id));
|
|
217
|
+
const ledgerOk = ledgerEvents.some((row) => row.event === 'node-end')
|
|
218
|
+
&& ledgerEvents.filter((row) => row.event === 'edge-observed').length === Math.max(0, path.length - 1);
|
|
219
|
+
return { id: item.id, pass: statusOk && visitOk && notVisitOk && ledgerOk && edgeIssues.length === 0, status: statusOk ? 'resume-refused' : interrupted?.status ?? 'missing',
|
|
220
|
+
path, dispatchedNodes, unexpectedEdges: edgeIssues, checks: { status: statusOk, mustVisit: visitOk, mustNotVisit: notVisitOk, ledgerEvents: ledgerOk }, injectedEvidence: {}, ledgerEvents,
|
|
221
|
+
statePath: stateFile, ...(refusal ? { refusal } : {}) };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Initial runs have no releaseCommandSource (the runner only accepts it on resume); all node shell work is intercepted here.
|
|
225
|
+
const state = await runGraph(RELEASE_GRAPH, { runId, input: scenario.input, pinChildUniverse: true, quiet: true,
|
|
226
|
+
deps: { root, runBash, log: capture } });
|
|
227
|
+
const path = state.path;
|
|
228
|
+
recordObservedEdges(path, ledgerEvents);
|
|
229
|
+
const edgeIssues = unexpectedEdges(path, state, edges);
|
|
230
|
+
const statusOk = state.status === item.expect.status;
|
|
231
|
+
const visitOk = item.expect.mustVisit.every((id) => path.includes(id));
|
|
232
|
+
const notVisitOk = item.expect.mustNotVisit.every((id) => !path.includes(id));
|
|
233
|
+
const ledgerOk = ledgerEvents.some((row) => row.event === 'node-start') && ledgerEvents.some((row) => row.event === 'node-end')
|
|
234
|
+
&& ledgerEvents.filter((row) => row.event === 'edge-observed').length === Math.max(0, path.length - 1);
|
|
235
|
+
const injectedEvidence = item.fault ? item.fault.evidence ?? {} : {};
|
|
236
|
+
return { id: item.id, pass: statusOk && visitOk && notVisitOk && ledgerOk && edgeIssues.length === 0, status: state.status, path, dispatchedNodes, unexpectedEdges: edgeIssues,
|
|
237
|
+
checks: { status: statusOk, mustVisit: visitOk, mustNotVisit: notVisitOk, ledgerEvents: ledgerOk }, injectedEvidence,
|
|
238
|
+
ledgerEvents, statePath: state.statePath };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export async function runReleaseSimRigScenario(source: string): Promise<ReleaseSimRigResult> {
|
|
242
|
+
const scenario = parseReleaseSimRigScenario(source);
|
|
243
|
+
const root = getTestStateRoot();
|
|
244
|
+
if (!root) throw new Error('release simulation rig requires --test isolated mode');
|
|
245
|
+
const { edges } = releaseGraphShape();
|
|
246
|
+
const cases = [];
|
|
247
|
+
for (const item of scenario.cases) cases.push(await runCase(scenario, item, root, edges));
|
|
248
|
+
const result: ReleaseSimRigResult = { id: scenario.id, pass: cases.every((item) => item.pass), universe: root, cases,
|
|
249
|
+
table: cases.map((item) => ({ scenario: item.id, path: item.path.join(' → '), status: item.status,
|
|
250
|
+
unexpectedEdges: item.unexpectedEdges.length ? JSON.stringify(item.unexpectedEdges) : 'none' })),
|
|
251
|
+
artifactPath: join(root, 'ux-sim', 'evidence', `${scenario.id}.json`) };
|
|
252
|
+
mkdirSync(join(root, 'ux-sim', 'evidence'), { recursive: true });
|
|
253
|
+
writeFileSync(result.artifactPath, `${JSON.stringify(result, null, 2)}\n`, { mode: 0o600 });
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export async function runReleaseSimRigIfFile(filePath: string): Promise<ReleaseSimRigResult | null> {
|
|
258
|
+
const source = readFileSync(resolveScenarioFilePath(filePath), 'utf8');
|
|
259
|
+
if (record(parseYaml(source), 'scenario').kind !== 'release-graph') return null;
|
|
260
|
+
if (!getTestStateRoot()) throw new Error('release simulation rig requires --test isolated mode');
|
|
261
|
+
return runReleaseSimRigScenario(source);
|
|
262
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simulate the 40-minute, seven-scene seminar rehearsal protocol.
|
|
3
|
+
*
|
|
4
|
+
* This checks timing, evidence completeness, fallback, and disclosure guards
|
|
5
|
+
* with injected records. It never claims that a real rehearsal or device run
|
|
6
|
+
* took place.
|
|
7
|
+
*/
|
|
8
|
+
// Targets mirror RUNBOOK-1027-seminar-smart-wizard-demo-2026-10-24.md; the test
|
|
9
|
+
// parses that table so edits to the runbook cannot silently drift from this rig.
|
|
10
|
+
export const SEMINAR_SCENES = [
|
|
11
|
+
{ id: 1, name: 'hook', targetMinutes: 3 },
|
|
12
|
+
{ id: 2, name: 'problem', targetMinutes: 5 },
|
|
13
|
+
{ id: 3, name: 'AI executive', targetMinutes: 8 },
|
|
14
|
+
{ id: 4, name: 'development demo', targetMinutes: 8 },
|
|
15
|
+
{ id: 5, name: 'two phones', targetMinutes: 8 },
|
|
16
|
+
{ id: 6, name: 'transit demo', targetMinutes: 4 },
|
|
17
|
+
{ id: 7, name: 'close', targetMinutes: 4 },
|
|
18
|
+
] as const;
|
|
19
|
+
|
|
20
|
+
export type SeminarSceneId = (typeof SEMINAR_SCENES)[number]['id'];
|
|
21
|
+
export type SeminarOutcome = 'pass' | 'fail' | 'unknown';
|
|
22
|
+
|
|
23
|
+
export interface SeminarSceneRecord {
|
|
24
|
+
readonly scene: SeminarSceneId;
|
|
25
|
+
readonly elapsedMinutes: number | null;
|
|
26
|
+
readonly medium: string | null;
|
|
27
|
+
readonly evidenceId: string | null;
|
|
28
|
+
readonly outcome: SeminarOutcome;
|
|
29
|
+
readonly publicSafe: boolean | null;
|
|
30
|
+
readonly fallbackUsed: boolean | null;
|
|
31
|
+
readonly offlineFallbackPlayed: boolean | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface SeminarRehearsalResult {
|
|
35
|
+
readonly simulated: true;
|
|
36
|
+
readonly totalTargetMinutes: number;
|
|
37
|
+
readonly scenes: ReadonlyArray<{
|
|
38
|
+
scene: SeminarSceneId;
|
|
39
|
+
name: string;
|
|
40
|
+
targetMinutes: number;
|
|
41
|
+
observedMinutes: number | null;
|
|
42
|
+
verdict: 'pass' | 'fail' | 'unknown';
|
|
43
|
+
reason: string;
|
|
44
|
+
}>;
|
|
45
|
+
readonly verdict: 'pass' | 'fail' | 'unknown';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function simSeminarRehearsal(records: readonly SeminarSceneRecord[]): SeminarRehearsalResult {
|
|
49
|
+
const byScene = new Map<SeminarSceneId, SeminarSceneRecord>();
|
|
50
|
+
for (const record of records) {
|
|
51
|
+
if (!SEMINAR_SCENES.some((scene) => scene.id === record.scene)) throw new Error(`unknown scene record: ${String(record.scene)}`);
|
|
52
|
+
if (byScene.has(record.scene)) throw new Error(`duplicate scene record: ${record.scene}`);
|
|
53
|
+
byScene.set(record.scene, record);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const scenes = SEMINAR_SCENES.map((scene) => {
|
|
57
|
+
const record = byScene.get(scene.id);
|
|
58
|
+
if (!record || record.elapsedMinutes === null || !record.medium || !record.evidenceId || record.outcome === 'unknown' || record.publicSafe === null || record.fallbackUsed === null || (record.fallbackUsed && record.offlineFallbackPlayed === null)) {
|
|
59
|
+
return { scene: scene.id, name: scene.name, targetMinutes: scene.targetMinutes, observedMinutes: record?.elapsedMinutes ?? null, verdict: 'unknown' as const, reason: '실행 기록의 시간·매체·증거·결과·공개 안전 중 미확인 값이 있음' };
|
|
60
|
+
}
|
|
61
|
+
if (record.outcome === 'fail') {
|
|
62
|
+
return { scene: scene.id, name: scene.name, targetMinutes: scene.targetMinutes, observedMinutes: record.elapsedMinutes, verdict: 'fail' as const, reason: '주입된 장면 결과가 fail' };
|
|
63
|
+
}
|
|
64
|
+
if (Math.abs(record.elapsedMinutes - scene.targetMinutes) > 1) {
|
|
65
|
+
return { scene: scene.id, name: scene.name, targetMinutes: scene.targetMinutes, observedMinutes: record.elapsedMinutes, verdict: 'fail' as const, reason: `목표 ${scene.targetMinutes}분에서 ±1분 초과` };
|
|
66
|
+
}
|
|
67
|
+
if (!record.publicSafe) {
|
|
68
|
+
return { scene: scene.id, name: scene.name, targetMinutes: scene.targetMinutes, observedMinutes: record.elapsedMinutes, verdict: 'fail' as const, reason: '공개 안전 확인 실패' };
|
|
69
|
+
}
|
|
70
|
+
if (record.fallbackUsed && !record.offlineFallbackPlayed) {
|
|
71
|
+
return { scene: scene.id, name: scene.name, targetMinutes: scene.targetMinutes, observedMinutes: record.elapsedMinutes, verdict: 'fail' as const, reason: '대체 경로를 선택했으나 오프라인 매체 재생을 확인하지 못함' };
|
|
72
|
+
}
|
|
73
|
+
return { scene: scene.id, name: scene.name, targetMinutes: scene.targetMinutes, observedMinutes: record.elapsedMinutes, verdict: 'pass' as const, reason: record.fallbackUsed ? '오프라인 대체 매체 재생 확인' : '주입된 시나리오 통과' };
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const verdict = scenes.some((scene) => scene.verdict === 'unknown')
|
|
77
|
+
? 'unknown'
|
|
78
|
+
: scenes.some((scene) => scene.verdict === 'fail')
|
|
79
|
+
? 'fail'
|
|
80
|
+
: 'pass';
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
simulated: true,
|
|
84
|
+
totalTargetMinutes: SEMINAR_SCENES.reduce((sum, scene) => sum + scene.targetMinutes, 0),
|
|
85
|
+
scenes,
|
|
86
|
+
verdict,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function seminarRehearsalSweep(): SeminarRehearsalResult {
|
|
91
|
+
const records: SeminarSceneRecord[] = SEMINAR_SCENES.map((scene) => ({
|
|
92
|
+
scene: scene.id,
|
|
93
|
+
elapsedMinutes: scene.targetMinutes,
|
|
94
|
+
medium: scene.id === 5 ? 'simulated iPhone + Fold8' : scene.id === 4 ? 'simulated offline video' : 'simulated stage screen',
|
|
95
|
+
evidenceId: `sim-scene-${scene.id}`,
|
|
96
|
+
outcome: 'pass',
|
|
97
|
+
publicSafe: true,
|
|
98
|
+
fallbackUsed: scene.id === 5,
|
|
99
|
+
offlineFallbackPlayed: scene.id === 5 ? true : null,
|
|
100
|
+
}));
|
|
101
|
+
return simSeminarRehearsal(records);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function renderSeminarRehearsal(result: SeminarRehearsalResult): string[] {
|
|
105
|
+
return [
|
|
106
|
+
`세미나 리허설 · ${result.totalTargetMinutes}분 · ${result.verdict} · sim only (실제 행사 실행 증거 아님)`,
|
|
107
|
+
...result.scenes.map((scene) => ` S${scene.scene} ${scene.name.padEnd(18)} ${scene.observedMinutes === null ? '미확인' : `${scene.observedMinutes}분`.padEnd(5)} / 목표 ${scene.targetMinutes}분 · ${scene.verdict} · ${scene.reason}`),
|
|
108
|
+
];
|
|
109
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// N03 장치 — SUBAGENT-TOOLS-EMPTY (0.2.36 · 2026-10-22 · 대표 P0).
|
|
2
|
-
// 진짜 classic TUI(
|
|
2
|
+
// 진짜 classic TUI(`--legacy`) ⊕ fake LLM 이 Agent 도구를 «틀린 이름» tool_filter 로 부른다
|
|
3
3
|
// (10-22 운영 실물: allow 5~12개를 줘도 49→0 · «0 tools · Blocked»). 판정은 같은 바이너리의 `logs --json`:
|
|
4
4
|
// mismatch — allow 가 모르는 이름뿐 → tool-filter allowIgnored ⊕ dispatch noTools=false(도구 상속)
|
|
5
5
|
// deny-all — 모든 도구를 deny → no-tools-refused(발사 거부 · 빈손 실행 0)
|
|
@@ -33,7 +33,7 @@ export async function runSubagentToolsDevice(spec: SubagentToolsSpec): Promise<S
|
|
|
33
33
|
: { allow: ['Read'], deny: ['Read'] };
|
|
34
34
|
const run = await mockSeatPtySequence({
|
|
35
35
|
executable: spec.executable,
|
|
36
|
-
args: [spec.entry, '--config-dir', '{root}', '--test-state-dir', '{root}'],
|
|
36
|
+
args: [spec.entry, '--legacy', '--config-dir', '{root}', '--test-state-dir', '{root}'],
|
|
37
37
|
root,
|
|
38
38
|
rows: 30,
|
|
39
39
|
cols: 100,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"commit":"
|
|
1
|
+
{"commit":"479072f6639b631e74d2a88a4e2f982193e00f89"}
|