elanous 0.2.34 → 0.2.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/chunks/{abb4b98b.163e0f56e84ae35d.js → 053a429e.9a63436527cc751c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +287 -0
- package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/190.285c832bd9626f8c.js +64 -0
- package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +36 -0
- package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +149 -0
- package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6086.913a69e6fa3e4a8b.js → 2683.c9773a0c589b031b.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{5576-82d3703636d5c4b9.js → 275-02ea4c2a33980422.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{ffdc3a04.b9c23c1b28dd4a96.js → 2812ca6a.3b9f4a7a08885744.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{9550.d5f76828f972058c.js → 2986.45d7652e4f13557e.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3031-85328a92fcce4da6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8817.61bb7ffbba502ecb.js → 3136.30aaaa5fa03662a3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9131-fce7256c4180c4a5.js → 3148-98efd4869d660a87.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3498.cf2a15a8a9e5b926.js → 3155.2587a55196ecb394.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3103.84470c8445962f04.js → 3324.a09703033abcbd2f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +8 -0
- package/apps/pwa/out/_next/static/chunks/3410.7f9af5ab77cbe65f.js +115 -0
- package/apps/pwa/out/_next/static/chunks/{3819.163d4777f0a597f6.js → 3538.a445e50bb359d068.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +286 -0
- package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3414.172ad4ca2d9b08e8.js → 3727.7949ccaacaa71242.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3757-180308bc61021b05.js +1 -0
- package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +74 -0
- package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9b48c871.204d5d13e7809bd0.js → 3a3d9966.cc4d4585a2708e7c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4116.a84a92a2492c080e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +104 -0
- package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6740.43de73fc427c9fe2.js → 4286.b70c4520306817e8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4304.e9b2512834a9e23e.js +23 -0
- package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8548.036c344973968847.js → 4615.8525eb0add35eba6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +148 -0
- package/apps/pwa/out/_next/static/chunks/{3411-f87314c6c66ebc73.js → 5085-bce4904931767ca6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +93 -0
- package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3110.0a7065f25c841818.js → 528.38ce20ef8aa251ff.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{1644.35dd25240ae24e4b.js → 552.b7d061ad91eeac51.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3837.722e053fb9f321ad.js → 5711.957b095705c12560.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2124.ed5bf480cea7f85b.js → 575.d929793a53f27c4b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7562.948255cbc3e79d33.js → 599.c39c571b6733f2a2.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +79 -0
- package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6466-92e65a48490b68a9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6566.926a1d1b7c911442.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +1 -0
- package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +27 -0
- package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5446.edf141cff9ef647d.js → 6925.562d532110879886.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{7005.1623d2aea78eb85f.js → 6943.c6b24124853a47b2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8368.014caa8de2f5af34.js → 7481.39f7a4654907bf6e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2554.3b5e200f5f5cfcd6.js → 771.c3cdb6c1f7f47c02.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/7784.1f0ac4a16d190cf4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3121.779fafe3e44612c5.js → 7891.03f910124a737985.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8037.e254fd797aa224d1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +1 -0
- package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{9a8cb466.cc9fc9e6e46038aa.js → 873d6c12.09bd499f57171543.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{7431.3051e9b8a4372d2d.js → 8904.7d51af2dc033965c.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +90 -0
- package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +94 -0
- package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1895-60ed0e341c658bd4.js → 9250-072df22eaadaa6b5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +77 -0
- package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2547.dd27303624cb4da8.js → 9514.131c52cc75fe6439.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +1 -0
- package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9f31e478.fefcbcd3c388ebc5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/{page-4fb31eb476dcbad3.js → page-083747f1d4518f61.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-e2de2e59111c9aad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2af16e62c12f22df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-e7abc34a48a6f71e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-c15958835534404b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5014f970-22bef0b5210f7d60.js → ccae1c4b-0cf414f5eff1b10d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4fa33ebd.21c1bd5b294496e6.js → ceba0382.650712b56b85b582.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/da5ecc5c-b005ad8cac737d57.js +1 -0
- package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +1 -0
- package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +1 -0
- package/apps/pwa/out/_next/static/{L04y73dlwKeTW-GetaTF3 → uC-N0emedeNOFuaBQFv-I}/_buildManifest.js +1 -1
- 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 +3 -2
- package/catalog/providers/opengateway.yaml +25 -0
- package/docs/goal-context/01-goal-authoring-checks.md +8 -0
- package/docs/goal-context/03-verification-menu.md +24 -0
- package/docs/goal-context/04-mock-scenarios.md +100 -0
- package/docs/goal-context/05-authoring-lessons.jsonl +47 -0
- package/docs/goal-context/README.md +7 -0
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/default-loop.yaml +63 -4
- package/graphs/document-loop.yaml +51 -3
- package/graphs/implement-loop.yaml +77 -4
- package/graphs/journey/ta-journey.yaml +11 -1
- package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
- package/graphs/journey/units/author-dialogue/observe.ts +96 -0
- package/graphs/journey/units/author-dialogue/recipes.yaml +10 -0
- package/graphs/operate-loop.yaml +51 -3
- package/graphs/release/recipes.yaml +6 -0
- package/graphs/release/release-loop.yaml +17 -4
- package/graphs/research-loop.yaml +137 -3
- package/graphs/test-diet/test-diet.yaml +3 -0
- package/graphs/wizard/recipes.yaml +44 -0
- package/graphs/wizard/wizard-loop.yaml +44 -0
- package/graphs/work/research-report.yaml +2 -0
- package/package.json +1 -1
- package/scripts/ci-typecheck-changed.ts +139 -5
- package/scripts/coord-role-pack.ts +19 -6
- package/scripts/first10-gate.ts +416 -0
- package/scripts/fleet/wsl-node-setup.sh +432 -0
- package/scripts/hq/standby-snapshot.ts +17 -12
- package/scripts/release-loop/docs-land-node.ts +21 -5
- package/scripts/release-loop/docs-node.ts +204 -8
- package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
- package/scripts/release-loop/gate-node.ts +427 -72
- package/scripts/release-loop/gate-partial.ts +65 -11
- package/scripts/release-loop/gate-radius-live.ts +177 -0
- package/scripts/release-loop/gate-radius-shadow.ts +1 -1
- package/scripts/release-loop/node-verdict.ts +14 -1
- package/scripts/release-loop/npm-publish-node.ts +66 -12
- package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
- package/scripts/release-loop/pwa-remote.ts +166 -0
- package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
- package/scripts/release-loop/resume-cap.ts +14 -34
- package/scripts/release-loop/resume-release.ts +78 -15
- package/scripts/release-loop/traffic-node.ts +59 -0
- package/scripts/release-loop/traffic-transition.ts +159 -0
- package/scripts/release-loop/unattended-release.ts +2 -0
- package/scripts/rhythm/daily.ts +137 -3
- package/scripts/test-diet/lib.ts +6 -1
- package/scripts/test-diet/node.ts +194 -13
- package/scripts/ux-sim.ts +92 -0
- package/skills/README.md +1 -0
- package/src/acp/core-turn-bridge.ts +48 -6
- package/src/agent/delegate-hint.ts +16 -0
- package/src/agent/runner.ts +82 -2
- package/src/agent/self-ambient-cache.ts +8 -0
- package/src/agent/task-notification.ts +56 -10
- package/src/agent/types.ts +4 -0
- package/src/agent-substrate/acp-reviewer.ts +39 -4
- package/src/agent-substrate/pr-reviewer.ts +72 -3
- package/src/agent-substrate/review-intent.ts +29 -2
- package/src/agent-substrate/review-observation.ts +3 -0
- package/src/agent-substrate/self-review-cli.ts +229 -28
- package/src/autopilot/mission-codebase-gate.ts +141 -12
- package/src/autopilot/pr-manager.ts +240 -41
- package/src/boot/daemon-tools/self-implement.ts +1 -0
- package/src/budget/run-usage-rollup.ts +1 -0
- package/src/budget/usage-outcomes.ts +8 -4
- package/src/capture/tui-self-report.ts +102 -0
- package/src/chat/goal-continue-verdict.ts +41 -0
- package/src/chat/index.ts +30 -6
- package/src/chat/internal-turn-origin.ts +1 -0
- package/src/chat/paste-fold.ts +86 -0
- package/src/chat/pickers/modal-runtime.ts +10 -27
- package/src/chat/tool-render/block.ts +32 -0
- package/src/chat/tool-render/dispatch.ts +2 -20
- package/src/chat/tool-render/result-text.ts +98 -0
- package/src/chat/turn-typeahead.ts +70 -7
- package/src/cli/agent-cli.ts +13 -2
- package/src/cli/config-audit.ts +119 -0
- package/src/cli/doctor-cli.ts +26 -1
- package/src/cli/guardian-cli.ts +10 -0
- package/src/cli/herdr-cli.ts +34 -0
- package/src/cli/light-entry-route.ts +50 -7
- package/src/cli/log-event-names.ts +2 -0
- package/src/cli/make-cli.ts +247 -11
- package/src/cli/msg-cli.ts +117 -3
- package/src/cli/pod-cli.ts +77 -3
- package/src/cli/pr-cli.ts +34 -18
- package/src/cli/pr-land-base-read.ts +11 -2
- package/src/cli/pr-land-heavy-remote.ts +6 -3
- package/src/cli/pr-land-overlap-evidence.ts +23 -4
- package/src/cli/pr-land-pod-shadow-job.ts +3 -0
- package/src/cli/pr-land-recovery.ts +117 -1
- package/src/cli/pty-takeover-cli.ts +8 -7
- package/src/cli/release-checklist-read-cli.ts +79 -0
- package/src/cli/release-cli.ts +92 -106
- package/src/cli/release-single-flight.ts +1 -1
- package/src/cli/remote-resolve.ts +1 -1
- package/src/cli/root-tui-entry.ts +48 -0
- package/src/cli/sim-cli.ts +22 -0
- package/src/cli/tasks-card-show.ts +162 -0
- package/src/cli/tasks-cli.ts +1065 -338
- package/src/cli/tasks-read-cli.ts +197 -0
- package/src/cli/usage-cli.ts +13 -11
- package/src/clipboard/history.ts +179 -13
- package/src/config.ts +8 -1
- package/src/core-turn/run-core-turn.ts +4 -2
- package/src/core-turn/run-goal-loop.ts +73 -16
- package/src/core-turn/types.ts +6 -1
- package/src/dashboard/chat/acp-chat.ts +8 -0
- package/src/dashboard/context/keys.ts +8 -31
- package/src/dashboard/index.ts +280 -59
- package/src/dashboard/input/agent-wake.ts +7 -1
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +146 -3
- package/src/dashboard/input/chat-main-slash-command.ts +4 -2
- package/src/dashboard/input/goal-continue.ts +210 -0
- package/src/dashboard/input/goal-interim.ts +2 -0
- package/src/dashboard/input/internal-turn.ts +2 -8
- package/src/dashboard/input/seat-autowake.ts +9 -7
- package/src/dashboard/input/turn-autoheal.ts +52 -0
- package/src/dashboard/render/theme-resolver.ts +33 -4
- package/src/dashboard/seat-boot-preamble.ts +132 -5
- package/src/dashboard/slash-runtime/chat-persona.ts +65 -8
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +3 -2
- package/src/dashboard/slash-runtime/model-choices.ts +15 -0
- package/src/dashboard/stale-install-check.ts +3 -99
- package/src/debug/batch-queue.ts +119 -0
- package/src/debug/tui-log-tag.ts +67 -0
- package/src/display/agent-surface.ts +7 -0
- package/src/domains/schedule-registry.ts +16 -2
- package/src/domains/standalone-log-sink.ts +15 -2
- package/src/esc-abort-gate.ts +69 -0
- package/src/git-fs/idle-refresh.ts +76 -0
- package/src/git-fs/index.ts +18 -7
- package/src/git-fs/worktree.ts +137 -5
- package/src/graph-kinds/registry.ts +2 -2
- package/src/graph-runner/graph-cli.ts +18 -0
- package/src/graph-runner/runner.ts +173 -21
- package/src/graph-wizard/generate.ts +108 -4
- package/src/graph-wizard/steps.ts +15 -0
- package/src/grok/credential.ts +10 -3
- package/src/grounding/proactive-ground.ts +86 -0
- package/src/harness/control-inbox.ts +49 -1
- package/src/harness/harness-cli-command.ts +163 -35
- package/src/harness/harness-incidents.ts +85 -1
- package/src/harness/launch-utterance-ledger.ts +208 -0
- package/src/harness/pod-control-send.ts +33 -5
- package/src/harness/self-send-remote.ts +69 -0
- package/src/harness/self-send-routing-guard.ts +6 -0
- package/src/harness/self-send-target.ts +4 -3
- package/src/impl-discipline/detector.ts +16 -4
- package/src/impl-discipline/system-prompt.ts +11 -0
- package/src/impl-discipline/types.ts +2 -2
- package/src/index.ts +822 -154
- package/src/input-core/context-key-runtime.ts +21 -0
- package/src/intake-plane/already-built-hint.ts +4 -2
- package/src/intake-plane/requirement-funnel.ts +29 -1
- package/src/light-cli.ts +32 -11
- package/src/llm/opengateway-models.ts +11 -0
- package/src/llm/provider-credentials.ts +14 -0
- package/src/llm/provider-detect.ts +8 -1
- package/src/llm/runtime-model-family.ts +2 -1
- package/src/llm-wellformed.ts +70 -0
- package/src/llm.ts +247 -59
- package/src/loops/msg-wake.ts +35 -39
- package/src/loops/orchestrator/inbox.ts +59 -11
- package/src/loops/orchestrator/knowhow-pack.ts +364 -0
- package/src/loops/orchestrator/tick.ts +5 -1
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/model-tier/llm-tier-map.ts +15 -1
- package/src/models/prompts.ts +17 -2
- package/src/msg/msg-post-office.ts +116 -0
- package/src/mss/logging/log-store.ts +79 -22
- package/src/native-tool-catalog.ts +15 -1
- package/src/nexus/api/decisions-route.ts +38 -18
- package/src/nexus/api/graph-wizard-api.ts +20 -2
- package/src/nexus/api/loop-resources.ts +13 -1
- package/src/nexus/boot/register-mcp-clients.ts +263 -38
- package/src/nexus/onboarding/first-boot-wizard.ts +56 -8
- package/src/oauth/codex.ts +7 -0
- package/src/onboarding/first-run.ts +37 -6
- package/src/onboarding/web-first.ts +43 -11
- package/src/ops/overview-collect.ts +30 -9
- package/src/ops/overview.ts +22 -9
- package/src/persona/loader.ts +11 -0
- package/src/persona/types.ts +8 -0
- package/src/pr-tool/census.ts +261 -27
- package/src/prompt-library/session-guidance.ts +14 -0
- package/src/provider-summary.ts +8 -0
- package/src/pty-shell/herdr-agent-report.ts +118 -9
- package/src/pty-shell/herdr-prompt.ts +266 -0
- package/src/pty-shell/pty-control-ipc.ts +151 -8
- package/src/pty-shell/pty-manifest.ts +7 -0
- package/src/pty-shell/pty-special-keys.ts +42 -2
- package/src/pty-shell/stale-install-check.ts +99 -0
- package/src/pty-shell/tui-run-state.ts +14 -2
- package/src/release-loop/auto-start.ts +20 -2
- package/src/release-loop/checklist.ts +100 -4
- package/src/release-loop/landed-but-yellow.ts +129 -5
- package/src/release-loop/light-rc.ts +1 -0
- package/src/release-loop/rehearsal.ts +37 -21
- package/src/repl/index.ts +192 -17
- package/src/repl/ops-msg-bridge.ts +32 -0
- package/src/seat-loop/knowhow-lint.ts +1 -1
- package/src/self-dev/ask-launch-flow.ts +44 -5
- package/src/self-dev/cli-help-text.ts +17 -0
- package/src/self-dev/decompose-proposal.ts +172 -20
- package/src/self-dev/decompose.ts +61 -0
- package/src/self-dev/dev-cli.ts +48 -12
- package/src/self-dev/dev-pipeline.ts +8 -2
- package/src/self-dev/draft-residue.ts +37 -1
- package/src/self-dev/draft-sweep.ts +137 -11
- package/src/self-dev/draft-triage-rules.ts +138 -0
- package/src/self-dev/fleet-reduce.ts +3 -2
- package/src/self-dev/glm-credential-guard.ts +77 -0
- package/src/self-dev/graph-front-nodes.ts +112 -0
- package/src/self-dev/graph-journey-nodes.ts +2 -0
- package/src/self-dev/graph-journey-route.ts +12 -2
- package/src/self-dev/harness-run-cli.ts +3 -15
- package/src/self-dev/orchestrate-cli-text.ts +10 -0
- package/src/self-dev/orchestrate-cli.ts +68 -3
- package/src/self-dev/orchestrate.ts +116 -17
- package/src/self-dev/review-provider-fallback.ts +35 -1
- package/src/self-dev/run-supervisor.ts +55 -2
- package/src/self-dev/run-types.ts +1 -1
- package/src/self-dev/self-orchestrate-runtime.ts +1 -11
- package/src/self-dev/shard-aggregate.ts +42 -5
- package/src/self-dev/shard-run.ts +8 -1
- package/src/self-health/autoheal.ts +153 -0
- package/src/self-health/signatures.ts +6 -0
- package/src/self-implement/blocked-draft-policy.ts +20 -0
- package/src/self-implement/classify-shadow.ts +3 -7
- package/src/self-implement/device-first.ts +116 -0
- package/src/self-implement/doctor-visit.ts +257 -2
- package/src/self-implement/evidence-command-budget.ts +80 -0
- package/src/self-implement/gate-baseline.ts +56 -17
- package/src/self-implement/gate-cli.ts +1 -0
- package/src/self-implement/gate-remote.ts +31 -20
- package/src/self-implement/goal-author-cli.ts +1 -0
- package/src/self-implement/goal-author-decompose.ts +534 -45
- package/src/self-implement/goal-author.ts +282 -7
- package/src/self-implement/goal-elaborate.ts +449 -0
- package/src/self-implement/goal-refine.ts +273 -0
- package/src/self-implement/graph-overlay-yaml.ts +14 -3
- package/src/self-implement/graph-variant.ts +40 -6
- package/src/self-implement/headless-elanous-driver.ts +19 -3
- package/src/self-implement/off-diff-evidence.ts +58 -6
- package/src/self-implement/orchestrator.ts +370 -62
- package/src/self-implement/pod-warm-pool-profile.ts +1 -0
- package/src/self-implement/pwa-import-graph.ts +1 -1
- package/src/self-implement/rework-budget-judgment.ts +5 -8
- package/src/self-implement/rework-policy.ts +30 -0
- package/src/self-implement/run-ledger.ts +108 -0
- package/src/self-implement/run-stop.ts +10 -1
- package/src/self-implement/run-ttl.ts +38 -24
- package/src/self-implement/running-runs.ts +29 -1
- package/src/self-implement/scope-adjacency.ts +115 -0
- package/src/self-implement/seams.ts +187 -28
- package/src/self-implement/stop-autoheal.ts +87 -1
- package/src/self-implement/wiring-check.ts +358 -0
- package/src/session-runtime/index.ts +1 -1
- package/src/setup/llm-env-detect.ts +5 -0
- package/src/shell-env-bootstrap.ts +11 -4
- package/src/skills/runner.ts +4 -2
- package/src/skills/tools/agent.ts +408 -40
- package/src/skills/tools/msg-ask.ts +100 -0
- package/src/skills/tools/ops-ledger.ts +2 -1
- package/src/skills/tools/schedule-wakeup.ts +23 -4
- package/src/skills/tools/shell.ts +61 -6
- package/src/skills/tools/terminal-modal-inject.ts +1 -2
- package/src/skills/tools/terminal-modal.ts +10 -8
- package/src/skills/url-router.ts +41 -1
- package/src/smart-wizard/run.ts +66 -0
- package/src/status/bar.ts +34 -6
- package/src/status/status-provider-info.ts +37 -6
- package/src/steward/hold-hygiene.ts +24 -6
- package/src/steward/rejudge-tick.ts +10 -2
- package/src/steward/ta-repair-event-collect.ts +17 -6
- package/src/steward/triage-budget.ts +194 -0
- package/src/steward/triage.ts +20 -3
- package/src/task-agent/actions.ts +72 -2
- package/src/task-agent/green-sweep.ts +4 -0
- package/src/task-agent/land-queue.ts +21 -8
- package/src/task-agent/live-moves.ts +182 -10
- package/src/task-agent/mission.ts +30 -0
- package/src/task-agent/parent-host.ts +123 -3
- package/src/task-agent/rejudge-on-head.ts +15 -0
- package/src/task-agent/repair-cycle.ts +138 -32
- package/src/task-agent/repair-next-move.ts +31 -3
- package/src/task-agent/repair-outcomes.ts +29 -0
- package/src/task-agent/repair-worker.ts +14 -4
- package/src/task-agent/shadow.ts +48 -4
- package/src/task-agent/task-card-prefix.ts +2 -0
- package/src/task-agent/task-hand.ts +525 -57
- package/src/task-agent/task-parent-role-llm.ts +36 -0
- package/src/task-agent/tier-split.ts +196 -0
- package/src/task-agent/work-order-build.ts +2 -0
- package/src/task-agent/work-order.ts +3 -2
- package/src/task-orchestrator/generator-prompt.ts +60 -11
- package/src/task-orchestrator/surfaces/pod-account-broker.ts +42 -0
- package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
- package/src/task-orchestrator/surfaces/pod-child-reuse.ts +146 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +130 -11
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +215 -3
- package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
- package/src/task-orchestrator/surfaces/pod-launch-history.ts +133 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
- package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +19 -2
- package/src/task-orchestrator/surfaces/pod-pool.ts +76 -4
- package/src/task-orchestrator/surfaces/pod-provenance.ts +82 -0
- package/src/task-orchestrator/surfaces/pod-repair-commit.ts +18 -3
- package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +16 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-host.ts +224 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +201 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-provider.ts +444 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-runner.ts +387 -0
- package/src/task-orchestrator/surfaces/pod-si-warm-transport.ts +157 -0
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +18 -0
- package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +6 -2
- package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +7 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +521 -40
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +3 -0
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +759 -50
- package/src/task-orchestrator/surfaces/self-implement.ts +65 -2
- package/src/tool-runtime/index.ts +15 -2
- package/src/tool-runtime/mcp-proxy-bootstrap.ts +29 -0
- package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
- package/src/tty-foreground.ts +155 -0
- package/src/tui/README.md +2 -0
- package/src/tui/chat/background-job-status.ts +54 -0
- package/src/tui/chat/goal-interim.ts +173 -0
- package/src/tui/chat/log-view.ts +267 -0
- package/src/tui/chat/self-health-status.ts +232 -0
- package/src/tui/entry.ts +695 -0
- package/src/tui/input/composer.ts +151 -0
- package/src/tui/seat-mail-boot.ts +59 -0
- package/src/tui/slash/compact-command.ts +7 -0
- package/src/tui/slash/compact.ts +94 -0
- package/src/tui/slash/new-session.ts +35 -0
- package/src/tui/slash/resume.ts +75 -0
- package/src/tui-client/local-chat-turn.ts +282 -0
- package/src/tui-client/local-harness-command.ts +63 -0
- package/src/tui-client/local-provider-command.ts +184 -0
- package/src/tui-client/next-dashboard-runtime.ts +8 -0
- package/src/tui-client/next-loop-command.ts +70 -0
- package/src/tui-client/next-wakeup.ts +191 -0
- package/src/tui.ts +37 -0
- package/src/ui/modal-adapter.ts +2 -2
- package/src/user-config.ts +4 -2
- package/src/ux-sim/classic-tui-seat-scenarios.ts +516 -0
- package/src/ux-sim/cli-config-audit-device.ts +121 -0
- package/src/ux-sim/dashboard-event-loop-stall-monitor-device.ts +238 -0
- package/src/ux-sim/event-monkey.ts +379 -0
- package/src/ux-sim/fake-bin.ts +87 -7
- package/src/ux-sim/fake-herdr.ts +238 -0
- package/src/ux-sim/fake-llm.ts +111 -6
- package/src/ux-sim/fault-glm-no-credential.ts +116 -0
- package/src/ux-sim/fault-nextmove-dispatch.ts +367 -0
- package/src/ux-sim/fault-pod-codex-503.ts +211 -0
- package/src/ux-sim/fault-scope-escape-lift.ts +216 -0
- package/src/ux-sim/fault-tui-400-autoheal.ts +297 -0
- package/src/ux-sim/goal-device.ts +619 -0
- package/src/ux-sim/in-process-cli.ts +22 -5
- package/src/ux-sim/mock-authoring-first-run-child.ts +35 -0
- package/src/ux-sim/mock-authoring-first-run.ts +97 -0
- package/src/ux-sim/mock-seat-pty-frame-child.ts +29 -0
- package/src/ux-sim/mock-seat-pty-frame.ts +297 -0
- package/src/ux-sim/mock-seat-pty-sequence-child.ts +21 -0
- package/src/ux-sim/mock-seat-pty-sequence.ts +206 -0
- package/src/ux-sim/next-tui-seat-scenarios.ts +631 -0
- package/src/ux-sim/onboarding-first-run-device.ts +269 -0
- package/src/ux-sim/pty-key-modifiers-device.ts +85 -0
- package/src/ux-sim/subagent-tools-device.ts +81 -0
- package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +250 -0
- package/src/ux-sim/tty-foreground-steal-child.ts +21 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +0 -79
- package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +0 -94
- package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +0 -23
- package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +0 -115
- package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +0 -8
- package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +0 -1
- package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2987-30cf9c2eb7b8bdd5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3001-5a52788c813b6113.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +0 -104
- package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +0 -286
- package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +0 -149
- package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +0 -148
- package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +0 -64
- package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +0 -74
- package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5028-f0722e6114c313e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5249.96a848656b582a93.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +0 -62
- package/apps/pwa/out/_next/static/chunks/5489.ec2dd1b5272a19dc.js +0 -24
- package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6053-d893974de92e6198.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +0 -1
- package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +0 -77
- package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +0 -90
- package/apps/pwa/out/_next/static/chunks/7193-cf355cca5ba6c5d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7386.5d8e7e42e818dfb6.js +0 -287
- package/apps/pwa/out/_next/static/chunks/7448.478958ffbbba0ac0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +0 -27
- package/apps/pwa/out/_next/static/chunks/7952.b192c31b6a0e00cc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +0 -36
- package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +0 -1
- package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +0 -93
- package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +0 -24
- package/apps/pwa/out/_next/static/chunks/9739.8d5f36ac67a3b236.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +0 -1
- package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-d7bff0f0905a662c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-398c0faa173203f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-df3445b207ceceab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +0 -122
- package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +0 -1
- /package/apps/pwa/out/_next/static/{L04y73dlwKeTW-GetaTF3 → uC-N0emedeNOFuaBQFv-I}/_ssgManifest.js +0 -0
|
@@ -14,9 +14,12 @@
|
|
|
14
14
|
* 이미지는 표준판(elanous-harness)만 — 이 발사 경로는 lite 를 쓰지 않는다.
|
|
15
15
|
*/
|
|
16
16
|
import { spawnSync } from 'node:child_process';
|
|
17
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
18
|
+
import { tmpdir } from 'node:os';
|
|
19
|
+
import { join } from 'node:path';
|
|
17
20
|
import { SPAWN_SYNC_MAX_BUFFER } from '../../util/spawn-sync-output.js';
|
|
18
21
|
import { debug } from '../../debug/log.js';
|
|
19
|
-
import { memberHasRegistry, registryImageRef, type RemoteRun } from './pod-pool.js';
|
|
22
|
+
import { memberHasRegistry, registryImageRef, syncPoolImages, parsePodPool, type PodPoolMember, type RemoteRun } from './pod-pool.js';
|
|
20
23
|
|
|
21
24
|
const POD_IMAGE = 'elanous-harness';
|
|
22
25
|
|
|
@@ -59,6 +62,91 @@ export function resolvePodImageSource(
|
|
|
59
62
|
return { kind: 'pinned', ref: podImageRef(registry, commit), commit, registry };
|
|
60
63
|
}
|
|
61
64
|
|
|
65
|
+
export interface PodShelfImage { readonly commit: string; readonly image: string; readonly action: 'fresh' | 'built' }
|
|
66
|
+
|
|
67
|
+
export function resolvePodShelfRef(ref: string, cwd = process.cwd(), exec = spawnSync): string {
|
|
68
|
+
const requested = ref.trim();
|
|
69
|
+
if (!requested || requested.startsWith('-') || /[\s\x00-\x1f]/u.test(requested)) throw new Error('pod shelf: invalid ref');
|
|
70
|
+
const spec = /^#?(\d+)$/u.exec(requested);
|
|
71
|
+
if (spec) {
|
|
72
|
+
const pr = exec('gh', ['pr', 'view', spec[1]!, '--json', 'headRefOid', '--jq', '.headRefOid'], { cwd, encoding: 'utf8', timeout: 30_000 });
|
|
73
|
+
const sha = String(pr.stdout ?? '').trim().toLowerCase();
|
|
74
|
+
if (pr.status !== 0 || !/^[0-9a-f]{40}$/u.test(sha)) throw new Error(`pod shelf: PR head unavailable: ${requested}`);
|
|
75
|
+
return sha;
|
|
76
|
+
}
|
|
77
|
+
const git = exec('git', ['rev-parse', '--verify', `${requested}^{commit}`], { cwd, encoding: 'utf8', timeout: 30_000 });
|
|
78
|
+
const sha = String(git.stdout ?? '').trim().toLowerCase();
|
|
79
|
+
if (git.status !== 0 || !/^[0-9a-f]{40}$/u.test(sha)) throw new Error(`pod shelf: ref unavailable: ${requested}`);
|
|
80
|
+
return sha;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Checkout only the requested commit; syncPoolImages retains its per-host build lock and SHA12 registry check. */
|
|
84
|
+
export async function putPodShelfImage(ref: string, pool: string, deps: {
|
|
85
|
+
resolve?: (ref: string) => string;
|
|
86
|
+
sync?: typeof syncPoolImages;
|
|
87
|
+
checkout?: (commit: string, dir: string) => void;
|
|
88
|
+
tempDir?: () => string;
|
|
89
|
+
remove?: (dir: string) => void;
|
|
90
|
+
hasRegistry?: (member: PodPoolMember) => boolean;
|
|
91
|
+
} = {}): Promise<PodShelfImage> {
|
|
92
|
+
const members = parsePodPool(pool);
|
|
93
|
+
if (members.length !== 1 || !members[0]!.sshHost) throw new Error('pod shelf: one remote registry pool member is required');
|
|
94
|
+
const member: PodPoolMember = members[0]!;
|
|
95
|
+
if (!(deps.hasRegistry ?? memberHasRegistry)(member)) throw new Error('pod shelf: remote registry unavailable');
|
|
96
|
+
const commit = (deps.resolve ?? resolvePodShelfRef)(ref);
|
|
97
|
+
if (!/^[0-9a-f]{40}$/u.test(commit)) throw new Error('pod shelf: full commit required');
|
|
98
|
+
const registry = member.registry ?? podImageRegistry();
|
|
99
|
+
const image = podImageRef(registry, commit);
|
|
100
|
+
if (!deps.sync && registryImageRef(member, commit) === image) return { commit, image, action: 'fresh' };
|
|
101
|
+
const dir = (deps.tempDir ?? (() => mkdtempSync(join(tmpdir(), 'pod-shelf-'))))();
|
|
102
|
+
try {
|
|
103
|
+
if (deps.checkout) deps.checkout(commit, dir);
|
|
104
|
+
else {
|
|
105
|
+
const clone = spawnSync('git', ['clone', '-q', '--no-checkout', process.cwd(), dir], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
106
|
+
if (clone.status !== 0) throw new Error(`pod shelf: clone failed: ${clone.stderr}`);
|
|
107
|
+
const fetch = spawnSync('git', ['-C', dir, 'fetch', '-q', 'origin', commit], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
108
|
+
if (fetch.status !== 0) {
|
|
109
|
+
const remote = spawnSync('git', ['remote', 'get-url', 'origin'], { encoding: 'utf8', timeout: 10_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
110
|
+
if (remote.status !== 0) throw new Error(`pod shelf: fetch failed: ${fetch.stderr}`);
|
|
111
|
+
const fromOrigin = spawnSync('git', ['-C', dir, 'fetch', '-q', String(remote.stdout).trim(), commit], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
112
|
+
if (fromOrigin.status !== 0) throw new Error(`pod shelf: fetch failed: ${fromOrigin.stderr}`);
|
|
113
|
+
}
|
|
114
|
+
const checkout = spawnSync('git', ['-C', dir, 'checkout', '--detach', commit], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
|
|
115
|
+
if (checkout.status !== 0) throw new Error(`pod shelf: checkout failed: ${checkout.stderr}`);
|
|
116
|
+
}
|
|
117
|
+
const sync = deps.sync ?? syncPoolImages;
|
|
118
|
+
const results = await sync([member], 'elanous-harness:local', commit, {
|
|
119
|
+
buildScript: join(dir, 'docker/harness/build.sh'),
|
|
120
|
+
...(deps.sync ? {} : { ship: () => ({ ok: false, action: 'failed' as const, detail: 'shelf build failed; local image fallback prohibited' }) }),
|
|
121
|
+
remoteBuild: deps.sync ? undefined : async (host, cluster, registry) => {
|
|
122
|
+
const { spawn } = await import('node:child_process');
|
|
123
|
+
return new Promise((done) => {
|
|
124
|
+
const child = spawn('bash', [join(dir, 'docker/harness/build.sh')], { env: { ...process.env, ELANOUS_BUILD_REMOTE: host, ELANOUS_L2_CLUSTER: cluster, ...(registry ? { ELANOUS_BUILD_REGISTRY: registry } : {}) }, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
125
|
+
let output = '';
|
|
126
|
+
child.stdout.on('data', (chunk) => { output += chunk; });
|
|
127
|
+
child.stderr.on('data', (chunk) => { output += chunk; });
|
|
128
|
+
child.on('close', (code) => done({ ok: code === 0, detail: output.slice(-300) }));
|
|
129
|
+
child.on('error', (error) => done({ ok: false, detail: error.message }));
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
const result = results.get(member.context);
|
|
134
|
+
if (!result?.ok || result.imageRef !== image) throw new Error(`pod shelf: image unavailable: ${result?.detail ?? image}`);
|
|
135
|
+
return { commit, image, action: result.action === 'fresh' ? 'fresh' : 'built' };
|
|
136
|
+
} finally { (deps.remove ?? ((path) => rmSync(path, { recursive: true, force: true })))(dir); }
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function listPodShelfImages(pool: string, run: RemoteRun): string[] {
|
|
140
|
+
const member = parsePodPool(pool)[0];
|
|
141
|
+
if (!member?.sshHost) throw new Error('pod shelf: remote pool member required');
|
|
142
|
+
const registry = member.registry ?? podImageRegistry();
|
|
143
|
+
const port = registry.slice(registry.lastIndexOf(':') + 1);
|
|
144
|
+
const result = run(member.sshHost, `curl -fsS --max-time 5 http://localhost:${port}/v2/elanous-harness/tags/list 2>/dev/null`);
|
|
145
|
+
if (result.status !== 0) throw new Error(`pod shelf: registry unavailable: ${result.stderr}`);
|
|
146
|
+
const tags: unknown = JSON.parse(result.stdout).tags;
|
|
147
|
+
return Array.isArray(tags) ? tags.filter((tag): tag is string => typeof tag === 'string' && /^[0-9a-f]{12}$/u.test(tag)).map((tag) => `${registry}/elanous-harness:${tag}`) : [];
|
|
148
|
+
}
|
|
149
|
+
|
|
62
150
|
export function podImageMissingMessage(ref: string): string {
|
|
63
151
|
return `기준 이미지 ${ref} 가 레지스트리에 없다 — 레일이 굽기 전이다`;
|
|
64
152
|
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POD-LAUNCH-PROVENANCE slice 2 — TA/harness si-task Jobs.
|
|
3
|
+
*
|
|
4
|
+
* ① `siTaskPodProvenance` fills the shared provenance set (pod-provenance.ts · #29650) for a si-task Job from the
|
|
5
|
+
* launch env the parent already has (owner · seat · task card · checklist slot · entrance stamp). It never builds
|
|
6
|
+
* labels itself — `podProvenanceMetadata` stays the one builder.
|
|
7
|
+
* ② The history is append-only rows on the parent's existing run ledger (`pod-launch-started` when the Job is
|
|
8
|
+
* applied, `pod-launch-finished` at the terminal verdict) — no new store. `readPodLaunchHistory(runId)` answers
|
|
9
|
+
* «who launched which Pod, when and why, and how did it end» from that ledger alone.
|
|
10
|
+
*/
|
|
11
|
+
import { userInfo } from 'node:os';
|
|
12
|
+
import { LAUNCH_SEATS, resolveLaunchStamp } from '../../harness/launch-stamp.js';
|
|
13
|
+
import { loadRunLedger, runLedgerDir, type RunLedgerEntry } from '../../self-implement/run-ledger.js';
|
|
14
|
+
import type { PodProvenance } from './pod-provenance.js';
|
|
15
|
+
import type { PodWorkIdentity } from './pod-pool.js';
|
|
16
|
+
|
|
17
|
+
export const POD_LAUNCH_STARTED_EVENT = 'pod-launch-started';
|
|
18
|
+
export const POD_LAUNCH_FINISHED_EVENT = 'pod-launch-finished';
|
|
19
|
+
|
|
20
|
+
export interface SiTaskProvenanceInput {
|
|
21
|
+
env: NodeJS.ProcessEnv | Readonly<Record<string, string | undefined>>;
|
|
22
|
+
/** The child runId this Job runs as (`ELANOUS_RUN_ID` inside the Pod). */
|
|
23
|
+
runId: string;
|
|
24
|
+
parentRunId?: string;
|
|
25
|
+
workIdentity: PodWorkIdentity;
|
|
26
|
+
/** ISO-8601 UTC. */
|
|
27
|
+
requestedAt: string;
|
|
28
|
+
feature: string;
|
|
29
|
+
launchHost?: string;
|
|
30
|
+
commit?: string | null;
|
|
31
|
+
version?: string;
|
|
32
|
+
memReq?: string;
|
|
33
|
+
shard?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const text = (value: string | undefined | null): string | undefined => {
|
|
37
|
+
const trimmed = value?.trim();
|
|
38
|
+
return trimmed ? trimmed : undefined;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
function osUser(): string | undefined {
|
|
42
|
+
try { return text(userInfo().username); } catch { return undefined; }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The si-task identity. Actor order: the Job owner the dispatcher named → the launch stamp actor (seat · session · loop)
|
|
47
|
+
* → the OS user. `pool` is deliberately absent: `ELANOUS_POD_POOL` is read as pool config by the child harness.
|
|
48
|
+
*/
|
|
49
|
+
export function siTaskPodProvenance(input: SiTaskProvenanceInput): Partial<PodProvenance> {
|
|
50
|
+
const env = input.env as NodeJS.ProcessEnv;
|
|
51
|
+
const identity = input.workIdentity;
|
|
52
|
+
const stamp = resolveLaunchStamp({}, env);
|
|
53
|
+
const ownerId = text(identity.ownerId);
|
|
54
|
+
const stampActor = text(stamp.actor);
|
|
55
|
+
const user = text(env.USER) ?? text(env.LOGNAME) ?? osUser();
|
|
56
|
+
const actor = ownerId ?? stampActor ?? user;
|
|
57
|
+
const actorKind = ownerId && identity.ownerKind
|
|
58
|
+
? (identity.ownerKind === 'steward' || identity.ownerKind === 'orchestrator' ? 'loop' : identity.ownerKind)
|
|
59
|
+
: stampActor && (LAUNCH_SEATS as readonly string[]).includes(stampActor) ? 'seat'
|
|
60
|
+
: stampActor && stampActor === text(env.ELANOUS_LOOP_NAME) ? 'loop'
|
|
61
|
+
: actor ? 'human' : undefined;
|
|
62
|
+
const authoring = identity.work === 'authoring';
|
|
63
|
+
const entrance = stamp.entrance !== 'unknown' ? stamp.entrance : identity.taskCard ? 'tasks-hand' : undefined;
|
|
64
|
+
const firstLine = input.feature.split('\n', 1)[0]?.trim().slice(0, 160) ?? '';
|
|
65
|
+
const reason = [identity.taskCard ? `TA ${identity.taskCard}` : undefined, firstLine || undefined].filter(Boolean).join(' · ');
|
|
66
|
+
return {
|
|
67
|
+
...(actorKind ? { actorKind } : {}),
|
|
68
|
+
...(actor ? { actor } : {}),
|
|
69
|
+
kind: 'si-task',
|
|
70
|
+
run: input.runId,
|
|
71
|
+
phase: authoring ? 'authoring' : 'impl',
|
|
72
|
+
requestedAt: input.requestedAt,
|
|
73
|
+
character: identity.taskCard ? 'ta-child' : authoring ? 'author-child' : 'harness-child',
|
|
74
|
+
...(entrance ? { entrance } : {}),
|
|
75
|
+
...(text(identity.slotId) ? { cell: identity.slotId } : {}),
|
|
76
|
+
...(text(input.version) ? { version: input.version } : {}),
|
|
77
|
+
...(text(input.commit) ? { commit: input.commit! } : {}),
|
|
78
|
+
...(text(input.launchHost) ? { launchHost: input.launchHost } : {}),
|
|
79
|
+
...(text(input.shard) ? { shard: input.shard } : {}),
|
|
80
|
+
...(text(input.memReq) ? { memReq: input.memReq } : {}),
|
|
81
|
+
...(text(input.parentRunId) ? { parent: input.parentRunId } : {}),
|
|
82
|
+
...(reason ? { reason } : {}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** `elanous.ai/<key>` annotations → `{ <key>: value }` for the started row (full values, not the 63-char labels). */
|
|
87
|
+
export function provenanceRowFromAnnotations(annotations: Readonly<Record<string, string>>): Record<string, string> {
|
|
88
|
+
const row: Record<string, string> = {};
|
|
89
|
+
for (const [key, value] of Object.entries(annotations)) if (key.startsWith('elanous.ai/')) row[key.slice('elanous.ai/'.length)] = value;
|
|
90
|
+
return row;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface PodLaunchRecord {
|
|
94
|
+
job: string;
|
|
95
|
+
run: string;
|
|
96
|
+
attempt: number | null;
|
|
97
|
+
startedAt: string | null;
|
|
98
|
+
provenance: Record<string, string>;
|
|
99
|
+
finished: { at: string | null; phase: string; exitCode: number | null; reason: string } | null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const str = (value: unknown): string | undefined => (typeof value === 'string' && value ? value : undefined);
|
|
103
|
+
|
|
104
|
+
/** Rebuild launch records from one run ledger. Rows pair on job·run; an unpaired row stays visible (never dropped). */
|
|
105
|
+
export function readPodLaunchHistory(runId: string, dir: string = runLedgerDir()): PodLaunchRecord[] {
|
|
106
|
+
const entries: RunLedgerEntry[] = loadRunLedger(runId, dir) ?? [];
|
|
107
|
+
const records: PodLaunchRecord[] = [];
|
|
108
|
+
const open = new Map<string, PodLaunchRecord>();
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
if (entry.event !== POD_LAUNCH_STARTED_EVENT && entry.event !== POD_LAUNCH_FINISHED_EVENT) continue;
|
|
111
|
+
const job = str(entry.data.job) ?? 'unknown';
|
|
112
|
+
const run = str(entry.data.run) ?? 'unknown';
|
|
113
|
+
const key = `${job}\u0000${run}`;
|
|
114
|
+
if (entry.event === POD_LAUNCH_STARTED_EVENT) {
|
|
115
|
+
const provenance: Record<string, string> = {};
|
|
116
|
+
const raw = entry.data.provenance;
|
|
117
|
+
if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
|
|
118
|
+
for (const [name, value] of Object.entries(raw as Record<string, unknown>)) if (typeof value === 'string') provenance[name] = value;
|
|
119
|
+
}
|
|
120
|
+
const record: PodLaunchRecord = { job, run, attempt: typeof entry.data.attempt === 'number' ? entry.data.attempt : null,
|
|
121
|
+
startedAt: entry.timestamp ?? null, provenance, finished: null };
|
|
122
|
+
records.push(record);
|
|
123
|
+
open.set(key, record);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const finished = { at: entry.timestamp ?? null, phase: str(entry.data.phase) ?? 'unknown',
|
|
127
|
+
exitCode: typeof entry.data.exitCode === 'number' ? entry.data.exitCode : null, reason: str(entry.data.reason) ?? 'unknown' };
|
|
128
|
+
const started = open.get(key);
|
|
129
|
+
if (started && !started.finished) { started.finished = finished; open.delete(key); continue; }
|
|
130
|
+
records.push({ job, run, attempt: typeof entry.data.attempt === 'number' ? entry.data.attempt : null, startedAt: null, provenance: {}, finished });
|
|
131
|
+
}
|
|
132
|
+
return records;
|
|
133
|
+
}
|
|
@@ -236,6 +236,10 @@ export interface ExternalGitHubProbe {
|
|
|
236
236
|
githubHttps: boolean | null;
|
|
237
237
|
measuredAt: string | null;
|
|
238
238
|
reason: string | null;
|
|
239
|
+
/** Name of the disposable Pod for matching this reading with its Kubernetes logs. */
|
|
240
|
+
podName?: string;
|
|
241
|
+
/** Unmodified stdout from `kubectl logs` for this Pod (only present when readable). */
|
|
242
|
+
podLog?: string;
|
|
239
243
|
}
|
|
240
244
|
const DNS_CACHE_MS = 10 * 60_000;
|
|
241
245
|
const DNS_STALE_OK_MS = 30 * 60_000;
|
|
@@ -261,9 +265,11 @@ export function probePoolGitHub(context: string, kubectl: PoolKubectl = leaseKub
|
|
|
261
265
|
if (typeof record?.at !== 'number' || now() < record.at || now() - record.at >= 60_000) return null;
|
|
262
266
|
if (typeof record.measuredAt !== 'string' || ![true, false].includes(record.externalDns as boolean) ||
|
|
263
267
|
![true, false, null].includes(record.githubHttps as boolean | null) ||
|
|
264
|
-
!(record.reason === null || typeof record.reason === 'string')
|
|
268
|
+
!(record.reason === null || typeof record.reason === 'string') ||
|
|
269
|
+
typeof record.podName !== 'string' || typeof record.podLog !== 'string') return null;
|
|
265
270
|
return { externalDns: record.externalDns as boolean, githubHttps: record.githubHttps as boolean | null,
|
|
266
|
-
measuredAt: record.measuredAt, reason: record.reason as string | null
|
|
271
|
+
measuredAt: record.measuredAt, reason: record.reason as string | null,
|
|
272
|
+
podName: record.podName, podLog: record.podLog };
|
|
267
273
|
} catch { return null; }
|
|
268
274
|
};
|
|
269
275
|
const fresh = cached();
|
|
@@ -285,6 +291,7 @@ export function probePoolGitHub(context: string, kubectl: PoolKubectl = leaseKub
|
|
|
285
291
|
const shared = cached();
|
|
286
292
|
if (shared) return shared;
|
|
287
293
|
const result = runPoolGitHubProbe(context, kubectl, new Date(now()).toISOString());
|
|
294
|
+
debug.log('pod.lease', 'github-egress-probe', { context, ...result });
|
|
288
295
|
if (result.measuredAt !== null) {
|
|
289
296
|
const temp = `${cache}.${randomUUID()}.tmp`;
|
|
290
297
|
try { writeFileSync(temp, JSON.stringify({ ...result, at: now() }), { mode: 0o600 }); renameSync(temp, cache); }
|
|
@@ -300,16 +307,18 @@ export function probePoolGitHub(context: string, kubectl: PoolKubectl = leaseKub
|
|
|
300
307
|
function runPoolGitHubProbe(context: string, kubectl: PoolKubectl, measuredAt: string): ExternalGitHubProbe {
|
|
301
308
|
const name = `elanous-egress-${randomUUID().slice(0, 12)}`;
|
|
302
309
|
const base = ['--context', context, '--request-timeout=15s'];
|
|
303
|
-
const unknown = (reason: string): ExternalGitHubProbe => ({ externalDns: null, githubHttps: null, measuredAt: null, reason });
|
|
304
310
|
let created = false;
|
|
311
|
+
const unknown = (reason: string): ExternalGitHubProbe => ({ externalDns: null, githubHttps: null, measuredAt: null, reason,
|
|
312
|
+
...(created ? { podName: name } : {}) });
|
|
305
313
|
try {
|
|
306
314
|
const manifest = JSON.stringify({ apiVersion: 'v1', kind: 'Pod', metadata: { name, namespace: 'elanous-test', labels: { 'elanous.probe': 'github-egress' } }, spec: {
|
|
307
315
|
restartPolicy: 'Never', activeDeadlineSeconds: 35, automountServiceAccountToken: false,
|
|
308
316
|
containers: [{ name: 'probe', image: 'busybox:1.36', command: ['sh', '-c',
|
|
309
|
-
'if nslookup github.com
|
|
317
|
+
'if nslookup github.com 2>&1; then echo EXTERNAL_DNS_OK; if wget -T 8 -O /dev/null https://github.com/ 2>&1; then echo GITHUB_HTTPS_OK; else echo GITHUB_HTTPS_FAILED; fi; else echo EXTERNAL_DNS_FAILED; fi'],
|
|
310
318
|
resources: { requests: { cpu: '0', memory: '16Mi' }, limits: { cpu: '100m', memory: '64Mi' } } }],
|
|
311
319
|
} });
|
|
312
|
-
|
|
320
|
+
const createdPod = kubectl([...base, 'create', '-f', '-'], manifest);
|
|
321
|
+
if (createdPod.status !== 0) return unknown(`probe create failed${createdPod.stderr.trim() ? `: ${createdPod.stderr.trim().split('\n').pop()!.slice(0, 160)}` : ''}`);
|
|
313
322
|
created = true;
|
|
314
323
|
const waited = kubectl([...base, '-n', 'elanous-test', 'wait', '--for=jsonpath={.status.phase}=Succeeded', `pod/${name}`, '--timeout=25s']);
|
|
315
324
|
const podResult = kubectl([...base, '-n', 'elanous-test', 'get', `pod/${name}`, '-o', 'json']);
|
|
@@ -327,10 +336,10 @@ function runPoolGitHubProbe(context: string, kubectl: PoolKubectl, measuredAt: s
|
|
|
327
336
|
const httpsOk = markers.includes('GITHUB_HTTPS_OK');
|
|
328
337
|
const httpsFail = markers.includes('GITHUB_HTTPS_FAILED');
|
|
329
338
|
if (dnsFail && !dnsOk && !httpsOk && !httpsFail)
|
|
330
|
-
return { externalDns: false, githubHttps: null, measuredAt, reason: 'external DNS failed' };
|
|
339
|
+
return { externalDns: false, githubHttps: null, measuredAt, reason: 'external DNS failed', podName: name, podLog: logs.stdout };
|
|
331
340
|
if (dnsOk && !dnsFail && httpsOk !== httpsFail)
|
|
332
|
-
return { externalDns: true, githubHttps: httpsOk, measuredAt, reason: httpsFail ? 'GitHub HTTPS failed' : null };
|
|
333
|
-
return unknown(waited.status === 0 ? 'probe output unavailable' : 'probe timeout');
|
|
341
|
+
return { externalDns: true, githubHttps: httpsOk, measuredAt, reason: httpsFail ? 'GitHub HTTPS failed' : null, podName: name, podLog: logs.stdout };
|
|
342
|
+
return { ...unknown(waited.status === 0 ? 'probe output unavailable' : 'probe timeout'), podLog: logs.stdout };
|
|
334
343
|
} catch { return unknown('probe failed'); }
|
|
335
344
|
finally {
|
|
336
345
|
if (created) try { kubectl([...base, '-n', 'elanous-test', 'delete', `pod/${name}`, '--ignore-not-found=true', '--wait=false']); }
|
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
import { BUDGET_SNAPSHOT_ENV } from '../../execution-loop/launch-gate.js';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/** The Pod push fence embeds a different six-hex run key in each independent launch. */
|
|
4
|
+
export function stablePodRunGuard(text: string): string {
|
|
5
|
+
return text.replace(/pr-create-r[0-9a-f]{6}-/g, 'pr-create-r<run>-')
|
|
6
|
+
.replace(/-r[0-9a-f]{6}(?=[-|*])/g, '-r<run>');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Preserve the manifest contract except for the budget timestamp and run identities generated per launch.
|
|
4
10
|
export function stablePodManifestText(applied: Array<Record<string, any>>): string {
|
|
5
11
|
const manifests = structuredClone(applied.filter((entry) => entry.kind === 'Job' || entry.kind === 'Secret'));
|
|
6
12
|
let snapshots = 0;
|
|
7
13
|
for (const manifest of manifests) {
|
|
8
14
|
if (manifest.kind !== 'Job') continue;
|
|
15
|
+
// POD-LAUNCH-PROVENANCE — the request time and the 8-char run/parent labels are per launch like the run id.
|
|
16
|
+
for (const meta of [manifest.metadata, manifest.spec?.template?.metadata]) {
|
|
17
|
+
for (const bag of [meta?.labels, meta?.annotations]) {
|
|
18
|
+
if (!bag) continue;
|
|
19
|
+
if (bag['elanous.ai/requested-at'] !== undefined) bag['elanous.ai/requested-at'] = '<requested-at>';
|
|
20
|
+
if (meta?.labels === bag) for (const key of ['elanous.ai/run', 'elanous.ai/parent']) if (bag[key] !== undefined) bag[key] = '<run-label>';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (const container of manifest.spec?.template?.spec?.containers ?? []) {
|
|
24
|
+
for (const entry of container.env ?? []) if (entry.name === 'ELANOUS_POD_REQUESTED_AT') entry.value = '<requested-at>';
|
|
25
|
+
}
|
|
9
26
|
for (const container of manifest.spec?.template?.spec?.containers ?? []) {
|
|
10
27
|
for (const entry of container.env ?? []) {
|
|
11
28
|
if (entry.name !== BUDGET_SNAPSHOT_ENV) continue;
|
|
@@ -19,5 +36,5 @@ export function stablePodManifestText(applied: Array<Record<string, any>>): stri
|
|
|
19
36
|
}
|
|
20
37
|
}
|
|
21
38
|
if (snapshots === 0) throw new Error('manifest comparison requires a budget snapshot');
|
|
22
|
-
return JSON.stringify(manifests).replace(/run-[0-9a-f-]{36}/g, 'run-<id>');
|
|
39
|
+
return stablePodRunGuard(JSON.stringify(manifests).replace(/run-[0-9a-f-]{36}/g, 'run-<id>'));
|
|
23
40
|
}
|
|
@@ -89,14 +89,29 @@ function defaultLocalImageInspect(image: string): { status: number | null; stdou
|
|
|
89
89
|
return { status: r.status, stdout: r.stdout ?? '' };
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/** 레지스트리 안 이미지 이름 — `docker/harness/build.sh` 의 full/lite 규칙 그대로. */
|
|
93
|
+
function podRegistryImageName(image: string): string {
|
|
94
|
+
return image === 'elanous-harness-lite:local' ? 'elanous-harness-lite' : 'elanous-harness';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** 레지스트리 태그 = 커밋 앞 12자리 (build.sh:295 와 같은 규칙). */
|
|
98
|
+
function podRegistryTag(commit: string): string {
|
|
99
|
+
return commit.slice(0, 12);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** 노드 로컬 레지스트리의 HTTP 포트 — 호스트에서는 같은 포트의 localhost 로 조회한다. */
|
|
103
|
+
function memberRegistryPort(member: PodPoolMember): string {
|
|
104
|
+
const registry = memberRegistry(member);
|
|
105
|
+
return registry.slice(registry.lastIndexOf(':') + 1);
|
|
106
|
+
}
|
|
107
|
+
|
|
92
108
|
/** 이 커밋의 이미지가 노드 레지스트리에 있나 — 있으면 클러스터 안 이미지 주소. */
|
|
93
109
|
export function registryImageRef(member: PodPoolMember, commit: string | null, run: RemoteRun = defaultRemoteRun, image = 'elanous-harness:local'): string | null {
|
|
94
110
|
if (!member.sshHost || !commit) return null;
|
|
95
|
-
const imageName = image
|
|
96
|
-
const tag = commit
|
|
111
|
+
const imageName = podRegistryImageName(image);
|
|
112
|
+
const tag = podRegistryTag(commit);
|
|
97
113
|
const registry = memberRegistry(member);
|
|
98
|
-
const
|
|
99
|
-
const r = run(member.sshHost, `curl -fsS --max-time 5 http://localhost:${port}/v2/${imageName}/tags/list 2>/dev/null`);
|
|
114
|
+
const r = run(member.sshHost, `curl -fsS --max-time 5 http://localhost:${memberRegistryPort(member)}/v2/${imageName}/tags/list 2>/dev/null`);
|
|
100
115
|
if (r.status !== 0) return null;
|
|
101
116
|
try {
|
|
102
117
|
const tags = (JSON.parse(r.stdout) as { tags?: string[] }).tags ?? [];
|
|
@@ -104,6 +119,54 @@ export function registryImageRef(member: PodPoolMember, commit: string | null, r
|
|
|
104
119
|
} catch { return null; }
|
|
105
120
|
}
|
|
106
121
|
|
|
122
|
+
/** 레지스트리 HTTP 한 번 — 노드에서 `curl -fsS --max-time 5`(registryImageRef 와 같은 규칙). 실패면 null. */
|
|
123
|
+
function registryHttpGet(member: PodPoolMember, path: string, run: RemoteRun, accept?: string): string | null {
|
|
124
|
+
if (!member.sshHost) return null;
|
|
125
|
+
const header = accept ? `-H 'Accept: ${accept}' ` : '';
|
|
126
|
+
const r = run(member.sshHost, `curl -fsS --max-time 5 ${header}http://localhost:${memberRegistryPort(member)}/v2/${path} 2>/dev/null`);
|
|
127
|
+
return r.status === 0 && r.stdout.trim() ? r.stdout : null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function registryLabelValue(raw: unknown): string | null {
|
|
131
|
+
return typeof raw === 'string' && raw.trim() && raw !== '<no value>' ? raw.trim() : null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* GATE-REGISTRY-IMAGE-FASTPATH (0.2.36): 레지스트리 HTTP 만으로 이 커밋 태그 이미지의 config label 을 읽는다 —
|
|
136
|
+
* 노드 Docker 데몬(`docker image inspect`)을 부르지 않는다. 태그 결손 · HTTP 오류 · manifest list(단일 config 없음) ·
|
|
137
|
+
* 비JSON 은 null 이다(판정하지 않고 종전 경로로 떨어진다).
|
|
138
|
+
* GET /v2/<이미지>/manifests/<커밋12> → config.digest → GET /v2/<이미지>/blobs/<digest> → config.Labels
|
|
139
|
+
*/
|
|
140
|
+
export function registryImageLabels(member: PodPoolMember, image: string, commit: string | null, run: RemoteRun = defaultRemoteRun): { commit: string | null; skills: string | null } | null {
|
|
141
|
+
if (!member.sshHost || !commit) return null;
|
|
142
|
+
const imageName = podRegistryImageName(image);
|
|
143
|
+
const manifest = registryHttpGet(member, `${imageName}/manifests/${podRegistryTag(commit)}`, run, 'application/vnd.docker.distribution.manifest.v2+json');
|
|
144
|
+
if (!manifest) return null;
|
|
145
|
+
let digest: string | undefined;
|
|
146
|
+
try { digest = (JSON.parse(manifest) as { config?: { digest?: string } }).config?.digest; } catch { return null; }
|
|
147
|
+
if (!digest) return null;
|
|
148
|
+
// config digest 는 `sha256:<64 hex>` — 이 형태가 아니면 경로에 넣지 않는다.
|
|
149
|
+
if (!/^sha256:[0-9a-f]{64}$/u.test(digest)) return null;
|
|
150
|
+
const blob = registryHttpGet(member, `${imageName}/blobs/${digest}`, run);
|
|
151
|
+
if (!blob) return null;
|
|
152
|
+
let labels: Record<string, unknown> | undefined;
|
|
153
|
+
try { labels = (JSON.parse(blob) as { config?: { Labels?: Record<string, unknown> } }).config?.Labels; } catch { return null; }
|
|
154
|
+
if (!labels || typeof labels !== 'object') return null;
|
|
155
|
+
return { commit: registryLabelValue(labels['elanous.commit']), skills: registryLabelValue(labels['elanous.pod-skills']) };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 이 커밋 태그의 이미지 label 이 이번 발사 값과 모두 맞나 — 맞으면 Docker 조회 없이 그 판을 쓸 수 있다.
|
|
160
|
+
* 커밋 label 은 발사 커밋과 «정확히» 같아야 한다(태그가 다른 판을 가리키는 경우를 거른다).
|
|
161
|
+
* `localSkillsDigest` 가 없으면(모르는 값) 커밋 label 만 본다 — syncPoolImages 의 종전 skillsSame 과 같은 뜻.
|
|
162
|
+
*/
|
|
163
|
+
export function registryImageLabelsMatch(member: PodPoolMember, image: string, commit: string | null, opts: { localSkillsDigest?: string | null; run?: RemoteRun } = {}): boolean {
|
|
164
|
+
if (!commit) return false;
|
|
165
|
+
const labels = registryImageLabels(member, image, commit, opts.run ?? defaultRemoteRun);
|
|
166
|
+
if (!labels || labels.commit !== commit) return false;
|
|
167
|
+
return opts.localSkillsDigest == null || labels.skills === opts.localSkillsDigest;
|
|
168
|
+
}
|
|
169
|
+
|
|
107
170
|
/** IMAGE-ONE-SOURCE: 이 멤버의 노드에 레지스트리 컨테이너가 있나(syncPoolImages 의 판정과 같은 명령). 로컬 멤버는 false. */
|
|
108
171
|
export function memberHasRegistry(member: PodPoolMember, run: RemoteRun = defaultRemoteRun): boolean {
|
|
109
172
|
if (!member.sshHost) return false;
|
|
@@ -873,6 +936,15 @@ export async function syncPoolImages(members: readonly PodPoolMember[], image: s
|
|
|
873
936
|
await Promise.all(members.map(async (m) => {
|
|
874
937
|
const t0 = Date.now();
|
|
875
938
|
if (!m.sshHost) { results.set(m.context, { ok: true, action: 'local', detail: 'this machine', ms: 0 }); return; }
|
|
939
|
+
// ⭐ GATE-REGISTRY-IMAGE-FASTPATH (0.2.36 · OP): 레지스트리 커밋 태그의 config label(commit ⊕ pod-skills)이 이번 발사
|
|
940
|
+
// 값과 같으면 노드 Docker 데몬을 «한 번도» 부르지 않고 그 커밋 ref 로 끝난다 — 데몬 조회가 느려도 gate 첫 Pod 이 뜬다.
|
|
941
|
+
// 태그 결손 · label 불일치 · HTTP 오류면 아래 종전 경로(원격 inspect → 노드 빌드 → 통째 전송)가 그대로 판정한다.
|
|
942
|
+
if (localCommit && registryImageLabelsMatch(m, image, localCommit, { ...(deps.localSkillsDigest !== undefined ? { localSkillsDigest: deps.localSkillsDigest } : {}), run })) {
|
|
943
|
+
const imageRef = `${memberRegistry(m)}/${podRegistryImageName(image)}:${podRegistryTag(localCommit)}`;
|
|
944
|
+
debug.log('pod.pool', 'image-fresh-registry-label', { context: m.context, host: m.sshHost, commit: localCommit, imageRef, skills: deps.localSkillsDigest ?? null, waitedMs: 0 });
|
|
945
|
+
results.set(m.context, { ok: true, action: 'fresh', detail: localCommit.slice(0, 12), ms: Date.now() - t0, imageRef });
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
876
948
|
const before = remoteImageCommit(m, image, run);
|
|
877
949
|
const skillsNow = deps.localSkillsDigest;
|
|
878
950
|
const refBefore = registryImageRef(m, localCommit, run, image);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { redactSecretText } from '../../debug/log.js';
|
|
2
|
+
|
|
3
|
+
/** The work that owns a Pod. Job metadata is the current view; pod.provenance events retain history. */
|
|
4
|
+
export interface PodProvenance {
|
|
5
|
+
actorKind: string;
|
|
6
|
+
actor: string;
|
|
7
|
+
kind: string;
|
|
8
|
+
run: string;
|
|
9
|
+
phase: string;
|
|
10
|
+
requestedAt: string;
|
|
11
|
+
character?: string;
|
|
12
|
+
launchHost?: string;
|
|
13
|
+
entrance?: string;
|
|
14
|
+
graphNode?: string;
|
|
15
|
+
cell?: string;
|
|
16
|
+
version?: string;
|
|
17
|
+
commit?: string;
|
|
18
|
+
shard?: string;
|
|
19
|
+
reason?: string;
|
|
20
|
+
/** Parent runId / lease id — whose child this Pod is. Label keeps the first 8 characters like run/commit. */
|
|
21
|
+
parent?: string;
|
|
22
|
+
pool?: string;
|
|
23
|
+
cpuReq?: string;
|
|
24
|
+
memReq?: string;
|
|
25
|
+
warmReused?: boolean;
|
|
26
|
+
argv?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const required = ['actorKind', 'actor', 'kind', 'run', 'phase', 'requestedAt'] as const;
|
|
30
|
+
const names: Record<keyof PodProvenance, string> = {
|
|
31
|
+
actorKind: 'actor-kind', actor: 'actor', kind: 'kind', run: 'run', phase: 'phase', requestedAt: 'requested-at',
|
|
32
|
+
character: 'character', launchHost: 'launch-host', entrance: 'entrance', graphNode: 'graph-node', cell: 'cell',
|
|
33
|
+
version: 'version', commit: 'commit', shard: 'shard', reason: 'reason', parent: 'parent',
|
|
34
|
+
pool: 'pool', cpuReq: 'cpu-req', memReq: 'mem-req',
|
|
35
|
+
warmReused: 'warm-reused', argv: 'argv',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** Every child env name the set can carry (`ELANOUS_POD_<KEY>`). */
|
|
39
|
+
export const POD_PROVENANCE_ENV_NAMES: readonly string[] = Object.values(names)
|
|
40
|
+
.map((name) => `ELANOUS_POD_${name.toUpperCase().replaceAll('-', '_')}`);
|
|
41
|
+
|
|
42
|
+
const labelValue = (value: string): string => {
|
|
43
|
+
const cleaned = value.toLowerCase().replace(/[^a-z0-9._-]/g, '-').replace(/^[^a-z0-9]+|[^a-z0-9]+$/g, '');
|
|
44
|
+
return cleaned.slice(0, 63).replace(/[^a-z0-9]+$/g, '') || 'unknown';
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export interface PodProvenanceMetadata {
|
|
48
|
+
labels: Record<string, string>;
|
|
49
|
+
annotations: Record<string, string>;
|
|
50
|
+
env: Array<{ name: string; value: string }>;
|
|
51
|
+
missing: string[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** A gate reports missing identity as `unknown`; every other launch refuses it before kubectl apply. */
|
|
55
|
+
export function podProvenanceMetadata(input: Partial<PodProvenance> | undefined, gate = false): PodProvenanceMetadata {
|
|
56
|
+
const missing = required.filter((key) => typeof input?.[key] !== 'string' || !input?.[key]?.trim());
|
|
57
|
+
if (missing.length && !gate) throw new Error(`pod provenance missing: ${missing.map((key) => names[key]).join(', ')}`);
|
|
58
|
+
const values: Record<string, string> = {};
|
|
59
|
+
for (const [key, name] of Object.entries(names) as Array<[keyof PodProvenance, string]>) {
|
|
60
|
+
const raw = input?.[key];
|
|
61
|
+
if (raw === undefined || raw === null || raw === '') continue;
|
|
62
|
+
const value = String(raw).trim();
|
|
63
|
+
if (!value) continue;
|
|
64
|
+
// Metadata and env are observable by many users. Never carry a raw secret through an identity field.
|
|
65
|
+
const redacted = redactSecretText(value);
|
|
66
|
+
if (redacted !== value && key !== 'reason' && key !== 'argv') throw new Error(`pod provenance secret in ${name}`);
|
|
67
|
+
values[name] = redacted;
|
|
68
|
+
}
|
|
69
|
+
for (const key of missing) values[names[key]] = 'unknown';
|
|
70
|
+
// The launch reason is observable even when the caller cannot supply one.
|
|
71
|
+
values.reason ??= 'unknown';
|
|
72
|
+
const labels: Record<string, string> = {};
|
|
73
|
+
const annotations: Record<string, string> = {};
|
|
74
|
+
const env: Array<{ name: string; value: string }> = [];
|
|
75
|
+
for (const [name, value] of Object.entries(values)) {
|
|
76
|
+
const label = name === 'run' || name === 'commit' || name === 'parent' ? value.slice(0, 8) : value;
|
|
77
|
+
if (name !== 'reason' && name !== 'argv') labels[`elanous.ai/${name}`] = labelValue(label);
|
|
78
|
+
annotations[`elanous.ai/${name}`] = value;
|
|
79
|
+
env.push({ name: `ELANOUS_POD_${name.toUpperCase().replaceAll('-', '_')}`, value });
|
|
80
|
+
}
|
|
81
|
+
return { labels, annotations, env, missing: missing.map((key) => names[key]) };
|
|
82
|
+
}
|
|
@@ -3,6 +3,7 @@ import { execFileSync } from 'node:child_process';
|
|
|
3
3
|
import { createHash } from 'node:crypto';
|
|
4
4
|
import { mkdirSync, readFileSync, realpathSync, statSync, writeFileSync } from 'node:fs';
|
|
5
5
|
import { isAbsolute, join, resolve } from 'node:path';
|
|
6
|
+
import { classifyGateEnvDeficit, GATE_ENV_DEFICIT_HARVESTABLE_MARK } from '../../self-implement/gate-env-retry.js';
|
|
6
7
|
|
|
7
8
|
export const REPAIR_REF = 'refs/elanous/repair/result';
|
|
8
9
|
export const REPAIR_BUNDLE_MAX_BYTES = 5 * 1024 * 1024;
|
|
@@ -39,15 +40,29 @@ function completedWorktree(output: string): { path: string; runId: string } {
|
|
|
39
40
|
let value: Record<string, unknown>;
|
|
40
41
|
try { value = JSON.parse(line) as Record<string, unknown>; } catch { continue; }
|
|
41
42
|
if (value.kind === 'self' && value.result && typeof value.result === 'object') value = value.result as Record<string, unknown>;
|
|
42
|
-
|
|
43
|
+
const completed = value.stage === 'worktree-completed' && value.ok === true;
|
|
44
|
+
// The gate could not measure an environmental failure. Keep the implementation as a
|
|
45
|
+
// bundle for the pinned PR; the parent still has to review and rejudge that head.
|
|
46
|
+
const gate = value.gate && typeof value.gate === 'object' && !Array.isArray(value.gate)
|
|
47
|
+
? value.gate as { passed?: unknown; log?: unknown; reflectGateFacts?: { introduced?: number; unknownReason?: string; childResponsibility?: string } }
|
|
48
|
+
: null;
|
|
49
|
+
const environmentHarvest = value.stage === 'gate-failed' && value.ok === false
|
|
50
|
+
&& value.harvestable === true && typeof value.detail === 'string'
|
|
51
|
+
&& value.detail.includes(GATE_ENV_DEFICIT_HARVESTABLE_MARK)
|
|
52
|
+
&& gate?.passed === false
|
|
53
|
+
&& gate.reflectGateFacts?.introduced === 0
|
|
54
|
+
&& gate.reflectGateFacts?.childResponsibility === 'none'
|
|
55
|
+
&& classifyGateEnvDeficit({ passed: false, ...(typeof gate.log === 'string' ? { log: gate.log } : {}),
|
|
56
|
+
...(gate.reflectGateFacts ? { reflectGateFacts: gate.reflectGateFacts } : {}) }).envDeficit;
|
|
57
|
+
if ((!completed && !environmentHarvest) || typeof value.worktreePath !== 'string'
|
|
43
58
|
|| typeof value.runId !== 'string' || !value.runId)
|
|
44
|
-
throw new Error('repair child final result is
|
|
59
|
+
throw new Error('repair child final result is neither successful worktree-only nor environment-deficit harvestable');
|
|
45
60
|
return { path: value.worktreePath, runId: value.runId };
|
|
46
61
|
}
|
|
47
62
|
throw new Error('repair child did not return a successful worktree-only result');
|
|
48
63
|
}
|
|
49
64
|
|
|
50
|
-
/** Called in the Pod after
|
|
65
|
+
/** Called in the Pod after a successful child or a verified environment-deficit harvest. */
|
|
51
66
|
export function writePodRepairCommit(input: { pr: number; baseHead: string; runId: string; output: string; repo: string; outbox: string }): PodRepairResult {
|
|
52
67
|
if (!Number.isSafeInteger(input.pr) || input.pr < 1 || !SHA40.test(input.baseHead)) throw new Error('invalid repair PR or base head');
|
|
53
68
|
if (!input.runId.trim()) throw new Error('repair parent run id missing');
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Opt-in SI warm entry; the ordinary Pod spawn remains the default. */
|
|
2
|
+
import { podSelfImplementSpawn, type PodSpawnOptions } from './self-implement-pod.js';
|
|
3
|
+
|
|
4
|
+
export async function podSpawnWithSiWarm(base: PodSpawnOptions,
|
|
5
|
+
env: NodeJS.ProcessEnv = process.env) {
|
|
6
|
+
if (env.ELANOUS_SI_WARM_REUSE !== '1') return podSelfImplementSpawn(base);
|
|
7
|
+
const { acquireSiWarmChild, postprocessSiWarmChild } = await import('./pod-si-warm-host.js');
|
|
8
|
+
return podSelfImplementSpawn({ ...base,
|
|
9
|
+
siWarmAttempt: async input => {
|
|
10
|
+
const result = await acquireSiWarmChild(input, base);
|
|
11
|
+
return result.status === 'acquired' ? result.attempt : null;
|
|
12
|
+
},
|
|
13
|
+
siWarmHostPostprocess: (result, attempt, input) =>
|
|
14
|
+
postprocessSiWarmChild(input, result, attempt, base),
|
|
15
|
+
});
|
|
16
|
+
}
|