elanous 0.2.43 → 0.2.44
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/{Om5xS9jpjSXJCeTNGYEi4 → HMXsxdy5MIIcHPMHv1wD4}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{3557ac4a.c8931684475018ad.js → 08334415.f0e80896acbef722.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1032-78ba4f6391258cab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1082-53f86a26e03d309d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1109-7d0e264f6f2edbc7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1124-7c26330402481143.js +1 -0
- package/apps/pwa/out/_next/static/chunks/118.2a89982fe4276880.js +23 -0
- package/apps/pwa/out/_next/static/chunks/1244.6c435dbf1bf21d8a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1252.9e665904d3aa3b1a.js +32 -0
- package/apps/pwa/out/_next/static/chunks/1266.a46cc33cb6a72d75.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{3955.6922286237f2ac2b.js → 1306.967240ede9a0f757.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1344.3b95f3bd1b77a3fe.js +94 -0
- package/apps/pwa/out/_next/static/chunks/{5628.6ddb2d5ffba4ff4c.js → 1401.22dfe92640a2b1ac.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/1431-f7c78bd5be21e011.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1451-cdd35a8a0b31834b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2573.387a707f6f9d720c.js → 1694.18debfd77562e56d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1708-f03d587b7a7545c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1775-fa7152bdeff6c95f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/178-4da509cd7266672a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7910-6f139bcafd238b9f.js → 1850-522de4ee34957210.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1876-c6f6e0ddcc76c6a1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1976.097066b072432242.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1406.a1dc2ab6f8449374.js → 1978.eeb60a606dc5deac.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{3402.44b565b314f2263c.js → 2043.e233e3b5a3e790f5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2150.71b94e3348107c83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2158.ebc6fc5a10280ab7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3694.e0099884345f0198.js → 2216.802962c04f40a26e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2294.7890edcfa046c97d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/235.c89aaae4bcd6233a.js +74 -0
- package/apps/pwa/out/_next/static/chunks/239.de075467b5523469.js +287 -0
- package/apps/pwa/out/_next/static/chunks/{1200.6a37c202f9f17e9a.js → 249.ba7051590d603c8f.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/2571.a6ac4e26c8618403.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2610.e149cd564a08913e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2705.9816f3c244f8b85f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2801.afeb8a4dae22f85f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3935.16701e33f8982dc9.js → 2954.bbefc95d6b20e0d8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{aa57532f.510551854ff239b1.js → 2e0f720a.a0697c08e3806a60.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3042.96ec235fe41c8d4e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3097-8e358f158acef46b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3205-93b1abe28b4fb16a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3273.b4434f0dcae7eb29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3311.9cbc43ea0c90d60c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5930.8b4df3b46c32b05a.js → 3349.b5f09ee474d9533e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5866.366966af47fdde5d.js → 3503.a47a9755fb4d97b0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3506-5f429b3b7e1392b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7900.096f455c7c1efc53.js → 3843.bad404d008893291.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3877-4b40e530b47e3bf9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/435-ce2958253cf7de61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8588.d1c6a2903727ce87.js → 4393.28fa5228d0eec217.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/4404.7281c847c6e10dfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8062-7cd0bcc7f01455ba.js → 4415-b9d6a90960920a4a.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{8313-dfa1021bb58a46d6.js → 447-5b304de1fe098f43.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4484-8ebea83d431e6fae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6944.309f4e3ea54d1537.js → 4502.bdcc877abd437a05.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4599-f95790fc5c65b8df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3072.01338851ca21a6f7.js → 46.57c783fa4884714f.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/463-b9114e411f33728e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4659.a57d1f0c5d754cd2.js +36 -0
- package/apps/pwa/out/_next/static/chunks/4722-a847e7a28115035f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8986.8e2e4efbfa655c59.js → 4757.67c6d7473a038e78.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4874-c86f878ec4502ad3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4891.3f80ba517a3b2373.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8205.282ca4bb62d54a0a.js → 4998.810ca8833084caa9.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/4f98febc.ea5841d4d616bfb2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5789.2da35c258292e1e5.js → 5052.7dbb12a55d4f18f5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5166-ca73b3e361085a6d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5180-039f4a18b07ad387.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5232.5a2ce4daf7a9e11d.js +115 -0
- package/apps/pwa/out/_next/static/chunks/{9770.5f75bc6088b16109.js → 5439.3fec6dbce29ecb36.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1313-19f737e0222c4444.js → 5612-074d9a5e00dfac6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5675-01989d524a84c505.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5751.af641a1adf5ec697.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5758-c6cb98714d18ab0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/578eded8.b582637306e16964.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{3969.272ee7f9fd6c62e5.js → 5790.5eb06a653ebd8571.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5853-4033e5bd5afbe06b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5904.97d70bb7f46b2db7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6540.c7bef57ad8f90a87.js → 5989.7ecd362c5c44b747.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{0ad6802e.ae7afb63fdcb4491.js → 5a34fb2f.52f1b4e1baebb48a.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{0966f8a1.745fcd44f64a87ea.js → 5a5078f8.2099200e5ea95e16.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6036-c302c34ff0b3d410.js +1 -0
- package/apps/pwa/out/_next/static/chunks/606.ef81c313381f4264.js +1 -0
- package/apps/pwa/out/_next/static/chunks/616.1af54a928b1ba704.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6201.bc936f71f613a8e9.js +41 -0
- package/apps/pwa/out/_next/static/chunks/6204-fdc86e0e64c4f92d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2144.25b292396712196d.js → 6245.1182e007e9d230d9.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{363bfab3.9623b9f89363541f.js → 63699a35.17262e162bc514b2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6420.494801a80030160c.js +27 -0
- package/apps/pwa/out/_next/static/chunks/{d96660fb.cbc21a2a88539dbb.js → 6549dad0.2740b25e51bf8f05.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{5564.9e72532188f57586.js → 6881.9e7955847640c7fe.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/6931.fcdfb94141e67b3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6991-8e081c6ce38c0ba1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3903.3ef4656c67572764.js → 7010.1bbd17a7f2b3e376.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7029.d1466acf55fae2ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7152-a123aa8e129c131f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7455.196168fffac3b9c4.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7638.6ca4770dd1129138.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7649-f37d76260e5e2a5a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2312.0c8b61e22d3136d7.js → 7679.32c40cdd14f20b4a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7751.04bfbd16b4c6cd0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7864.b1ff31d4030b8994.js +148 -0
- package/apps/pwa/out/_next/static/chunks/7869-c47bd2c075c1fefa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4199.ce86b281fd0a60b7.js → 8442.2f09ca969d631615.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8445.2738dbd59a78c78c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8447.5510c439f9938c6d.js +286 -0
- package/apps/pwa/out/_next/static/chunks/8551.f762945c2cda2e95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8635-57a9d8d9db70f4f1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{fb7d20d5-6892502b6ee39ca6.js → 86961958-4b0689a5048f756b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8709.3c6019bb18f8554f.js +8 -0
- package/apps/pwa/out/_next/static/chunks/8759.c999528a0a907bf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/87f498e5-0881de09f2e44707.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8843.c3197f904c952b81.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{cb0f8df8.09a4a6be97e3fc5f.js → 892fd990.456232f326cc39c2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{837-81336ebaca8198a8.js → 8965-135a2c9eaa2464cb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8971-8d3b9c96f8a6c958.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9059.c8598d96f8e5e9cd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9115.90447ae198b84eae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9147.d9b0a02e0babc9b4.js +93 -0
- package/apps/pwa/out/_next/static/chunks/9204-83075f4b70c61cdc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9244-c32ef14b5dc72bdf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/930.2a9a30f964350c66.js +90 -0
- package/apps/pwa/out/_next/static/chunks/{8637.90f92d5c8db4732c.js → 9398.1f56e3f17795f43f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9527.3e5ad31c891c5fcb.js +79 -0
- package/apps/pwa/out/_next/static/chunks/9571-4ac933e774d1225c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-9fc644de2d8edae3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-0c9dace2db62bee8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f5e65c3dc9d89f2a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-2a9c19b9a140b7b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-61533ad92141adfb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-112004ced6fd0329.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-f733318c237a49d8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-51ea677d2d33bbc0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-428b41f2f9566e3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-1b29396ea90a61e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-cf83ec613ac904bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-3f4c0ecbc284bb5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-b63c322f54f70cc6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-fe328c4ee9aac6b4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-bfb855c584f0fb98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-9fc644de2d8edae3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-47b1710c110eabd7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-42895214458bc6d2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-d03de0ebd8366e23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-3ed6c47e4b1c61c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-ae653e9bf261c738.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-23f3f0a0209c0ac4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-88c691273aae66f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e187ac52a95538b3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-6e45828daed1295e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-edb5d7287bb46186.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-4a7eaacd93c3f6a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ca073d43d74cc84.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1e9fee67b1199436.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-df1283ea963c6816.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-19fcf8d8301ccd18.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-5ab699e0303bbb40.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-7cde0d29756984c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-9d4c598e8ee22f7a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-cc1609a71f44ec62.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7659a9a1345bfaa9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-0afef60ecc0c4af5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-a3553949f8f34f5f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-9fc644de2d8edae3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-057a69702f3c67c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-c0f0e570f3f74c73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-1825071ae34e3b89.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-6244e3e135d8ccfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-0a815f34367b6db6.js → page-da787e8a10b8a82e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-1316d32498e2be42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-4df94572e343de2e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-708969f7475e88c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-c58add08c919a1dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-a24847f45e5d5bf9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-acfec65a3a60e22e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-3dfc598e6fbde245.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-c658a626118411b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-4c73685fd891445b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-6310f7e5de7dd01d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-51c326bf48610be1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-d0beadf754da59b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-acd243bfbf3f6732.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/graphs/overlays/README.md +6 -0
- package/graphs/release/release-loop.yaml +33 -17
- package/graphs/units/verbs/make-doc.yaml +1 -0
- package/package.json +1 -1
- package/scripts/bench-metering-plan.ts +229 -0
- package/scripts/demo/demo1104-parallel-host.ts +56 -0
- package/scripts/demo/demo1104-parallel.ts +72 -0
- package/scripts/public-leak-baseline.txt +0 -1
- package/scripts/release-loop/docs-node.ts +4 -2
- package/scripts/release-loop/gate-image-pin.ts +116 -2
- package/scripts/release-loop/gate-node.ts +217 -25
- package/scripts/release-loop/gate-progress-sim.ts +73 -0
- package/scripts/release-loop/notes-repair.ts +18 -1
- package/scripts/release-loop/preflight.ts +188 -8
- package/scripts/release-loop/render-warm-control-manifest.ts +22 -0
- package/scripts/release-loop/resume-release.ts +9 -7
- package/scripts/release-loop/resume.ts +13 -4
- package/scripts/release-loop/warm-control-forward.ts +178 -0
- package/scripts/retro-cycle.ts +30 -8
- package/scripts/rhythm/daily.ts +4 -1
- package/scripts/rhythm/linear-progress-sync.ts +28 -15
- package/scripts/ux-sim.ts +7 -1
- package/scripts/warm-pool-provider-config.ts +6 -1
- package/src/agent-mission/grok-auth-status.ts +78 -18
- package/src/agent-mission/mission-out.ts +2 -2
- package/src/agent-substrate/pr-reviewer.ts +147 -11
- package/src/agent-substrate/self-review-cli.ts +10 -2
- package/src/auto-research/research-fanout.ts +221 -0
- package/src/auto-research/research-turn.ts +282 -36
- package/src/autopilot/mission-codebase-gate.ts +7 -3
- package/src/cli/control-cli.ts +15 -6
- package/src/cli/log-event-names.ts +8 -0
- package/src/cli/setup-keys.ts +20 -8
- package/src/cli/tui-test-cli.ts +9 -5
- package/src/control-plane/ledger.ts +42 -4
- package/src/control-plane/member-tokens.ts +25 -2
- package/src/control-plane/ports.ts +8 -3
- package/src/control-plane/server.ts +26 -5
- package/src/core-turn/research-policy.ts +7 -1
- package/src/core-turn/run-core-turn.ts +186 -39
- package/src/core-turn/types.ts +2 -0
- package/src/dashboard/classic-sidetab-mission-job.ts +113 -24
- package/src/dashboard/classic-sidetab-mission-pair.ts +3 -2
- package/src/dashboard/classic-sidetab-mission-trio.ts +35 -12
- package/src/dashboard/classic-sidetab-mission.ts +2 -0
- package/src/dashboard/index.ts +9 -1
- package/src/dashboard/sidetab-runtime.ts +2 -0
- package/src/dashboard/visible-mission-diagnostics.ts +16 -0
- package/src/domains/retro-cycle-observation.ts +43 -0
- package/src/domains/retro-cycle.ts +13 -2
- package/src/domains/retro-proposals.ts +92 -0
- package/src/domains/retro-report.ts +6 -1
- package/src/graph-runner/graph-cli.ts +24 -1
- package/src/graph-runner/graph-grow-llm.ts +3 -1
- package/src/graph-runner/runner.ts +226 -30
- package/src/harness/harness-cli-command.ts +4 -2
- package/src/harness/harness-pod-dispatch.ts +3 -0
- package/src/index.ts +2 -2
- package/src/llm/child-first-llm-observation.ts +112 -0
- package/src/llm/provider-credentials.ts +60 -4
- package/src/llm/provider-failure-evidence.ts +44 -0
- package/src/llm.ts +170 -11
- package/src/mcp/client.ts +7 -0
- package/src/mcp/proxy-runtime.ts +6 -1
- package/src/mcp/server.ts +54 -0
- package/src/native-tool-catalog.ts +2 -2
- package/src/nexus/api/consult-requests.ts +18 -6
- package/src/nexus/api/discord-trigger-bot.ts +6 -6
- package/src/nexus/api/graphs-api.ts +4 -2
- package/src/nexus/api/grokbot-trigger-bot.ts +206 -0
- package/src/nexus/api/telegram-trigger-bot.ts +6 -6
- package/src/nexus/boot/register-mcp-clients.ts +114 -8
- package/src/nexus/index.ts +15 -0
- package/src/nexus/outbound/grokbot-adapter.ts +71 -0
- package/src/nexus/outbound/router.ts +33 -13
- package/src/oauth/codex-owner-mirror.ts +47 -10
- package/src/onboarding/first-run.ts +44 -6
- package/src/preview/terminal.ts +22 -7
- package/src/prompt-enhance/enhance.ts +10 -0
- package/src/pty-shell/pty-write-provenance.ts +21 -3
- package/src/pty-shell/registry.ts +9 -2
- package/src/release-loop/proposal-auto-place.ts +83 -0
- package/src/research/axis-fanout.ts +40 -5
- package/src/research/lenses/second-order.ts +312 -0
- package/src/self-dev/dev-cli.ts +3 -1
- package/src/self-dev/draft-sweep.ts +31 -10
- package/src/self-dev/draft-triage-rules.ts +60 -3
- package/src/self-dev/run-supervisor.ts +152 -2
- package/src/self-implement/goal-author.ts +208 -23
- package/src/self-implement/graph-overlay-yaml.ts +151 -0
- package/src/self-implement/graph-yaml.ts +68 -2
- package/src/self-implement/orchestrator.ts +62 -15
- package/src/self-implement/test-scenario-request.ts +37 -6
- package/src/session/chat.ts +2 -2
- package/src/session-runtime/index.ts +37 -5
- package/src/sidetab-core/model.ts +205 -10
- package/src/sidetab-core/visible-agent-mission-pair.ts +51 -0
- package/src/sidetab-core/visible-agent-mission.ts +105 -47
- package/src/skills/tools/omni-search.ts +4 -2
- package/src/task-agent/parent-host.ts +19 -1
- package/src/task-agent/recall-inject.ts +98 -0
- package/src/task-agent/task-hand.ts +26 -7
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +19 -1
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +15 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-host.ts +21 -9
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +460 -96
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +45 -3
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +38 -8
- package/src/tool-hints/gate.ts +45 -14
- package/src/tool-hints/signals.ts +1 -1
- package/src/tool-hints/types.ts +2 -0
- package/src/tool-runtime/browser-hand-runtime.ts +11 -1
- package/src/tool-runtime/browser-runtime.ts +31 -18
- package/src/tool-runtime/elanous-linear-secretary-runtime.ts +152 -36
- package/src/tool-runtime/types.ts +2 -0
- package/src/tui/entry.ts +27 -7
- package/src/tui/sidetab/attach.ts +112 -0
- package/src/tui/sidetab/list.ts +3 -2
- package/src/tui-client/next-dashboard-runtime.ts +52 -0
- package/src/ux-sim/draft-inventory-builder.ts +2 -1
- package/src/ux-sim/linear-secretary.ts +4 -12
- package/src/ux-sim/mock-scenario-catalog.json +32 -29
- package/src/ux-sim/mock-scenario-catalog.ts +55 -3
- package/src/ux-sim/release-sim-rig.ts +62 -18
- package/src/ux-sim/service-key-setup.ts +63 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/114.2b90424d1a3ce84c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1151-5c2bb8f002ca2dd6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1261-a616d5728e02e624.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1357.3bbef3976c37f94a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1362-20adddfaf662b0fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1737-9491fc6ab29b9ec6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1803-4f91a8e7dcaf042c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1961.a81b12872c3e93a9.js +0 -23
- package/apps/pwa/out/_next/static/chunks/1970cf59.2d4d8ce5d6c81853.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2073-ba274e00e4f9efb4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2268-53861f339e0b65a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/273.f156eee28f11af77.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2873.d2140e5a82546401.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3091.a5a4143dea33d197.js +0 -90
- package/apps/pwa/out/_next/static/chunks/3095.dc44586a5f83b86d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3113.d7472bbc27d580c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3228-9650b6447b6fa288.js +0 -1
- package/apps/pwa/out/_next/static/chunks/360.ae9f9f4c33c395e8.js +0 -79
- package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +0 -286
- package/apps/pwa/out/_next/static/chunks/3744.54f87db52acfd1ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4311-6dd3144002cc0c2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4426-2b230fad00c88930.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4445.7990c76b3751a918.js +0 -115
- package/apps/pwa/out/_next/static/chunks/4447-14c5161fa59166c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4856-b0b8075bba8c53f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4870-de370d65e73c0bb5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4885-2c989165c4b29fad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4894.fec2ca9e99caefa2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5093.8f04b7f8cb899a95.js +0 -94
- package/apps/pwa/out/_next/static/chunks/5122-2bb177cebf89e19a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5154.5f56dc3902e3d275.js +0 -36
- package/apps/pwa/out/_next/static/chunks/529.64ff7257180b2ac9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5394.5dabeb0c62293a28.js +0 -93
- package/apps/pwa/out/_next/static/chunks/5461.08bf2404ff38ec85.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5474-22e08a85583209b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5567-265df39ed8fe9dcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5570-a94ae19811cb2046.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5574-b47c9ef2dceff1fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5730.43d7ccc09988e646.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5824.da9527b15a3221e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5963-c4d8469c52a0828b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6001.ec4049ceb3c43418.js +0 -27
- package/apps/pwa/out/_next/static/chunks/6120-471f03db1e299c0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6175-41479e643aca1878.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6291.a2de4f9787637075.js +0 -104
- package/apps/pwa/out/_next/static/chunks/6400-6699907c3537436a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6428.1f4327d6ae5fdf9a.js +0 -287
- package/apps/pwa/out/_next/static/chunks/644.02cb026fa44bcd0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6466-6c87d60d3dd174fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6773.d4264665ab31bec0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6822.3c789f1a8443e774.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7261-8ff69d3b2ee671fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7266.084c6bbc70035140.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7271.5c0100e7320aa856.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7429-bf5731358c8f2f68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7464.01f7a0ae1215fbe7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7479.0fcad5f37eb64f0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7483.427a2fe2049e388d.js +0 -148
- package/apps/pwa/out/_next/static/chunks/7502-be74718178e13e56.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7530.0889722b19572065.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7645.5b2ee3ad45c55ea3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7788.7d1c79f1a8e18946.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7966.f71c8958d1637548.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8073.f6cf2f2c71aafbd0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8201.190b94088980f430.js +0 -74
- package/apps/pwa/out/_next/static/chunks/8447.7963352ef5f71b76.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8574-868e8129525ef6d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/868.6e953be05bcf6dca.js +0 -41
- package/apps/pwa/out/_next/static/chunks/8706-e1fe0309343a2273.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8749-06384cdfc4520add.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8861-cc1fa1c7b920fa8e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8967-7dfebf710c9dec9d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8997-3c564dbb3b58b055.js +0 -1
- package/apps/pwa/out/_next/static/chunks/923.2034d10ae91e9c20.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +0 -1
- package/apps/pwa/out/_next/static/chunks/943.39ae5e82f4f1893f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9469.0500480de55fb205.js +0 -32
- package/apps/pwa/out/_next/static/chunks/9810-2543267050e58b82.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9870.8419702475254745.js +0 -8
- package/apps/pwa/out/_next/static/chunks/9941-376d1b74d51b01a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9958.385434ab04241758.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-deea1450b17cb8dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-70985b904f8650ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a2e15e33e56a4353.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-fc72ce2db12d6ca9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-be03e41f9436ebd9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-35a35999382da3f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-3ff5b1e6ca88b848.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-a65101300a0ee5c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3aca5b6d67dba511.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-45b8ab0a71e61314.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-53046e282d4cda8e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-17809e60e8354c17.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-fd2442d347bf5898.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-e9d720d6fc082e21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-6b8b4267bab0a677.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-deea1450b17cb8dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-8bcf6233ac7c17af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-7cc25591cfc2126f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-053e871f35c9beba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-eff819f0c2d5e084.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-4d7e9d8db5274a87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-2b2d8f5aa5f69ad4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-0b8f92c5062e68b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1bd9d0fdac2ced3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-9ee28f7df07428ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-44b7a1ff468c6648.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-cbc6523711dc1b65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-fdad47899c2695be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-79a8b5fee4c20871.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-03e8ac9606aeaffb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-4cd55c55ec287e2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-db17b4305404161e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-30041d848350fd02.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c540da022dbf86b0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9399efc538da057f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ca2d09128c585ca4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-0e2635aecd343038.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ef7f4399b6b7726e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-deea1450b17cb8dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-caf530535b875468.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-eaa20c1543a5fd8e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c541eb1b75120f61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-ab5e213eda9479f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-e858ba0ed9393b68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-1638ee9dd6e0582f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4cf5a399109391f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b4396321238798ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-cb72bfd21006781a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6135d0242afbc434.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a1dccf907eddb856.js +0 -1
- package/apps/pwa/out/_next/static/chunks/c7945435-b44d4dbe90ba0dcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ea514caa.05a24f78d9dffe5f.js +0 -122
- package/apps/pwa/out/_next/static/chunks/framework-e8a911e19b1be41f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-7022f418fabba021.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-e5f15df755756a1e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-4525f91e36940c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-140f0e519c085b0f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-8f22ef63dcb865b1.js +0 -1
- /package/apps/pwa/out/_next/static/{Om5xS9jpjSXJCeTNGYEi4 → HMXsxdy5MIIcHPMHv1wD4}/_ssgManifest.js +0 -0
|
@@ -4,6 +4,7 @@ import type { BloomResearchQuestion, ResearchEvidenceEnvelope } from '../auto-re
|
|
|
4
4
|
import { getAvailableResearchWebSearchProviders } from '../web-search/index.js';
|
|
5
5
|
import type { WebSearchHit, WebSearchProvider } from '../web-search/provider.js';
|
|
6
6
|
import { debug } from '../debug/log.js';
|
|
7
|
+
import { dispatchWebFetch } from '../skills/tools/webfetch.js';
|
|
7
8
|
|
|
8
9
|
const RESEARCH_SEARCH_ENGINES = ['exa', 'firecrawl'] as const;
|
|
9
10
|
const RESEARCH_WEB_FALLBACK_IDS = ['exa', 'firecrawl'] as const;
|
|
@@ -42,8 +43,9 @@ export type AxisSearch = (query: string, signal?: AbortSignal, context?: AxisSea
|
|
|
42
43
|
|
|
43
44
|
export interface AxisFanoutDeps {
|
|
44
45
|
search?: AxisSearch;
|
|
46
|
+
fetchPage?: (url: string, question: BloomResearchQuestion, signal?: AbortSignal) => Promise<{ url: string; output: string }>;
|
|
45
47
|
signal?: AbortSignal;
|
|
46
|
-
admitToolCall?: (toolName: 'OmniSearch') => boolean;
|
|
48
|
+
admitToolCall?: (toolName: 'OmniSearch' | 'WebFetch') => boolean;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
interface ProviderHealth {
|
|
@@ -201,15 +203,34 @@ export async function fanOutAxisEvidence(
|
|
|
201
203
|
throw new Error('research axis question IDs must be unique');
|
|
202
204
|
}
|
|
203
205
|
const search = deps.search ?? createResearchAxisSearcher();
|
|
204
|
-
const
|
|
206
|
+
const fetchPage = deps.fetchPage ?? (!deps.search
|
|
207
|
+
? async (url: string, question: BloomResearchQuestion, signal?: AbortSignal) =>
|
|
208
|
+
dispatchWebFetch({ url, prompt: question.prompt }, { signal })
|
|
209
|
+
: undefined);
|
|
210
|
+
const fetchedQuestions = new Set<string>();
|
|
211
|
+
const settled = await Promise.allSettled(plan.map(async call => {
|
|
205
212
|
if (deps.admitToolCall && !deps.admitToolCall('OmniSearch')) {
|
|
206
|
-
return
|
|
213
|
+
return { hits: [], errors: ['research tool budget reached'] } satisfies AxisSearchResult;
|
|
207
214
|
}
|
|
208
215
|
const question = questions.find(candidate => candidate.id === call.questionId)!;
|
|
209
|
-
|
|
216
|
+
const raw = await search(call.query, deps.signal, {
|
|
210
217
|
questionPrompt: question.prompt,
|
|
211
218
|
requestedWindow: question.requestedWindow,
|
|
212
219
|
});
|
|
220
|
+
const response = Array.isArray(raw) ? { hits: raw, errors: [] } : raw;
|
|
221
|
+
if (!fetchPage || response.hits.length === 0 || fetchedQuestions.has(question.id)) return response;
|
|
222
|
+
fetchedQuestions.add(question.id);
|
|
223
|
+
if (deps.admitToolCall && !deps.admitToolCall('WebFetch')) return response;
|
|
224
|
+
try {
|
|
225
|
+
const page = await fetchPage(response.hits[0]!.url, question, deps.signal);
|
|
226
|
+
return { ...response, fetchedPage: page };
|
|
227
|
+
} catch (error) {
|
|
228
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
229
|
+
debug.log('research.search', 'native-fetch-failed', {
|
|
230
|
+
questionId: question.id, reason: message.slice(0, 200),
|
|
231
|
+
}, { level: 'warn' });
|
|
232
|
+
return response;
|
|
233
|
+
}
|
|
213
234
|
}));
|
|
214
235
|
const axes: AxisEvidenceGroup[] = questions.map(question => ({ questionId: question.id, evidence: [] }));
|
|
215
236
|
const groups = new Map(axes.map(axis => [axis.questionId, axis]));
|
|
@@ -226,10 +247,24 @@ export async function fanOutAxisEvidence(
|
|
|
226
247
|
const group = groups.get(call.questionId)!;
|
|
227
248
|
const question = byQuestion.get(call.questionId)!;
|
|
228
249
|
if (outcome.status === 'fulfilled') {
|
|
229
|
-
const response =
|
|
250
|
+
const response = outcome.value;
|
|
230
251
|
if (response.hits.length === 0 && response.errors.length === 0) {
|
|
231
252
|
group.evidence.push({ ...failedEvidence(question, call.query, 'no hits returned'), outcome: 'partial' });
|
|
232
253
|
}
|
|
254
|
+
const fetchedPage = 'fetchedPage' in response ? response.fetchedPage : undefined;
|
|
255
|
+
if (fetchedPage) {
|
|
256
|
+
const content = fetchedPage.output;
|
|
257
|
+
const excerpt = Array.from(content).slice(0, 8_000).join('');
|
|
258
|
+
group.evidence.push({
|
|
259
|
+
questionId: question.id,
|
|
260
|
+
sourceKind: 'web-fetch',
|
|
261
|
+
source: fetchedPage.url,
|
|
262
|
+
...(question.requestedWindow ? { requestedWindow: question.requestedWindow } : {}),
|
|
263
|
+
content: excerpt,
|
|
264
|
+
outcome: excerpt ? 'complete' : 'partial',
|
|
265
|
+
truncated: Array.from(content).length > 8_000,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
233
268
|
for (const hit of response.hits) {
|
|
234
269
|
try {
|
|
235
270
|
group.evidence.push(evidenceFromHit(question, hit));
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/** Chain order a synthesis step lands in: what happens first, what that causes, what that settles. */
|
|
2
|
+
export type SecondOrderOrder = 'primary' | 'secondary' | 'tertiary';
|
|
3
|
+
|
|
4
|
+
export interface SecondOrderLensStage {
|
|
5
|
+
order: SecondOrderOrder;
|
|
6
|
+
label: string;
|
|
7
|
+
horizonDays: number;
|
|
8
|
+
purpose: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Public lens definition: what the T2 second-order lens is and which orders it fans a synthesis into. */
|
|
12
|
+
export interface SecondOrderLensDefinition {
|
|
13
|
+
id: string;
|
|
14
|
+
cell: string;
|
|
15
|
+
tier: string;
|
|
16
|
+
rfc: string;
|
|
17
|
+
description: string;
|
|
18
|
+
stages: readonly SecondOrderLensStage[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Public verification format attached to every secondary effect. */
|
|
22
|
+
export interface SecondOrderVerificationNode {
|
|
23
|
+
claim: string;
|
|
24
|
+
scenarioCondition: string | null;
|
|
25
|
+
metric: string | null;
|
|
26
|
+
expectedValue: number | null;
|
|
27
|
+
threshold: number | null;
|
|
28
|
+
unit: string | null;
|
|
29
|
+
windowDays: number;
|
|
30
|
+
falsifiable: boolean | null;
|
|
31
|
+
measurementStatus: 'unmeasured' | 'needs-operationalization';
|
|
32
|
+
evidenceSource: string | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SecondOrderEvidenceFact {
|
|
36
|
+
questionId: string;
|
|
37
|
+
question: string;
|
|
38
|
+
content: string;
|
|
39
|
+
source: string;
|
|
40
|
+
outcome: 'complete' | 'partial' | 'failed';
|
|
41
|
+
observedWindow?: string;
|
|
42
|
+
units?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface SecondOrderChainNode {
|
|
46
|
+
id: string;
|
|
47
|
+
order: SecondOrderOrder;
|
|
48
|
+
orderIndex: 1 | 2 | 3;
|
|
49
|
+
statement: string;
|
|
50
|
+
horizonDays: number;
|
|
51
|
+
derivedFrom: readonly string[];
|
|
52
|
+
verification: SecondOrderVerificationNode | null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Public result-chain format: primary → secondary → tertiary, with secondary effects verified. */
|
|
56
|
+
export interface SecondOrderResultChain {
|
|
57
|
+
lensId: string;
|
|
58
|
+
question: string;
|
|
59
|
+
orderStages: readonly SecondOrderLensStage[];
|
|
60
|
+
nodes: readonly SecondOrderChainNode[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type SecondOrderTriggerKind = 'decision' | 'forecast' | 'none';
|
|
64
|
+
|
|
65
|
+
export interface SecondOrderTriggerDecision {
|
|
66
|
+
triggered: boolean;
|
|
67
|
+
kind: SecondOrderTriggerKind;
|
|
68
|
+
score: number;
|
|
69
|
+
matchedSignals: readonly string[];
|
|
70
|
+
reason: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface SecondOrderLensInput {
|
|
74
|
+
question: string;
|
|
75
|
+
synthesis: readonly string[];
|
|
76
|
+
/** IDs must align with synthesis; evidence is joined by questionId, never by flat-array position. */
|
|
77
|
+
synthesisQuestionIds?: readonly string[];
|
|
78
|
+
evidenceFacts?: readonly SecondOrderEvidenceFact[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface SecondOrderLensResult {
|
|
82
|
+
lens: SecondOrderLensDefinition;
|
|
83
|
+
trigger: SecondOrderTriggerDecision;
|
|
84
|
+
chain: SecondOrderResultChain | null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Injection seam lets a host supply private trigger calibration without shipping it here. */
|
|
88
|
+
export type SecondOrderTriggerClassifier = (question: string) => SecondOrderTriggerDecision;
|
|
89
|
+
|
|
90
|
+
export const SECOND_ORDER_LENS: SecondOrderLensDefinition = {
|
|
91
|
+
id: 'second-order',
|
|
92
|
+
cell: 'THINK-LENS-T2-SECOND-ORDER',
|
|
93
|
+
tier: 'T2',
|
|
94
|
+
rfc: 'RFC-PRO §2',
|
|
95
|
+
description: '결정·예측 질문에서 6단 종합을 1차 → 2차 → 3차 결과 사슬로 펼치고, 2차 효과마다 검증 노드를 붙인다.',
|
|
96
|
+
stages: [
|
|
97
|
+
{
|
|
98
|
+
order: 'primary',
|
|
99
|
+
label: '1차 결과',
|
|
100
|
+
horizonDays: 30,
|
|
101
|
+
purpose: '결정이나 예측이 직접 만드는 즉시 효과',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
order: 'secondary',
|
|
105
|
+
label: '2차 결과',
|
|
106
|
+
horizonDays: 180,
|
|
107
|
+
purpose: '1차 효과가 다른 주체로 전이되며 생기는 효과 — 검증 노드가 붙는 자리',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
order: 'tertiary',
|
|
111
|
+
label: '3차 결과',
|
|
112
|
+
horizonDays: 540,
|
|
113
|
+
purpose: '2차 효과가 구조·규범·시장에 정착하며 생기는 효과',
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const DECISION_QUESTION_FORM = /(?:해야\s*(?:할까|하나|할지)|(?:고르|선택|결정|전환|도입|투자|진입|매수|매도)(?:해야\s*(?:할까|하나|할지)|할까|할지\s*(?:말지|여부)))|\b(?:should\s+(?:i|we)|whether\s+to|choose\s+between|decide\s+whether)\b/i;
|
|
119
|
+
const FORECAST_QUESTION_FORM = /(?:얼마나\s+[^?\n]{0,80}(?:될|오를|내릴|늘어날|줄어들|바뀔|변할)|(?:언제|몇)\s+[^?\n]{0,80}(?:될|오를|내릴|늘어날|줄어들|바뀔)|어떻게\s+(?:될까|변할까))|\b(?:how\s+much|how\s+many)\s+(?:will|might|could|is\s+expected\s+to|is\s+projected\s+to)\b.{0,120}\b(?:rise|fall|grow|shrink|change|cost|be)\b|\b(?:when\s+will|what\s+will)\b.{0,120}\b(?:rise|fall|grow|shrink|change|cost|be)\b|\bwill\s+[^?\n]{1,120}\b(?:increase|decrease|rise|fall|grow|shrink|change|cost|remain|reach|exceed|decline)\b/i;
|
|
120
|
+
|
|
121
|
+
/** Decide whether a question is a decision or a forecast, i.e. whether the second-order lens applies. */
|
|
122
|
+
export function detectSecondOrderTrigger(question: string): SecondOrderTriggerDecision {
|
|
123
|
+
const text = requireText(question, 'question').toLowerCase();
|
|
124
|
+
if (!/[??]\s*$/u.test(text)) return noTrigger();
|
|
125
|
+
const decision = DECISION_QUESTION_FORM.exec(text);
|
|
126
|
+
const forecast = FORECAST_QUESTION_FORM.exec(text);
|
|
127
|
+
const kind: SecondOrderTriggerKind = decision ? 'decision' : forecast ? 'forecast' : 'none';
|
|
128
|
+
const score = kind === 'none' ? 0 : 1;
|
|
129
|
+
const matchedSignals = Object.freeze(kind === 'decision' ? ['decision-form'] : kind === 'forecast' ? ['forecast-form'] : []);
|
|
130
|
+
if (kind === 'none') {
|
|
131
|
+
return {
|
|
132
|
+
triggered: false,
|
|
133
|
+
kind: 'none',
|
|
134
|
+
score,
|
|
135
|
+
matchedSignals,
|
|
136
|
+
reason: '질문이 결정이나 예측이 아니라 결과 사슬을 펼치지 않는다',
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
triggered: true,
|
|
141
|
+
kind,
|
|
142
|
+
score,
|
|
143
|
+
matchedSignals,
|
|
144
|
+
reason: kind === 'decision'
|
|
145
|
+
? '결정 질문이므로 1차 → 2차 → 3차 결과 사슬을 펼친다'
|
|
146
|
+
: '예측 질문이므로 1차 → 2차 → 3차 결과 사슬을 펼친다',
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function noTrigger(): SecondOrderTriggerDecision {
|
|
151
|
+
return {
|
|
152
|
+
triggered: false,
|
|
153
|
+
kind: 'none',
|
|
154
|
+
score: 0,
|
|
155
|
+
matchedSignals: Object.freeze([]),
|
|
156
|
+
reason: '결정·예측 질문형이 아니므로 결과 사슬을 펼치지 않는다',
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Expand synthesis steps into a primary → secondary → tertiary chain with a verification node on each secondary effect. */
|
|
161
|
+
export function buildSecondOrderResultChain(input: SecondOrderLensInput): SecondOrderResultChain {
|
|
162
|
+
const question = requireText(input.question, 'question');
|
|
163
|
+
const steps = input.synthesis.map((step, index) => requireText(step, `synthesis[${index}]`));
|
|
164
|
+
if (input.evidenceFacts?.length && input.synthesisQuestionIds?.length !== steps.length) {
|
|
165
|
+
throw new Error('synthesisQuestionIds must align with synthesis when evidenceFacts are supplied');
|
|
166
|
+
}
|
|
167
|
+
if (steps.length < SECOND_ORDER_LENS.stages.length) {
|
|
168
|
+
throw new Error('synthesis requires at least three steps to expand into a result chain');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const buckets = splitIntoOrders(steps, SECOND_ORDER_LENS.stages.length);
|
|
172
|
+
const nodes: SecondOrderChainNode[] = [];
|
|
173
|
+
let previousIds: string[] = [];
|
|
174
|
+
for (const [stageIndex, stage] of SECOND_ORDER_LENS.stages.entries()) {
|
|
175
|
+
const stageIds: string[] = [];
|
|
176
|
+
for (const [stepIndex, statement] of buckets[stageIndex]!.entries()) {
|
|
177
|
+
const inputIndex = buckets.slice(0, stageIndex).reduce((count, bucket) => count + bucket.length, 0) + stepIndex;
|
|
178
|
+
const questionId = input.synthesisQuestionIds?.[inputIndex];
|
|
179
|
+
const fact = questionId ? combineQuestionEvidence(questionId, input.evidenceFacts ?? []) : undefined;
|
|
180
|
+
const id = `${stage.order}-${stepIndex + 1}`;
|
|
181
|
+
stageIds.push(id);
|
|
182
|
+
const parentIndex = stageIndex === 0 ? -1 : Math.min(stepIndex, previousIds.length - 1);
|
|
183
|
+
const parentId = parentIndex >= 0 ? previousIds[parentIndex] : undefined;
|
|
184
|
+
const parent = parentId ? nodes.find((node) => node.id === parentId) : undefined;
|
|
185
|
+
const outputStatement = fact
|
|
186
|
+
? makeOutcomeHypothesis(stage.order, question, fact, parent?.statement)
|
|
187
|
+
: stage.order === 'primary'
|
|
188
|
+
? `1차 가설: ${statement}`
|
|
189
|
+
: `${stage.order === 'secondary' ? '2차' : '3차'} 가설: ${parent?.statement ?? '앞 단계 결과'}가 이어지면 ${statement}라는 후속 결과가 생길 수 있다.`;
|
|
190
|
+
nodes.push({
|
|
191
|
+
id,
|
|
192
|
+
order: stage.order,
|
|
193
|
+
orderIndex: (stageIndex + 1) as 1 | 2 | 3,
|
|
194
|
+
statement: outputStatement,
|
|
195
|
+
horizonDays: stage.horizonDays,
|
|
196
|
+
derivedFrom: Object.freeze(parentId ? [parentId] : []),
|
|
197
|
+
verification: stage.order === 'secondary'
|
|
198
|
+
? buildVerificationNode(outputStatement, fact, stepIndex)
|
|
199
|
+
: null,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
previousIds = stageIds;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
lensId: SECOND_ORDER_LENS.id,
|
|
207
|
+
question,
|
|
208
|
+
orderStages: SECOND_ORDER_LENS.stages,
|
|
209
|
+
nodes: Object.freeze(nodes),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Run the lens: the trigger decides whether a chain is produced at all. */
|
|
214
|
+
export function applySecondOrderLens(
|
|
215
|
+
input: SecondOrderLensInput,
|
|
216
|
+
classifyTrigger: SecondOrderTriggerClassifier = detectSecondOrderTrigger,
|
|
217
|
+
): SecondOrderLensResult {
|
|
218
|
+
const trigger = classifyTrigger(input.question);
|
|
219
|
+
if (!trigger.triggered) return { lens: SECOND_ORDER_LENS, trigger, chain: null };
|
|
220
|
+
return { lens: SECOND_ORDER_LENS, trigger, chain: buildSecondOrderResultChain(input) };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function buildVerificationNode(statement: string, fact: SecondOrderEvidenceFact | undefined, index: number): SecondOrderVerificationNode {
|
|
224
|
+
const metric = fact?.outcome === 'complete' ? extractObservableMetric(fact.content) : null;
|
|
225
|
+
const windowDays = 90 * (index + 1);
|
|
226
|
+
const scenarioCondition = metric && fact
|
|
227
|
+
? `${fact.observedWindow ? `${fact.observedWindow} 기준선` : '확인 가능한 기준선'}과 ${windowDays}일 뒤 ${metric}을 비교한다. 판정 임계값은 아직 정하지 않았다.`
|
|
228
|
+
: null;
|
|
229
|
+
return {
|
|
230
|
+
claim: statement,
|
|
231
|
+
scenarioCondition,
|
|
232
|
+
metric,
|
|
233
|
+
expectedValue: null,
|
|
234
|
+
threshold: null,
|
|
235
|
+
unit: fact?.units ?? null,
|
|
236
|
+
windowDays,
|
|
237
|
+
falsifiable: null,
|
|
238
|
+
measurementStatus: metric ? 'needs-operationalization' : 'unmeasured',
|
|
239
|
+
evidenceSource: fact?.source ?? null,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function splitIntoOrders(steps: readonly string[], orderCount: number): string[][] {
|
|
244
|
+
const base = Math.floor(steps.length / orderCount);
|
|
245
|
+
const remainder = steps.length % orderCount;
|
|
246
|
+
const buckets: string[][] = [];
|
|
247
|
+
let cursor = 0;
|
|
248
|
+
for (let index = 0; index < orderCount; index += 1) {
|
|
249
|
+
const size = base + (index < remainder ? 1 : 0);
|
|
250
|
+
buckets.push(steps.slice(cursor, cursor + size));
|
|
251
|
+
cursor += size;
|
|
252
|
+
}
|
|
253
|
+
return buckets;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function makeOutcomeHypothesis(
|
|
257
|
+
order: SecondOrderOrder,
|
|
258
|
+
question: string,
|
|
259
|
+
fact: SecondOrderEvidenceFact,
|
|
260
|
+
parentStatement?: string,
|
|
261
|
+
): string {
|
|
262
|
+
const detail = compactEvidence(fact.content);
|
|
263
|
+
const citation = `[${fact.questionId}; ${fact.source}; ${fact.outcome}]`;
|
|
264
|
+
if (fact.outcome !== 'complete') {
|
|
265
|
+
return `${order === 'primary' ? '1차' : order === 'secondary' ? '2차' : '3차'} 가설 미작성: ${fact.question}에 대한 완전한 근거를 확보하지 못했다 (${fact.outcome}; ${citation}).`;
|
|
266
|
+
}
|
|
267
|
+
if (order === 'primary') return `1차 가설: 「${question}」의 직접 효과 후보는 「${detail}」이다. 근거 ${citation}`;
|
|
268
|
+
if (order === 'secondary') return `2차 가설: 「${parentStatement ?? '직접 결과'}」가 이어질 경우 「${detail}」라는 후속 효과가 생길 수 있다. 근거 ${citation}`;
|
|
269
|
+
return `3차 가설: 「${parentStatement ?? '2차 효과'}」가 지속될 경우 「${detail}」라는 장기 결과로 이어질 수 있다. 근거 ${citation}`;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function compactEvidence(value: string): string {
|
|
273
|
+
const normalized = value.replace(/\s+/g, ' ').trim();
|
|
274
|
+
return normalized.length > 180 ? `${normalized.slice(0, 177)}…` : normalized;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function combineQuestionEvidence(questionId: string, evidenceFacts: readonly SecondOrderEvidenceFact[]): SecondOrderEvidenceFact | undefined {
|
|
278
|
+
const matching = evidenceFacts.filter((fact) => fact.questionId === questionId);
|
|
279
|
+
if (!matching.length) return undefined;
|
|
280
|
+
const complete = matching.filter((fact) => fact.outcome === 'complete');
|
|
281
|
+
const selected = complete.length ? complete : matching;
|
|
282
|
+
const units = [...new Set(selected.map((fact) => fact.units).filter((unit): unit is string => Boolean(unit)))].join(', ');
|
|
283
|
+
const observedWindow = [...new Set(selected.map((fact) => fact.observedWindow).filter((window): window is string => Boolean(window)))].join(', ');
|
|
284
|
+
return {
|
|
285
|
+
questionId,
|
|
286
|
+
question: selected[0]!.question,
|
|
287
|
+
content: selected.map((fact) => fact.content).join(' · '),
|
|
288
|
+
source: [...new Set(selected.map((fact) => fact.source))].join(', '),
|
|
289
|
+
outcome: complete.length ? 'complete' : selected.some((fact) => fact.outcome === 'partial') ? 'partial' : 'failed',
|
|
290
|
+
...(observedWindow ? { observedWindow } : {}),
|
|
291
|
+
...(units ? { units } : {}),
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function extractObservableMetric(value: string): string | null {
|
|
296
|
+
const patterns = [
|
|
297
|
+
/(?:응답\s*시간|처리\s*시간|처리량|대기\s*시간|전환율|이탈률|잔존율|오류율|정확도|매출|수익|비용|수출액|수출량|문의\s*건수|사용자\s*수|판매량|생산성|파이프라인)/iu,
|
|
298
|
+
/\b(?:response time|processing time|wait time|conversion rate|churn rate|retention rate|error rate|accuracy|revenue|cost|export volume|inquiry count|user count|sales volume|productivity|pipeline|adoption rate|demand)\b/iu,
|
|
299
|
+
];
|
|
300
|
+
for (const pattern of patterns) {
|
|
301
|
+
const match = value.match(pattern);
|
|
302
|
+
if (match?.[0]) return match[0].replace(/\s+/g, ' ').trim();
|
|
303
|
+
}
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function requireText(value: unknown, field: string): string {
|
|
308
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
309
|
+
throw new Error(`${field} must not be empty`);
|
|
310
|
+
}
|
|
311
|
+
return value.trim();
|
|
312
|
+
}
|
package/src/self-dev/dev-cli.ts
CHANGED
|
@@ -930,7 +930,9 @@ export function startDraftTriage(
|
|
|
930
930
|
const inventory = inventories.find((entry) => entry.repository === repository)?.snapshot;
|
|
931
931
|
const enriched = { ...draft, branch: draft.branch ?? '', ...inventoryByUrl.get(draft.url!) };
|
|
932
932
|
if ((!inventory || !inventoryByUrl.has(draft.url!)) && !IN_TEST_PROCESS()) { unobservedDrafts.push(draft.number); continue; }
|
|
933
|
-
const
|
|
933
|
+
const triageNow = nowMs();
|
|
934
|
+
const decision = decideDraft({ draft: enriched, now: new Date(triageNow), runStatus: resolvedStatus,
|
|
935
|
+
mergedTwins: inventory?.merged ?? [], ageHours: (triageNow - draft.openedAtMs) / 3_600_000, liveBranches });
|
|
934
936
|
if (decision.reason.startsWith('superseded-by')) decisions.superseded += 1;
|
|
935
937
|
else if (decision.reason === 'stale-ended-run') decisions.staleEndedRun += 1;
|
|
936
938
|
else if (decision.reason.startsWith('label:')) decisions.humanApproval += 1; // approval-waiting or human «keep»
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CLAIM_IDLE_HOURS, PR_LABELS, STALLED_DRAFT_HOURS } from '../github/pr-labels.js';
|
|
2
2
|
import { debug } from '../debug/log.js';
|
|
3
|
-
import { assessDraftTriage, decideDraft, draftClaimComment, draftClaimState, draftReleaseComment, laterMergedTwins, sameGoalPr, PROTECTED_LABELS, type DraftTriageAssessment, type DraftTriagePr, type DraftTriageReviewState } from './draft-triage-rules.js';
|
|
3
|
+
import { assessDraftTriage, decideDraft, draftClaimComment, draftClaimState, draftIntentHoldReason, draftIntentHoldRejection, draftReleaseComment, harvestDeferredMarker, laterMergedTwins, parseDraftIntentHold, sameGoalPr, PROTECTED_LABELS, type DraftTriageAssessment, type DraftTriagePr, type DraftTriageReviewState } from './draft-triage-rules.js';
|
|
4
4
|
import { cellIdFromBody } from '../pr-tool/census.js';
|
|
5
5
|
import { RELEASE_PATH_LABEL } from './release-path-guard.js';
|
|
6
6
|
import { cardPrNumber, draftTaskOwner, type TaskCard } from '../task-agent/task-hand.js';
|
|
@@ -659,12 +659,14 @@ export function resolveDraftSweepCloseCap(input: { flag?: unknown; config?: unkn
|
|
|
659
659
|
export async function supersedeDraftsOnMerge(input: {
|
|
660
660
|
repository: string;
|
|
661
661
|
merged: SweepMergedPr & { createdAt: string; mergedAt: string };
|
|
662
|
+
now?: Date;
|
|
662
663
|
/** `pr land` and HQ train invoke only the explicit same-cell successor path. */
|
|
663
664
|
onlyExplicitSameCell?: boolean;
|
|
664
665
|
adapters: Pick<DraftSweepAdapters, 'listDrafts' | 'listLiveBranches' | 'getRunStatus' | 'setLabels' | 'closeDraft'>
|
|
665
666
|
& Pick<Partial<DraftSweepAdapters>, 'getLatestFileChanges' | 'getPrFiles' | 'commentDraft' | 'listIssueComments'>;
|
|
666
667
|
}): Promise<{ closed: number[]; kept: number[] }> {
|
|
667
668
|
const { repository, merged, adapters } = input;
|
|
669
|
+
const now = input.now ?? new Date();
|
|
668
670
|
const closed: number[] = [];
|
|
669
671
|
const kept: number[] = [];
|
|
670
672
|
let drafts: SweepDraft[] = [];
|
|
@@ -691,6 +693,7 @@ export async function supersedeDraftsOnMerge(input: {
|
|
|
691
693
|
const old = drafts.find((draft) => draft.number === explicitOld);
|
|
692
694
|
if (old && cellIdFromBody(old.body ?? '') === mergedCell
|
|
693
695
|
&& Date.parse(old.createdAt) < Date.parse(merged.mergedAt)
|
|
696
|
+
&& !parseDraftIntentHold(old.body, now)
|
|
694
697
|
&& !old.labels.some((label) => PROTECTED_LABELS.has(label))
|
|
695
698
|
&& PR_LABELS.filter((label) => label.axis === 'state' && old.labels.includes(label.name)).length <= 1) {
|
|
696
699
|
const marker = `<!-- elanous:same-cell-superseded #${old.number} -> #${merged.number} -->`;
|
|
@@ -745,7 +748,7 @@ export async function supersedeDraftsOnMerge(input: {
|
|
|
745
748
|
kept.push(draft.number);
|
|
746
749
|
continue;
|
|
747
750
|
}
|
|
748
|
-
const decision = decideDraft({ draft, runStatus: statuses.get(draft.number),
|
|
751
|
+
const decision = decideDraft({ draft, now, runStatus: statuses.get(draft.number),
|
|
749
752
|
mergedTwins: [landed], liveBranches, ageHours: NaN });
|
|
750
753
|
if (decision.action !== 'close' || !decision.reason.startsWith(`superseded-by #${merged.number}`)
|
|
751
754
|
|| PR_LABELS.filter((entry) => entry.axis === 'state' && draft.labels.includes(entry.name)).length > 1
|
|
@@ -1345,6 +1348,16 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1345
1348
|
...(claimWriteFailed ? { error: claimWriteError, ...(claimPartialApplied ? { partialApplied: true } : {}) } : {}) });
|
|
1346
1349
|
continue;
|
|
1347
1350
|
}
|
|
1351
|
+
// DRAFT-ZERO's failed-run harvest evidence remains the strongest explicit hold; this intent marker
|
|
1352
|
+
// must not rewrite its reason or mask the harvest classification.
|
|
1353
|
+
if (runStatus === 'failed' && harvestDeferredMarker(draft.body)) {
|
|
1354
|
+
record({ number: draft.number, action: 'keep', reason: 'harvest-deferred', applied: false });
|
|
1355
|
+
continue;
|
|
1356
|
+
}
|
|
1357
|
+
const intentHoldRejection = draftIntentHoldRejection(draft.body, now);
|
|
1358
|
+
if (intentHoldRejection) {
|
|
1359
|
+
try { debug.log('self-dev.draft-sweep', 'intent-hold-rejected', { pr: draft.number, reason: intentHoldRejection }); } catch { /* fail-soft */ }
|
|
1360
|
+
}
|
|
1348
1361
|
if (draft.labels.includes(releaseHoldLabel ?? '') || draft.labels.includes(RELEASE_PATH_LABEL)
|
|
1349
1362
|
|| (!contradiction && draft.labels.includes(keepLabel ?? ''))) {
|
|
1350
1363
|
const held = draft.labels.includes(keepLabel ?? '') ? keepLabel
|
|
@@ -1352,6 +1365,19 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1352
1365
|
record({ number: draft.number, action: 'keep', reason: `label:${held}`, applied: false });
|
|
1353
1366
|
continue;
|
|
1354
1367
|
}
|
|
1368
|
+
// Outside-harness drafts keep their established jurisdiction reason, even when they carry a valid marker.
|
|
1369
|
+
if (!contradiction && !states.length && !draft.branch.startsWith('self-impl/')) {
|
|
1370
|
+
record({ number: draft.number, action: 'keep', reason: 'outside-harness', applied: false });
|
|
1371
|
+
continue;
|
|
1372
|
+
}
|
|
1373
|
+
const intentHold = parseDraftIntentHold(draft.body, now);
|
|
1374
|
+
if (intentHold) {
|
|
1375
|
+
const reason = draftIntentHoldReason(intentHold);
|
|
1376
|
+
record({ number: draft.number, action: 'keep', reason, applied: false });
|
|
1377
|
+
try { debug.log('self-dev.draft-sweep', 'intent-hold-kept', { pr: draft.number, owner: intentHold.owner,
|
|
1378
|
+
reason: intentHold.reason, expiresAt: intentHold.expiresAt }); } catch { /* fail-soft */ }
|
|
1379
|
+
continue;
|
|
1380
|
+
}
|
|
1355
1381
|
const claimState = contradiction ? 'unclaimed' : draftClaimState(draft, now);
|
|
1356
1382
|
const isClaimed = claimState !== 'unclaimed';
|
|
1357
1383
|
const ageHours = (now.getTime() - Date.parse(draft.createdAt)) / 3_600_000;
|
|
@@ -1368,7 +1394,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1368
1394
|
const cellNewer = contradiction || lineageNewer ? undefined : newerSameCellDraft(draft, drafts);
|
|
1369
1395
|
const duplicateNewer = lineageNewer ?? cellNewer;
|
|
1370
1396
|
if (duplicateNewer) {
|
|
1371
|
-
const base = decideDraft({ draft, runStatus, mergedTwins: merged, openDrafts: drafts, liveBranches,
|
|
1397
|
+
const base = decideDraft({ draft, now, runStatus, mergedTwins: merged, openDrafts: drafts, liveBranches,
|
|
1372
1398
|
finalRunResult, ageHours: runStatus ? ageHours : idleHours });
|
|
1373
1399
|
if (!base.reason.startsWith('label:') && !base.reason.startsWith('superseded-by #') && !base.reason.startsWith('duplicate-of-open #')) {
|
|
1374
1400
|
const runLive = isLiveDraftRun(runStatus, draft.branch, liveBranches);
|
|
@@ -1457,7 +1483,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1457
1483
|
}
|
|
1458
1484
|
// An unobserved claim may still have a merged twin: liveness/holds retain their priority,
|
|
1459
1485
|
// but a superseded draft must not be hidden by the six-hour claim window.
|
|
1460
|
-
const mergedDecision = isClaimed ? decideDraft({ draft, runStatus, mergedTwins: merged, openDrafts: drafts, liveBranches,
|
|
1486
|
+
const mergedDecision = isClaimed ? decideDraft({ draft, now, runStatus, mergedTwins: merged, openDrafts: drafts, liveBranches,
|
|
1461
1487
|
finalRunResult, ageHours: idleHours }) : undefined;
|
|
1462
1488
|
const supersededClaim = mergedDecision?.reason.startsWith('superseded-by #') === true
|
|
1463
1489
|
|| mergedDecision?.reason.startsWith('duplicate-of-open #') === true;
|
|
@@ -1509,12 +1535,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
|
|
|
1509
1535
|
}
|
|
1510
1536
|
continue;
|
|
1511
1537
|
}
|
|
1512
|
-
|
|
1513
|
-
if (!contradiction && !states.length && !draft.branch.startsWith('self-impl/')) {
|
|
1514
|
-
record({ number: draft.number, action: 'keep', reason: 'outside-harness', applied: false });
|
|
1515
|
-
continue;
|
|
1516
|
-
}
|
|
1517
|
-
let decision = supersededClaim ? mergedDecision! : decideDraft({ draft, runStatus, mergedTwins: merged, openDrafts: drafts, liveBranches,
|
|
1538
|
+
let decision = supersededClaim ? mergedDecision! : decideDraft({ draft, now, runStatus, mergedTwins: merged, openDrafts: drafts, liveBranches,
|
|
1518
1539
|
finalRunResult, ageHours: runStatus ? ageHours : idleHours });
|
|
1519
1540
|
const fallback = decision.reason === 'unobserved' || decision.reason === 'stale-unobserved'
|
|
1520
1541
|
|| decision.reason === 'recent' || decision.reason.startsWith('recent (') || decision.reason.startsWith('stale-ended-run');
|
|
@@ -23,12 +23,64 @@ export function draftClaimRecordLive(at: string, now: Date): boolean {
|
|
|
23
23
|
return Number.isFinite(updated) && (now.getTime() - updated) / 3_600_000 < CLAIM_IDLE_HOURS;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
export interface DraftIntentHold {
|
|
27
|
+
readonly owner: string;
|
|
28
|
+
readonly reason: string;
|
|
29
|
+
readonly expiresAt: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function inspectDraftIntentHold(body: string | undefined, now = new Date()): { hold?: DraftIntentHold; rejection?: string } {
|
|
33
|
+
if (!body || !body.includes('<!-- elanous:draft-intent-hold')) return {};
|
|
34
|
+
if (!Number.isFinite(now.getTime())) return { rejection: 'invalid-sweep-time' };
|
|
35
|
+
const matches = [...body.matchAll(/<!-- elanous:draft-intent-hold ([\s\S]*?) -->/g)];
|
|
36
|
+
const markerStarts = body.match(/<!-- elanous:draft-intent-hold\b/g) ?? [];
|
|
37
|
+
if (matches.length !== 1 || markerStarts.length !== 1) return { rejection: 'marker-count-or-termination' };
|
|
38
|
+
const raw = matches[0]![1]!;
|
|
39
|
+
let value: unknown;
|
|
40
|
+
try { value = JSON.parse(raw); } catch { return { rejection: 'invalid-json' }; }
|
|
41
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return { rejection: 'invalid-shape' };
|
|
42
|
+
const row = value as Record<string, unknown>;
|
|
43
|
+
if (Object.keys(row).length !== 3 || !Object.hasOwn(row, 'owner') || !Object.hasOwn(row, 'reason') || !Object.hasOwn(row, 'expiresAt')) {
|
|
44
|
+
return { rejection: 'invalid-fields' };
|
|
45
|
+
}
|
|
46
|
+
const { owner, reason, expiresAt } = row;
|
|
47
|
+
if (typeof owner !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(owner)
|
|
48
|
+
|| typeof reason !== 'string' || !reason.trim() || reason !== reason.trim() || reason.length > 240
|
|
49
|
+
|| /[\r\n;=]/.test(reason) || reason.includes('-->')
|
|
50
|
+
|| typeof expiresAt !== 'string' || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(expiresAt)) {
|
|
51
|
+
return { rejection: 'invalid-fields' };
|
|
52
|
+
}
|
|
53
|
+
// Compare against the one writer-defined field order. JSON.stringify(parsedObject) alone preserves
|
|
54
|
+
// incoming key order and would silently accept alternate serializations or duplicate keys.
|
|
55
|
+
if (JSON.stringify({ owner, reason, expiresAt }) !== raw) return { rejection: 'noncanonical-json' };
|
|
56
|
+
const expiry = Date.parse(expiresAt);
|
|
57
|
+
if (!Number.isFinite(expiry) || new Date(expiry).toISOString() !== expiresAt) return { rejection: 'invalid-expiry' };
|
|
58
|
+
if (expiry <= now.getTime()) return { rejection: 'expired' };
|
|
59
|
+
return { hold: { owner, reason: reason.trim(), expiresAt } };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Only one canonical, complete, unexpired body marker is a hold; malformed or ambiguous markers fail open to normal triage. */
|
|
63
|
+
export function parseDraftIntentHold(body: string | undefined, now = new Date()): DraftIntentHold | undefined {
|
|
64
|
+
return inspectDraftIntentHold(body, now).hold;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Diagnostic for a present but rejected hold marker; absence is not an error. */
|
|
68
|
+
export function draftIntentHoldRejection(body: string | undefined, now = new Date()): string | undefined {
|
|
69
|
+
return inspectDraftIntentHold(body, now).rejection;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function draftIntentHoldReason(hold: DraftIntentHold): string {
|
|
73
|
+
return `intent-hold owner=${hold.owner}; reason=${hold.reason}; expiresAt=${hold.expiresAt}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
26
76
|
export interface DraftTriagePr {
|
|
27
77
|
number: number;
|
|
28
78
|
title?: string;
|
|
29
79
|
branch: string;
|
|
30
80
|
labels?: readonly string[];
|
|
31
81
|
body?: string;
|
|
82
|
+
/** Last PR update (push, label, comment); absence is not an expiry timestamp. */
|
|
83
|
+
updatedAt?: string;
|
|
32
84
|
mergeCommitMessage?: string;
|
|
33
85
|
landingVerifiedComments?: readonly string[];
|
|
34
86
|
createdAt?: string;
|
|
@@ -109,7 +161,8 @@ export function assessDraftTriage(input: DraftTriageAssessmentInput): DraftTriag
|
|
|
109
161
|
const clock = now.getTime();
|
|
110
162
|
const ageHours = Number.isFinite(latestCommit) && Number.isFinite(clock) ? (clock - latestCommit) / 3_600_000 : NaN;
|
|
111
163
|
const protectedLabel = (draft.labels ?? []).find((name) => CLOSE_PROTECTED_LABELS.has(name));
|
|
112
|
-
const
|
|
164
|
+
const intentHold = parseDraftIntentHold(draft.body, now);
|
|
165
|
+
const protectedState = Boolean(protectedLabel || intentHold);
|
|
113
166
|
const running = input.runStatus === 'running' || input.runStatus === 'probable-running'
|
|
114
167
|
|| (draft.labels ?? []).includes('elanous:running');
|
|
115
168
|
const cellComplete = input.cellStatus === 'green' || input.cellStatus === 'done';
|
|
@@ -146,7 +199,8 @@ export function assessDraftTriage(input: DraftTriageAssessmentInput): DraftTriag
|
|
|
146
199
|
: { state: 'unknown', evidence: '현재 adapter는 같은 칸 병합 PR과 이 초안의 대체 관계를 증명하지 않음; follow-up 필요' },
|
|
147
200
|
'newer-same-card': { state: input.newerSameCellSameCard === undefined ? 'unknown' : input.newerSameCellSameCard ? 'yes' : 'no', evidence: `${input.newerSameCellSameCard === undefined ? '같은 칸·카드 새 draft 관계 미관측' : `same-cell-same-card-newer=${input.newerSameCellSameCard}`}; 관측 표지이며 대체 증거가 아님` },
|
|
148
201
|
'idle-48h': { state: Number.isFinite(ageHours) ? (idle48h ? 'yes' : 'no') : 'unknown', evidence: Number.isFinite(ageHours) ? `head age=${ageHours.toFixed(1)}h` : 'head commit 시각 미관측' },
|
|
149
|
-
protected: { state: protectedState ? 'yes' : 'no', evidence: protectedLabel ? `보호 표지=${protectedLabel}`
|
|
202
|
+
protected: { state: protectedState ? 'yes' : 'no', evidence: protectedLabel ? `보호 표지=${protectedLabel}`
|
|
203
|
+
: intentHold ? draftIntentHoldReason(intentHold) : '보호 표지 없음' },
|
|
150
204
|
'recent-commit': { state: Number.isFinite(latestCommit) ? (recentCommit ? 'yes' : 'no') : 'unknown', evidence: Number.isFinite(latestCommit) ? `last commit=${draft.latestCommitAt}; cutoff=09:30 KST` : 'head commit 시각 미관측' },
|
|
151
205
|
running: { state: running ? 'yes' : runNotRunning ? 'no' : 'unknown', evidence: running ? `run=${input.runStatus ?? 'elanous:running'}` : runNotRunning ? `종결 run=${input.runStatus}` : `run 상태 미관측${input.runStatus ? ` (${input.runStatus})` : ''}` },
|
|
152
206
|
'owner-confirmed': { state: input.ownerConfirmed === undefined ? 'unknown' : input.ownerConfirmed ? 'yes' : 'no', evidence: input.ownerConfirmed === undefined ? '소유자 출처 미관측' : input.ownerConfirmed ? '고유 카드 또는 활성 claim owner 확인' : '고유 소유자 없음' },
|
|
@@ -161,6 +215,7 @@ export function assessDraftTriage(input: DraftTriageAssessmentInput): DraftTriag
|
|
|
161
215
|
|
|
162
216
|
export interface DraftTriageInput {
|
|
163
217
|
draft: DraftTriagePr;
|
|
218
|
+
now?: Date;
|
|
164
219
|
runStatus: string | undefined;
|
|
165
220
|
mergedTwins: readonly DraftTriagePr[];
|
|
166
221
|
openDrafts?: readonly DraftTriagePr[];
|
|
@@ -251,10 +306,12 @@ export function harvestDeferredMarker(body: string | undefined): boolean {
|
|
|
251
306
|
&& rows.length > 0 && rows.every((value) => value === HARVEST_DEFERRED_MARKER_VALUE);
|
|
252
307
|
}
|
|
253
308
|
|
|
254
|
-
export function decideDraft({ draft, runStatus, mergedTwins, openDrafts, ageHours, liveBranches, finalRunResult }: DraftTriageInput): DraftDecision {
|
|
309
|
+
export function decideDraft({ draft, runStatus, mergedTwins, openDrafts, ageHours, liveBranches, finalRunResult, now = new Date() }: DraftTriageInput): DraftDecision {
|
|
255
310
|
// DRAFT-ZERO — a verified harvest-deferred marker is the strongest hold: it outranks protected labels
|
|
256
311
|
// and every close rule, so a failed run's harvestable draft survives the sweep for harvest.
|
|
257
312
|
if (runStatus === 'failed' && harvestDeferredMarker(draft.body)) return { action: 'keep', reason: 'harvest-deferred' };
|
|
313
|
+
const intentHold = parseDraftIntentHold(draft.body, now);
|
|
314
|
+
if (intentHold) return { action: 'keep', reason: draftIntentHoldReason(intentHold) };
|
|
258
315
|
const held = draft.labels?.find((label) => PROTECTED_LABELS.has(label));
|
|
259
316
|
if (held) return { action: 'keep', reason: `label:${held}` };
|
|
260
317
|
if (runStatus !== 'self-implement.result final' && draft.branch && liveBranches.has(draft.branch)
|