elanous 0.2.41 → 0.2.43
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/{GiOLWmt4MqDZePubBjA4Q → Om5xS9jpjSXJCeTNGYEi4}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{2fe2c302.41b517f88d6fe502.js → 0966f8a1.745fcd44f64a87ea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{385e4574.e9886ab32759eda3.js → 0ad6802e.ae7afb63fdcb4491.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/114.2b90424d1a3ce84c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1151-5c2bb8f002ca2dd6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1200.6a37c202f9f17e9a.js +226 -0
- package/apps/pwa/out/_next/static/chunks/1261-a616d5728e02e624.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1313-19f737e0222c4444.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1357.3bbef3976c37f94a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1362-20adddfaf662b0fa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6874.d5cf7eb8edb2cabe.js → 1406.a1dc2ab6f8449374.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1737-9491fc6ab29b9ec6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1803-4f91a8e7dcaf042c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5744.b9415e18ad623100.js → 1961.a81b12872c3e93a9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1970cf59.2d4d8ce5d6c81853.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2073-ba274e00e4f9efb4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5471.1e611302ed3a7c53.js → 2144.25b292396712196d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{3230-49298c3b73ef2268.js → 2268-53861f339e0b65a2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9834.63ab2bbc3153172e.js → 2312.0c8b61e22d3136d7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1800.f7ff51dc4978a958.js → 2573.387a707f6f9d720c.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/273.f156eee28f11af77.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2873.d2140e5a82546401.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9048.212083de42d25be3.js → 3072.01338851ca21a6f7.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3091.a5a4143dea33d197.js +90 -0
- package/apps/pwa/out/_next/static/chunks/3095.dc44586a5f83b86d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2263.e09b6edea33bad2d.js → 3113.d7472bbc27d580c7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3228-9650b6447b6fa288.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3402.44b565b314f2263c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{addc2b32.8c4ff8f0aefe987d.js → 3557ac4a.c8931684475018ad.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/360.ae9f9f4c33c395e8.js +79 -0
- package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +286 -0
- package/apps/pwa/out/_next/static/chunks/{a0a01613.6d1cca322238d7fe.js → 363bfab3.9623b9f89363541f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3694.e0099884345f0198.js +64 -0
- package/apps/pwa/out/_next/static/chunks/3744.54f87db52acfd1ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3903.3ef4656c67572764.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3935.16701e33f8982dc9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3955.6922286237f2ac2b.js +24 -0
- package/apps/pwa/out/_next/static/chunks/3969.272ee7f9fd6c62e5.js +34 -0
- package/apps/pwa/out/_next/static/chunks/4199.ce86b281fd0a60b7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4311-6dd3144002cc0c2d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4426-2b230fad00c88930.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{530.d26346e18089640a.js → 4445.7990c76b3751a918.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4447-14c5161fa59166c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4856-b0b8075bba8c53f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4870-de370d65e73c0bb5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4885-2c989165c4b29fad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4894.fec2ca9e99caefa2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5093.8f04b7f8cb899a95.js +94 -0
- package/apps/pwa/out/_next/static/chunks/5122-2bb177cebf89e19a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5154.5f56dc3902e3d275.js +36 -0
- package/apps/pwa/out/_next/static/chunks/529.64ff7257180b2ac9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5394.5dabeb0c62293a28.js +93 -0
- package/apps/pwa/out/_next/static/chunks/5461.08bf2404ff38ec85.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5474-22e08a85583209b2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1219.7e17964e0e7cd8e5.js → 5564.9e72532188f57586.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/5567-265df39ed8fe9dcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5570-a94ae19811cb2046.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5574-b47c9ef2dceff1fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5628.6ddb2d5ffba4ff4c.js +309 -0
- package/apps/pwa/out/_next/static/chunks/5730.43d7ccc09988e646.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1178.1aa9cad0e7695427.js → 5789.2da35c258292e1e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4133.2056bb4d78f621af.js → 5824.da9527b15a3221e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5866.366966af47fdde5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4527.a69f2894d1bc9f4a.js → 5930.8b4df3b46c32b05a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5963-c4d8469c52a0828b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6001.ec4049ceb3c43418.js +27 -0
- package/apps/pwa/out/_next/static/chunks/6120-471f03db1e299c0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6175-41479e643aca1878.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6291.a2de4f9787637075.js +104 -0
- package/apps/pwa/out/_next/static/chunks/6400-6699907c3537436a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6428.1f4327d6ae5fdf9a.js +287 -0
- package/apps/pwa/out/_next/static/chunks/644.02cb026fa44bcd0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6466-6c87d60d3dd174fb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9507.7026657a2f47eb64.js → 6540.c7bef57ad8f90a87.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/6773.d4264665ab31bec0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6822.3c789f1a8443e774.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5574.f35accf4f132b29d.js → 6944.309f4e3ea54d1537.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7261-8ff69d3b2ee671fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7266.084c6bbc70035140.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7271.5c0100e7320aa856.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7429-bf5731358c8f2f68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7464.01f7a0ae1215fbe7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7479.0fcad5f37eb64f0c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7483.427a2fe2049e388d.js +148 -0
- package/apps/pwa/out/_next/static/chunks/7502-be74718178e13e56.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7530.0889722b19572065.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7645.5b2ee3ad45c55ea3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7788.7d1c79f1a8e18946.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7900.096f455c7c1efc53.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7910-6f139bcafd238b9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7966.f71c8958d1637548.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5947-135e26537d80a6b9.js → 8062-7cd0bcc7f01455ba.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/8073.f6cf2f2c71aafbd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8201.190b94088980f430.js +74 -0
- package/apps/pwa/out/_next/static/chunks/8205.282ca4bb62d54a0a.js +62 -0
- package/apps/pwa/out/_next/static/chunks/8313-dfa1021bb58a46d6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/837-81336ebaca8198a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8447.7963352ef5f71b76.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8574-868e8129525ef6d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8588.d1c6a2903727ce87.js +149 -0
- package/apps/pwa/out/_next/static/chunks/8637.90f92d5c8db4732c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2743.5d3f76948be32b34.js → 868.6e953be05bcf6dca.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/8706-e1fe0309343a2273.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8749-06384cdfc4520add.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5964-7e21164a8f2cf0ce.js → 8861-cc1fa1c7b920fa8e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8967-7dfebf710c9dec9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5159.115f1c2ca471386c.js → 8986.8e2e4efbfa655c59.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8997-3c564dbb3b58b055.js +1 -0
- package/apps/pwa/out/_next/static/chunks/923.2034d10ae91e9c20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +1 -0
- package/apps/pwa/out/_next/static/chunks/943.39ae5e82f4f1893f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9469.0500480de55fb205.js +32 -0
- package/apps/pwa/out/_next/static/chunks/9770.5f75bc6088b16109.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9810-2543267050e58b82.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9870.8419702475254745.js +8 -0
- package/apps/pwa/out/_next/static/chunks/9941-376d1b74d51b01a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9958.385434ab04241758.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b2271e54.c1de3347976e90b0.js → aa57532f.510551854ff239b1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-deea1450b17cb8dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-70985b904f8650ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a2e15e33e56a4353.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-fc72ce2db12d6ca9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-be03e41f9436ebd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-35a35999382da3f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-3ff5b1e6ca88b848.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-a65101300a0ee5c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-3aca5b6d67dba511.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-45b8ab0a71e61314.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-53046e282d4cda8e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-17809e60e8354c17.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-fd2442d347bf5898.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-e9d720d6fc082e21.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-6b8b4267bab0a677.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-deea1450b17cb8dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-8bcf6233ac7c17af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-7cc25591cfc2126f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-053e871f35c9beba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-eff819f0c2d5e084.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-4d7e9d8db5274a87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-2b2d8f5aa5f69ad4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-0b8f92c5062e68b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1bd9d0fdac2ced3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-9ee28f7df07428ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-44b7a1ff468c6648.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-cbc6523711dc1b65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-fdad47899c2695be.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-40f9e19149024298.js → page-79a8b5fee4c20871.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-03e8ac9606aeaffb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-4cd55c55ec287e2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-db17b4305404161e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-30041d848350fd02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c540da022dbf86b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9399efc538da057f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-a142dfb0331a05f5.js → page-ca2d09128c585ca4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-0e2635aecd343038.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ef7f4399b6b7726e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-deea1450b17cb8dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-caf530535b875468.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-eaa20c1543a5fd8e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c541eb1b75120f61.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-ab5e213eda9479f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-0a815f34367b6db6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-e858ba0ed9393b68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-1638ee9dd6e0582f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4cf5a399109391f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b4396321238798ec.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-cb72bfd21006781a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6135d0242afbc434.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a1dccf907eddb856.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{53aeb4ee-51c92f8d683f5220.js → c7945435-b44d4dbe90ba0dcb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{2fdf2931.b431eee4fb468bc3.js → cb0f8df8.09a4a6be97e3fc5f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{c0c1a699.0ba79f97005965d4.js → d96660fb.cbc21a2a88539dbb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/ea514caa.05a24f78d9dffe5f.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{83184dcd-0ee6247ff41eb3f2.js → fb7d20d5-6892502b6ee39ca6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-e8a911e19b1be41f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-7022f418fabba021.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-e5f15df755756a1e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-4525f91e36940c9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-140f0e519c085b0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-8f22ef63dcb865b1.js +1 -0
- package/apps/pwa/out/_next/static/css/{b9d8151e48998417.css → 62c858ad53854f47.css} +1 -1
- package/apps/pwa/out/_next/static/css/d1f8bb401740a549.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +23 -23
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +22 -22
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +24 -25
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +23 -23
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +24 -25
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +24 -25
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/catalog/external-commands.yaml +5 -3
- package/catalog/meta/catalogVersion.yaml +2 -1
- package/catalog/signing/catalog-signing-public.pem +3 -0
- package/docs/goal-context/04-mock-scenarios.md +13 -0
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/heal/heal-loop.yaml +1 -0
- package/graphs/intake/intake-daily.yaml +16 -0
- package/graphs/intake/news-sources.yaml +1 -0
- package/graphs/intake/recipes.yaml +7 -0
- package/graphs/overlays/examples/research-runtime-empty-terminal.yaml +28 -0
- package/graphs/overlays/stop-heal-ladder.yaml +113 -0
- package/graphs/profiles/local.yaml +5 -0
- package/graphs/profiles/pod.yaml +4 -0
- package/graphs/units/verbs/recipes.yaml +11 -11
- package/graphs/work/research-report.yaml +10 -2
- package/package.json +6 -2
- package/plugins/demo-absorption-briefing/plugin.json +18 -0
- package/plugins/demo-absorption-briefing/skills/demo-absorption-briefing/SKILL.md +8 -0
- package/plugins/demo-browser-hand/plugin.json +13 -0
- package/plugins/demo-browser-hand/skills/demo-browser-hand/SKILL.md +8 -0
- package/plugins/demo-linear-secretary/plugin.json +15 -0
- package/plugins/demo-linear-secretary/skills/demo-linear-secretary/SKILL.md +8 -0
- package/plugins/demo-plugin-wizard/plugin.json +11 -0
- package/plugins/demo-plugin-wizard/skills/demo-plugin-wizard/SKILL.md +8 -0
- package/plugins/demo-research/plugin.json +16 -0
- package/plugins/demo-research/skills/demo-research/SKILL.md +8 -0
- package/plugins/demo-video-briefing/plugin.json +15 -0
- package/plugins/demo-video-briefing/skills/demo-video-briefing/SKILL.md +8 -0
- package/scripts/build-signed-catalog.ts +48 -0
- package/scripts/ci-typecheck-main-delta.sh +88 -0
- package/scripts/codex-fallback-live-probe.ts +1 -1
- package/scripts/demo/demo1104-parallel-scenes.ts +301 -0
- package/scripts/demo/demo1104-stage.config.ts +21 -0
- package/scripts/demo/demo1104-stage.ts +316 -0
- package/scripts/goal-method-audit.ts +17 -1
- package/scripts/graph-units/land-enqueue.ts +90 -0
- package/scripts/heal/run-role.ts +99 -5
- package/scripts/hooks/codex-notify.sh +32 -0
- package/scripts/install.sh +10 -38
- package/scripts/land-global-checks.ts +6 -1
- package/scripts/landing-heal/land-plan.ts +57 -0
- package/scripts/lib/decompose-ab.ts +1 -0
- package/scripts/lib/fixtures/tui-regress/help-insufficient-commands.txt +15 -0
- package/scripts/lib/fixtures/tui-regress/help-live.txt +42 -0
- package/scripts/lib/fixtures/tui-regress/help-missing-keys.txt +21 -0
- package/scripts/lib/fixtures/tui-regress/help-original.txt +51 -0
- package/scripts/lib/fixtures/tui-regress/help-shifted-input.txt +26 -0
- package/scripts/lib/tui-regress-checks.ts +33 -13
- package/scripts/release-loop/auto-approve-node.ts +1 -1
- package/scripts/release-loop/gate-autoheal-sim-evidence.ts +60 -0
- package/scripts/release-loop/gate-baseline-receipt.ts +47 -9
- package/scripts/release-loop/gate-image-pin.ts +81 -0
- package/scripts/release-loop/gate-method.ts +139 -0
- package/scripts/release-loop/gate-node-sim.ts +207 -0
- package/scripts/release-loop/gate-node.ts +463 -64
- package/scripts/release-loop/gate-pod-image-sticky-plan.ts +99 -0
- package/scripts/release-loop/gate-radius-live.ts +97 -13
- package/scripts/release-loop/gate-shard-dispatch.ts +43 -0
- package/scripts/release-loop/gate-traffic-mode.ts +151 -3
- package/scripts/release-loop/gate-train-receipts.ts +122 -0
- package/scripts/release-loop/node-verdict.ts +38 -25
- package/scripts/release-loop/preflight.ts +362 -8
- package/scripts/release-loop/resume-release.ts +83 -8
- package/scripts/release-loop/unattended-release.ts +20 -9
- package/scripts/rhythm/daily.ts +36 -4
- package/scripts/rhythm/linear-progress-sync.ts +298 -0
- package/scripts/ux-sim.ts +18 -1
- package/scripts/video-pipeline.ts +9 -1
- package/scripts/warm-pool-provider-config.ts +286 -0
- package/skills/omni-crawl/SKILL.md +5 -2
- package/skills/omni-crawl/scripts/main.ts +84 -23
- package/src/acp/agent-manager.ts +1 -0
- package/src/acp/codex-app-server-agent.ts +33 -0
- package/src/acp/codex-app-server-client.ts +153 -16
- package/src/acp/core-turn-bridge.ts +27 -9
- package/src/acp/event-router.ts +20 -1
- package/src/acp/server.ts +6 -0
- package/src/agent/registry.ts +2 -0
- package/src/agent/task-notification.ts +25 -5
- package/src/agent/types.ts +6 -0
- package/src/agent-mission/browser-roundtrip-coordinator.ts +85 -0
- package/src/agent-mission/claude-headless.ts +4 -1
- package/src/agent-mission/codex-exec.ts +105 -0
- package/src/agent-mission/driver.ts +192 -11
- package/src/agent-mission/grok-auth-status.ts +47 -0
- package/src/agent-mission/hand-hooks.ts +101 -0
- package/src/agent-mission/mission-cli.ts +63 -4
- package/src/agent-mission/mission-hand-reply.ts +118 -0
- package/src/agent-mission/mission-line.ts +180 -0
- package/src/agent-mission/mission-out.ts +833 -0
- package/src/agent-mission/tool-install.ts +200 -3
- package/src/agent-substrate/context-strategy.ts +4 -4
- package/src/agent-substrate/self-review-cli.ts +178 -13
- package/src/agents/general-purpose.md +1 -1
- package/src/auto-research/research-turn.ts +211 -53
- package/src/autopilot/pr-manager.ts +69 -10
- package/src/autopilot/pty-control-loop.ts +2 -0
- package/src/boot/daemon-tools/self-implement.ts +3 -1
- package/src/boot/daemon-tools/web-search.ts +1 -2
- package/src/briefing/brief-items.ts +55 -11
- package/src/capture/tui-self-report.ts +22 -6
- package/src/chat/index.ts +1 -1
- package/src/cli/agent-cli.ts +2 -1
- package/src/cli/catalog-cli.ts +31 -0
- package/src/cli/connector-cli.ts +16 -0
- package/src/cli/doctor-fix.ts +2 -2
- package/src/cli/fixtures/review-loop-breaker/opwaiver-32646-1694ccc7a170.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-32853-bd8f73595c83.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-33097-1cc85900413c.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-33106-972f31e4a3ca.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/opwaiver-33113-3ab51f05968f.json +1 -0
- package/src/cli/fixtures/review-loop-breaker/pr-33097-1cc85900413c.json +1 -0
- package/src/cli/intake-source-cli.ts +44 -8
- package/src/cli/msg-cli.ts +32 -3
- package/src/cli/pr-cli.ts +21 -1
- package/src/cli/pr-land-heavy-remote.ts +75 -5
- package/src/cli/pr-land-overlap-evidence.ts +113 -2
- package/src/cli/pr-land-pod-shadow-job.ts +202 -4
- package/src/cli/pr-land-pod-shadow.ts +9 -2
- package/src/cli/release-checklist-read-cli.ts +57 -19
- package/src/cli/release-cli.ts +23 -3
- package/src/cli/research-cli.ts +13 -5
- package/src/cli/setup-cli.ts +166 -6
- package/src/cli/setup-keys.ts +187 -0
- package/src/cli/task-plugin-wizard-host.ts +114 -0
- package/src/cli/tasks-cli.ts +61 -9
- package/src/cli/tui-test-cli.ts +186 -0
- package/src/compact/auto.ts +8 -1
- package/src/config.ts +4 -2
- package/src/connectors/linear-daily-progress.ts +228 -0
- package/src/connectors/linear-projector.ts +34 -12
- package/src/connectors/linear.ts +151 -7
- package/src/control-plane/ledger.ts +52 -2
- package/src/control-plane/server.ts +16 -2
- package/src/core-turn/deep-turn-bloom.ts +67 -0
- package/src/core-turn/research-policy.ts +37 -0
- package/src/core-turn/run-core-turn.ts +606 -95
- package/src/core-turn/run-goal-loop.ts +18 -0
- package/src/core-turn/types.ts +4 -0
- package/src/dashboard/chat/acp-chat.ts +10 -0
- package/src/dashboard/classic-sidetab-mission-job.ts +161 -0
- package/src/dashboard/classic-sidetab-mission-pair.ts +81 -0
- package/src/dashboard/classic-sidetab-mission-trio.ts +219 -0
- package/src/dashboard/classic-sidetab-mission.ts +347 -0
- package/src/dashboard/index.ts +517 -18
- package/src/dashboard/input/agent-wake.ts +23 -1
- package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +17 -0
- package/src/dashboard/mission-cli-consumer.ts +165 -0
- package/src/dashboard/plugin-wizard-runtime.ts +50 -0
- package/src/dashboard/plugin-wizard-tool.ts +55 -0
- package/src/dashboard/seat-boot-preamble.ts +171 -1
- package/src/dashboard/side-basic-runtime.ts +54 -1
- package/src/dashboard/sidetab-runtime.ts +90 -1
- package/src/dashboard/skill-catalog-preamble.ts +101 -0
- package/src/dashboard/skill-detection-runtime.ts +55 -15
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +15 -0
- package/src/dashboard/terminal-popup-runtime.ts +6 -3
- package/src/dashboard/turn-preamble.ts +53 -15
- package/src/dashboard/turn-prompt-runtime.ts +4 -2
- package/src/decisions/linear-progress-summary.ts +78 -0
- package/src/decisions/linear-progress-sync.ts +152 -0
- package/src/domains/outbound-alert.ts +49 -11
- package/src/domains/telegram-kind-route.ts +16 -9
- package/src/graph-runner/arg-allowance.ts +13 -0
- package/src/graph-runner/graph-cli.ts +23 -7
- package/src/graph-runner/graph-run-api.ts +3 -1
- package/src/graph-runner/graph-tick.ts +10 -2
- package/src/graph-runner/runner.ts +86 -18
- package/src/graph-wizard/mission-compose.ts +407 -12
- package/src/grok/agent-search.ts +14 -4
- package/src/grok/credential.ts +28 -11
- package/src/harness/dispatch-backpressure.ts +54 -1
- package/src/harness/dispatch-shadow-compare.ts +74 -0
- package/src/harness/harness-cli-command.ts +11 -1
- package/src/harness/harness-pod-dispatch.ts +81 -15
- package/src/harness/harness-stop.ts +155 -11
- package/src/harness/skill-exec.ts +21 -9
- package/src/harness/skill-select.ts +1 -1
- package/src/hooks/error-report-cloud.ts +101 -0
- package/src/hooks/receiver.ts +29 -2
- package/src/index.ts +159 -13
- package/src/instance/spawn-elanous.ts +6 -4
- package/src/intake-plane/actions.ts +354 -0
- package/src/intake-plane/adapters/telegram-ambient.ts +34 -18
- package/src/intake-plane/intake-sources.ts +78 -8
- package/src/intake-plane/items.ts +14 -4
- package/src/intake-plane/linear-mission-sync.ts +80 -0
- package/src/intake-plane/linear-secretary-runtime.ts +178 -0
- package/src/intake-plane/linear-wish.ts +227 -1
- package/src/life/life-cli.ts +168 -0
- package/src/life/life-kinds.ts +160 -0
- package/src/live-supply/budget-consumer.ts +78 -0
- package/src/live-supply/read.ts +3 -0
- package/src/live-supply/snapshot.ts +45 -0
- package/src/llm/provider-credentials.ts +8 -2
- package/src/llm.ts +168 -9
- package/src/loops/orchestrator/coordinator-shadow.ts +226 -0
- package/src/loops/orchestrator/tick.ts +13 -0
- package/src/maturity/feature-maturity.ts +4 -4
- package/src/msg/msg-sse-server.ts +3 -3
- package/src/msg/msg-store.ts +177 -19
- package/src/native-tool-catalog.ts +38 -4
- package/src/nexus/api/harness-traversal.ts +11 -0
- package/src/nexus/api/http-server.ts +37 -1
- package/src/nexus/api/mcp-public-allowlist.ts +2 -0
- package/src/nexus/index.ts +7 -2
- package/src/nexus/outbound/format.ts +9 -0
- package/src/nexus/outbound/router.ts +98 -13
- package/src/nexus/setup-status.ts +9 -0
- package/src/nexus/state/state.ts +3 -0
- package/src/oauth/codex-account-store.ts +20 -7
- package/src/oauth/codex-owner-mirror.ts +44 -0
- package/src/oauth/codex.ts +17 -2
- package/src/oauth/fallback-chain.ts +47 -17
- package/src/onboarding/first-run-doctor.ts +8 -1
- package/src/onboarding/first-run.ts +85 -26
- package/src/onboarding/key-setup.ts +103 -0
- package/src/onboarding/menu-answer.ts +13 -0
- package/src/onboarding/secret-prompt.ts +37 -0
- package/src/plugins/install/plugin-install.ts +59 -0
- package/src/pr-tool/census.ts +133 -2
- package/src/pty-shell/pty-control-ipc.ts +4 -1
- package/src/pty-shell/tui-run-state.ts +188 -2
- package/src/registry/catalog-server.ts +232 -0
- package/src/registry/loader.ts +45 -1
- package/src/registry/types.ts +1 -2
- package/src/release-loop/checklist-target-path-hint.ts +13 -0
- package/src/release-loop/checklist.ts +9 -1
- package/src/repl/index.ts +43 -2
- package/src/research/axis-fanout.ts +136 -16
- package/src/research/bloom-exemplars.ts +3 -1
- package/src/research/gap-followup.ts +13 -1
- package/src/research/plugin-discovery.ts +36 -14
- package/src/research-bridge/invoke.ts +22 -5
- package/src/research-bridge/types.ts +2 -0
- package/src/self-dev/ask-launch-flow.ts +72 -1
- package/src/self-dev/decompose.ts +119 -5
- package/src/self-dev/dev-cli.ts +4 -1
- package/src/self-dev/dev-pipeline.ts +5 -0
- package/src/self-dev/draft-residue.ts +64 -5
- package/src/self-dev/graph-front-nodes.ts +2 -1
- package/src/self-dev/graph-journey-route.ts +76 -21
- package/src/self-dev/launch-preflight-text.ts +5 -6
- package/src/self-dev/launch-preflight.ts +58 -0
- package/src/self-dev/orchestrate.ts +13 -3
- package/src/self-dev/review-provider-fallback.ts +9 -2
- package/src/self-dev/run-supervisor.ts +42 -4
- package/src/self-dev/run-types.ts +4 -0
- package/src/self-dev/shard-aggregate.ts +4 -0
- package/src/self-dev/shard-run.ts +36 -15
- package/src/self-implement/abandoned-classification.ts +12 -3
- package/src/self-implement/budget-gate.ts +7 -0
- package/src/self-implement/child-llm-preference.ts +10 -1
- package/src/self-implement/doctor-visit.ts +118 -8
- package/src/self-implement/elanous-tui-spawn.ts +3 -0
- package/src/self-implement/fixtures/tdd-green-missing-passing-child-transcript.txt +2 -0
- package/src/self-implement/gate-artifacts.ts +2 -1
- package/src/self-implement/goal-author-cli.ts +4 -2
- package/src/self-implement/goal-author.ts +684 -7
- package/src/self-implement/graph-overlay-yaml.ts +37 -4
- package/src/self-implement/graph-overlay.ts +3 -1
- package/src/self-implement/graph-profile-yaml.ts +107 -0
- package/src/self-implement/graph-yaml.ts +26 -3
- package/src/self-implement/headless-elanous-driver.ts +31 -2
- package/src/self-implement/heal-intake.ts +112 -4
- package/src/self-implement/heal-triage.ts +20 -0
- package/src/self-implement/host-regate.ts +27 -4
- package/src/self-implement/merge-train.ts +5 -0
- package/src/self-implement/off-diff-evidence.ts +249 -5
- package/src/self-implement/orchestrator.ts +365 -25
- package/src/self-implement/regate-detail.ts +38 -1
- package/src/self-implement/rework-child-provider.ts +25 -0
- package/src/self-implement/run-chart.ts +122 -0
- package/src/self-implement/run-ledger.ts +162 -11
- package/src/self-implement/run-stop.ts +188 -4
- package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
- package/src/self-implement/stop-autoheal.ts +13 -0
- package/src/self-implement/tdd-evidence-tags.ts +9 -0
- package/src/self-implement/train-gate-receipt.ts +166 -0
- package/src/self-implement/train-gate-remote.ts +62 -18
- package/src/session/chat.ts +40 -4
- package/src/session/session-fanout.ts +2 -0
- package/src/session/streaming/acp-stream-sink.ts +2 -1
- package/src/session/streaming/chunk-producer.ts +6 -0
- package/src/session/streaming/stream-compositor.ts +3 -2
- package/src/session-runtime/index.ts +135 -5
- package/src/session-runtime/retry-policy.ts +1 -1
- package/src/session-runtime/tier-flip.ts +3 -3
- package/src/setup/llm-env-detect.ts +3 -0
- package/src/setup/service-key-catalog.ts +46 -0
- package/src/setup/service-keys.ts +241 -0
- package/src/sidetab-core/model.ts +19 -5
- package/src/sidetab-core/visible-agent-mission.ts +262 -0
- package/src/skills/name-match.ts +20 -0
- package/src/skills/tools/agent.ts +53 -6
- package/src/skills/tools/omni-search.ts +173 -13
- package/src/task-agent/parent-host.ts +10 -0
- package/src/task-agent/pod-distributor-entry.ts +3 -0
- package/src/task-agent/repair-outcomes.ts +65 -0
- package/src/task-agent/task-hand.ts +47 -7
- package/src/task-orchestrator/dispatcher.ts +14 -1
- package/src/task-orchestrator/linear-capture-events.ts +55 -0
- package/src/task-orchestrator/store.ts +16 -5
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +4 -0
- package/src/task-orchestrator/surfaces/pod-distributor.ts +48 -0
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +92 -1
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +38 -1
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
- package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +33 -6
- package/src/task-orchestrator/surfaces/pod-source-bundle.ts +45 -9
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +178 -16
- package/src/task-orchestrator/surfaces/pod-source-spec.ts +3 -3
- package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +237 -41
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +80 -3
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +337 -51
- package/src/task-orchestrator/surfaces/self-implement.ts +27 -3
- package/src/task-orchestrator/surfaces/warm-reuse-evidence.ts +169 -0
- package/src/task-orchestrator/types.ts +14 -0
- package/src/telegram.ts +14 -16
- package/src/terminal/coding-agent.ts +14 -5
- package/src/terminal/session-registry.ts +1 -1
- package/src/tokens.ts +35 -2
- package/src/tool-hints/gate.ts +1 -0
- package/src/tool-runtime/agent-runtime.ts +2 -0
- package/src/tool-runtime/browser-hand-runtime.ts +381 -0
- package/src/tool-runtime/browser-runtime.ts +2 -1
- package/src/tool-runtime/elanous-linear-issue-runtime.ts +76 -0
- package/src/tool-runtime/elanous-linear-secretary-runtime.ts +57 -0
- package/src/tool-runtime/elanous-skills-list-runtime.ts +5 -1
- package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
- package/src/tool-runtime/index.ts +6 -0
- package/src/tool-runtime/skill-exec-runtime.ts +33 -13
- package/src/tool-runtime/types.ts +4 -0
- package/src/tui/entry.ts +38 -5
- package/src/tui/sidetab/attach.ts +177 -1
- package/src/tui/sidetab/herdr-portal.ts +225 -0
- package/src/tui-client/local-chat-turn.ts +26 -13
- package/src/tui.ts +22 -0
- package/src/user-config.ts +34 -9
- package/src/user-intent/types.ts +4 -3
- package/src/ux-sim/browser-hand.ts +165 -0
- package/src/ux-sim/draft-inventory-builder.ts +198 -0
- package/src/ux-sim/fake-browser-page.ts +81 -0
- package/src/ux-sim/fake-kubectl.ts +37 -3
- package/src/ux-sim/fake-linear-device.ts +31 -0
- package/src/ux-sim/fault-pool-cap.ts +11 -6
- package/src/ux-sim/graph-engine-sim.ts +47 -0
- package/src/ux-sim/linear-secretary.ts +216 -0
- package/src/ux-sim/mock-scenario-catalog.json +93 -0
- package/src/ux-sim/mock-scenario-catalog.ts +274 -0
- package/src/ux-sim/onboarding-first-run-device.ts +31 -21
- package/src/ux-sim/scenario.ts +185 -48
- package/src/ux-sim/service-key-setup.ts +50 -0
- package/src/ux-sim/term-slash-device.ts +74 -0
- package/src/ux-sim/turn-throw-sim.ts +31 -0
- package/src/version/packed-revision.json +1 -1
- package/src/voice/voice-tts-singleton.ts +18 -3
- package/src/web-search/exa.ts +77 -0
- package/src/web-search/grok.ts +5 -9
- package/src/web-search/index.ts +30 -9
- package/src/web-search/provider.ts +4 -1
- package/src/web-search/x-intent.ts +5 -0
- package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +0 -36
- package/apps/pwa/out/_next/static/chunks/1197-54da59d250a6e476.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +0 -90
- package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1765.679b29625c8e88d4.js +0 -77
- package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2073.689dcb2680113d76.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +0 -1
- package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2773.0e80b9d325fb5635.js +0 -32
- package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3097.864e92bdaa2f4d15.js +0 -79
- package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +0 -74
- package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4156.ba4de4a3664f04b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +0 -148
- package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +0 -226
- package/apps/pwa/out/_next/static/chunks/4667.97e31aa38c95c475.js +0 -309
- package/apps/pwa/out/_next/static/chunks/4702.4a4adc1f16d7c93b.js +0 -64
- package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +0 -94
- package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +0 -8
- package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +0 -24
- package/apps/pwa/out/_next/static/chunks/5892.2526d962339662d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5937.c2df9e3447e1f667.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +0 -286
- package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +0 -27
- package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +0 -62
- package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +0 -24
- package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +0 -122
- package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7191.fdc955f7d96064a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8050-9b364bdef8f71927.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +0 -104
- package/apps/pwa/out/_next/static/chunks/8464-e24f10451b658aac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8880.64c445592f04acaf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8981.c706964c8ba27aff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +0 -93
- package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9579.4a8169600fff2058.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +0 -34
- package/apps/pwa/out/_next/static/chunks/9869.81a1e24ca682d5a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-14949db884bfa672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +0 -1
- package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
- package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +0 -1
- /package/apps/pwa/out/_next/static/{GiOLWmt4MqDZePubBjA4Q → Om5xS9jpjSXJCeTNGYEi4}/_ssgManifest.js +0 -0
|
@@ -32,6 +32,8 @@ import {
|
|
|
32
32
|
type AcceptanceReport,
|
|
33
33
|
} from './acceptance.js';
|
|
34
34
|
import { recordOpsEventSafe, type OpsEventInput } from '../domains/ops-log.js';
|
|
35
|
+
import { getHarnessRunId } from '../harness/harness-space.js';
|
|
36
|
+
import { collectLinearCaptureArtifacts } from './linear-capture-events.js';
|
|
35
37
|
import { defaultAnomalyCluster, extractContainerExit, type AnomalyCluster } from '../loops/orchestrator/anomaly-cluster.js';
|
|
36
38
|
|
|
37
39
|
// ───────────────────────── Concurrency caps ────────────────────────
|
|
@@ -309,7 +311,18 @@ export class TaskDispatcher {
|
|
|
309
311
|
const kind = task.surface.kind;
|
|
310
312
|
let savedExecution = false;
|
|
311
313
|
try {
|
|
312
|
-
const
|
|
314
|
+
const completedExecution = { ...await res.promise, id: res.executionId };
|
|
315
|
+
// The run identity is taken from this dispatcher process, never from child-reported execution output.
|
|
316
|
+
const runId = getHarnessRunId();
|
|
317
|
+
let captureArtifacts: TaskExecution['captureArtifacts'] = [];
|
|
318
|
+
if (runId) {
|
|
319
|
+
try {
|
|
320
|
+
captureArtifacts = collectLinearCaptureArtifacts({ runId, startedAt: completedExecution.startedAt,
|
|
321
|
+
endedAt: completedExecution.endedAt ?? this.now() });
|
|
322
|
+
} catch { /* Capture observation is optional; an unavailable log store must not block task completion. */ }
|
|
323
|
+
}
|
|
324
|
+
const exec: TaskExecution = { ...completedExecution, runId: runId || undefined,
|
|
325
|
+
captureArtifacts: captureArtifacts.length ? captureArtifacts : undefined };
|
|
313
326
|
// Keep the task row and execution in the same store read by GET /v1/tasks/:id.
|
|
314
327
|
this.opts.store?.saveTask(this.opts.graph.getTask(task.id)!);
|
|
315
328
|
this.opts.store?.saveExecution(exec);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { LogStore, logsDbPath, type LogStoreRow } from '../mss/logging/log-store.js';
|
|
3
|
+
import type { TaskCaptureArtifact } from './types.js';
|
|
4
|
+
|
|
5
|
+
export interface LinearCaptureEventWindow { runId: string; startedAt: number; endedAt: number }
|
|
6
|
+
export type LinearCaptureEventStore = Pick<LogStore, 'queryByDataKeys' | 'close'>;
|
|
7
|
+
|
|
8
|
+
function parseCaptureEvent(row: LogStoreRow, expectedRunId: string): TaskCaptureArtifact | undefined {
|
|
9
|
+
if (row.event !== 'executed' || !row.data) return undefined;
|
|
10
|
+
let data: Record<string, unknown>;
|
|
11
|
+
try {
|
|
12
|
+
const parsed: unknown = JSON.parse(row.data);
|
|
13
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return undefined;
|
|
14
|
+
data = parsed as Record<string, unknown>;
|
|
15
|
+
} catch { return undefined; }
|
|
16
|
+
if (data.action !== 'read' || data.mode !== 'screenshot' || data.ok !== true || data.captureOutcome !== 'saved') return undefined;
|
|
17
|
+
const capture = data.capture;
|
|
18
|
+
if (!capture || typeof capture !== 'object' || Array.isArray(capture)) return undefined;
|
|
19
|
+
const descriptor = capture as Record<string, unknown>;
|
|
20
|
+
if (typeof descriptor.path !== 'string' || !descriptor.path || typeof descriptor.mimeType !== 'string' ||
|
|
21
|
+
descriptor.runId !== expectedRunId || typeof descriptor.linearIssueId !== 'string' || !descriptor.linearIssueId ||
|
|
22
|
+
descriptor.externalShare !== true || typeof descriptor.sensitivity !== 'string' ||
|
|
23
|
+
typeof descriptor.createdAt !== 'number' || !Number.isFinite(descriptor.createdAt)) return undefined;
|
|
24
|
+
return {
|
|
25
|
+
path: descriptor.path,
|
|
26
|
+
mimeType: descriptor.mimeType,
|
|
27
|
+
runId: expectedRunId,
|
|
28
|
+
linearIssueId: descriptor.linearIssueId,
|
|
29
|
+
externalShare: true,
|
|
30
|
+
sensitivity: descriptor.sensitivity,
|
|
31
|
+
createdAt: descriptor.createdAt,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Read only approved browser screenshot events emitted during this exact TOX execution. */
|
|
36
|
+
export function collectLinearCaptureArtifacts(window: LinearCaptureEventWindow, deps: {
|
|
37
|
+
dbPath?: string;
|
|
38
|
+
openStore?: (path: string) => LinearCaptureEventStore;
|
|
39
|
+
} = {}): TaskCaptureArtifact[] {
|
|
40
|
+
const runId = window.runId.trim();
|
|
41
|
+
if (!runId || !Number.isFinite(window.startedAt) || !Number.isFinite(window.endedAt) || window.endedAt < window.startedAt) return [];
|
|
42
|
+
const path = deps.dbPath ?? logsDbPath();
|
|
43
|
+
if (!existsSync(path)) return [];
|
|
44
|
+
const store = (deps.openStore ?? LogStore.openReadOnly)(path);
|
|
45
|
+
try {
|
|
46
|
+
const rows = store.queryByDataKeys({ exactCategories: ['harness.browser-action'], runIds: [runId] });
|
|
47
|
+
const found = new Map<string, TaskCaptureArtifact>();
|
|
48
|
+
for (const row of rows) {
|
|
49
|
+
if (row.ts_ms < window.startedAt || row.ts_ms > window.endedAt) continue;
|
|
50
|
+
const capture = parseCaptureEvent(row, runId);
|
|
51
|
+
if (capture) found.set(capture.path, capture);
|
|
52
|
+
}
|
|
53
|
+
return [...found.values()].sort((a, b) => a.createdAt - b.createdAt || a.path.localeCompare(b.path));
|
|
54
|
+
} finally { store.close(); }
|
|
55
|
+
}
|
|
@@ -56,7 +56,8 @@ import type {
|
|
|
56
56
|
// v3 (Mission Fabric 통합 U1 · 2026-07-09) — tox_missions.autopilot_json
|
|
57
57
|
// (PFC Layer2 자율 메타 흡수 · apm Mission 병렬 table 제거 준비)
|
|
58
58
|
// v4 — external task identity and approval
|
|
59
|
-
|
|
59
|
+
// v5 — run-scoped browser capture artifacts on executions
|
|
60
|
+
export const TOX_SCHEMA_VERSION = 5;
|
|
60
61
|
|
|
61
62
|
// ─────────────────────── Row shapes ────────────────────────────────
|
|
62
63
|
|
|
@@ -114,6 +115,8 @@ interface ExecutionRow {
|
|
|
114
115
|
model_id: string | null;
|
|
115
116
|
host_id: string | null;
|
|
116
117
|
hostname: string | null;
|
|
118
|
+
run_id: string | null;
|
|
119
|
+
capture_artifacts_json: string | null;
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
interface EventRow {
|
|
@@ -262,7 +265,9 @@ export class TaskStore {
|
|
|
262
265
|
token_input INTEGER,
|
|
263
266
|
token_output INTEGER,
|
|
264
267
|
cost_usd REAL,
|
|
265
|
-
model_id TEXT
|
|
268
|
+
model_id TEXT,
|
|
269
|
+
run_id TEXT,
|
|
270
|
+
capture_artifacts_json TEXT
|
|
266
271
|
);
|
|
267
272
|
|
|
268
273
|
CREATE TABLE IF NOT EXISTS tox_events (
|
|
@@ -314,6 +319,8 @@ export class TaskStore {
|
|
|
314
319
|
this.db.exec('CREATE INDEX IF NOT EXISTS idx_tox_missions_project ON tox_missions(project_id)');
|
|
315
320
|
this.addColumnIfMissing('tox_executions', 'host_id', 'TEXT');
|
|
316
321
|
this.addColumnIfMissing('tox_executions', 'hostname', 'TEXT');
|
|
322
|
+
this.addColumnIfMissing('tox_executions', 'run_id', 'TEXT');
|
|
323
|
+
this.addColumnIfMissing('tox_executions', 'capture_artifacts_json', 'TEXT');
|
|
317
324
|
this.db.exec('CREATE INDEX IF NOT EXISTS idx_tox_executions_host ON tox_executions(host_id, started_at)');
|
|
318
325
|
this.addColumnIfMissing('tox_tasks', 'approval_json', 'TEXT');
|
|
319
326
|
this.addColumnIfMissing('tox_tasks', 'external_provider', 'TEXT');
|
|
@@ -477,8 +484,8 @@ export class TaskStore {
|
|
|
477
484
|
`INSERT OR REPLACE INTO tox_executions (
|
|
478
485
|
id, task_id, started_at, ended_at, duration_ms, status, surface_json,
|
|
479
486
|
surface_address, output, output_path, error_json, token_input,
|
|
480
|
-
token_output, cost_usd, model_id, host_id, hostname
|
|
481
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
487
|
+
token_output, cost_usd, model_id, host_id, hostname, run_id, capture_artifacts_json
|
|
488
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
482
489
|
)
|
|
483
490
|
.run(
|
|
484
491
|
exec.id,
|
|
@@ -497,7 +504,9 @@ export class TaskStore {
|
|
|
497
504
|
exec.costUsd ?? null,
|
|
498
505
|
exec.modelId ?? null,
|
|
499
506
|
hostId ?? null,
|
|
500
|
-
hostname ?? null
|
|
507
|
+
hostname ?? null,
|
|
508
|
+
exec.runId ?? null,
|
|
509
|
+
exec.captureArtifacts ? JSON.stringify(exec.captureArtifacts) : null
|
|
501
510
|
));
|
|
502
511
|
}
|
|
503
512
|
|
|
@@ -769,6 +778,8 @@ export class TaskStore {
|
|
|
769
778
|
modelId: row.model_id ?? undefined,
|
|
770
779
|
...(row.host_id !== null ? { hostId: row.host_id } : {}),
|
|
771
780
|
...(row.hostname !== null ? { hostname: row.hostname } : {}),
|
|
781
|
+
...(row.run_id !== null ? { runId: row.run_id } : {}),
|
|
782
|
+
...(row.capture_artifacts_json ? { captureArtifacts: JSON.parse(row.capture_artifacts_json) as TaskExecution['captureArtifacts'] } : {}),
|
|
772
783
|
};
|
|
773
784
|
}
|
|
774
785
|
}
|
|
@@ -102,6 +102,10 @@ export function podNoResultDiagnostic(ledger: string): string | null {
|
|
|
102
102
|
try {
|
|
103
103
|
const entry = JSON.parse(line) as { event?: unknown; data?: Record<string, unknown> };
|
|
104
104
|
if (!entry || typeof entry !== 'object' || !entry.data || typeof entry.data !== 'object' || typeof entry.event !== 'string' || entry.event === 'pod-ledger-incomplete') continue;
|
|
105
|
+
// Route evidence is not a child execution stage. The observer writes the category
|
|
106
|
+
// (`graph.path`) only to the log store; the run ledger keeps the event name
|
|
107
|
+
// (`path-signature`), which may be appended after the child failure.
|
|
108
|
+
if (entry.event === 'graph.path' || entry.event === 'path-signature') continue;
|
|
105
109
|
if (typeof entry.data.round === 'number' && Number.isSafeInteger(entry.data.round)) round = entry.data.round;
|
|
106
110
|
if (entry.event !== 'run-origin') stage = entry.event;
|
|
107
111
|
// `reviewed` carries pointers only (count + finding ids); the text stays in the review artifact.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { PodPoolMember, PodPoolScheduler } from './pod-pool.js';
|
|
2
|
+
export { POD_DISTRIBUTOR_ENTRY_ENV, TASK_HAND_POD_DISTRIBUTOR_ENTRY } from '../../task-agent/pod-distributor-entry.js';
|
|
3
|
+
import { TASK_HAND_POD_DISTRIBUTOR_ENTRY } from '../../task-agent/pod-distributor-entry.js';
|
|
4
|
+
|
|
5
|
+
/** Origin marker carried only by `tasks hand` Pod launches. */
|
|
6
|
+
export type PodPoolAcquireMode = NonNullable<Parameters<PodPoolScheduler['tryAcquire']>[2]>;
|
|
7
|
+
|
|
8
|
+
/** Admission context that the later resource-core adapter can map to its request contract. */
|
|
9
|
+
export interface PodDistributorAdmission {
|
|
10
|
+
requestId: string;
|
|
11
|
+
idempotencyKey: string;
|
|
12
|
+
owner: { runId: string; cardId?: string; seat?: string };
|
|
13
|
+
lane: 'ta';
|
|
14
|
+
workload: { memoryLimit: string; kind: string };
|
|
15
|
+
skip?: ReadonlySet<string>;
|
|
16
|
+
onEmpty?: (reason: string) => void;
|
|
17
|
+
mode?: PodPoolAcquireMode;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Small seam between a Pod launch surface and its admission backend.
|
|
22
|
+
* The current adapter delegates to PodPoolScheduler, which owns the existing HostPoolLease accounting.
|
|
23
|
+
* CORE can replace this adapter with resource admission without changing the tasks-hand call site.
|
|
24
|
+
*/
|
|
25
|
+
export interface PodDistributorAdapter {
|
|
26
|
+
acquire(request: PodDistributorAdmission): Promise<PodPoolMember | null>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function createPodPoolDistributorAdapter(pool: PodPoolScheduler): PodDistributorAdapter {
|
|
30
|
+
// The legacy pool has no consumer for identity/workload fields; preserve them at this seam for CORE.
|
|
31
|
+
return {
|
|
32
|
+
acquire: ({ skip, onEmpty, mode }) => pool.tryAcquire(skip, onEmpty, mode),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Only the tasks-hand entry uses the adapter in this first wire slice; other launchers keep the established path. */
|
|
37
|
+
export function acquirePodPoolSlot(input: {
|
|
38
|
+
entry: string | undefined;
|
|
39
|
+
pool: PodPoolScheduler;
|
|
40
|
+
adapter?: PodDistributorAdapter;
|
|
41
|
+
request: PodDistributorAdmission;
|
|
42
|
+
}): Promise<PodPoolMember | null> {
|
|
43
|
+
const { entry, pool, adapter, request } = input;
|
|
44
|
+
if (entry === TASK_HAND_POD_DISTRIBUTOR_ENTRY) {
|
|
45
|
+
return (adapter ?? createPodPoolDistributorAdapter(pool)).acquire(request);
|
|
46
|
+
}
|
|
47
|
+
return pool.tryAcquire(request.skip, request.onEmpty, request.mode);
|
|
48
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { podChildProviderOf, type PodChildProvider } from './pod-child-providers.js';
|
|
2
|
+
|
|
1
3
|
/** STOP-RECORD stop_class values used by the card terminal classifier. */
|
|
2
4
|
export const STOP_CLASS_POD_FAILURE = 'pod-failure' as const;
|
|
3
5
|
export const STOP_CLASS_NO_LAUNCH = 'no-launch' as const;
|
|
@@ -20,12 +22,19 @@ export function nestedPodResult(row: Record<string, unknown>): {
|
|
|
20
22
|
const result = row.result as Record<string, unknown>;
|
|
21
23
|
if (typeof result.stage !== 'string' || typeof result.ok !== 'boolean') return null;
|
|
22
24
|
if (result.ok) return { stage: result.stage, ok: true };
|
|
25
|
+
// The terminal stage/node/outcome often says only `aborted` or `abandoned`.
|
|
26
|
+
// Keep the child's explicit stop detail (for example a same-cell PR guard
|
|
27
|
+
// failure) while retaining the established node/outcome/classification text.
|
|
28
|
+
// Forward only the typed guard failure this path owns. Other aborted children
|
|
29
|
+
// can carry verbose PTY summaries in `detail`; those are not parent attribution.
|
|
30
|
+
const explicitDetail = result.detailKind === 'blocked-draft-pr-guard' ? ledgerString(result.detail) : '';
|
|
23
31
|
const classification = result.abandonedClassification;
|
|
24
32
|
const detail = typeof result.supervisorVerdict === 'string' ? result.supervisorVerdict
|
|
25
33
|
: classification && typeof classification === 'object' && !Array.isArray(classification)
|
|
26
34
|
? (classification as Record<string, unknown>).classification : undefined;
|
|
27
35
|
const reason = [result.node, result.outcome].filter((part): part is string => typeof part === 'string' && part.length > 0).join(' ');
|
|
28
|
-
const error = [reason || (typeof result.error === 'string' ? result.error : ''), typeof detail === 'string' && detail ? detail : '']
|
|
36
|
+
const error = [reason || (typeof result.error === 'string' ? result.error : ''), typeof detail === 'string' && detail ? detail : '', explicitDetail]
|
|
37
|
+
.filter(Boolean).join(' · ');
|
|
29
38
|
// PREFLIGHT-RESULT-LINE: a nested preflight rejection carries its blockers under result.blockers — the same ledger fields as the flat row.
|
|
30
39
|
const blockers = result.stage === 'preflight-blocked' ? preflightBlockerText(result.blockers)
|
|
31
40
|
: { error: '', preflightChecks: [] as PreflightCheck[] };
|
|
@@ -121,6 +130,15 @@ export function podTerminalRow(row: Record<string, unknown>): {
|
|
|
121
130
|
return nestedPodResult(row);
|
|
122
131
|
}
|
|
123
132
|
|
|
133
|
+
/**
|
|
134
|
+
* OBS-GAP-BATCH-1030 — 자식 LLM 실패의 «누가·어떤 HTTP status 로» 죽었나를 부모 원장에 얹는 두 스칼라.
|
|
135
|
+
* ⛔ 응답 본문·메시지·자격증명은 담지 않는다 — provider 는 정규 id, status 는 4xx/5xx 숫자뿐이다.
|
|
136
|
+
*/
|
|
137
|
+
export interface PodProviderFailureFact {
|
|
138
|
+
readonly provider?: PodChildProvider;
|
|
139
|
+
readonly httpStatusCode?: number;
|
|
140
|
+
}
|
|
141
|
+
|
|
124
142
|
export const POD_EXIT_CLASSES = ['oom-killed', 'deadline-exceeded', 'gh-login-failed', 'pod-secret', 'ask-reprompt', 'provider-error', 'child-unconverged', 'child-error', 'no-result-line', 'unknown'] as const;
|
|
125
143
|
|
|
126
144
|
export type PodExitClass = typeof POD_EXIT_CLASSES[number];
|
|
@@ -143,6 +161,8 @@ export function podChildEvidenceLedgerRow(input: {
|
|
|
143
161
|
noResultDiagnostic?: string | null;
|
|
144
162
|
noResultLogEvidence?: Record<string, unknown> | null;
|
|
145
163
|
podTermination?: PodTermination | null;
|
|
164
|
+
/** OBS-GAP-BATCH-1030 — 실패 행에만 붙는 두 스칼라(provider · HTTP status). 없으면 종전 행 그대로. */
|
|
165
|
+
providerFailure?: PodProviderFailureFact | null;
|
|
146
166
|
}): Record<string, unknown> | null {
|
|
147
167
|
const { result } = input;
|
|
148
168
|
const persist = input.state === 'failed' || input.state === 'aborted' || input.noResultLogEvidence != null
|
|
@@ -163,6 +183,8 @@ export function podChildEvidenceLedgerRow(input: {
|
|
|
163
183
|
childEvidence,
|
|
164
184
|
childRunId: input.childRunId,
|
|
165
185
|
job: input.job,
|
|
186
|
+
...(input.providerFailure?.provider ? { provider: input.providerFailure.provider } : {}),
|
|
187
|
+
...(input.providerFailure?.httpStatusCode !== undefined ? { httpStatusCode: input.providerFailure.httpStatusCode } : {}),
|
|
166
188
|
...(input.podTermination ? { podTermination: input.podTermination } : {}),
|
|
167
189
|
...(childResult && Object.keys(childResult).length > 0 ? { childResult } : {}),
|
|
168
190
|
};
|
|
@@ -195,6 +217,75 @@ function isPodProviderErrorLine(line: string): boolean {
|
|
|
195
217
|
return POD_PROVIDER_ERROR_LINE.test(line);
|
|
196
218
|
}
|
|
197
219
|
|
|
220
|
+
/** 401·429·503 같은 «상태 숫자»만 — 응답 본문·메시지는 돌려주지 않는다. 4xx/5xx 밖의 수는 상태가 아니다. */
|
|
221
|
+
function podProviderHttpStatus(line: string): number | undefined {
|
|
222
|
+
const explicit = /"status"\s*:\s*(\d{3})/u.exec(line) ?? /\b(?:LLM API|HTTP|status(?:[ _-]?code)?)\b\s*[:=]?\s*(\d{3})\b/iu.exec(line);
|
|
223
|
+
// 맨숫자 형태는 «상태 자리»에 선 것만 — `500ms`·`1.5e3` 같은 수를 상태로 세지 않는다.
|
|
224
|
+
const digits = (explicit ?? /(?:^|[^\d])([45]\d{2})(?![\d\p{L}.])/u.exec(line))?.[1];
|
|
225
|
+
const value = digits === undefined ? NaN : Number(digits);
|
|
226
|
+
return Number.isSafeInteger(value) && value >= 400 && value <= 599 ? value : undefined;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** 줄이 이름한 provider — `llm.<id>` 접두 우선, 없으면 줄 안의 정식 이름/별칭. 목록 밖 이름은 세지 않는다. */
|
|
230
|
+
function podLineProvider(line: string): PodChildProvider | undefined {
|
|
231
|
+
const scoped = /\bllm\.([a-z0-9_-]+)\b/iu.exec(line)?.[1];
|
|
232
|
+
const scopedProvider = podChildProviderOf(scoped);
|
|
233
|
+
if (scopedProvider) return scopedProvider;
|
|
234
|
+
for (const token of line.match(/[A-Za-z][A-Za-z0-9_-]{1,31}/gu) ?? []) {
|
|
235
|
+
const provider = podChildProviderOf(token);
|
|
236
|
+
if (provider) return provider;
|
|
237
|
+
}
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** provider 실패를 «말하는» 줄 — 분류기가 provider-error 로 읽는 줄, 또는 자식이 낸 `LLM API <status>` 문면. */
|
|
242
|
+
const isPodProviderFailureSource = (line: string): boolean => isPodProviderErrorLine(line) || /\bLLM API\s+\d{3}\b/iu.test(line);
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* 마지막 canonical 자식 terminal 과 «그 직전» 구간 — duplicate-cap 귀속의 한 자리(classifyPodExit 과 같은 규칙).
|
|
246
|
+
* terminal 이 없으면 구간은 전체 로그다(결과행 없는 자식도 provider 실패는 귀속된다).
|
|
247
|
+
*/
|
|
248
|
+
function podTerminalWindow(logs: string): { terminal: ReturnType<typeof podTerminalRow>; window: string[] } {
|
|
249
|
+
const lines = logs.split(/\r\n|\n|\r/u);
|
|
250
|
+
let terminal: ReturnType<typeof podTerminalRow> = null;
|
|
251
|
+
let lastIndex = -1;
|
|
252
|
+
let previousIndex = -1;
|
|
253
|
+
for (const [index, raw] of lines.entries()) {
|
|
254
|
+
const line = raw.trim();
|
|
255
|
+
if (!line.startsWith('{')) continue;
|
|
256
|
+
let parsed: unknown;
|
|
257
|
+
try { parsed = JSON.parse(line); } catch { continue; }
|
|
258
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) continue;
|
|
259
|
+
const row = podTerminalRow(parsed as Record<string, unknown>);
|
|
260
|
+
if (!row) continue;
|
|
261
|
+
previousIndex = lastIndex;
|
|
262
|
+
terminal = row;
|
|
263
|
+
lastIndex = index;
|
|
264
|
+
}
|
|
265
|
+
const window = lines.slice(previousIndex + 1, lastIndex === -1 ? undefined : lastIndex)
|
|
266
|
+
.map((line) => line.trim()).filter(Boolean);
|
|
267
|
+
return { terminal, window };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* OBS-GAP-BATCH-1030 — 자식 실패를 «공급자 + HTTP status» 로 귀속한다(응답 본문·자격증명 제외).
|
|
272
|
+
* 마지막 canonical terminal 이 성공이면 null — 과거(재시도 전) provider 실패를 성공한 결과에 재사용하지 않는다.
|
|
273
|
+
* 줄이 공급자를 이름하지 않으면 호출자가 준 hint(Pod 의 자식 provider)를 정규 id 로만 쓴다.
|
|
274
|
+
*/
|
|
275
|
+
export function podChildProviderFailureFact(logs: string, opts?: { providerHint?: string }): PodProviderFailureFact | null {
|
|
276
|
+
const { terminal, window } = podTerminalWindow(logs);
|
|
277
|
+
if (terminal?.ok === true) return null;
|
|
278
|
+
const terminalErrors = typeof terminal?.error === 'string'
|
|
279
|
+
? terminal.error.split(/\r\n|\n|\r/u).map((line) => line.trim()).filter(Boolean) : [];
|
|
280
|
+
const sources = [...window, ...terminalErrors].filter((line) => isPodProviderFailureSource(line)).reverse();
|
|
281
|
+
if (!sources.length) return null;
|
|
282
|
+
// 마지막 줄이 `LLM API <status>` 만 말할 수 있다 — 공급자는 «이름한» 줄에서 따로 찾는다.
|
|
283
|
+
const provider = sources.map(podLineProvider).find((named) => named !== undefined) ?? podChildProviderOf(opts?.providerHint);
|
|
284
|
+
const httpStatusCode = sources.map(podProviderHttpStatus).find((status) => status !== undefined);
|
|
285
|
+
if (!provider && httpStatusCode === undefined) return null;
|
|
286
|
+
return { ...(provider ? { provider } : {}), ...(httpStatusCode !== undefined ? { httpStatusCode } : {}) };
|
|
287
|
+
}
|
|
288
|
+
|
|
198
289
|
/**
|
|
199
290
|
* POD-FAIL-EVIDENCE-CAPTURE-FU — duplicate-cap 귀속: 마지막 «canonical» 자식 terminal 하나에만 실패를 붙인다.
|
|
200
291
|
* canonical 접두(`self`/`external`)가 아닌 lookalike kind 행은 건너뛰고, 마지막 canonical terminal 이 성공이거나
|
|
@@ -184,6 +184,37 @@ export function createPodLedgerFollower(opts: {
|
|
|
184
184
|
if (!Number.isFinite(stallMinutes) || stallMinutes <= 0) throw new RangeError('stallMinutes must be positive');
|
|
185
185
|
const onStall = opts.onStall ?? ((message: string) => console.error(message));
|
|
186
186
|
const path = runLedgerPath(opts.runId, dir); // runId 검증(경로·셸에 안전한 문자만)도 여기서 된다
|
|
187
|
+
function activityTimestamp(epoch: number): string {
|
|
188
|
+
const iso = new Date(Math.floor(epoch / 1_000) * 1_000).toISOString();
|
|
189
|
+
return `${iso.slice(0, 4)}${iso.slice(5, 7)}${iso.slice(8, 10)}${iso.slice(11, 13)}${iso.slice(14, 16)}.${iso.slice(17, 19)}`;
|
|
190
|
+
}
|
|
191
|
+
function activityCommand(since: string, until: string, offset: number, sinceTimestamp: string, untilTimestamp: string): string {
|
|
192
|
+
return [
|
|
193
|
+
`s="\${ELANOUS_STATE_DIR:-$HOME/.elanous}"`,
|
|
194
|
+
`f="$s/run-ledger/${opts.runId}.jsonl"`,
|
|
195
|
+
'w="$s/worktrees"',
|
|
196
|
+
'if [ -f "$f" ]; then tail -c +' + (offset + 1) + ' "$f" || exit 1; fi',
|
|
197
|
+
"target=''; matches=0",
|
|
198
|
+
'for tree in "$w"/*/*.worktrees/*; do',
|
|
199
|
+
' [ -e "$tree/.git" ] || continue',
|
|
200
|
+
' owner=$(git -C "$tree" config --worktree --get elanous.harness.owner 2>/dev/null) || continue',
|
|
201
|
+
` [ "$owner" = 'dev:${opts.runId}' ] || continue`,
|
|
202
|
+
' target="$tree"; matches=$((matches + 1))',
|
|
203
|
+
'done',
|
|
204
|
+
'if [ "$matches" -eq 1 ]; then',
|
|
205
|
+
' touch_activity_ref() { stamp_value=$1; fallback=$2; ref=$3; touch -d "@$stamp_value" "$ref" 2>/dev/null && return 0; TZ=UTC touch -t "$fallback" "$ref"; }',
|
|
206
|
+
` activity_since="$s/.pod-activity-${opts.runId}-$$-since"`,
|
|
207
|
+
` activity_until="$s/.pod-activity-${opts.runId}-$$-until"`,
|
|
208
|
+
" activity=''",
|
|
209
|
+
` if : > "$activity_since" && : > "$activity_until" && touch_activity_ref '${since}' '${sinceTimestamp}' "$activity_since" && touch_activity_ref '${until}' '${untilTimestamp}' "$activity_until"; then`,
|
|
210
|
+
' activity=$(find "$target" -type d \\( -name .git -o -name node_modules \\) -prune -o -type f -newer "$activity_since" ! -newer "$activity_until" -exec printf . \\; 2>/dev/null)',
|
|
211
|
+
' activity_status=$?',
|
|
212
|
+
' else activity_status=1; fi',
|
|
213
|
+
' rm -f "$activity_since" "$activity_until"',
|
|
214
|
+
' if [ "$activity_status" -eq 0 ]; then printf \'\\nELANOUS_ACTIVITY %s\\n\' "\${#activity}"; else printf \'\\nELANOUS_ACTIVITY_ERROR\\n\'; fi',
|
|
215
|
+
"else printf '\\nELANOUS_ACTIVITY_ERROR\\n'; fi",
|
|
216
|
+
].join('\n');
|
|
217
|
+
}
|
|
187
218
|
let offset = 0;
|
|
188
219
|
let pending = '';
|
|
189
220
|
let owned = false;
|
|
@@ -218,7 +249,13 @@ export function createPodLedgerFollower(opts: {
|
|
|
218
249
|
const since = `${Math.floor(lastActivityMeasuredAt / 1000)}.${String(lastActivityMeasuredAt % 1000).padStart(3, '0')}`;
|
|
219
250
|
const measurementStartedAt = now();
|
|
220
251
|
const until = `${Math.floor(measurementStartedAt / 1000)}.${String(measurementStartedAt % 1000).padStart(3, '0')}`;
|
|
221
|
-
const r = opts.exec(
|
|
252
|
+
const r = opts.exec(activityCommand(
|
|
253
|
+
since,
|
|
254
|
+
until,
|
|
255
|
+
offset,
|
|
256
|
+
activityTimestamp(lastActivityMeasuredAt),
|
|
257
|
+
activityTimestamp(measurementStartedAt),
|
|
258
|
+
));
|
|
222
259
|
if (r.status !== 0) { log('self-implement.pod', 'ledger-live-unavailable', { runId: opts.runId, status: r.status, stderr: r.stderr.trim().slice(0, 200) }); checkStall(false, false); return { ledgerRead: false, activityMeasured: false }; }
|
|
223
260
|
const marker = r.stdout.lastIndexOf('\nELANOUS_ACTIVITY');
|
|
224
261
|
const activityLine = marker < 0 ? '' : r.stdout.slice(marker + 1);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
+
import { podTerminalRow } from './pod-failure-reason.js';
|
|
4
5
|
|
|
5
6
|
/** Capture a failed Job against its recorded placement, never the caller's current kubectl context. */
|
|
6
7
|
export function captureFailedPodJobs(input: {
|
|
@@ -39,10 +40,14 @@ export function captureFailedPodJobs(input: {
|
|
|
39
40
|
finish('failed', 'placement-conflict'); return;
|
|
40
41
|
}
|
|
41
42
|
const location = { host: first.host, context: first.context, namespace: first.namespace, childRunId: first.childRunId, jobUid: first.jobUid };
|
|
43
|
+
const childRows = rows.filter(row => row.event === 'pod-child-run' && row.data?.job === job
|
|
44
|
+
&& row.data.childRunId === first.childRunId && Number.isSafeInteger(row.data.attempt)
|
|
45
|
+
&& (row.data.attempt as number) > 0);
|
|
46
|
+
const attempt = childRows.length ? childRows[childRows.length - 1]!.data!.attempt as number : undefined;
|
|
42
47
|
const evidenceDir = join(artifactDir, 'pod-failure-capture', runId, job, first.childRunId as string);
|
|
43
48
|
// A failed kubectl/SSH read is itself the missing diagnostic. Keep its stderr in
|
|
44
49
|
// the private artifact directory and put only the path and exit status in the ledger.
|
|
45
|
-
const
|
|
50
|
+
const captureStderr = (reason: string, result: { status: number | null; stderr: string }): Record<string, unknown> => {
|
|
46
51
|
let stderrEvidence: string | null = null;
|
|
47
52
|
let stderrCaptureStatus: 'saved' | 'redacted' | 'empty' | 'write-failed' = result.stderr ? 'saved' : 'empty';
|
|
48
53
|
if (result.stderr) {
|
|
@@ -61,19 +66,40 @@ export function captureFailedPodJobs(input: {
|
|
|
61
66
|
}
|
|
62
67
|
} catch { stderrEvidence = null; stderrCaptureStatus = 'write-failed'; }
|
|
63
68
|
}
|
|
64
|
-
|
|
69
|
+
return { kubectlStatus: result.status, stderrEvidence, stderrCaptureStatus };
|
|
70
|
+
};
|
|
71
|
+
const readFailure = (reason: string, result: { status: number | null; stderr: string }, extra: Record<string, unknown> = {}): void => {
|
|
72
|
+
finish('failed', reason, { ...location, ...extra, ...captureStderr(reason, result) });
|
|
65
73
|
};
|
|
66
74
|
const previous = rows.find(row => row.event === 'pod-failure-capture' && row.data?.job === job && row.data?.outcome === 'collected'
|
|
67
75
|
&& row.data.childRunId === first.childRunId && row.data.jobUid === first.jobUid
|
|
68
76
|
&& row.data.host === first.host && row.data.context === first.context && row.data.namespace === first.namespace);
|
|
77
|
+
const priorLogEvidence = previous?.data?.logEvidence;
|
|
78
|
+
const priorPreviousLogEvidence = previous?.data?.previousLogEvidence;
|
|
79
|
+
const priorCurrentReadStatus = previous?.data?.currentLogReadStatus;
|
|
80
|
+
const priorPreviousReadStatus = previous?.data?.previousLogReadStatus;
|
|
69
81
|
// A ledger row describes a prior collection; it does not guarantee that its files survived.
|
|
70
|
-
//
|
|
71
|
-
|
|
82
|
+
// Validate the required artifacts and every log artifact claimed by the prior row before deduping.
|
|
83
|
+
// Unknown restart count is terminal for this Job snapshot: another identical Pod read cannot recover it.
|
|
84
|
+
const previousReadComplete = priorCurrentReadStatus === 'captured'
|
|
85
|
+
? ['captured', 'empty', 'not-needed', 'unknown'].includes(String(priorPreviousReadStatus))
|
|
86
|
+
: priorCurrentReadStatus === 'empty' && priorPreviousReadStatus === 'captured';
|
|
87
|
+
const currentLogEvidencePresent = priorCurrentReadStatus === 'captured'
|
|
88
|
+
&& priorLogEvidence === join(evidenceDir, 'child.log')
|
|
89
|
+
&& (() => { try { return statSync(priorLogEvidence).isFile(); } catch { return false; } })();
|
|
90
|
+
const previousLogEvidencePresent = priorPreviousReadStatus === 'captured'
|
|
91
|
+
&& priorPreviousLogEvidence === join(evidenceDir, 'child.previous.log')
|
|
92
|
+
&& (() => { try { return statSync(priorPreviousLogEvidence).isFile(); } catch { return false; } })();
|
|
93
|
+
const logEvidenceComplete = currentLogEvidencePresent
|
|
94
|
+
? priorPreviousReadStatus !== 'captured' || previousLogEvidencePresent
|
|
95
|
+
: priorCurrentReadStatus === 'empty' && previousLogEvidencePresent;
|
|
96
|
+
if (previous && previousReadComplete && ([['jobEvidence', 'job.json'], ['podEvidence', 'pods.json']] as const)
|
|
72
97
|
.every(([field, filename]) => {
|
|
73
98
|
const path = join(evidenceDir, filename);
|
|
74
99
|
if (previous.data?.[field] !== path) return false;
|
|
75
100
|
try { return statSync(path).isFile(); } catch { return false; }
|
|
76
|
-
})
|
|
101
|
+
})
|
|
102
|
+
&& logEvidenceComplete) return;
|
|
77
103
|
const args = ['--context', first.context as string, '-n', first.namespace as string] as const;
|
|
78
104
|
try {
|
|
79
105
|
const jobResult = kubectl(first.host as string, [...args, 'get', 'job', job, '-o', 'json']);
|
|
@@ -103,23 +129,88 @@ export function captureFailedPodJobs(input: {
|
|
|
103
129
|
});
|
|
104
130
|
const podResult = kubectl(first.host as string, [...args, 'get', 'pods', '-l', `job-name=${job}`, '-o', 'json']);
|
|
105
131
|
if (podResult.status !== 0) { readFailure('pods-read-failed', podResult, { jobEvidence }); return; }
|
|
106
|
-
const pods = JSON.parse(podResult.stdout) as { items?: Array<{
|
|
132
|
+
const pods = JSON.parse(podResult.stdout) as { items?: Array<{
|
|
133
|
+
metadata?: { name?: string; uid?: string; ownerReferences?: Array<{ uid?: string }> };
|
|
134
|
+
status?: { phase?: string; containerStatuses?: Array<{ name?: string; restartCount?: number;
|
|
135
|
+
state?: { terminated?: { reason?: string; exitCode?: number; finishedAt?: string } } }> };
|
|
136
|
+
}> };
|
|
107
137
|
if (!pods.items?.length || pods.items.some(p => !p.metadata?.ownerReferences?.some(owner => owner.uid === jobBody.metadata?.uid))) {
|
|
108
138
|
finish('failed', 'pod-owner-mismatch', { ...location, jobEvidence }); return;
|
|
109
139
|
}
|
|
110
140
|
const podEvidence = save('pods.json', podResult.stdout);
|
|
111
|
-
const
|
|
141
|
+
const pod = pods.items[0]!;
|
|
142
|
+
const podName = pod.metadata?.name;
|
|
112
143
|
if (pods.items.length !== 1 || !podName || !/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(podName)) {
|
|
113
144
|
finish('failed', 'pod-ambiguous', { ...location, jobEvidence, podEvidence }); return;
|
|
114
145
|
}
|
|
146
|
+
const childStatus = pod.status?.containerStatuses?.find(status => status.name === 'child');
|
|
147
|
+
const terminated = childStatus?.state?.terminated;
|
|
148
|
+
const shortCode = (value: unknown): string | undefined => typeof value === 'string' && /^[A-Za-z0-9_.:-]{1,64}$/.test(value) && !SECRET_VALUE.test(value) ? value : undefined;
|
|
149
|
+
const numeric = (value: unknown): number | undefined => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
150
|
+
const exitCode = (value: unknown): number | undefined => typeof value === 'number' && Number.isSafeInteger(value) ? value : undefined;
|
|
151
|
+
const restartCount = numeric(childStatus?.restartCount);
|
|
152
|
+
const podSummary: Record<string, unknown> = {
|
|
153
|
+
...location,
|
|
154
|
+
...(attempt !== undefined ? { attempt } : {}), podName,
|
|
155
|
+
...(shortCode(pod.metadata?.uid) ? { podUid: shortCode(pod.metadata?.uid) } : {}),
|
|
156
|
+
...(shortCode(pod.status?.phase) ? { podPhase: shortCode(pod.status?.phase) } : {}),
|
|
157
|
+
...(shortCode(terminated?.reason) ? { containerReason: shortCode(terminated?.reason) } : {}),
|
|
158
|
+
...(exitCode(terminated?.exitCode) !== undefined ? { containerExitCode: exitCode(terminated?.exitCode) } : {}),
|
|
159
|
+
...(typeof terminated?.finishedAt === 'string' && /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?Z$/.test(terminated.finishedAt) ? { containerFinishedAt: terminated.finishedAt } : {}),
|
|
160
|
+
...(restartCount !== undefined ? { containerRestartCount: restartCount } : {}),
|
|
161
|
+
};
|
|
115
162
|
const logs = kubectl(first.host as string, [...args, 'logs', `pod/${podName}`, '-c', 'child']);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
163
|
+
const currentLogReadStatus = logs.status === 0 ? (logs.stdout.trim() ? 'captured' : 'empty') : 'failed';
|
|
164
|
+
const currentLogBytes = logs.status === 0 ? Buffer.byteLength(logs.stdout) : 0;
|
|
165
|
+
let logEvidence: string | undefined;
|
|
166
|
+
let previousLogEvidence: string | undefined;
|
|
167
|
+
let previousLogReadStatus = restartCount === undefined || restartCount > 0 ? 'unknown' : 'not-needed';
|
|
168
|
+
let previousLogBytes: number | undefined;
|
|
169
|
+
let previousLogFailure: Record<string, unknown> = {};
|
|
170
|
+
let resultMarkerPresent = false;
|
|
171
|
+
if (logs.status === 0 && logs.stdout.trim()) {
|
|
172
|
+
logEvidence = save('child.log', logs.stdout);
|
|
173
|
+
resultMarkerPresent = hasTerminalMarker(logs.stdout);
|
|
174
|
+
}
|
|
175
|
+
if (restartCount !== undefined && restartCount > 0) {
|
|
176
|
+
const previousLogs = kubectl(first.host as string, [...args, 'logs', `pod/${podName}`, '-c', 'child', '--previous']);
|
|
177
|
+
previousLogReadStatus = previousLogs.status === 0 ? (previousLogs.stdout.trim() ? 'captured' : 'empty') : 'failed';
|
|
178
|
+
previousLogBytes = previousLogs.status === 0 ? Buffer.byteLength(previousLogs.stdout) : 0;
|
|
179
|
+
if (previousLogs.status !== 0) {
|
|
180
|
+
const failure = captureStderr('previous-logs-read-failed', previousLogs);
|
|
181
|
+
previousLogFailure = {
|
|
182
|
+
previousLogKubectlStatus: failure.kubectlStatus,
|
|
183
|
+
previousLogStderrEvidence: failure.stderrEvidence,
|
|
184
|
+
previousLogStderrCaptureStatus: failure.stderrCaptureStatus,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (previousLogs.status === 0 && previousLogs.stdout.trim()) {
|
|
188
|
+
previousLogEvidence = save('child.previous.log', previousLogs.stdout);
|
|
189
|
+
resultMarkerPresent ||= hasTerminalMarker(previousLogs.stdout);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const summary = { ...podSummary, jobEvidence, podEvidence, currentLogReadStatus, currentLogBytes,
|
|
193
|
+
previousLogReadStatus, ...(previousLogBytes !== undefined ? { previousLogBytes } : {}), ...previousLogFailure, resultMarkerPresent,
|
|
194
|
+
...(logEvidence ? { logEvidence } : {}), ...(previousLogEvidence ? { previousLogEvidence } : {}) };
|
|
195
|
+
if (currentLogReadStatus !== 'captured' && previousLogReadStatus !== 'captured') {
|
|
196
|
+
if (logs.status !== 0) { readFailure('logs-read-failed', logs, summary); return; }
|
|
197
|
+
finish('failed', 'logs-empty', summary); return;
|
|
198
|
+
}
|
|
199
|
+
if (logs.status !== 0) finish('collected', 'job-failed', { ...summary, ...captureStderr('logs-read-failed', logs) });
|
|
200
|
+
else finish('collected', 'job-failed', summary);
|
|
120
201
|
} catch { finish('failed', 'capture-error', location); }
|
|
121
202
|
}
|
|
122
203
|
|
|
204
|
+
function hasTerminalMarker(logs: string): boolean {
|
|
205
|
+
for (const line of logs.split(/\r?\n/)) {
|
|
206
|
+
try {
|
|
207
|
+
const row: unknown = JSON.parse(line);
|
|
208
|
+
if (row && typeof row === 'object' && !Array.isArray(row) && podTerminalRow(row as Record<string, unknown>)) return true;
|
|
209
|
+
} catch { /* ordinary child output is not a terminal result marker */ }
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
|
|
123
214
|
const SECRET_FIELD = /token|secret|password|authorization|key/i;
|
|
124
215
|
const SAFE_FIELD = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
|
|
125
216
|
const SECRET_VALUE = /(?:\b(?:bearer|basic)\s+\S+|\b(?:token|secret|password|authorization|api[-_]?key|access[-_]?key|private[-_]?key)\b\s*(?:is|[=:])\s*["']?\S+|\b(?:sk-[A-Za-z0-9_-]{8,}|gh[pousr]_[A-Za-z0-9_]{8,}))\b/i;
|
|
@@ -127,8 +218,12 @@ const MAX_FIELDS = 32;
|
|
|
127
218
|
// Review R2: only lifecycle events the host needs to see, and no free text. Event names must start with a known
|
|
128
219
|
// lifecycle prefix; string fields survive only when they are short code-like values in a fixed set of keys.
|
|
129
220
|
const EVENT_ALLOWED = /^(?:gate|gated|review|reviewed|repair|repaired|rework|merge|merged|pr|land|landed|stage|round|supervisor|child|plan|planned|decompose|decomposed|shard|stall|harvest|decision|run|pipeline|progress|human|start|started|finish|finished|done|implement|implemented|commit|test|typecheck)(?:-(?:started|finished|round|opened|closed|failed|passed|blocked|done|entry|node|outcome|delivery|decision|stop|merged|ready|requested|resolved|result|fix|must-fix|verdict|skipped|origin|cleared))*$/;
|
|
130
|
-
const CODE_FIELDS = new Set(['stage', 'outcome', 'verdict', 'status', 'kind', 'phase', 'role', 'result'
|
|
221
|
+
const CODE_FIELDS = new Set(['stage', 'outcome', 'verdict', 'status', 'kind', 'phase', 'role', 'result', 'containerReason',
|
|
222
|
+
'podPhase', 'currentLogReadStatus', 'previousLogReadStatus', 'previousLogStderrCaptureStatus', 'stderrCaptureStatus']);
|
|
131
223
|
const CODE_VALUE = /^[a-z0-9_.:-]{1,40}$/i;
|
|
224
|
+
const IDENTITY_FIELDS = new Set(['job', 'jobUid', 'childRunId', 'host', 'context', 'namespace', 'podName', 'podUid']);
|
|
225
|
+
const SAFE_ID_VALUE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
226
|
+
const SAFE_ISO_TIMESTAMP = /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?Z$/;
|
|
132
227
|
|
|
133
228
|
function secretValues(root: Record<string, unknown>): string[] {
|
|
134
229
|
const secrets: string[] = [];
|
|
@@ -163,7 +258,8 @@ export function ledgerLineToLogEvent(line: string, runId: string): {
|
|
|
163
258
|
const sources = [entry, details].filter((source): source is Record<string, unknown> => source !== undefined);
|
|
164
259
|
const knownSecrets = secretValues(entry);
|
|
165
260
|
const containsCredential = (value: string) => SECRET_VALUE.test(value) || knownSecrets.some((secret) => value.includes(secret));
|
|
166
|
-
if (containsCredential(entry.event) || (!EVENT_ALLOWED.test(entry.event) && entry.event !== '
|
|
261
|
+
if (containsCredential(entry.event) || (!EVENT_ALLOWED.test(entry.event) && entry.event !== 'pod-failure-capture'
|
|
262
|
+
&& entry.event !== 'ask-auto-target-candidates' && entry.event !== 'ask-auto-reauthor')) return undefined;
|
|
167
263
|
|
|
168
264
|
const data: Record<string, unknown> = { runId };
|
|
169
265
|
let fields = 0;
|
|
@@ -176,7 +272,10 @@ export function ledgerLineToLogEvent(line: string, runId: string): {
|
|
|
176
272
|
if (!SAFE_FIELD.test(outputName) || SECRET_FIELD.test(outputName) || Object.hasOwn(data, outputName)) continue;
|
|
177
273
|
if (typeof value === 'string') {
|
|
178
274
|
// Free text (reasons, messages, patches) never leaves the pod ledger; only short code values in known keys.
|
|
179
|
-
|
|
275
|
+
const acceptedCode = CODE_FIELDS.has(name) && CODE_VALUE.test(value);
|
|
276
|
+
const acceptedIdentity = IDENTITY_FIELDS.has(name) && SAFE_ID_VALUE.test(value);
|
|
277
|
+
const acceptedTimestamp = name === 'containerFinishedAt' && SAFE_ISO_TIMESTAMP.test(value);
|
|
278
|
+
if ((!acceptedCode && !acceptedIdentity && !acceptedTimestamp) || containsCredential(value)) continue;
|
|
180
279
|
data[name] = value;
|
|
181
280
|
} else if (typeof value === 'number' && Number.isFinite(value) || typeof value === 'boolean' || value === null) {
|
|
182
281
|
data[name] = value;
|