elanous 0.2.42 → 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/{X1ucLw10Cds_h614NoEnh → Om5xS9jpjSXJCeTNGYEi4}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{7a98bc80.fa935989e829f9c2.js → 0966f8a1.745fcd44f64a87ea.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{73d2eb0e.4966ad55293c801a.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/{3507.97e1977bc4d5fb0a.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/1961.a81b12872c3e93a9.js +23 -0
- package/apps/pwa/out/_next/static/chunks/{53c73f84.373b6160adfa89a4.js → 1970cf59.2d4d8ce5d6c81853.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9211-330b6736a63d4cb3.js → 2073-ba274e00e4f9efb4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{7411.9b4b8b747dc7b802.js → 2144.25b292396712196d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/2268-53861f339e0b65a2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2312.0c8b61e22d3136d7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6632.0eac1c554f8f2ef3.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/{1262.e804feb8fd1acb8c.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/{2456.b6de0e1c05f28843.js → 3095.dc44586a5f83b86d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3207.a756c95e9ec8c3c8.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/3557ac4a.c8931684475018ad.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8505.fd803c6c33b54cc3.js → 360.ae9f9f4c33c395e8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +286 -0
- package/apps/pwa/out/_next/static/chunks/{b450776b.3db34d8d965f82d3.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/{8138.6c10b2a356d52fca.js → 4199.ce86b281fd0a60b7.js} +1 -1
- 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/{2690.0521c738b7749931.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/{1945.7b54990d578c119b.js → 4894.fec2ca9e99caefa2.js} +1 -1
- 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/{9427.96aa912ddb5801e0.js → 5564.9e72532188f57586.js} +16 -16
- 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/{4043.6b91203436c9c86b.js → 5628.6ddb2d5ffba4ff4c.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/{1319.b9b815ae0f181e06.js → 5730.43d7ccc09988e646.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3482.a9ae9d2ad6a5bd97.js → 5789.2da35c258292e1e5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5824.da9527b15a3221e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5866.366966af47fdde5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1487.2f67b79444062da6.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/{3347.f846266b5e5f3ede.js → 6540.c7bef57ad8f90a87.js} +3 -3
- 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/{8262.ddc03e06b733f184.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/{4770.769c9cd9c7034eba.js → 7483.427a2fe2049e388d.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{1147-5196d19c222051b3.js → 7502-be74718178e13e56.js} +1 -1
- 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/{8673-bab689a55f7e13b9.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/868.6e953be05bcf6dca.js +41 -0
- 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/{9656-374232558fd528d0.js → 8861-cc1fa1c7b920fa8e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5440-4236de26c5ea5856.js → 8967-7dfebf710c9dec9d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1063.2fb8a9dc55c731f2.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/{4320.583cbab64db6be02.js → 923.2034d10ae91e9c20.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1574.878c18ecc97b1bd4.js → 943.39ae5e82f4f1893f.js} +1 -1
- 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/aa57532f.510551854ff239b1.js +1 -0
- 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-0f291d3c8fd55a3a.js → page-9ee28f7df07428ea.js} +1 -1
- 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-79a8b5fee4c20871.js +1 -0
- 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-ca2d09128c585ca4.js +1 -0
- 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/c7945435-b44d4dbe90ba0dcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3d0154af.5331fec737ffe8c3.js → cb0f8df8.09a4a6be97e3fc5f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{e8543907.5b040a5f22a0b0e5.js → d96660fb.cbc21a2a88539dbb.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{50061469.0326382241ef3b2d.js → ea514caa.05a24f78d9dffe5f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/fb7d20d5-6892502b6ee39ca6.js +1 -0
- 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/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 +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +23 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/catalog/external-commands.yaml +5 -3
- package/catalog/meta/catalogVersion.yaml +2 -1
- package/catalog/signing/catalog-signing-public.pem +3 -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/profiles/local.yaml +5 -0
- package/graphs/profiles/pod.yaml +4 -0
- 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/hooks/codex-notify.sh +32 -0
- package/scripts/install.sh +10 -38
- package/scripts/landing-heal/land-plan.ts +57 -0
- 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-method.ts +139 -0
- package/scripts/release-loop/gate-node.ts +180 -20
- package/scripts/release-loop/gate-traffic-mode.ts +151 -3
- package/scripts/release-loop/node-verdict.ts +38 -25
- package/scripts/release-loop/preflight.ts +362 -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/video-pipeline.ts +9 -1
- package/scripts/warm-pool-provider-config.ts +29 -6
- 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 +17 -12
- package/src/acp/event-router.ts +20 -1
- package/src/acp/server.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 +56 -21
- 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 +256 -18
- package/src/agent-mission/tool-install.ts +122 -11
- package/src/agents/general-purpose.md +1 -1
- package/src/auto-research/research-turn.ts +95 -10
- package/src/autopilot/pr-manager.ts +31 -3
- 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/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/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 +44 -6
- package/src/cli/pr-land-overlap-evidence.ts +13 -1
- package/src/cli/pr-land-pod-shadow-job.ts +143 -5
- package/src/cli/pr-land-pod-shadow.ts +9 -2
- package/src/cli/release-checklist-read-cli.ts +44 -16
- package/src/cli/release-cli.ts +23 -3
- package/src/cli/research-cli.ts +9 -0
- 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 +54 -9
- package/src/cli/tui-test-cli.ts +186 -0
- 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/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 +320 -30
- package/src/core-turn/types.ts +2 -0
- package/src/dashboard/chat/acp-chat.ts +10 -0
- package/src/dashboard/classic-sidetab-mission-job.ts +103 -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 +167 -5
- package/src/dashboard/index.ts +378 -13
- package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +8 -0
- package/src/dashboard/mission-cli-consumer.ts +20 -8
- package/src/dashboard/plugin-wizard-runtime.ts +50 -0
- package/src/dashboard/plugin-wizard-tool.ts +55 -0
- package/src/dashboard/sidetab-runtime.ts +1 -1
- package/src/dashboard/terminal-popup-runtime.ts +6 -3
- 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-run-api.ts +3 -1
- package/src/graph-runner/runner.ts +85 -17
- package/src/graph-wizard/mission-compose.ts +407 -12
- 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/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 +127 -10
- 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 +2 -1
- package/src/maturity/feature-maturity.ts +3 -3
- package/src/msg/msg-sse-server.ts +3 -3
- package/src/msg/msg-store.ts +177 -19
- package/src/native-tool-catalog.ts +36 -2
- 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 +130 -0
- package/src/pty-shell/pty-control-ipc.ts +4 -1
- package/src/registry/catalog-server.ts +232 -0
- package/src/registry/loader.ts +45 -1
- package/src/registry/types.ts +1 -2
- package/src/research/axis-fanout.ts +43 -28
- package/src/self-dev/ask-launch-flow.ts +72 -1
- 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.ts +58 -0
- package/src/self-dev/orchestrate.ts +1 -1
- 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 +30 -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 +358 -4
- package/src/self-implement/graph-overlay-yaml.ts +30 -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/off-diff-evidence.ts +249 -5
- package/src/self-implement/orchestrator.ts +240 -15
- package/src/self-implement/run-chart.ts +6 -3
- package/src/self-implement/run-ledger.ts +51 -1
- package/src/self-implement/runtime-overlay-run-steps.ts +95 -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 +4 -2
- 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 +37 -1
- package/src/session-runtime/retry-policy.ts +1 -1
- 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/visible-agent-mission.ts +98 -22
- package/src/skills/tools/agent.ts +23 -4
- package/src/skills/tools/omni-search.ts +123 -25
- package/src/task-agent/parent-host.ts +10 -0
- package/src/task-agent/repair-outcomes.ts +65 -0
- package/src/task-agent/task-hand.ts +20 -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-failure-reason.ts +92 -1
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +23 -11
- package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +35 -9
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +172 -6
- 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/tool-hints/gate.ts +1 -0
- package/src/tool-runtime/agent-runtime.ts +1 -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/graph-mcp-runtimes.ts +240 -0
- package/src/tool-runtime/index.ts +6 -0
- package/src/tool-runtime/types.ts +3 -0
- package/src/tui/entry.ts +24 -1
- package/src/tui/sidetab/attach.ts +140 -11
- package/src/tui/sidetab/herdr-portal.ts +225 -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-linear-device.ts +31 -0
- 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 +75 -23
- package/src/ux-sim/mock-scenario-catalog.ts +120 -2
- package/src/ux-sim/onboarding-first-run-device.ts +31 -21
- package/src/ux-sim/scenario.ts +70 -26
- 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/web-search/exa.ts +77 -0
- 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/0244e5b5.6fc7670f8223d82d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1121.13ba7a8aff19df81.js +0 -36
- package/apps/pwa/out/_next/static/chunks/1345-31427b833438f521.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1455-530ca16c7e71baff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1586.fafc33a9a5835cb7.js +0 -32
- package/apps/pwa/out/_next/static/chunks/1744.855fd60ae4c4a8c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/193.21a47a3e07ef6860.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2004.e839fda7ea5a738a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2044-dd681a5c08779ff8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2101.2248decb38829b03.js +0 -286
- package/apps/pwa/out/_next/static/chunks/2160.a097e7b138ae1c55.js +0 -23
- package/apps/pwa/out/_next/static/chunks/2300.41ea70ac1bef1446.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2357-07b5eeb5fb12628d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2364.28652020695a6db3.js +0 -34
- package/apps/pwa/out/_next/static/chunks/2526.c3e50ac1fec064bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2549-cda50b716ff4250c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2550-5f1e88f615568045.js +0 -1
- package/apps/pwa/out/_next/static/chunks/261-319078c954e40d66.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2974.595d1e29d040cb6a.js +0 -64
- package/apps/pwa/out/_next/static/chunks/3285.89ee2f298682f5e5.js +0 -93
- package/apps/pwa/out/_next/static/chunks/3447.06edc7b092021417.js +0 -41
- package/apps/pwa/out/_next/static/chunks/3510-9ca392698bfe4391.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3541.772e5ce425aaa611.js +0 -24
- package/apps/pwa/out/_next/static/chunks/3741.9cf76acaa2ee5298.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3837.a210d7d0db8d8abd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3898-955c896f394217a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3947-ef57acea76eaa8d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4037-3b82ebc7d78afdc7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/405.9022d4a478202b67.js +0 -77
- package/apps/pwa/out/_next/static/chunks/417-fb2cc9a9910e5968.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4276.336d76d858fcdf1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4302.6ced9aa4535de947.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4768-8eac183fd291ca53.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4895.65605ec3e6504e89.js +0 -74
- package/apps/pwa/out/_next/static/chunks/5112.4b9f300124fab7b3.js +0 -149
- package/apps/pwa/out/_next/static/chunks/5335.375ee922bcd5bc83.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5342.023a2e729689b320.js +0 -27
- package/apps/pwa/out/_next/static/chunks/5431-72a1dbde59400691.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5486-b318c165f645d8ba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5506-c7d2ec25c62a7c94.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5570-c66ecbea26b4e3b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5696.ffca5aa259d8451e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5793-8c584aea2aa87560.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5848-6de6b8c173351a90.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5885.0a3e52c8faccec98.js +0 -287
- package/apps/pwa/out/_next/static/chunks/5999.94e3c83040200f31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5a7901d6-2d8d9b5587cf9042.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6131.348b7d6bdcd267ce.js +0 -226
- package/apps/pwa/out/_next/static/chunks/6164.86133a0172611184.js +0 -90
- package/apps/pwa/out/_next/static/chunks/6377.bc7df239edbff244.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6515.e07e8b2b8a707a87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6522-c005514f87d18982.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6642.648adb1767f39ecf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6848.138805a09d001d09.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7049-c09e2b7a253a24f3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7072.1e00447d9fa39972.js +0 -104
- package/apps/pwa/out/_next/static/chunks/7106.64201c539c5e220c.js +0 -94
- package/apps/pwa/out/_next/static/chunks/7151-1f742b455986530e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7199.18d6b25e001154ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7279-c199ea83f34338fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/728b938d.ffaa7ad583d60e58.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7309.171c3de54e0322f1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/733.7a1ab3342e03306f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7504.d5cf1e7cd89b1b08.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7573-0fd4af62d65d4598.js +0 -1
- package/apps/pwa/out/_next/static/chunks/759.6f8267df4689c401.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7825-668b046f72f14483.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7852-1538768b6eb19388.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7868.cff810430bb63c91.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8084-dfcc796874ab4e07.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8266.6bf9b131b2584678.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8403.7b81d5e64074a725.js +0 -8
- package/apps/pwa/out/_next/static/chunks/8470.1998cbd0866a7eac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8546-6f03f8ea34dd61d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8687-246fda8433d3477c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/898-280022fb082936bc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9098-50eefc1844212e3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9249.976f1e69a9d80754.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9255-cf88fceda5666645.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9306-e523ba58bb8adc42.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9324.a9866d717ba62cb6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9325.a8510e8aa87c8143.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9353-12bfff0c130104cf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9415.69e4a21c60c7d2db.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9479-154a697d4b6e4e98.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9540-65aa6ccc31b3fd78.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9633.ce5bddc56784da72.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9832.f4a98c878ecf2c0a.js +0 -62
- package/apps/pwa/out/_next/static/chunks/9865.f094440645f02d98.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9a852a62-6192a6ea9346ced3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-e772b4710df5d936.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-4361368e6a76b967.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-802f349fdd65248d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-7f35513988a2a495.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-798121656540e33e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-20a089490affe98c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-e5e4ec786d70e604.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-d12fe5d0801430e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-d8cf21022fecc026.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-21ce565c9c57ee97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-b56563025f619c9b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-52f14dd133da8348.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-c0ed7fdcdba76633.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-af8c3020cb520f15.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-72eda67af9f5e35c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-e772b4710df5d936.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-67a6620d31f0a46f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-f059363aa0880ec2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-f9f917d6a57f69fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-d3ae55eee2f0826c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-0e3d7b9421b79dac.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-ba738f7e233eb211.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-33438b98c74fd599.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-0b34d5fd990d793a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-3fced192be5279c1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-04cb3cf182a7c1ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6ccbd2ab23a21542.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-aa0518c48a5f4e56.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4b32226d341ad7d7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3224fd8f6383b61f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-efbc97459f2914e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-2fe487d88cd5d97c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-48861dd1a858bab7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-197d5d4d21d228ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a763ba89fbdd9c27.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7edb253510b1c136.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0c875702c61965ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-e772b4710df5d936.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-e425c951151095f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-9c90e0aec4e27f77.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-733e09a02e727d42.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-4f899e14c34d77a1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-bf067887b3307423.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-7af10868ff87d04e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-efe5304057aa11c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-76bcd29aaa8a26c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-4cfd88e2273ce50f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-0a1ddb47efba0a32.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2a176c707152c892.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-efe03031b8797fbf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-d0d2d673bfd8a8a9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-4c9fceb2baa09cb7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-b0ab8d8fc9a97556.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-7e2cc62a2e5cec96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-22324935f753ec5e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-9dc1bfa25334998a.js +0 -1
- package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
- /package/apps/pwa/out/_next/static/{X1ucLw10Cds_h614NoEnh → Om5xS9jpjSXJCeTNGYEi4}/_ssgManifest.js +0 -0
|
@@ -2,6 +2,7 @@ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { tmpdir } from 'node:os';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { spawnElanous } from '../instance/spawn-elanous.js';
|
|
5
|
+
import type { AgentCliPreparation } from '../agent-mission/tool-install.js';
|
|
5
6
|
|
|
6
7
|
export interface ClassicMissionCliResult {
|
|
7
8
|
ok: boolean;
|
|
@@ -58,6 +59,7 @@ export interface MissionCliConsumerDeps {
|
|
|
58
59
|
runCli?: typeof runCli;
|
|
59
60
|
delay?: (ms: number) => Promise<void>;
|
|
60
61
|
now?: () => number;
|
|
62
|
+
prepareAgentCli?: (agent: 'codex' | 'claude') => Promise<AgentCliPreparation>;
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
export interface StartedClassicMissionCliJob {
|
|
@@ -92,11 +94,20 @@ export async function cancelClassicMissionCli(interactionId: string, executeCli:
|
|
|
92
94
|
export async function startClassicMissionCli(input: {
|
|
93
95
|
agent: 'codex' | 'claude';
|
|
94
96
|
prompt: string;
|
|
97
|
+
linearIssueId?: string;
|
|
95
98
|
onInteractionId?: (interactionId: string) => void;
|
|
96
99
|
}, deps: MissionCliConsumerDeps = {}): Promise<StartClassicMissionCliResult> {
|
|
97
100
|
const executeCli = deps.runCli ?? runCli;
|
|
98
101
|
const wait = deps.delay ?? delay;
|
|
99
102
|
const now = deps.now ?? Date.now;
|
|
103
|
+
if (deps.prepareAgentCli) {
|
|
104
|
+
try {
|
|
105
|
+
const prepared = await deps.prepareAgentCli(input.agent);
|
|
106
|
+
if (!prepared.ready) return { ok: false, status: 'failed', path: '', error: prepared.message };
|
|
107
|
+
} catch {
|
|
108
|
+
return { ok: false, status: 'failed', path: '', error: `${input.agent}: 설치·로그인 상태를 확인하지 못했습니다` };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
100
111
|
const tempRoot = mkdtempSync(join(tmpdir(), 'elanous-classic-mission-'));
|
|
101
112
|
const promptPath = join(tempRoot, 'prompt.txt');
|
|
102
113
|
const outputPath = join(tempRoot, 'result.md');
|
|
@@ -105,7 +116,8 @@ export async function startClassicMissionCli(input: {
|
|
|
105
116
|
try {
|
|
106
117
|
writeFileSync(promptPath, input.prompt, { encoding: 'utf8', mode: 0o600 });
|
|
107
118
|
const launched = parseJson<{ missionId: string; status: 'running' }>(await executeCli([
|
|
108
|
-
'mission', 'run', '--agent', input.agent, '--prompt-file', promptPath, '--out', outputPath,
|
|
119
|
+
'mission', 'run', '--agent', input.agent, '--prompt-file', promptPath, '--out', outputPath,
|
|
120
|
+
...(input.linearIssueId ? ['--linear-issue-id', input.linearIssueId] : []), '--json',
|
|
109
121
|
]));
|
|
110
122
|
if (!isClassicMissionId(launched.missionId) || launched.status !== 'running') throw new Error('Mission CLI returned an invalid interaction ID');
|
|
111
123
|
interactionId = launched.missionId;
|
|
@@ -113,17 +125,17 @@ export async function startClassicMissionCli(input: {
|
|
|
113
125
|
const completion = (async (): Promise<ClassicMissionCliResult> => {
|
|
114
126
|
try {
|
|
115
127
|
while (now() - startedAt < MAX_WAIT_MS) {
|
|
116
|
-
const
|
|
117
|
-
if (
|
|
128
|
+
const missionStatus: MissionStatus = parseJson<MissionStatus>(await executeCli(['mission', 'status', interactionId!, '--json']));
|
|
129
|
+
if (missionStatus.missionId !== interactionId) throw new Error('Mission status did not match its interaction ID');
|
|
118
130
|
// `eln mission status --json` exposes completed records as `done`.
|
|
119
131
|
// Keep `completed` accepted for compatible bridges and existing callers.
|
|
120
|
-
if (
|
|
121
|
-
if (typeof
|
|
122
|
-
return { ok: true, status: 'completed', interactionId, path: outputPath, content:
|
|
132
|
+
if (missionStatus.status === 'done' || missionStatus.status === 'completed') {
|
|
133
|
+
if (typeof missionStatus.result !== 'string' || !missionStatus.result.trim()) throw new Error('Mission completed without a final answer');
|
|
134
|
+
return { ok: true, status: 'completed', interactionId, path: outputPath, content: missionStatus.result };
|
|
123
135
|
}
|
|
124
|
-
if (
|
|
136
|
+
if (missionStatus.status !== 'running') return {
|
|
125
137
|
ok: false,
|
|
126
|
-
status:
|
|
138
|
+
status: missionStatus.status === 'cancelled' ? 'cancelled' : 'failed',
|
|
127
139
|
interactionId,
|
|
128
140
|
path: outputPath,
|
|
129
141
|
error: 'Mission did not complete successfully',
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { debug } from '../debug/log.js';
|
|
2
|
+
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
3
|
+
import { createTaskPluginWizardHostDeps, type TaskPluginWizardHostResult } from '../cli/task-plugin-wizard-host.js';
|
|
4
|
+
import { defaultTaskLauncher } from '../cli/tasks-cli.js';
|
|
5
|
+
import { handTask, type HandTaskOptions } from '../task-agent/task-hand.js';
|
|
6
|
+
import { TASK_CARD_PREFIX } from '../task-agent/task-card-prefix.js';
|
|
7
|
+
import type { PluginMaker, PluginWizardDeps } from '../graph-wizard/mission-compose.js';
|
|
8
|
+
import { createTuiPluginWizardTool, type TuiPluginWizardTool } from './plugin-wizard-tool.js';
|
|
9
|
+
import type { TuiPluginWizardRequest } from './plugin-wizard-tool.js';
|
|
10
|
+
|
|
11
|
+
export interface DashboardPluginWizardRuntimePorts {
|
|
12
|
+
runMissionPair: (request: {
|
|
13
|
+
runId: string;
|
|
14
|
+
prompt: string;
|
|
15
|
+
context?: TuiPluginWizardRequest['context'];
|
|
16
|
+
}) => Promise<Partial<Record<PluginMaker, TaskPluginWizardHostResult>>>;
|
|
17
|
+
getWorkspace: () => string;
|
|
18
|
+
taskHand?: (options: HandTaskOptions) => Promise<unknown>;
|
|
19
|
+
launcher?: HandTaskOptions['launcher'];
|
|
20
|
+
onEvent?: PluginWizardDeps['onEvent'];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Connect the TUI entry tool to handTask and the existing plugin composer without blocking the ACP turn. */
|
|
24
|
+
export function createDashboardPluginWizardRuntime(ports: DashboardPluginWizardRuntimePorts): TuiPluginWizardTool {
|
|
25
|
+
return createTuiPluginWizardTool(async (request) => {
|
|
26
|
+
const pluginWizardDeps = createTaskPluginWizardHostDeps({
|
|
27
|
+
runMissionPair: ({ prompt }) => ports.runMissionPair({ runId: request.runId, prompt, ...(request.context ? { context: request.context } : {}) }),
|
|
28
|
+
onEvent: ports.onEvent ?? ((event) => {
|
|
29
|
+
if (event.step !== 'validate' || !event.detail || typeof event.detail !== 'object') return;
|
|
30
|
+
const winner = (event.detail as { winner?: unknown }).winner;
|
|
31
|
+
if (winner) debug.log('wizard.validate', 'winner-adopted', { runId: event.wizardId, ts: event.ts, winner });
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
const runHandTask = ports.taskHand ?? handTask;
|
|
35
|
+
await runHandTask({
|
|
36
|
+
id: `${TASK_CARD_PREFIX}plugin-${request.runId.replaceAll('-', '').slice(0, 20)}`,
|
|
37
|
+
text: request.mission,
|
|
38
|
+
seat: 'TC',
|
|
39
|
+
live: true,
|
|
40
|
+
launcher: ports.launcher ?? defaultTaskLauncher,
|
|
41
|
+
pluginWizard: {
|
|
42
|
+
missing: request.missing,
|
|
43
|
+
root: effectiveInstanceRoot(),
|
|
44
|
+
workspace: ports.getWorkspace(),
|
|
45
|
+
wizardId: request.runId,
|
|
46
|
+
},
|
|
47
|
+
pluginWizardDeps,
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { debug } from '../debug/log.js';
|
|
3
|
+
import type { LLMToolSpec } from '../llm.js';
|
|
4
|
+
import type { ClassicSidetabMissionDispatchContext } from './classic-sidetab-mission.js';
|
|
5
|
+
|
|
6
|
+
export const TUI_PLUGIN_WIZARD_TOOL_NAME = 'StartPluginWizard';
|
|
7
|
+
|
|
8
|
+
export interface TuiPluginWizardRequest {
|
|
9
|
+
runId: string;
|
|
10
|
+
mission: string;
|
|
11
|
+
missing: string;
|
|
12
|
+
context?: ClassicSidetabMissionDispatchContext;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface TuiPluginWizardTool {
|
|
16
|
+
getTools(existing: readonly LLMToolSpec[]): LLMToolSpec[];
|
|
17
|
+
dispatchTool(name: string, args: unknown, context?: ClassicSidetabMissionDispatchContext): Promise<unknown> | undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Add a non-blocking TUI entry point; the injected host runs the shared task/plugin-wizard path. */
|
|
21
|
+
export function createTuiPluginWizardTool(start: (request: TuiPluginWizardRequest) => Promise<void>, createId: () => string = randomUUID): TuiPluginWizardTool {
|
|
22
|
+
const spec: LLMToolSpec = {
|
|
23
|
+
name: TUI_PLUGIN_WIZARD_TOOL_NAME,
|
|
24
|
+
description: 'When a needed capability is missing, start the plugin wizard in this TUI session. It asks a short question, searches trusted plugins, and if needed launches the visible Codex and Claude side-tab pair. Returns a run ID immediately; check the task notification for completion.',
|
|
25
|
+
parameters: {
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: {
|
|
28
|
+
mission: { type: 'string', minLength: 1, description: 'The active task to complete after installing or creating the tool.' },
|
|
29
|
+
missing: { type: 'string', minLength: 1, description: 'The missing tool or capability.' },
|
|
30
|
+
},
|
|
31
|
+
required: ['mission', 'missing'],
|
|
32
|
+
additionalProperties: false,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
getTools: (existing) => [...existing, spec],
|
|
38
|
+
dispatchTool(name, args, context) {
|
|
39
|
+
if (name !== TUI_PLUGIN_WIZARD_TOOL_NAME) return undefined;
|
|
40
|
+
const output = (status: 'running' | 'error', body: string, id: string | null = null) => ({ status, body, artifacts: [], id });
|
|
41
|
+
if (!args || typeof args !== 'object' || Array.isArray(args)) return Promise.resolve(output('error', 'arguments must be an object'));
|
|
42
|
+
const input = args as Record<string, unknown>;
|
|
43
|
+
if (Object.keys(input).some((key) => key !== 'mission' && key !== 'missing')) return Promise.resolve(output('error', 'arguments contain unsupported fields'));
|
|
44
|
+
const mission = typeof input.mission === 'string' ? input.mission.trim() : '';
|
|
45
|
+
const missing = typeof input.missing === 'string' ? input.missing.trim() : '';
|
|
46
|
+
if (!mission || !missing) return Promise.resolve(output('error', 'mission and missing capability are required'));
|
|
47
|
+
const runId = createId();
|
|
48
|
+
void Promise.resolve().then(() => start({ runId, mission, missing, ...(context ? { context } : {}) })).catch((error) => {
|
|
49
|
+
try { debug.log('plugin-wizard.tool', 'start-failed', { runId, reason: error instanceof Error ? error.message : String(error) }, { level: 'error' }); }
|
|
50
|
+
catch { /* failure reporting must not re-enter the tool boundary */ }
|
|
51
|
+
});
|
|
52
|
+
return Promise.resolve(output('running', `Plugin wizard started in the background (run ${runId}).`, runId));
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -7,7 +7,7 @@ export interface DashboardLocalAgentSession {
|
|
|
7
7
|
id: string;
|
|
8
8
|
title: string;
|
|
9
9
|
kind: 'shell' | 'coding-agent';
|
|
10
|
-
agentBrand?: 'claude-code' | 'codex' | 'gemini';
|
|
10
|
+
agentBrand?: 'claude-code' | 'codex' | 'gemini' | 'grok';
|
|
11
11
|
state: 'foreground' | 'background' | 'exited';
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { TerminalSession } from '../terminal/session-registry.js';
|
|
2
2
|
|
|
3
|
-
export type DashboardTerminalPopupAgentBrand = 'claude-code' | 'codex' | 'gemini';
|
|
3
|
+
export type DashboardTerminalPopupAgentBrand = 'claude-code' | 'codex' | 'gemini' | 'grok';
|
|
4
4
|
|
|
5
5
|
export type DashboardTerminalPopupRequest =
|
|
6
6
|
| { kind: 'shell'; cwd: string; command?: string; env?: Record<string, string> }
|
|
7
|
-
| { kind: 'coding-agent'; brand: DashboardTerminalPopupAgentBrand; cwd: string; extraArgs?: readonly string[] };
|
|
7
|
+
| { kind: 'coding-agent'; brand: DashboardTerminalPopupAgentBrand; cwd: string; extraArgs?: readonly string[]; env?: Record<string, string>; id?: string };
|
|
8
8
|
|
|
9
9
|
export interface DashboardTerminalPopupRuntimeDeps {
|
|
10
10
|
onMissingCwd: () => void;
|
|
@@ -15,6 +15,7 @@ export interface DashboardTerminalPopupBuilder {
|
|
|
15
15
|
cwd(cwd: string): DashboardTerminalPopupBuilder;
|
|
16
16
|
command(command: string): DashboardTerminalPopupBuilder;
|
|
17
17
|
env(env: Record<string, string>): DashboardTerminalPopupBuilder;
|
|
18
|
+
id(id: string): DashboardTerminalPopupBuilder;
|
|
18
19
|
args(extraArgs: readonly string[]): DashboardTerminalPopupBuilder;
|
|
19
20
|
open(): TerminalSession | null;
|
|
20
21
|
}
|
|
@@ -34,11 +35,13 @@ export function createDashboardTerminalPopupRuntime(
|
|
|
34
35
|
let cwd: string | null = null;
|
|
35
36
|
let command: string | undefined;
|
|
36
37
|
let env: Record<string, string> | undefined;
|
|
38
|
+
let id: string | undefined;
|
|
37
39
|
let args: readonly string[] | undefined;
|
|
38
40
|
return {
|
|
39
41
|
cwd(next) { cwd = next; return this; },
|
|
40
42
|
command(next) { command = next; return this; },
|
|
41
43
|
env(next) { env = next; return this; },
|
|
44
|
+
id(next) { id = next; return this; },
|
|
42
45
|
args(next) { args = next; return this; },
|
|
43
46
|
open() {
|
|
44
47
|
if (cwd === null) {
|
|
@@ -47,7 +50,7 @@ export function createDashboardTerminalPopupRuntime(
|
|
|
47
50
|
}
|
|
48
51
|
const req: DashboardTerminalPopupRequest = kind === 'shell'
|
|
49
52
|
? { kind: 'shell', cwd, command, env }
|
|
50
|
-
: { kind: 'coding-agent', brand: kind, cwd, extraArgs: args };
|
|
53
|
+
: { kind: 'coding-agent', brand: kind, cwd, ...(args ? { extraArgs: args } : {}), ...(env ? { env } : {}), ...(id ? { id } : {}) };
|
|
51
54
|
return deps.openInteractiveTerminalPopup(req);
|
|
52
55
|
},
|
|
53
56
|
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { DecisionEntry } from './decision-ledger.js';
|
|
2
|
+
import type { Checklist, ChecklistHistory, ChecklistItem } from '../release-loop/checklist.js';
|
|
3
|
+
|
|
4
|
+
const LINEAR_ISSUE = /\bELA-[A-Z0-9]+\b/gi;
|
|
5
|
+
const PULL_URL = /https:\/\/github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\/pull\/\d+/g;
|
|
6
|
+
|
|
7
|
+
export interface LinearProgressSummary {
|
|
8
|
+
issue: string;
|
|
9
|
+
day: string;
|
|
10
|
+
body: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function issueRefs(text: string): string[] {
|
|
14
|
+
return [...new Set(text.match(LINEAR_ISSUE) ?? [])].map(value => value.toUpperCase());
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function eventIssues(item: ChecklistItem): string[] {
|
|
18
|
+
return issueRefs(`${item.title}\n${item.evidence ?? ''}\n${item.refs?.join('\n') ?? ''}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function short(value: unknown): string {
|
|
22
|
+
return typeof value === 'string' ? value.replace(/[\r\n]+/g, ' ').trim().slice(0, 80) : '미상';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Build non-sensitive daily summaries from local ledgers; this function performs no network or file writes. */
|
|
26
|
+
export function buildLinearProgressSummaries(input: {
|
|
27
|
+
checklist: Checklist;
|
|
28
|
+
history: readonly ChecklistHistory[];
|
|
29
|
+
decisions: readonly DecisionEntry[];
|
|
30
|
+
since: string;
|
|
31
|
+
now?: Date;
|
|
32
|
+
}): LinearProgressSummary[] {
|
|
33
|
+
const since = Date.parse(input.since);
|
|
34
|
+
if (!Number.isFinite(since)) throw new Error('since must be a valid timestamp');
|
|
35
|
+
const now = input.now ?? new Date();
|
|
36
|
+
const day = now.toISOString().slice(0, 10);
|
|
37
|
+
const cells = new Map(input.checklist.items.map(item => [item.id, item]));
|
|
38
|
+
const grouped = new Map<string, string[]>();
|
|
39
|
+
const add = (issue: string, line: string) => {
|
|
40
|
+
const lines = grouped.get(issue) ?? [];
|
|
41
|
+
if (!lines.includes(line)) lines.push(line);
|
|
42
|
+
grouped.set(issue, lines);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
for (const event of input.history) {
|
|
46
|
+
if (Date.parse(event.at) < since) continue;
|
|
47
|
+
const item = cells.get(event.id);
|
|
48
|
+
if (!item || event.field !== 'status') continue;
|
|
49
|
+
for (const issue of eventIssues(item)) add(issue, `칸 ${item.id}: ${short(event.from)} → ${short(event.to)}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (const decision of input.decisions) {
|
|
53
|
+
const changed = decision.history.filter(event => event.at && Date.parse(event.at) >= since);
|
|
54
|
+
if (!changed.length) continue;
|
|
55
|
+
for (const ref of decision.refs ?? []) for (const issue of issueRefs(ref)) {
|
|
56
|
+
const latest = changed.at(-1)!;
|
|
57
|
+
add(issue, `결정 ${decision.id}: ${latest.type === 'decided' ? `확정 ${short(latest.choice)}` : latest.type}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
for (const item of input.checklist.items) {
|
|
62
|
+
if (item.status === 'green' || item.status === 'done') continue;
|
|
63
|
+
for (const issue of eventIssues(item)) add(issue, `다음: ${item.id}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (const event of input.history) {
|
|
67
|
+
if (Date.parse(event.at) < since || !['evidence', 'evidence.add'].includes(event.field)) continue;
|
|
68
|
+
const item = cells.get(event.id);
|
|
69
|
+
if (!item) continue;
|
|
70
|
+
const pulls = String(event.to ?? '').match(PULL_URL) ?? [];
|
|
71
|
+
for (const issue of eventIssues(item)) for (const url of pulls) add(issue, `PR: ${url}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return [...grouped].sort(([a], [b]) => a.localeCompare(b)).map(([issue, lines]) => {
|
|
75
|
+
const body = [`진행 요약 · ${day}`, ...lines].join('\n');
|
|
76
|
+
return { issue, day, body };
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, statSync, unlinkSync, writeFileSync, writeSync, renameSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { commentLinearIssue } from '../connectors/linear.js';
|
|
4
|
+
import { debug } from '../debug/log.js';
|
|
5
|
+
import { getSecretAsync } from '../nexus/config/secrets/index.js';
|
|
6
|
+
import { releaseLedgerRoot } from '../instance/resolve.js';
|
|
7
|
+
import { DecisionLedger } from './decision-ledger.js';
|
|
8
|
+
import { buildLinearProgressSummaries, type LinearProgressSummary } from './linear-progress-summary.js';
|
|
9
|
+
import { checklistHistory, listChecklist } from '../release-loop/checklist.js';
|
|
10
|
+
|
|
11
|
+
type SentState = Record<string, true>;
|
|
12
|
+
type IssueLookup = { issue?: { id?: string; team?: { key?: string }; comments?: { nodes?: Array<{ body?: string }> } } };
|
|
13
|
+
|
|
14
|
+
export interface LinearProgressSyncResult {
|
|
15
|
+
day: string;
|
|
16
|
+
planned: number;
|
|
17
|
+
posted: number;
|
|
18
|
+
skipped: number;
|
|
19
|
+
failed: number;
|
|
20
|
+
plan: Array<{ issue: string; body: string; action: 'post' | 'already-posted' | 'team-mismatch' }>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function readState(path: string): SentState {
|
|
24
|
+
if (!existsSync(path)) return {};
|
|
25
|
+
const value: unknown = JSON.parse(readFileSync(path, 'utf8'));
|
|
26
|
+
const invalid = !value || typeof value !== 'object' || Array.isArray(value)
|
|
27
|
+
|| Object.entries(value).some(([key, row]) => !/^\d{4}-\d{2}-\d{2}:ELA-[A-Z0-9]+$/.test(key)
|
|
28
|
+
|| (row !== true && (!row || typeof row !== 'object' || Array.isArray(row))));
|
|
29
|
+
if (invalid) {
|
|
30
|
+
throw new Error('invalid Linear progress sync state');
|
|
31
|
+
}
|
|
32
|
+
// Older entries stored write-only fingerprint/postedAt metadata. Normalize them to the marker that skip logic reads.
|
|
33
|
+
return Object.fromEntries(Object.keys(value).map(key => [key, true]));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function saveState(path: string, state: SentState): void {
|
|
37
|
+
const temp = `${path}.${process.pid}.tmp`;
|
|
38
|
+
try {
|
|
39
|
+
writeFileSync(temp, JSON.stringify(state), { mode: 0o600 });
|
|
40
|
+
renameSync(temp, path);
|
|
41
|
+
} finally { if (existsSync(temp)) unlinkSync(temp); }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function lookupIssue(apiKey: string, identifier: string, fetchFn: typeof fetch): Promise<IssueLookup['issue']> {
|
|
45
|
+
const response = await fetchFn('https://api.linear.app/graphql', {
|
|
46
|
+
method: 'POST', headers: { Authorization: apiKey, 'Content-Type': 'application/json' },
|
|
47
|
+
body: JSON.stringify({ query: 'query ProgressIssue($id: String!) { issue(id: $id) { id team { key } comments(first: 100) { nodes { body } } } }', variables: { id: identifier } }),
|
|
48
|
+
});
|
|
49
|
+
if (!response.ok) throw new Error(`Linear GraphQL HTTP ${response.status}`);
|
|
50
|
+
const body = await response.json() as { data?: IssueLookup; errors?: unknown[] };
|
|
51
|
+
if (body.errors?.length || !body.data) throw new Error('Linear GraphQL issue lookup failed');
|
|
52
|
+
return body.data.issue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function marker(summary: LinearProgressSummary): string { return `progress-sync:${summary.day}:${summary.issue}`; }
|
|
56
|
+
|
|
57
|
+
function summaries(version: string, now: Date): LinearProgressSummary[] {
|
|
58
|
+
const checklist = listChecklist(version);
|
|
59
|
+
const history = [...new Set(checklist.items.map(item => item.id))].flatMap(id => checklistHistory(id));
|
|
60
|
+
const since = `${now.toISOString().slice(0, 10)}T00:00:00.000Z`;
|
|
61
|
+
return buildLinearProgressSummaries({ checklist, history, decisions: new DecisionLedger().list({ status: 'all' }), since, now });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Plan is read-only by default. `live` sends at most one marked comment per issue per UTC day. */
|
|
65
|
+
export async function syncLinearProgress(options: {
|
|
66
|
+
version: string;
|
|
67
|
+
live?: boolean;
|
|
68
|
+
now?: Date;
|
|
69
|
+
fetch?: typeof fetch;
|
|
70
|
+
getSecret?: (name: string) => Promise<string | undefined>;
|
|
71
|
+
ledgerRoot?: string;
|
|
72
|
+
/** Injection seam for deterministic sync tests; normal callers use the local ledgers. */
|
|
73
|
+
buildSummaries?: (version: string, now: Date) => LinearProgressSummary[];
|
|
74
|
+
}): Promise<LinearProgressSyncResult> {
|
|
75
|
+
const now = options.now ?? new Date();
|
|
76
|
+
const plans = (options.buildSummaries ?? summaries)(options.version, now);
|
|
77
|
+
const result: LinearProgressSyncResult = { day: now.toISOString().slice(0, 10), planned: plans.length, posted: 0, skipped: 0, failed: 0,
|
|
78
|
+
plan: plans.map(summary => ({ issue: summary.issue, body: summary.body, action: 'post' })) };
|
|
79
|
+
if (!options.live) {
|
|
80
|
+
for (const item of result.plan) debug.log('linear.progress-sync', 'planned', { issue: item.issue, day: result.day });
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const apiKey = await (options.getSecret ?? getSecretAsync)('connector.linear.apiKey');
|
|
85
|
+
if (!apiKey) throw new Error('Linear credential missing');
|
|
86
|
+
const ledgerRoot = options.ledgerRoot ?? releaseLedgerRoot();
|
|
87
|
+
const directory = join(ledgerRoot, 'release');
|
|
88
|
+
mkdirSync(directory, { recursive: true });
|
|
89
|
+
const path = join(directory, 'linear-progress-sync.json');
|
|
90
|
+
const lockPath = `${path}.lock`;
|
|
91
|
+
let lock: number | undefined;
|
|
92
|
+
const deadline = Date.now() + 10_000;
|
|
93
|
+
for (;;) {
|
|
94
|
+
try { lock = openSync(lockPath, 'wx', 0o600); writeSync(lock, `${process.pid}`); break; }
|
|
95
|
+
catch (error) {
|
|
96
|
+
if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
|
|
97
|
+
try {
|
|
98
|
+
const pid = Number(readFileSync(lockPath, 'utf8'));
|
|
99
|
+
if (Number.isSafeInteger(pid) && pid > 0 && Date.now() - statSync(lockPath).mtimeMs > 30_000) {
|
|
100
|
+
try { process.kill(pid, 0); }
|
|
101
|
+
catch (probe) { if ((probe as NodeJS.ErrnoException).code === 'ESRCH') { unlinkSync(lockPath); continue; } }
|
|
102
|
+
}
|
|
103
|
+
} catch (probe) { if ((probe as NodeJS.ErrnoException).code === 'ENOENT') continue; }
|
|
104
|
+
if (Date.now() >= deadline) throw new Error('Linear progress sync lock timeout');
|
|
105
|
+
await Bun.sleep(25);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const state = readState(path);
|
|
110
|
+
const fetchFn = options.fetch ?? fetch;
|
|
111
|
+
for (const summary of plans) {
|
|
112
|
+
const key = `${summary.day}:${summary.issue}`;
|
|
113
|
+
if (state[key]) {
|
|
114
|
+
result.skipped++;
|
|
115
|
+
result.plan.find(item => item.issue === summary.issue)!.action = 'already-posted';
|
|
116
|
+
debug.log('linear.progress-sync', 'skipped', { issue: summary.issue, day: summary.day, reason: 'already-posted' });
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const issue = await lookupIssue(apiKey, summary.issue, fetchFn);
|
|
121
|
+
if (!issue?.id) throw new Error('Linear issue not found');
|
|
122
|
+
if (issue.team?.key !== 'DEMO') {
|
|
123
|
+
result.skipped++;
|
|
124
|
+
result.plan.find(item => item.issue === summary.issue)!.action = 'team-mismatch';
|
|
125
|
+
debug.log('linear.progress-sync', 'skipped', { issue: summary.issue, day: summary.day, reason: 'team-not-allowed' });
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if ((issue.comments?.nodes ?? []).some(comment => comment.body?.includes(marker(summary)))) {
|
|
129
|
+
state[key] = true;
|
|
130
|
+
saveState(path, state);
|
|
131
|
+
result.skipped++;
|
|
132
|
+
result.plan.find(item => item.issue === summary.issue)!.action = 'already-posted';
|
|
133
|
+
debug.log('linear.progress-sync', 'skipped', { issue: summary.issue, day: summary.day, reason: 'remote-marker-found' });
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const body = `${summary.body}\n\n_${marker(summary)}_`;
|
|
137
|
+
await commentLinearIssue({ apiKey, issueId: issue.id, body, fetch: fetchFn });
|
|
138
|
+
state[key] = true;
|
|
139
|
+
saveState(path, state);
|
|
140
|
+
result.posted++;
|
|
141
|
+
debug.log('linear.progress-sync', 'posted', { issue: summary.issue, day: summary.day });
|
|
142
|
+
} catch (error) {
|
|
143
|
+
result.failed++;
|
|
144
|
+
const reason = error instanceof Error ? (/^Linear GraphQL HTTP \d{3}$/.test(error.message) ? error.message : error.name) : 'unknown';
|
|
145
|
+
debug.log('linear.progress-sync', 'failed', { issue: summary.issue, day: summary.day, reason });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
} finally {
|
|
150
|
+
if (lock !== undefined) { closeSync(lock); unlinkSync(lockPath); }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -119,10 +119,42 @@ export function kstMinutes(now: Date = new Date()): number {
|
|
|
119
119
|
return ((h ?? 0) % 24) * 60 + (m ?? 0);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
export const OUTBOUND_QUIET_HOURS_ENV = 'ELANOUS_OUTBOUND_QUIET_HOURS';
|
|
123
|
+
const DEFAULT_QUIET_HOURS = '00:00-06:30';
|
|
124
|
+
type QuietHours = 'off' | { start: number; end: number; label: string };
|
|
125
|
+
|
|
126
|
+
/** `off` 또는 HH:MM-HH:MM 을 분 범위로 해석한다. 잘못된 설정은 기본값에 맡긴다. */
|
|
127
|
+
function parseQuietHours(value: unknown): QuietHours | null {
|
|
128
|
+
if (value === 'off') return 'off';
|
|
129
|
+
if (typeof value !== 'string') return null;
|
|
130
|
+
const match = /^(\d{2}):(\d{2})-(\d{2}):(\d{2})$/.exec(value.trim());
|
|
131
|
+
if (!match) return null;
|
|
132
|
+
const [, sh, sm, eh, em] = match;
|
|
133
|
+
const startHour = Number(sh), startMinute = Number(sm), endHour = Number(eh), endMinute = Number(em);
|
|
134
|
+
if (startHour > 23 || endHour > 23 || startMinute > 59 || endMinute > 59) return null;
|
|
135
|
+
const start = startHour * 60 + startMinute, end = endHour * 60 + endMinute;
|
|
136
|
+
if (start === end) return null;
|
|
137
|
+
return { start, end, label: `${sh}:${sm}-${eh}:${em}` };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** config.outbound.quietHours > ELANOUS_OUTBOUND_QUIET_HOURS > 기존 기본 창. */
|
|
141
|
+
function configuredQuietHours(): QuietHours {
|
|
142
|
+
try {
|
|
143
|
+
const configValue = parseQuietHours(getUserConfig().outbound?.quietHours);
|
|
144
|
+
if (configValue) return configValue;
|
|
145
|
+
} catch { /* use env/default */ }
|
|
146
|
+
const envValue = parseQuietHours(process.env[OUTBOUND_QUIET_HOURS_ENV]?.trim());
|
|
147
|
+
return envValue ?? parseQuietHours(DEFAULT_QUIET_HOURS)!;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** 야간 무음 창. 기본은 기존 00:00 ≤ t < 06:30 KST. */
|
|
123
151
|
export function inQuietHours(now: Date = new Date()): boolean {
|
|
124
|
-
const
|
|
125
|
-
|
|
152
|
+
const quiet = configuredQuietHours();
|
|
153
|
+
if (quiet === 'off') return false;
|
|
154
|
+
const minute = kstMinutes(now);
|
|
155
|
+
return quiet.start < quiet.end
|
|
156
|
+
? minute >= quiet.start && minute < quiet.end
|
|
157
|
+
: minute >= quiet.start || minute < quiet.end;
|
|
126
158
|
}
|
|
127
159
|
|
|
128
160
|
/** 최근 사용자 활동 우회 창(분) — 이 시간 내 genuine 사용자 인텐트가 있으면 무음이어도 즉시 발송. */
|
|
@@ -465,11 +497,14 @@ export function flushDeferred(path = DEFERRED_PATH, deps: FlushDeferredDeps = {}
|
|
|
465
497
|
|
|
466
498
|
/** TEST-PROD-LEAK — a test process may not reach a real bot or the ops daemon. `external` = a third-party bot API
|
|
467
499
|
* (refused unless curl is a test double replacing the real one); the local daemon is refused only when ops-routed. */
|
|
468
|
-
function assertTestSendFaked(what: string, external = true): void {
|
|
500
|
+
function assertTestSendFaked(what: string, external = true, injectedTransport?: unknown): void {
|
|
469
501
|
let roots: string[] = [];
|
|
470
502
|
try { roots = [getElanousConfigDir(), dirname(ACP_TOKEN_PATH), effectiveInstanceRoot(), conatusDataDir(), dirname(DEFERRED_PATH)]; }
|
|
471
503
|
catch { roots = [dirname(ACP_TOKEN_PATH), dirname(DEFERRED_PATH)]; }
|
|
472
|
-
|
|
504
|
+
const transportFaked = injectedTransport === undefined
|
|
505
|
+
? isTestDouble(childProcess.execFileSync, REAL_EXEC_FILE_SYNC)
|
|
506
|
+
: isTestDouble(injectedTransport);
|
|
507
|
+
assertNoRealSendFromTest(what, { transportFaked, routingRoots: roots, external });
|
|
473
508
|
}
|
|
474
509
|
|
|
475
510
|
/** 동기 curl(POST). body 는 stdin. 파싱 실패/에러 → null. `what` names the send for the test guard (never the URL — it carries the token). */
|
|
@@ -509,25 +544,28 @@ export function sendOutbound(text: string, kind = 'alert', origin?: (MissionOrig
|
|
|
509
544
|
: 'unknown');
|
|
510
545
|
ensureOutboundLogSink();
|
|
511
546
|
let bot = origin?.channel === 'discord' ? 'discord:configured' : 'unknown';
|
|
547
|
+
const quietConfig = configuredQuietHours();
|
|
548
|
+
const quietMode = quietConfig === 'off' ? 'off' : `window:${quietConfig.label}`;
|
|
512
549
|
const logOutcome = (event: 'sent' | 'deferred' | 'failed', path?: string): void => {
|
|
513
|
-
try { debug.log('outbound.send', event, { kind: safeObservationLabel(kind), source: safeObservationLabel(source), chars: text.length, bot, ...(path ? { path } : {}) }); } catch { /* fail-open */ }
|
|
550
|
+
try { debug.log('outbound.send', event, { kind: safeObservationLabel(kind), source: safeObservationLabel(source), chars: text.length, bot, quietMode, ...(path ? { path } : {}) }); } catch { /* fail-open */ }
|
|
514
551
|
};
|
|
515
552
|
// ★ 무음 우회(대표 2026-07-14) — 사용자가 최근(기본 30분) genuine 인텐트(타이핑/버튼탭)를 냈으면
|
|
516
553
|
// 깨어있으므로 야간 무음이어도 즉시 발송(사용자 발원 흐름의 결과물이 아침까지 묶이지 않게).
|
|
517
554
|
// 우회 시 flushDeferred 로 그간 보류분도 함께 전달(사용자가 지금 볼 수 있음).
|
|
518
|
-
|
|
555
|
+
const quietNow = inQuietHours();
|
|
556
|
+
if (quietNow && !userRecentlyActive()) {
|
|
519
557
|
const queued = deferOutbound(text, kind, origin);
|
|
520
558
|
if (queued) recordOutbound(text, kind); // 성공한 보류만 회상 대상
|
|
521
559
|
logOutcome(queued ? 'deferred' : 'failed', queued ? 'deferred' : 'queue-failed');
|
|
522
560
|
return queued; // 적재가 성공했을 때만 보류 수락
|
|
523
561
|
}
|
|
524
|
-
const bypass =
|
|
562
|
+
const bypass = quietNow;
|
|
525
563
|
if (bypass) console.error('[outbound] 야간 무음 우회 — 최근 사용자 활동(깨어있음) → 즉시 발송 + 보류분 flush');
|
|
526
564
|
try { flushDeferred(); } catch { /* fail-soft */ }
|
|
527
565
|
// ★ 발송 관측(대표 지시) — 발송 시각·mode·밀림(burst) 판정을 logs.db 에. burst=최근 2분 5건+
|
|
528
566
|
// (몰려 나가는 중 = 밀림 의심). `elanous logs --category outbound.send` 로 실시간/밀림 구분.
|
|
529
567
|
const { recentCount, burst } = recentSendBurst();
|
|
530
|
-
logSend(bypass ? 'quiet-bypass' : 'realtime', kind, { burst, recentCount, ...(burst ? { backlog: true } : {}) });
|
|
568
|
+
logSend(bypass ? 'quiet-bypass' : 'realtime', kind, { burst, recentCount, quietMode, ...(burst ? { backlog: true } : {}) });
|
|
531
569
|
// ★ origin 되돌림(무음 밖) — 발신 채널로 직접 발송. 성공 시 종료, 실패면 report 폴백.
|
|
532
570
|
if (origin && deliverToOrigin(origin, text, (label) => { bot = label; })) {
|
|
533
571
|
recordOutbound(text, kind);
|
|
@@ -706,8 +744,8 @@ export function sendTelegramDirect(
|
|
|
706
744
|
onBot?: (bot: string) => void,
|
|
707
745
|
): boolean {
|
|
708
746
|
const sendRaw = (token: string, chatId: string | number, body: string): boolean => {
|
|
709
|
-
// The transport is checked only after a route is eligible;
|
|
710
|
-
assertTestSendFaked('send a real Telegram message',
|
|
747
|
+
// The transport is checked only after a route is eligible; injected transports must themselves be test doubles.
|
|
748
|
+
assertTestSendFaked('send a real Telegram message', true, deps.sendRaw);
|
|
711
749
|
return (deps.sendRaw ?? sendTelegramRaw)(token, chatId, body);
|
|
712
750
|
};
|
|
713
751
|
let cfg: UserConfig | undefined;
|
|
@@ -36,16 +36,23 @@ function operationsBotToken(cfg: UserConfig): string | undefined {
|
|
|
36
36
|
const tradingTokens = new Set(channels.filter(c => c.roles.includes('report')).map(c => c.botToken));
|
|
37
37
|
// The report (trading) bot is never the operations bot — with or without a channels table (review must-fix · OUT1).
|
|
38
38
|
if (cfg.telegram.reportChannel?.botToken) tradingTokens.add(cfg.telegram.reportChannel.botToken);
|
|
39
|
+
// An explicit operational channel is authoritative even when env/tokenRef/legacy botToken
|
|
40
|
+
// resolves first; those older sources can point at a different (or trading) bot.
|
|
41
|
+
const operationalChannels = channels.filter(c => (c.name === 'ops' && c.roles.includes('system'))
|
|
42
|
+
|| (c.name === 'main' && c.roles.some(r => r === 'system' || r === 'qa' || r === 'default')));
|
|
43
|
+
if (operationalChannels.length > 0) {
|
|
44
|
+
const tokens = new Set(operationalChannels.filter(c => !tradingTokens.has(c.botToken)).map(c => c.botToken));
|
|
45
|
+
if (tokens.size !== 1) return undefined;
|
|
46
|
+
const explicitToken = tokens.values().next().value;
|
|
47
|
+
// The explicitly named operational channel outranks the generic tab's tokenRef;
|
|
48
|
+
// legacy/env conflicts without a trading identity remain ambiguous and fail closed.
|
|
49
|
+
if (main.source !== 'channels.main' && main.source !== 'tokenRef'
|
|
50
|
+
&& main.token && main.token !== explicitToken && !tradingTokens.has(main.token)) return undefined;
|
|
51
|
+
return explicitToken;
|
|
52
|
+
}
|
|
53
|
+
|
|
39
54
|
if (main.source !== 'channels.main') return main.token && !tradingTokens.has(main.token) ? main.token : undefined;
|
|
40
|
-
|
|
41
|
-
// Only a named operations channel (or the named main channel) with an
|
|
42
|
-
// operational role establishes identity; array order and role alone do not.
|
|
43
|
-
const tokens = new Set(channels
|
|
44
|
-
.filter(c => (c.name === 'ops' && c.roles.includes('system'))
|
|
45
|
-
|| (c.name === 'main' && c.roles.some(r => r === 'system' || r === 'qa' || r === 'default')))
|
|
46
|
-
.filter(c => !tradingTokens.has(c.botToken))
|
|
47
|
-
.map(c => c.botToken));
|
|
48
|
-
return tokens.size === 1 ? tokens.values().next().value : undefined;
|
|
55
|
+
return undefined;
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
function isAllowedBot(cfg: UserConfig, kind: string | undefined, token: string): boolean {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type AllowanceDecision =
|
|
2
|
+
| { readonly kind: 'run'; readonly requested: number; readonly granted: number; readonly clamped: boolean }
|
|
3
|
+
| { readonly kind: 'needs-human'; readonly requested: number; readonly remaining: 0 };
|
|
4
|
+
|
|
5
|
+
/** Resolve a child allowance against the parent's remaining steps before spawning the child. */
|
|
6
|
+
export function resolveChildAllowance(requested: number, parentRemaining: number): AllowanceDecision {
|
|
7
|
+
if (!Number.isSafeInteger(requested) || requested < 1) throw new Error('requested allowance must be a positive safe integer');
|
|
8
|
+
if (!(parentRemaining === Infinity || (Number.isSafeInteger(parentRemaining) && parentRemaining >= 0)))
|
|
9
|
+
throw new Error('parent remaining allowance must be a non-negative safe integer or Infinity');
|
|
10
|
+
if (parentRemaining === 0) return { kind: 'needs-human', requested, remaining: 0 };
|
|
11
|
+
const granted = Math.min(requested, parentRemaining);
|
|
12
|
+
return { kind: 'run', requested, granted, clamped: granted < requested };
|
|
13
|
+
}
|
|
@@ -29,6 +29,8 @@ export interface GraphRunApiDeps {
|
|
|
29
29
|
root?: string;
|
|
30
30
|
run?: typeof runGraph;
|
|
31
31
|
now?: () => number;
|
|
32
|
+
/** Allows a host-owned preview/demo request to stop an in-flight editor graph run. */
|
|
33
|
+
signal?: AbortSignal;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
/** 시작 전에 죽은 런(레시피 없음 등)은 원장 파일이 안 생긴다 — 그 이유를 여기 잠깐 들고 있다가 상태 조회에 돌려준다. */
|
|
@@ -187,7 +189,7 @@ export function handleGraphRunStart(rawId: string, deps: GraphRunApiDeps = {}):
|
|
|
187
189
|
return jsonResponse({ error: 'run-workspace-failed', reason: error instanceof Error ? error.message.slice(0, 200) : 'unknown' }, 500);
|
|
188
190
|
}
|
|
189
191
|
debug.log('graphs.run', 'started', { id, runId });
|
|
190
|
-
void (deps.run ?? runGraph)(join(work, 'graph.yaml'), { runId, input: { source: 'editor' }, deps: { root } })
|
|
192
|
+
void (deps.run ?? runGraph)(join(work, 'graph.yaml'), { runId, input: { source: 'editor' }, ...(deps.signal ? { signal: deps.signal } : {}), deps: { root } })
|
|
191
193
|
.then((state) => debug.log('graphs.run', 'finished', { id, runId, status: state.status, executed: state.executed }))
|
|
192
194
|
.catch((error: unknown) => {
|
|
193
195
|
const message = error instanceof Error ? error.message : String(error);
|