elanous 0.2.38 → 0.2.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → GiOLWmt4MqDZePubBjA4Q}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +149 -0
- package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +36 -0
- package/apps/pwa/out/_next/static/chunks/1178.1aa9cad0e7695427.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1197-54da59d250a6e476.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5203.51e5d8b5f1dcfe53.js → 1219.7e17964e0e7cd8e5.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +287 -0
- package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +90 -0
- package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7573.2376e13c9c21f1f8.js → 1765.679b29625c8e88d4.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{3528.e4b8ab70d339f965.js → 1800.f7ff51dc4978a958.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2073.689dcb2680113d76.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +1 -0
- package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8879.ac06755bcf3e44a1.js → 2263.e09b6edea33bad2d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2743.5d3f76948be32b34.js +41 -0
- package/apps/pwa/out/_next/static/chunks/2773.0e80b9d325fb5635.js +32 -0
- package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9fe1b809.738da85c8b17e3fb.js → 2fdf2931.b431eee4fb468bc3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{eaad0cba.771200940c529df7.js → 2fe2c302.41b517f88d6fe502.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3097.864e92bdaa2f4d15.js +79 -0
- package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3230-49298c3b73ef2268.js +1 -0
- package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +74 -0
- package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b7478fef.5917716286213fcc.js → 385e4574.e9886ab32759eda3.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4133.2056bb4d78f621af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4156.ba4de4a3664f04b4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +148 -0
- package/apps/pwa/out/_next/static/chunks/{8911.bf5e712acb25fb6c.js → 4527.a69f2894d1bc9f4a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{5307.d7328020227880c2.js → 4667.97e31aa38c95c475.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/{6142.913b44e260a3f925.js → 4702.4a4adc1f16d7c93b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +94 -0
- package/apps/pwa/out/_next/static/chunks/{8487.291666583bebe640.js → 5159.115f1c2ca471386c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/530.d26346e18089640a.js +115 -0
- package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{89d6c04f-6b8ab341748e468a.js → 53aeb4ee-51c92f8d683f5220.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3291.f6c1005387d514bd.js → 5471.1e611302ed3a7c53.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3086.fb14b60ce98b53d3.js → 5574.f35accf4f132b29d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{1632.7d87f998e714bede.js → 5744.b9415e18ad623100.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5300.677c97e0393742e6.js → 5892.2526d962339662d8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5937.c2df9e3447e1f667.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +286 -0
- package/apps/pwa/out/_next/static/chunks/{7161-8f22db3ec5ed005e.js → 5947-135e26537d80a6b9.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{3124-561f7f037943cde2.js → 5964-7e21164a8f2cf0ce.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +27 -0
- package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +62 -0
- package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +24 -0
- package/apps/pwa/out/_next/static/chunks/6874.d5cf7eb8edb2cabe.js +2 -0
- package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +122 -0
- package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2415.738b777642a02233.js → 7191.fdc955f7d96064a4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1026-44010f405704050c.js → 8050-9b364bdef8f71927.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/83184dcd-0ee6247ff41eb3f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +104 -0
- package/apps/pwa/out/_next/static/chunks/8464-e24f10451b658aac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8880.64c445592f04acaf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8981.c706964c8ba27aff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5638.107314dc479e2f37.js → 9048.212083de42d25be3.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8019.21ca554a821dad01.js → 9507.7026657a2f47eb64.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +93 -0
- package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9579.4a8169600fff2058.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{6493.27ad77de7aac7966.js → 9834.63ab2bbc3153172e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3389.012c70767a872f9b.js → 9869.81a1e24ca682d5a0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{8994d93e.33ba491f95345fc2.js → a0a01613.6d1cca322238d7fe.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{de8b930d.d94c0f42acf807fc.js → addc2b32.8c4ff8f0aefe987d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-866aac5ff226a7f3.js → page-14949db884bfa672.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-40f9e19149024298.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a142dfb0331a05f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/b2271e54.c1de3347976e90b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b7459770.6539b11860eb8a9c.js → c0c1a699.0ba79f97005965d4.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +22 -22
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +21 -21
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +22 -22
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +22 -22
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/bin/elanous.mjs +6 -1
- package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
- package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
- package/graphs/demo/persona-marketer/fixtures/marketer-scenario.yaml +10 -0
- package/graphs/demo/persona-marketer/persona-marketer.yaml +25 -0
- package/graphs/demo/persona-marketer/recipes.yaml +19 -0
- package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
- package/graphs/demo/persona-teacher/recipes.yaml +17 -0
- package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
- package/graphs/overlays/stop-heal-ladder.yaml +23 -2
- package/graphs/release/release-loop.yaml +3 -1
- package/graphs/units/gate/gate.yaml +20 -0
- package/graphs/units/git/git.yaml +26 -0
- package/graphs/units/implement/implement.yaml +19 -0
- package/graphs/units/landing/landing.yaml +18 -0
- package/graphs/units/review/review.yaml +20 -0
- package/graphs/units/verbs/recipes.yaml +3 -0
- package/graphs/units/verbs/research.yaml +20 -0
- package/graphs/video/explainer-line.yaml +4 -1
- package/graphs/work/research-report.yaml +11 -1
- package/package.json +1 -1
- package/scripts/dead-code/report.ts +169 -0
- package/scripts/disk-steward.ts +46 -0
- package/scripts/fleet/node-setup.sh +50 -0
- package/scripts/graph-units/verbs/research.ts +55 -0
- package/scripts/lib/morning-report-options.ts +3 -4
- package/scripts/lib/tui-regress-evidence.ts +56 -0
- package/scripts/llm-cost-ledger.ts +179 -8
- package/scripts/measure-nl-routing-corpus.ts +10 -2
- package/scripts/morning-report.ts +5 -1
- package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
- package/scripts/public-copy-lint.ts +163 -19
- package/scripts/public-export.ts +15 -7
- package/scripts/ratchets/train-side-invariants.sh +0 -1
- package/scripts/release-loop/export-check-node.ts +21 -3
- package/scripts/release-loop/gate-autoheal.ts +117 -0
- package/scripts/release-loop/gate-baseline-receipt.ts +8 -1
- package/scripts/release-loop/gate-diff.ts +22 -3
- package/scripts/release-loop/gate-node.ts +583 -64
- package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
- package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
- package/scripts/release-loop/gate-shard-receipts.ts +89 -0
- package/scripts/release-loop/gate-triage-node.ts +70 -10
- package/scripts/release-loop/gate-wall.ts +5 -5
- package/scripts/release-loop/preflight.ts +6 -2
- package/scripts/release-loop/resume-release.ts +267 -20
- package/scripts/release-loop/resume.ts +48 -0
- package/scripts/release-loop/traffic-node.ts +6 -3
- package/scripts/release-loop/unattended-release.ts +4 -2
- package/scripts/release-loop/version-node.ts +7 -2
- package/scripts/release-story/draft.ts +1 -1
- package/scripts/research-bench/README.md +53 -0
- package/scripts/research-bench/questions.json +66 -0
- package/scripts/research-bench/rubric.md +33 -0
- package/scripts/research-bench/run.ts +523 -0
- package/scripts/shadow-authoring-probe.ts +20 -0
- package/scripts/tui-regress.ts +85 -10
- package/scripts/ux-sim.ts +19 -2
- package/src/acp/core-turn-bridge.ts +94 -4
- package/src/agent/autonomous-tools.ts +10 -3
- package/src/agent/monad-agent-turn.ts +4 -1
- package/src/agent/registry.ts +26 -2
- package/src/agent/shared-app-tools.ts +1 -1
- package/src/agent/surface-ux/build.ts +12 -3
- package/src/agent/surface-ux/types.ts +1 -1
- package/src/agent/task-notification.ts +75 -6
- package/src/agent/types.ts +3 -0
- package/src/agent-mission/driver.ts +29 -3
- package/src/agent-mission/mission-cli.ts +2 -1
- package/src/agent-substrate/review-context-pack.ts +365 -0
- package/src/agent-substrate/self-review-cli.ts +291 -20
- package/src/ask-user-question/index.ts +6 -0
- package/src/ask-user-question/inline-resolver.ts +49 -0
- package/src/auto-research/question-ladder-contract.ts +22 -3
- package/src/auto-research/research-turn.ts +359 -17
- package/src/autopilot/agent-loop.ts +1 -1
- package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
- package/src/autopilot/pty-control-loop.ts +8 -1
- package/src/boot/daemon-tools/index.ts +4 -3
- package/src/boot/daemon-tools/self-implement.ts +312 -7
- package/src/boot/daemon-tools/types.ts +2 -0
- package/src/budget/llm-cost.ts +44 -5
- package/src/budget/shadow-arms.ts +52 -0
- package/src/budget/unified-usage.ts +17 -1
- package/src/capture/tui-self-report.ts +14 -0
- package/src/chat/index.ts +33 -7
- package/src/chat/pickers/state.ts +7 -1
- package/src/cli/agent-cli.ts +43 -8
- package/src/cli/intake-cli.ts +22 -1
- package/src/cli/lesson-cli.ts +19 -3
- package/src/cli/log-event-names.ts +6 -0
- package/src/cli/mcp-login.ts +8 -18
- package/src/cli/msg-cli.ts +57 -1
- package/src/cli/pod-cli.ts +17 -2
- package/src/cli/pr-land-heavy-remote.ts +15 -9
- package/src/cli/pty-takeover-cli.ts +67 -7
- package/src/cli/release-cli.ts +79 -7
- package/src/cli/repo-cli.ts +2 -1
- package/src/cli/sim-cli.ts +7 -1
- package/src/cli/tasks-cli.ts +41 -13
- package/src/codex/models.ts +30 -15
- package/src/control-plane/ledger.ts +21 -4
- package/src/core-turn/run-core-turn.ts +47 -3
- package/src/core-turn/run-goal-loop.ts +240 -10
- package/src/core-turn/types.ts +9 -0
- package/src/dashboard/acp-boot.ts +72 -3
- package/src/dashboard/chat/acp-chat.ts +2 -2
- package/src/dashboard/classic-sigquit.ts +16 -0
- package/src/dashboard/index.ts +327 -27
- package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
- package/src/dashboard/input/chat-main-slash-command.ts +7 -0
- package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
- package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
- package/src/dashboard/input/external-input-host.ts +2 -0
- package/src/dashboard/sidetab-runtime.ts +228 -0
- package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +20 -8
- package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
- package/src/dashboard/term-slash-runtime.ts +16 -18
- package/src/dashboard/turn-preamble.ts +14 -1
- package/src/disk-steward/judge.ts +73 -0
- package/src/disk-steward/ledger.ts +122 -0
- package/src/disk-steward/steward.ts +373 -0
- package/src/domains/guardian-tick.ts +191 -2
- package/src/domains/knowledge.ts +1 -1
- package/src/esc-abort-gate.ts +33 -1
- package/src/execution-loop/launch-gate.ts +206 -1
- package/src/graph-runner/graph-cli.ts +27 -4
- package/src/graph-runner/in-process-registry.ts +37 -0
- package/src/graph-runner/runner.ts +63 -11
- package/src/graph-wizard/generate.ts +16 -7
- package/src/graph-wizard/mission-compose.ts +201 -0
- package/src/grok/agent-search.ts +8 -2
- package/src/grok/credential.ts +5 -0
- package/src/grounding/ref-index.ts +30 -0
- package/src/grounding/ref-vector.ts +61 -0
- package/src/grounding/sources-cli.ts +11 -3
- package/src/grounding/sources.ts +15 -1
- package/src/harness/harness-cli-command.ts +305 -23
- package/src/harness/harness-incidents.ts +312 -7
- package/src/harness/harness-pod-dispatch.ts +7 -1
- package/src/harness/harness-space.ts +15 -1
- package/src/harness/progress-worker-entry.ts +59 -0
- package/src/harness/progress-worker-runtime.ts +11 -0
- package/src/index.ts +35 -5
- package/src/input/external-input-queue.ts +10 -0
- package/src/instance/dev-project.ts +25 -0
- package/src/intake-plane/collect-telegram-saved.ts +36 -1
- package/src/intake-plane/intake-to-tasks.ts +246 -3
- package/src/intelligence-map/model-alias.ts +6 -5
- package/src/intelligence-map/model-catalog.ts +59 -2
- package/src/lessons/friction-ledger.ts +154 -0
- package/src/live-supply/collector.ts +149 -0
- package/src/live-supply/probes.ts +52 -0
- package/src/live-supply/snapshot.ts +40 -0
- package/src/llm/model-defaults.ts +4 -4
- package/src/llm.ts +473 -87
- package/src/loops/orchestrator/tick.ts +56 -0
- package/src/mcp/mcp-oauth.ts +3 -1
- package/src/model-tier/llm-tier-map.ts +9 -9
- package/src/model-tier/turn-tier.ts +1 -1
- package/src/msg/msg-mirror-github.ts +80 -0
- package/src/msg/msg-mirror-policy.ts +61 -0
- package/src/msg/msg-mirror-runner.ts +219 -0
- package/src/msg/msg-mirror-state.ts +33 -0
- package/src/msg/msg-store.ts +11 -0
- package/src/nexus/api/harness-api.ts +2 -1
- package/src/output-truncation.ts +41 -12
- package/src/project/project-store.ts +48 -1
- package/src/pty/snapshot.py +132 -0
- package/src/pty-shell/pty-control-ipc.ts +29 -2
- package/src/pty-shell/pty-manifest.ts +59 -3
- package/src/pty-shell/registry.ts +2 -0
- package/src/pty-shell/tui-run-state.ts +80 -3
- package/src/release-loop/gate-host-reservation.ts +157 -4
- package/src/release-loop/gate-shard-ledger.ts +68 -0
- package/src/release-loop/merged-pr-checklist.ts +25 -2
- package/src/release-loop/rehearsal-shard-plan.ts +6 -1
- package/src/release-loop/rehearsal.ts +27 -0
- package/src/release-loop/release-schedule.ts +90 -1
- package/src/research/bloom-exemplars.ts +135 -0
- package/src/research/edge-decision.ts +124 -15
- package/src/research/gap-followup.ts +249 -0
- package/src/research/lenses/counter-evidence.ts +100 -0
- package/src/research/lenses/working-backwards.ts +89 -0
- package/src/research/plugin-discovery.ts +242 -0
- package/src/research-bridge/invoke.ts +4 -2
- package/src/research-bridge/types.ts +2 -0
- package/src/self-dev/ask-launch-flow.ts +73 -131
- package/src/self-dev/dev-cli.ts +19 -17
- package/src/self-dev/dev-pipeline.ts +8 -4
- package/src/self-dev/graph-front-nodes.ts +23 -0
- package/src/self-dev/graph-journey-route.ts +10 -2
- package/src/self-dev/launch-preflight-text.ts +2 -2
- package/src/self-dev/launch-preflight.ts +47 -11
- package/src/self-dev/orchestrate-cli.ts +1 -0
- package/src/self-dev/orchestrate.ts +15 -0
- package/src/self-dev/run-supervisor.ts +204 -3
- package/src/self-dev/run-types.ts +3 -0
- package/src/self-implement/device-first.ts +8 -2
- package/src/self-implement/doctor-visit.ts +76 -58
- package/src/self-implement/gate-artifacts.ts +16 -0
- package/src/self-implement/gate-baseline.ts +75 -4
- package/src/self-implement/gate-cli.ts +368 -30
- package/src/self-implement/gate-receipt-registry.ts +180 -0
- package/src/self-implement/gate-remote.ts +165 -24
- package/src/self-implement/goal-author-clarification.ts +205 -32
- package/src/self-implement/goal-author-decompose.ts +24 -15
- package/src/self-implement/goal-author.ts +86 -10
- package/src/self-implement/graph-stage-units.ts +172 -0
- package/src/self-implement/graph-templates.ts +162 -1
- package/src/self-implement/graph-variant.ts +37 -4
- package/src/self-implement/host-regate.ts +124 -49
- package/src/self-implement/impl-findings-feedback.ts +188 -0
- package/src/self-implement/knowhow-pack.ts +227 -10
- package/src/self-implement/off-diff-evidence.ts +124 -0
- package/src/self-implement/orchestrator.ts +320 -28
- package/src/self-implement/run-ledger.ts +110 -14
- package/src/self-implement/run-stop.ts +33 -2
- package/src/self-implement/running-runs.ts +35 -12
- package/src/self-implement/seams.ts +6 -3
- package/src/self-implement/self-implement-cli.ts +40 -6
- package/src/self-implement/stop-autoheal-operational.ts +43 -0
- package/src/self-implement/stop-autoheal.ts +15 -6
- package/src/session/chat.ts +66 -15
- package/src/session/request-size-guard.ts +123 -0
- package/src/session-runtime/provider-circuit.ts +140 -0
- package/src/shell-runner/file-engine.ts +1 -0
- package/src/shell-runner/types.ts +4 -0
- package/src/sidetab-core/model.ts +312 -0
- package/src/skills/tools/schedule-wakeup.ts +23 -1
- package/src/skills/tools/shell.ts +51 -5
- package/src/steward/directive-audit.ts +354 -0
- package/src/surface/child-process.ts +31 -0
- package/src/surface/tui-stderr-owner.ts +48 -0
- package/src/task-agent/cover.ts +30 -12
- package/src/task-agent/judge.ts +56 -0
- package/src/task-agent/parent-host.ts +14 -1
- package/src/task-agent/postland-card.ts +35 -2
- package/src/task-agent/rejudge-on-head.ts +46 -2
- package/src/task-agent/repair-cycle.ts +1 -1
- package/src/task-agent/task-hand.ts +133 -25
- package/src/task-agent/tier-split.ts +105 -21
- package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
- package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +70 -2
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
- package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
- package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +298 -45
- package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
- package/src/tool-runtime/skill-exec-runtime.ts +95 -5
- package/src/tui/entry.ts +25 -5
- package/src/tui/inline-choice.ts +188 -0
- package/src/tui/sidetab/list.ts +36 -165
- package/src/tui/sidetab/nl-tool.ts +2 -136
- package/src/tui/sidetab/peek.ts +52 -0
- package/src/tui/slash/term.ts +12 -1
- package/src/tui-client/dashboard-session.ts +10 -1
- package/src/user-config.ts +45 -9
- package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
- package/src/ux-sim/fake-land-queue.ts +88 -0
- package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
- package/src/ux-sim/fault-pod-child-result.ts +42 -0
- package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
- package/src/ux-sim/goal-interim-trace.ts +24 -0
- package/src/ux-sim/next-tui-seat-scenarios.ts +8 -13
- package/src/ux-sim/release-sim-rig.ts +262 -0
- package/src/ux-sim/seminar-rehearsal.ts +109 -0
- package/src/ux-sim/subagent-tools-device.ts +2 -2
- package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
- package/src/version/packed-revision.json +1 -1
- package/src/video-pipeline/recipes/explainer.ts +54 -2
- package/src/web-search/grok.ts +32 -6
- package/src/web-search/index.ts +8 -7
- package/src/workflow-runtime/node-catalog.ts +53 -4
- package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +0 -27
- package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +0 -148
- package/apps/pwa/out/_next/static/chunks/2104.70e086d5174a4736.js +0 -1
- package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +0 -93
- package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +0 -104
- package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +0 -24
- package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +0 -36
- package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +0 -287
- package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +0 -94
- package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4199-f7c6eb40cd0322f8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +0 -32
- package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +0 -90
- package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +0 -79
- package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +0 -74
- package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +0 -286
- package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +0 -1
- package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +0 -8
- package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +0 -62
- package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7488.966b116789f3d41a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7524.ce973525d30b3d52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7628.6b16863ac3972333.js +0 -34
- package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7954.4f7a8832663ee979.js +0 -115
- package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +0 -1
- package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +0 -149
- package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +0 -41
- package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +0 -226
- package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +0 -24
- package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +0 -2
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +0 -1
- package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +0 -122
- package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +0 -1
- package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
- /package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → GiOLWmt4MqDZePubBjA4Q}/_ssgManifest.js +0 -0
|
@@ -47,7 +47,7 @@ import { executeSiWarmTransport, type SiWarmFixedRunner,
|
|
|
47
47
|
type SiWarmPodIdentity } from './pod-si-warm-transport.js';
|
|
48
48
|
|
|
49
49
|
export const POD_CONTROL_INBOX_DIR = '/tmp/elanous-control.inbox';
|
|
50
|
-
/** Pod Job 수명 상한(`activeDeadlineSeconds`) —
|
|
50
|
+
/** Pod Job 수명 상한(`activeDeadlineSeconds`) — 2026-09-26 대표 지시로 90분 → 180분(90분에 `DeadlineExceeded` 로 죽은 런 둘). */
|
|
51
51
|
/** Newest pod log bytes returned when the export passes the 5MB artifact limit (headroom under it). */
|
|
52
52
|
export const POD_LOGS_KEEP_BYTES = 4_500_000;
|
|
53
53
|
|
|
@@ -61,6 +61,37 @@ export const POD_RESULT_FLATTEN = `ELANOUS_CHILD_RC="$rc" bun -e ' const fs=requ
|
|
|
61
61
|
|
|
62
62
|
export const POD_JOB_DEADLINE_SECONDS = 10_800;
|
|
63
63
|
|
|
64
|
+
/** Record the source-stage IO marker emitted by podSourceScript. */
|
|
65
|
+
export function recordPodSourceIoSummary(logs: string, job: string, runId: string | null | undefined,
|
|
66
|
+
runIdSource: 'explicit-child-id' | 'pod-launch-child-run-id',
|
|
67
|
+
log: typeof debug.log = (category, event, data, options) => debug.log(category, event, data, options),
|
|
68
|
+
hostOriginCalls: number | null = 0): void {
|
|
69
|
+
const ioSummary = /^ELANOUS_POD_SOURCE_IO (\{[^\r\n]+\})\r?$/m.exec(logs)?.[1];
|
|
70
|
+
if (!ioSummary) return;
|
|
71
|
+
try {
|
|
72
|
+
const measured = JSON.parse(ioSummary) as Record<string, unknown>;
|
|
73
|
+
const pushCounterReady = /^ELANOUS_POD_GIT_PUSH_COUNTER ready\r?$/m.test(logs);
|
|
74
|
+
const pushCalls = (logs.match(/^ELANOUS_POD_GIT_PUSH_ATTEMPT\r?$/gm) ?? []).length;
|
|
75
|
+
log('pod.source', 'io-summary', { job, runId, runIdSource, ...measured, hostOriginCalls,
|
|
76
|
+
...(pushCounterReady ? { pushCalls } : {}) });
|
|
77
|
+
} catch (error) {
|
|
78
|
+
log('pod.source', 'io-summary-invalid', { job, runId, runIdSource, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Select a timestamp for a DeadlineExceeded observation without making detector time look like Job completion.
|
|
83
|
+
* `podFinishedAt` must come from readPodTermination for the same verified Job uid. */
|
|
84
|
+
export function podJobFinishedTiming(input: { jobCreatedAt: string | null; jobCompletedAt: string | null;
|
|
85
|
+
podFinishedAt: string | null; observedAt: string }): { finishedAt: string; finishedAtSource: 'job-completion' | 'pod-termination' | 'observed-at'; elapsedMs: number | null } {
|
|
86
|
+
const valid = (value: string | null): value is string => typeof value === 'string' && Number.isFinite(Date.parse(value));
|
|
87
|
+
const selected = valid(input.jobCompletedAt) ? { finishedAt: input.jobCompletedAt, finishedAtSource: 'job-completion' as const }
|
|
88
|
+
: valid(input.podFinishedAt) ? { finishedAt: input.podFinishedAt, finishedAtSource: 'pod-termination' as const }
|
|
89
|
+
: { finishedAt: input.observedAt, finishedAtSource: 'observed-at' as const };
|
|
90
|
+
const elapsedMs = valid(input.jobCreatedAt) && Number.isFinite(Date.parse(selected.finishedAt))
|
|
91
|
+
? Math.max(0, Date.parse(selected.finishedAt) - Date.parse(input.jobCreatedAt)) : null;
|
|
92
|
+
return { ...selected, elapsedMs };
|
|
93
|
+
}
|
|
94
|
+
|
|
64
95
|
/** 자식 컨테이너 «요청» — 🩸 2026-09-27: limits 만 두면 k8s 가 requests=limits(cpu 4)로 잡아, 32코어 노드에
|
|
65
96
|
* «자리 요청»이 88% 차서 잡이 Pending 인데 실사용은 14%였다(풀 25 자리 중 ~8 만 떴다). 상한(limits)은 그대로 두고
|
|
66
97
|
* 예약만 실사용에 맞춘다. */
|
|
@@ -109,7 +140,7 @@ import { ZAI_POD_EGRESS_LABEL, checkZaiPodSecret, countActiveZaiJobs, decideZaiP
|
|
|
109
140
|
import { ZAI_CODING_DEFAULT_MODEL, ZAI_OPENROUTER_FALLBACK_MODEL, zaiSettingsFromConfig, type ZaiCodingPlanSettings } from '../../llm/zai-coding-plan.js';
|
|
110
141
|
import { normalizePlanningFallbackReason, selectEnhanceLlm } from '../../prompt-enhance/enhance.js';
|
|
111
142
|
import { inferProviderFromModel } from '../../llm.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';
|
|
143
|
+
import { classifyPodExit, extractPodFailureReason, podChildEvidenceLedgerRow, podChildFailureAttribution, podDeadlineResultMarker, podJobConditionReason, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
|
|
113
144
|
import { kubectlTransientReason, retryKubectlTransient } from './kubectl-transient-retry.js';
|
|
114
145
|
import { OLD_DOOR_STAMP_ENV } from '../../self-dev/old-door.js';
|
|
115
146
|
import { resolveDefaultSourceHead, seedMirrorOnce, type MirrorSeedResult } from './pod-mirror-seed.js';
|
|
@@ -201,7 +232,7 @@ export interface PodSpawnOptions {
|
|
|
201
232
|
warmPodRequest?: WarmPodRequestHook;
|
|
202
233
|
/** SI-SEED-DEFAULT — resolves a default source's branch tip for the mirror seed (test seam · default
|
|
203
234
|
* {@link resolveDefaultSourceHead}; none with an injected kubectl unless given). */
|
|
204
|
-
resolveSourceHead?: (o: { repoUrl: string; base?: string; cwd: string }) => Promise<{ sha?: string; reason?: string }>;
|
|
235
|
+
resolveSourceHead?: (o: { repoUrl: string; base?: string; cwd: string }) => Promise<{ sha?: string; reason?: string; originCalls?: number }>;
|
|
205
236
|
/** 설정 읽기(시험 주입). kubectl 주입 시험에서는 기본 사용자 설정을 읽지 않는다. */
|
|
206
237
|
configHostMirror?: () => string | undefined;
|
|
207
238
|
/** AUTHOR-POD2 host config seam; Pod itself has no host config. */
|
|
@@ -513,7 +544,7 @@ export function hostCredentials(account: string, storePath: string = authStorePa
|
|
|
513
544
|
* (POD_GROK_MIN_JOB_SECONDS) plus a margin left, and that launch's `activeDeadlineSeconds` is cut to the token's
|
|
514
545
|
* remaining life minus the margin (`fitPodDeadlineToGrok`) — so a long run ends as a classified DeadlineExceeded
|
|
515
546
|
* instead of a silent mid-run 401. With the host credential relay (pod.groundingUrl) the Pod renews mid-run and
|
|
516
|
-
* nothing is cut. 90 min = the Job cap before
|
|
547
|
+
* nothing is cut. 90 min = the Job cap before the 09-26 decision raised it (only two runs had reached it). */
|
|
517
548
|
export const POD_GROK_MIN_JOB_SECONDS = 90 * 60;
|
|
518
549
|
/** Slack between the fitted Job end and the token expiry (clock skew · Pod scheduling). */
|
|
519
550
|
export const POD_GROK_EXPIRY_MARGIN_MS = 15 * 60_000;
|
|
@@ -743,9 +774,10 @@ export function podGitPushGuardScript(runId?: string): string {
|
|
|
743
774
|
' *) echo "[pod] git-guard: refused push to $rref (only this run\'s branches)" >&2; exit 1 ;;',
|
|
744
775
|
' esac',
|
|
745
776
|
'done',
|
|
777
|
+
'case "$2" in https://github.com/*|http://github.com/*|git@github.com:*|ssh://git@github.com/*) printf \'ELANOUS_POD_GIT_PUSH_ATTEMPT\\n\' >&2 ;; esac',
|
|
746
778
|
'exit 0',
|
|
747
779
|
'ELANOUS_PRE_PUSH',
|
|
748
|
-
`chmod 755 "${POD_GIT_HOOKS_DIR}/pre-push" && git config --global core.hooksPath "${POD_GIT_HOOKS_DIR}"`,
|
|
780
|
+
`chmod 755 "${POD_GIT_HOOKS_DIR}/pre-push" && git config --global core.hooksPath "${POD_GIT_HOOKS_DIR}" && printf 'ELANOUS_POD_GIT_PUSH_COUNTER ready\\n'`,
|
|
749
781
|
].join('\n');
|
|
750
782
|
}
|
|
751
783
|
|
|
@@ -960,7 +992,7 @@ export function podRunLabels(o: { runId?: string; parentRunId?: string }): Recor
|
|
|
960
992
|
return { ...(run ? { 'elanous.run': run } : {}), ...(child ? { 'elanous.child-run': child } : {}) };
|
|
961
993
|
}
|
|
962
994
|
|
|
963
|
-
/** Pod 메모리 «등급» —
|
|
995
|
+
/** Pod 메모리 «등급» — 09-27 결정: PWA Pod 골이 16Gi 에서 OOM 으로 죽는다 ⇒ «high» 등급을 옵션으로 고른다.
|
|
964
996
|
* 등급 = `standard`(`ELANOUS_POD_MEMORY` 또는 16Gi) · `high`(`ELANOUS_POD_MEMORY_HIGH` 또는 32Gi · standard 보다 작아지지 않는다).
|
|
965
997
|
* 고르는 순서(앞이 이긴다): ① 발사 옵션 `--pod-memory <등급>`(→ `ELANOUS_POD_MEMORY_TIER`) ② 조각 문면 `Pod 메모리: lite|standard|high` ③ 조각의 `apps/pwa/` ④ 부모의 명시 메모리 줄·PWA 경로 ⑤ 실측 권고 ⑥ 권고 없는 research/document 는 lite ⑦ standard.
|
|
966
998
|
* node-b 노드 할당 가능 약 251Gi. */
|
|
@@ -1216,7 +1248,7 @@ export function podDeadlineWatchdogScript(input: { deadlineSeconds: number; job:
|
|
|
1216
1248
|
|
|
1217
1249
|
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
1250
|
|
|
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> {
|
|
1251
|
+
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' }; configSnapshotHash?: string; /** 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> {
|
|
1220
1252
|
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'))) {
|
|
1221
1253
|
throw new Error('repair commit-only requires matching PR source and no PR/merge flags');
|
|
1222
1254
|
}
|
|
@@ -1247,7 +1279,10 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
|
|
|
1247
1279
|
const script = [
|
|
1248
1280
|
'set -u',
|
|
1249
1281
|
...(o.fallbackChain ? [
|
|
1250
|
-
|
|
1282
|
+
...(o.configSnapshotHash ? [
|
|
1283
|
+
'bun -e \'import { createHash } from "node:crypto"; import { readFileSync } from "node:fs"; const e = JSON.parse(readFileSync("/creds/config-snapshot.json", "utf8")); const c = JSON.parse(readFileSync("/creds/llm-fallback-config.json", "utf8")); const h = createHash("sha256").update(JSON.stringify({ version: e.version, keys: e.keys, sources: e.sources })).digest("hex"); if (h !== e.hash || JSON.stringify(c) !== JSON.stringify(e.keys)) process.exit(1);\' || exit 6',
|
|
1284
|
+
] : []),
|
|
1285
|
+
'mkdir -p "$HOME/.elanous" && { [ -e "$HOME/.elanous/config.json" ] || [ -L "$HOME/.elanous/config.json" ] || install -m 600 /creds/llm-fallback-config.json "$HOME/.elanous/config.json"; } || exit 6',
|
|
1251
1286
|
`echo "ELANOUS_POD_FALLBACK_CHAIN source=${o.fallbackChain.source} steps=${o.fallbackChain.steps.join(',')}"`,
|
|
1252
1287
|
] : []),
|
|
1253
1288
|
openGatewayModel
|
|
@@ -1390,7 +1425,7 @@ if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
|
|
|
1390
1425
|
apiVersion: 'batch/v1',
|
|
1391
1426
|
kind: 'Job',
|
|
1392
1427
|
metadata: { name: o.name, namespace: o.namespace, labels: { 'elanous.substrate': 'pod', 'elanous.job': o.name, ...podRunLabels(o), ...(o.workIdentity ? podWorkLabels(o.workIdentity) : {}), ...(o.zai || o.zaiFallback ? { [ZAI_POD_EGRESS_LABEL]: 'true' } : {}), ...o.provenance?.labels },
|
|
1393
|
-
...((o.execution || o.hostLeaseAdmitted || o.provenance) ? { annotations: { ...o.provenance?.annotations, ...(o.execution ? { [POD_EXECUTION_KEY_ANNOTATION]: o.execution.key, [POD_ATTEMPT_ANNOTATION]: String(o.execution.attempt) } : {}), ...(o.hostLeaseAdmitted ? { [POD_HOST_LEASE_ANNOTATION]: 'true' } : {}) } } : {}) },
|
|
1428
|
+
...((o.execution || o.hostLeaseAdmitted || o.provenance || o.configSnapshotHash) ? { annotations: { ...o.provenance?.annotations, ...(o.configSnapshotHash ? { 'elanous.config-snapshot-sha256': o.configSnapshotHash } : {}), ...(o.execution ? { [POD_EXECUTION_KEY_ANNOTATION]: o.execution.key, [POD_ATTEMPT_ANNOTATION]: String(o.execution.attempt) } : {}), ...(o.hostLeaseAdmitted ? { [POD_HOST_LEASE_ANNOTATION]: 'true' } : {}) } } : {}) },
|
|
1394
1429
|
spec: {
|
|
1395
1430
|
backoffLimit: 0,
|
|
1396
1431
|
ttlSecondsAfterFinished: POD_JOB_TTL_AFTER_FINISHED_SECONDS,
|
|
@@ -1573,19 +1608,42 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1573
1608
|
}
|
|
1574
1609
|
if (options.siWarmAttempt) {
|
|
1575
1610
|
const done = (async (): Promise<SelfImplementJobDone> => {
|
|
1611
|
+
// POD-REUSE-REQUEST-CLEAN-FU — one fail-soft row per request decision. `runId` is the
|
|
1612
|
+
// ledger partition (warm child, then parent run, then the legacy spaceId fallback);
|
|
1613
|
+
// `correlationId` always names the request's spaceId. `warm-path-selected` is recorded
|
|
1614
|
+
// before transport, so only the later return/quarantine row settles whether reuse completed.
|
|
1615
|
+
// A ledger write failure is an observation failure only.
|
|
1616
|
+
const recordWarmRequestDecision = (data: Record<string, unknown>, runId?: string) => {
|
|
1617
|
+
const parentRunId = env.ELANOUS_RUN_ID;
|
|
1618
|
+
const ledgerRunId = runId ?? parentRunId ?? input.spaceId;
|
|
1619
|
+
const runIdSource = runId ? 'warm-child-run' : parentRunId ? 'parent-run' : 'space-id-fallback';
|
|
1620
|
+
try { writeWarmLedger({ runId: ledgerRunId, event: 'pod-reuse-request-decision',
|
|
1621
|
+
data: { ...data, correlationId: input.spaceId, runIdSource } }); }
|
|
1622
|
+
catch (error) { debug.log('pod.reuse', 'ledger-unavailable', { spaceId: input.spaceId,
|
|
1623
|
+
event: 'pod-reuse-request-decision',
|
|
1624
|
+
reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
|
|
1625
|
+
};
|
|
1576
1626
|
let attempt: SiWarmChildAttempt;
|
|
1577
1627
|
try {
|
|
1578
1628
|
const acquired = await options.siWarmAttempt!(input);
|
|
1579
1629
|
if (!acquired) {
|
|
1580
1630
|
// No lease was fenced: use the existing one-shot Job path.
|
|
1631
|
+
recordWarmRequestDecision({ spaceId: input.spaceId, outcome: 'cold-job',
|
|
1632
|
+
workerId: null, leaseId: null, generation: null, podUid: null });
|
|
1581
1633
|
const { siWarmAttempt: _unused, siWarmHostPostprocess: _postprocess, ...coldOptions } = options;
|
|
1582
1634
|
return podSelfImplementSpawn(coldOptions)(input).done;
|
|
1583
1635
|
}
|
|
1584
1636
|
attempt = acquired;
|
|
1637
|
+
recordWarmRequestDecision({ spaceId: input.spaceId, outcome: 'warm-path-selected',
|
|
1638
|
+
workerId: acquired.command?.workerId ?? null, leaseId: acquired.command?.leaseId ?? null,
|
|
1639
|
+
generation: acquired.command?.generation ?? null, podUid: acquired.command?.podUid ?? null },
|
|
1640
|
+
acquired.command?.runId);
|
|
1585
1641
|
}
|
|
1586
1642
|
catch (error) {
|
|
1587
1643
|
// A lost exec reply may conceal an already opened PR. Never start another child here.
|
|
1588
1644
|
const message = error instanceof Error ? error.message : String(error);
|
|
1645
|
+
recordWarmRequestDecision({ spaceId: input.spaceId, outcome: 'acquire-failed', reason: message,
|
|
1646
|
+
workerId: null, leaseId: null, generation: null, podUid: null });
|
|
1589
1647
|
debug.log('pod.reuse', 'attempt-unavailable', { spaceId: input.spaceId, reason: message }, { level: 'warn' });
|
|
1590
1648
|
return { exitCode: 1, output: '', error: { code: 'si-warm-reconcile-only', message } };
|
|
1591
1649
|
}
|
|
@@ -1942,6 +2000,38 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1942
2000
|
try {
|
|
1943
2001
|
// Every attempt, including an OOM retry, must acquire a pool slot before applying a Job.
|
|
1944
2002
|
const stallMs = options.launchStallMs ?? (getUserConfig().harness?.launchStallMinutes ?? 15) * 60_000;
|
|
2003
|
+
const slotNow = options.now ?? Date.now;
|
|
2004
|
+
let slotAttemptNumber = 0;
|
|
2005
|
+
let lastSlotReasonCode: string | undefined;
|
|
2006
|
+
let lastSlotAttempt: { observationKey: string; requestedAtMs: number; requestedAt: string } | undefined;
|
|
2007
|
+
const slotReasonCode = (reason: string | null | undefined): string => {
|
|
2008
|
+
if (!reason) return 'not-measured-yet';
|
|
2009
|
+
if (/no free slot/iu.test(reason)) return 'no-free-slot';
|
|
2010
|
+
if (/memory/iu.test(reason)) return 'memory-capacity';
|
|
2011
|
+
if (/capacity|lease/iu.test(reason)) return 'capacity';
|
|
2012
|
+
return 'pool-slot-unavailable';
|
|
2013
|
+
};
|
|
2014
|
+
const recordSlotObservation = (attempt: { observationKey: string; requestedAtMs: number; requestedAt: string },
|
|
2015
|
+
outcome: 'requested' | 'queued' | 'admitted' | 'rejected', reasonCode: string,
|
|
2016
|
+
cancellation?: { abortReason?: string; waitReason: string | null }): void => {
|
|
2017
|
+
const pool = options.pool;
|
|
2018
|
+
let occupants: Record<string, number> | null = null;
|
|
2019
|
+
try { occupants = pool ? pool.snapshot() : null; } catch { /* observation must not change scheduling */ }
|
|
2020
|
+
const poolCapacity = pool?.members?.reduce((total, member) => total + Math.max(0, member.capacity), 0) ?? null;
|
|
2021
|
+
const data = {
|
|
2022
|
+
observationKey: attempt.observationKey, runId: childRunId, host: resolveHostId(env),
|
|
2023
|
+
requestedAt: attempt.requestedAt, waitedMs: Math.max(0, slotNow() - attempt.requestedAtMs),
|
|
2024
|
+
queued: outcome === 'queued', poolCapacity, occupants, reasonCode, parentId: ledgerRunId, outcome,
|
|
2025
|
+
...(cancellation ? { waitReason: cancellation.waitReason,
|
|
2026
|
+
...(cancellation.abortReason === undefined ? {} : { abortReason: cancellation.abortReason }) } : {}),
|
|
2027
|
+
};
|
|
2028
|
+
debug.log('pod.slot', outcome, data, { level: outcome === 'admitted' || outcome === 'requested' ? 'info' : 'warn' });
|
|
2029
|
+
try {
|
|
2030
|
+
appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-slot-observation', data }, ledgerDir);
|
|
2031
|
+
if (outcome === 'rejected') appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-slot-incident', data }, ledgerDir);
|
|
2032
|
+
}
|
|
2033
|
+
catch (error) { debug.log('pod.slot', 'ledger-unavailable', { ...data, writeError: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
|
|
2034
|
+
};
|
|
1945
2035
|
// LAUNCH-STALL (10-06): a stage that waits past the cap says so once — today Pods sat 22 min to 5 h with no event.
|
|
1946
2036
|
const stalledStages = new Set<string>();
|
|
1947
2037
|
// pool-slot reason = what THIS launch saw on its last empty tryAcquire; admission reason = the pool-wide lease measurement (one pool, one reading).
|
|
@@ -1979,25 +2069,43 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
1979
2069
|
};
|
|
1980
2070
|
const acquireSlot = async (): Promise<PodPoolMember | null> => {
|
|
1981
2071
|
if (!options.pool) return null;
|
|
2072
|
+
// Each actual acquisition is a separate observation, including the OOM retry in this
|
|
2073
|
+
// same child run. The ordinal keeps keys distinct even with a fixed test clock.
|
|
2074
|
+
const requestedAtMs = slotNow();
|
|
2075
|
+
const attempt = { observationKey: `${childRunId}:pod-slot:${requestedAtMs}:${++slotAttemptNumber}`,
|
|
2076
|
+
requestedAtMs, requestedAt: new Date(requestedAtMs).toISOString() };
|
|
2077
|
+
let firstSlotReasonCode: string | undefined;
|
|
2078
|
+
stageReason['pool-slot'] = null;
|
|
2079
|
+
let slotQueuedRecorded = false;
|
|
1982
2080
|
const stop = watchStall('pool-slot');
|
|
1983
2081
|
// MINIH-MODE (0.2.37): the location is declared by the launch env — absent/unknown keeps the configured
|
|
1984
2082
|
// capacities, so this launch path behaves exactly as before unless the declaration is there.
|
|
1985
2083
|
const minihLocation = minihLocationFrom(env.ELANOUS_MINIH_LOCATION);
|
|
1986
2084
|
try {
|
|
2085
|
+
recordSlotObservation(attempt, 'requested', 'pending');
|
|
1987
2086
|
for (;;) {
|
|
1988
2087
|
if (input.signal?.aborted) return null;
|
|
1989
2088
|
// The reason comes back inside this call, so a concurrent launch cannot overwrite it.
|
|
1990
2089
|
const kind = podPlacementKind(oomRetried ? retryTier : memoryTier, selectedGoalType, requestKind);
|
|
1991
|
-
const acquired = await options.pool.tryAcquire(unfitContexts, (reason) => {
|
|
2090
|
+
const acquired = await options.pool.tryAcquire(unfitContexts, (reason) => {
|
|
2091
|
+
stageReason['pool-slot'] = reason;
|
|
2092
|
+
firstSlotReasonCode ??= slotReasonCode(reason);
|
|
2093
|
+
},
|
|
1992
2094
|
{ kind, ...(minihLocation ? { minihLocation } : {}), onPlacement: (placement) => { lastPlacement = placement; } });
|
|
1993
2095
|
if (acquired) {
|
|
2096
|
+
recordSlotObservation(attempt, 'admitted', firstSlotReasonCode ?? 'admitted');
|
|
1994
2097
|
debug.log('self-implement.pod', 'pool-slot', { spaceId: input.spaceId, context: acquired.context, inflight: options.pool.snapshot(), ...(lastPlacement ? { placement: lastPlacement } : {}) });
|
|
1995
2098
|
if (lastPlacement) console.warn(`[pod] 배치: ${lastPlacement.reason}`);
|
|
1996
2099
|
return acquired;
|
|
1997
2100
|
}
|
|
2101
|
+
firstSlotReasonCode ??= slotReasonCode(stageReason['pool-slot']);
|
|
2102
|
+
if (!slotQueuedRecorded) {
|
|
2103
|
+
slotQueuedRecorded = true;
|
|
2104
|
+
recordSlotObservation(attempt, 'queued', firstSlotReasonCode);
|
|
2105
|
+
}
|
|
1998
2106
|
await sleep(options.pollMs ?? 15_000);
|
|
1999
2107
|
}
|
|
2000
|
-
} finally { stop(); }
|
|
2108
|
+
} finally { lastSlotReasonCode = firstSlotReasonCode; lastSlotAttempt = attempt; stop(); }
|
|
2001
2109
|
};
|
|
2002
2110
|
const acquireAdmission = async (): Promise<boolean> => {
|
|
2003
2111
|
if (!options.pool || typeof options.pool.acquireAdmission !== 'function') return true;
|
|
@@ -2033,8 +2141,12 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2033
2141
|
let member: PodPoolMember | null;
|
|
2034
2142
|
try { member = await acquireSlot(); } catch (error) { podAdmitError(error); throw error; }
|
|
2035
2143
|
if (options.pool && !member) {
|
|
2144
|
+
if (lastSlotAttempt) recordSlotObservation(lastSlotAttempt, 'rejected', lastSlotReasonCode ?? 'aborted', {
|
|
2145
|
+
waitReason: stageReason['pool-slot'] ?? null,
|
|
2146
|
+
...(typeof input.signal?.reason === 'string' ? { abortReason: input.signal.reason } : {}),
|
|
2147
|
+
});
|
|
2036
2148
|
exitJourneyNode('pool-admit', { provenance: 'self-implement-pod', outcome: 'refused', data: { spaceId: input.spaceId, reason: 'no-slot' } });
|
|
2037
|
-
return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before a pool slot opened' } };
|
|
2149
|
+
return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before a pool slot opened', ...(lastSlotReasonCode ? { reasonCode: lastSlotReasonCode } : {}) } };
|
|
2038
2150
|
}
|
|
2039
2151
|
exitJourneyNode('pool-admit', { provenance: 'self-implement-pod', outcome: 'admitted', data: { spaceId: input.spaceId, ...(member ? { context: member.context } : {}) } });
|
|
2040
2152
|
const currentContext = member ? null : baseKubectl(['config', 'current-context']);
|
|
@@ -2062,6 +2174,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2062
2174
|
const cleanupSecret = () => { kubectl(['-n', namespace, 'delete', 'secret', `${name}-creds`, '--ignore-not-found']); };
|
|
2063
2175
|
let repairResultAnnounced = false;
|
|
2064
2176
|
let repairArtifactReady = false;
|
|
2177
|
+
let hostOriginCalls: number | null = 0;
|
|
2178
|
+
let sourceBaseSha: string | undefined;
|
|
2065
2179
|
const collectFullLogs = (unavailableEvent: string, replace?: ReadonlySet<string>, onEvent?: (event: string, data: Record<string, unknown>) => void, childId?: string): { status: 'ok' | 'unavailable' | 'incomplete'; childLedgerIncomplete: boolean; samples: ReturnType<typeof parseMemSamples> } => {
|
|
2066
2180
|
let full: ReturnType<Kubectl>;
|
|
2067
2181
|
try {
|
|
@@ -2078,6 +2192,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2078
2192
|
const imageSkip = /^ELANOUS_POD_SOURCE_IMAGE_SKIP ([^\r\n]+)\r?$/m.exec(full.stdout)?.[1];
|
|
2079
2193
|
const delta = /^ELANOUS_POD_SOURCE_DELTA (mirror|origin)\r?$/m.exec(full.stdout)?.[1];
|
|
2080
2194
|
if (via) debug.log('self-implement.pod', 'source-via', { job: name, via, ...(mirrorSkip ? { mirrorSkip } : {}), ...(imageSkip ? { imageSkip } : {}), ...(delta ? { delta } : {}) });
|
|
2195
|
+
recordPodSourceIoSummary(full.stdout, name, childId ?? childRunId, childId ? 'explicit-child-id' : 'pod-launch-child-run-id',
|
|
2196
|
+
(category, event, data, logOptions) => debug.log(category, event, data, logOptions), hostOriginCalls);
|
|
2081
2197
|
let ledgerIncomplete = false;
|
|
2082
2198
|
let childLedgerIncomplete = false;
|
|
2083
2199
|
let artifactIncomplete = false;
|
|
@@ -2355,20 +2471,43 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2355
2471
|
}
|
|
2356
2472
|
const now = options.now ?? Date.now;
|
|
2357
2473
|
const issueVerifiedAppCredential = async (fresh = false): Promise<{ token: string; expiresAt: number } | null> => {
|
|
2358
|
-
if (!repository)
|
|
2474
|
+
if (!repository) {
|
|
2475
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, reason: 'repository-unavailable', fresh });
|
|
2476
|
+
return null;
|
|
2477
|
+
}
|
|
2359
2478
|
// This is the same repository-scoped, contents+pull_requests installation request on launch and refresh.
|
|
2360
|
-
|
|
2361
|
-
|
|
2479
|
+
let candidate: ReturnType<NonNullable<typeof options.githubInstallation>>;
|
|
2480
|
+
try { candidate = (options.githubInstallation ?? ((repo, o) => coalescedInstallationCredential({ repository: repo.split('/')[1]! }, { fresh: o?.fresh })))(repository, { fresh }); }
|
|
2481
|
+
catch {
|
|
2482
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'mint-threw', fresh });
|
|
2483
|
+
return null;
|
|
2484
|
+
}
|
|
2485
|
+
if (!candidate?.token) {
|
|
2486
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'mint-unavailable', fresh });
|
|
2487
|
+
return null;
|
|
2488
|
+
}
|
|
2362
2489
|
const expiry = candidate.expires_at ?? ('expiresAt' in candidate ? candidate.expiresAt : undefined);
|
|
2363
2490
|
const expiresAt = typeof expiry === 'number' ? expiry : Date.parse(expiry ?? '');
|
|
2364
|
-
if (!Number.isFinite(expiresAt) || expiresAt <= now())
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2491
|
+
if (!Number.isFinite(expiresAt) || expiresAt <= now()) {
|
|
2492
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: Number.isFinite(expiresAt) ? 'expired' : 'expiry-unavailable', expiresAt: Number.isFinite(expiresAt) ? new Date(expiresAt).toISOString() : null, fresh });
|
|
2493
|
+
return null;
|
|
2494
|
+
}
|
|
2495
|
+
let available: Awaited<ReturnType<NonNullable<typeof options.githubRepositories>>>;
|
|
2496
|
+
try { available = await (options.githubRepositories ?? installationRepositories)(candidate.token); }
|
|
2497
|
+
catch {
|
|
2498
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'verification-threw', expiresAt: new Date(expiresAt).toISOString(), fresh });
|
|
2499
|
+
return null;
|
|
2500
|
+
}
|
|
2501
|
+
if (available?.length !== 1 || available[0]?.toLowerCase() !== repository.toLowerCase()) {
|
|
2502
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'repository-verification-failed', availableCount: available?.length ?? null, expiresAt: new Date(expiresAt).toISOString(), fresh });
|
|
2503
|
+
return null;
|
|
2504
|
+
}
|
|
2505
|
+
debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'verified', expiresAt: new Date(expiresAt).toISOString(), fresh });
|
|
2506
|
+
return { token: candidate.token, expiresAt };
|
|
2368
2507
|
};
|
|
2369
2508
|
let appCredential: Awaited<ReturnType<typeof issueVerifiedAppCredential>> = null;
|
|
2370
2509
|
try { appCredential = await issueVerifiedAppCredential(ghLoginRetried); }
|
|
2371
|
-
catch { debug.log('self-implement.pod', 'github-app-unavailable', { job: name, reason: 'mint-or-verification-
|
|
2510
|
+
catch { debug.log('self-implement.pod', 'github-app-unavailable', { job: name, repository, reason: 'mint-or-verification-threw' }); }
|
|
2372
2511
|
// PODCRED1: a short token is still shipped — the host renews it in the Pod on the first live poll — but it is
|
|
2373
2512
|
// observed, so an exit-7 burst can be checked against the remaining life the Pods actually started with.
|
|
2374
2513
|
if (appCredential && appCredential.expiresAt - now() < POD_APP_TOKEN_MIN_START_MS) {
|
|
@@ -2384,6 +2523,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2384
2523
|
// The host polling loop is a refresh path even when the Pod cannot reach the relay.
|
|
2385
2524
|
const hostRefresh = Boolean(appCredential);
|
|
2386
2525
|
const podGhToken = hostRefresh ? appCredential!.token : creds.ghToken;
|
|
2526
|
+
debug.log('self-implement.pod', 'github-credential-source', { job: name, repository, source: hostRefresh ? 'verified-app' : 'human-fallback', expiresAt: hostRefresh ? new Date(appCredential!.expiresAt).toISOString() : null });
|
|
2387
2527
|
const githubPassKeys = hostRefresh ? passKeys.filter((key) => !['GH_TOKEN', 'GITHUB_TOKEN', 'GH_CONFIG_DIR'].includes(key)) : passKeys;
|
|
2388
2528
|
let ghTokenExpiresAt = hostRefresh ? appCredential!.expiresAt : null;
|
|
2389
2529
|
const requestedGoalDoc = env.ELANOUS_POD_GOAL_DOC;
|
|
@@ -2515,6 +2655,12 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2515
2655
|
if (!zaiFallbackSpec) fallbackSteps = fallbackSteps.filter(step => step !== 'zai');
|
|
2516
2656
|
}
|
|
2517
2657
|
const fallbackChain = { steps: fallbackSteps, source: normalizedFallback.usedDefault ? 'default' as const : 'host' as const };
|
|
2658
|
+
const { buildPodConfigSnapshot } = await import('./pod-config-snapshot.js');
|
|
2659
|
+
const configSnapshot = buildPodConfigSnapshot(hostConfig, {
|
|
2660
|
+
steps: fallbackChain.steps, overage: zaiOverage,
|
|
2661
|
+
worktreeAddTimeoutSec: worktreeAddTimeoutSec(hostConfig.harness?.worktreeAddTimeoutSec) ?? 1200,
|
|
2662
|
+
});
|
|
2663
|
+
debug.log('self-implement.pod', 'config-snapshot', { job: name, hash: configSnapshot.hash, keyCount: configSnapshot.keyCount });
|
|
2518
2664
|
debug.log('self-implement.pod', 'fallback-chain-carried', {
|
|
2519
2665
|
job: name, source: fallbackChain.source, steps: fallbackChain.steps,
|
|
2520
2666
|
...(normalizedFallback.dropped.length ? { droppedCount: normalizedFallback.dropped.length } : {}),
|
|
@@ -2533,7 +2679,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2533
2679
|
? Object.fromEntries(codexCredentials.map((candidate, i) => [`codex-${i}.json`, JSON.stringify({ elanousAuth: candidate.elanousAuth, codexAuth: candidate.codexAuth })]))
|
|
2534
2680
|
: { 'elanous-auth.json': (creds as ReturnType<typeof hostCredentials>).elanousAuth, 'codex-auth.json': (creds as ReturnType<typeof hostCredentials>).codexAuth }),
|
|
2535
2681
|
'gh-token': podGhToken, feature: input.feature,
|
|
2536
|
-
'llm-fallback-config.json':
|
|
2682
|
+
'llm-fallback-config.json': configSnapshot.configJson,
|
|
2683
|
+
'config-snapshot.json': configSnapshot.envelopeJson,
|
|
2537
2684
|
...(goalDocument !== undefined ? { 'goal-doc': goalDocument } : {}),
|
|
2538
2685
|
...Object.fromEntries(Object.entries(skillEnvs).map(([n, text]) => [`skillenv-${n}`, text])),
|
|
2539
2686
|
...(grounding ? { [`env-${GROUNDING_TOKEN_ENV}`]: grounding.token } : {}),
|
|
@@ -2547,7 +2694,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2547
2694
|
if (missing.length) debug.log('self-implement.pod', 'pass-env-missing', { job: name, missing }, { level: 'warn' });
|
|
2548
2695
|
// ☸️ 재개(P3 · 2026-09-26): 같은 이름의 Job 이 이미 있으면 «지우지 않고» 붙는다 — 호스트가 끊긴 동안에도 원격은 계속 돌았다.
|
|
2549
2696
|
// 🩸 종전엔 여기서 delete 부터 해서, 재개가 원격에서 멀쩡히 돌던 Job 을 죽였다. 실패로 끝난 Job 만 지우고 다시 만든다.
|
|
2550
|
-
// ☸️ 노드 레지스트리에 이 판이 있으면 그것을 pull 한다(델타 ·
|
|
2697
|
+
// ☸️ 노드 레지스트리에 이 판이 있으면 그것을 pull 한다(델타 · 2026-09-26) — 라벨 판정은 로컬 이미지 이름으로 한다.
|
|
2551
2698
|
const jobImage = member?.imageRef ?? image;
|
|
2552
2699
|
// A pool member may pull a different image than the host's local one.
|
|
2553
2700
|
// The local Docker label cannot prove that member image's commit.
|
|
@@ -2729,12 +2876,21 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2729
2876
|
slotId: env.ELANOUS_POD_SLOT_ID,
|
|
2730
2877
|
work: !goalDoc && env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'authoring' : (oomRetried ? retryTier : memoryTier) === 'lite' ? 'lite' : 'harness',
|
|
2731
2878
|
};
|
|
2732
|
-
// TA-POD-WARMBOOT-PARITY shadow only:
|
|
2733
|
-
//
|
|
2879
|
+
// TA-POD-WARMBOOT-PARITY shadow only: read injected evidence, then keep the fresh-Job path.
|
|
2880
|
+
// This boundary must not open host configuration or credential files for a warm decision.
|
|
2734
2881
|
if (workIdentity.taskCard) {
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2882
|
+
let stage: 'config' | 'evidence' | 'decision' = 'config';
|
|
2883
|
+
try {
|
|
2884
|
+
const config = options.warmReuseConfig?.();
|
|
2885
|
+
stage = 'evidence';
|
|
2886
|
+
const evidence = options.warmReuseEvidence?.();
|
|
2887
|
+
stage = 'decision';
|
|
2888
|
+
const decision = decideWarmReuse('ta', config, evidence);
|
|
2889
|
+
debug.log('pod.warm', 'ta-shadow-observation', { ...decision, execution: 'fresh-job' });
|
|
2890
|
+
} catch {
|
|
2891
|
+
debug.log('pod.warm', 'ta-shadow-unavailable', { spaceId: input.spaceId,
|
|
2892
|
+
reason: stage === 'decision' ? 'warm-decision-failed' : `injected-${stage}-failed`, execution: 'fresh-job' }, { level: 'warn' });
|
|
2893
|
+
}
|
|
2738
2894
|
}
|
|
2739
2895
|
// TA-POD-WARMBOOT-PARITY (GATE-WARM-BOOT parity · #27805): a commit-pinned source on a pool host — put that commit into
|
|
2740
2896
|
// the host mirror first (once per host·commit in this process) so podSourceScript finds it instead of fetching
|
|
@@ -2753,12 +2909,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2753
2909
|
else if (seedSource.kind !== 'default') seedSkip = `source-${seedSource.kind}`;
|
|
2754
2910
|
else {
|
|
2755
2911
|
const resolveHead = options.resolveSourceHead ?? (options.kubectl ? undefined : resolveDefaultSourceHead);
|
|
2756
|
-
let head: { sha?: string; reason?: string } | undefined;
|
|
2912
|
+
let head: { sha?: string; reason?: string; originCalls?: number } | undefined;
|
|
2757
2913
|
try { head = resolveHead ? await resolveHead({ repoUrl, ...(seedSource.base ? { base: seedSource.base } : {}), cwd: seedCwd }) : undefined; }
|
|
2758
2914
|
catch { head = { reason: 'resolve-threw' }; }
|
|
2759
2915
|
if (!resolveHead) seedSkip = 'no-head-resolver';
|
|
2760
|
-
else if (head
|
|
2761
|
-
|
|
2916
|
+
else if (head) hostOriginCalls = typeof head.originCalls === 'number' && Number.isSafeInteger(head.originCalls) && head.originCalls >= 0 ? head.originCalls : null;
|
|
2917
|
+
if (head?.sha && /^[0-9a-f]{40}$/.test(head.sha)) { seedCommit = head.sha; sourceBaseSha = head.sha; }
|
|
2918
|
+
else if (resolveHead) seedSkip = `default-head-${head?.reason ?? 'unresolved'}`;
|
|
2762
2919
|
}
|
|
2763
2920
|
if (seedMirror && seedCommit && member?.sshHost) {
|
|
2764
2921
|
const seedHost = member.sshHost;
|
|
@@ -2769,7 +2926,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2769
2926
|
} catch (error) {
|
|
2770
2927
|
seed = { host: seedHost, ok: false, ms: 0, detail: String(error).slice(0, 300) };
|
|
2771
2928
|
}
|
|
2772
|
-
debug.log('self-implement.pod', 'mirror-seed', { job: name, host: seedHost, commit: seedCommit, sourceKind: seedSource.kind, ok: seed?.ok ?? false, ms: seed?.ms ?? 0, ...(seed?.detail ? { detail: seed.detail } : {}) }, seed?.ok ? undefined : { level: 'warn' });
|
|
2929
|
+
debug.log('self-implement.pod', 'mirror-seed', { job: name, host: seedHost, commit: seedCommit, sourceKind: seedSource.kind, ...(sourceBaseSha ? { sourceBaseSha } : {}), ok: seed?.ok ?? false, ms: seed?.ms ?? 0, ...(seed?.detail ? { detail: seed.detail } : {}) }, seed?.ok ? undefined : { level: 'warn' });
|
|
2773
2930
|
} else {
|
|
2774
2931
|
debug.log('self-implement.pod', 'mirror-seed-skipped', { job: name, reason: seedSkip ?? 'unknown', sourceKind: seedSource.kind, ...(member?.sshHost ? { host: member.sshHost } : {}) });
|
|
2775
2932
|
}
|
|
@@ -2804,7 +2961,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2804
2961
|
cleanupSecret();
|
|
2805
2962
|
return { exitCode: 1, output: '', error: { code: 'pod-provenance', message } };
|
|
2806
2963
|
}
|
|
2807
|
-
const job = podJobManifest({ provenance, name, namespace, fallbackChain, ...(resultMarkerLine ? { resultMarkerLine } : {}), image: jobImage, workIdentity, ...(env.ELANOUS_TASK_BOUND_PR && /^[1-9]\d*$/.test(env.ELANOUS_TASK_BOUND_PR) && Number.isSafeInteger(Number(env.ELANOUS_TASK_BOUND_PR)) ? { boundPrNumber: Number(env.ELANOUS_TASK_BOUND_PR) } : {}), ...(member?.imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}), repoUrl, ...(options.source ? { source: options.source } : {}), ...(options.repairCommitOnly ? { repairCommitOnly: options.repairCommitOnly } : {}), ...(hostMirror ? { hostMirror } : {}), args: jobArgs, passEnv: jobPassEnv, deadlineSeconds: jobDeadlineSeconds, ...(goalDoc ? { goalDoc } : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? { authorSentence: true, ...(env.ELANOUS_POD_AUTHOR_GRADE === 'lite' || env.ELANOUS_POD_AUTHOR_GRADE === 'full' ? { authorGrade: env.ELANOUS_POD_AUTHOR_GRADE } : {}) } : {}), runId: launchRunId, ...(parentRunId ? { parentRunId } : {}), ...(jobArmEnv ? { armEnv: jobArmEnv } : {}), hostId: resolveHostId(env), skillEnvs: Object.keys(skillEnvs), memoryLimit, memoryRequest, imageCommit: jobImageCommit, ...(grok ? { grokCredential: 'grokAuth' in creds && creds.grokAuth ? 'subscription' as const : 'api_key' as const } : {}), ...(codexAccounts ? { codexAccounts } : {}), ...(hostRefresh ? { appCredential: true } : {}), execution: { key: executionKey, attempt: oomRetried ? 2 : 1 }, hostLeaseAdmitted: !!releaseAdmission, ...(roleCodexCredential ? { reviewerCodexAuth: true } : {}), ...(bedrockSpec ? { bedrock: bedrockSpec } : {}), ...(zaiSpec ? { zai: zaiSpec } : {}), ...(zaiFallbackSpec ? { zaiFallback: zaiFallbackSpec } : {}) }); // kubectl 주입(=시험)이면 docker 를 부르지 않는다
|
|
2964
|
+
const job = podJobManifest({ provenance, name, namespace, fallbackChain, configSnapshotHash: configSnapshot.hash, ...(resultMarkerLine ? { resultMarkerLine } : {}), image: jobImage, workIdentity, ...(env.ELANOUS_TASK_BOUND_PR && /^[1-9]\d*$/.test(env.ELANOUS_TASK_BOUND_PR) && Number.isSafeInteger(Number(env.ELANOUS_TASK_BOUND_PR)) ? { boundPrNumber: Number(env.ELANOUS_TASK_BOUND_PR) } : {}), ...(member?.imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}), repoUrl, ...((seedSource.kind === 'default' && sourceBaseSha) ? { source: { ...seedSource, baseSha: sourceBaseSha } } : options.source ? { source: options.source } : {}), ...(options.repairCommitOnly ? { repairCommitOnly: options.repairCommitOnly } : {}), ...(hostMirror ? { hostMirror } : {}), args: jobArgs, passEnv: jobPassEnv, deadlineSeconds: jobDeadlineSeconds, ...(goalDoc ? { goalDoc } : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? { authorSentence: true, ...(env.ELANOUS_POD_AUTHOR_GRADE === 'lite' || env.ELANOUS_POD_AUTHOR_GRADE === 'full' ? { authorGrade: env.ELANOUS_POD_AUTHOR_GRADE } : {}) } : {}), runId: launchRunId, ...(parentRunId ? { parentRunId } : {}), ...(jobArmEnv ? { armEnv: jobArmEnv } : {}), hostId: resolveHostId(env), skillEnvs: Object.keys(skillEnvs), memoryLimit, memoryRequest, imageCommit: jobImageCommit, ...(grok ? { grokCredential: 'grokAuth' in creds && creds.grokAuth ? 'subscription' as const : 'api_key' as const } : {}), ...(codexAccounts ? { codexAccounts } : {}), ...(hostRefresh ? { appCredential: true } : {}), execution: { key: executionKey, attempt: oomRetried ? 2 : 1 }, hostLeaseAdmitted: !!releaseAdmission, ...(roleCodexCredential ? { reviewerCodexAuth: true } : {}), ...(bedrockSpec ? { bedrock: bedrockSpec } : {}), ...(zaiSpec ? { zai: zaiSpec } : {}), ...(zaiFallbackSpec ? { zaiFallback: zaiFallbackSpec } : {}) }); // kubectl 주입(=시험)이면 docker 를 부르지 않는다
|
|
2808
2965
|
const carriedBranch = goalDoc ? 'goal-doc' as const : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'author' as const : undefined;
|
|
2809
2966
|
const carriedChildLlm = carriedBranch ? podDelegatedChildLlm(jobArgs) : undefined;
|
|
2810
2967
|
jobApplyStartedAt = Date.now();
|
|
@@ -2812,6 +2969,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2812
2969
|
zaiPendingApply.delete(name); // apply 뒤엔 Job 라벨이 센다(성공) · 실패면 셀 것이 없다
|
|
2813
2970
|
if (a.status !== 0) { cleanupSecret(); return { exitCode: 1, output: a.stderr, error: { code: 'pod-apply', message: a.stderr.trim() } }; }
|
|
2814
2971
|
releaseAdmission?.applied?.(name, context, namespace);
|
|
2972
|
+
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-config-snapshot', data: {
|
|
2973
|
+
job: name, hash: configSnapshot.hash, keyCount: configSnapshot.keyCount,
|
|
2974
|
+
} }, ledgerDir); } catch (error) {
|
|
2975
|
+
debug.log('self-implement.pod', 'config-snapshot-ledger-unavailable', {
|
|
2976
|
+
job: name, reason: error instanceof Error ? error.message : String(error),
|
|
2977
|
+
}, { level: 'warn' });
|
|
2978
|
+
}
|
|
2815
2979
|
const imageFacts = { job: name, childRunId: liveChildRunId, image: jobImage, imageCommit: jobImageCommit, context };
|
|
2816
2980
|
// POD-LAUNCH-PROVENANCE — append-only «started» row: who · why · when, on the parent's existing run ledger.
|
|
2817
2981
|
const startedRow = { job: name, run: launchRunId, attempt: oomRetried ? 2 : 1, provenance: provenanceRowFromAnnotations(provenance.annotations) };
|
|
@@ -2875,7 +3039,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2875
3039
|
}
|
|
2876
3040
|
}
|
|
2877
3041
|
try {
|
|
2878
|
-
appendRunLedgerEntry({ runId: ledgerRunId,
|
|
3042
|
+
appendRunLedgerEntry({ runId: ledgerRunId, timestamp: new Date((options.now ?? Date.now)()).toISOString(),
|
|
3043
|
+
event: 'pod-child-run', data: { childRunId: liveChildRunId, job: name, attempt: oomRetried ? 2 : 1, ...(goalFile ? { goalFile } : {}) } }, ledgerDir);
|
|
2879
3044
|
appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-job-applied', data: { job: name, childRunId: liveChildRunId, jobUid: lifecycleJobUid, host: member?.sshHost ?? resolveHostId(env), context, namespace } }, ledgerDir);
|
|
2880
3045
|
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);
|
|
2881
3046
|
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);
|
|
@@ -2891,6 +3056,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
2891
3056
|
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 } : {}) });
|
|
2892
3057
|
let state: 'complete' | 'failed' | 'aborted' = 'failed';
|
|
2893
3058
|
let failedReason = '';
|
|
3059
|
+
let deadlineJobCreatedAt: string | null = null;
|
|
3060
|
+
let deadlineJobCompletedAt: string | null = null;
|
|
2894
3061
|
let containerReason: string | null = null;
|
|
2895
3062
|
let containerExitCode: number | null = null;
|
|
2896
3063
|
// JOB-FAILURE-TERMINATION-CAPTURE — this Job's Kubernetes facts, read once at the failure verdict (before GC).
|
|
@@ -3007,6 +3174,11 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3007
3174
|
catch (error) { jobReadError = error; }
|
|
3008
3175
|
const observedJobReason = jobRead?.status === 0 ? podJobConditionReason(jobRead.stdout.split('\t')[0]) : 'unknown';
|
|
3009
3176
|
failedReason = observedJobReason === 'unknown' ? '' : observedJobReason;
|
|
3177
|
+
if (jobRead?.status === 0) {
|
|
3178
|
+
const [, , , createdText, completedText] = jobRead.stdout.replace(/\r?\n$/, '').split('\t');
|
|
3179
|
+
deadlineJobCreatedAt = createdText && Number.isFinite(Date.parse(createdText)) ? createdText : null;
|
|
3180
|
+
deadlineJobCompletedAt = completedText && Number.isFinite(Date.parse(completedText)) ? completedText : null;
|
|
3181
|
+
}
|
|
3010
3182
|
// One Pods read serves both: its first three columns are the classification layout, the rest the termination capture.
|
|
3011
3183
|
let podsRead: { status: number | null; stdout: string } | null = null;
|
|
3012
3184
|
try {
|
|
@@ -3044,8 +3216,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3044
3216
|
if (seen !== null) {
|
|
3045
3217
|
releaseAdmission?.observed?.();
|
|
3046
3218
|
state = seen === 0 ? 'complete' : 'failed';
|
|
3047
|
-
// The child's own rc
|
|
3048
|
-
|
|
3219
|
+
// The child's own rc is the parent's exit code even when 0 — the condition path below yields none here.
|
|
3220
|
+
containerExitCode = seen;
|
|
3049
3221
|
if (seen !== 0) podTermination = readPodTermination({ kubectl, namespace, job: name, path: 'result-marker', jobUid: lifecycleJobUid });
|
|
3050
3222
|
if (seen !== 0) captureFailedJob(liveChildRunId);
|
|
3051
3223
|
debug.log('self-implement.pod', 'result-marker-early', { job: name, waitedMs: Date.now() - waitStartedAt, rc: seen });
|
|
@@ -3102,7 +3274,6 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3102
3274
|
}
|
|
3103
3275
|
await sleep(options.pollMs ?? 15_000);
|
|
3104
3276
|
}
|
|
3105
|
-
await refreshPodTermination();
|
|
3106
3277
|
if (!terminalImageRecorded) recordPodImage(true);
|
|
3107
3278
|
let logs = '';
|
|
3108
3279
|
let logTailReason: string | undefined;
|
|
@@ -3354,17 +3525,65 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3354
3525
|
if (noResultDiagnostic && !noResultDiagnostic.includes('stage=unknown')) {
|
|
3355
3526
|
debug.log('self-implement.pod', 'no-result-ledger-diagnostic', { job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic }, { compact: { stringMax: 500 } });
|
|
3356
3527
|
}
|
|
3528
|
+
// The marker can precede the container status by several seconds. Read the Pod after
|
|
3529
|
+
// collecting the child logs, before the first terminal evidence row is emitted.
|
|
3530
|
+
await refreshPodTermination();
|
|
3357
3531
|
// POD-LAUNCH-PROVENANCE — append-only «finished» row paired with its started row on job·run.
|
|
3358
3532
|
// Keyed on launchRunId like the started row; a reattached Job's inherited child run rides along as childRun.
|
|
3359
3533
|
// exitCode stays null when the container's code was not read (never filled in as 0).
|
|
3360
3534
|
const finishedRow = { job: name, run: launchRunId, ...(liveChildRunId !== launchRunId ? { childRun: liveChildRunId } : {}),
|
|
3361
3535
|
attempt: oomRetried ? 2 : 1, phase: state, exitCode: containerExitCode,
|
|
3362
|
-
reason: failedReason || containerReason || (state === 'complete' ? 'complete' : 'unknown')
|
|
3536
|
+
reason: failedReason || containerReason || (state === 'complete' ? 'complete' : 'unknown'),
|
|
3537
|
+
// POD-TERMINAL-EVIDENCE-JOIN: keep classifier and termination cause on this Job/childRun/attempt row.
|
|
3538
|
+
failureClassification: disposition?.failureClassification ?? null,
|
|
3539
|
+
classificationBasis: disposition?.childEvidence?.classificationBasis ?? null,
|
|
3540
|
+
// The child-run status is a different axis from the implementation's abandoned classification.
|
|
3541
|
+
// Preserve it even when the child did not emit a parseable self-implement disposition.
|
|
3542
|
+
podExitClass: state === 'failed' ? classifyPodExit({ containerReason: containerReason ?? null,
|
|
3543
|
+
containerExitCode: containerExitCode ?? null, jobReason: failedReason || null, logs }).class : null,
|
|
3544
|
+
childFailureStage: childFailure?.stage ?? null,
|
|
3545
|
+
terminationReason: typeof disposition?.childEvidence?.terminationReason === 'string'
|
|
3546
|
+
? redactSecretText(disposition.childEvidence.terminationReason).slice(0, 200) : null };
|
|
3363
3547
|
try { appendRunLedgerEntry({ runId: ledgerRunId, event: POD_LAUNCH_FINISHED_EVENT, timestamp: new Date((options.now ?? Date.now)()).toISOString(), data: finishedRow }, ledgerDir); }
|
|
3364
3548
|
catch (error) { debug.log('pod.provenance', 'history-unavailable', { job: name, row: 'finished', reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
|
|
3365
3549
|
debug.log('pod.provenance', 'job-finished', finishedRow);
|
|
3366
|
-
|
|
3550
|
+
// Keep report-deficit incidents queryable as one bounded event. The child detail field is
|
|
3551
|
+
// intentionally capped elsewhere, so cause evidence must not depend on that full payload.
|
|
3552
|
+
const reportDeficit = disposition?.failureClassification === 'report-deficit';
|
|
3553
|
+
const noResultIncident = state === 'failed' && failedReason !== 'DeadlineExceeded' && !disposition;
|
|
3554
|
+
if (reportDeficit || noResultIncident) {
|
|
3555
|
+
const evidence = disposition?.childEvidence;
|
|
3556
|
+
const diagnosticLines = [
|
|
3557
|
+
...(Array.isArray(evidence?.podLogTail) ? evidence.podLogTail : []),
|
|
3558
|
+
...(typeof evidence?.detail === 'string' ? evidence.detail.split('\n') : []),
|
|
3559
|
+
...(typeof evidence?.detailTail === 'string' ? evidence.detailTail.split('\n') : []),
|
|
3560
|
+
...(typeof evidence?.stderr === 'string' ? evidence.stderr.split('\n') : []),
|
|
3561
|
+
...(Array.isArray(noResultLogEvidence?.logTail) ? noResultLogEvidence.logTail as string[] : []),
|
|
3562
|
+
...(Array.isArray(noResultLogEvidence?.podLogTail) ? noResultLogEvidence.podLogTail as string[] : []),
|
|
3563
|
+
...(typeof noResultLogEvidence?.stderr === 'string' ? noResultLogEvidence.stderr.split('\n') : []),
|
|
3564
|
+
].slice(-12).map((line) => redactSecretText(line).slice(0, 500));
|
|
3565
|
+
debug.log('pod.child', reportDeficit ? 'report-deficit-cause' : 'terminal-cause', {
|
|
3566
|
+
job: name, run: launchRunId, childRun: liveChildRunId, attempt: oomRetried ? 2 : 1,
|
|
3567
|
+
// A missing parsed result is an incident trigger, not proof of the child's classifier.
|
|
3568
|
+
classification: disposition?.failureClassification ?? null,
|
|
3569
|
+
...(noResultIncident ? { trigger: 'no-result' } : {}),
|
|
3570
|
+
podExitClass: finishedRow.podExitClass,
|
|
3571
|
+
classificationBasis: evidence?.classificationBasis ?? null,
|
|
3572
|
+
phase: state, exitCode: containerExitCode,
|
|
3573
|
+
reason: failedReason || containerReason || 'unknown',
|
|
3574
|
+
terminationReason: evidence?.terminationReason ?? null,
|
|
3575
|
+
providerErrors: disposition?.providerErrors ?? null,
|
|
3576
|
+
oomKilled, podTermination: podTermination ?? null,
|
|
3577
|
+
detailTail: evidence?.detailTail ?? null,
|
|
3578
|
+
lastLines: diagnosticLines,
|
|
3579
|
+
}, { level: 'warn', compact: { stringMax: 4_500 } });
|
|
3580
|
+
}
|
|
3581
|
+
debug.log('self-implement.pod', 'job-finished', { job: name, ...(member ? { context: member.context } : {}), state, containerReason, stage: disposition?.stage ?? null, prUrl: disposition?.prUrl ?? null, childRunId: liveChildRunId, attempt: oomRetried ? 2 : 1, ledgerCompleteness,
|
|
3582
|
+
...(noResultLogEvidence ? { stopEvidenceTail: podStopEvidenceTail(noResultLogEvidence) } : {}),
|
|
3367
3583
|
...(podTermination ? { podTermination } : {}),
|
|
3584
|
+
failureClassification: finishedRow.failureClassification,
|
|
3585
|
+
classificationBasis: finishedRow.classificationBasis,
|
|
3586
|
+
terminationReason: finishedRow.terminationReason,
|
|
3368
3587
|
...(state === 'failed' && !oomKilled && failedReason !== 'DeadlineExceeded'
|
|
3369
3588
|
? { ...(childFailure ? { childStage: childFailure.stage } : disposition?.stage ? { childStage: disposition.stage } : {}),
|
|
3370
3589
|
// POD-NORESULT: a parsed result row without error text is not a missing result line (UX 10-07 01:01: 28 of 28 exit-2 Jobs printed one).
|
|
@@ -3429,7 +3648,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3429
3648
|
if (unfitRetry) return unfitRetry;
|
|
3430
3649
|
if (!await acquireAdmission()) return admissionFailure();
|
|
3431
3650
|
member = await acquireSlot();
|
|
3432
|
-
if (options.pool && !member)
|
|
3651
|
+
if (options.pool && !member) {
|
|
3652
|
+
if (lastSlotAttempt) recordSlotObservation(lastSlotAttempt, 'rejected', lastSlotReasonCode ?? 'aborted', {
|
|
3653
|
+
waitReason: stageReason['pool-slot'] ?? null,
|
|
3654
|
+
...(typeof input.signal?.reason === 'string' ? { abortReason: input.signal.reason } : {}),
|
|
3655
|
+
});
|
|
3656
|
+
return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before a pool slot opened', ...(lastSlotReasonCode ? { reasonCode: lastSlotReasonCode } : {}) } };
|
|
3657
|
+
}
|
|
3433
3658
|
if (member) context = member.context;
|
|
3434
3659
|
if (input.signal?.aborted) return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before OOM retry' } };
|
|
3435
3660
|
continue;
|
|
@@ -3453,13 +3678,21 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3453
3678
|
}
|
|
3454
3679
|
// The host still has the complete Pod log here. The CLI only retains a short stdout tail,
|
|
3455
3680
|
// so preserve the parsed child facts in the parent ledger before that tail is returned.
|
|
3456
|
-
|
|
3681
|
+
const childEvidenceRow = podChildEvidenceLedgerRow({
|
|
3682
|
+
job: name,
|
|
3683
|
+
childRunId: liveChildRunId,
|
|
3684
|
+
state,
|
|
3685
|
+
result: disposition ?? null,
|
|
3686
|
+
noResultDiagnostic,
|
|
3687
|
+
noResultLogEvidence,
|
|
3688
|
+
podTermination,
|
|
3689
|
+
});
|
|
3690
|
+
if (childEvidenceRow) {
|
|
3457
3691
|
// Every terminal attempt writes a marker, including one with no parseable child facts.
|
|
3458
3692
|
// The next attempt must never inherit an earlier Pod's classification.
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-evidence', data: { childEvidence, childRunId: liveChildRunId, job: name, ...(podTermination ? { podTermination } : {}) } }, ledgerDir); }
|
|
3693
|
+
// Also persist completed Jobs whose child result is unsuccessful; Kubernetes
|
|
3694
|
+
// Completed is container success, not proof the requested work converged.
|
|
3695
|
+
try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-evidence', data: childEvidenceRow }, ledgerDir); }
|
|
3463
3696
|
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' }); }
|
|
3464
3697
|
}
|
|
3465
3698
|
let prLookup: OpenPrByBranch | undefined;
|
|
@@ -3498,6 +3731,17 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
|
|
|
3498
3731
|
const deadlineExceeded = state === 'failed' && failedReason === 'DeadlineExceeded';
|
|
3499
3732
|
const deadlineSeconds = jobDeadlineSeconds;
|
|
3500
3733
|
if (deadlineExceeded) {
|
|
3734
|
+
const jobCreatedAt = deadlineJobCreatedAt;
|
|
3735
|
+
const timing = podJobFinishedTiming({ jobCreatedAt, jobCompletedAt: deadlineJobCompletedAt,
|
|
3736
|
+
podFinishedAt: typeof podTermination?.finishedAt === 'string' && Number.isFinite(Date.parse(podTermination.finishedAt))
|
|
3737
|
+
? podTermination.finishedAt : null,
|
|
3738
|
+
observedAt: new Date((options.now ?? Date.now)()).toISOString() });
|
|
3739
|
+
const lastStage = deadlineMarker?.stage ?? disposition?.stage ?? null;
|
|
3740
|
+
debug.log('pod.job', 'finished', {
|
|
3741
|
+
job: name, jobCreatedAt, finishedAt: timing.finishedAt, finishedAtSource: timing.finishedAtSource,
|
|
3742
|
+
elapsedMs: timing.elapsedMs,
|
|
3743
|
+
deadlineSec: deadlineSeconds, tier: oomRetried ? retryTier : memoryTier, lastStage,
|
|
3744
|
+
});
|
|
3501
3745
|
debug.log('self-implement.pod', 'deadline-exceeded', {
|
|
3502
3746
|
job: name,
|
|
3503
3747
|
deadlineSeconds,
|
|
@@ -3678,6 +3922,15 @@ function boundedPodLogText(source: string, maxChars: number): string {
|
|
|
3678
3922
|
return redacted.length > maxChars ? `${redacted.slice(0, maxChars)}…[truncated]` : redacted;
|
|
3679
3923
|
}
|
|
3680
3924
|
|
|
3925
|
+
/** A compact, redacted stop clue carried on the attempt-scoped finished row. */
|
|
3926
|
+
function podStopEvidenceTail(evidence: Record<string, unknown>): string[] {
|
|
3927
|
+
const raw = Array.isArray(evidence.logTail) ? evidence.logTail
|
|
3928
|
+
: Array.isArray(evidence.podLogTail) ? evidence.podLogTail
|
|
3929
|
+
: typeof evidence.stderr === 'string' ? evidence.stderr.split(/\r\n|\n|\r/u) : [];
|
|
3930
|
+
return raw.slice(-12).filter((line): line is string => typeof line === 'string' && line.length > 0)
|
|
3931
|
+
.map((line) => redactSecretText(line).slice(0, 240));
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3681
3934
|
/** 로그 꼬리 — 마지막 N줄만, 한 줄씩 비밀값 마스킹. */
|
|
3682
3935
|
export function podNoResultLogTailLines(source: string, maxLines: number = POD_NO_RESULT_LOG_TAIL_LINES): string[] {
|
|
3683
3936
|
const lines = source.replace(/\r\n/g, '\n').split('\n');
|
|
@@ -4006,7 +4259,7 @@ export async function rebuildLocalPodImageOnce(deps: {
|
|
|
4006
4259
|
});
|
|
4007
4260
|
});
|
|
4008
4261
|
});
|
|
4009
|
-
const result = await build('docker
|
|
4262
|
+
const result = await build(['docker', 'harness', 'build.sh'].join(sep));
|
|
4010
4263
|
if (result.status !== 0) {
|
|
4011
4264
|
return { image, action: 'failed', error: `--substrate pod: 이미지 굽기 실패 rc=${result.status}${result.error ? ` (${(result.error as NodeJS.ErrnoException).code ?? result.error.message})` : ''}: ${(result.stdout + result.stderr).slice(-400)}` };
|
|
4012
4265
|
}
|