elanous 0.2.32 → 0.2.34
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/{IVKr3AlRUVLKsw2fh7eXF → L04y73dlwKeTW-GetaTF3}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +79 -0
- package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +94 -0
- package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 1644.35dd25240ae24e4b.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 1895-60ed0e341c658bd4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 2124.ed5bf480cea7f85b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +23 -0
- package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +115 -0
- package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +8 -0
- package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 2547.dd27303624cb4da8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 2554.3b5e200f5f5cfcd6.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 2987-30cf9c2eb7b8bdd5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3541-ce3a5424ed5ad7f1.js → 3001-5a52788c813b6113.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3103.84470c8445962f04.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 3110.0a7065f25c841818.js} +17 -17
- package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3121.779fafe3e44612c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3411-f87314c6c66ebc73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 3414.172ad4ca2d9b08e8.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4745.67d6f99c245af3f7.js → 3498.cf2a15a8a9e5b926.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3819.163d4777f0a597f6.js +32 -0
- package/apps/pwa/out/_next/static/chunks/{5543.a438b8ab5a13ea47.js → 3837.722e053fb9f321ad.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +104 -0
- package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +286 -0
- package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +149 -0
- package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +148 -0
- package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +64 -0
- package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +74 -0
- package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → 4fa33ebd.21c1bd5b294496e6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 5014f970-22bef0b5210f7d60.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2112-e4efc21a6505d5bc.js → 5028-f0722e6114c313e7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2898.fd781bc7cf01a7b7.js → 5249.96a848656b582a93.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{9407.e49124dedf0f5e72.js → 5446.edf141cff9ef647d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9002.e5658224e3dc1b6f.js → 5489.ec2dd1b5272a19dc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 5576-82d3703636d5c4b9.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6053-d893974de92e6198.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 6086.913a69e6fa3e4a8b.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +1 -0
- package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +77 -0
- package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 6740.43de73fc427c9fe2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +90 -0
- package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7005.1623d2aea78eb85f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7193-cf355cca5ba6c5d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7386.5d8e7e42e818dfb6.js +287 -0
- package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 7431.3051e9b8a4372d2d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{3583.a05e88cc8d594628.js → 7448.478958ffbbba0ac0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7562.948255cbc3e79d33.js +41 -0
- package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +27 -0
- package/apps/pwa/out/_next/static/chunks/{9989.3694300e5f000b14.js → 7952.b192c31b6a0e00cc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +36 -0
- package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +1 -0
- package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 8368.014caa8de2f5af34.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 8548.036c344973968847.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8817.61bb7ffbba502ecb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 9131-fce7256c4180c4a5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +93 -0
- package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9550.d5f76828f972058c.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{2534.e85ae21ad0dac829.js → 9739.8d5f36ac67a3b236.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → 9a8cb466.cc9fc9e6e46038aa.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → 9b48c871.204d5d13e7809bd0.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → abb4b98b.163e0f56e84ae35d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-4fb31eb476dcbad3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-d7bff0f0905a662c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-8c66a3b24a745630.js → page-398c0faa173203f7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-04d00ae9b0890349.js → page-df3445b207ceceab.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +122 -0
- package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{ebc7d829.264a0bcb6c750b50.js → ffdc3a04.b9c23c1b28dd4a96.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.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 +9 -2
- package/docs/goal-context/README.md +1 -0
- package/graphs/default-loop.yaml +20 -3
- package/graphs/document-loop.yaml +21 -2
- package/graphs/implement-loop.yaml +6 -0
- package/graphs/journey/SCENARIOS.md +33 -0
- package/graphs/journey/recipes.yaml +1 -0
- package/graphs/journey/ta-journey.yaml +84 -0
- package/graphs/journey/units/author/author.yaml +20 -0
- package/graphs/journey/units/author/recipes.yaml +2 -0
- package/graphs/journey/units/green/green.yaml +20 -0
- package/graphs/journey/units/green/recipes.yaml +2 -0
- package/graphs/journey/units/pr/pr.yaml +20 -0
- package/graphs/journey/units/pr/recipes.yaml +2 -0
- package/graphs/journey/units/remember/recipes.yaml +2 -0
- package/graphs/journey/units/remember/remember.yaml +20 -0
- package/graphs/operate-loop.yaml +21 -2
- package/graphs/overlays/stop-heal-ladder.yaml +1 -1
- package/graphs/release-rehearsal/recipes.yaml +1 -1
- package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
- package/graphs/research-loop.yaml +23 -2
- package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
- package/graphs/units/dispatch-pod/recipes.yaml +14 -0
- package/graphs/units/entry/entry.yaml +50 -0
- package/graphs/units/entry/recipes.yaml +14 -0
- package/graphs/units/harvest/harvest.yaml +25 -0
- package/graphs/units/harvest/recipes.yaml +4 -0
- package/graphs/units/land/land.yaml +45 -0
- package/graphs/units/land/recipes.yaml +3 -0
- package/graphs/units/recipes.yaml +7 -0
- package/graphs/units/recover.yaml +39 -0
- package/graphs/units/reflect/recipes.yaml +3 -0
- package/graphs/units/reflect/reflect.yaml +15 -0
- package/graphs/units/task-agent-recover-review.yaml +17 -0
- package/graphs/units/task-agent-recover-wait.yaml +17 -0
- package/graphs/units/verbs/make-doc.yaml +34 -0
- package/graphs/units/verbs/recipes.yaml +33 -0
- package/graphs/units/verbs/verify.yaml +55 -0
- package/graphs/work/recipes.yaml +2 -0
- package/graphs/work/research-report.yaml +28 -0
- package/package.json +1 -1
- package/scripts/ci-typecheck-changed.ts +69 -16
- package/scripts/docs/generate-graph-anatomy.ts +19 -2
- package/scripts/graph-harvest-unit.ts +22 -0
- package/scripts/graph-units/journey-stub.ts +6 -0
- package/scripts/graph-units/land-enqueue.ts +78 -0
- package/scripts/graph-units/recover-plan.ts +15 -0
- package/scripts/graph-units/reflect-node.ts +88 -0
- package/scripts/graph-units/ta-journey-observe.ts +109 -0
- package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
- package/scripts/graph-units/verbs/verify-stage.ts +75 -0
- package/scripts/graph-units/verbs-envelope.ts +139 -0
- package/scripts/hq/standby-snapshot.ts +25 -0
- package/scripts/public-export.ts +43 -1
- package/scripts/ratchets/train-side-invariants.sh +45 -0
- package/scripts/release-loop/auto-approve-node.ts +30 -16
- package/scripts/release-loop/gate-closure.ts +5 -1
- package/scripts/release-loop/gate-diff.ts +1 -1
- package/scripts/release-loop/gate-node.ts +498 -31
- package/scripts/release-loop/gate-partial.ts +3 -3
- package/scripts/release-loop/gate-radius-shadow.ts +138 -0
- package/scripts/release-loop/gate-traffic-mode.ts +128 -0
- package/scripts/release-loop/gate-triage-node.ts +5 -2
- package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
- package/scripts/release-loop/known-issues-node.ts +77 -8
- package/scripts/release-loop/preflight.ts +93 -7
- package/scripts/release-loop/publish-node.ts +60 -9
- package/scripts/release-loop/resume-cap.ts +56 -0
- package/scripts/release-loop/resume-release.ts +114 -15
- package/scripts/release-loop/resume.ts +24 -1
- package/scripts/release-loop/tui-sim-node.ts +8 -2
- package/scripts/release-loop/unattended-release.ts +8 -2
- package/src/acp/core-turn-bridge.ts +20 -5
- package/src/acp/reasoning-thought-buffer.ts +45 -0
- package/src/agent-substrate/acp-reviewer.ts +52 -12
- package/src/agent-substrate/review-finding-key.ts +53 -0
- package/src/agent-substrate/self-review-cli.ts +126 -5
- package/src/ask-user-question/pending-questions.ts +1 -1
- package/src/autopilot/pr-manager.ts +192 -43
- package/src/chat/tool-render/dispatch.ts +62 -10
- package/src/cli/control-cli.ts +24 -7
- package/src/cli/guardian-cli.ts +10 -0
- package/src/cli/light-entry-route.ts +35 -0
- package/src/cli/llm-detect-cli.ts +23 -1
- package/src/cli/pr-cli.ts +76 -12
- package/src/cli/pr-land-base-read.ts +2 -0
- package/src/cli/pr-land-overlap-evidence.ts +154 -16
- package/src/cli/pr-land-recovery.ts +64 -0
- package/src/cli/pty-takeover-cli.ts +6 -5
- package/src/cli/release-cli.ts +120 -33
- package/src/cli/release-run-if-ready.ts +29 -28
- package/src/cli/release-single-flight.ts +178 -0
- package/src/cli/seat-cli.ts +37 -0
- package/src/cli/setup-cli.ts +40 -1
- package/src/cli/tasks-cli.ts +149 -5
- package/src/control/control-status.ts +8 -3
- package/src/control-plane/ledger.ts +5 -3
- package/src/control-plane/server.ts +5 -3
- package/src/core-turn/short-question.ts +5 -1
- package/src/dashboard/index.ts +36 -67
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
- package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
- package/src/dashboard/input/seat-autowake.ts +56 -3
- package/src/dashboard/seat-boot-preamble.ts +1 -1
- package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
- package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
- package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
- package/src/dashboard/turn-preamble.ts +47 -1
- package/src/dashboard/turn-stream-formatter.ts +34 -1
- package/src/dashboard/turn-stream-runtime.ts +2 -0
- package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
- package/src/domains/guardian-tick.ts +54 -2
- package/src/domains/outbound-alert.ts +3 -2
- package/src/extractors.ts +3 -1
- package/src/git-fs/retry.ts +4 -0
- package/src/git-fs/runner.ts +2 -0
- package/src/graph-runner/runner.ts +114 -44
- package/src/grok/credential.ts +5 -0
- package/src/harness/harness-cli-command.ts +39 -10
- package/src/harness/harness-incidents.ts +4 -0
- package/src/harness/harness-pod-dispatch.ts +38 -1
- package/src/harness/harness-salvage-cli.ts +14 -2
- package/src/index.ts +192 -8
- package/src/intake-plane/already-built-hint.ts +89 -0
- package/src/knowhow/pack.ts +199 -0
- package/src/light-cli.ts +95 -0
- package/src/llm.ts +55 -9
- package/src/loops/budget.ts +95 -0
- package/src/loops/msg-wake.ts +8 -2
- package/src/loops/orchestrator/traffic.ts +132 -1
- package/src/mss/logging/log-store.ts +4 -5
- package/src/nexus/api/graphs-api.ts +22 -3
- package/src/nexus/api/http-server.ts +1 -1
- package/src/nexus/api/ops-api.ts +12 -0
- package/src/oauth/claude-pty-maturity.ts +66 -0
- package/src/oauth/codex-access-mirror.ts +55 -0
- package/src/oauth/fallback-chain.ts +1 -1
- package/src/onboarding/first-run.ts +5 -3
- package/src/onboarding/non-interactive.ts +64 -13
- package/src/onboarding.ts +10 -2
- package/src/ops/overview-collect.ts +36 -1
- package/src/ops/overview.ts +11 -0
- package/src/pr-tool/census.ts +23 -5
- package/src/pr-tool/inflight-registry.ts +160 -7
- package/src/prompt-library/gpt6-family-addendum.ts +14 -1
- package/src/pty-shell/herdr-agent-report.ts +442 -0
- package/src/pty-shell/pty-control-ipc.ts +5 -5
- package/src/pty-shell/pty-write-outcome.ts +24 -6
- package/src/pty-shell/tui-run-state.ts +117 -3
- package/src/release-loop/checklist.ts +79 -5
- package/src/release-loop/feature-store.ts +19 -2
- package/src/release-loop/placement.ts +10 -3
- package/src/release-loop/rehearsal.ts +205 -25
- package/src/release-loop/rubric.ts +16 -2
- package/src/self-dev/draft-sweep.ts +52 -3
- package/src/self-dev/graph-journey-nodes.ts +10 -6
- package/src/self-dev/graph-journey-route.ts +60 -6
- package/src/self-dev/orchestrate.ts +79 -3
- package/src/self-dev/run-supervisor.ts +107 -12
- package/src/self-dev/run-types.ts +5 -1
- package/src/self-implement/gate-baseline.ts +49 -5
- package/src/self-implement/gate-remote.ts +9 -5
- package/src/self-implement/goal-author-identity.ts +66 -0
- package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
- package/src/self-implement/goal-author.ts +4 -120
- package/src/self-implement/graph-overlay-yaml.ts +17 -2
- package/src/self-implement/graph-unit-flatten.ts +103 -0
- package/src/self-implement/graph-unit-resolver.ts +107 -0
- package/src/self-implement/graph-yaml.ts +151 -1
- package/src/self-implement/headless-elanous-driver.ts +1 -0
- package/src/self-implement/knowhow-pack.ts +103 -0
- package/src/self-implement/orchestrator.ts +8 -0
- package/src/self-implement/pod-warm-pool-profile.ts +45 -0
- package/src/self-implement/review-mustfix-class.ts +203 -0
- package/src/self-implement/run-stop.ts +8 -2
- package/src/self-implement/seams.ts +32 -1
- package/src/self-implement/stop-autoheal.ts +25 -1
- package/src/session/chat.ts +27 -0
- package/src/session-runtime/retry-policy.ts +2 -1
- package/src/skills/tools/schedule-wakeup.ts +66 -17
- package/src/steward/release-day.ts +7 -3
- package/src/steward/triage.ts +37 -4
- package/src/task-agent/harvest-unit.ts +141 -0
- package/src/task-agent/live-moves.ts +98 -12
- package/src/task-agent/parent-host.ts +93 -3
- package/src/task-agent/postland-card.ts +80 -1
- package/src/task-agent/rejudge-on-head.ts +112 -26
- package/src/task-agent/repair-branch-cas.ts +4 -1
- package/src/task-agent/repair-cycle.ts +16 -3
- package/src/task-agent/run-identity.ts +4 -3
- package/src/task-agent/shadow.ts +12 -2
- package/src/task-agent/task-hand.ts +54 -7
- package/src/task-agent/work-order-build.ts +22 -0
- package/src/task-orchestrator/surfaces/pod-account-broker.ts +39 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +2 -1
- package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
- package/src/task-orchestrator/surfaces/pod-pool.ts +73 -17
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +54 -4
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +26 -3
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +389 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +2 -1
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +223 -38
- package/src/task-orchestrator/surfaces/self-implement.ts +83 -2
- package/src/tool-runtime/truncation-store.ts +4 -0
- package/src/tui-client/dashboard-session.ts +10 -1
- package/src/user-config/coercion.ts +36 -0
- package/src/user-config.ts +18 -41
- package/src/ux-sim/scenario.ts +72 -13
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
- package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
- package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
- package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
- package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
- package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
- package/apps/pwa/out/_next/static/chunks/3267c0e6.d34854e7b3984a6e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +0 -34
- package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
- package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
- package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
- package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
- package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
- package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
- package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
- package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
- package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
- package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
- package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
- package/apps/pwa/out/_next/static/chunks/69-0a2c8209c6d4a158.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
- package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
- package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-a27b1e5a0d1b308f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-32866485913d6a04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-c219f2ed171131be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
- package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
- package/src/cli/g6a-registration-probe.ts +0 -16
- /package/apps/pwa/out/_next/static/{IVKr3AlRUVLKsw2fh7eXF → L04y73dlwKeTW-GetaTF3}/_ssgManifest.js +0 -0
|
@@ -4,6 +4,7 @@ import { readFileSync, readdirSync } from 'node:fs';
|
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { parse as parseYaml } from 'yaml';
|
|
6
6
|
import { HARNESS_CORE_KINDS, hasNodeKind } from '../graph-kinds/registry.js';
|
|
7
|
+
import { parseOverlayCondition } from './graph-overlay-condition.js';
|
|
7
8
|
|
|
8
9
|
/** ⭐ RFC-graph-templates-as-yaml §5 «0단계» — YAML 저작본을 읽어 실행·해시·원장용 정규형으로.
|
|
9
10
|
*
|
|
@@ -36,6 +37,8 @@ export interface GraphNodeSpec {
|
|
|
36
37
|
/** Entry selected by this call when a unit exposes more than one entry. */
|
|
37
38
|
readonly callEntry?: string;
|
|
38
39
|
readonly budget?: { readonly innerSteps: number };
|
|
40
|
+
/** L1: skip this optional node when a measured state condition holds. */
|
|
41
|
+
readonly skipWhen?: string;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
export interface GraphEdgeSpec {
|
|
@@ -48,6 +51,8 @@ export interface GraphEdgeSpec {
|
|
|
48
51
|
/** 심이 «주입 안 됐을 때» 내려가는 순서. `requires` 는 그 심 이름들. */
|
|
49
52
|
readonly fallback?: readonly { readonly node: string; readonly requires: readonly string[]; readonly observed?: number }[];
|
|
50
53
|
readonly observed?: number;
|
|
54
|
+
/** L1: a measured state condition takes precedence over the default edge. */
|
|
55
|
+
readonly when?: string;
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
export interface GraphTemplateSpec {
|
|
@@ -63,10 +68,41 @@ export interface GraphTemplateSpec {
|
|
|
63
68
|
/** ⭐ 런 계약(선택) — 이 그래프가 «기본으로» 요구하는 실행 칸 등. 발사 인자가 덮는다(graph-run-contract.ts). */
|
|
64
69
|
readonly runContract?: GraphRunContractSpec;
|
|
65
70
|
readonly unit?: { readonly inputs: readonly string[]; readonly outputs: readonly string[]; readonly exits: readonly string[]; readonly entries?: readonly string[] };
|
|
71
|
+
/** Non-executable landing policy declaration. The train executor consumes this in a later slice. */
|
|
72
|
+
readonly policy?: LandUnitTrainPolicySpec;
|
|
66
73
|
readonly nodes: readonly GraphNodeSpec[];
|
|
67
74
|
readonly edges: readonly GraphEdgeSpec[];
|
|
68
75
|
}
|
|
69
76
|
|
|
77
|
+
export interface LandUnitTrainPolicySpec {
|
|
78
|
+
readonly express: {
|
|
79
|
+
readonly by: readonly ('queueFlag' | 'predecessorOf' | 'multiplierTier' | 'p0InCutWindow2h')[];
|
|
80
|
+
readonly waitsForBatch: false;
|
|
81
|
+
readonly directive: string;
|
|
82
|
+
};
|
|
83
|
+
readonly batch: {
|
|
84
|
+
readonly min: number;
|
|
85
|
+
readonly max: number;
|
|
86
|
+
readonly groupBy: readonly ('area' | 'cellPrefix')[];
|
|
87
|
+
readonly maxWaitMin: number;
|
|
88
|
+
readonly order: readonly ('express' | 'predecessor' | 'enqueued')[];
|
|
89
|
+
readonly directive: string;
|
|
90
|
+
};
|
|
91
|
+
readonly scenarioPrebuild: {
|
|
92
|
+
readonly source: readonly ('src/ux-sim' | 'scenarios/ux-sim' | 'fake-llm' | 'fake-harness')[];
|
|
93
|
+
readonly mock: 'required';
|
|
94
|
+
readonly directive: string;
|
|
95
|
+
};
|
|
96
|
+
readonly gate: { readonly oncePerBatch: true; readonly directive: string };
|
|
97
|
+
readonly land: {
|
|
98
|
+
readonly perPr: 'squash';
|
|
99
|
+
readonly pinnedHead: true;
|
|
100
|
+
readonly ejectOnFail: true;
|
|
101
|
+
readonly integrationPr: false;
|
|
102
|
+
readonly directive: string;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
70
106
|
export interface GraphParseIssue {
|
|
71
107
|
readonly path: string;
|
|
72
108
|
readonly message: string;
|
|
@@ -80,6 +116,7 @@ export interface GraphParseResult {
|
|
|
80
116
|
|
|
81
117
|
/** ⚠️ YAML 함정 — `no`/`off`/`yes`/`on` 이 boolean 으로 파싱된다(Norway 문제). 노드 이름에 쓰면 조용히 깨진다. */
|
|
82
118
|
const YAML_TRAP_WORDS = new Set(['true', 'false', 'yes', 'no', 'on', 'off', 'null', '~']);
|
|
119
|
+
export const L1_PROTECTED_ROUTE_NODES = new Set(['gate', 'regate', 'review', 'merge', 'freeze-check']);
|
|
83
120
|
|
|
84
121
|
function asArray(value: unknown): unknown[] {
|
|
85
122
|
return Array.isArray(value) ? value : [];
|
|
@@ -102,6 +139,8 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
|
|
|
102
139
|
|
|
103
140
|
const graphId = typeof doc.graph_id === 'string' ? doc.graph_id : undefined;
|
|
104
141
|
if (graphId === undefined) errors.push({ path: `${label}/graph_id`, message: 'graph_id 가 없거나 문자열이 아니다' });
|
|
142
|
+
const policy = graphId === 'land' ? parseLandUnitTrainPolicy(doc.policy, `${label}/policy`, errors) : undefined;
|
|
143
|
+
if (graphId === 'land' && doc.policy === undefined) errors.push({ path: `${label}/policy`, message: 'land 유닛에는 착지 열차 policy 가 필요하다' });
|
|
105
144
|
const version = typeof doc.version === 'number' && Number.isInteger(doc.version) ? doc.version : undefined;
|
|
106
145
|
if (version === undefined) errors.push({ path: `${label}/version`, message: 'version 이 없거나 정수가 아니다' });
|
|
107
146
|
const entryNode = typeof doc.entry_node === 'string' ? doc.entry_node : undefined;
|
|
@@ -147,6 +186,12 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
|
|
|
147
186
|
: 'journey_stage 는 비어 있지 않은 문자열이어야 한다' });
|
|
148
187
|
continue;
|
|
149
188
|
}
|
|
189
|
+
if (n.skip_when !== undefined) {
|
|
190
|
+
if (typeof n.skip_when !== 'string' || !parseOverlayCondition(n.skip_when).ok)
|
|
191
|
+
errors.push({ path: `${at}/skip_when`, message: 'skip_when 은 오버레이 조건 한 개(key op literal)여야 한다' });
|
|
192
|
+
if (L1_PROTECTED_ROUTE_NODES.has(nodeId) || kind === 'gate' || terminalNodes.includes(nodeId))
|
|
193
|
+
errors.push({ path: `${at}/skip_when`, message: `'${nodeId}' 는 필수 검증·착지·종결 노드라 건너뛸 수 없다` });
|
|
194
|
+
}
|
|
150
195
|
const contractRaw = n.contract as Record<string, unknown> | undefined;
|
|
151
196
|
const contract: GraphNodeContract | undefined = contractRaw && typeof contractRaw === 'object'
|
|
152
197
|
? {
|
|
@@ -190,6 +235,7 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
|
|
|
190
235
|
...(kind === 'subgraph' && n.budget && typeof n.budget === 'object' && !Array.isArray(n.budget) &&
|
|
191
236
|
typeof (n.budget as Record<string, unknown>).inner_steps === 'number'
|
|
192
237
|
? { budget: { innerSteps: (n.budget as { inner_steps: number }).inner_steps } } : {}),
|
|
238
|
+
...(typeof n.skip_when === 'string' ? { skipWhen: n.skip_when } : {}),
|
|
193
239
|
});
|
|
194
240
|
}
|
|
195
241
|
if (nodes.length === 0) errors.push({ path: `${label}/nodes`, message: '노드가 하나도 없다' });
|
|
@@ -205,6 +251,12 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
|
|
|
205
251
|
if (!known.has(from)) { errors.push({ path: `${at}/from`, message: `'${from}' 은 선언된 노드가 아니다` }); continue; }
|
|
206
252
|
const hasTo = typeof e.to === 'string';
|
|
207
253
|
const hasMap = e.map !== null && typeof e.map === 'object';
|
|
254
|
+
if (e.when !== undefined && (typeof e.when !== 'string' || !parseOverlayCondition(e.when).ok))
|
|
255
|
+
errors.push({ path: `${at}/when`, message: 'when 은 오버레이 조건 한 개(key op literal)여야 한다' });
|
|
256
|
+
if (e.when !== undefined && (L1_PROTECTED_ROUTE_NODES.has(from) || nodes.some(node => node.nodeId === from && node.kind === 'gate') || terminalNodes.includes(from)))
|
|
257
|
+
errors.push({ path: `${at}/when`, message: `'${from}' 의 필수 검증·착지 결과는 when 간선으로 덮을 수 없다` });
|
|
258
|
+
if (e.when !== undefined && (!hasTo || hasMap || e.on !== undefined))
|
|
259
|
+
errors.push({ path: `${at}/when`, message: 'when 은 to 간선에서만 쓴다' });
|
|
208
260
|
if (hasTo === hasMap) {
|
|
209
261
|
errors.push({ path: at, message: 'to 와 map 중 «정확히 하나»를 써야 한다' });
|
|
210
262
|
continue;
|
|
@@ -237,8 +289,21 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
|
|
|
237
289
|
...(hasMap ? { on: String(e.on), map } : {}),
|
|
238
290
|
...(fallback.length > 0 ? { fallback } : {}),
|
|
239
291
|
...(typeof e.observed === 'number' ? { observed: e.observed } : {}),
|
|
292
|
+
...(typeof e.when === 'string' ? { when: e.when } : {}),
|
|
240
293
|
});
|
|
241
294
|
}
|
|
295
|
+
for (const node of nodes) {
|
|
296
|
+
if (node.skipWhen === undefined) continue;
|
|
297
|
+
const outgoing = edges.filter(edge => edge.from === node.nodeId);
|
|
298
|
+
if (outgoing.length !== 1 || outgoing[0]?.to === undefined || outgoing[0]?.when !== undefined ||
|
|
299
|
+
(outgoing[0]?.fallback?.length ?? 0) > 0)
|
|
300
|
+
errors.push({ path: `${label}/nodes/${node.nodeId}/skip_when`, message: 'skip_when 노드에는 분기 없는 무조건 to 후속 간선 하나만 필요하다' });
|
|
301
|
+
}
|
|
302
|
+
for (const edge of edges) {
|
|
303
|
+
if (edge.when === undefined) continue;
|
|
304
|
+
if (!edges.some(candidate => candidate.from === edge.from && candidate.when === undefined))
|
|
305
|
+
errors.push({ path: `${label}/edges/${edge.from}/when`, message: 'when 간선에는 모호·미관측 때 탈 무조건 기본 간선이 필요하다' });
|
|
306
|
+
}
|
|
242
307
|
|
|
243
308
|
if (entryNode !== undefined && !known.has(entryNode)) errors.push({ path: `${label}/entry_node`, message: `'${entryNode}' 는 선언된 노드가 아니다` });
|
|
244
309
|
for (const t of terminalNodes) if (!known.has(t)) errors.push({ path: `${label}/terminal_nodes`, message: `'${t}' 는 선언된 노드가 아니다` });
|
|
@@ -288,6 +353,7 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
|
|
|
288
353
|
template: {
|
|
289
354
|
graphId: graphId!, version: version!, entryNode: entryNode!, terminalNodes, nodes, edges,
|
|
290
355
|
...(unit ? { unit } : {}),
|
|
356
|
+
...(policy ? { policy } : {}),
|
|
291
357
|
...(Array.isArray(journeyStages) ? { journeyStages: journeyStages as string[] } : {}),
|
|
292
358
|
...(loop ? { loop } : {}),
|
|
293
359
|
...(typeof doc.docs_only_gate_skip === 'boolean' ? { docsOnlyGateSkip: doc.docs_only_gate_skip } : {}),
|
|
@@ -298,6 +364,89 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
|
|
|
298
364
|
};
|
|
299
365
|
}
|
|
300
366
|
|
|
367
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
368
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function exactKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {
|
|
372
|
+
return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function isEnumList<T extends string>(value: unknown, allowed: readonly T[], expected: readonly T[]): value is T[] {
|
|
376
|
+
return Array.isArray(value) && value.every((item): item is T => typeof item === 'string' && allowed.includes(item as T))
|
|
377
|
+
&& value.length === expected.length && expected.every((item, index) => value[index] === item);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function isDirectiveText(value: unknown): value is string {
|
|
381
|
+
if (typeof value !== 'string') return false;
|
|
382
|
+
const entry = value.replace(/[\p{P}\p{S}\s]/gu, '');
|
|
383
|
+
return entry.length > 0;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function parseLandUnitTrainPolicy(
|
|
387
|
+
value: unknown,
|
|
388
|
+
path: string,
|
|
389
|
+
errors: GraphParseIssue[],
|
|
390
|
+
): LandUnitTrainPolicySpec | undefined {
|
|
391
|
+
if (value === undefined) return undefined;
|
|
392
|
+
const fail = (suffix: string, message: string): void => { errors.push({ path: `${path}${suffix}`, message }); };
|
|
393
|
+
if (!isRecord(value) || !exactKeys(value, ['express', 'batch', 'scenarioPrebuild', 'gate', 'land'])) {
|
|
394
|
+
fail('', 'policy 는 express·batch·scenarioPrebuild·gate·land 만 가진 맵이어야 한다');
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
397
|
+
const express = value.express;
|
|
398
|
+
const batch = value.batch;
|
|
399
|
+
const scenarioPrebuild = value.scenarioPrebuild;
|
|
400
|
+
const gate = value.gate;
|
|
401
|
+
const land = value.land;
|
|
402
|
+
const field = (name: string, raw: unknown, keys: readonly string[]): Record<string, unknown> | undefined => {
|
|
403
|
+
if (!isRecord(raw) || !exactKeys(raw, keys)) {
|
|
404
|
+
fail(`/${name}`, `${name} 필드는 ${keys.join('·')} 키만 가진 맵이어야 한다`);
|
|
405
|
+
return undefined;
|
|
406
|
+
}
|
|
407
|
+
if (!isDirectiveText(raw.directive))
|
|
408
|
+
fail(`/${name}/directive`, 'directive 는 구두점만으로 된 값이 아닌 비어 있지 않은 문자열이어야 한다');
|
|
409
|
+
return raw;
|
|
410
|
+
};
|
|
411
|
+
const e = field('express', express, ['by', 'waitsForBatch', 'directive']);
|
|
412
|
+
const b = field('batch', batch, ['min', 'max', 'groupBy', 'maxWaitMin', 'order', 'directive']);
|
|
413
|
+
const s = field('scenarioPrebuild', scenarioPrebuild, ['source', 'mock', 'directive']);
|
|
414
|
+
const g = field('gate', gate, ['oncePerBatch', 'directive']);
|
|
415
|
+
const l = field('land', land, ['perPr', 'pinnedHead', 'ejectOnFail', 'integrationPr', 'directive']);
|
|
416
|
+
|
|
417
|
+
if (e && !isEnumList(e.by, ['queueFlag', 'predecessorOf', 'multiplierTier', 'p0InCutWindow2h'], ['queueFlag', 'predecessorOf', 'multiplierTier', 'p0InCutWindow2h']))
|
|
418
|
+
fail('/express/by', 'by 는 queueFlag·predecessorOf·multiplierTier·p0InCutWindow2h 를 각각 한 번 포함해야 한다');
|
|
419
|
+
if (e && e.waitsForBatch !== false) fail('/express/waitsForBatch', 'express 는 waitsForBatch: false 여야 한다');
|
|
420
|
+
if (b) {
|
|
421
|
+
if (!Number.isSafeInteger(b.min) || b.min !== 2) fail('/batch/min', 'min 은 정확히 2여야 한다');
|
|
422
|
+
if (!Number.isSafeInteger(b.max) || b.max !== 4) fail('/batch/max', 'max 는 정확히 4여야 한다');
|
|
423
|
+
if (Number.isSafeInteger(b.min) && Number.isSafeInteger(b.max) && (b.min as number) > (b.max as number)) fail('/batch', 'min 은 max 이하여야 한다');
|
|
424
|
+
if (!isEnumList(b.groupBy, ['area', 'cellPrefix'], ['area', 'cellPrefix'])) fail('/batch/groupBy', 'groupBy 는 area·cellPrefix 를 각각 한 번 포함해야 한다');
|
|
425
|
+
if (!Number.isSafeInteger(b.maxWaitMin) || (b.maxWaitMin as number) !== 30) fail('/batch/maxWaitMin', 'maxWaitMin 은 30 정수여야 한다');
|
|
426
|
+
if (!Array.isArray(b.order) || b.order.length !== 3 || b.order.some((item, index) => item !== ['express', 'predecessor', 'enqueued'][index]))
|
|
427
|
+
fail('/batch/order', 'order 는 express·predecessor·enqueued 순이어야 한다');
|
|
428
|
+
}
|
|
429
|
+
if (s && !isEnumList(s.source, ['src/ux-sim', 'scenarios/ux-sim', 'fake-llm', 'fake-harness'], ['src/ux-sim', 'scenarios/ux-sim', 'fake-llm', 'fake-harness']))
|
|
430
|
+
fail('/scenarioPrebuild/source', 'source 는 UX sim·fake LLM·fake harness 네 경로를 각각 한 번 포함해야 한다');
|
|
431
|
+
if (s && s.mock !== 'required') fail('/scenarioPrebuild/mock', 'mock 은 required 여야 한다');
|
|
432
|
+
if (g && g.oncePerBatch !== true) fail('/gate/oncePerBatch', 'oncePerBatch 는 true 여야 한다');
|
|
433
|
+
if (l) {
|
|
434
|
+
if (l.perPr !== 'squash') fail('/land/perPr', 'perPr 은 squash 여야 한다');
|
|
435
|
+
if (l.pinnedHead !== true) fail('/land/pinnedHead', 'pinnedHead 는 true 여야 한다');
|
|
436
|
+
if (l.ejectOnFail !== true) fail('/land/ejectOnFail', 'ejectOnFail 은 true 여야 한다');
|
|
437
|
+
if (l.integrationPr !== false) fail('/land/integrationPr', 'integrationPr 는 false 여야 한다');
|
|
438
|
+
}
|
|
439
|
+
if (!e || !b || !s || !g || !l || errors.some((error) => error.path.startsWith(`${path}/`))) return undefined;
|
|
440
|
+
return {
|
|
441
|
+
express: { by: e.by as LandUnitTrainPolicySpec['express']['by'], waitsForBatch: false, directive: e.directive as string },
|
|
442
|
+
batch: { min: b.min as number, max: b.max as number, groupBy: b.groupBy as LandUnitTrainPolicySpec['batch']['groupBy'], maxWaitMin: b.maxWaitMin as number,
|
|
443
|
+
order: b.order as LandUnitTrainPolicySpec['batch']['order'], directive: b.directive as string },
|
|
444
|
+
scenarioPrebuild: { source: s.source as LandUnitTrainPolicySpec['scenarioPrebuild']['source'], mock: 'required', directive: s.directive as string },
|
|
445
|
+
gate: { oncePerBatch: true, directive: g.directive as string },
|
|
446
|
+
land: { perPr: 'squash', pinnedHead: true, ejectOnFail: true, integrationPr: false, directive: l.directive as string },
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
|
|
301
450
|
/** 정규 JSON — 「같은 그래프인가」를 답하는 유일한 형식. ⛔ 키를 «정렬»해 직렬화 순서를 없앤다. */
|
|
302
451
|
export function canonicalGraphJson(template: GraphTemplateSpec): string {
|
|
303
452
|
const sort = (value: unknown): unknown => {
|
|
@@ -330,7 +479,8 @@ export function loadGraphTemplates(dir: string): GraphLoadResult {
|
|
|
330
479
|
const templates: Record<string, GraphTemplateSpec> = {};
|
|
331
480
|
let files: string[];
|
|
332
481
|
try {
|
|
333
|
-
|
|
482
|
+
// recipes are command catalogs consumed by the runner, not graph templates.
|
|
483
|
+
files = readdirSync(dir).filter((f) => (f.endsWith('.yaml') || f.endsWith('.yml')) && f !== 'recipes.yaml' && f !== 'recipes.yml').sort();
|
|
334
484
|
} catch (error) {
|
|
335
485
|
return { templates, errors: [{ path: dir, message: `그래프 디렉토리를 못 읽었다: ${error instanceof Error ? error.message : String(error)}` }], warnings, scannedFiles: 0 };
|
|
336
486
|
}
|
|
@@ -1329,6 +1329,7 @@ export async function runHeadlessGoalLoopPty(opts: HeadlessGoalLoopPtyOptions):
|
|
|
1329
1329
|
workdir: opts.cwd,
|
|
1330
1330
|
env: {
|
|
1331
1331
|
...(opts.stateDir ? { ELANOUS_STATE_DIR: opts.stateDir } : {}),
|
|
1332
|
+
...(process.env.XDG_DATA_HOME?.trim() ? { XDG_DATA_HOME: process.env.XDG_DATA_HOME } : {}),
|
|
1332
1333
|
[CHILD_LIVENESS_HEARTBEAT_ENV]: resolveChildLivenessHeartbeatPath(opts.cwd),
|
|
1333
1334
|
...controlInboxEnv(controlInboxDir),
|
|
1334
1335
|
// ⛔⭐ 뿌리와 «한 벌»로 간다(`OBS-T121`) — 안 주면 자식이 「파생」을 「명시 격리」로 읽는다.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** Bounded, read-only context from promoted repository knowhow. */
|
|
2
|
+
import { lstatSync, readFileSync, realpathSync, readdirSync, statSync } from 'node:fs';
|
|
3
|
+
import { join, relative, resolve, sep } from 'node:path';
|
|
4
|
+
|
|
5
|
+
export const KNOWHOW_PACK_MAX_BYTES = 4096;
|
|
6
|
+
const MARKER = '[KNOWHOW-PACK v1';
|
|
7
|
+
const SIGNATURES = ['no-progress', 'scope-escape', 'wallclock-cap', 'pod-job-failed', 'gate-failed', 'review-blocked', 'token_revoked'];
|
|
8
|
+
|
|
9
|
+
export interface KnowhowPack {
|
|
10
|
+
text: string;
|
|
11
|
+
ids: string[];
|
|
12
|
+
bytes: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function inside(root: string, path: string): boolean {
|
|
16
|
+
const rel = relative(root, path);
|
|
17
|
+
return rel === '' || (rel !== '..' && !rel.startsWith(`..${sep}`) && !rel.startsWith(sep));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function promotedSections(source: string): Array<{ id: string; text: string }> {
|
|
21
|
+
const sections: Array<{ id: string; text: string }> = [];
|
|
22
|
+
for (const block of source.split(/(?=^## K-[A-Z]+-\d+\b)/m)) {
|
|
23
|
+
const id = /^## (K-[A-Z]+-\d+)\b/m.exec(block)?.[1];
|
|
24
|
+
if (!id || !/^[-*] 출처:.*상태: active\s*$/m.test(block)) continue;
|
|
25
|
+
sections.push({ id, text: block.trim() });
|
|
26
|
+
}
|
|
27
|
+
return sections;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function mentionedPaths(text: string): Set<string> {
|
|
31
|
+
// Keep the complete repository-relative path, including package/docs prefixes.
|
|
32
|
+
// First slice: root filenames have no directory context and are deliberately excluded.
|
|
33
|
+
// A path may use any extension; reject absolute and parent-relative paths as whole tokens.
|
|
34
|
+
const paths = new Set<string>();
|
|
35
|
+
for (const match of text.matchAll(/(?<![\w./~-])([\w.-]+(?:\/[\w.-]+)+)/g)) {
|
|
36
|
+
const path = match[1].replace(/[.,;:!?]+$/, '');
|
|
37
|
+
const segments = path.split('/');
|
|
38
|
+
if (segments.some((segment) => segment === '.' || segment === '..' || !segment)) continue;
|
|
39
|
+
if (!/\.[\w-]+$/.test(segments.at(-1) ?? '')) continue;
|
|
40
|
+
paths.add(path);
|
|
41
|
+
}
|
|
42
|
+
return paths;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function relevance(goal: string, section: string): number {
|
|
46
|
+
const paths = mentionedPaths(goal);
|
|
47
|
+
const sourcePaths = mentionedPaths(section);
|
|
48
|
+
let score = 0;
|
|
49
|
+
for (const path of paths) {
|
|
50
|
+
if (sourcePaths.has(path)) score += 20;
|
|
51
|
+
}
|
|
52
|
+
// A path-scoped remedy must not be selected solely because an unrelated goal shares its failure label.
|
|
53
|
+
// No exact directory path match means no injection, even if the failure label happens to match.
|
|
54
|
+
if (score === 0) return 0;
|
|
55
|
+
for (const signature of SIGNATURES) {
|
|
56
|
+
if (goal.includes(signature) && section.includes(signature)) score += 6;
|
|
57
|
+
}
|
|
58
|
+
return score;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Reads only 내부 문서 `KNOWHOW` inside the supplied repository. */
|
|
62
|
+
export function selectKnowhowPack(repo: string, goal: string): KnowhowPack {
|
|
63
|
+
if (goal.includes(MARKER)) return { text: '', ids: [], bytes: 0 };
|
|
64
|
+
const rolesDir = resolve(repo, 'docs/roles');
|
|
65
|
+
let realRoles: string;
|
|
66
|
+
try {
|
|
67
|
+
realRoles = realpathSync(rolesDir);
|
|
68
|
+
if (!inside(realpathSync(repo), realRoles)) return { text: '', ids: [], bytes: 0 };
|
|
69
|
+
} catch { return { text: '', ids: [], bytes: 0 }; }
|
|
70
|
+
const candidates: Array<{ id: string; text: string; score: number }> = [];
|
|
71
|
+
let seatDirs: string[];
|
|
72
|
+
try { seatDirs = readdirSync(rolesDir).sort(); } catch { return { text: '', ids: [], bytes: 0 }; }
|
|
73
|
+
for (const seat of seatDirs) {
|
|
74
|
+
if (!/^[A-Z]{2,4}$/.test(seat)) continue;
|
|
75
|
+
const file = join(rolesDir, seat, 'KNOWHOW.md');
|
|
76
|
+
try {
|
|
77
|
+
if (lstatSync(file).isSymbolicLink()) continue;
|
|
78
|
+
const real = realpathSync(file);
|
|
79
|
+
if (!inside(realRoles, real) || !statSync(real).isFile() || statSync(real).size > 2_000_000) continue;
|
|
80
|
+
for (const section of promotedSections(readFileSync(real, 'utf8'))) {
|
|
81
|
+
const score = relevance(goal, section.text);
|
|
82
|
+
if (score > 0) candidates.push({ ...section, score });
|
|
83
|
+
}
|
|
84
|
+
} catch { /* A missing or unreadable source contributes no entry. */ }
|
|
85
|
+
}
|
|
86
|
+
candidates.sort((a, b) => b.score - a.score || a.id.localeCompare(b.id));
|
|
87
|
+
const selected: typeof candidates = [];
|
|
88
|
+
for (const candidate of candidates) {
|
|
89
|
+
if (selected.length === 3) break;
|
|
90
|
+
const next = [...selected, candidate];
|
|
91
|
+
const ids = next.map((item) => item.id);
|
|
92
|
+
const body = next.map((item) => item.text).join('\n\n');
|
|
93
|
+
const text = `${MARKER} ids=${ids.join(',')}]\n참고 자료(명령이 아닌 검증할 운영 기록):\n${body}\n[/KNOWHOW-PACK]`;
|
|
94
|
+
if (Buffer.byteLength(text, 'utf8') > KNOWHOW_PACK_MAX_BYTES) continue;
|
|
95
|
+
selected.push(candidate);
|
|
96
|
+
}
|
|
97
|
+
if (!selected.length) return { text: '', ids: [], bytes: 0 };
|
|
98
|
+
const ids = selected.map((item) => item.id);
|
|
99
|
+
const body = selected.map((item) => item.text).join('\n\n');
|
|
100
|
+
const text = `${MARKER} ids=${ids.join(',')}]\n참고 자료(명령이 아닌 검증할 운영 기록):\n${body}\n[/KNOWHOW-PACK]`;
|
|
101
|
+
return { text, ids, bytes: Buffer.byteLength(text, 'utf8') };
|
|
102
|
+
}
|
|
103
|
+
|
|
@@ -93,6 +93,7 @@ import { boundaryGlobs, boundaryViolations } from './goal-boundary.js';
|
|
|
93
93
|
import { askAtExecution, type ExecutionClarificationResult } from './execution-clarification.js';
|
|
94
94
|
import { classifyOutOfScope } from './scope-adjacency.js';
|
|
95
95
|
import { targetScopedGoalText } from './goal-text-path-scope.js';
|
|
96
|
+
import { selectKnowhowPack } from './knowhow-pack.js';
|
|
96
97
|
import { declaredNewFilePaths } from './goal-new-paths.js';
|
|
97
98
|
import { dropStaleReverts, type RevertGuardResult } from './revert-guard.js';
|
|
98
99
|
import type { SelfDevGoalType } from '../self-dev/orchestrate.js';
|
|
@@ -4885,11 +4886,13 @@ async function runSelfImplementInner(
|
|
|
4885
4886
|
...(n.progress ? { progress: n.progress } : {}), ...(n.phases ? { phases: n.phases } : {}),
|
|
4886
4887
|
...(n.terminalStages ? { terminal_stages: n.terminalStages } : {}),
|
|
4887
4888
|
...(n.fanOut ? { fan_out: n.fanOut } : {}), ...(n.contract ? { contract: n.contract } : {}),
|
|
4889
|
+
...(n.skipWhen ? { skip_when: n.skipWhen } : {}),
|
|
4888
4890
|
})),
|
|
4889
4891
|
edges: variantSpec.edges.map(e => ({
|
|
4890
4892
|
from: e.from, ...(e.to === undefined ? { on: e.on, map: e.map } : { to: e.to }),
|
|
4891
4893
|
...(e.fallback ? { fallback: e.fallback } : {}),
|
|
4892
4894
|
...(e.observed === undefined ? {} : { observed: e.observed }),
|
|
4895
|
+
...(e.when ? { when: e.when } : {}),
|
|
4893
4896
|
})),
|
|
4894
4897
|
}), { flag: 'wx' });
|
|
4895
4898
|
observe('graph-variant-applied', { graphId: variant.template.graphId, overlayId: variant.overlay.overlayId,
|
|
@@ -5251,6 +5254,11 @@ async function runSelfImplementInner(
|
|
|
5251
5254
|
} else observe('memory', { injected: false });
|
|
5252
5255
|
}
|
|
5253
5256
|
|
|
5257
|
+
// The repository copy travels with both local and Pod worktrees. Operational HQ ledgers are never read here.
|
|
5258
|
+
const knowhow = selectKnowhowPack(wt.path, opts.feature);
|
|
5259
|
+
if (knowhow.text) round0Feature = `${knowhow.text}\n\n${round0Feature}`;
|
|
5260
|
+
observe('knowhow-pack', { ids: knowhow.ids, bytes: knowhow.bytes, injected: knowhow.bytes > 0 });
|
|
5261
|
+
|
|
5254
5262
|
const maxRework = Math.max(0, opts.maxReworkRounds ?? 2);
|
|
5255
5263
|
const selfImplementConfig = (await import('../user-config.js')).getUserConfig().tools.selfImplement;
|
|
5256
5264
|
const shadowStop = opts.reworkBudgetShadowStop ?? selfImplementConfig.reworkBudget.shadowStop;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Warm-pool profile labels select a host/tier allocation policy. */
|
|
2
|
+
export const WARM_POOL_PROFILES = ['fixed', 'gate', 'landing', 'feature'] as const;
|
|
3
|
+
export type WarmPoolProfile = (typeof WARM_POOL_PROFILES)[number];
|
|
4
|
+
export type WarmPoolTier = 'lite' | 'standard';
|
|
5
|
+
const STANDARD_HOST_MAX: Readonly<Record<string, number>> = {
|
|
6
|
+
node-b: 16,
|
|
7
|
+
node-c: 4,
|
|
8
|
+
'host-e-wsl': 5,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// Only this host/tier pair has a measured lite allocation. Other pairs fail closed to zero.
|
|
12
|
+
const LITE_HOST_MAX: Readonly<Record<string, number>> = { mbp: 7 };
|
|
13
|
+
|
|
14
|
+
export function isWarmPoolProfile(value: unknown): value is WarmPoolProfile {
|
|
15
|
+
return typeof value === 'string' && (WARM_POOL_PROFILES as readonly string[]).includes(value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Parse a configured profile. Missing or invalid values fail closed to the fixed profile. */
|
|
19
|
+
function parseWarmPoolProfile(value: unknown): WarmPoolProfile {
|
|
20
|
+
return isWarmPoolProfile(value) ? value : 'fixed';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Read the profile from either the full config object or its pod section. */
|
|
24
|
+
export function resolveWarmPoolProfile(config: unknown): WarmPoolProfile {
|
|
25
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) return 'fixed';
|
|
26
|
+
const root = config as Record<string, unknown>;
|
|
27
|
+
const pod = root.pod && typeof root.pod === 'object' && !Array.isArray(root.pod)
|
|
28
|
+
? root.pod as Record<string, unknown>
|
|
29
|
+
: root;
|
|
30
|
+
const raw = root.raw && typeof root.raw === 'object' && !Array.isArray(root.raw)
|
|
31
|
+
? root.raw as Record<string, unknown>
|
|
32
|
+
: undefined;
|
|
33
|
+
const rawPod = raw?.pod && typeof raw.pod === 'object' && !Array.isArray(raw.pod)
|
|
34
|
+
? raw.pod as Record<string, unknown>
|
|
35
|
+
: undefined;
|
|
36
|
+
return parseWarmPoolProfile(pod.warmPoolProfile ?? rawPod?.warmPoolProfile);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Physical warm-worker cap for a host and worker memory tier; unknown pairs are unmeasured (0). */
|
|
40
|
+
export function resolveWarmPoolQuota(profile: WarmPoolProfile, host: string, tier: WarmPoolTier): number {
|
|
41
|
+
if (!isWarmPoolProfile(profile) || !host.trim()) return 0;
|
|
42
|
+
if (tier === 'lite') return Object.hasOwn(LITE_HOST_MAX, host) ? LITE_HOST_MAX[host] : 0;
|
|
43
|
+
if (tier === 'standard') return Object.hasOwn(STANDARD_HOST_MAX, host) ? STANDARD_HOST_MAX[host] : 0;
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
@@ -113,3 +113,206 @@ export function classifyMustFixRound(
|
|
|
113
113
|
}
|
|
114
114
|
return { class: 'new-defect', reason: '앞 회차에 없던 새 지적 — 새 실결함 수렴으로 그대로 간다' };
|
|
115
115
|
}
|
|
116
|
+
|
|
117
|
+
// ── 범위 판정 축 (REVIEW-MUSTFIX-CLASSIFY 첫 조각 · 대표 10-17 19:3x) ──
|
|
118
|
+
//
|
|
119
|
+
// 회차 분류(①②③) 위에 must-fix «한 줄마다» 범위를 가른다:
|
|
120
|
+
// in-scope (가) 이 PR 범위 안 — 언급한 파일이 PR 변경 파일·칸 대상 경로 안이고, 쪼갤 신호가 없다 → 고친다.
|
|
121
|
+
// split (나) 새 축 — PR 밖 파일 · 다른 PR · 설계 문서 · 다른 자리 결정 · 앞 라운드에 없던 축(r≥3) · ③ recurring
|
|
122
|
+
// · ② 착지 뒤 증거(③·② 는 범위 입력·경로와 무관하게 split) → 같은 런에서 고치지 않고 «중간 착지 ⊕ 연결 골»로 뗀다.
|
|
123
|
+
// ask-owner (다) 판단 불가 — 신호가 엇갈리거나, 범위 입력(변경 파일·대상 경로)이 없거나, 신호가 하나도 없다 → 칸 주인 HITL.
|
|
124
|
+
// ⛔ 결정적 신호만(이 조각엔 LLM 판정 없음). ⛔ 입력이 없으면 «범위 밖 신호 없음»으로 읽지 않는다 — ask-owner.
|
|
125
|
+
// ⛔ in-scope 는 «긍정 증거»(PR 안 파일 언급)가 있을 때만 — 신호가 없다고 범위 안이 아니다.
|
|
126
|
+
|
|
127
|
+
export type MustFixScope = 'in-scope' | 'split' | 'ask-owner';
|
|
128
|
+
|
|
129
|
+
export type MustFixScopeSignal =
|
|
130
|
+
| 'path-inside' | 'path-outside' | 'other-pr' | 'design-doc' | 'seat-decision'
|
|
131
|
+
| 'new-axis' | 'recurring' | 'post-land-evidence' | 'no-scope-input' | 'no-signal'
|
|
132
|
+
/** PR 번호를 언급했지만 이 PR 번호를 모른다 — 자기 번호일 수 있어 other-pr 로 단정하지 않는다. */
|
|
133
|
+
| 'pr-unknown'
|
|
134
|
+
/** 대상 경로 밖이지만 PR 변경 파일을 안 쟀다 — 실제 변경 파일일 수 있어 «밖»으로 단정하지 않는다. */
|
|
135
|
+
| 'path-unmeasured';
|
|
136
|
+
|
|
137
|
+
export interface MustFixScopeInput {
|
|
138
|
+
/** PR 변경 파일 목록. undefined = 안 쟀다(빈 배열과 다르다). */
|
|
139
|
+
readonly changedFiles?: readonly string[];
|
|
140
|
+
/** 칸·골 대상 경로(hotPaths). undefined = 안 쟀다. */
|
|
141
|
+
readonly targetPaths?: readonly string[];
|
|
142
|
+
/** 이 PR 번호 — 자기 번호 언급은 «다른 PR» 이 아니다. */
|
|
143
|
+
readonly prNumber?: number;
|
|
144
|
+
/** 리뷰 라운드(1부터). undefined = 안 쟀다 → new-axis 신호를 안 낸다. */
|
|
145
|
+
readonly reviewRound?: number;
|
|
146
|
+
/** 앞 라운드 must-fix. undefined = 안 쟀다 → new-axis 신호를 안 낸다. */
|
|
147
|
+
readonly prevItems?: readonly MustFixItem[];
|
|
148
|
+
/** 이 회차 ③ recurring 으로 짝지어진 정규화 문면. */
|
|
149
|
+
readonly recurring?: readonly string[];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface MustFixScopeJudgement {
|
|
153
|
+
readonly text: string;
|
|
154
|
+
readonly scope: MustFixScope;
|
|
155
|
+
readonly signals: readonly MustFixScopeSignal[];
|
|
156
|
+
readonly reason: string;
|
|
157
|
+
/** 언급한 경로 중 PR 범위 밖인 것 — 연결 골 대상 경로 초안. */
|
|
158
|
+
readonly outsidePaths?: readonly string[];
|
|
159
|
+
/** 언급한 경로 중 PR 범위 안인 것. */
|
|
160
|
+
readonly insidePaths?: readonly string[];
|
|
161
|
+
/** ② 착지 뒤 증거 종류 — 연결 골 판정선을 시험이 아니라 착지 후 관측으로 낸다. */
|
|
162
|
+
readonly evidence?: MustFixEvidenceKind;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const SPLIT_SIGNALS: ReadonlySet<MustFixScopeSignal> = new Set([
|
|
166
|
+
'path-outside', 'other-pr', 'design-doc', 'seat-decision', 'new-axis', 'recurring', 'post-land-evidence',
|
|
167
|
+
]);
|
|
168
|
+
/** «앞 라운드에 없던 축»이 쪼갤 신호가 되는 첫 라운드(대표 규칙 «r3 부터 (나) 먼저 뗀다»). */
|
|
169
|
+
export const NEW_AXIS_SPLIT_FROM_ROUND = 3;
|
|
170
|
+
|
|
171
|
+
const PATH_RE = /(?:[\w@.-]+\/)+[\w@.-]+\.[A-Za-z]{1,5}\b|\b[\w-]+(?:\.[\w-]+)*\.(?:tsx?|mjs|cjs|jsx?|json|md|ya?ml|sh|py)\b/gu;
|
|
172
|
+
const DESIGN_DOC_RE = /\b(?:RFC|MANUAL|DECISION)[-_\s]/u;
|
|
173
|
+
const SEAT_DECISION_RE = /(?:다른\s*자리|자리\s*결정|대표\s*결정|\u{1F451}|owner\s+decision|another\s+seat)/iu;
|
|
174
|
+
|
|
175
|
+
function normPath(p: string): string {
|
|
176
|
+
return p.replace(/^\.\//u, '').replace(/[),.;:]+$/u, '');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** 경로가 범위 집합 안인가 — 정확 일치 · 디렉터리 접두 · (언급이 파일 이름뿐이면) 파일 이름 일치. */
|
|
180
|
+
function pathInside(mention: string, scope: readonly string[]): boolean {
|
|
181
|
+
const m = normPath(mention);
|
|
182
|
+
return scope.some((raw) => {
|
|
183
|
+
const s = normPath(raw);
|
|
184
|
+
if (s === m) return true;
|
|
185
|
+
if (s.endsWith('/') ? m.startsWith(s) : m.startsWith(`${s}/`)) return true;
|
|
186
|
+
return !m.includes('/') && s.split('/').at(-1) === m;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** 단순 토큰 자카드(2자 이상 · 소문자) — 앞 라운드에 없던 축 판정용. */
|
|
191
|
+
export function mustFixTokenJaccard(a: string, b: string): number {
|
|
192
|
+
const tok = (s: string): Set<string> => new Set(s.toLowerCase().split(/[^\p{L}\p{N}_]+/u).filter((t) => t.length >= 2));
|
|
193
|
+
const x = tok(a);
|
|
194
|
+
const y = tok(b);
|
|
195
|
+
if (x.size === 0 && y.size === 0) return 0;
|
|
196
|
+
let inter = 0;
|
|
197
|
+
for (const t of x) if (y.has(t)) inter++;
|
|
198
|
+
return inter / (x.size + y.size - inter);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function judgeMustFixScope(item: MustFixItem, input: MustFixScopeInput): MustFixScopeJudgement {
|
|
202
|
+
const signals: MustFixScopeSignal[] = [];
|
|
203
|
+
const scopePaths = [...(input.changedFiles ?? []), ...(input.targetPaths ?? [])];
|
|
204
|
+
const scopeMeasured = input.changedFiles !== undefined || input.targetPaths !== undefined;
|
|
205
|
+
const mentions = [...new Set((item.text.match(PATH_RE) ?? []).map(normPath))];
|
|
206
|
+
const insidePaths = scopeMeasured ? mentions.filter((m) => pathInside(m, scopePaths)) : [];
|
|
207
|
+
const outsidePaths = scopeMeasured ? mentions.filter((m) => !pathInside(m, scopePaths)) : mentions;
|
|
208
|
+
if (!scopeMeasured) signals.push('no-scope-input');
|
|
209
|
+
else {
|
|
210
|
+
if (insidePaths.length) signals.push('path-inside');
|
|
211
|
+
// 변경 파일을 안 쟀으면 대상 경로 밖이라는 사실만으로 «PR 밖»이 아니다.
|
|
212
|
+
if (outsidePaths.length) signals.push(input.changedFiles === undefined ? 'path-unmeasured' : 'path-outside');
|
|
213
|
+
}
|
|
214
|
+
const prs = [...item.text.matchAll(/#(\d{5})\b/gu)].map((m) => Number(m[1]));
|
|
215
|
+
if (prs.length > 0 && input.prNumber === undefined) signals.push('pr-unknown');
|
|
216
|
+
else if (prs.some((n) => n !== input.prNumber)) signals.push('other-pr');
|
|
217
|
+
if (DESIGN_DOC_RE.test(item.text)) signals.push('design-doc');
|
|
218
|
+
if (SEAT_DECISION_RE.test(item.text)) signals.push('seat-decision');
|
|
219
|
+
if (item.evidence !== undefined) signals.push('post-land-evidence');
|
|
220
|
+
if (input.recurring?.includes(mustFixKey(item.text))) signals.push('recurring');
|
|
221
|
+
if (input.reviewRound !== undefined && input.reviewRound >= NEW_AXIS_SPLIT_FROM_ROUND
|
|
222
|
+
&& input.prevItems !== undefined && input.prevItems.length > 0
|
|
223
|
+
&& input.prevItems.every((p) => mustFixTokenJaccard(p.text, item.text) === 0)) signals.push('new-axis');
|
|
224
|
+
|
|
225
|
+
const split = signals.filter((s) => SPLIT_SIGNALS.has(s));
|
|
226
|
+
const paths = {
|
|
227
|
+
...(outsidePaths.length ? { outsidePaths } : {}),
|
|
228
|
+
...(insidePaths.length ? { insidePaths } : {}),
|
|
229
|
+
...(item.evidence !== undefined ? { evidence: item.evidence } : {}),
|
|
230
|
+
};
|
|
231
|
+
if (signals.includes('recurring')) {
|
|
232
|
+
return { text: item.text, scope: 'split', signals, reason: '같은 축이 수리 뒤 다시 나왔다 — 같은 런 재수리 대신 연결 골로 뗀다', ...paths };
|
|
233
|
+
}
|
|
234
|
+
// ② 착지 뒤 증거는 줄 단위 사실 — 경로가 PR 안이어도 같은 런에서 못 낸다. 회차 분류 ② 와 늘 같은 갈래(split)로 간다.
|
|
235
|
+
if (signals.includes('post-land-evidence')) {
|
|
236
|
+
return { text: item.text, scope: 'split', signals, reason: '증거는 착지 뒤에만 난다 — 그림자 착지 → 관측 → live 연결 골로 뗀다', ...paths };
|
|
237
|
+
}
|
|
238
|
+
if (signals.includes('path-unmeasured')) {
|
|
239
|
+
return { text: item.text, scope: 'ask-owner', signals, reason: '대상 경로 밖 경로를 언급했지만 PR 변경 파일을 안 쟀다 — PR 밖인지 못 가린다', ...paths };
|
|
240
|
+
}
|
|
241
|
+
if (signals.includes('pr-unknown')) {
|
|
242
|
+
return { text: item.text, scope: 'ask-owner', signals, reason: 'PR 번호를 언급했는데 이 PR 번호를 모른다 — 다른 PR 인지 못 가린다', ...paths };
|
|
243
|
+
}
|
|
244
|
+
if (split.length > 0 && !scopeMeasured) {
|
|
245
|
+
return { text: item.text, scope: 'ask-owner', signals, reason: `쪼갤 신호(${split.join(' · ')})는 있으나 범위 입력이 없다 — 이 PR 이 이미 맡았는지 못 가린다`, ...paths };
|
|
246
|
+
}
|
|
247
|
+
if (split.length > 0 && signals.includes('path-inside')) {
|
|
248
|
+
return { text: item.text, scope: 'ask-owner', signals, reason: `신호가 엇갈린다 — PR 안 파일 언급 ⊕ 쪼갤 신호(${split.join(' · ')})`, ...paths };
|
|
249
|
+
}
|
|
250
|
+
if (split.length > 0) {
|
|
251
|
+
return { text: item.text, scope: 'split', signals, reason: `이 PR 범위 밖 신호(${split.join(' · ')}) — 중간 착지 ⊕ 연결 골로 뗀다`, ...paths };
|
|
252
|
+
}
|
|
253
|
+
if (signals.includes('path-inside')) {
|
|
254
|
+
return { text: item.text, scope: 'in-scope', signals, reason: '언급한 파일이 PR 범위 안이고 쪼갤 신호가 없다 — 이 PR 에서 고친다', ...paths };
|
|
255
|
+
}
|
|
256
|
+
if (scopeMeasured) signals.push('no-signal');
|
|
257
|
+
return {
|
|
258
|
+
text: item.text, scope: 'ask-owner', signals,
|
|
259
|
+
reason: scopeMeasured ? '범위 신호가 하나도 없다 — «없다»를 범위 안으로 읽지 않고 칸 주인에게 묻는다' : '범위 입력(변경 파일·대상 경로)이 없다 — 칸 주인에게 묻는다',
|
|
260
|
+
...paths,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** (나) split 한 줄의 «중간 착지 ⊕ 연결 골» 제안 — 다음 라운드 intent 스코프 경계 문장 ⊕ 연결 골 초안. */
|
|
265
|
+
export interface MustFixSplitProposal {
|
|
266
|
+
readonly text: string;
|
|
267
|
+
/** 다음 라운드 intent «의도적 스코프 경계» 에 넣을 문장(이유 포함). */
|
|
268
|
+
readonly intentScopeBoundary: string;
|
|
269
|
+
/** 연결 골 초안 — 대상 경로 ⊕ 판정선 한 줄. targetPaths 가 비면 «대상 경로 미상»(저작 단계에서 채운다). */
|
|
270
|
+
readonly linkGoal: { readonly targetPaths: readonly string[]; readonly verdictLine: string };
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function clip(text: string, n = 120): string {
|
|
274
|
+
const t = text.trim().replace(/\s+/gu, ' ');
|
|
275
|
+
return t.length > n ? `${t.slice(0, n - 1)}…` : t;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function testPathFor(path: string): string | undefined {
|
|
279
|
+
if (/\.test\.tsx?$/u.test(path)) return path;
|
|
280
|
+
const m = /^(.*)\.(tsx?)$/u.exec(path);
|
|
281
|
+
return m ? `${m[1]}.test.${m[2]}` : undefined;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const EVIDENCE_OBSERVATION: Record<MustFixEvidenceKind, string> = {
|
|
285
|
+
'live-caller': 'live 호출자가 실제로 부르는 것',
|
|
286
|
+
'ops-consumption': '운영이 실제로 소비하는 것',
|
|
287
|
+
'artifact-landing': '실물이 실제로 착지한 것',
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* 연결 골 대상 경로는 지적이 «언급한» 경로만 — 원래 골의 hotPaths 를 끌어다 대지 않는다(근거 없음 → 미상, 저작 단계에서 채운다).
|
|
292
|
+
* ② 착지 뒤 증거는 시험 통과로 증명되지 않으므로 판정선을 «그림자 착지 뒤 관측»으로 낸다.
|
|
293
|
+
*/
|
|
294
|
+
export function proposeMustFixSplit(j: MustFixScopeJudgement): MustFixSplitProposal {
|
|
295
|
+
const targetPaths = j.outsidePaths?.length ? [...j.outsidePaths] : j.insidePaths?.length ? [...j.insidePaths] : [];
|
|
296
|
+
const test = targetPaths.map(testPathFor).find((p): p is string => p !== undefined);
|
|
297
|
+
const subject = clip(j.text, 80);
|
|
298
|
+
if (j.evidence !== undefined) {
|
|
299
|
+
return {
|
|
300
|
+
text: j.text,
|
|
301
|
+
intentScopeBoundary: `«${subject}» — 미완이 아니라 이 PR 의 결정이다: ${j.reason}(신호 ${j.signals.join(' · ')}). 연결 골로 뗐다 · 이것으로 must-fix 를 만들지 말 것`,
|
|
302
|
+
linkGoal: {
|
|
303
|
+
targetPaths,
|
|
304
|
+
verdictLine: `판정(착지 뒤 관측): 그림자 착지 뒤 ${EVIDENCE_OBSERVATION[j.evidence]}을 로그·원장에서 관측 — 관측 명령은 저작 단계에서 채운다(시험 통과만으로는 증명 아님)`,
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
text: j.text,
|
|
310
|
+
intentScopeBoundary: `«${subject}» — 미완이 아니라 이 PR 의 결정이다: ${j.reason}(신호 ${j.signals.join(' · ')}). 연결 골로 뗐다 · 이것으로 must-fix 를 만들지 말 것`,
|
|
311
|
+
linkGoal: {
|
|
312
|
+
targetPaths,
|
|
313
|
+
verdictLine: test
|
|
314
|
+
? `판정: bun test ${test} → «${subject}» 고정 시험 ⊕ 0 fail`
|
|
315
|
+
: `판정: «${subject}» 해소를 반증 명령 한 줄로 — 대상 경로 ${targetPaths.length ? targetPaths.join(' ') : '미상'}(저작 단계에서 채운다)`,
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
}
|