elanous 0.2.32 → 0.2.35
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 → T1mBQqmkwKDLGtyisDCOd}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 0368f25d-ad84af92fefee68f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1165.bad13fc9151a7288.js +1 -0
- package/apps/pwa/out/_next/static/chunks/13.02a07436dec15f89.js +32 -0
- package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 1530.0e612369b6fd7ea0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1540.af38731fa7c4a3e0.js +41 -0
- package/apps/pwa/out/_next/static/chunks/{7391.ebae168025c91b6a.js → 1674.2a65fd5668e1cc5f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1850.f2b470ba5a471da0.js +24 -0
- package/apps/pwa/out/_next/static/chunks/193.62da94cd0b88323b.js +74 -0
- package/apps/pwa/out/_next/static/chunks/1975.260f6d249fac5f7c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1982-67cd8dfe8682325f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7947-d0759430f8042240.js → 1993-c0007b7ad0c0ef41.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{60fb96c9.360b01d8d4927b7b.js → 1c735de4.f993a30bbd3c57c4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1dc5a567.9b092bfae3d7099b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 2018.a741297bce759490.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2085.8f950b4bda1cbbc7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2159-6179a961376956b9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/216.b5c2a421aa1d28a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2251.49fbe369f74c372c.js +148 -0
- package/apps/pwa/out/_next/static/chunks/2286-2939577360d3dcc0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3902.e1e71aaac850a045.js → 2625.5d870aa999f33db1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2668.34d21539e62bf111.js +77 -0
- package/apps/pwa/out/_next/static/chunks/2833-0fe47af99ed13c29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2930.d0edb4f108787ef7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2973.77318e7d85f59477.js +62 -0
- package/apps/pwa/out/_next/static/chunks/3103.0df8da390948bb84.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3123.2bee9ba15d320bd2.js +90 -0
- package/apps/pwa/out/_next/static/chunks/3162-6cf652bf7124d8cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 3408.21d1570602f4b6c0.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3577-7340009f7007a795.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3589.5444a06bcf6e775c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/359-2250789a2d3499e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3618.f514792d6c59d7fd.js +36 -0
- package/apps/pwa/out/_next/static/chunks/3669.343f9119aa276001.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 3677-4215f826f6aa68e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3736.c2efad489604cc3b.js +79 -0
- package/apps/pwa/out/_next/static/chunks/3817.f9aeab2bb6675d73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3f7c4ee5.3dde54f01a816613.js +122 -0
- package/apps/pwa/out/_next/static/chunks/4182-0b9b1251c29cc0cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7371.80c05c653b08e907.js → 4346.8601952e73bf5803.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4441-875b97f5821ed58a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4582.bd68683c076649e3.js +286 -0
- package/apps/pwa/out/_next/static/chunks/4605-6e623f55aec77422.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4607.5cc27468628eb4bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4627.f07508b3936fd6c0.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 4705-194e64e47ca0fbdb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 4718-17d2af636796a330.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/4747-c22262c093e46807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4775-178215aed0daba61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4815-6ffb8c3c991cc45d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4834-beca8b47ad29a898.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5023-fb4802b6d2492b02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 5101.e32282718f99ed6f.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{2001.6c7e0fd02190886c.js → 5154.a118f3957ed14e36.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5210-a2e0015e3d4d5d9c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5356.84ac712cc15928bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5401.22352141b6fd336e.js +23 -0
- package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 5483-dd5d7697f6bdb106.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5637.281e5dec4ea6ecf1.js +94 -0
- package/apps/pwa/out/_next/static/chunks/5662.02eaa029af05ad46.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3267c0e6.d34854e7b3984a6e.js → 56d372f2.681ab4ec4c998fae.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5852.db1f7449f4f74612.js +287 -0
- package/apps/pwa/out/_next/static/chunks/5891-0f11a7d7362a9072.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5943.264d14a44ca32513.js +1 -0
- package/apps/pwa/out/_next/static/chunks/604-1b3c39df083c02aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6121-5f97072330738caf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6193.07d8ca5af4b09086.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6203-b3fea3a60d69ff14.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 6236.e18cced2d5ba6afb.js} +17 -17
- package/apps/pwa/out/_next/static/chunks/6286.d638fb5953e2e757.js +8 -0
- package/apps/pwa/out/_next/static/chunks/630.fe5a46428d63b013.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6301.ae0245f507e4395e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6673.fbbe5699f6ea5991.js +27 -0
- package/apps/pwa/out/_next/static/chunks/6777-f6d301efb5de828d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6786.423f24c88de034c7.js +93 -0
- package/apps/pwa/out/_next/static/chunks/6854-cef64a948c5e122d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6866-79aa5b4e47cac6aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6544cb48.a87fe20ddf137be2.js → 6b89c8bd.24df687a820500b3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7037-fe27f001db30d323.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7080.2d826860534fd88e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7118.8731be28c3ebb14b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7196.44241bc1df3e26fe.js +149 -0
- package/apps/pwa/out/_next/static/chunks/7235.c7c4e6cb5c693c2d.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7385.50a308a477bdfc21.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 7644.17e37ba6f1d4226e.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/7706-58bfb1546637f217.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7839.5b91455338c9fd3f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7857-31f13ee96f4011aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/81.f74cb60312fe4001.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8018.a32663f04a6fc5f9.js → 8219.baa715d1deee80e2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4111.2bfedbb233ad206b.js → 8256.e3ac8421a71f82f4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8310-444a6a895c402f12.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8423.f7dda8aca4fcaae5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8437-8d5492094b166cfa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 8444.4c26b379ca2b9596.js} +17 -17
- package/apps/pwa/out/_next/static/chunks/8496.75649af8652c74f4.js +226 -0
- package/apps/pwa/out/_next/static/chunks/8557-e7898769499cd56f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8576.65bb654b524f3614.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8609.558ce2f8f9aea2be.js +64 -0
- package/apps/pwa/out/_next/static/chunks/8614.caec96cfb91f4ae7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 8637.47f5b35afcae5e6b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8714.ff0b7ce3ec3e3ae2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8732.367f44a916202353.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9141-7fd1f73a5400bdc2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/921.c4267d0d69a65404.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9214.63a510d39178e997.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9261.3962c3321b047691.js +115 -0
- package/apps/pwa/out/_next/static/chunks/936-26efd1a0efdd44d3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 938.66ad1ef0e5abae1c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 9512.5a76207a730e0491.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9627-4b9efe616b27e2e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{69-0a2c8209c6d4a158.js → 967-2aa39b2d04b4c690.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9734.40eb1e558c29ccea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9908.3aa54f7a586a73dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 9952.5daf5f94063a2b3e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9954-ca8d29752bdbb45a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9974-507fa67cb94066dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-ce9e00f7fb45506a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-fa59d6d17daa3389.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-53f68bbe7bd4b774.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-1c500fbb9f4a7a04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-99d72673aa5c307c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-d2d5adc1e9484c88.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-c607c5aae637f1cc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-fa8c23596d555c0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-bdab8c5e855c8416.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/{page-a27b1e5a0d1b308f.js → page-406b47745b53f269.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-a4276386b7051f50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-8a26bab9ad375f25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-775f48aa1dc7a2d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-1c4dd5f959d0c558.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-c48938a8377c9f70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-ce9e00f7fb45506a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-c6e7905859425aa9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c280f4252452e830.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-cf8c57498f20970a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-ca3a17caf409fc83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-26e6c18a1a750cf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-3abc872cc6aeee39.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-f7481b7b2174fe3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1ae7ef8077680337.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-32866485913d6a04.js → page-47c5d4db587266bd.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-415f1e243c7ccb13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-73f380f17b76f95c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-2991073ad66ee2d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1f5a60f70cb4dd0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fbad60d1e358fb2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-bac7dee94e5eae4a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-398047d6949e8ca5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-2d33a2231540ca89.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5bf1e6bf70bcb96c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-ba59c19376a0917d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-111f187139add30f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-acaae197d5be5779.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0df20b0f546a0d7d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-ce9e00f7fb45506a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-27e1202d24b8fe35.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-bda78c50a78363e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-da592691293d9c9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f832994317a2e9f0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-04d00ae9b0890349.js → page-dc0a532f5b9196ec.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-cfccbbeae0473404.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-527e2073af84c81b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-bac86e9112671357.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6d59dff410e9d76a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-53a61f8be09f02d2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-db8f559e763c17f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c02aa4cc66455093.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → b2f6ba4d.fb56fdbbf798df33.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/b6705a4f-b9a9047de9eecfd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → cbe38a15.5a032598e39970c6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → d06f9160.a3d9062f95de8ad7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → da5176c6.6773b6c5994e1d99.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/framework-50e6acebc630849b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-7a1ae342d5ed75e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-7ad7d505ba1f92b4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-02edba75232cb235.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-97d6ebae3e8eee4a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-e986adaa429163e8.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 +10 -2
- package/catalog/providers/opengateway.yaml +25 -0
- package/docs/goal-context/01-goal-authoring-checks.md +8 -0
- package/docs/goal-context/03-verification-menu.md +24 -0
- package/docs/goal-context/04-mock-scenarios.md +100 -0
- package/docs/goal-context/README.md +5 -0
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/default-loop.yaml +76 -5
- package/graphs/document-loop.yaml +71 -4
- package/graphs/implement-loop.yaml +59 -4
- package/graphs/journey/SCENARIOS.md +33 -0
- package/graphs/journey/recipes.yaml +1 -0
- package/graphs/journey/ta-journey.yaml +94 -0
- package/graphs/journey/units/author/author.yaml +20 -0
- package/graphs/journey/units/author/recipes.yaml +2 -0
- package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
- package/graphs/journey/units/author-dialogue/observe.ts +96 -0
- package/graphs/journey/units/author-dialogue/recipes.yaml +10 -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 +71 -4
- 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 +159 -4
- package/graphs/test-diet/test-diet.yaml +3 -0
- 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/coord-role-pack.ts +19 -6
- 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 +30 -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/docs-land-node.ts +21 -5
- package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
- 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 +675 -49
- package/scripts/release-loop/gate-partial.ts +68 -14
- package/scripts/release-loop/gate-radius-live.ts +177 -0
- 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/node-verdict.ts +12 -1
- package/scripts/release-loop/npm-publish-node.ts +66 -12
- package/scripts/release-loop/preflight.ts +93 -7
- package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
- package/scripts/release-loop/publish-node.ts +60 -9
- package/scripts/release-loop/pwa-remote.ts +166 -0
- package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
- package/scripts/release-loop/resume-cap.ts +56 -0
- package/scripts/release-loop/resume-release.ts +155 -19
- 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 +10 -2
- package/scripts/test-diet/lib.ts +6 -1
- package/scripts/test-diet/node.ts +194 -13
- package/scripts/ux-sim.ts +39 -0
- package/src/acp/core-turn-bridge.ts +20 -5
- package/src/acp/reasoning-thought-buffer.ts +45 -0
- package/src/agent/self-ambient-cache.ts +8 -0
- package/src/agent-substrate/acp-reviewer.ts +90 -15
- package/src/agent-substrate/pr-reviewer.ts +17 -0
- package/src/agent-substrate/review-finding-key.ts +53 -0
- package/src/agent-substrate/self-review-cli.ts +188 -18
- package/src/ask-user-question/pending-questions.ts +1 -1
- package/src/autopilot/pr-manager.ts +393 -65
- package/src/budget/run-usage-rollup.ts +1 -0
- package/src/chat/index.ts +0 -2
- package/src/chat/pickers/modal-runtime.ts +10 -27
- package/src/chat/tool-render/dispatch.ts +62 -10
- package/src/cli/agent-cli.ts +13 -2
- package/src/cli/control-cli.ts +24 -7
- package/src/cli/doctor-cli.ts +4 -1
- package/src/cli/guardian-cli.ts +10 -0
- package/src/cli/light-entry-route.ts +75 -0
- package/src/cli/llm-detect-cli.ts +23 -1
- package/src/cli/pod-cli.ts +77 -3
- package/src/cli/pr-cli.ts +81 -14
- 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-pod-shadow-job.ts +3 -0
- package/src/cli/pr-land-recovery.ts +64 -0
- package/src/cli/pty-takeover-cli.ts +6 -5
- package/src/cli/release-checklist-read-cli.ts +79 -0
- package/src/cli/release-cli.ts +189 -132
- package/src/cli/release-run-if-ready.ts +29 -28
- package/src/cli/release-single-flight.ts +178 -0
- package/src/cli/remote-resolve.ts +1 -1
- package/src/cli/root-tui-entry.ts +48 -0
- package/src/cli/seat-cli.ts +37 -0
- package/src/cli/setup-cli.ts +40 -1
- package/src/cli/sim-cli.ts +22 -0
- package/src/cli/tasks-cli.ts +667 -14
- package/src/cli/usage-cli.ts +13 -11
- package/src/clipboard/history.ts +179 -13
- package/src/config.ts +8 -1
- 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/chat/acp-chat.ts +8 -0
- package/src/dashboard/index.ts +114 -77
- 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/render/theme-resolver.ts +33 -4
- 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/domains/schedule-registry.ts +16 -2
- package/src/extractors.ts +3 -1
- package/src/git-fs/idle-refresh.ts +76 -0
- package/src/git-fs/index.ts +18 -7
- package/src/git-fs/retry.ts +4 -0
- package/src/git-fs/runner.ts +2 -0
- package/src/git-fs/worktree.ts +42 -4
- package/src/graph-kinds/registry.ts +2 -2
- package/src/graph-runner/runner.ts +267 -54
- package/src/grok/credential.ts +15 -3
- package/src/harness/harness-cli-command.ts +151 -38
- package/src/harness/harness-incidents.ts +37 -0
- package/src/harness/harness-pod-dispatch.ts +38 -1
- package/src/harness/harness-salvage-cli.ts +14 -2
- package/src/harness/launch-utterance-ledger.ts +208 -0
- package/src/impl-discipline/detector.ts +16 -4
- package/src/impl-discipline/system-prompt.ts +11 -0
- package/src/impl-discipline/types.ts +2 -2
- package/src/index.ts +683 -146
- package/src/intake-plane/already-built-hint.ts +91 -0
- package/src/intake-plane/requirement-funnel.ts +29 -1
- package/src/knowhow/pack.ts +199 -0
- package/src/light-cli.ts +111 -0
- package/src/llm/opengateway-models.ts +11 -0
- package/src/llm/provider-credentials.ts +14 -0
- package/src/llm/provider-detect.ts +8 -1
- package/src/llm/runtime-model-family.ts +2 -1
- package/src/llm.ts +268 -65
- 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/model-tier/llm-tier-map.ts +15 -1
- package/src/mss/logging/log-store.ts +4 -5
- package/src/native-tool-catalog.ts +15 -1
- package/src/nexus/api/graphs-api.ts +22 -3
- package/src/nexus/api/http-server.ts +1 -1
- package/src/nexus/api/loop-resources.ts +13 -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/codex.ts +7 -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 +54 -4
- package/src/ops/overview.ts +31 -7
- package/src/pr-tool/census.ts +282 -30
- 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-manifest.ts +7 -0
- 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 +103 -5
- package/src/release-loop/feature-store.ts +19 -2
- package/src/release-loop/landed-but-yellow.ts +129 -5
- package/src/release-loop/light-rc.ts +1 -0
- 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/repl/index.ts +174 -17
- package/src/repl/ops-msg-bridge.ts +32 -0
- package/src/self-dev/ask-launch-flow.ts +44 -5
- package/src/self-dev/cli-help-text.ts +17 -0
- package/src/self-dev/dev-cli.ts +11 -9
- package/src/self-dev/draft-residue.ts +37 -1
- package/src/self-dev/draft-sweep.ts +188 -13
- package/src/self-dev/draft-triage-rules.ts +107 -0
- package/src/self-dev/fleet-reduce.ts +3 -2
- package/src/self-dev/graph-front-nodes.ts +112 -0
- package/src/self-dev/graph-journey-nodes.ts +11 -6
- package/src/self-dev/graph-journey-route.ts +60 -6
- package/src/self-dev/harness-run-cli.ts +3 -15
- package/src/self-dev/orchestrate-cli-text.ts +10 -0
- package/src/self-dev/orchestrate.ts +79 -3
- package/src/self-dev/review-provider-fallback.ts +35 -1
- package/src/self-dev/run-supervisor.ts +107 -12
- package/src/self-dev/run-types.ts +5 -1
- package/src/self-dev/self-orchestrate-runtime.ts +1 -11
- package/src/self-dev/shard-aggregate.ts +42 -5
- package/src/self-dev/shard-run.ts +8 -1
- package/src/self-implement/blocked-draft-policy.ts +20 -0
- package/src/self-implement/classify-shadow.ts +3 -7
- package/src/self-implement/doctor-visit.ts +18 -1
- package/src/self-implement/gate-baseline.ts +95 -12
- package/src/self-implement/gate-cli.ts +1 -0
- package/src/self-implement/gate-remote.ts +40 -25
- package/src/self-implement/goal-author-decompose.ts +275 -47
- 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 +254 -120
- package/src/self-implement/goal-elaborate.ts +295 -0
- package/src/self-implement/goal-refine.ts +270 -0
- package/src/self-implement/graph-overlay-yaml.ts +28 -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 +160 -45
- 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/rework-budget-judgment.ts +5 -8
- package/src/self-implement/run-stop.ts +17 -2
- package/src/self-implement/running-runs.ts +29 -1
- package/src/self-implement/scope-adjacency.ts +113 -0
- package/src/self-implement/seams.ts +138 -4
- package/src/self-implement/stop-autoheal.ts +112 -2
- package/src/session/chat.ts +27 -0
- package/src/session-runtime/index.ts +1 -1
- package/src/session-runtime/retry-policy.ts +2 -1
- package/src/setup/llm-env-detect.ts +5 -0
- package/src/skills/tools/agent.ts +140 -14
- package/src/skills/tools/msg-ask.ts +100 -0
- package/src/skills/tools/ops-ledger.ts +2 -1
- package/src/skills/tools/schedule-wakeup.ts +66 -17
- package/src/steward/hold-hygiene.ts +24 -6
- package/src/steward/release-day.ts +7 -3
- package/src/steward/triage-budget.ts +194 -0
- package/src/steward/triage.ts +57 -7
- package/src/task-agent/actions.ts +69 -1
- package/src/task-agent/green-sweep.ts +4 -0
- package/src/task-agent/harvest-unit.ts +141 -0
- package/src/task-agent/live-moves.ts +257 -15
- package/src/task-agent/parent-host.ts +216 -6
- 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 +19 -3
- package/src/task-agent/task-hand.ts +96 -36
- package/src/task-agent/tier-split.ts +127 -0
- package/src/task-agent/work-order-build.ts +24 -0
- package/src/task-agent/work-order.ts +3 -2
- package/src/task-orchestrator/generator-prompt.ts +60 -11
- package/src/task-orchestrator/surfaces/pod-account-broker.ts +72 -3
- package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-command-job.ts +47 -8
- package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
- package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
- package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
- package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +8 -2
- package/src/task-orchestrator/surfaces/pod-pool.ts +73 -17
- package/src/task-orchestrator/surfaces/pod-provenance.ts +76 -0
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +72 -4
- package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +32 -5
- package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +3 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +421 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +2 -1
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +588 -71
- package/src/task-orchestrator/surfaces/self-implement.ts +106 -2
- package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
- package/src/tool-runtime/truncation-store.ts +4 -0
- package/src/tui/README.md +2 -0
- package/src/tui/chat/background-job-status.ts +54 -0
- package/src/tui/chat/log-view.ts +80 -0
- package/src/tui/entry.ts +406 -0
- package/src/tui/input/composer.ts +144 -0
- package/src/tui/seat-mail-boot.ts +59 -0
- package/src/tui/slash/compact.ts +100 -0
- package/src/tui/slash/new-session.ts +35 -0
- package/src/tui-client/dashboard-session.ts +10 -1
- package/src/tui-client/local-chat-turn.ts +239 -0
- package/src/tui-client/local-harness-command.ts +63 -0
- package/src/tui-client/local-provider-command.ts +184 -0
- package/src/user-config/coercion.ts +36 -0
- package/src/user-config.ts +22 -43
- package/src/ux-sim/event-monkey.ts +378 -0
- package/src/ux-sim/fake-bin.ts +42 -7
- package/src/ux-sim/fault-nextmove-dispatch.ts +266 -0
- package/src/ux-sim/fault-pod-codex-503.ts +211 -0
- package/src/ux-sim/fault-scope-escape-lift.ts +189 -0
- 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/2030.41fae98c7e907304.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.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/2534.e85ae21ad0dac829.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2898.fd781bc7cf01a7b7.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/3541-ce3a5424ed5ad7f1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.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/4745.67d6f99c245af3f7.js +0 -226
- 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/5543.a438b8ab5a13ea47.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/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/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/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/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/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/9002.e5658224e3dc1b6f.js +0 -24
- 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/9407.e49124dedf0f5e72.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/9989.3694300e5f000b14.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/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/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/devices/page-8c66a3b24a745630.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/ebc7d829.264a0bcb6c750b50.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 → T1mBQqmkwKDLGtyisDCOd}/_ssgManifest.js +0 -0
|
@@ -9,21 +9,24 @@
|
|
|
9
9
|
// 구현을 교체(누적 아님). 기존 PR 없으면 새로 생성.
|
|
10
10
|
|
|
11
11
|
import { spawnSync } from 'node:child_process';
|
|
12
|
+
import { randomUUID } from 'node:crypto';
|
|
12
13
|
import { githubAutomationToken } from '../auth/github-app-token.js';
|
|
13
|
-
import { debug } from '../debug/log.js';
|
|
14
|
+
import { debug, redactSecretText } from '../debug/log.js';
|
|
14
15
|
import { POD_GITHUB_CREDENTIAL_TOKEN_ENV, POD_GITHUB_CREDENTIAL_URL_ENV } from '../nexus/api/pod-credential-api.js';
|
|
15
16
|
import { runGitWithRetry } from '../git-fs/retry.js';
|
|
16
17
|
import { DEFAULT_BRANCH_WORKTREE_BASE } from '../git-fs/worktree.js';
|
|
17
18
|
import { isElanousRuntimeArtifactPath } from '../self-implement/gate-scope.js';
|
|
18
19
|
import { isTransientExecutionFailure } from '../self-dev/execution-transient.js';
|
|
19
20
|
import { withGhRestFallback } from './gh-rest-fallback.js';
|
|
20
|
-
import { cellIdFromBody, guardNewPr, parseDiffHunks, readOpenPrs, recordGuardUnmeasured, type GuardVerdict, type HunkOverlapMode, type Seat } from '../pr-tool/census.js';
|
|
21
|
+
import { cardIdFromBody, cellIdFromBody, guardNewPr, hasCardMarker, parseDiffHunks, readOpenPrs, recordGuardUnmeasured, sharedCensusDiffCache, sliceMarkerFromBody, spawnParallelCommands, type GuardVerdict, type HunkOverlapMode, type PrToolParallelCommand, type Seat } from '../pr-tool/census.js';
|
|
22
|
+
import { labelsForAxis, PR_LABEL_NAMES } from '../github/pr-labels.js';
|
|
21
23
|
import { getUserConfig } from '../user-config.js';
|
|
24
|
+
import { runSuffixKey } from '../self-implement/salvage-branches.js';
|
|
22
25
|
|
|
23
26
|
/** ★ stderr 캡처(대표 2026-07-21·관측 갭) — 종전엔 stdout 만 담아 git/gh 실패 사유가 소실됐다
|
|
24
27
|
* (705308: makePr 실패가 bare null 로 뭉뚱그려져 triage 가 "인증·네트워크"로 환각 오라우팅).
|
|
25
28
|
* 이제 err 에 stderr 를 담아 upsertPr 가 실패 단계·사유를 구조화해 반환한다. */
|
|
26
|
-
export interface CmdResult { ok: boolean; out: string; err?: string }
|
|
29
|
+
export interface CmdResult { ok: boolean; out: string; err?: string; /** 실제 종료 코드 — defaultCmdRunner 만 채운다(스텁은 ok 로만 판정). */ rc?: number }
|
|
27
30
|
/** 명령 실행 추상화(주입형·테스트 스텁) — git/gh 를 실제로 돌리지 않고 로직 검증. */
|
|
28
31
|
export type CmdRunner = (cmd: string, args: readonly string[], opts?: { cwd?: string }) => CmdResult;
|
|
29
32
|
|
|
@@ -75,7 +78,10 @@ export const defaultCmdRunner: CmdRunner = (cmd, args, opts) => {
|
|
|
75
78
|
// never read an overflow as success.
|
|
76
79
|
const r = spawnSync(cmd, [...args], { encoding: 'utf-8', timeout: 120_000, maxBuffer: 256 * 1024 * 1024, env, ...(opts?.cwd ? { cwd: opts.cwd } : {}) });
|
|
77
80
|
const overflow = (r.error as NodeJS.ErrnoException | undefined)?.code === 'ENOBUFS';
|
|
78
|
-
|
|
81
|
+
const result: CmdResult = { ok: r.status === 0 && !overflow, out: (r.stdout ?? '').trim(), err: [(r.stderr ?? '').trim(), overflow ? 'output exceeded 256MiB (ENOBUFS)' : ''].filter(Boolean).join('\n') };
|
|
82
|
+
// Keep the historical enumerable result shape while making the exit code available to PR incidents.
|
|
83
|
+
if (typeof r.status === 'number') Object.defineProperty(result, 'rc', { value: r.status, enumerable: false });
|
|
84
|
+
return result;
|
|
79
85
|
} catch (e) { return { ok: false, out: '', err: e instanceof Error ? e.message : String(e) }; }
|
|
80
86
|
};
|
|
81
87
|
|
|
@@ -88,6 +94,8 @@ export function extractPrNumber(prUrl: string): number | null {
|
|
|
88
94
|
export interface UpsertPrInput {
|
|
89
95
|
/** 안정 브랜치명(se/…-<phaseHex>) — 재활용 키. */
|
|
90
96
|
branch: string;
|
|
97
|
+
/** Owning self-implement run; used to keep temporary upload refs inside its Pod push fence. */
|
|
98
|
+
runId?: string;
|
|
91
99
|
/** 격리 worktree 경로(git cwd). */
|
|
92
100
|
worktreePath: string;
|
|
93
101
|
title: string;
|
|
@@ -118,8 +126,10 @@ export interface UpsertPrResult { url: string; reused: boolean }
|
|
|
118
126
|
* 특히 `noop`(nothing to commit)은 **실패가 아니라 이미 반영된 no-op** — 호출부가 정직 PASS 처리.
|
|
119
127
|
* 나머지 reason(add/commit/push/gh)은 진짜 실패로 detail(stderr)과 함께 관측·pr-failed. */
|
|
120
128
|
export type UpsertPrOutcome =
|
|
121
|
-
| { ok: true; url: string; reused: boolean; labelsApplied?: boolean; labelsOmitted?: boolean
|
|
122
|
-
|
|
129
|
+
| { ok: true; url: string; reused: boolean; labelsApplied?: boolean; labelsOmitted?: boolean;
|
|
130
|
+
supersededPr?: number }
|
|
131
|
+
| { ok: false; reason: 'add' | 'commit' | 'base' | 'noop' | 'push' | 'gh' | 'guard'; detail: string;
|
|
132
|
+
incident?: PrCreateFailureIncident };
|
|
123
133
|
|
|
124
134
|
/** 관측된 문면 두 가지:
|
|
125
135
|
* could not add label: 'auto-review' not found
|
|
@@ -178,7 +188,7 @@ function readPrMergeState(run: CmdRunner, prNumber: number, cwd?: string): Merge
|
|
|
178
188
|
export type FindPrForBranchOutcome =
|
|
179
189
|
| { status: 'ok OUTPUT'; url: string }
|
|
180
190
|
| { status: 'ok EMPTY'; url: null }
|
|
181
|
-
| { status: 'FAILED'; url: null }
|
|
191
|
+
| { status: 'FAILED'; url: null; rc?: number; stderrTail?: string }
|
|
182
192
|
| { status: 'SKIPPED'; url: null };
|
|
183
193
|
|
|
184
194
|
export interface PrManager {
|
|
@@ -316,25 +326,276 @@ function isTransientPushFailure(detail: string): boolean {
|
|
|
316
326
|
return isTransientExecutionFailure(pushFailureMessageForTransientCheck(detail));
|
|
317
327
|
}
|
|
318
328
|
|
|
329
|
+
// ── 칸 PR-CREATE-FAIL-OBSERVE-FU — PR 생성 실패 incident(관측 단위) ──────────────
|
|
330
|
+
// run-7308cfbf·run-fabc2564·run-32bca71e·run-42876ab6 의 draft PR 생성 실패가
|
|
331
|
+
// outcome 원장만으로는 push·gh create·인증·원격 충돌 중 어느 단계인지 못 가렸다.
|
|
332
|
+
// 하나의 incident 가 push 와 gh 단계를 각각 식별해 rc·stderr 꼬리·branch/remote·push 성패를 남긴다.
|
|
333
|
+
/** PR 생성 경로에서 실패 관측 대상인 단계. */
|
|
334
|
+
export type PrCreateStageId = 'push' | 'gh';
|
|
335
|
+
/** 단계별 관측: 실행 여부 · 종료 코드 · (자격증명 제거된) stderr 꼬리 · push 성공 여부. */
|
|
336
|
+
export interface PrCreateStageObservation {
|
|
337
|
+
stage: PrCreateStageId;
|
|
338
|
+
ran: boolean;
|
|
339
|
+
rc?: number;
|
|
340
|
+
stderrTail?: string;
|
|
341
|
+
/** push 단계 전용 — force-push 최종 성공 여부. */
|
|
342
|
+
ok?: boolean;
|
|
343
|
+
}
|
|
344
|
+
/** PR 생성 실패 한 건 — push/gh 두 단계 관측을 하나의 기록에. */
|
|
345
|
+
export interface PrCreateFailureIncident {
|
|
346
|
+
runId?: string;
|
|
347
|
+
branch: string;
|
|
348
|
+
remote: string;
|
|
349
|
+
push: PrCreateStageObservation;
|
|
350
|
+
gh: PrCreateStageObservation;
|
|
351
|
+
}
|
|
352
|
+
/** stderr 꼬리로 남기는 최대 글자 수. */
|
|
353
|
+
export const PR_CREATE_STDERR_TAIL_CHARS = 400;
|
|
354
|
+
|
|
355
|
+
/** 토큰·URL 자격증명을 기록 전에 지운다(원문 꼬리는 살리고 비밀만 뭉개기). */
|
|
356
|
+
const CREDENTIAL_REDACTION_PATTERNS: readonly { pattern: RegExp; replacement: string }[] = [
|
|
357
|
+
// GitHub token prefixes(ghp_/gho_/ghu_/ghs_/ghr_/github_pat_ …) — secret 부분만 치환.
|
|
358
|
+
{ pattern: /\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{16,}/g, replacement: '[REDACTED]' },
|
|
359
|
+
{ pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}/g, replacement: '[REDACTED]' },
|
|
360
|
+
// URL userInfo(https://user:pass@host · ssh://user:pass@host) — 스킴은 살리고 자격증명만.
|
|
361
|
+
{ pattern: /((?:https?|ssh|git\+ssh):\/\/)[^\s/@]+:[^\s/@]+@/g, replacement: '$1[REDACTED]@' },
|
|
362
|
+
];
|
|
363
|
+
|
|
364
|
+
/** stderr 텍스트에서 토큰·URL 자격증명을 제거한다. */
|
|
365
|
+
export function sanitizeCredentialText(text: string): string {
|
|
366
|
+
let out = text;
|
|
367
|
+
for (const { pattern, replacement } of CREDENTIAL_REDACTION_PATTERNS) out = out.replace(pattern, replacement);
|
|
368
|
+
return redactSecretText(out);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/** stderr 를 자격증명 제거 뒤 꼬리(기본 400자)만 남긴다. 비면 undefined. */
|
|
372
|
+
export function stderrTailOf(err: string | undefined, chars: number = PR_CREATE_STDERR_TAIL_CHARS): string | undefined {
|
|
373
|
+
const sanitized = sanitizeCredentialText(err ?? '').trim();
|
|
374
|
+
return sanitized ? sanitized.slice(-chars) : undefined;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** PR 생성 실패 incident 를 원장(debug.log)에 남긴다. 성공 경로는 기록하지 않는다. */
|
|
378
|
+
export function recordPrCreateFailureIncident(incident: PrCreateFailureIncident): PrCreateFailureIncident {
|
|
379
|
+
const safe: PrCreateFailureIncident = {
|
|
380
|
+
...(incident.runId ? { runId: sanitizeCredentialText(incident.runId) } : {}),
|
|
381
|
+
branch: sanitizeCredentialText(incident.branch),
|
|
382
|
+
remote: sanitizeCredentialText(incident.remote),
|
|
383
|
+
push: { ...incident.push, ...(incident.push.stderrTail ? { stderrTail: stderrTailOf(incident.push.stderrTail) } : {}) },
|
|
384
|
+
gh: { ...incident.gh, ...(incident.gh.stderrTail ? { stderrTail: stderrTailOf(incident.gh.stderrTail) } : {}) },
|
|
385
|
+
};
|
|
386
|
+
debug.log('autopilot.pr-manager', 'pr-create-failure-incident', safe);
|
|
387
|
+
return safe;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function prCreateFailureOutcome(input: UpsertPrInput, reason: 'push' | 'gh' | 'guard', detail: string,
|
|
391
|
+
push: PrCreateStageObservation, gh: PrCreateStageObservation, targetBranch = input.branch): UpsertPrOutcome {
|
|
392
|
+
const incident = recordPrCreateFailureIncident({
|
|
393
|
+
...(input.runId ? { runId: input.runId } : {}), branch: targetBranch, remote: 'origin', push, gh,
|
|
394
|
+
});
|
|
395
|
+
const safeDetail = sanitizeCredentialText(detail).slice(0, 300);
|
|
396
|
+
// The production caller carries detail into its child failure record.
|
|
397
|
+
return input.runId
|
|
398
|
+
? { ok: false, reason, detail: `${safeDetail}\npr-create-incident=${JSON.stringify(incident)}`, incident }
|
|
399
|
+
: { ok: false, reason, detail: safeDetail };
|
|
400
|
+
}
|
|
401
|
+
|
|
319
402
|
function seatFromEnvironment(): Seat | null {
|
|
320
403
|
// Production launchers stamp this in harness-pod-dispatch.ts and harness-cli-command.ts.
|
|
321
404
|
const value = process.env.ELANOUS_HARNESS_SEAT;
|
|
322
405
|
return value === 'OP' || value === 'TC' || value === 'MK' || value === 'UX' ? value : null;
|
|
323
406
|
}
|
|
324
407
|
|
|
408
|
+
function sameCellGuardDetail(verdict: GuardVerdict, candidateCardId: string | null): string {
|
|
409
|
+
const reasons = verdict.reasons.map(reason => `${reason.code}: ${reason.detail}${reason.prs?.length ? ` (${reason.prs.map(number => `#${number}`).join(', ')})` : ''}`).join('; ');
|
|
410
|
+
return verdict.sameCellConflicts?.length
|
|
411
|
+
? `${reasons}; candidateCardId=${candidateCardId ?? 'unknown'}; blockers=${verdict.sameCellConflicts.map(({ pr, cardId }) => `#${pr}:${cardId ?? 'unknown'}`).join(',')}`
|
|
412
|
+
: reasons;
|
|
413
|
+
}
|
|
414
|
+
|
|
325
415
|
/** PR-GUARD-HUNK-WARN: config `prTool.hunkOverlap` — 'refuse' 만 옛 거부, 없거나 그 밖은 'warn'. */
|
|
326
416
|
export function configuredHunkOverlapMode(raw: Record<string, unknown> | undefined = getUserConfig().raw): HunkOverlapMode {
|
|
327
417
|
const prTool = raw?.prTool as { hunkOverlap?: unknown } | undefined;
|
|
328
418
|
return prTool?.hunkOverlap === 'refuse' ? 'refuse' : 'warn';
|
|
329
419
|
}
|
|
330
420
|
|
|
421
|
+
/** PR-CENSUS-PARALLEL: the guard's `gh pr diff` fan-out, with the same gh credentials as {@link defaultCmdRunner}. */
|
|
422
|
+
export const defaultCensusParallelRunner: PrToolParallelCommand = (calls, concurrency) =>
|
|
423
|
+
spawnParallelCommands(calls, { concurrency, env: ghAutomationEnv(process.env) });
|
|
424
|
+
|
|
331
425
|
function defaultPrCreateGuard(input: { cwd: string; base: string | undefined; seat: Seat | null; body: string }, run: CmdRunner): GuardVerdict {
|
|
332
426
|
if (!input.base) return guardNewPr({ files: null, seat: input.seat }, { status: 'unknown', reason: '비교 base 없음' });
|
|
333
427
|
const diff = run('git', ['-C', input.cwd, 'diff', '--name-only', '-z', `${input.base}...HEAD`]);
|
|
334
428
|
const files = diff.ok ? diff.out.split('\0').filter(Boolean) : null;
|
|
335
429
|
const patch = run('git', ['-C', input.cwd, 'diff', '--unified=0', `${input.base}...HEAD`]);
|
|
336
430
|
if (!patch.ok) return guardNewPr({ files: null, seat: input.seat }, { status: 'unknown', reason: `후보 수정 줄 조회 실패: ${patch.err || patch.out}` });
|
|
337
|
-
|
|
431
|
+
const boundRaw = process.env.ELANOUS_TASK_BOUND_PR;
|
|
432
|
+
const boundPrNumber = boundRaw && /^[1-9]\d*$/.test(boundRaw) ? Number(boundRaw) : undefined;
|
|
433
|
+
return guardNewPr({ files, seat: input.seat, cellId: cellIdFromBody(input.body), cardId: cardIdFromBody(input.body),
|
|
434
|
+
slice: sliceMarkerFromBody(input.body),
|
|
435
|
+
...(boundPrNumber && Number.isSafeInteger(boundPrNumber) ? { boundPrNumber } : {}),
|
|
436
|
+
hunks: parseDiffHunks(patch.out), hunkOverlap: configuredHunkOverlapMode() }, readOpenPrs(run, { cwd: input.cwd, ...(files ? { candidateFiles: files } : {}),
|
|
437
|
+
runParallel: defaultCensusParallelRunner, diffCache: sharedCensusDiffCache }));
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function editExistingPr(run: CmdRunner, input: UpsertPrInput, url: string): UpsertPrOutcome {
|
|
441
|
+
const opts = { cwd: input.worktreePath };
|
|
442
|
+
const detailOf = (r: CmdResult) => (r.err || r.out || '').slice(0, 300);
|
|
443
|
+
const editArgs = ['pr', 'edit', url, '--title', input.title, '--body', input.body];
|
|
444
|
+
const explicitBase = input.base?.trim();
|
|
445
|
+
if (explicitBase && !isBranchSelfRef(explicitBase, input.branch)) editArgs.push('--base', prBaseFromComparison(explicitBase));
|
|
446
|
+
for (const label of new Set((input.labels ?? []).map(label => label.trim()).filter(Boolean))) editArgs.push('--add-label', label);
|
|
447
|
+
const edited = run('gh', editArgs, opts);
|
|
448
|
+
if (!edited.ok) return { ok: false, reason: 'gh', detail: detailOf(edited) || 'gh pr edit 실패' };
|
|
449
|
+
if (input.draft !== undefined) {
|
|
450
|
+
const stateR = run('gh', ['pr', 'view', url, '--json', 'isDraft', '-q', '.isDraft'], opts);
|
|
451
|
+
const raw = stateR.out.trim();
|
|
452
|
+
if (!stateR.ok || (raw !== 'true' && raw !== 'false'))
|
|
453
|
+
return { ok: false, reason: 'gh', detail: detailOf(stateR) || `draft 상태 조회 실패(isDraft=${raw || 'empty'})` };
|
|
454
|
+
if (input.draft === false && raw === 'true') {
|
|
455
|
+
const ready = run('gh', ['pr', 'ready', url], opts);
|
|
456
|
+
if (!ready.ok) return { ok: false, reason: 'gh', detail: detailOf(ready) || 'gh pr ready 실패' };
|
|
457
|
+
} else if (input.draft === true && raw === 'false') {
|
|
458
|
+
const undo = run('gh', ['pr', 'ready', url, '--undo'], opts);
|
|
459
|
+
if (!undo.ok) return { ok: false, reason: 'gh', detail: detailOf(undo) || 'gh pr ready --undo 실패' };
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (input.reuseComment) run('gh', ['pr', 'comment', url, '--body', input.reuseComment], opts);
|
|
463
|
+
return { ok: true, url, reused: true };
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** Same-card rework may have a new run branch. Merge the bound PR head into that work,
|
|
467
|
+
* then update the bound branch with a plain fast-forward push. Every identity read is
|
|
468
|
+
* checked again after the inventory snapshot; an ambiguous or moved PR stays refused. */
|
|
469
|
+
function reuseSameCellPr(run: CmdRunner, input: UpsertPrInput, target: NonNullable<GuardVerdict['sameCellReuse']>, recheck: () => GuardVerdict): UpsertPrOutcome {
|
|
470
|
+
const cwd = input.worktreePath;
|
|
471
|
+
const pushEvidence = { ref: `refs/heads/${target.branch}`, remoteHead: target.headSha, cardId: target.cardId };
|
|
472
|
+
const fail = (detail: string): UpsertPrOutcome => {
|
|
473
|
+
const safeDetail = sanitizeCredentialText(detail).slice(0, 300);
|
|
474
|
+
debug.log('autopilot.pr-manager', 'same-cell-push-decision', { ...pushEvidence, outcome: 'refused', reason: safeDetail }, { level: 'warn' });
|
|
475
|
+
return { ok: false, reason: 'guard', detail: `same-cell reuse: ${safeDetail}` };
|
|
476
|
+
};
|
|
477
|
+
if (!/^[0-9a-f]{40}$/i.test(target.headSha) || !Number.isSafeInteger(target.number) || target.number < 1
|
|
478
|
+
|| cellIdFromBody(input.body) !== target.cellId || cardIdFromBody(input.body) !== target.cardId)
|
|
479
|
+
return fail('candidate identity mismatch');
|
|
480
|
+
const validBranch = run('git', ['-C', cwd, 'check-ref-format', '--branch', target.branch]);
|
|
481
|
+
if (!validBranch.ok) return fail('PR branch name invalid');
|
|
482
|
+
const viewFields = 'state,headRefOid,headRefName,body,isCrossRepository,url,isDraft,labels';
|
|
483
|
+
const view = run('gh', ['pr', 'view', String(target.number), '--json', viewFields], { cwd });
|
|
484
|
+
if (!view.ok) return fail('PR identity read failed');
|
|
485
|
+
let pr: Record<string, unknown>;
|
|
486
|
+
try { pr = JSON.parse(view.out) as Record<string, unknown>; } catch { return fail('PR identity malformed'); }
|
|
487
|
+
if (pr.state !== 'OPEN' || pr.isCrossRepository !== false || pr.headRefOid !== target.headSha
|
|
488
|
+
|| pr.headRefName !== target.branch || typeof pr.body !== 'string'
|
|
489
|
+
|| cellIdFromBody(pr.body) !== target.cellId
|
|
490
|
+
|| (sliceMarkerFromBody(input.body)?.slice ?? null) !== (sliceMarkerFromBody(pr.body)?.slice ?? null)
|
|
491
|
+
|| (sliceMarkerFromBody(input.body)?.total ?? null) !== (sliceMarkerFromBody(pr.body)?.total ?? null)
|
|
492
|
+
|| (target.legacyBound ? hasCardMarker(pr.body) || process.env.ELANOUS_TASK_BOUND_PR !== String(target.number)
|
|
493
|
+
: cardIdFromBody(pr.body) !== target.cardId)
|
|
494
|
+
|| typeof pr.url !== 'string' || extractPrNumber(pr.url) !== target.number)
|
|
495
|
+
return fail('PR state, head, repository, or card lineage changed');
|
|
496
|
+
const remoteRef = `refs/heads/${target.branch}`;
|
|
497
|
+
const remote = run('git', ['-C', cwd, 'ls-remote', '--exit-code', 'origin', remoteRef]);
|
|
498
|
+
if (!remote.ok || remote.out.trim() !== `${target.headSha}\t${remoteRef}`) return fail('remote head changed');
|
|
499
|
+
const localRef = `refs/elanous/pr-reuse/${target.number}-${target.headSha.slice(0, 12)}`;
|
|
500
|
+
const fetched = run('git', ['-C', cwd, 'fetch', 'origin', `${remoteRef}:${localRef}`]);
|
|
501
|
+
const fetchedHead = fetched.ok ? run('git', ['-C', cwd, 'rev-parse', localRef]) : undefined;
|
|
502
|
+
if (!fetched.ok || !fetchedHead?.ok || fetchedHead.out.trim() !== target.headSha) return fail('PR head fetch mismatch');
|
|
503
|
+
const merged = run('git', ['-C', cwd, 'merge', '--no-edit', target.headSha]);
|
|
504
|
+
if (!merged.ok) {
|
|
505
|
+
const aborted = run('git', ['-C', cwd, 'merge', '--abort']);
|
|
506
|
+
if (!aborted.ok) return fail(`PR head merge abort failed: ${(aborted.err || aborted.out).slice(0, 220)}`);
|
|
507
|
+
// A conflicting same-card draft cannot be fast-forwarded. Preserve this run's
|
|
508
|
+
// head on its own branch, and let the returned new PR URL bind the card.
|
|
509
|
+
if (pr.isDraft !== true) return fail('conflicting PR is not a draft');
|
|
510
|
+
const clean = run('git', ['-C', cwd, 'status', '--porcelain', '--untracked-files=no']);
|
|
511
|
+
if (!clean.ok || clean.out.trim()) return fail('worktree changed after merge abort');
|
|
512
|
+
const before = run('gh', ['pr', 'view', String(target.number), '--json', viewFields], { cwd });
|
|
513
|
+
let old: Record<string, unknown>;
|
|
514
|
+
try { old = JSON.parse(before.out) as Record<string, unknown>; } catch { return fail('PR pre-create identity malformed'); }
|
|
515
|
+
const remoteNow = run('git', ['-C', cwd, 'ls-remote', '--exit-code', 'origin', remoteRef]);
|
|
516
|
+
const latest = recheck().sameCellReuse;
|
|
517
|
+
if (!before.ok || old.state !== 'OPEN' || old.isDraft !== true || old.headRefOid !== target.headSha
|
|
518
|
+
|| old.headRefName !== target.branch || old.body !== pr.body || old.url !== pr.url
|
|
519
|
+
|| !remoteNow.ok || remoteNow.out.trim() !== `${target.headSha}\t${remoteRef}`
|
|
520
|
+
|| !latest || latest.number !== target.number || latest.branch !== target.branch
|
|
521
|
+
|| latest.headSha !== target.headSha || latest.cellId !== target.cellId
|
|
522
|
+
|| latest.cardId !== target.cardId || Boolean(latest.legacyBound) !== Boolean(target.legacyBound))
|
|
523
|
+
return fail('PR changed before superseding draft');
|
|
524
|
+
const newRef = `refs/heads/${input.branch}`;
|
|
525
|
+
if (!run('git', ['-C', cwd, 'check-ref-format', '--branch', input.branch]).ok) return fail('new run branch name invalid');
|
|
526
|
+
const newRemote = run('git', ['-C', cwd, 'ls-remote', '--heads', 'origin', newRef]);
|
|
527
|
+
if (!newRemote.ok || newRemote.out.trim()) return fail('new run branch already exists or remote unreadable');
|
|
528
|
+
const localHead = run('git', ['-C', cwd, 'rev-parse', 'HEAD']);
|
|
529
|
+
if (!localHead.ok || !/^[0-9a-f]{40}$/i.test(localHead.out.trim())) return fail('new run head unreadable');
|
|
530
|
+
// Upload the commit through a unique scratch ref. GitHub's create-ref API then
|
|
531
|
+
// atomically refuses a concurrent writer of the intended branch name.
|
|
532
|
+
const runKey = input.runId ? runSuffixKey(input.runId) : null;
|
|
533
|
+
if (!runKey) return fail(input.runId ? 'new run id invalid for scratch ref' : 'run id required for scratch ref');
|
|
534
|
+
const scratch = `self-impl/pr-create-r${runKey}-${randomUUID()}`;
|
|
535
|
+
const scratchRef = `refs/heads/${scratch}`;
|
|
536
|
+
const uploaded = run('git', ['-C', cwd, 'push', 'origin', `HEAD:${scratchRef}`]);
|
|
537
|
+
if (!uploaded.ok) return fail(`new run object upload failed: ${(uploaded.err || uploaded.out).slice(0, 220)}`);
|
|
538
|
+
const repository = run('gh', ['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner'], { cwd });
|
|
539
|
+
const repoName = repository.out.trim();
|
|
540
|
+
const createdRef = repository.ok && /^[^/\s]+\/[^/\s]+$/.test(repoName)
|
|
541
|
+
? run('gh', ['api', '--method', 'POST', `repos/${repoName}/git/refs`, '-f', `ref=${newRef}`, '-f', `sha=${localHead.out.trim()}`], { cwd })
|
|
542
|
+
: { ok: false, out: '', err: 'repository identity unavailable' };
|
|
543
|
+
const removedScratch = run('git', ['-C', cwd, 'push', 'origin', `:${scratchRef}`]);
|
|
544
|
+
if (!removedScratch.ok) debug.log('autopilot.pr-manager', 'same-cell-scratch-cleanup-failed',
|
|
545
|
+
{ scratchRef, detail: removedScratch.err || removedScratch.out,
|
|
546
|
+
stderr: removedScratch.err ?? '', stdout: removedScratch.out, truncated: false }, { level: 'warn' });
|
|
547
|
+
if (!createdRef.ok) return fail(`new run branch create refused: ${(createdRef.err || createdRef.out).slice(0, 220)}`);
|
|
548
|
+
const stateLabels = new Set(labelsForAxis('state').map(label => label.name));
|
|
549
|
+
const labels = [...new Set([...(input.labels ?? []).filter(label => !stateLabels.has(label as typeof PR_LABEL_NAMES.running)),
|
|
550
|
+
PR_LABEL_NAMES.running, ...(input.seat ? [`seat:${input.seat}`] : [])])];
|
|
551
|
+
const body = `${input.body.trimEnd()}\n\nSupersedes: #${target.number}`;
|
|
552
|
+
const create = ['pr', 'create', '--draft', '--head', input.branch, '--title', input.title, '--body', body];
|
|
553
|
+
const base = input.base?.trim();
|
|
554
|
+
if (base && !isBranchSelfRef(base, input.branch)) create.push('--base', prBaseFromComparison(base));
|
|
555
|
+
for (const label of labels) create.push('--label', label);
|
|
556
|
+
const created = run('gh', create, { cwd });
|
|
557
|
+
const newUrl = created.out.trim();
|
|
558
|
+
const newNumber = extractPrNumber(newUrl);
|
|
559
|
+
if (!created.ok || !newNumber) return { ok: false, reason: 'gh', detail: `superseding draft create failed: ${(created.err || created.out).slice(0, 220)}` };
|
|
560
|
+
debug.log('autopilot.pr-manager', 'same-cell-conflict-new-draft',
|
|
561
|
+
{ oldPr: target.number, newPr: newNumber, cardId: target.cardId, oldDraftCleanup: 'deferred' });
|
|
562
|
+
return { ok: true, url: newUrl, reused: false, supersededPr: target.number };
|
|
563
|
+
}
|
|
564
|
+
if (!run('git', ['-C', cwd, 'merge-base', '--is-ancestor', target.headSha, 'HEAD']).ok) return fail('PR head is not ancestor of result');
|
|
565
|
+
const finalView = run('gh', ['pr', 'view', String(target.number), '--json', viewFields], { cwd });
|
|
566
|
+
let finalPr: Record<string, unknown>;
|
|
567
|
+
try { finalPr = JSON.parse(finalView.out) as Record<string, unknown>; } catch { return fail('PR pre-push identity read failed'); }
|
|
568
|
+
if (!finalView.ok || finalPr.state !== 'OPEN' || finalPr.isCrossRepository !== false
|
|
569
|
+
|| finalPr.headRefOid !== target.headSha || finalPr.headRefName !== target.branch
|
|
570
|
+
|| typeof finalPr.body !== 'string' || cellIdFromBody(finalPr.body) !== target.cellId
|
|
571
|
+
|| (sliceMarkerFromBody(input.body)?.slice ?? null) !== (sliceMarkerFromBody(finalPr.body)?.slice ?? null)
|
|
572
|
+
|| (sliceMarkerFromBody(input.body)?.total ?? null) !== (sliceMarkerFromBody(finalPr.body)?.total ?? null)
|
|
573
|
+
|| (target.legacyBound ? hasCardMarker(finalPr.body) || process.env.ELANOUS_TASK_BOUND_PR !== String(target.number)
|
|
574
|
+
: cardIdFromBody(finalPr.body) !== target.cardId)
|
|
575
|
+
|| finalPr.url !== pr.url) return fail('PR changed before push');
|
|
576
|
+
const finalRemote = run('git', ['-C', cwd, 'ls-remote', '--exit-code', 'origin', remoteRef]);
|
|
577
|
+
if (!finalRemote.ok || finalRemote.out.trim() !== `${target.headSha}\t${remoteRef}`) return fail('remote head changed before push');
|
|
578
|
+
const latest = recheck().sameCellReuse;
|
|
579
|
+
if (!latest || latest.number !== target.number || latest.branch !== target.branch
|
|
580
|
+
|| latest.headSha !== target.headSha || latest.cellId !== target.cellId
|
|
581
|
+
|| latest.cardId !== target.cardId || Boolean(latest.legacyBound) !== Boolean(target.legacyBound))
|
|
582
|
+
return fail('OPEN PR inventory changed before push');
|
|
583
|
+
// The result descends from the exact fetched head. The explicit lease binds the
|
|
584
|
+
// remote update to that head, so a delete or move between reads cannot be revived.
|
|
585
|
+
// The Pod hook receives these values for this one push only. It checks the Pod card,
|
|
586
|
+
// exact remote head and ancestry independently before allowing another run's ref.
|
|
587
|
+
const podReuseConfig = input.runId && process.env.ELANOUS_TASK_CARD_ID ? [
|
|
588
|
+
'-c', `elanous.sameCellReuseRef=${remoteRef}`,
|
|
589
|
+
'-c', `elanous.sameCellReuseHead=${target.headSha}`,
|
|
590
|
+
'-c', `elanous.sameCellReuseCard=${target.cardId}`,
|
|
591
|
+
] : [];
|
|
592
|
+
const pushed = run('git', ['-C', cwd,
|
|
593
|
+
...podReuseConfig,
|
|
594
|
+
'push', `--force-with-lease=${remoteRef}:${target.headSha}`, 'origin', `HEAD:${remoteRef}`]);
|
|
595
|
+
if (!pushed.ok) return fail(`fast-forward push refused: ${(pushed.err || pushed.out).slice(0, 220)}`);
|
|
596
|
+
debug.log('autopilot.pr-manager', 'same-cell-push-decision', { ...pushEvidence, outcome: 'allowed', reason: 'bound-card-pr-head-fast-forward' });
|
|
597
|
+
debug.log('autopilot.pr-manager', 'same-cell-reused', { pr: target.number, cellId: target.cellId, cardId: target.cardId, branch: target.branch });
|
|
598
|
+
return editExistingPr(run, input, pr.url);
|
|
338
599
|
}
|
|
339
600
|
|
|
340
601
|
/** ★ PR 매니저 팩토리(대표 2026-07-12) — CmdRunner 주입(테스트 스텁). 실 배선은 기본 러너. */
|
|
@@ -362,7 +623,9 @@ export function makePrManager(
|
|
|
362
623
|
const r = run('gh', ['pr', 'list', '--head', branch, '--state', 'open', '--json', 'url', '--jq', '.[0].url // ""'], cwd ? { cwd } : undefined);
|
|
363
624
|
const url = r.out.trim() || null;
|
|
364
625
|
const outcome: FindPrForBranchOutcome = !r.ok
|
|
365
|
-
? { status: 'FAILED', url: null
|
|
626
|
+
? { status: 'FAILED', url: null,
|
|
627
|
+
...(typeof r.rc === 'number' ? { rc: r.rc } : {}),
|
|
628
|
+
...(stderrTailOf(r.err || r.out) ? { stderrTail: stderrTailOf(r.err || r.out) } : {}) }
|
|
366
629
|
: url
|
|
367
630
|
? { status: 'ok OUTPUT', url }
|
|
368
631
|
: { status: 'ok EMPTY', url: null };
|
|
@@ -378,21 +641,34 @@ export function makePrManager(
|
|
|
378
641
|
return {
|
|
379
642
|
findPrForBranch,
|
|
380
643
|
findPrForBranchOutcome,
|
|
381
|
-
upsertPr(
|
|
644
|
+
upsertPr(candidateInput) {
|
|
645
|
+
// ★ sibling-slice(쪼개기 정착) — composeSliceHandText(tier-split.ts)가 hand 문면에 표지를 쓰고
|
|
646
|
+
// prBody(orchestrator.ts)가 그 문면을 PR 본문에 보존한다. 조각 번호만 제목에 덧붙인다.
|
|
647
|
+
const candidateSlice = sliceMarkerFromBody(candidateInput.body);
|
|
648
|
+
const input: UpsertPrInput = candidateSlice
|
|
649
|
+
? { ...candidateInput,
|
|
650
|
+
title: `${candidateInput.title} · 조각 ${candidateSlice.slice}/${candidateSlice.total}`,
|
|
651
|
+
body: candidateInput.body }
|
|
652
|
+
: candidateInput;
|
|
653
|
+
const taskCardId = process.env.ELANOUS_TASK_CARD_ID;
|
|
654
|
+
if (taskCardId && (!hasCardMarker(input.body) || cardIdFromBody(input.body) !== taskCardId))
|
|
655
|
+
return { ok: false, reason: 'guard', detail: `task card PR body missing or conflicting card marker: expected=${taskCardId}` };
|
|
382
656
|
const cwd = input.worktreePath;
|
|
383
657
|
const opts = { cwd };
|
|
384
658
|
const runGitWrite = (args: string[]): CmdResult => {
|
|
659
|
+
let lastRc: number | undefined;
|
|
385
660
|
const result = runGitWithRetry(
|
|
386
661
|
args,
|
|
387
662
|
(gitArgs) => {
|
|
388
663
|
const command = run('git', gitArgs, opts);
|
|
389
|
-
|
|
664
|
+
lastRc = command.rc;
|
|
665
|
+
return { status: command.ok ? 0 : (command.rc && command.rc !== 0 ? command.rc : 1), stdout: command.out, stderr: command.err ?? '' };
|
|
390
666
|
},
|
|
391
667
|
(attempt) => debug.log('autopilot.pr-manager', 'git-write.retry-succeeded', { attempt, args }),
|
|
392
668
|
);
|
|
393
|
-
return { ok: result.status === 0, out: result.stdout, err: result.stderr };
|
|
669
|
+
return { ok: result.status === 0, out: result.stdout, err: result.stderr, rc: lastRc ?? (typeof result.status === 'number' ? result.status : undefined) };
|
|
394
670
|
};
|
|
395
|
-
const detailOf = (r: CmdResult) => (r.err || r.out || '').slice(0, 300);
|
|
671
|
+
const detailOf = (r: CmdResult) => sanitizeCredentialText(r.err || r.out || '').slice(0, 300);
|
|
396
672
|
// ★ gitignored 경로는 exclude pathspec 에서 뺀다(대표 2026-07-21·705308 근본). git add -A 는 gitignored
|
|
397
673
|
// (node_modules·apps/pwa/out 심링크)를 이미 자동 skip 하는데, `:(exclude)<ignored>` 로 명시 지목하면
|
|
398
674
|
// git 이 "paths ignored by .gitignore … use -f" 로 exit 1 을 뱉는다(staging 은 성공하지만 exit≠0).
|
|
@@ -496,11 +772,71 @@ export function makePrManager(
|
|
|
496
772
|
}
|
|
497
773
|
// ahead > 0 + 내용차 존재 → 이미 커밋된 산출. commit 스킵하고 아래 push + PR 로 fall-through.
|
|
498
774
|
}
|
|
775
|
+
// 카드 계보를 아는 재작업은 새 run 가지를 발사하기 전에 같은 칸 PR 을 찾는다.
|
|
776
|
+
// 같은 카드로 증명된 단일 PR 만 기존 가지를 빠른 전진시킨다. 다른 계보·모호한 목록은 종전 가드다.
|
|
777
|
+
const candidateCardId = cardIdFromBody(input.body);
|
|
778
|
+
if (hasCardMarker(input.body) && !candidateCardId)
|
|
779
|
+
return { ok: false, reason: 'guard', detail: 'candidate card lineage is ambiguous' };
|
|
780
|
+
const earlyGuard = candidateCardId && checkCreate
|
|
781
|
+
? checkCreate({ cwd, base: comparisonBase, seat: input.seat ?? seatFromEnvironment(), body: input.body }, run)
|
|
782
|
+
: undefined;
|
|
783
|
+
// ★ sibling-slice 허용 분기 — 같은 칸의 «다른 조각» OPEN PR 은 충돌로 보지 않는다.
|
|
784
|
+
// 다른 조각 번호(같은 total) → same-cell 사유만 빼고 새 draft 허용 · 같은 조각 번호 → 기존
|
|
785
|
+
// 재사용/거부 그대로 · 후보에 표지 없음 → 기존 가드 그대로(siblingSliceAllowed 는 그대로 반환).
|
|
786
|
+
const siblingSliceAllowed = (verdict: GuardVerdict): GuardVerdict => {
|
|
787
|
+
// Injected guards may still use the old card-only reuse predicate. Never force-push
|
|
788
|
+
// one slice over another, even when the card lineage matches.
|
|
789
|
+
const reused = verdict.sameCellReuse;
|
|
790
|
+
const reusedConflict = reused && verdict.sameCellConflicts?.find(conflict => conflict.pr === reused.number);
|
|
791
|
+
const safeReuse = !reused || ((candidateSlice?.slice ?? null) === (reusedConflict?.slice?.slice ?? null)
|
|
792
|
+
&& (candidateSlice?.total ?? null) === (reusedConflict?.slice?.total ?? null));
|
|
793
|
+
const checkedVerdict = safeReuse ? verdict : { ...verdict, sameCellReuse: undefined };
|
|
794
|
+
if (!candidateSlice || checkedVerdict.status !== 'refuse' || checkedVerdict.sameCellReuse || !checkedVerdict.sameCellConflicts?.length)
|
|
795
|
+
return checkedVerdict;
|
|
796
|
+
const conflicts = checkedVerdict.sameCellConflicts;
|
|
797
|
+
if (conflicts.some(conflict => !conflict.slice || conflict.slice.slice === candidateSlice.slice)) return checkedVerdict;
|
|
798
|
+
if (!conflicts.every(conflict => conflict.slice!.total === candidateSlice.total)) return checkedVerdict;
|
|
799
|
+
debug.log('autopilot.pr-manager', 'same-cell-sibling-slice', {
|
|
800
|
+
cell: cellIdFromBody(input.body), slice: candidateSlice.slice, total: candidateSlice.total,
|
|
801
|
+
existingSlice: conflicts[0]!.slice!.slice, outcome: 'allowed' });
|
|
802
|
+
const reasons = checkedVerdict.reasons.filter(reason => reason.code !== 'same-cell');
|
|
803
|
+
return reasons.length ? { ...checkedVerdict, reasons } : { ...checkedVerdict, status: 'allow', reasons: [] };
|
|
804
|
+
};
|
|
805
|
+
const earlyVerdict = earlyGuard ? siblingSliceAllowed(earlyGuard) : undefined;
|
|
806
|
+
const freshGuard = () => checkCreate!({ cwd, base: comparisonBase, seat: input.seat ?? seatFromEnvironment(), body: input.body }, run);
|
|
807
|
+
if (earlyVerdict?.sameCellReuse) return reuseSameCellPr(run, input, earlyVerdict.sameCellReuse, freshGuard);
|
|
808
|
+
if (earlyVerdict?.status === 'refuse') return { ok: false, reason: 'guard', detail: sameCellGuardDetail(earlyVerdict, candidateCardId) };
|
|
809
|
+
const earlyInventoryUnknown = !!candidateCardId && (!checkCreate || (earlyVerdict?.status === 'unknown'
|
|
810
|
+
&& earlyVerdict.reasons.length === 1 && earlyVerdict.reasons[0]?.code === 'inventory-unknown'));
|
|
811
|
+
if (candidateCardId && earlyVerdict?.status !== 'allow' && !earlyInventoryUnknown)
|
|
812
|
+
return { ok: false, reason: 'guard', detail: 'candidate card inventory unmeasured before push' };
|
|
813
|
+
if (earlyInventoryUnknown) debug.log('pr-tool.open-guard', 'candidate-inventory-unmeasured', {
|
|
814
|
+
branch: input.branch, cardId: candidateCardId, stage: 'before-push',
|
|
815
|
+
reason: earlyVerdict?.reasons[0]?.detail ?? 'create guard unavailable',
|
|
816
|
+
});
|
|
817
|
+
if (candidateCardId) {
|
|
818
|
+
const branchPr = findPrForBranchOutcome(input.branch, cwd);
|
|
819
|
+
if (branchPr.status === 'FAILED' || branchPr.url)
|
|
820
|
+
return { ok: false, reason: 'guard', detail: 'candidate run branch PR already exists or is unmeasured before push' };
|
|
821
|
+
}
|
|
499
822
|
// force-push — 재구현이 이전 구현을 교체(기존 브랜치 갱신 or 신규). 안정 브랜치명이라 기존 PR 이
|
|
500
823
|
// 있으면 GitHub 이 그 PR 을 자동 업데이트(닫고 새로 안 만듦). elanous 자체 SE 브랜치라 force 안전.
|
|
501
824
|
// 일시 원격 실패(5xx·연결 끊김 등)만 최대 3회. 영구 거부는 한 번에 끝낸다.
|
|
502
825
|
const waitForPushRetry = input.waitForPushRetry ?? defaultWaitForPushRetry;
|
|
503
|
-
|
|
826
|
+
// ★ 칸 PR-CREATE-FAIL-OBSERVE-FU — push/gh 단계 관측을 쌓아 실패 시 한 incident 로.
|
|
827
|
+
const pushStage: PrCreateStageObservation = { stage: 'push', ran: false };
|
|
828
|
+
const ghStage: PrCreateStageObservation = { stage: 'gh', ran: false };
|
|
829
|
+
const markGhRan = (r: CmdResult): CmdResult => {
|
|
830
|
+
ghStage.ran = true;
|
|
831
|
+
ghStage.rc = r.rc;
|
|
832
|
+
ghStage.stderrTail = stderrTailOf(r.err);
|
|
833
|
+
return r;
|
|
834
|
+
};
|
|
835
|
+
const failedCreate = (reason: 'push' | 'gh', detail: string): UpsertPrOutcome =>
|
|
836
|
+
prCreateFailureOutcome(input, reason, detail, pushStage, ghStage);
|
|
837
|
+
const pushArgs = candidateCardId
|
|
838
|
+
? ['-C', cwd, 'push', '-u', 'origin', input.branch]
|
|
839
|
+
: ['-C', cwd, 'push', '--force', '-u', 'origin', input.branch];
|
|
504
840
|
let pushR = runGitWrite(pushArgs);
|
|
505
841
|
let pushAttempts = 1;
|
|
506
842
|
while (!pushR.ok && pushAttempts < MAX_PUSH_ATTEMPTS && isTransientPushFailure(detailOf(pushR))) {
|
|
@@ -508,80 +844,68 @@ export function makePrManager(
|
|
|
508
844
|
pushR = runGitWrite(pushArgs);
|
|
509
845
|
pushAttempts += 1;
|
|
510
846
|
}
|
|
847
|
+
pushStage.ran = true;
|
|
848
|
+
pushStage.ok = pushR.ok;
|
|
849
|
+
pushStage.rc = pushR.rc;
|
|
850
|
+
pushStage.stderrTail = stderrTailOf(pushR.err);
|
|
511
851
|
if (!pushR.ok) {
|
|
512
852
|
const detail = pushAttempts > 1
|
|
513
853
|
? `push ${pushAttempts}/${MAX_PUSH_ATTEMPTS} failed: ${detailOf(pushR)}`
|
|
514
854
|
: detailOf(pushR);
|
|
515
|
-
return
|
|
855
|
+
return failedCreate('push', detail);
|
|
516
856
|
}
|
|
517
857
|
const existing = findPrForBranchOutcome(input.branch, cwd);
|
|
518
|
-
if (existing.
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
// draft=false && 현재 draft → gh pr ready · draft=true && 현재 ready → gh pr ready --undo.
|
|
524
|
-
const editArgs = ['pr', 'edit', existing.url, '--title', input.title, '--body', input.body];
|
|
525
|
-
// ⚠️ 재사용 경로는 **명시 base 만** 넘긴다(리뷰 must-fix 2026-07-26). 추론한 base 를 넘기면
|
|
526
|
-
// `release/*` 등 비기본 브랜치를 대상으로 열려 있던 기존 PR 을 **main 으로 재타기팅**하는
|
|
527
|
-
// 회귀가 된다(요청자는 base 를 지정하지도 않았는데). 미지정 = "base 는 건드리지 마라".
|
|
528
|
-
// 신규 생성은 base 가 반드시 필요하므로 그쪽만 추론값을 쓴다.
|
|
529
|
-
// 트림은 신규 경로(resolveDeliverableBase)와 동일하게 — 공백 전용 base 는 미지정으로 본다(리뷰 should-fix).
|
|
530
|
-
const explicitBase = input.base?.trim();
|
|
531
|
-
if (explicitBase && !isBranchSelfRef(explicitBase, input.branch)) editArgs.push('--base', prBaseFromComparison(explicitBase));
|
|
532
|
-
for (const label of new Set((input.labels ?? []).map(label => label.trim()).filter(Boolean))) editArgs.push('--add-label', label);
|
|
533
|
-
let edited = run('gh', editArgs, opts);
|
|
534
|
-
if (!edited.ok) return { ok: false, reason: 'gh', detail: detailOf(edited) || 'gh pr edit 실패' };
|
|
535
|
-
if (input.draft !== undefined) {
|
|
536
|
-
// 현재 draft 상태 조회 — 조회 실패/비정상 출력은 fail-closed(요청 draft 를 적용 못했는데
|
|
537
|
-
// 성공 반환하면 openPr 계약 위반). 정상 조회 시에만 실제 전이가 필요할 때 수행(멱등).
|
|
538
|
-
const stateR = run('gh', ['pr', 'view', existing.url, '--json', 'isDraft', '-q', '.isDraft'], opts);
|
|
539
|
-
const raw = stateR.out.trim();
|
|
540
|
-
if (!stateR.ok || (raw !== 'true' && raw !== 'false')) {
|
|
541
|
-
return { ok: false, reason: 'gh', detail: detailOf(stateR) || `draft 상태 조회 실패(isDraft=${raw || 'empty'})` };
|
|
542
|
-
}
|
|
543
|
-
const isDraft = raw === 'true';
|
|
544
|
-
if (input.draft === false && isDraft) {
|
|
545
|
-
const ready = run('gh', ['pr', 'ready', existing.url], opts);
|
|
546
|
-
if (!ready.ok) return { ok: false, reason: 'gh', detail: detailOf(ready) || 'gh pr ready 실패' };
|
|
547
|
-
} else if (input.draft === true && !isDraft) {
|
|
548
|
-
const undo = run('gh', ['pr', 'ready', existing.url, '--undo'], opts);
|
|
549
|
-
if (!undo.ok) return { ok: false, reason: 'gh', detail: detailOf(undo) || 'gh pr ready --undo 실패' };
|
|
550
|
-
}
|
|
858
|
+
if (existing.status !== 'SKIPPED') {
|
|
859
|
+
ghStage.ran = true;
|
|
860
|
+
if (existing.status === 'FAILED') {
|
|
861
|
+
ghStage.rc = existing.rc;
|
|
862
|
+
ghStage.stderrTail = existing.stderrTail;
|
|
551
863
|
}
|
|
552
|
-
if (input.reuseComment) run('gh', ['pr', 'comment', existing.url, '--body', input.reuseComment], opts);
|
|
553
|
-
return { ok: true, url: existing.url, reused: true };
|
|
554
864
|
}
|
|
555
|
-
|
|
865
|
+
if (existing.url) {
|
|
866
|
+
if (candidateCardId)
|
|
867
|
+
return { ok: false, reason: 'guard', detail: 'candidate run branch PR appeared after push; refuse edit' };
|
|
868
|
+
return editExistingPr(run, input, existing.url);
|
|
869
|
+
}
|
|
870
|
+
if (existing.status === 'FAILED') {
|
|
871
|
+
return failedCreate('gh', 'existing PR branch lookup failed');
|
|
872
|
+
}
|
|
873
|
+
let guardUnmeasured = earlyInventoryUnknown;
|
|
556
874
|
let hunkOverlapWarning: { prs: readonly number[]; files: readonly string[] } | null = null;
|
|
557
875
|
if (checkCreate) {
|
|
558
876
|
const seat = input.seat ?? seatFromEnvironment();
|
|
877
|
+
// Another run may open a PR after the early inventory and before this create.
|
|
878
|
+
// Read the complete OPEN inventory again after push, immediately before create.
|
|
559
879
|
const verdict = checkCreate({ cwd, base: comparisonBase, seat, body: input.body }, run);
|
|
560
|
-
|
|
880
|
+
// sibling-slice: 같은 칸의 다른 조각이 inventories 사이 열려도 생성은 허용한다(위 분기와 동일 규칙).
|
|
881
|
+
const siblingVerdict = siblingSliceAllowed(verdict);
|
|
882
|
+
if (siblingVerdict.sameCellReuse)
|
|
883
|
+
return { ok: false, reason: 'guard', detail: 'same-cell PR appeared after run branch push; retry from fresh inventory' };
|
|
884
|
+
const hunkWarn = siblingVerdict.status === 'allow' ? siblingVerdict.warnings.find(warning => warning.code === 'hunk-overlap') : undefined;
|
|
561
885
|
if (hunkWarn) hunkOverlapWarning = { prs: hunkWarn.prs ?? [], files: hunkWarn.files ?? [] };
|
|
562
|
-
if (
|
|
886
|
+
if (siblingVerdict.status === 'unknown' && siblingVerdict.reasons.length === 1 && siblingVerdict.reasons[0]?.code === 'inventory-unknown') {
|
|
563
887
|
const inPod = process.env.ELANOUS_SUBSTRATE === 'pod'
|
|
564
888
|
|| Object.keys(process.env).some(key => key.startsWith('ELANOUS_POD_'));
|
|
565
889
|
if (inPod) {
|
|
566
890
|
// Pod state and mailbox are local to this Job. Count and alert only
|
|
567
891
|
// in the host parent, where the shared instance root is authoritative.
|
|
568
|
-
debug.log('pr-tool.open-guard', 'pod-unmeasured', { seat, reason:
|
|
892
|
+
debug.log('pr-tool.open-guard', 'pod-unmeasured', { seat, reason: siblingVerdict.reasons[0].detail });
|
|
569
893
|
} else {
|
|
570
|
-
const count = recordUnmeasured({ seat, reason:
|
|
894
|
+
const count = recordUnmeasured({ seat, reason: siblingVerdict.reasons[0].detail });
|
|
571
895
|
if (count.blocked) {
|
|
572
|
-
const alert = run('eln', ['msg', 'post', '--from', seat ?? 'HARNESS', '--to', 'OP', '--kind', 'alert', '--body', `PR open-guard 판정 불가 1시간 ${count.count}회 · 새 PR 차단 · ${count.reason ??
|
|
896
|
+
const alert = run('eln', ['msg', 'post', '--from', seat ?? 'HARNESS', '--to', 'OP', '--kind', 'alert', '--body', `PR open-guard 판정 불가 1시간 ${count.count}회 · ${candidateCardId ? '카드 후보는 draft 관측' : '새 PR 차단'} · ${count.reason ?? siblingVerdict.reasons[0].detail}`]);
|
|
573
897
|
if (!alert.ok) debug.log('pr-tool.open-guard', 'op-alert-failed', { seat, reason: alert.err || alert.out || 'eln msg post 실패' });
|
|
574
|
-
return { ok: false, reason: 'guard', detail: `inventory-unknown: 1시간 ${count.count}회 · 새 PR 차단${count.reason ? ` (${count.reason})` : ''}` };
|
|
898
|
+
if (!candidateCardId) return { ok: false, reason: 'guard', detail: `inventory-unknown: 1시간 ${count.count}회 · 새 PR 차단${count.reason ? ` (${count.reason})` : ''}` };
|
|
575
899
|
}
|
|
576
900
|
}
|
|
577
901
|
guardUnmeasured = true;
|
|
578
|
-
} else if (
|
|
579
|
-
return { ok: false, reason: 'guard', detail:
|
|
902
|
+
} else if (siblingVerdict.status !== 'allow') {
|
|
903
|
+
return { ok: false, reason: 'guard', detail: sameCellGuardDetail(siblingVerdict, candidateCardId) };
|
|
580
904
|
}
|
|
581
905
|
}
|
|
582
906
|
const createArgs = ['pr', 'create', '--head', input.branch, '--title', input.title, '--body', input.body];
|
|
583
907
|
if (prBase) createArgs.push('--base', prBase);
|
|
584
|
-
if (input.draft) createArgs.push('--draft');
|
|
908
|
+
if (input.draft || guardUnmeasured) createArgs.push('--draft');
|
|
585
909
|
const seat = input.seat ?? seatFromEnvironment();
|
|
586
910
|
const requiredLabels = [...(seat ? [`seat:${seat}`] : []), ...(guardUnmeasured ? ['pr-guard:unmeasured'] : [])];
|
|
587
911
|
// PR-GUARD-HUNK-WARN: 줄 겹침 경고 라벨은 «최선» — 만들기 실패해도 아래 재시도가 빼고 PR 을 연다.
|
|
@@ -590,15 +914,18 @@ export function makePrManager(
|
|
|
590
914
|
const requestedLabels = [...new Set([...(input.labels ?? []), ...creatableLabels].map((label) => label.trim()).filter(Boolean))];
|
|
591
915
|
const labeledArgs = [...createArgs];
|
|
592
916
|
for (const label of requestedLabels) labeledArgs.push('--label', label);
|
|
593
|
-
let created = run('gh', labeledArgs, opts);
|
|
917
|
+
let created = markGhRan(run('gh', labeledArgs, opts));
|
|
594
918
|
if (!created.ok && creatableLabels.length && isLabelNotFoundFailure(created, creatableLabels)) {
|
|
595
919
|
for (const label of creatableLabels) run('gh', ['label', 'create', label, '--color', 'BFDADC'], opts);
|
|
596
|
-
created = run('gh', labeledArgs, opts);
|
|
920
|
+
created = markGhRan(run('gh', labeledArgs, opts));
|
|
597
921
|
}
|
|
598
922
|
const logHunkOverlapWarn = (url: string): void => {
|
|
599
923
|
if (hunkOverlapWarning) debug.log('pr-tool.guard', 'hunk-overlap-warn', { pr: extractPrNumber(url), files: hunkOverlapWarning.files, against: hunkOverlapWarning.prs });
|
|
600
924
|
};
|
|
601
925
|
if (created.ok && created.out) {
|
|
926
|
+
if (guardUnmeasured) debug.log('pr-tool.open-guard', 'candidate-draft-unmeasured', {
|
|
927
|
+
branch: input.branch, cardId: candidateCardId ?? null, url: created.out,
|
|
928
|
+
});
|
|
602
929
|
logHunkOverlapWarn(created.out);
|
|
603
930
|
return {
|
|
604
931
|
ok: true,
|
|
@@ -610,7 +937,7 @@ export function makePrManager(
|
|
|
610
937
|
if (requestedLabels.length > 0 && isLabelNotFoundFailure(created, requestedLabels)) {
|
|
611
938
|
const retryArgs = [...createArgs];
|
|
612
939
|
for (const label of requiredLabels) retryArgs.push('--label', label);
|
|
613
|
-
const retry = run('gh', retryArgs, opts);
|
|
940
|
+
const retry = markGhRan(run('gh', retryArgs, opts));
|
|
614
941
|
if (retry.ok && retry.out) {
|
|
615
942
|
logHunkOverlapWarn(retry.out);
|
|
616
943
|
debug.log('autopilot.pr-manager', 'create.labels-omitted', {
|
|
@@ -621,9 +948,10 @@ export function makePrManager(
|
|
|
621
948
|
});
|
|
622
949
|
return { ok: true, url: retry.out, reused: false, labelsOmitted: true };
|
|
623
950
|
}
|
|
624
|
-
return
|
|
951
|
+
return failedCreate('gh', detailOf(retry) || 'gh pr create 실패');
|
|
625
952
|
}
|
|
626
|
-
|
|
953
|
+
// 여기까지 흘러내려왔으면 성공 return 을 못 만났다 — 실패 incident 로 마무리.
|
|
954
|
+
return failedCreate('gh', detailOf(created) || 'gh pr create 실패');
|
|
627
955
|
},
|
|
628
956
|
closePr(prUrl, comment) {
|
|
629
957
|
const n = extractPrNumber(prUrl);
|