elanous 0.2.36 → 0.2.38
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/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 1026-44010f405704050c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 1632.7d87f998e714bede.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
- package/apps/pwa/out/_next/static/chunks/{7784.1f0ac4a16d190cf4.js → 2104.70e086d5174a4736.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6566.926a1d1b7c911442.js → 214.186a430da28338f1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
- package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 2415.738b777642a02233.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 3086.fb14b60ce98b53d3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3148-98efd4869d660a87.js → 3124-561f7f037943cde2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
- package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 3291.f6c1005387d514bd.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
- package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
- package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 3528.e4b8ab70d339f965.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
- package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3031-85328a92fcce4da6.js → 4199-f7c6eb40cd0322f8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
- package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +90 -0
- package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
- package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
- package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
- package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 5307.d7328020227880c2.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
- package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
- package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5638.107314dc479e2f37.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
- package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6925.562d532110879886.js → 6493.27ad77de7aac7966.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 7161-8f22db3ec5ed005e.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 7488.966b116789f3d41a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4116.a84a92a2492c080e.js → 7524.ce973525d30b3d52.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 7628.6b16863ac3972333.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 7954.4f7a8832663ee979.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 8019.21ca554a821dad01.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 8487.291666583bebe640.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 8879.ac06755bcf3e44a1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 8911.bf5e712acb25fb6c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 8994d93e.33ba491f95345fc2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{599.c39c571b6733f2a2.js → 9223.cbcc88e0e9950426.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
- package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
- package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8037.e254fd797aa224d1.js → 9581.da63ddf41acfad46.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
- package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-e7abc34a48a6f71e.js → page-291ab19fe2acb173.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-c15958835534404b.js → page-6b140f77593576eb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → b7459770.6539b11860eb8a9c.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → b7478fef.5917716286213fcc.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{2812ca6a.3b9f4a7a08885744.js → de8b930d.d94c0f42acf807fc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → eaad0cba.771200940c529df7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +1 -0
- package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/drafts/recipes.yaml +27 -7
- package/graphs/release/recipes.yaml +9 -0
- package/graphs/release/release-loop.yaml +26 -18
- package/graphs/work/draft-close.yaml +54 -0
- package/graphs/work/green-close.yaml +37 -0
- package/graphs/work/recipes.yaml +46 -1
- package/graphs/work/run-research.yaml +35 -0
- package/package.json +1 -1
- package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
- package/scripts/ask-op-inbox-once.ts +17 -0
- package/scripts/boundary-proof-mapping-audit.ts +88 -0
- package/scripts/brand/check.ts +13 -4
- package/scripts/codex-fallback-live-probe.ts +17 -15
- package/scripts/fleet/node-setup.sh +32 -2
- package/scripts/fleet/run-light-worker.sh +9 -0
- package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
- package/scripts/gate-0226-failure-census.ts +546 -0
- package/scripts/goals/authoring-metrics.ts +258 -0
- package/scripts/graph-units/draft-close-node.ts +222 -0
- package/scripts/hook-order-sweep.ts +7 -4
- package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
- package/scripts/land-global-checks.ts +69 -1
- package/scripts/measure-nl-routing-corpus.ts +207 -2
- package/scripts/provision-export-redactions.ts +15 -0
- package/scripts/public-copy-lint.ts +122 -0
- package/scripts/public-export.ts +69 -2
- package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
- package/scripts/ratchets/train-side-invariants.sh +7 -1
- package/scripts/release-loop/cut-branch.ts +61 -12
- package/scripts/release-loop/docs-node.ts +140 -0
- package/scripts/release-loop/gate-closure.ts +48 -0
- package/scripts/release-loop/gate-diff.ts +2 -1
- package/scripts/release-loop/gate-node.ts +161 -25
- package/scripts/release-loop/gate-partial.ts +82 -3
- package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
- package/scripts/release-loop/gate-radius-live.ts +4 -2
- package/scripts/release-loop/known-issues-node.ts +6 -4
- package/scripts/release-loop/notes-repair.ts +216 -0
- package/scripts/release-loop/prepare-node.ts +61 -5
- package/scripts/release-loop/resume-cap.ts +2 -1
- package/scripts/release-loop/resume-release.ts +406 -7
- package/scripts/release-loop/resume-test-traffic.ts +10 -0
- package/scripts/release-loop/resume.ts +13 -5
- package/scripts/release-loop/traffic-node.ts +12 -4
- package/scripts/release-loop/traffic-transition.ts +53 -13
- package/scripts/release-loop/version-node.ts +109 -15
- package/scripts/train/green-leg.ts +176 -0
- package/scripts/tui-continue-real-evidence.ts +47 -0
- package/scripts/ux-sim.ts +1 -1
- package/scripts/video-pipeline.ts +2 -2
- package/src/acp/client.ts +31 -5
- package/src/acp/core-turn-bridge.ts +12 -1
- package/src/acp/stderr-summary.ts +49 -0
- package/src/agent/monad-agent-turn.ts +1 -0
- package/src/agent/run-context.ts +1 -1
- package/src/agent/task-notification.ts +3 -1
- package/src/agent/terminal-surface.ts +217 -0
- package/src/agent-substrate/pr-reviewer.ts +11 -3
- package/src/agent-substrate/review-observation.ts +10 -0
- package/src/agent-substrate/self-review-cli.ts +537 -57
- package/src/auto-research/question-ladder-contract.ts +137 -0
- package/src/auto-research/research-turn.ts +134 -0
- package/src/autopilot/discovery/doc-lint.ts +1 -1
- package/src/autopilot/lineage/sources.ts +1 -1
- package/src/autopilot/pr-manager.ts +64 -13
- package/src/boot/daemon-runtime.ts +35 -3
- package/src/boot/daemon-tools/pty-shell.ts +2 -1
- package/src/bots/screen-probe.ts +1 -1
- package/src/budget/run-usage-rollup.ts +12 -7
- package/src/budget/unified-usage.ts +20 -0
- package/src/capture/tui-self-report.ts +42 -5
- package/src/chat/index.ts +1 -0
- package/src/chat/tool-render/dispatch.ts +8 -1
- package/src/cli/autopilot-cli.ts +24 -9
- package/src/cli/decisions-cli.ts +7 -4
- package/src/cli/doctor-cli.ts +116 -7
- package/src/cli/guardian-cli.ts +3 -1
- package/src/cli/intake-cli.ts +48 -12
- package/src/cli/lesson-cli.ts +69 -9
- package/src/cli/logs-cli.ts +357 -2
- package/src/cli/memory-cli.ts +30 -1
- package/src/cli/msg-cli.ts +15 -11
- package/src/cli/pr-granularity.ts +5 -3
- package/src/cli/pr-land-overlap-evidence.ts +38 -5
- package/src/cli/pr-land-refusal.ts +1 -1
- package/src/cli/pty-takeover-cli.ts +58 -5
- package/src/cli/release-checklist-read-cli.ts +112 -4
- package/src/cli/release-cli.ts +89 -18
- package/src/cli/review-carry.ts +77 -0
- package/src/cli/self-update.ts +24 -6
- package/src/cli/self-utterances-cli.ts +13 -16
- package/src/cli/tasks-card-show.ts +31 -1
- package/src/cli/tasks-cli.ts +370 -33
- package/src/cli/tasks-read-cli.ts +13 -5
- package/src/cli/usage-cli.ts +12 -10
- package/src/context-bus/claude-memory-import.ts +99 -0
- package/src/context-bus/context-now.ts +86 -2
- package/src/context-bus/long-term-memory.ts +125 -0
- package/src/core-turn/run-core-turn.ts +9 -2
- package/src/core-turn/run-goal-loop.ts +5 -2
- package/src/core-turn/types.ts +5 -0
- package/src/dashboard/chat/acp-chat.ts +9 -0
- package/src/dashboard/index.ts +115 -30
- package/src/dashboard/input/agent-wake.ts +43 -0
- package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
- package/src/dashboard/input/terminal-modal-router.ts +8 -159
- package/src/dashboard/replay-preview.ts +25 -0
- package/src/dashboard/side-basic-runtime.ts +61 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +19 -8
- package/src/dashboard/synchronized-frame-output.ts +74 -0
- package/src/dashboard/term-slash-runtime.ts +2 -0
- package/src/dashboard/turn-preamble.ts +28 -4
- package/src/display/coordinator.ts +45 -12
- package/src/display/resize-listener.ts +41 -20
- package/src/display/synchronized-output-region.ts +60 -0
- package/src/domains/guardian-tick.ts +9 -0
- package/src/domains/surface-events.ts +80 -1
- package/src/exec-requests/planner.ts +37 -2
- package/src/execution-loop/launch-gate.ts +4 -3
- package/src/git-fs/cli-stderr.ts +45 -0
- package/src/git-fs/gh-cli.ts +6 -3
- package/src/git-fs/git-cli.ts +11 -5
- package/src/git-fs/watcher.ts +27 -22
- package/src/git-fs/worktree.ts +19 -3
- package/src/graph-runner/graph-cli.ts +26 -2
- package/src/graph-runner/graph-grow.ts +37 -9
- package/src/graph-runner/graph-run-api.ts +3 -2
- package/src/graph-runner/runner.ts +34 -7
- package/src/graph-wizard/generate.ts +29 -6
- package/src/grok/credential.ts +107 -36
- package/src/harness/harness-cli-command.ts +179 -33
- package/src/harness/review-adapter.ts +26 -6
- package/src/hq/fence-wrapper.ts +1 -1
- package/src/hq/transfer.ts +1 -1
- package/src/index.ts +151 -18
- package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
- package/src/intake-plane/collect-telegram-saved.ts +54 -5
- package/src/interactive-terminal-modal.ts +3 -0
- package/src/keybindings.ts +17 -22
- package/src/llm/provider-credentials.ts +1 -1
- package/src/llm/route-decision.ts +13 -0
- package/src/llm-tool-name.ts +37 -0
- package/src/llm-tool-schema.ts +55 -0
- package/src/llm.ts +203 -21
- package/src/loops/checker.ts +100 -0
- package/src/loops/consensus.ts +26 -2
- package/src/loops/loop-cli.ts +9 -4
- package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
- package/src/loops/orchestrator/inbox-once.ts +28 -0
- package/src/loops/orchestrator/inbox.ts +130 -1
- package/src/loops/orchestrator/tick.ts +55 -7
- package/src/maturity/feature-maturity.ts +1 -0
- package/src/model-tier/llm-tier-map.ts +12 -17
- package/src/msg/msg-store.ts +17 -0
- package/src/native-tool-catalog.ts +1 -1
- package/src/nexus/api/channel-ask-op.ts +96 -0
- package/src/nexus/api/discord-trigger-bot.ts +28 -1
- package/src/nexus/api/graph-wizard-api.ts +27 -2
- package/src/nexus/api/grid.ts +24 -4
- package/src/nexus/api/http-server.ts +1 -1
- package/src/nexus/api/ops-api.ts +14 -6
- package/src/nexus/api/telegram-trigger-bot.ts +24 -0
- package/src/nexus/api/terminals.ts +28 -6
- package/src/nexus/state/state.ts +7 -1
- package/src/oauth/codex-account-store.ts +34 -1
- package/src/ops/loops-map.ts +46 -0
- package/src/ops/overview-cache.ts +22 -4
- package/src/ops/overview.ts +41 -5
- package/src/patents/ledger.ts +18 -1
- package/src/policy/llm-policy.ts +3 -1
- package/src/preview/terminal.ts +4 -2
- package/src/prompt-cache/anthropic.ts +2 -0
- package/src/prompt-enhance/enhance.ts +9 -4
- package/src/pty-shell/availability.ts +7 -0
- package/src/pty-shell/herdr-agent-report.ts +40 -31
- package/src/pty-shell/herdr-prune-stale.ts +17 -0
- package/src/pty-shell/herdr-sequence-lease.ts +60 -0
- package/src/pty-shell/pty-control-ipc.ts +187 -18
- package/src/pty-shell/pty-manifest.ts +16 -2
- package/src/pty-shell/registry.ts +25 -15
- package/src/pty-shell/tui-run-state.ts +235 -1
- package/src/release-loop/checklist.ts +50 -5
- package/src/release-loop/feature-store.ts +9 -9
- package/src/release-loop/gate-shards.ts +61 -0
- package/src/release-loop/landed-but-yellow.ts +93 -12
- package/src/release-loop/light-rc.ts +7 -4
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/repl/index.ts +18 -0
- package/src/research/axis-fanout.ts +133 -0
- package/src/research/edge-decision.ts +88 -0
- package/src/research/output-router.ts +127 -0
- package/src/research-bridge/format.ts +16 -1
- package/src/research-bridge/index.ts +1 -0
- package/src/research-bridge/invoke.ts +41 -5
- package/src/seat-loop/seat-report.ts +1 -0
- package/src/self-dev/ask-launch-flow.ts +86 -10
- package/src/self-dev/decompose-proposal.ts +29 -18
- package/src/self-dev/decompose.ts +45 -9
- package/src/self-dev/dev-pipeline.ts +29 -7
- package/src/self-dev/draft-residue.ts +221 -2
- package/src/self-dev/draft-sweep.ts +254 -16
- package/src/self-dev/draft-triage-rules.ts +19 -5
- package/src/self-dev/orchestrate.ts +1 -0
- package/src/self-dev/review-provider-fallback.ts +45 -7
- package/src/self-dev/run-supervisor.ts +22 -7
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-run.ts +310 -6
- package/src/self-implement/comment-only-source.ts +54 -0
- package/src/self-implement/doctor-visit.ts +108 -0
- package/src/self-implement/gate-artifacts.ts +6 -2
- package/src/self-implement/gate-baseline.ts +99 -1
- package/src/self-implement/gate-cli.ts +231 -82
- package/src/self-implement/gate-failure-signature.ts +44 -0
- package/src/self-implement/gate-remote.ts +30 -4
- package/src/self-implement/gate-scope.ts +13 -1
- package/src/self-implement/goal-author.ts +407 -21
- package/src/self-implement/goal-doc/section.ts +22 -0
- package/src/self-implement/goal-supervisor-fill.ts +110 -27
- package/src/self-implement/importer-test-index.ts +215 -2
- package/src/self-implement/knowhow-pack.ts +125 -12
- package/src/self-implement/l8-merge-queue.ts +198 -32
- package/src/self-implement/off-diff-evidence.ts +23 -0
- package/src/self-implement/orchestrator.ts +369 -33
- package/src/self-implement/pod-inplace-worktree.ts +82 -0
- package/src/self-implement/pod-warm-pool-profile.ts +2 -2
- package/src/self-implement/premise-review.ts +7 -5
- package/src/self-implement/review-round-brief.ts +300 -0
- package/src/self-implement/rework-policy.ts +14 -0
- package/src/self-implement/run-ledger.ts +428 -6
- package/src/self-implement/run-stop.ts +1 -1
- package/src/self-implement/running-runs.ts +17 -3
- package/src/self-implement/seams.ts +45 -16
- package/src/self-implement/self-implement-cli.ts +26 -2
- package/src/self-implement/stop-autoheal.ts +1 -0
- package/src/self-implement/test-seams.ts +13 -1
- package/src/self-implement/train-reach-grouping.ts +8 -2
- package/src/session/channel-ask-op-envelope.ts +36 -0
- package/src/session/channel-op-reply-route.ts +200 -0
- package/src/session/chat.ts +10 -1
- package/src/session/id-prefix.ts +60 -0
- package/src/session/index.ts +6 -0
- package/src/session-runtime/index.ts +18 -23
- package/src/skills/runner.ts +7 -3
- package/src/skills/tools/dev-harness.ts +2 -2
- package/src/skills/tools/pty.ts +5 -0
- package/src/skills/tools/schedule-wakeup.ts +1 -6
- package/src/status/bar.ts +3 -3
- package/src/status/metrics.ts +12 -1
- package/src/steward/rejudge-tick.ts +12 -5
- package/src/steward/resync-tick.ts +31 -4
- package/src/storage/file-lock.ts +17 -4
- package/src/task-agent/actions.ts +199 -4
- package/src/task-agent/adopt-pr.ts +63 -2
- package/src/task-agent/boundary-proof-mapping.ts +12 -0
- package/src/task-agent/boundary-proof-producer.ts +147 -0
- package/src/task-agent/completion-evidence.ts +2 -1
- package/src/task-agent/evidence-command-normalize.ts +42 -0
- package/src/task-agent/export-redactions-provision.ts +43 -0
- package/src/task-agent/green-close-recipe.ts +239 -0
- package/src/task-agent/green-sweep.ts +64 -10
- package/src/task-agent/live-moves.ts +48 -3
- package/src/task-agent/map-host-adapter.ts +134 -0
- package/src/task-agent/map-reduce.ts +158 -0
- package/src/task-agent/map-run-ledger.ts +226 -0
- package/src/task-agent/parent-host.ts +74 -17
- package/src/task-agent/rejudge-on-head.ts +72 -5
- package/src/task-agent/repair-cycle.ts +108 -8
- package/src/task-agent/repair-next-move.ts +12 -2
- package/src/task-agent/repair-worker.ts +37 -1
- package/src/task-agent/review-prior-fix.ts +12 -2
- package/src/task-agent/shadow.ts +188 -5
- package/src/task-agent/task-hand.ts +253 -20
- package/src/task-agent/task-parent-role-llm.ts +9 -0
- package/src/task-agent/tier-split.ts +40 -5
- package/src/task-agent/work-order.ts +53 -2
- package/src/task-orchestrator/dispatcher.ts +46 -1
- package/src/task-orchestrator/generator-prompt.ts +6 -0
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +31 -4
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +77 -8
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +338 -79
- package/src/task-orchestrator/surfaces/self-implement.ts +37 -2
- package/src/terminal/session-registry.ts +1 -0
- package/src/terminal/terminal-modal-router.ts +156 -0
- package/src/testing/linux-env.ts +177 -0
- package/src/tool-hints/gate.ts +6 -4
- package/src/tool-hints/signals.ts +33 -1
- package/src/tui/chat/background-job-status.ts +8 -2
- package/src/tui/chat/goal-interim.ts +5 -1
- package/src/tui/entry.ts +722 -30
- package/src/tui/input/at-picker.ts +55 -0
- package/src/tui/sidetab/attach.ts +304 -0
- package/src/tui/sidetab/list.ts +176 -0
- package/src/tui/sidetab/nl-tool.ts +136 -0
- package/src/tui/slash/resume-command.ts +23 -0
- package/src/tui/slash/resume.ts +38 -35
- package/src/tui/slash/signals.ts +114 -0
- package/src/tui/slash/term-next.ts +72 -0
- package/src/tui-client/local-chat-turn.ts +31 -9
- package/src/user-config.ts +30 -3
- package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
- package/src/ux-sim/classic-tui-seat-scenarios.ts +158 -4
- package/src/ux-sim/fake-gh.ts +174 -0
- package/src/ux-sim/fake-kubectl.ts +142 -0
- package/src/ux-sim/fake-llm.ts +17 -6
- package/src/ux-sim/next-tui-seat-scenarios.ts +176 -6
- package/src/ux-sim/resume-picker-device.ts +173 -0
- package/src/ux-sim/session-id-seed.ts +60 -0
- package/src/ux-sim/skills-tools-shell-device.ts +156 -0
- package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
- package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/190.285c832bd9626f8c.js +0 -64
- package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +0 -36
- package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +0 -149
- package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +0 -24
- package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +0 -24
- package/apps/pwa/out/_next/static/chunks/2986.45d7652e4f13557e.js +0 -2
- package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +0 -226
- package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +0 -8
- package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +0 -32
- package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +0 -286
- package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +0 -1
- package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3757-180308bc61021b05.js +0 -1
- package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
- package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +0 -104
- package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +0 -148
- package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +0 -93
- package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +0 -122
- package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +0 -79
- package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6466-92e65a48490b68a9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +0 -1
- package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +0 -27
- package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +0 -1
- package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7481.39f7a4654907bf6e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7891.03f910124a737985.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +0 -1
- package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +0 -62
- package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +0 -90
- package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +0 -94
- package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +0 -77
- package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9514.131c52cc75fe6439.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-e2de2e59111c9aad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2af16e62c12f22df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ccae1c4b-0cf414f5eff1b10d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +0 -1
- package/scripts/migrate-monad-to-elanous.ts +0 -195
- package/scripts/rebrand-elanous.ts +0 -242
- /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
|
@@ -21,7 +21,8 @@ import { POD_CREDENTIAL_TOKEN_ENV, POD_CREDENTIAL_URL_ENV } from '../../grok/cre
|
|
|
21
21
|
import { isVerifiedOpenGatewayModel } from '../../llm/opengateway-models.js';
|
|
22
22
|
import { configuredOpenGatewayKeys } from '../../llm/provider-credentials.js';
|
|
23
23
|
import { collectPodLedgers, createPodLedgerFollower } from './pod-ledger-collect.js';
|
|
24
|
-
import {
|
|
24
|
+
import { captureFailedPodJobs } from './pod-ledger-events.js';
|
|
25
|
+
import { collectPodArtifacts, podNoResultDiagnostic, POD_SALVAGE_BUNDLE_FILE_LIMIT, POD_SALVAGE_BUNDLE_TOTAL_LIMIT } from './pod-artifact-return.js';
|
|
25
26
|
import { readPodRepairArtifact } from './pod-repair-commit.js';
|
|
26
27
|
import { isValidAccountName, resolveCodexAccount } from '../../oauth/codex-account.js';
|
|
27
28
|
import { createCodexAccessMirror } from '../../oauth/codex-access-mirror.js';
|
|
@@ -31,6 +32,8 @@ import { finishPodFragment, writePodFragment } from '../../harness/self-send-tar
|
|
|
31
32
|
import { mintRunId, normalizeRunId } from '../../harness/harness-space.js';
|
|
32
33
|
import { TA_LAND_ENV } from '../../task-agent/task-hand.js';
|
|
33
34
|
import { appendRunLedgerEntry, loadRunLedger, runLedgerDir, runLedgerPath, type RunLedgerEntry } from '../../self-implement/run-ledger.js';
|
|
35
|
+
import { recordRunStop } from '../../self-implement/run-stop.js';
|
|
36
|
+
import { gateFailureReceipt, gateFailureReceiptLines } from '../../self-implement/gate-failure-signature.js';
|
|
34
37
|
import { runSuffixKey } from '../../self-implement/salvage-branches.js';
|
|
35
38
|
import type { GoalExecutionRecord } from '../../self-implement/orchestrator.js';
|
|
36
39
|
import { hostRepositoryUnavailable, runHostRegate, type HostRegateResult } from '../../self-implement/host-regate.js';
|
|
@@ -67,14 +70,14 @@ export const POD_JOB_DEADLINE_SECONDS = 10_800;
|
|
|
67
70
|
import { POD_LAUNCH_FINISHED_EVENT, POD_LAUNCH_STARTED_EVENT, provenanceRowFromAnnotations, siTaskPodProvenance } from './pod-launch-history.js';
|
|
68
71
|
import { podProvenanceMetadata, type PodProvenanceMetadata } from './pod-provenance.js';
|
|
69
72
|
import { packageVersion } from '../../version/code-revision.js';
|
|
70
|
-
import { podWorkLabels, type PodWorkIdentity, type PodPlacement, type PodPlacementKind, type PodPoolMember, type PodPoolScheduler } from './pod-pool.js';
|
|
73
|
+
import { minihLocationFrom, podWorkLabels, type PodWorkIdentity, type PodPlacement, type PodPlacementKind, type PodPoolMember, type PodPoolScheduler } from './pod-pool.js';
|
|
71
74
|
export { POD_CHILD_REQUESTS } from './pod-lease.js';
|
|
72
75
|
import { measurePoolLease, recommendConcurrency, POD_CHILD_REQUESTS, POD_SI_ADMISSION_CAP_BYTES, POD_HOST_LEASE_ANNOTATION, POD_JOB_TTL_AFTER_FINISHED_SECONDS, LEASE_KUBECTL_MAX_BUFFER, memoryQuantityBytes } from './pod-lease.js';
|
|
73
76
|
import { ACTUAL_SUBSTRATE_ENV, RUN_CONTRACT_ENV, carryRunContract, completionFloorFor } from '../../self-implement/graph-run-contract.js';
|
|
74
|
-
import { execFile, spawnSync } from 'node:child_process';
|
|
77
|
+
import { execFile, execFileSync, spawnSync } from 'node:child_process';
|
|
75
78
|
import { createHash } from 'node:crypto';
|
|
76
|
-
import { existsSync, mkdirSync, readFileSync, realpathSync } from 'node:fs';
|
|
77
|
-
import { homedir } from 'node:os';
|
|
79
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync } from 'node:fs';
|
|
80
|
+
import { homedir, tmpdir } from 'node:os';
|
|
78
81
|
import { isAbsolute, join, normalize, relative, resolve, sep } from 'node:path';
|
|
79
82
|
import { findGitDir } from '../../git-fs/locate.js';
|
|
80
83
|
import { hostLeaseBaseDir } from '../../pod-lease/host-lease.js';
|
|
@@ -84,20 +87,21 @@ import { enterJourneyNode, exitJourneyNode, passJourneyNode } from '../../self-d
|
|
|
84
87
|
import { routeJourneyEdge } from '../../self-dev/graph-journey-route.js';
|
|
85
88
|
import { selectLiveDetail } from '../../live/detail-switch.js';
|
|
86
89
|
import { authStorePath } from '../../oauth/store.js';
|
|
87
|
-
import { grokAuthFilePath, isGrokSubscriptionExpiring, refreshGrokSubscriptionToken, resolveGrokCredential, type GrokRefreshOutcome } from '../../grok/credential.js';
|
|
90
|
+
import { grokAuthFilePath, isGrokSubscriptionExpiring, readSelectedGrokScope, refreshGrokSubscriptionToken, resolveGrokCredential, type GrokRefreshOutcome } from '../../grok/credential.js';
|
|
88
91
|
import { defaultGrokModel } from '../../grok/models.js';
|
|
89
92
|
import { resolveHostId } from '../../platform/host-id.js';
|
|
90
93
|
import { BUDGET_SNAPSHOT_ENV, encodeBudgetSnapshot, harnessLaunchBudgetDecision, type BudgetSnapshot } from '../../execution-loop/launch-gate.js';
|
|
91
94
|
import type { ReadBudgetInputsDeps } from '../../self-implement/budget-gate.js';
|
|
92
95
|
import { envLiteral } from '../../platform/env-literal.js';
|
|
93
96
|
import { LLM_TIER_MAP_BY_PROVIDER, lookupLlmTierSpec, type LlmTierProvider } from '../../model-tier/llm-tier-map.js';
|
|
94
|
-
import { parseSelfImplementJson, type SelfImplementJobDone, type SelfImplementJobSpawn } from './self-implement.js';
|
|
97
|
+
import { parseSelfImplementJson, type SelfImplementDisposition, type SelfImplementJobDone, type SelfImplementJobSpawn } from './self-implement.js';
|
|
95
98
|
import { codexQuotaPolicyFromConfig } from '../../oauth/codex-account-store.js';
|
|
96
99
|
import { normalizeFallbackChain, type FallbackStep } from '../../oauth/fallback-chain.js';
|
|
97
100
|
import { goalTypeOf, type GoalType } from '../../../scripts/measure-pod-memory-by-goal.js';
|
|
98
101
|
import { declaredGoalType, type GoalType as DeclaredGoalType } from '../../self-implement/goal-author.js';
|
|
99
102
|
import { readPodMemoryAdvice, type PodMemoryAdvice } from '../../cli/pod-memory-advice.js';
|
|
100
103
|
import { DEFAULT_BUDGET_GATE_MAX_USED_PERCENT, getUserConfig, roleLlmEnvName, type UserConfig } from '../../user-config.js';
|
|
104
|
+
import { worktreeAddTimeoutSec } from '../../git-fs/worktree.js';
|
|
101
105
|
import { podChildProviderOf, podChildProviderRefusal, type PodChildProvider } from './pod-child-providers.js';
|
|
102
106
|
import { BEDROCK_POD_EGRESS_LABEL, bedrockPodEnv, checkBedrockPodSecret, type BedrockPodSpec } from './pod-bedrock-child.js';
|
|
103
107
|
import { resolveBedrockRegion, validBedrockRegion } from '../../llm/bedrock.js';
|
|
@@ -105,7 +109,7 @@ import { ZAI_POD_EGRESS_LABEL, checkZaiPodSecret, countActiveZaiJobs, decideZaiP
|
|
|
105
109
|
import { ZAI_CODING_DEFAULT_MODEL, ZAI_OPENROUTER_FALLBACK_MODEL, zaiSettingsFromConfig, type ZaiCodingPlanSettings } from '../../llm/zai-coding-plan.js';
|
|
106
110
|
import { normalizePlanningFallbackReason, selectEnhanceLlm } from '../../prompt-enhance/enhance.js';
|
|
107
111
|
import { inferProviderFromModel } from '../../llm.js';
|
|
108
|
-
import { classifyPodExit, extractPodFailureReason, podChildFailureAttribution, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
|
|
112
|
+
import { classifyPodExit, extractPodFailureReason, podChildFailureAttribution, podDeadlineResultMarker, podJobConditionReason, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
|
|
109
113
|
import { kubectlTransientReason, retryKubectlTransient } from './kubectl-transient-retry.js';
|
|
110
114
|
import { OLD_DOOR_STAMP_ENV } from '../../self-dev/old-door.js';
|
|
111
115
|
import { resolveDefaultSourceHead, seedMirrorOnce, type MirrorSeedResult } from './pod-mirror-seed.js';
|
|
@@ -228,6 +232,8 @@ export interface PodSpawnOptions {
|
|
|
228
232
|
/** LAUNCH-STALL: ms a launch may wait in one stage before `launch-stalled` (test seam; default harness.launchStallMinutes · 15 min). */
|
|
229
233
|
launchStallMs?: number;
|
|
230
234
|
kubectl?: Kubectl;
|
|
235
|
+
/** Capture SSH transport test seam; host selection and placement validation remain in the production path. */
|
|
236
|
+
failureCaptureRemote?: (host: string, args: readonly string[]) => ReturnType<Kubectl>;
|
|
231
237
|
/** Host-side regate (injected for Pod tests). */
|
|
232
238
|
hostRegate?: (input: { prNumber: number; headCommit: string; repoRoot: string; goalFile?: string; noMerge?: true }) => Promise<HostRegateResult>;
|
|
233
239
|
/** REVIEW-ACP-POD — Pod merge-ready PR 을 호스트 Claude ACP 로 리뷰한 뒤 재게이트(opt-in · 옵션 → env `ELANOUS_POD_HOST_ACP_REVIEW` → config `llm.podHostAcpReview`). */
|
|
@@ -522,15 +528,6 @@ export function formatGrokRemaining(ms: number | null): string {
|
|
|
522
528
|
return m >= 60 ? `${Math.floor(m / 60)}h${String(m % 60).padStart(2, '0')}m` : `${m}m`;
|
|
523
529
|
}
|
|
524
530
|
|
|
525
|
-
/** Latest `expires_at` among scopes that carry an access key (the token the Pod would get). */
|
|
526
|
-
function grokSubscriptionExpiresAtMs(home?: string): number | null {
|
|
527
|
-
try {
|
|
528
|
-
const scopes = JSON.parse(readFileSync(grokAuthFilePath(home), 'utf8')) as Record<string, { key?: unknown; expires_at?: unknown }>;
|
|
529
|
-
const all = Object.values(scopes).flatMap((s) => (s && typeof s.key === 'string' && s.key && typeof s.expires_at === 'string' && Number.isFinite(Date.parse(s.expires_at)) ? [Date.parse(s.expires_at)] : []));
|
|
530
|
-
return all.length ? Math.max(...all) : null;
|
|
531
|
-
} catch { return null; }
|
|
532
|
-
}
|
|
533
|
-
|
|
534
531
|
/** POD-GROK-VALIDITY-FIT — this launch's Job deadline for a refresh-less grok subscription copy.
|
|
535
532
|
* · relay (the Pod can renew from the host) or unknown expiry → the requested deadline as is.
|
|
536
533
|
* · otherwise → min(requested, remaining − margin); below the minimum Job (time passed since the credential check)
|
|
@@ -570,38 +567,46 @@ export function podGhLoginRetryBackoffMs(job: string): number {
|
|
|
570
567
|
export function hostGrokCredentials(opts: {
|
|
571
568
|
home?: string; env?: NodeJS.ProcessEnv; apiKeyOptIn?: boolean; ghToken?: () => string;
|
|
572
569
|
/** Test seams — the host refresh (read-only `grok models`) and the expiry probe. */
|
|
573
|
-
refresh?: () => void; isExpiring?: () => boolean;
|
|
570
|
+
refresh?: () => void; isExpiring?: () => boolean; grokPath?: string;
|
|
574
571
|
/** Required remaining token life (default POD_GROK_MIN_VALIDITY_MS) — a caller whose Job is not fitted passes its own deadline. */
|
|
575
572
|
minValidityMs?: number; now?: () => number;
|
|
576
573
|
} = {}): { grokAuth?: string; grokApiKey?: string; ghToken: string } {
|
|
577
574
|
let credential = resolveGrokCredential({ home: opts.home, env: opts.env });
|
|
578
575
|
if (credential?.kind === 'subscription') {
|
|
576
|
+
const initialScope = readSelectedGrokScope(opts.home);
|
|
577
|
+
if (!initialScope) throw new Error('grok: 선택된 구독 scope 없음 — 발사를 거부');
|
|
579
578
|
const minValidityMs = opts.minValidityMs ?? POD_GROK_MIN_VALIDITY_MS;
|
|
580
|
-
const
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
throw new Error(`grok: 구독 access 토큰 남은 시간 ${formatGrokRemaining(remainingMs)} < Pod 발사 기준 ${formatGrokRemaining(minValidityMs)} — 호스트 갱신(grok models)도 못 늘렸다 · 다음: 호스트에서 grok login --device-auth 후 다시`);
|
|
579
|
+
const clock = opts.now ?? Date.now;
|
|
580
|
+
const initialExpiry = initialScope.expiresAt ? Date.parse(initialScope.expiresAt) : NaN;
|
|
581
|
+
const expiring = opts.isExpiring ? opts.isExpiring()
|
|
582
|
+
: !Number.isFinite(initialExpiry) || initialExpiry - clock() < minValidityMs;
|
|
583
|
+
if (expiring) {
|
|
584
|
+
if (!initialScope.hasRefreshToken) {
|
|
585
|
+
throw new Error('grok: 선택된 구독 scope에 refresh token 없음 — 다른 계정으로 대체하지 않고 발사를 거부');
|
|
588
586
|
}
|
|
589
|
-
|
|
590
|
-
|
|
587
|
+
try {
|
|
588
|
+
if (opts.refresh) opts.refresh();
|
|
589
|
+
else refreshGrokSubscriptionToken({ home: opts.home, requireRefreshToken: true,
|
|
590
|
+
requiredValidityMs: minValidityMs, nowMs: clock(), ...(opts.grokPath ? { grokPath: opts.grokPath } : {}) });
|
|
591
|
+
} catch { /* Final snapshot below is the launch decision. */ }
|
|
591
592
|
}
|
|
592
|
-
const
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
...(typeof scope.user_id === 'string' ? { user_id: scope.user_id } : {}),
|
|
602
|
-
};
|
|
593
|
+
const selected = readSelectedGrokScope(opts.home);
|
|
594
|
+
if (!selected || selected.scopeName !== initialScope.scopeName) {
|
|
595
|
+
throw new Error('grok: 자격 확인 중 선택된 구독 scope가 사라졌거나 바뀜 — 발사를 거부');
|
|
596
|
+
}
|
|
597
|
+
const selectedExpiry = selected.expiresAt ? Date.parse(selected.expiresAt) : NaN;
|
|
598
|
+
if (!Number.isFinite(selectedExpiry) || selectedExpiry - clock() < minValidityMs) {
|
|
599
|
+
const remainingMs = Number.isFinite(selectedExpiry) ? selectedExpiry - clock() : null;
|
|
600
|
+
try { debug.log('pod.grok-credentials', 'refused', { remainingMs, minValidityMs, expiresAt: selected.expiresAt }); } catch { /* fail-soft */ }
|
|
601
|
+
throw new Error(`grok: 구독 access 토큰 남은 시간 ${formatGrokRemaining(remainingMs)} < Pod 발사 기준 ${formatGrokRemaining(minValidityMs)} — 호스트 갱신(grok models)도 못 늘렸다 · 다음: 호스트에서 grok login --device-auth 후 다시`);
|
|
603
602
|
}
|
|
604
|
-
|
|
603
|
+
const redacted: Record<string, { key: string; expires_at?: string; user_id?: string }> = {
|
|
604
|
+
[selected.scopeName]: {
|
|
605
|
+
key: selected.key,
|
|
606
|
+
...(selected.expiresAt ? { expires_at: selected.expiresAt } : {}),
|
|
607
|
+
...(selected.userId ? { user_id: selected.userId } : {}),
|
|
608
|
+
},
|
|
609
|
+
};
|
|
605
610
|
return { grokAuth: JSON.stringify(redacted), ghToken: (opts.ghToken ?? defaultGhToken)() };
|
|
606
611
|
}
|
|
607
612
|
if (credential?.kind === 'api_key' && opts.apiKeyOptIn === true) {
|
|
@@ -804,6 +809,48 @@ export function podGithubWatchdogScript(staleSeconds: number, intervalSeconds =
|
|
|
804
809
|
].join('\n');
|
|
805
810
|
}
|
|
806
811
|
|
|
812
|
+
export function podSalvageBundleScript(): string {
|
|
813
|
+
return `if [ "\${rc:-0}" -ne 0 ] && grep -Eq 'draft PR 생성 실패|PR (gh|guard) 실패|same-cell reuse:' "\${ELANOUS_POD_CHILD_OUTPUT:-/tmp/si.out}"; then
|
|
814
|
+
mkdir -p "$HOME/outbox/pod-salvage"
|
|
815
|
+
found_commits=0
|
|
816
|
+
preservation_failed=0
|
|
817
|
+
bundle_bytes=0
|
|
818
|
+
worktree_rows=$(git worktree list --porcelain) || preservation_failed=1
|
|
819
|
+
while IFS= read -r wt; do
|
|
820
|
+
[ -n "$wt" ] || continue
|
|
821
|
+
git -C "$wt" rev-parse --is-inside-work-tree >/dev/null 2>&1 || { preservation_failed=1; continue; }
|
|
822
|
+
wt_name=$(basename -- "$wt")
|
|
823
|
+
case "$wt_name" in ''|.*|*/*|*'..'*) preservation_failed=1; continue ;; esac
|
|
824
|
+
base=$(git -C "$wt" rev-parse --verify '@{u}' 2>/dev/null || git -C "$wt" rev-parse --verify origin/HEAD 2>/dev/null || git -C "$wt" rev-list --max-parents=0 HEAD | tail -n 1)
|
|
825
|
+
head=$(git -C "$wt" rev-parse HEAD) || { preservation_failed=1; continue; }
|
|
826
|
+
[ -n "$base" ] || { preservation_failed=1; continue; }
|
|
827
|
+
commitCount=$(git -C "$wt" rev-list --count "$base..$head") || { preservation_failed=1; continue; }
|
|
828
|
+
if [ "$commitCount" -eq 0 ]; then continue; fi
|
|
829
|
+
found_commits=1
|
|
830
|
+
diffStats=$(git -C "$wt" diff --numstat "$base..$head") || { preservation_failed=1; continue; }
|
|
831
|
+
diffLines=$(printf '%s\\n' "$diffStats" | awk '{added += $1; removed += $2} END {print added + removed}')
|
|
832
|
+
bundle="$HOME/outbox/pod-salvage/$wt_name.bundle"
|
|
833
|
+
branch=$(git -C "$wt" symbolic-ref --quiet --short HEAD) || { preservation_failed=1; continue; }
|
|
834
|
+
if git -C "$wt" bundle create "$bundle" "refs/heads/$branch" && [ -s "$bundle" ]; then
|
|
835
|
+
size=$(( $(wc -c < "$bundle") ))
|
|
836
|
+
if [ "$size" -gt ${POD_SALVAGE_BUNDLE_FILE_LIMIT} ] || [ $((bundle_bytes + size)) -gt ${POD_SALVAGE_BUNDLE_TOTAL_LIMIT} ]; then
|
|
837
|
+
preservation_failed=1
|
|
838
|
+
rm -f -- "$bundle"
|
|
839
|
+
printf 'ELANOUS_POD_SALVAGE_FAILED size-limit %s %s %s\\n' "$wt_name" "$size" "$head"
|
|
840
|
+
else
|
|
841
|
+
bundle_bytes=$((bundle_bytes + size))
|
|
842
|
+
printf 'ELANOUS_POD_SALVAGE_BUNDLE pod-salvage/%s.bundle %s %s %s\\n' "$wt_name" "$commitCount" "$diffLines" "$head"
|
|
843
|
+
fi
|
|
844
|
+
else
|
|
845
|
+
preservation_failed=1
|
|
846
|
+
printf 'ELANOUS_POD_SALVAGE_FAILED bundle-create %s\\n' "$wt_name"
|
|
847
|
+
fi
|
|
848
|
+
done < <(printf '%s\\n' "$worktree_rows" | awk '/^worktree / {sub(/^worktree /, ""); print}')
|
|
849
|
+
if [ "$preservation_failed" -ne 0 ]; then printf 'ELANOUS_POD_SALVAGE_FAILED incomplete\\n'
|
|
850
|
+
elif [ "$found_commits" -eq 0 ]; then printf 'ELANOUS_POD_SALVAGE_NONE no-commits\\n'; fi
|
|
851
|
+
fi`;
|
|
852
|
+
}
|
|
853
|
+
|
|
807
854
|
export function podSalvageScript(): string {
|
|
808
855
|
return [
|
|
809
856
|
'if [ "${rc:-0}" -ne 0 ]; then',
|
|
@@ -1146,6 +1193,29 @@ export function podSigtermTrapScript(seqFile: string = POD_USAGE_PARTIAL_SEQ_FIL
|
|
|
1146
1193
|
return `trap '{ [ -n "$si_pid" ] && kill "$si_pid" 2>/dev/null || true; [ -n "\${usage_partial_pid:-}" ] && kill "$usage_partial_pid" 2>/dev/null || true; si_seq=$(cat ${seqFile} 2>/dev/null || true); case "$si_seq" in ""|*[!0-9]*) si_seq=0;; esac; si_seq=$((10#$si_seq + 1)); { [ -f scripts/usage-rollup.ts ] && bun scripts/usage-rollup.ts --since 12h --partial --seq "$si_seq"; } & si_rollup_pid=$!; for si_i in 1 2 3 4 5 6 7 8; do kill -0 "$si_rollup_pid" 2>/dev/null || break; sleep 1; done; kill "$si_rollup_pid" 2>/dev/null || true; wait "$si_rollup_pid" 2>/dev/null || true; exit 143; }' TERM`;
|
|
1147
1194
|
}
|
|
1148
1195
|
|
|
1196
|
+
/** Leave enough time for the Pod wrapper to print its result and push a salvage branch before Kubernetes kills the Job. */
|
|
1197
|
+
export function podDeadlineWatchdogScript(input: { deadlineSeconds: number; job: string; runId?: string; prNumber?: number }): string {
|
|
1198
|
+
const leadSeconds = Math.max(1, Math.min(600, Math.floor(input.deadlineSeconds / 10)));
|
|
1199
|
+
const waitSeconds = Math.max(1, input.deadlineSeconds - leadSeconds);
|
|
1200
|
+
const job = /^[A-Za-z0-9_.:-]+$/.test(input.job) ? input.job : 'unknown-job';
|
|
1201
|
+
const runId = input.runId && /^[A-Za-z0-9_.:-]+$/.test(input.runId) ? input.runId : 'unknown-run';
|
|
1202
|
+
const pr = input.prNumber && Number.isSafeInteger(input.prNumber) && input.prNumber > 0 ? String(input.prNumber) : 'unknown';
|
|
1203
|
+
const jsonPr = pr === 'unknown' ? 'null' : pr;
|
|
1204
|
+
return `printf 'clone\\n' > /tmp/si.stage
|
|
1205
|
+
(sleep ${waitSeconds}; [ -f /tmp/si.finished ] && exit 0
|
|
1206
|
+
stage=$(cat /tmp/si.stage 2>/dev/null || true); case "$stage" in clone|setup|run) ;; *) stage=unknown;; esac
|
|
1207
|
+
branch=$(git -C repo branch --show-current 2>/dev/null || true); case "$branch" in ''|*[!A-Za-z0-9_./-]*) branch=unknown;; esac
|
|
1208
|
+
[ -f /tmp/si.finished ] && exit 0
|
|
1209
|
+
si_target=$(cat /tmp/si.pid 2>/dev/null || true)
|
|
1210
|
+
case "$si_target" in ''|*[!0-9]*) ;; *) kill -0 "$si_target" 2>/dev/null || exit 0;; esac
|
|
1211
|
+
printf 'ELANOUS_POD_DEADLINE_RESULT ${job} ${runId} stop-cause=deadline stage=%s pr=${pr} branch=%s\\n' "$stage" "$branch" | tee /tmp/si.deadline-marker
|
|
1212
|
+
printf '{"stage":"deadline","ok":false,"error":"Pod deadline preemption","stopCause":"deadline","prNumber":${jsonPr},"branch":"%s"}\\n' "$branch" > /tmp/si.deadline-result
|
|
1213
|
+
case "$si_target" in ''|*[!0-9]*) ;; *) kill -TERM "$si_target" 2>/dev/null || true;; esac
|
|
1214
|
+
) & si_deadline_watch_pid=$!`;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
export const POD_DEADLINE_AFTER_WAIT = `if [ "$rc" -ne 0 ] && [ -f /tmp/si.deadline-result ]; then printf '\\n' >> /tmp/si.out; cat /tmp/si.deadline-result >> /tmp/si.out; rc=124; fi`;
|
|
1218
|
+
|
|
1149
1219
|
export function podJobManifest(o: { name: string; namespace: string; image: string; workIdentity?: PodWorkIdentity; boundPrNumber?: number; /** 레지스트리 이미지면 IfNotPresent(노드가 pull) · 반입 이미지면 Never. */ imagePullPolicy?: 'Never' | 'IfNotPresent'; repoUrl: string; source?: PodSource; repairCommitOnly?: { pr: number; baseHead: string }; hostMirror?: string; args: readonly string[]; passEnv: readonly string[]; deadlineSeconds: number; runId?: string; parentRunId?: string; armEnv?: Readonly<Record<string, string>>; hostId?: string; imageCommit?: string | null; skillEnvs?: readonly string[]; memoryLimit?: string; memoryRequest?: string; goalDoc?: string; /** AUTHOR-POD2 — run `harness say` on /creds/feature inside the Pod (authoring happens off the host). */ authorSentence?: boolean; authorGrade?: 'full' | 'lite'; grokCredential?: 'subscription' | 'api_key'; codexAccounts?: readonly string[]; appCredential?: boolean; /** Test seam — default POD_GH_STALE_SECONDS. */ githubStaleSeconds?: number; /** Which goal execution and attempt this Job is — a resumed host verifies it before following the Job (POD9). */ execution?: { key: string; attempt: number }; hostLeaseAdmitted?: boolean; /** POD-ROLE-LLM — OpenRouter 자식 Pod 에 리뷰어용 codex 자격을 깐다. */ reviewerCodexAuth?: boolean; /** BEDROCK-PROVIDER ② — bedrock 자식만: 이름 있는 AWS Secret 의 키(secretKeyRef) ⊕ 리전 ⊕ 이그레스 라벨. */ bedrock?: BedrockPodSpec; /** ZAI-POD-CHILD — glm(ZAI) 자식만: 이름 있는 ZAI Secret 의 키(secretKeyRef) ⊕ 이그레스·동시 상한 라벨(Pod ⊕ Job). */ zai?: ZaiPodSpec; /** Codex Job may use the same named Secret only for an explicitly admitted ZAI fallback. */ zaiFallback?: ZaiPodSpec; fallbackChain?: { steps: readonly FallbackStep[]; source: 'host' | 'default' }; /** TA-POD-WARMBOOT-PARITY — the child's final line (podResultMarkerShellLine), just before `exit $rc`. */ resultMarkerLine?: string; /** POD-LAUNCH-PROVENANCE — the shared provenance set (labels ⊕ annotations ⊕ child env) for this si-task Job. */ provenance?: PodProvenanceMetadata }): Record<string, unknown> {
|
|
1150
1220
|
if (o.repairCommitOnly && (o.source?.kind !== 'pr' || o.source.number !== o.repairCommitOnly.pr || !/^[0-9a-f]{40}$/.test(o.repairCommitOnly.baseHead) || o.args.includes('--open-pr') || o.args.includes('--merge-by-host') || o.args.includes('--auto-merge'))) {
|
|
1151
1221
|
throw new Error('repair commit-only requires matching PR source and no PR/merge flags');
|
|
@@ -1206,9 +1276,11 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
|
|
|
1206
1276
|
// SI-POD-STAGE-MARKERS — Pod 시계 단계 표지(`ELANOUS_POD_STAGE <stage> <start|end> <epoch초>`): 호스트가 Job 로그에서 읽어
|
|
1207
1277
|
// pod.lifecycle stages 의 clone · mirror · run 을 채운다. 실패한 단계는 끝 표지가 없다(→ missing · 지어내지 않는다).
|
|
1208
1278
|
// clone 끝 = podSourceScript 전체가 끝난 뒤(갈래마다 마지막 줄이 `ELANOUS_POD_SOURCE` 또는 `cd repo` — 둘 다 소스 받기의 일부).
|
|
1279
|
+
podDeadlineWatchdogScript({ deadlineSeconds: o.deadlineSeconds, job: o.name, runId: o.runId, prNumber: o.boundPrNumber }),
|
|
1209
1280
|
siTaskPodStageShell('clone', 'start'),
|
|
1210
1281
|
podSourceScript(o.source ?? { kind: 'default' }, o.repoUrl, undefined, { stageMarkers: true }),
|
|
1211
1282
|
siTaskPodStageShell('clone', 'end'),
|
|
1283
|
+
`printf 'setup\\n' > /tmp/si.stage`,
|
|
1212
1284
|
// This image already contains runtime dependencies; there is no child install command.
|
|
1213
1285
|
// Record that fact before the main command, without treating clone completion as install completion.
|
|
1214
1286
|
`printf 'ELANOUS_POD_DEPS skipped %s image-prepared-no-install\\n' "$(date +%s)" || true`,
|
|
@@ -1232,15 +1304,19 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
|
|
|
1232
1304
|
// 마지막 줄 JSON 이 «맨 끝»이어야 한다(parseSelfImplementJson) — rollup 은 그 앞에.
|
|
1233
1305
|
// ⛔ `--author-grade` 는 Pod 안 `elanous`(이미지에 깔린 판)가 모를 수 있어 넘기지 않는다 — 10-06 «unknown option» 즉사(#24445 되돌림).
|
|
1234
1306
|
// AUTHOR-LITE2-POD — 등급은 환경변수 `ELANOUS_AUTHOR_GRADE` 로 싣는다(옛 Pod elanous 는 모르는 환경변수를 무시하고 full 로 돈다).
|
|
1307
|
+
`printf 'run\\n' > /tmp/si.stage`,
|
|
1235
1308
|
siTaskPodStageShell('run', 'start'),
|
|
1236
1309
|
o.repairCommitOnly
|
|
1237
|
-
? `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json --no-open-pr ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; if elanous self repair-commit-export '${o.repairCommitOnly.pr}' '${o.repairCommitOnly.baseHead}' /tmp/si.out "$PWD" "$HOME/outbox"; then rc=0; elif [ "$rc" -eq 0 ]; then rc=8; fi`
|
|
1310
|
+
? `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json --no-open-pr ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; if elanous self repair-commit-export '${o.repairCommitOnly.pr}' '${o.repairCommitOnly.baseHead}' /tmp/si.out "$PWD" "$HOME/outbox"; then rc=0; elif [ "$rc" -eq 0 ]; then rc=8; fi; ${POD_DEADLINE_AFTER_WAIT}`
|
|
1238
1311
|
: o.authorSentence
|
|
1239
|
-
? `echo "ELANOUS_AUTHOR_ON_POD started host=$(hostname) at=$(date -u +%Y-%m-%dT%H:%M:%SZ)"; author_t0=$(date +%s); ${o.authorGrade === 'lite' || o.authorGrade === 'full' ? `ELANOUS_AUTHOR_GRADE=${o.authorGrade} ` : ''}elanous harness say --substrate local --json${quotedAsk}${quotedChildLlm} -- "$(cat /creds/feature)" > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; echo "ELANOUS_AUTHOR_ON_POD finished host=$(hostname) rc=$rc seconds=$(( $(date +%s) - author_t0 ))"; ${POD_RESULT_FLATTEN}`
|
|
1312
|
+
? `echo "ELANOUS_AUTHOR_ON_POD started host=$(hostname) at=$(date -u +%Y-%m-%dT%H:%M:%SZ)"; author_t0=$(date +%s); ${o.authorGrade === 'lite' || o.authorGrade === 'full' ? `ELANOUS_AUTHOR_GRADE=${o.authorGrade} ` : ''}elanous harness say --substrate local --json${quotedAsk}${quotedChildLlm} -- "$(cat /creds/feature)" > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; echo "ELANOUS_AUTHOR_ON_POD finished host=$(hostname) rc=$rc seconds=$(( $(date +%s) - author_t0 ))"; ${POD_RESULT_FLATTEN}`
|
|
1240
1313
|
: goalPath
|
|
1241
|
-
? `elanous harness ask ${goalPath} --json${quotedAsk}${quotedChildLlm} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; ${POD_RESULT_FLATTEN}`
|
|
1242
|
-
: `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; ${POD_RESULT_FLATTEN}`,
|
|
1314
|
+
? `elanous harness ask ${goalPath} --json${quotedAsk}${quotedChildLlm} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; ${POD_RESULT_FLATTEN}`
|
|
1315
|
+
: `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; ${POD_RESULT_FLATTEN}`,
|
|
1243
1316
|
'cat /tmp/si.out',
|
|
1317
|
+
...(o.appCredential && !o.repairCommitOnly ? ['kill "$gh_watch_pid" 2>/dev/null || true'] : []),
|
|
1318
|
+
...(o.repairCommitOnly ? [] : [podSalvageScript()]),
|
|
1319
|
+
podSalvageBundleScript(),
|
|
1244
1320
|
'[ -f scripts/usage-rollup.ts ] && bun scripts/usage-rollup.ts --since 12h || echo "ELANOUS_USAGE_ROLLUP {\"measured\":false,\"reason\":\"no rollup script\"}"',
|
|
1245
1321
|
// A long run's log export can pass the 5MB artifact limit; skipping it whole left no window into why a
|
|
1246
1322
|
// 2h+ child failed (🅢 09-27). Keep the newest lines under the limit instead, and say so.
|
|
@@ -1257,23 +1333,27 @@ else
|
|
|
1257
1333
|
fi`,
|
|
1258
1334
|
`set -o pipefail
|
|
1259
1335
|
artifact_bytes=0
|
|
1336
|
+
salvage_bundle_bytes=0
|
|
1260
1337
|
if [ -d "$HOME/outbox" ]; then
|
|
1261
1338
|
while IFS= read -r -d '' file; do
|
|
1262
1339
|
[ -f "$file" ] && [ ! -L "$file" ] || continue
|
|
1263
1340
|
relative=\${file#"$HOME/outbox/"}
|
|
1264
1341
|
size=$(( $(wc -c < "$file") ))
|
|
1265
|
-
|
|
1342
|
+
salvage_bundle=0
|
|
1343
|
+
case "$relative" in pod-salvage/*.bundle) salvage_bundle=1 ;; esac
|
|
1344
|
+
if { [ "$salvage_bundle" -eq 0 ] && { [ "$size" -gt 5242880 ] || [ $((artifact_bytes + size)) -gt 20971520 ]; }; } || { [ "$salvage_bundle" -eq 1 ] && { [ "$size" -gt ${POD_SALVAGE_BUNDLE_FILE_LIMIT} ] || [ $((salvage_bundle_bytes + size)) -gt ${POD_SALVAGE_BUNDLE_TOTAL_LIMIT} ]; }; }; then
|
|
1266
1345
|
printf 'ELANOUS_POD_ARTIFACT_SKIPPED %s %s\\n' "$relative" "$size"
|
|
1267
1346
|
continue
|
|
1268
1347
|
fi
|
|
1269
1348
|
path_token=$(printf '%s' "$relative" | base64 | tr -d '\\n' | tr '+/' '-_' | tr -d '=')
|
|
1270
1349
|
if encoded=$(gzip -c "$file" | base64 | tr -d '\\n'); then
|
|
1271
|
-
artifact_bytes=$((artifact_bytes + size))
|
|
1350
|
+
if [ "$salvage_bundle" -eq 1 ]; then salvage_bundle_bytes=$((salvage_bundle_bytes + size)); else artifact_bytes=$((artifact_bytes + size)); fi
|
|
1272
1351
|
total=$(( (\${#encoded} + 7999) / 8000 ))
|
|
1273
|
-
|
|
1274
|
-
|
|
1352
|
+
n=1
|
|
1353
|
+
while IFS= read -r chunk || [ -n "$chunk" ]; do
|
|
1275
1354
|
printf 'ELANOUS_POD_ARTIFACT %s %s/%s %s\\n' "$path_token" "$n" "$total" "$chunk"
|
|
1276
|
-
|
|
1355
|
+
n=$((n + 1))
|
|
1356
|
+
done < <(printf '%s' "$encoded" | fold -w 8000)
|
|
1277
1357
|
else
|
|
1278
1358
|
printf 'ELANOUS_POD_ARTIFACT_SKIPPED %s %s\\n' "$relative" "$size"
|
|
1279
1359
|
fi
|
|
@@ -1296,12 +1376,12 @@ for ledger in "\${ELANOUS_STATE_DIR:-$HOME/.elanous}"/run-ledger/*.jsonl; do
|
|
|
1296
1376
|
done
|
|
1297
1377
|
if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
|
|
1298
1378
|
'kill "$mem_sampler_pid" 2>/dev/null || true',
|
|
1299
|
-
...(o.appCredential && !o.repairCommitOnly ? ['kill "$gh_watch_pid" 2>/dev/null || true'] : []),
|
|
1300
1379
|
'[ -n "${usage_partial_pid:-}" ] && kill "$usage_partial_pid" 2>/dev/null || true',
|
|
1301
1380
|
'wait "$mem_sampler_pid" 2>/dev/null || true',
|
|
1302
1381
|
'[ -n "${usage_partial_pid:-}" ] && wait "$usage_partial_pid" 2>/dev/null || true',
|
|
1382
|
+
'if [ "$rc" -ne 0 ] && [ -f /tmp/si.deadline-result ]; then rc=124; fi',
|
|
1303
1383
|
'tail -n 1 /tmp/si.out',
|
|
1304
|
-
|
|
1384
|
+
'touch /tmp/si.finished; kill "$si_deadline_watch_pid" 2>/dev/null || true; [ -f /tmp/si.deadline-marker ] && cat /tmp/si.deadline-marker || true',
|
|
1305
1385
|
// TA-POD-WARMBOOT-PARITY: the last line says «the child is done» so the host need not wait for the Job condition.
|
|
1306
1386
|
...(o.resultMarkerLine ? [o.resultMarkerLine] : []),
|
|
1307
1387
|
'exit $rc',
|
|
@@ -1337,6 +1417,9 @@ if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
|
|
|
1337
1417
|
? [{ name: 'ELANOUS_TASK_BOUND_PR', value: String(o.boundPrNumber) }] : []),
|
|
1338
1418
|
...(o.workIdentity?.slotId ? [{ name: 'ELANOUS_POD_SLOT_ID', value: o.workIdentity.slotId }] : []),
|
|
1339
1419
|
{ name: 'ELANOUS_SUBSTRATE', value: 'pod' },
|
|
1420
|
+
// POD-INPLACE-WORKTREE: explicit host opt-in only; one Job runs one implementation child.
|
|
1421
|
+
{ name: 'ELANOUS_POD_SINGLE_CHILD', value: '1' },
|
|
1422
|
+
{ name: 'ELANOUS_POD_INPLACE_WORKTREE', value: process.env.ELANOUS_POD_INPLACE_WORKTREE === '1' ? '1' : '0' },
|
|
1340
1423
|
...Object.entries(controlInboxEnv(POD_CONTROL_INBOX_DIR)).map(([name, value]) => ({ name, value })),
|
|
1341
1424
|
// ⭐ 런 출처(🅣 RFC run-origin §A3 · #20457/#20468 칸 이름) — Pod 는 자기 elanous_id 를 쓰지 않고 «띄운 감독기»의 hostId 를 물려받는다.
|
|
1342
1425
|
{ name: 'ELANOUS_POD_NAME', valueFrom: { fieldRef: { fieldPath: 'metadata.name' } } },
|
|
@@ -1897,13 +1980,16 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1897
1980
|
const acquireSlot = async (): Promise<PodPoolMember | null> => {
|
|
1898
1981
|
if (!options.pool) return null;
|
|
1899
1982
|
const stop = watchStall('pool-slot');
|
|
1983
|
+
// MINIH-MODE (0.2.37): the location is declared by the launch env — absent/unknown keeps the configured
|
|
1984
|
+
// capacities, so this launch path behaves exactly as before unless the declaration is there.
|
|
1985
|
+
const minihLocation = minihLocationFrom(env.ELANOUS_MINIH_LOCATION);
|
|
1900
1986
|
try {
|
|
1901
1987
|
for (;;) {
|
|
1902
1988
|
if (input.signal?.aborted) return null;
|
|
1903
1989
|
// The reason comes back inside this call, so a concurrent launch cannot overwrite it.
|
|
1904
1990
|
const kind = podPlacementKind(oomRetried ? retryTier : memoryTier, selectedGoalType, requestKind);
|
|
1905
1991
|
const acquired = await options.pool.tryAcquire(unfitContexts, (reason) => { stageReason['pool-slot'] = reason; },
|
|
1906
|
-
{ kind, onPlacement: (placement) => { lastPlacement = placement; } });
|
|
1992
|
+
{ kind, ...(minihLocation ? { minihLocation } : {}), onPlacement: (placement) => { lastPlacement = placement; } });
|
|
1907
1993
|
if (acquired) {
|
|
1908
1994
|
debug.log('self-implement.pod', 'pool-slot', { spaceId: input.spaceId, context: acquired.context, inflight: options.pool.snapshot(), ...(lastPlacement ? { placement: lastPlacement } : {}) });
|
|
1909
1995
|
if (lastPlacement) console.warn(`[pod] 배치: ${lastPlacement.reason}`);
|
|
@@ -1954,6 +2040,21 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1954
2040
|
const currentContext = member ? null : baseKubectl(['config', 'current-context']);
|
|
1955
2041
|
let context = member?.context ?? (currentContext?.status === 0 ? currentContext.stdout.trim() : '');
|
|
1956
2042
|
const kubectl: Kubectl = (args, stdin) => baseKubectl(['--context', context, ...args], stdin);
|
|
2043
|
+
const captureKubectl = (host: string, args: readonly string[]): ReturnType<Kubectl> => {
|
|
2044
|
+
if (member?.sshHost ? member.sshHost !== host : host !== resolveHostId(env))
|
|
2045
|
+
return { status: 1, stdout: '', stderr: 'ledger host is not the selected pool host' };
|
|
2046
|
+
if (!member?.sshHost) return baseKubectl(args);
|
|
2047
|
+
if (options.failureCaptureRemote) return options.failureCaptureRemote(host, args);
|
|
2048
|
+
const result = spawnSync('ssh', ['-o', 'BatchMode=yes', '-o', 'ConnectTimeout=5', '--', host, 'kubectl', ...args],
|
|
2049
|
+
{ encoding: 'utf8', timeout: 30_000, maxBuffer: LEASE_KUBECTL_MAX_BUFFER });
|
|
2050
|
+
return { status: result.status, stdout: result.stdout ?? '', stderr: (result.stderr ?? '') + (result.error ? String(result.error) : '') };
|
|
2051
|
+
};
|
|
2052
|
+
const captureFailedJob = (childRunId: string): void => {
|
|
2053
|
+
try {
|
|
2054
|
+
captureFailedPodJobs({ runId: ledgerRunId, job: name, childRunId, ledgerPath: runLedgerPath(ledgerRunId, ledgerDir), artifactDir: join(effectiveInstanceRoot(), 'pod-artifacts'),
|
|
2055
|
+
kubectl: captureKubectl, record: (event, data) => appendRunLedgerEntry({ runId: ledgerRunId, event, data }, ledgerDir), now: options.now });
|
|
2056
|
+
} catch (error) { debug.log('self-implement.pod', 'failure-capture-ledger-unavailable', { job: name, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
|
|
2057
|
+
};
|
|
1957
2058
|
let recorded = false;
|
|
1958
2059
|
let groundingMinted: string | null = null;
|
|
1959
2060
|
try {
|
|
@@ -1995,6 +2096,44 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1995
2096
|
collectPodArtifacts(full.stdout, { dir: join(effectiveInstanceRoot(), 'pod-artifacts'), job: name, log: record });
|
|
1996
2097
|
}
|
|
1997
2098
|
catch (error) { record('self-implement.pod', 'artifact-collect-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
|
|
2099
|
+
for (const line of full.stdout.split(/\r?\n/)) {
|
|
2100
|
+
const bundle = /^ELANOUS_POD_SALVAGE_BUNDLE (pod-salvage\/[a-zA-Z0-9._-]+\.bundle) ([0-9]+) ([0-9]+)(?: ([0-9a-f]{40,64}))?$/.exec(line);
|
|
2101
|
+
if (bundle) {
|
|
2102
|
+
const bundlePath = join(effectiveInstanceRoot(), 'pod-artifacts', name, bundle[1]!);
|
|
2103
|
+
if (!existsSync(bundlePath)) {
|
|
2104
|
+
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-salvage-bundle', data: { job: name, disposition: '보존 실패', reason: 'bundle artifact missing' } }, ledgerDir); }
|
|
2105
|
+
catch (error) { record('self-implement.pod', 'salvage-bundle-ledger-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
|
|
2106
|
+
record('self-implement.pod', 'salvage-bundle-collect-incomplete', { job: name, path: bundlePath, reason: 'bundle artifact missing' });
|
|
2107
|
+
continue;
|
|
2108
|
+
}
|
|
2109
|
+
try {
|
|
2110
|
+
const refs = execFileSync('git', ['bundle', 'list-heads', bundlePath], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim().split(/\r?\n/);
|
|
2111
|
+
const [bundleHead, bundleRef] = refs[0]?.trim().split(/\s+/) ?? [];
|
|
2112
|
+
if (!bundleHead || !bundleRef?.startsWith('refs/heads/')) throw new Error('bundle contains no branch ref');
|
|
2113
|
+
const verifyDir = mkdtempSync(join(tmpdir(), 'pod-salvage-verify-'));
|
|
2114
|
+
try {
|
|
2115
|
+
execFileSync('git', ['clone', '--quiet', '--branch', bundleRef.slice('refs/heads/'.length), bundlePath, verifyDir], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
2116
|
+
const cloneHead = execFileSync('git', ['-C', verifyDir, 'rev-parse', 'HEAD'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
|
|
2117
|
+
if (cloneHead !== bundleHead || (bundle[4] && cloneHead !== bundle[4])) throw new Error('bundle clone HEAD mismatch');
|
|
2118
|
+
} finally { rmSync(verifyDir, { recursive: true, force: true }); }
|
|
2119
|
+
appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-salvage-bundle', data: {
|
|
2120
|
+
job: name, path: bundlePath,
|
|
2121
|
+
commitCount: Number(bundle[2]), diffLines: Number(bundle[3]), ...(bundle[4] ? { head: bundle[4] } : {}),
|
|
2122
|
+
} }, ledgerDir);
|
|
2123
|
+
} catch (error) {
|
|
2124
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
2125
|
+
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-salvage-bundle', data: { job: name, disposition: '보존 실패', reason: `bundle validation failed: ${reason}` } }, ledgerDir); }
|
|
2126
|
+
catch (ledgerError) { record('self-implement.pod', 'salvage-bundle-ledger-incomplete', { job: name, reason: ledgerError instanceof Error ? ledgerError.message : String(ledgerError) }); }
|
|
2127
|
+
record('self-implement.pod', 'salvage-bundle-collect-incomplete', { job: name, reason });
|
|
2128
|
+
}
|
|
2129
|
+
} else if (line === 'ELANOUS_POD_SALVAGE_NONE no-commits') {
|
|
2130
|
+
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-salvage-bundle', data: { job: name, disposition: '보존할 것 없음', commitCount: 0, diffLines: 0 } }, ledgerDir); }
|
|
2131
|
+
catch (error) { record('self-implement.pod', 'salvage-bundle-ledger-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
|
|
2132
|
+
} else if (line.startsWith('ELANOUS_POD_SALVAGE_FAILED ')) {
|
|
2133
|
+
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-salvage-bundle', data: { job: name, disposition: '보존 실패', reason: line.slice('ELANOUS_POD_SALVAGE_FAILED '.length) } }, ledgerDir); }
|
|
2134
|
+
catch (error) { record('self-implement.pod', 'salvage-bundle-ledger-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
1998
2137
|
if (options.repairCommitOnly) {
|
|
1999
2138
|
const artifactDir = join(effectiveInstanceRoot(), 'pod-artifacts', name, 'repair');
|
|
2000
2139
|
try {
|
|
@@ -2022,9 +2161,11 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2022
2161
|
// 상한 안 → ZAI(이름 있는 Secret · 없으면 거부) · 넘침 → 정책대로(openrouter·balance = 기존 OpenRouter GLM · stop = 거부 · apply 0).
|
|
2023
2162
|
let zaiRoute: 'zai' | 'openrouter' | undefined;
|
|
2024
2163
|
let zaiSpec: ZaiPodSpec | undefined;
|
|
2164
|
+
let zaiLaunchOverage: 'stop' | 'balance' | 'openrouter' | undefined;
|
|
2025
2165
|
zaiPendingApply.delete(name);
|
|
2026
2166
|
if (options.provider === 'glm') {
|
|
2027
2167
|
const settings = (options.zaiSettings ?? (() => zaiSettingsFromConfig(getUserConfig().llm)))();
|
|
2168
|
+
zaiLaunchOverage = settings.overage;
|
|
2028
2169
|
const poolMembers = (options.pool as { members?: readonly PodPoolMember[] } | undefined)?.members;
|
|
2029
2170
|
const contexts = Array.isArray(poolMembers) && poolMembers.length > 0 ? poolMembers.map((m) => m.context) : [context];
|
|
2030
2171
|
let active: number | null = 0;
|
|
@@ -2056,6 +2197,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2056
2197
|
const anthropic = options.provider === 'anthropic';
|
|
2057
2198
|
const bedrockChild = options.provider === 'bedrock';
|
|
2058
2199
|
const zaiChild = zaiRoute === 'zai';
|
|
2200
|
+
/** ZAI 로 입장한 자식도 플랜 한도 오류 뒤 OpenRouter 로 전환할 수 있다. 실행 중 폴백 자격을 발사 전에 확보한다. */
|
|
2201
|
+
const openrouterCredentialRequired = openrouter || (zaiChild && zaiLaunchOverage !== 'stop');
|
|
2059
2202
|
/** API 키 자식 — codex 계정·자격 파일을 안 쓴다(키는 작업별 creds Secret 의 `env-<KEY>` · bedrock·glm 은 이름 있는 Secret 으로만). */
|
|
2060
2203
|
const apiKeyChild = openrouter || openGateway || anthropic || bedrockChild || zaiChild;
|
|
2061
2204
|
const plannedAccount = retryAccount ?? (grok ? 'grok' : openrouter ? 'openrouter' : openGateway ? 'opengateway' : anthropic ? 'anthropic' : bedrockChild ? 'bedrock' : zaiChild ? 'glm' : options.accountBroker?.() ?? options.account ?? 'team');
|
|
@@ -2099,8 +2242,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2099
2242
|
}
|
|
2100
2243
|
return credential;
|
|
2101
2244
|
}) : undefined;
|
|
2102
|
-
const openrouterKey =
|
|
2103
|
-
if (
|
|
2245
|
+
const openrouterKey = openrouterCredentialRequired ? env.OPENROUTER_API_KEY?.trim() || (options.readKeyCache ?? defaultReadKeyCache)('OPENROUTER_API_KEY')?.trim() : undefined;
|
|
2246
|
+
if (openrouterCredentialRequired && !openrouterKey) throw new Error('pod: Pod 에 openrouter 키 없음 — 호스트 키 캐시 또는 OPENROUTER_API_KEY 필요');
|
|
2104
2247
|
const openGatewayEnvKey = openGateway ? env.OPENGATEWAY_API_KEY?.trim() : undefined;
|
|
2105
2248
|
const openGatewayCachedKey = openGateway ? (options.readKeyCache ?? defaultReadKeyCache)('OPENGATEWAY_API_KEY')?.trim() : undefined;
|
|
2106
2249
|
if (openGatewayEnvKey && openGatewayCachedKey && openGatewayEnvKey !== openGatewayCachedKey)
|
|
@@ -2182,7 +2325,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2182
2325
|
}
|
|
2183
2326
|
}
|
|
2184
2327
|
// Grok 자격은 전용 Secret 키 하나로만 보낸다 — passEnv 의 API 키 중복 전달은 막는다.
|
|
2185
|
-
const passKeys = [...new Set([...(options.passEnv ?? []), ...(
|
|
2328
|
+
const passKeys = [...new Set([...(options.passEnv ?? []), ...(openrouterCredentialRequired ? ['OPENROUTER_API_KEY'] : []), ...(openGateway ? ['OPENGATEWAY_API_KEY'] : []), ...(anthropic ? ['ANTHROPIC_API_KEY'] : [])])].filter((key) => key !== 'ELANOUS_LIVE_DETAIL_UNTIL'
|
|
2186
2329
|
&& key !== POD_GITHUB_CREDENTIAL_TOKEN_ENV && key !== POD_GITHUB_CREDENTIAL_URL_ENV
|
|
2187
2330
|
&& (!grok || !['XAI_API_KEY', 'GROK_API_KEY', 'GROK_CODE_XAI_API_KEY'].includes(key)));
|
|
2188
2331
|
const skillEnvs: Record<string, string> = options.skillEnv
|
|
@@ -2307,6 +2450,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2307
2450
|
if (key.startsWith('ELANOUS_PROMPT_ENHANCE_') && key !== 'ELANOUS_PROMPT_ENHANCE_MODEL' && key !== 'ELANOUS_PROMPT_ENHANCE_EFFORT') delete hostAuthorEnv[key];
|
|
2308
2451
|
}
|
|
2309
2452
|
let authorChoice = authorOnPod ? selectEnhanceLlm({ config: (options.authorConfig ?? getUserConfig)() }, hostAuthorEnv) : undefined;
|
|
2453
|
+
// A named child model is this launch's model when planning has no explicit choice.
|
|
2454
|
+
// Relay it to authoring too: the Pod's persistent grounding goal loop otherwise
|
|
2455
|
+
// receives the host's default "better" model and silently spends sol for a luna child.
|
|
2456
|
+
const namedChildModel = podDelegatedChildLlm(jobArgs)?.model;
|
|
2457
|
+
if (authorChoice?.modelSource === 'default' && namedChildModel) {
|
|
2458
|
+
authorChoice = { ...authorChoice, model: namedChildModel, modelSource: 'child' };
|
|
2459
|
+
}
|
|
2310
2460
|
let authorFallbackReason: string | undefined;
|
|
2311
2461
|
let authorRequestedModel: string | undefined;
|
|
2312
2462
|
let authorRequestedSource: string | undefined;
|
|
@@ -2328,8 +2478,10 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2328
2478
|
authorChoice = { ...authorChoice, model: childModel, modelSource: 'fallback-child' };
|
|
2329
2479
|
} else debug.log('self-implement.pod', 'role-llm-armed', { job: name, role: 'planning', model: authorChoice.model, source: authorChoice.modelSource, account: roleCodexAccount });
|
|
2330
2480
|
}
|
|
2331
|
-
const hostKey = (k: string): string | undefined => k === 'OPENROUTER_API_KEY' &&
|
|
2332
|
-
const
|
|
2481
|
+
const hostKey = (k: string): string | undefined => k === 'OPENROUTER_API_KEY' && openrouterCredentialRequired ? openrouterKey : k === 'OPENGATEWAY_API_KEY' && openGateway ? openGatewayKey : k === 'ANTHROPIC_API_KEY' && anthropic ? anthropicKey : env[k] ?? (options.readKeyCache ?? defaultReadKeyCache)(k);
|
|
2482
|
+
const hostConfig = (options.fallbackConfig ?? getUserConfig)();
|
|
2483
|
+
const hostFallbackNames = hostConfig.llm.fallbackChain;
|
|
2484
|
+
const zaiOverage = zaiLaunchOverage ?? zaiSettingsFromConfig(hostConfig.llm).overage;
|
|
2333
2485
|
const normalizedFallback = normalizeFallbackChain(hostFallbackNames);
|
|
2334
2486
|
let fallbackSteps = normalizedFallback.chain;
|
|
2335
2487
|
let zaiFallbackSpec: ZaiPodSpec | undefined;
|
|
@@ -2381,7 +2533,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2381
2533
|
? Object.fromEntries(codexCredentials.map((candidate, i) => [`codex-${i}.json`, JSON.stringify({ elanousAuth: candidate.elanousAuth, codexAuth: candidate.codexAuth })]))
|
|
2382
2534
|
: { 'elanous-auth.json': (creds as ReturnType<typeof hostCredentials>).elanousAuth, 'codex-auth.json': (creds as ReturnType<typeof hostCredentials>).codexAuth }),
|
|
2383
2535
|
'gh-token': podGhToken, feature: input.feature,
|
|
2384
|
-
'llm-fallback-config.json': JSON.stringify({ llm: { fallbackChain: fallbackChain.steps } }),
|
|
2536
|
+
'llm-fallback-config.json': JSON.stringify({ llm: { fallbackChain: fallbackChain.steps, zaiCodingPlan: { overage: zaiOverage } }, harness: { worktreeAddTimeoutSec: worktreeAddTimeoutSec(hostConfig.harness?.worktreeAddTimeoutSec) ?? 1200 } }),
|
|
2385
2537
|
...(goalDocument !== undefined ? { 'goal-doc': goalDocument } : {}),
|
|
2386
2538
|
...Object.fromEntries(Object.entries(skillEnvs).map(([n, text]) => [`skillenv-${n}`, text])),
|
|
2387
2539
|
...(grounding ? { [`env-${GROUNDING_TOKEN_ENV}`]: grounding.token } : {}),
|
|
@@ -2448,6 +2600,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2448
2600
|
}
|
|
2449
2601
|
}
|
|
2450
2602
|
if (failedExisting) {
|
|
2603
|
+
captureFailedJob(liveChildRunId);
|
|
2451
2604
|
const pods = kubectl(['-n', namespace, 'get', 'pods', '-l', `job-name=${name}`, '-o', 'jsonpath={range .items[*]}{.metadata.creationTimestamp}{"\\t"}{range .status.containerStatuses[?(@.name=="child")]}{.state.terminated.reason}{"\\t"}{.state.terminated.exitCode}{end}{"\\n"}{end}']);
|
|
2452
2605
|
const latestPod = pods.status === 0 ? pods.stdout.trimEnd().split('\n').map((line) => line.split('\t'))
|
|
2453
2606
|
.filter(([created]) => created && !Number.isNaN(Date.parse(created)))
|
|
@@ -2723,6 +2876,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2723
2876
|
}
|
|
2724
2877
|
try {
|
|
2725
2878
|
appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-run', data: { childRunId: liveChildRunId, job: name, attempt: oomRetried ? 2 : 1, ...(goalFile ? { goalFile } : {}) } }, ledgerDir);
|
|
2879
|
+
appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-job-applied', data: { job: name, childRunId: liveChildRunId, jobUid: lifecycleJobUid, host: member?.sshHost ?? resolveHostId(env), context, namespace } }, ledgerDir);
|
|
2726
2880
|
if (lastPlacement) appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-placement', data: { job: name, childRunId: liveChildRunId, attempt: oomRetried ? 2 : 1, member: lastPlacement.member, kind: lastPlacement.kind, outcome: lastPlacement.outcome, preferred: lastPlacement.preferred, reason: lastPlacement.reason } }, ledgerDir);
|
|
2727
2881
|
appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-memory-selected', data: { job: name, childRunId: liveChildRunId, attempt: oomRetried ? 2 : 1, limit: memoryLimit, ...(appliedMemoryRequest ? { request: appliedMemoryRequest } : {}), tier: oomRetried ? retryTier : memoryTier, source: oomRetried ? 'oom-retry' : memorySource, reason: oomRetried ? 'OOMKilled' : memoryReason, declaredGoalType: selectedGoalType } }, ledgerDir);
|
|
2728
2882
|
if (oomRetried && retryFromChildRunId) appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-oom-retry', data: { attempt: 2, from: retryFromMemoryLimit ?? selectedMemoryLimit, to: memoryLimit, tier: retryTier, reason: 'OOMKilled', job: name, childRunId: liveChildRunId, fromChildRunId: retryFromChildRunId } }, ledgerDir);
|
|
@@ -2734,7 +2888,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2734
2888
|
}
|
|
2735
2889
|
writePodFragment({ spaceId: input.spaceId, context, namespace, job: name, inboxDir: POD_CONTROL_INBOX_DIR, ...(liveChildRunId === normalizeRunId(liveChildRunId) ? { runId: liveChildRunId } : {}), ...(parentRunId && normalizeRunId(parentRunId) === parentRunId ? { parentRunId } : {}) }, env);
|
|
2736
2890
|
recorded = true;
|
|
2737
|
-
debug.log('self-implement.pod', 'job-applied', { job: name, namespace, ...(member ? { context: member.context } : {}), image: jobImage, spaceId: input.spaceId, passEnv, ...(
|
|
2891
|
+
debug.log('self-implement.pod', 'job-applied', { job: name, namespace, ...(member ? { context: member.context } : {}), image: jobImage, spaceId: input.spaceId, passEnv, ...(openrouterCredentialRequired ? { openrouterKeyPresent: passEnv.includes('OPENROUTER_API_KEY') } : {}), ...(openGateway ? { openGatewayKeyPresent: passEnv.includes('OPENGATEWAY_API_KEY') } : {}), ...(anthropic ? { anthropicKeyPresent: passEnv.includes('ANTHROPIC_API_KEY') } : {}), ...(bedrockSpec ? { bedrockSecret: bedrockSpec.secretName, bedrockSecretKeys: bedrockSpec.keys, bedrockRegionFrom: bedrockSpec.region.from } : {}), ...(zaiRoute ? { zaiRoute, ...(zaiSpec ? { zaiSecret: zaiSpec.secretName } : {}) } : {}), extraArgs: options.extraArgs ?? [], ...(options.armEnv?.ELANOUS_ARM_ID ? { armId: options.armEnv.ELANOUS_ARM_ID } : {}) });
|
|
2738
2892
|
let state: 'complete' | 'failed' | 'aborted' = 'failed';
|
|
2739
2893
|
let failedReason = '';
|
|
2740
2894
|
let containerReason: string | null = null;
|
|
@@ -2742,10 +2896,33 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2742
2896
|
// JOB-FAILURE-TERMINATION-CAPTURE — this Job's Kubernetes facts, read once at the failure verdict (before GC).
|
|
2743
2897
|
// Observation only: failedReason · containerReason · containerExitCode keep driving the classification.
|
|
2744
2898
|
let podTermination: PodTermination | null = null;
|
|
2899
|
+
const refreshPodTermination = async (): Promise<void> => {
|
|
2900
|
+
if (state !== 'failed' || !podTermination || (podTermination.podLookup === 'terminated'
|
|
2901
|
+
&& podTermination.containerReason !== 'unknown' && podTermination.exitCode !== 'unknown'
|
|
2902
|
+
&& podTermination.finishedAt !== 'unknown')) return;
|
|
2903
|
+
// The result marker and the Job Failed condition can precede container termination status.
|
|
2904
|
+
// Re-read this launch's Pod once; keep the verdict's Job facts even if the Job has since been GC'd.
|
|
2905
|
+
await sleep(1_000);
|
|
2906
|
+
const retry = readPodTermination({ kubectl, namespace, job: name, path: podTermination.path,
|
|
2907
|
+
jobUid: lifecycleJobUid, jobRead: null });
|
|
2908
|
+
const observed = retry.podLookup === 'unavailable' ? podTermination : retry;
|
|
2909
|
+
const complete = observed.podLookup === 'terminated' && observed.containerReason !== 'unknown'
|
|
2910
|
+
&& observed.exitCode !== 'unknown' && observed.finishedAt !== 'unknown';
|
|
2911
|
+
const collectionFailureReason: PodTermination['collectionFailureReason'] | undefined = complete ? undefined
|
|
2912
|
+
: retry.podLookup === 'unavailable' ? 'pod-read-unavailable-after-retry'
|
|
2913
|
+
: retry.podLookup === 'absent' ? 'pod-absent-after-retry'
|
|
2914
|
+
: retry.podLookup === 'running' || retry.podLookup === 'pending' ? 'pod-still-running-after-retry'
|
|
2915
|
+
: retry.podLookup === 'terminated' ? 'terminated-fields-missing-after-retry'
|
|
2916
|
+
: 'pod-state-unknown-after-retry';
|
|
2917
|
+
podTermination = { ...podTermination, observedAt: retry.observedAt,
|
|
2918
|
+
podLookup: observed.podLookup, containerReason: observed.containerReason, exitCode: observed.exitCode,
|
|
2919
|
+
finishedAt: observed.finishedAt, oomKilled: observed.oomKilled, collectionAttempts: 2,
|
|
2920
|
+
...(collectionFailureReason ? { collectionFailureReason } : {}) };
|
|
2921
|
+
};
|
|
2745
2922
|
// METER-POD-ROLLUP-GAP — abort 때 Job 삭제 «전»에 거둔 로그 사본(삭제 뒤엔 PARTIAL 줄도 못 읽는다).
|
|
2746
2923
|
let abortLogs = '';
|
|
2747
2924
|
// ⭐ 런 «도중» 원장 증분 회수 — 호스트 슈퍼바이저가 Pod 걸음을 실시간으로 본다(🅣 요청 · 힐 루프 runtime 성형의 전제).
|
|
2748
|
-
const follower = createPodLedgerFollower({ runId: liveChildRunId, dir: ledgerDir, exec: (script) => kubectl(['-n', namespace, 'exec', `job/${name}`, '-c', 'child', '--', 'sh', '-c', script]) });
|
|
2925
|
+
const follower = createPodLedgerFollower({ runId: liveChildRunId, dir: ledgerDir, now, exec: (script) => kubectl(['-n', namespace, 'exec', `job/${name}`, '-c', 'child', '--', 'sh', '-c', script]) });
|
|
2749
2926
|
// ⭐ METER-POD-ROLLUP-GAP-3 — 런 «도중» 마지막 PARTIAL 줄을 호스트가 쥔다: Pod 가 지워지면(SIGTERM 등) 종료 로그에서 PARTIAL 이 사라진다.
|
|
2750
2927
|
let livePartialLine: string | null = null;
|
|
2751
2928
|
let pollsSinceCapture = 0;
|
|
@@ -2774,6 +2951,10 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2774
2951
|
const capturePolls = Math.max(1, options.usagePartialCapturePolls ?? Math.round(POD_USAGE_PARTIAL_CAPTURE_MS / Math.max(1, options.pollMs ?? 15_000)));
|
|
2775
2952
|
const markerWait = markerToken ? await import('./pod-result-marker-wait.js') : null;
|
|
2776
2953
|
const waitStartedAt = Date.now();
|
|
2954
|
+
let consecutiveJobNotFound = 0;
|
|
2955
|
+
let podVanished = false;
|
|
2956
|
+
let unmeasurableSince: number | null = null;
|
|
2957
|
+
let unmeasurableIncidentRecorded = false;
|
|
2777
2958
|
for (;;) {
|
|
2778
2959
|
if (input.signal?.aborted) {
|
|
2779
2960
|
recordPodImage(true);
|
|
@@ -2788,6 +2969,32 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2788
2969
|
}
|
|
2789
2970
|
if (!imageSnapshotRecorded) recordPodImage(false);
|
|
2790
2971
|
const g = kubectl(['-n', namespace, 'get', 'job', name, '-o', 'jsonpath={.status.conditions[*].type}']);
|
|
2972
|
+
if (g.status !== 0) {
|
|
2973
|
+
// A transport/5xx error says nothing about Job existence. Only Kubernetes Job NotFound counts.
|
|
2974
|
+
const jobNotFound = /\(NotFound\)/i.test(g.stderr) || /\bjobs?(?:\.batch)?\b[^\n]*\bnot found\b/i.test(g.stderr);
|
|
2975
|
+
consecutiveJobNotFound = jobNotFound ? consecutiveJobNotFound + 1 : 0;
|
|
2976
|
+
unmeasurableSince = null;
|
|
2977
|
+
if (consecutiveJobNotFound >= 3) {
|
|
2978
|
+
state = 'failed';
|
|
2979
|
+
failedReason = 'JobNotFound';
|
|
2980
|
+
podVanished = true;
|
|
2981
|
+
const facts = { job: name, childRunId: liveChildRunId, class: 'pod-vanished', consecutiveNotFound: consecutiveJobNotFound };
|
|
2982
|
+
debug.log('self-implement.pod', 'pod-vanished', facts, { level: 'error' });
|
|
2983
|
+
try {
|
|
2984
|
+
recordRunStop({ runId: ledgerRunId, class: 'pod-vanished', site: 'pod-job-poll',
|
|
2985
|
+
cause: `Job ${name} NotFound on ${consecutiveJobNotFound} consecutive polls`,
|
|
2986
|
+
evidenceRef: `run-ledger:${ledgerRunId}:pod-job-applied`,
|
|
2987
|
+
nextMove: 'Inspect Job deletion and child artifacts before relaunch' },
|
|
2988
|
+
(entry) => appendRunLedgerEntry(entry, ledgerDir));
|
|
2989
|
+
} catch (error) {
|
|
2990
|
+
debug.log('self-implement.pod', 'pod-vanished-ledger-unavailable', { ...facts, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
|
|
2991
|
+
}
|
|
2992
|
+
break;
|
|
2993
|
+
}
|
|
2994
|
+
await sleep(options.pollMs ?? 15_000);
|
|
2995
|
+
continue;
|
|
2996
|
+
}
|
|
2997
|
+
consecutiveJobNotFound = 0;
|
|
2791
2998
|
const types = g.stdout;
|
|
2792
2999
|
if (/Complete|SuccessCriteriaMet/.test(types)) { releaseAdmission?.observed?.(); state = 'complete'; break; }
|
|
2793
3000
|
if (/Failed|FailureTarget/.test(types)) {
|
|
@@ -2798,7 +3005,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2798
3005
|
let jobReadError: unknown;
|
|
2799
3006
|
try { jobRead = kubectl(['-n', namespace, 'get', 'job', name, '-o', `jsonpath=${POD_TERMINATION_JOB_JSONPATH}`]); }
|
|
2800
3007
|
catch (error) { jobReadError = error; }
|
|
2801
|
-
|
|
3008
|
+
const observedJobReason = jobRead?.status === 0 ? podJobConditionReason(jobRead.stdout.split('\t')[0]) : 'unknown';
|
|
3009
|
+
failedReason = observedJobReason === 'unknown' ? '' : observedJobReason;
|
|
2802
3010
|
// One Pods read serves both: its first three columns are the classification layout, the rest the termination capture.
|
|
2803
3011
|
let podsRead: { status: number | null; stdout: string } | null = null;
|
|
2804
3012
|
try {
|
|
@@ -2817,8 +3025,11 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2817
3025
|
} catch { /* Pod 가 사라졌거나 조회 불가 — 종료 사유는 미상. */ }
|
|
2818
3026
|
debug.log('self-implement.pod', 'container-terminated', { job: name, container: 'child', reason: containerReason, exitCode: containerExitCode, jobReason: failedReason || null, memoryLimit });
|
|
2819
3027
|
podTermination = readPodTermination({ kubectl, namespace, job: name, path: 'job-failed-condition', jobRead, podsRead, jobUid: lifecycleJobUid });
|
|
3028
|
+
// Keep the verdict's single Job read authoritative; collecting files may re-read a Job that GC has removed.
|
|
3029
|
+
captureFailedJob(liveChildRunId);
|
|
2820
3030
|
if (jobReadError !== undefined) {
|
|
2821
3031
|
// Today's outcome stays (the throw ends the spawn as pod-error); the capture is in the ledger first.
|
|
3032
|
+
await refreshPodTermination();
|
|
2822
3033
|
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-evidence', data: { childEvidence: null, childRunId: liveChildRunId, job: name, podTermination } }, ledgerDir); }
|
|
2823
3034
|
catch (error) { debug.log('self-implement.pod', 'child-evidence-write-failed', { job: name, childRunId: liveChildRunId, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
|
|
2824
3035
|
debug.log('self-implement.pod', 'pod-termination-captured', { job: name, podTermination, jobReadThrew: true }, { level: 'warn' });
|
|
@@ -2836,6 +3047,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2836
3047
|
// The child's own rc (the Pod's terminated state may lag like the condition) — exit-code paths read it as before.
|
|
2837
3048
|
if (seen !== 0) containerExitCode = seen;
|
|
2838
3049
|
if (seen !== 0) podTermination = readPodTermination({ kubectl, namespace, job: name, path: 'result-marker', jobUid: lifecycleJobUid });
|
|
3050
|
+
if (seen !== 0) captureFailedJob(liveChildRunId);
|
|
2839
3051
|
debug.log('self-implement.pod', 'result-marker-early', { job: name, waitedMs: Date.now() - waitStartedAt, rc: seen });
|
|
2840
3052
|
break;
|
|
2841
3053
|
}
|
|
@@ -2863,7 +3075,19 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2863
3075
|
debug.log('self-implement.pod', 'gh-token-refresh-failed', { job: name, reason: 'mint-verification-or-exec-failed' });
|
|
2864
3076
|
}
|
|
2865
3077
|
}
|
|
2866
|
-
|
|
3078
|
+
let measurement = { ledgerRead: false, activityMeasured: false };
|
|
3079
|
+
try { measurement = follower.poll(); } catch (e) { debug.log('self-implement.pod', 'ledger-live-unavailable', { job: name, reason: e instanceof Error ? e.message : String(e) }); }
|
|
3080
|
+
if (!measurement.ledgerRead && !measurement.activityMeasured) {
|
|
3081
|
+
unmeasurableSince ??= now();
|
|
3082
|
+
const unmeasurableMs = Math.max(0, now() - unmeasurableSince);
|
|
3083
|
+
if (!unmeasurableIncidentRecorded && unmeasurableMs >= 120 * 60_000) {
|
|
3084
|
+
unmeasurableIncidentRecorded = true;
|
|
3085
|
+
const incident = { job: name, childRunId: liveChildRunId, unmeasurableMs, jobStatus: 'alive', ledgerRead: false, activityMeasured: false };
|
|
3086
|
+
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-stall-unmeasurable-incident', data: incident }, ledgerDir); }
|
|
3087
|
+
catch (error) { debug.log('self-implement.pod', 'pod-stall-incident-ledger-unavailable', { job: name, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
|
|
3088
|
+
debug.log('self-implement.pod', 'pod-stall-unmeasurable-incident', incident, { level: 'warn' });
|
|
3089
|
+
}
|
|
3090
|
+
} else unmeasurableSince = null;
|
|
2867
3091
|
if (++pollsSinceCapture >= capturePolls) {
|
|
2868
3092
|
pollsSinceCapture = 0;
|
|
2869
3093
|
try {
|
|
@@ -2878,6 +3102,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2878
3102
|
}
|
|
2879
3103
|
await sleep(options.pollMs ?? 15_000);
|
|
2880
3104
|
}
|
|
3105
|
+
await refreshPodTermination();
|
|
2881
3106
|
if (!terminalImageRecorded) recordPodImage(true);
|
|
2882
3107
|
let logs = '';
|
|
2883
3108
|
let logTailReason: string | undefined;
|
|
@@ -2891,6 +3116,14 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2891
3116
|
if (!logs && abortLogs) logs = abortLogs;
|
|
2892
3117
|
// TA-POD-WARMBOOT-PARITY: the marker line is not child output — remove it so the last-line result parse sees the same bytes.
|
|
2893
3118
|
if (markerWait && markerToken && logs) logs = markerWait.stripPodResultMarker(logs, markerToken);
|
|
3119
|
+
const deadlineMarker = podDeadlineResultMarker(logs, name, liveChildRunId);
|
|
3120
|
+
if (deadlineMarker && state !== 'aborted' && state !== 'complete') {
|
|
3121
|
+
state = 'failed';
|
|
3122
|
+
failedReason = 'DeadlineExceeded';
|
|
3123
|
+
debug.log('self-implement.pod', 'deadline-result-marker', { job: name, childRunId: liveChildRunId, ...deadlineMarker });
|
|
3124
|
+
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-deadline-result', data: { job: name, childRunId: liveChildRunId, stopCause: 'deadline', ...deadlineMarker } }, ledgerDir); }
|
|
3125
|
+
catch { /* A full ledger must not hide the Pod's terminal marker. */ }
|
|
3126
|
+
}
|
|
2894
3127
|
let ledgerReason = '';
|
|
2895
3128
|
let ledgerCollected = false;
|
|
2896
3129
|
const collection = collectFullLogs('ledger-collect-incomplete', follower.owned ? new Set([liveChildRunId]) : undefined, (event, data) => {
|
|
@@ -2950,7 +3183,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2950
3183
|
continue;
|
|
2951
3184
|
}
|
|
2952
3185
|
// Pod 안 경로는 호스트에서 쓸 수 없다.
|
|
2953
|
-
let disposition = parsed ? { ...parsed, worktreePath: undefined } :
|
|
3186
|
+
let disposition: SelfImplementDisposition | undefined = parsed ? { ...parsed, worktreePath: undefined } : deadlineMarker
|
|
3187
|
+
? { stage: 'deadline', ok: false, ...(deadlineMarker.pr ? { prNumber: deadlineMarker.pr } : {}), ...(deadlineMarker.branch ? { branch: deadlineMarker.branch } : {}) }
|
|
3188
|
+
: undefined;
|
|
2954
3189
|
if (options.repairCommitOnly && state === 'complete' && !repairArtifactReady) {
|
|
2955
3190
|
disposition = { ...disposition, worktreePath: undefined, ok: false, stage: 'repair-artifact-missing', detail: 'Pod repair result or bundle was not collected' };
|
|
2956
3191
|
}
|
|
@@ -3082,25 +3317,37 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3082
3317
|
}
|
|
3083
3318
|
let noResultDiagnostic: string | null = null;
|
|
3084
3319
|
// POD-NORESULT: a terminal Job without a parsed disposition is incomplete even when the Job condition says Complete.
|
|
3085
|
-
const noResultCandidate = !disposition && !oomKilled && failedReason !== 'DeadlineExceeded' &&
|
|
3320
|
+
const noResultCandidate = !podVanished && !disposition && !oomKilled && failedReason !== 'DeadlineExceeded' &&
|
|
3086
3321
|
(state === 'complete' || (state === 'failed' && containerExitCode !== 0));
|
|
3087
3322
|
if (noResultCandidate) {
|
|
3088
3323
|
try { noResultDiagnostic = podNoResultDiagnostic(readFileSync(runLedgerPath(liveChildRunId, ledgerDir), 'utf8')); }
|
|
3089
3324
|
catch { /* ledger not returned: do not invent a stage */ }
|
|
3090
3325
|
noResultDiagnostic ??= 'child terminal result missing; last ledger stage=unknown; round=unknown; mustFix=unknown';
|
|
3091
3326
|
}
|
|
3092
|
-
// POD-
|
|
3093
|
-
//
|
|
3094
|
-
//
|
|
3327
|
+
// POD-FAIL-EVIDENCE-CAPTURE: failed Pods are collected/deleted immediately after terminal handling.
|
|
3328
|
+
// Preserve a bounded log tail for every non-OOM/non-deadline failure, including known child stages:
|
|
3329
|
+
// the terminal result line can be followed by the useful stderr that explains the actual exit.
|
|
3095
3330
|
let noResultLogEvidence: Record<string, unknown> | null = null;
|
|
3096
|
-
|
|
3331
|
+
const shouldCaptureFailureLog = state === 'failed' && !oomKilled && failedReason !== 'DeadlineExceeded';
|
|
3332
|
+
const missingStage = noResultDiagnostic?.includes('stage=unknown') ?? false;
|
|
3333
|
+
if (shouldCaptureFailureLog || missingStage) {
|
|
3097
3334
|
const logRead = readPodNoResultLogTail({ run: kubectl, namespace, job: name, maxLines: POD_NO_RESULT_LOG_TAIL_LINES });
|
|
3098
3335
|
if ('tail' in logRead) {
|
|
3099
|
-
noResultLogEvidence =
|
|
3100
|
-
|
|
3336
|
+
noResultLogEvidence = missingStage
|
|
3337
|
+
? { stderr: logRead.tail.join('\n'), logTail: logRead.tail, logTailLines: logRead.tail.length }
|
|
3338
|
+
: { podLogTail: logRead.tail, podLogTailLines: logRead.tail.length };
|
|
3339
|
+
debug.log('self-implement.pod', missingStage ? 'no-result-log-tail' : 'failed-pod-log-tail', {
|
|
3340
|
+
job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic, lines: logRead.tail.length, logTail: logRead.tail,
|
|
3341
|
+
}, { compact: { stringMax: 500 } });
|
|
3101
3342
|
} else {
|
|
3102
|
-
|
|
3103
|
-
|
|
3343
|
+
const unavailable = `log-unavailable: ${logRead.unavailable}`;
|
|
3344
|
+
noResultLogEvidence = missingStage
|
|
3345
|
+
? { stderr: unavailable }
|
|
3346
|
+
: { podLogUnavailable: logRead.unavailable };
|
|
3347
|
+
debug.log('self-implement.pod', missingStage ? 'no-result-log-tail' : 'failed-pod-log-tail', {
|
|
3348
|
+
job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic,
|
|
3349
|
+
logUnavailable: missingStage ? unavailable : logRead.unavailable,
|
|
3350
|
+
}, { level: 'warn' });
|
|
3104
3351
|
}
|
|
3105
3352
|
}
|
|
3106
3353
|
if (childFailure) debug.log('self-implement.pod', 'child-error', { job: name, stage: childFailure.stage, error: childFailure.error, ...(childPrFailure ?? {}) }, { compact: { stringMax: 500 } });
|
|
@@ -3192,7 +3439,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3192
3439
|
appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-oom-retry-finished', data: { job: name, executionKey, fromChildRunId: retryFromChildRunId, childRunId: liveChildRunId, state } }, ledgerDir);
|
|
3193
3440
|
}
|
|
3194
3441
|
if (goalFile) {
|
|
3195
|
-
const noResultOutcome = state === 'failed' && containerExitCode !== null && noResultDiagnostic ? 'abandoned' : 'pod-no-result';
|
|
3442
|
+
const noResultOutcome = podVanished || (state === 'failed' && containerExitCode !== null && noResultDiagnostic) ? 'abandoned' : 'pod-no-result';
|
|
3196
3443
|
const record: GoalExecutionRecord = {
|
|
3197
3444
|
runId: liveChildRunId,
|
|
3198
3445
|
stage: (state === 'aborted' || !disposition ? 'aborted' : disposition.stage) as GoalExecutionRecord['stage'],
|
|
@@ -3209,7 +3456,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3209
3456
|
if (state === 'failed' || state === 'aborted' || noResultLogEvidence || (state === 'complete' && noResultDiagnostic !== null)) {
|
|
3210
3457
|
// Every terminal attempt writes a marker, including one with no parseable child facts.
|
|
3211
3458
|
// The next attempt must never inherit an earlier Pod's classification.
|
|
3212
|
-
const childEvidence = noResultLogEvidence
|
|
3459
|
+
const childEvidence = noResultLogEvidence
|
|
3460
|
+
? { ...(disposition?.childEvidence ?? {}), ...noResultLogEvidence }
|
|
3461
|
+
: disposition?.childEvidence ?? null;
|
|
3213
3462
|
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-evidence', data: { childEvidence, childRunId: liveChildRunId, job: name, ...(podTermination ? { podTermination } : {}) } }, ledgerDir); }
|
|
3214
3463
|
catch (error) { debug.log('self-implement.pod', 'child-evidence-write-failed', { job: name, childRunId: liveChildRunId, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
|
|
3215
3464
|
}
|
|
@@ -3218,7 +3467,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3218
3467
|
if (disposition && (state === 'failed' || state === 'aborted' || disposition.ok === false)
|
|
3219
3468
|
&& (!Number.isSafeInteger(disposition.prNumber) || (disposition.prNumber ?? 0) <= 0) && terminalBranch) {
|
|
3220
3469
|
try { prLookup = await (options.lookupOpenPrByBranch ?? defaultLookupOpenPrByBranch)(terminalBranch, repoUrl); }
|
|
3221
|
-
catch { prLookup = { status: 'failed', reason:
|
|
3470
|
+
catch (error) { prLookup = { status: 'failed', reason: `pr-lookup-failed: ${error instanceof Error ? error.message : String(error)}`.slice(0, 200) }; }
|
|
3222
3471
|
}
|
|
3223
3472
|
const terminalDisposition = prLookup?.status === 'found' && disposition
|
|
3224
3473
|
? { ...disposition, prNumber: prLookup.prNumber, prUrl: prLookup.prUrl } : disposition;
|
|
@@ -3262,7 +3511,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3262
3511
|
: disposition;
|
|
3263
3512
|
// A gate environment deficit can exit the child with 1 while still yielding a
|
|
3264
3513
|
// verified repair bundle. The host rejudges the new PR head after CAS apply.
|
|
3265
|
-
const podExitCode = repairPodExitCode({ state, repairCommitOnly: !!options.repairCommitOnly,
|
|
3514
|
+
const podExitCode = podVanished ? 1 : repairPodExitCode({ state, repairCommitOnly: !!options.repairCommitOnly,
|
|
3266
3515
|
repairArtifactReady, disposition });
|
|
3267
3516
|
// SCHED-CONTRACT: a failed child must say why outside the Pod, not «no error diagnostic».
|
|
3268
3517
|
const rawPodReason = podExitCode === 1 ? extractPodFailureReason({ logs, logTailReason, containerReason, jobReason: failedReason || undefined, deadlineSeconds, result: disposition ? { stage: disposition.stage, prUrl: disposition.prUrl ?? null, prNumber: disposition.prNumber ?? null } : null }) : undefined;
|
|
@@ -3276,10 +3525,18 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3276
3525
|
const salvageOutcome = /^ELANOUS_POD_SALVAGE \S+ \S+$/m.test(logs) ? 'pushed' : logs.includes('ELANOUS_POD_SALVAGE_NONE') ? 'none' : 'unknown';
|
|
3277
3526
|
passJourneyNode('salvage', { provenance: 'self-implement-pod', outcome: salvageOutcome, data: { job: name } });
|
|
3278
3527
|
}
|
|
3528
|
+
const repairGateReceipt = disposition?.stage === 'gate-failed' ? gateFailureReceipt(disposition.gate) : null;
|
|
3529
|
+
if (repairGateReceipt) {
|
|
3530
|
+
for (const line of gateFailureReceiptLines(repairGateReceipt)) console.log(line);
|
|
3531
|
+
debug.log('self-implement.pod', 'gate-failure-receipt', { job: name, childRunId: liveChildRunId,
|
|
3532
|
+
signature: repairGateReceipt.signature, tests: repairGateReceipt.tests });
|
|
3533
|
+
}
|
|
3279
3534
|
return {
|
|
3280
3535
|
exitCode: podExitCode,
|
|
3281
3536
|
output: tail,
|
|
3282
|
-
...(
|
|
3537
|
+
...(podVanished
|
|
3538
|
+
? { error: { code: 'pod-vanished', message: `Job ${name} disappeared after 3 consecutive NotFound polls` } }
|
|
3539
|
+
: deadlineExceeded
|
|
3283
3540
|
? { error: { code: 'pod-deadline-exceeded', message: `Job ${name} 이 수명 상한 ${deadlineSeconds}초에 닿았다` } }
|
|
3284
3541
|
: state === 'failed'
|
|
3285
3542
|
? containerExitCode === 7
|
|
@@ -3429,7 +3686,9 @@ export function podNoResultLogTailLines(source: string, maxLines: number = POD_N
|
|
|
3429
3686
|
let chars = 0;
|
|
3430
3687
|
for (const line of lines.slice(-Math.max(0, maxLines)).reverse()) {
|
|
3431
3688
|
if (chars >= POD_NO_RESULT_LOG_TAIL_MAX_CHARS) break;
|
|
3432
|
-
const
|
|
3689
|
+
const redacted = redactSecretText(line);
|
|
3690
|
+
const limit = Math.min(POD_NO_RESULT_LOG_TAIL_LINE_CHARS, POD_NO_RESULT_LOG_TAIL_MAX_CHARS - chars);
|
|
3691
|
+
const bounded = redacted.length > limit ? `${redacted.slice(0, limit)}…[truncated]` : redacted;
|
|
3433
3692
|
if (!bounded) continue;
|
|
3434
3693
|
result.push(bounded);
|
|
3435
3694
|
chars += bounded.length;
|
|
@@ -3451,7 +3710,7 @@ export function readPodNoResultLogTail(args: {
|
|
|
3451
3710
|
}): PodNoResultLogRead {
|
|
3452
3711
|
const maxLines = args.maxLines ?? POD_NO_RESULT_LOG_TAIL_LINES;
|
|
3453
3712
|
try {
|
|
3454
|
-
const result = args.run(['-n', args.namespace, 'logs', `job/${args.job}`, `--tail=${maxLines}`]);
|
|
3713
|
+
const result = args.run(['-n', args.namespace, 'logs', `job/${args.job}`, '-c', 'child', `--tail=${maxLines}`]);
|
|
3455
3714
|
if (result.status !== 0) {
|
|
3456
3715
|
const reason = boundedPodLogText(result.stderr || result.stdout || '', POD_NO_RESULT_LOG_REASON_MAX_CHARS);
|
|
3457
3716
|
return { unavailable: reason || `kubectl logs exit ${result.status}` };
|