elanous 0.2.40 → 0.2.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → X1ucLw10Cds_h614NoEnh}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/0244e5b5.6fc7670f8223d82d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4769.9fd582071301f382.js → 1063.2fb8a9dc55c731f2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1121.13ba7a8aff19df81.js +36 -0
- package/apps/pwa/out/_next/static/chunks/1147-5196d19c222051b3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{470.51a72a2348306455.js → 1262.e804feb8fd1acb8c.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/1319.b9b815ae0f181e06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1345-31427b833438f521.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7219-15bdd9a80661af8e.js → 1455-530ca16c7e71baff.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1281.d81877e35b9068f4.js → 1487.2f67b79444062da6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1574.878c18ecc97b1bd4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1586.fafc33a9a5835cb7.js +32 -0
- package/apps/pwa/out/_next/static/chunks/1744.855fd60ae4c4a8c8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/193.21a47a3e07ef6860.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1945.7b54990d578c119b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2004.e839fda7ea5a738a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2044-dd681a5c08779ff8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2101.2248decb38829b03.js +286 -0
- package/apps/pwa/out/_next/static/chunks/2160.a097e7b138ae1c55.js +23 -0
- package/apps/pwa/out/_next/static/chunks/2300.41ea70ac1bef1446.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2357-07b5eeb5fb12628d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2364.28652020695a6db3.js +34 -0
- package/apps/pwa/out/_next/static/chunks/{1350.59f40e39e02d91b1.js → 2456.b6de0e1c05f28843.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2526.c3e50ac1fec064bd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2549-cda50b716ff4250c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2550-5f1e88f615568045.js +1 -0
- package/apps/pwa/out/_next/static/chunks/261-319078c954e40d66.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2690.0521c738b7749931.js +115 -0
- package/apps/pwa/out/_next/static/chunks/{5436.fdf6fa8ae3e9588d.js → 2974.595d1e29d040cb6a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5383.bdfa5d886e39a826.js → 3207.a756c95e9ec8c3c8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3285.89ee2f298682f5e5.js +93 -0
- package/apps/pwa/out/_next/static/chunks/{2177.df8547f9d7215c4e.js → 3347.f846266b5e5f3ede.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/3447.06edc7b092021417.js +41 -0
- package/apps/pwa/out/_next/static/chunks/{9184.45afbf44fec87574.js → 3482.a9ae9d2ad6a5bd97.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3507.97e1977bc4d5fb0a.js +2 -0
- package/apps/pwa/out/_next/static/chunks/3510-9ca392698bfe4391.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3541.772e5ce425aaa611.js +24 -0
- package/apps/pwa/out/_next/static/chunks/{8099.1cccf31c1baa7e1c.js → 3741.9cf76acaa2ee5298.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3837.a210d7d0db8d8abd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3898-955c896f394217a6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3947-ef57acea76eaa8d2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4864a2ca.1c1c280a7772c5e5.js → 3d0154af.5331fec737ffe8c3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4037-3b82ebc7d78afdc7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4043.6b91203436c9c86b.js +309 -0
- package/apps/pwa/out/_next/static/chunks/405.9022d4a478202b67.js +77 -0
- package/apps/pwa/out/_next/static/chunks/417-fb2cc9a9910e5968.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3330.7443183b7e6fdbdf.js → 4276.336d76d858fcdf1b.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4302.6ced9aa4535de947.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4320.583cbab64db6be02.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4768-8eac183fd291ca53.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4770.769c9cd9c7034eba.js +148 -0
- package/apps/pwa/out/_next/static/chunks/4895.65605ec3e6504e89.js +74 -0
- package/apps/pwa/out/_next/static/chunks/{3b355b3d.6f73c98bf6f9c749.js → 50061469.0326382241ef3b2d.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5112.4b9f300124fab7b3.js +149 -0
- package/apps/pwa/out/_next/static/chunks/5335.375ee922bcd5bc83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5342.023a2e729689b320.js +27 -0
- package/apps/pwa/out/_next/static/chunks/{8d173e38.18a2f7b4e1848bdb.js → 53c73f84.373b6160adfa89a4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{1537-6bb97b5214928ea9.js → 5431-72a1dbde59400691.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5440-4236de26c5ea5856.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5486-b318c165f645d8ba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5506-c7d2ec25c62a7c94.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5570-c66ecbea26b4e3b1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5696.ffca5aa259d8451e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5793-8c584aea2aa87560.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5848-6de6b8c173351a90.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5885.0a3e52c8faccec98.js +287 -0
- package/apps/pwa/out/_next/static/chunks/5999.94e3c83040200f31.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5a7901d6-2d8d9b5587cf9042.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{261.0d471e8aded799f3.js → 6131.348b7d6bdcd267ce.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/6164.86133a0172611184.js +90 -0
- package/apps/pwa/out/_next/static/chunks/{9175.2de5209a5ce6f68a.js → 6377.bc7df239edbff244.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6515.e07e8b2b8a707a87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6522-c005514f87d18982.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2226.2cf61ec781827219.js → 6632.0eac1c554f8f2ef3.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/6642.648adb1767f39ecf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6848.138805a09d001d09.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7049-c09e2b7a253a24f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7072.1e00447d9fa39972.js +104 -0
- package/apps/pwa/out/_next/static/chunks/7106.64201c539c5e220c.js +94 -0
- package/apps/pwa/out/_next/static/chunks/7151-1f742b455986530e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7199.18d6b25e001154ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7279-c199ea83f34338fa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/728b938d.ffaa7ad583d60e58.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7309.171c3de54e0322f1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/733.7a1ab3342e03306f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{b84cad00.594027ebe0531fe2.js → 73d2eb0e.4966ad55293c801a.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/{6257.c0037b8949239f5e.js → 7411.9b4b8b747dc7b802.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/7504.d5cf1e7cd89b1b08.js +24 -0
- package/apps/pwa/out/_next/static/chunks/7573-0fd4af62d65d4598.js +1 -0
- package/apps/pwa/out/_next/static/chunks/759.6f8267df4689c401.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7825-668b046f72f14483.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7852-1538768b6eb19388.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7868.cff810430bb63c91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9189505a.980427ac048c8c60.js → 7a98bc80.fa935989e829f9c2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8084-dfcc796874ab4e07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8138.6c10b2a356d52fca.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2566.beaffc3a5e1fcd2e.js → 8262.ddc03e06b733f184.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8266.6bf9b131b2584678.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8403.7b81d5e64074a725.js +8 -0
- package/apps/pwa/out/_next/static/chunks/8470.1998cbd0866a7eac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8505.fd803c6c33b54cc3.js +79 -0
- package/apps/pwa/out/_next/static/chunks/{8272-025653884f9645d2.js → 8546-6f03f8ea34dd61d9.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{6051-0ae955eedb10adb9.js → 8673-bab689a55f7e13b9.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/8687-246fda8433d3477c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/898-280022fb082936bc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9098-50eefc1844212e3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9211-330b6736a63d4cb3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4351.0f37a6db2b34d50b.js → 9249.976f1e69a9d80754.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9255-cf88fceda5666645.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9306-e523ba58bb8adc42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9324.a9866d717ba62cb6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9325.a8510e8aa87c8143.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9353-12bfff0c130104cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9415.69e4a21c60c7d2db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6749.0744ce6eb08d40e9.js → 9427.96aa912ddb5801e0.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/9479-154a697d4b6e4e98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9540-65aa6ccc31b3fd78.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7611.85f045bf232053ac.js → 9633.ce5bddc56784da72.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3746-f80a78f220bf37b5.js → 9656-374232558fd528d0.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9832.f4a98c878ecf2c0a.js +62 -0
- package/apps/pwa/out/_next/static/chunks/9865.f094440645f02d98.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9a852a62-6192a6ea9346ced3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-e772b4710df5d936.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-4361368e6a76b967.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-802f349fdd65248d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-7f35513988a2a495.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-798121656540e33e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-20a089490affe98c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-e5e4ec786d70e604.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-d12fe5d0801430e4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-d8cf21022fecc026.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-21ce565c9c57ee97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-b56563025f619c9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-52f14dd133da8348.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-c0ed7fdcdba76633.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-af8c3020cb520f15.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-72eda67af9f5e35c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-e772b4710df5d936.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-67a6620d31f0a46f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-f059363aa0880ec2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-f9f917d6a57f69fb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-d3ae55eee2f0826c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/{page-83d27757e2b8060a.js → page-0e3d7b9421b79dac.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-ba738f7e233eb211.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-33438b98c74fd599.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-0b34d5fd990d793a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-0f291d3c8fd55a3a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-3fced192be5279c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-04cb3cf182a7c1ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6ccbd2ab23a21542.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-aa0518c48a5f4e56.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4b32226d341ad7d7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-3224fd8f6383b61f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-efbc97459f2914e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-2fe487d88cd5d97c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-48861dd1a858bab7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-197d5d4d21d228ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a763ba89fbdd9c27.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7edb253510b1c136.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0c875702c61965ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-e772b4710df5d936.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-e425c951151095f7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-9c90e0aec4e27f77.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-733e09a02e727d42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-4f899e14c34d77a1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-139d722de1dcd6c1.js → page-bf067887b3307423.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-7af10868ff87d04e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-efe5304057aa11c7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-76bcd29aaa8a26c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-4cfd88e2273ce50f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-0a1ddb47efba0a32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2a176c707152c892.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-efe03031b8797fbf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{409c787b.e48c5bec8ec10456.js → b450776b.3db34d8d965f82d3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{ca3702f8.2913182e73889fa2.js → e8543907.5b040a5f22a0b0e5.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/framework-d0d2d673bfd8a8a9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-4c9fceb2baa09cb7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-b0ab8d8fc9a97556.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-7e2cc62a2e5cec96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-22324935f753ec5e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-9dc1bfa25334998a.js +1 -0
- package/apps/pwa/out/_next/static/css/{b9d8151e48998417.css → 62c858ad53854f47.css} +1 -1
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +22 -22
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +22 -22
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +22 -22
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +21 -21
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +21 -21
- package/apps/pwa/out/ceo/index.html +1 -1
- package/apps/pwa/out/ceo/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +21 -21
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +22 -22
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +22 -22
- package/apps/pwa/out/decisions/index.html +1 -1
- package/apps/pwa/out/decisions/index.txt +21 -21
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +22 -22
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -24
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +22 -22
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +22 -22
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +21 -21
- package/apps/pwa/out/inside/index.html +1 -1
- package/apps/pwa/out/inside/index.txt +22 -22
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +22 -22
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -24
- package/apps/pwa/out/live-run/index.html +1 -1
- package/apps/pwa/out/live-run/index.txt +23 -24
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +21 -21
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +21 -21
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +21 -21
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +22 -22
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +22 -22
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +21 -21
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +21 -21
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +21 -21
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +21 -21
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +22 -22
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +22 -22
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +21 -21
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +22 -22
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +22 -22
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +22 -22
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +22 -22
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +22 -22
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +21 -21
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +22 -22
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +22 -22
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +22 -22
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +22 -22
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +22 -22
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +22 -22
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +22 -22
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +22 -22
- package/bin/elanous.mjs +6 -1
- package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
- package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
- package/docs/goal-context/04-mock-scenarios.md +13 -0
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
- package/graphs/demo/persona-teacher/recipes.yaml +17 -0
- package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
- package/graphs/heal/heal-loop.yaml +1 -0
- package/graphs/overlays/stop-heal-ladder.yaml +136 -2
- package/graphs/release/release-loop.yaml +3 -1
- package/graphs/units/gate/gate.yaml +20 -0
- package/graphs/units/git/git.yaml +26 -0
- package/graphs/units/implement/implement.yaml +19 -0
- package/graphs/units/landing/landing.yaml +18 -0
- package/graphs/units/review/review.yaml +20 -0
- package/graphs/units/verbs/recipes.yaml +13 -10
- package/graphs/units/verbs/research.yaml +20 -0
- package/graphs/work/research-report.yaml +21 -3
- package/package.json +1 -1
- package/scripts/disk-steward.ts +46 -0
- package/scripts/fleet/node-setup.sh +50 -0
- package/scripts/graph-units/verbs/research.ts +55 -0
- package/scripts/heal/run-role.ts +99 -5
- package/scripts/land-global-checks.ts +6 -1
- 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/llm-cost-ledger.ts +179 -8
- package/scripts/measure-nl-routing-corpus.ts +10 -2
- package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
- package/scripts/public-copy-lint.ts +163 -19
- package/scripts/ratchets/train-side-invariants.sh +0 -1
- package/scripts/release-loop/gate-autoheal.ts +117 -0
- package/scripts/release-loop/gate-baseline-receipt.ts +55 -10
- package/scripts/release-loop/gate-diff.ts +22 -3
- package/scripts/release-loop/gate-image-pin.ts +81 -0
- package/scripts/release-loop/gate-node-sim.ts +207 -0
- package/scripts/release-loop/gate-node.ts +489 -62
- 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-shard-load-flaky.ts +256 -0
- package/scripts/release-loop/gate-train-receipts.ts +122 -0
- package/scripts/release-loop/gate-triage-node.ts +70 -10
- package/scripts/release-loop/resume-release.ts +330 -23
- package/scripts/release-loop/traffic-node.ts +6 -3
- package/scripts/release-loop/unattended-release.ts +4 -2
- package/scripts/shadow-authoring-probe.ts +20 -0
- package/scripts/ux-sim.ts +37 -3
- package/scripts/warm-pool-provider-config.ts +263 -0
- package/skills/omni-crawl/SKILL.md +5 -2
- package/skills/omni-crawl/scripts/main.ts +84 -23
- package/src/acp/core-turn-bridge.ts +99 -4
- 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/mission-cli.ts +24 -0
- package/src/agent-mission/mission-out.ts +595 -0
- package/src/agent-mission/tool-install.ts +88 -2
- package/src/agent-substrate/context-strategy.ts +4 -4
- package/src/agent-substrate/self-review-cli.ts +267 -40
- package/src/auto-research/research-turn.ts +133 -51
- package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
- package/src/autopilot/pr-manager.ts +38 -7
- package/src/autopilot/pty-control-loop.ts +2 -0
- package/src/boot/daemon-tools/self-implement.ts +46 -9
- package/src/budget/shadow-arms.ts +52 -0
- package/src/capture/tui-self-report.ts +22 -6
- package/src/chat/index.ts +1 -1
- package/src/chat/pickers/state.ts +7 -1
- 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/log-event-names.ts +5 -0
- package/src/cli/mcp-login.ts +8 -18
- package/src/cli/msg-cli.ts +57 -1
- package/src/cli/pr-land-heavy-remote.ts +47 -9
- package/src/cli/pr-land-overlap-evidence.ts +100 -1
- package/src/cli/pr-land-pod-shadow-job.ts +60 -0
- package/src/cli/release-checklist-read-cli.ts +20 -10
- package/src/cli/release-cli.ts +27 -1
- package/src/cli/research-cli.ts +4 -5
- package/src/cli/sim-cli.ts +7 -1
- package/src/cli/tasks-cli.ts +12 -4
- package/src/codex/models.ts +30 -15
- package/src/compact/auto.ts +8 -1
- package/src/control-plane/ledger.ts +52 -2
- package/src/control-plane/server.ts +16 -2
- package/src/core-turn/run-core-turn.ts +313 -89
- package/src/core-turn/run-goal-loop.ts +106 -2
- package/src/core-turn/types.ts +2 -0
- package/src/dashboard/acp-boot.ts +72 -3
- package/src/dashboard/classic-sidetab-mission-job.ts +58 -0
- package/src/dashboard/classic-sidetab-mission.ts +185 -0
- package/src/dashboard/index.ts +155 -15
- package/src/dashboard/input/agent-wake.ts +23 -1
- package/src/dashboard/input/chat-main-plain-turn-runtime.ts +9 -0
- package/src/dashboard/mission-cli-consumer.ts +153 -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/turn-preamble.ts +65 -16
- package/src/dashboard/turn-prompt-runtime.ts +4 -2
- package/src/disk-steward/judge.ts +73 -0
- package/src/disk-steward/ledger.ts +122 -0
- package/src/disk-steward/steward.ts +373 -0
- package/src/domains/guardian-tick.ts +191 -2
- package/src/graph-runner/graph-cli.ts +44 -7
- package/src/graph-runner/graph-tick.ts +10 -2
- package/src/graph-runner/in-process-registry.ts +37 -0
- package/src/graph-runner/runner.ts +34 -4
- package/src/grok/agent-search.ts +14 -4
- package/src/grok/credential.ts +28 -11
- package/src/grounding/ref-index.ts +19 -0
- package/src/grounding/sources-cli.ts +9 -1
- package/src/harness/harness-cli-command.ts +267 -14
- package/src/harness/harness-incidents.ts +312 -7
- package/src/harness/harness-pod-dispatch.ts +81 -15
- package/src/harness/harness-space.ts +15 -1
- package/src/harness/harness-stop.ts +155 -11
- package/src/harness/progress-worker-entry.ts +59 -0
- package/src/harness/progress-worker-runtime.ts +11 -0
- package/src/index.ts +52 -7
- package/src/instance/dev-project.ts +25 -0
- package/src/instance/spawn-elanous.ts +6 -4
- package/src/intelligence-map/model-alias.ts +6 -5
- package/src/intelligence-map/model-catalog.ts +59 -2
- package/src/llm/model-defaults.ts +4 -4
- package/src/llm.ts +208 -19
- package/src/loops/orchestrator/coordinator-shadow.ts +226 -0
- package/src/loops/orchestrator/tick.ts +61 -0
- package/src/maturity/feature-maturity.ts +1 -1
- package/src/mcp/mcp-oauth.ts +3 -1
- package/src/model-tier/llm-tier-map.ts +9 -9
- package/src/model-tier/turn-tier.ts +1 -1
- package/src/msg/msg-mirror-github.ts +80 -0
- package/src/msg/msg-mirror-policy.ts +61 -0
- package/src/msg/msg-mirror-runner.ts +219 -0
- package/src/msg/msg-mirror-state.ts +33 -0
- package/src/msg/msg-store.ts +11 -0
- package/src/native-tool-catalog.ts +2 -2
- package/src/nexus/api/harness-traversal.ts +11 -0
- package/src/output-truncation.ts +41 -12
- package/src/pr-tool/census.ts +3 -2
- package/src/project/project-store.ts +48 -1
- package/src/pty-shell/tui-run-state.ts +188 -2
- package/src/release-loop/checklist-target-path-hint.ts +13 -0
- package/src/release-loop/checklist.ts +9 -1
- package/src/release-loop/gate-host-reservation.ts +144 -0
- package/src/release-loop/release-schedule.ts +90 -1
- package/src/repl/index.ts +43 -2
- package/src/research/axis-fanout.ts +121 -16
- package/src/research/bloom-exemplars.ts +137 -0
- 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 +39 -25
- package/src/self-dev/decompose.ts +119 -5
- package/src/self-dev/dev-cli.ts +17 -17
- package/src/self-dev/graph-front-nodes.ts +23 -0
- package/src/self-dev/launch-preflight-text.ts +5 -6
- package/src/self-dev/launch-preflight.ts +9 -4
- package/src/self-dev/orchestrate.ts +27 -2
- package/src/self-dev/review-provider-fallback.ts +9 -2
- package/src/self-dev/run-supervisor.ts +226 -6
- package/src/self-dev/run-types.ts +7 -0
- package/src/self-implement/doctor-visit.ts +88 -0
- package/src/self-implement/gate-artifacts.ts +13 -0
- package/src/self-implement/gate-cli.ts +54 -24
- package/src/self-implement/gate-remote.ts +23 -5
- package/src/self-implement/goal-author-clarification.ts +31 -12
- package/src/self-implement/goal-author.ts +403 -8
- package/src/self-implement/graph-overlay-yaml.ts +7 -0
- package/src/self-implement/graph-stage-units.ts +172 -0
- package/src/self-implement/graph-templates.ts +162 -1
- package/src/self-implement/graph-variant.ts +37 -4
- package/src/self-implement/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 +31 -8
- package/src/self-implement/knowhow-pack.ts +38 -0
- package/src/self-implement/merge-train.ts +5 -0
- package/src/self-implement/orchestrator.ts +359 -30
- 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 +119 -0
- package/src/self-implement/run-ledger.ts +176 -17
- package/src/self-implement/run-stop.ts +208 -5
- package/src/self-implement/running-runs.ts +35 -12
- package/src/self-implement/self-implement-cli.ts +36 -4
- package/src/self-implement/stop-autoheal-operational.ts +43 -0
- package/src/self-implement/stop-autoheal.ts +28 -6
- package/src/session/chat.ts +69 -58
- package/src/session/request-size-guard.ts +123 -0
- package/src/session-runtime/index.ts +98 -4
- package/src/session-runtime/tier-flip.ts +3 -3
- package/src/sidetab-core/model.ts +150 -0
- package/src/sidetab-core/visible-agent-mission.ts +186 -0
- package/src/skills/name-match.ts +20 -0
- package/src/skills/tools/agent.ts +30 -2
- package/src/skills/tools/omni-search.ts +67 -5
- package/src/task-agent/parent-host.ts +14 -1
- package/src/task-agent/pod-distributor-entry.ts +3 -0
- package/src/task-agent/task-hand.ts +31 -1
- package/src/task-orchestrator/surfaces/pod-distributor.ts +48 -0
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +43 -0
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +38 -1
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
- 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 +163 -13
- package/src/task-orchestrator/surfaces/pod-source-spec.ts +3 -3
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +209 -39
- package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +80 -3
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +280 -60
- package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
- package/src/tokens.ts +35 -2
- package/src/tool-runtime/agent-runtime.ts +1 -0
- package/src/tool-runtime/elanous-skills-list-runtime.ts +5 -1
- package/src/tool-runtime/skill-exec-runtime.ts +33 -13
- package/src/tool-runtime/types.ts +1 -0
- package/src/tui/entry.ts +24 -7
- package/src/tui/sidetab/attach.ts +47 -0
- package/src/tui/sidetab/list.ts +45 -0
- package/src/tui/sidetab/nl-tool.ts +2 -136
- package/src/tui/sidetab/peek.ts +52 -0
- package/src/tui-client/dashboard-session.ts +3 -0
- package/src/tui-client/local-chat-turn.ts +26 -13
- package/src/tui.ts +22 -0
- package/src/user-config.ts +11 -5
- package/src/ux-sim/fake-kubectl.ts +37 -3
- package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
- package/src/ux-sim/fault-pod-child-result.ts +42 -0
- package/src/ux-sim/fault-pool-cap.ts +11 -6
- package/src/ux-sim/mock-scenario-catalog.json +41 -0
- package/src/ux-sim/mock-scenario-catalog.ts +156 -0
- package/src/ux-sim/release-sim-rig.ts +262 -0
- package/src/ux-sim/scenario.ts +116 -23
- package/src/ux-sim/seminar-rehearsal.ts +109 -0
- package/src/ux-sim/subagent-tools-device.ts +2 -2
- package/src/version/packed-revision.json +1 -1
- package/src/voice/voice-tts-singleton.ts +18 -3
- package/src/web-search/grok.ts +5 -9
- package/apps/pwa/out/_next/static/chunks/1060.014f1f01a17aec26.js +0 -115
- package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1452.162bb2d9d699e82a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +0 -286
- package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +0 -90
- package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +0 -104
- package/apps/pwa/out/_next/static/chunks/2047.8f23e210995d4548.js +0 -2
- package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2066.a77257c8c350770a.js +0 -23
- package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2281-b8cede695c6c650e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2499.02fbfd18126c10c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2522.f2766b76d22c8bdf.js +0 -34
- package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +0 -27
- package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2774-719820e3f5b2a3eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2829-734fe8bf2eee7347.js +0 -1
- package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +0 -24
- package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +0 -77
- package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +0 -36
- package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +0 -287
- package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +0 -1
- package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +0 -74
- package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5622.94893f5aea7185d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +0 -8
- package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +0 -62
- package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +0 -94
- package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6624.981ef7caeb680560.js +0 -32
- package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +0 -148
- package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6cc1d1d6.9a98dd4622f1afc6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +0 -93
- package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7515.1ad6efe157fa4448.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8086.1ab9103c41be884f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8357.1aaa713b052a78b1.js +0 -309
- package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9069.657590a84afb8fac.js +0 -41
- package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9992.07ce73c10bd5e6a1.js +0 -79
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-ba957ff875a026a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-4edb8df90f4537ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-fca2e59a81744d9e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-ccde99f07aaf71f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +0 -1
- package/apps/pwa/out/_next/static/chunks/c696986b.5dc8bb1143af16d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/d8de0de2-dd0f4ac8e5ab1832.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +0 -1
- package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +0 -1
- package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
- /package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → X1ucLw10Cds_h614NoEnh}/_ssgManifest.js +0 -0
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// 판독(CLI 쪽): `describePtyRunState` 가 행 ⊕ 설치본 기록 ⊕ (체크아웃이면) 그 뿌리의 HEAD 로 판정한다.
|
|
13
13
|
|
|
14
14
|
import { spawn } from 'node:child_process';
|
|
15
|
-
import { readFileSync } from 'node:fs';
|
|
15
|
+
import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
16
16
|
import { homedir } from 'node:os';
|
|
17
17
|
import { dirname, join, resolve } from 'node:path';
|
|
18
18
|
import { fileURLToPath } from 'node:url';
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
updatePtyManifestAbortRequested, updatePtyManifestBuild, updatePtyManifestProgress, updatePtyManifestTurn,
|
|
31
31
|
type PtyBuildIdentity, type PtyManifestRow, type PtyTurnState,
|
|
32
32
|
} from './pty-manifest.js';
|
|
33
|
+
import { ptyEventLogDbPath, readPtyEventsAfterAt } from './pty-event-log.js';
|
|
33
34
|
|
|
34
35
|
const CODE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
35
36
|
|
|
@@ -496,6 +497,139 @@ export function judgeTurnProgress(input: TurnProgressInput): TurnProgressJudgmen
|
|
|
496
497
|
return 'progressing';
|
|
497
498
|
}
|
|
498
499
|
|
|
500
|
+
// ── TUI-SEAT-PILOT-2H-COMPARE — 좌석 대조 판정 신호 한 줄 ──
|
|
501
|
+
//
|
|
502
|
+
// 완료 경계는 «실행 명령·runId·시작/끝 시각·두 표면의 원장 행·산출 바이트·오류 수·결과» 를
|
|
503
|
+
// `seat-state/OP/tools/sim-log.sh` 한 줄로 남기라고 한다. 그 한 줄의 «형식» 은 순수 함수가 정하고,
|
|
504
|
+
// 두 표면의 원장 행은 각자의 생산 원장에서 읽는다 — tui-run-state 는 pty_manifest 행, pty-event-log 는
|
|
505
|
+
// `pty_events` 의 그 표면 행이다. ⛔ 재지 못한 항목은 «미측정» 으로 남긴다 — 측정된 `0` 과 섞지 않는다(null ≠ 0).
|
|
506
|
+
|
|
507
|
+
/** 재지 못한 항목의 직렬화 값. 측정된 `0`·빈 문자열과 구별된다. */
|
|
508
|
+
export const SEAT_COMPARE_UNMEASURED = '미측정';
|
|
509
|
+
|
|
510
|
+
/** 한 표면의 원장 요약. `rows === null` 은 «못 읽었다» 이지 «0행» 이 아니다. */
|
|
511
|
+
export interface SeatCompareLedgerSummary {
|
|
512
|
+
readonly surface: string;
|
|
513
|
+
readonly rows: number | null;
|
|
514
|
+
readonly lastSeq: number | null;
|
|
515
|
+
readonly lastState: string | null;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/** 판정 신호 입력 — 완료 경계가 이름으로 요구한 항목 그대로. */
|
|
519
|
+
export interface SeatCompareSignalInput {
|
|
520
|
+
readonly runId: string | null;
|
|
521
|
+
readonly command: string | null;
|
|
522
|
+
readonly startedAt: number | null;
|
|
523
|
+
readonly endedAt: number | null;
|
|
524
|
+
/** 이 TUI 좌석 표면의 원장 행 요약(pty_manifest 턴 행). */
|
|
525
|
+
readonly tuiRunState: SeatCompareLedgerSummary;
|
|
526
|
+
/** 비교 상대 표면의 원장 행 요약(`pty_events`). */
|
|
527
|
+
readonly ptyEventLog: SeatCompareLedgerSummary;
|
|
528
|
+
readonly outputBytes: number | null;
|
|
529
|
+
readonly errors: number | null;
|
|
530
|
+
readonly result: string | null;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function seatCompareText(value: string | null | undefined): string {
|
|
534
|
+
if (value === null || value === undefined) return SEAT_COMPARE_UNMEASURED;
|
|
535
|
+
// 한 줄 계약 — 값 안의 개행·연속 공백은 접어서 줄을 쪼개지 못하게 한다.
|
|
536
|
+
const flat = value.replace(/\s+/g, ' ').trim();
|
|
537
|
+
return flat.length > 0 ? flat : SEAT_COMPARE_UNMEASURED;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function seatCompareCount(value: number | null | undefined): string {
|
|
541
|
+
if (value === null || value === undefined || !Number.isFinite(value)) return SEAT_COMPARE_UNMEASURED;
|
|
542
|
+
return String(value);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function seatCompareAt(ms: number | null | undefined): string {
|
|
546
|
+
if (ms === null || ms === undefined || !Number.isFinite(ms)) return SEAT_COMPARE_UNMEASURED;
|
|
547
|
+
return new Date(ms).toISOString();
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
function seatCompareLedger(summary: SeatCompareLedgerSummary): string {
|
|
551
|
+
return [
|
|
552
|
+
`ledger:${seatCompareText(summary.surface)}`,
|
|
553
|
+
`rows=${seatCompareCount(summary.rows)}`,
|
|
554
|
+
`lastSeq=${seatCompareCount(summary.lastSeq)}`,
|
|
555
|
+
`lastState=${seatCompareText(summary.lastState)}`,
|
|
556
|
+
].join(' ');
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/** 판정 신호 한 줄 — 새 줄 없이 ` · ` 로 잇는다. 못 잰 항목은 «미측정» 으로 남는다. */
|
|
560
|
+
export function buildSeatCompareSignalLine(input: SeatCompareSignalInput): string {
|
|
561
|
+
return [
|
|
562
|
+
`run=${seatCompareText(input.runId)}`,
|
|
563
|
+
`cmd=${seatCompareText(input.command)}`,
|
|
564
|
+
`start=${seatCompareAt(input.startedAt)}`,
|
|
565
|
+
`end=${seatCompareAt(input.endedAt)}`,
|
|
566
|
+
seatCompareLedger(input.tuiRunState),
|
|
567
|
+
seatCompareLedger(input.ptyEventLog),
|
|
568
|
+
`bytes=${seatCompareCount(input.outputBytes)}`,
|
|
569
|
+
`errors=${seatCompareCount(input.errors)}`,
|
|
570
|
+
`result=${seatCompareText(input.result)}`,
|
|
571
|
+
].join(' · ');
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/** 생산 이음매 — `pty_events` 원장에서 이 표면의 행을 실제로 읽어 요약한다. 못 읽으면 rows=null(미측정). */
|
|
575
|
+
export function readPtyEventLogLedger(surfaceId: string, dbPath: string = ptyEventLogDbPath()): SeatCompareLedgerSummary {
|
|
576
|
+
const surface = 'pty-event-log';
|
|
577
|
+
const read = readPtyEventsAfterAt(dbPath, 0, { surfaceId });
|
|
578
|
+
if (read.status !== 'ok') return { surface, rows: null, lastSeq: null, lastState: null };
|
|
579
|
+
const last = read.rows.length > 0 ? read.rows[read.rows.length - 1] : undefined;
|
|
580
|
+
return { surface, rows: read.rows.length, lastSeq: last ? last.seq : 0, lastState: last?.state ?? null };
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/** 기본 기록 위치 — 셸 도구와 같은 파일(`seat-state/OP/tools/sim-log.log`). `ELANOUS_SEAT_COMPARE_LOG` 로 바꾼다. */
|
|
584
|
+
export const SEAT_COMPARE_LOG_PATH = join(CODE_ROOT, 'seat-state', 'OP', 'tools', 'sim-log.log');
|
|
585
|
+
|
|
586
|
+
export interface SeatCompareWriteDeps {
|
|
587
|
+
readonly path?: string;
|
|
588
|
+
/** append 이음매 — 시험이 임시 파일·메모리로 바꾼다. */
|
|
589
|
+
readonly append?: (path: string, line: string) => void;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/** 판정 신호 한 줄을 sim-log 에 append 한다. 실패(권한 등)는 false — 종료 경로를 깨지 않는다. */
|
|
593
|
+
export function appendSeatCompareSignalLine(line: string, deps: SeatCompareWriteDeps = {}): boolean {
|
|
594
|
+
const path = deps.path ?? (process.env.ELANOUS_SEAT_COMPARE_LOG?.trim() || SEAT_COMPARE_LOG_PATH);
|
|
595
|
+
try {
|
|
596
|
+
if (deps.append) {
|
|
597
|
+
deps.append(path, line);
|
|
598
|
+
} else {
|
|
599
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
600
|
+
appendFileSync(path, `${line}\n`, 'utf8');
|
|
601
|
+
}
|
|
602
|
+
return true;
|
|
603
|
+
} catch {
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* 생산 진입점 스위치 — `ELANOUS_SEAT_COMPARE_RUN_ID` 가 있을 때만 좌석 대조 원장을 켠다.
|
|
610
|
+
* 없으면 `null` = 녹음기가 그 한 줄을 안 남긴다(«미실행은 미측정»).
|
|
611
|
+
*/
|
|
612
|
+
export function seatCompareDepsFromEnv(env: NodeJS.ProcessEnv = process.env): TuiSeatCompareDeps | null {
|
|
613
|
+
const runId = env.ELANOUS_SEAT_COMPARE_RUN_ID?.trim();
|
|
614
|
+
if (!runId) return null;
|
|
615
|
+
const command = env.ELANOUS_SEAT_COMPARE_COMMAND?.trim() || [process.execPath, ...process.argv.slice(1)].join(' ');
|
|
616
|
+
return { runId, command };
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/** 좌석 대조 판정 신호를 켜는 손잡이 — 주면 녹음기 종료 경로가 두 표면 원장을 읽어 한 줄을 남긴다. */
|
|
620
|
+
export interface TuiSeatCompareDeps {
|
|
621
|
+
readonly runId: string | null;
|
|
622
|
+
readonly command?: string | null;
|
|
623
|
+
/** 산출 바이트 — 녹음기가 못 재면 생략(«미측정»). */
|
|
624
|
+
readonly outputBytes?: number | null;
|
|
625
|
+
/** 결과 판정 문구 — 생략하면 종료 시 마지막 턴 상태. */
|
|
626
|
+
readonly result?: string | null;
|
|
627
|
+
/** 원장 요약 읽기 이음매(시험: 가짜 원장). 생략하면 실 `pty_events`. */
|
|
628
|
+
readonly readLedger?: (surfaceId: string) => SeatCompareLedgerSummary;
|
|
629
|
+
/** 기록 이음매(시험: 메모리). 생략하면 sim-log 파일 append. */
|
|
630
|
+
readonly write?: (line: string) => boolean;
|
|
631
|
+
}
|
|
632
|
+
|
|
499
633
|
// ── 기록(TUI) ──
|
|
500
634
|
|
|
501
635
|
export interface TuiRunStateRecorderDeps {
|
|
@@ -524,6 +658,11 @@ export interface TuiRunStateRecorderDeps {
|
|
|
524
658
|
* 생략하면 감시를 안 건다 — 이 축을 켜는 것은 호출자(생산 진입점)의 결정이다.
|
|
525
659
|
*/
|
|
526
660
|
readonly selfRestart?: TuiSelfRestartDeps;
|
|
661
|
+
/**
|
|
662
|
+
* TUI-SEAT-PILOT-2H-COMPARE 좌석 대조 판정 신호. 주면 종료 경로가 두 표면(pty_manifest 턴 행 ⊕
|
|
663
|
+
* `pty_events`)의 원장행을 읽어 «한 줄» 을 sim-log 에 남긴다. 생략하면 아무것도 안 남긴다(미실행=미측정).
|
|
664
|
+
*/
|
|
665
|
+
readonly seatCompare?: TuiSeatCompareDeps;
|
|
527
666
|
}
|
|
528
667
|
|
|
529
668
|
interface ActiveRecorder {
|
|
@@ -550,9 +689,29 @@ const defaultLog = (event: string, data: Record<string, unknown>): void => { deb
|
|
|
550
689
|
export function startTuiRunStateRecorder(surfaceId: string, deps: TuiRunStateRecorderDeps = {}): () => void {
|
|
551
690
|
const now = deps.now ?? Date.now;
|
|
552
691
|
const log = deps.log ?? defaultLog;
|
|
553
|
-
const
|
|
692
|
+
const writeTurnBase = deps.writeTurn ?? updatePtyManifestTurn;
|
|
554
693
|
const writeProgress = deps.writeProgress ?? updatePtyManifestProgress;
|
|
555
694
|
const writeAbortRequested = deps.writeAbortRequested ?? updatePtyManifestAbortRequested;
|
|
695
|
+
// 좌석 대조 신호가 켜졌을 때만 턴 행 수·쓰기 실패를 센다 — 꺼져 있으면 판정 신호 비용 0.
|
|
696
|
+
const seatCompare = deps.seatCompare ?? null;
|
|
697
|
+
// 시작 시각도 신호가 켜졌을 때만 잰다 — 꺼져 있으면 종전과 같이 now() 를 한 번도 더 부르지 않는다.
|
|
698
|
+
const seatCompareStartedAt = seatCompare ? now() : 0;
|
|
699
|
+
let seatCompareTurnRows = 0;
|
|
700
|
+
let seatCompareWriteFailures = 0;
|
|
701
|
+
const writeTurn = seatCompare
|
|
702
|
+
? (id: string, turn: PtyTurnState, at: number): boolean => {
|
|
703
|
+
let ok = false;
|
|
704
|
+
try {
|
|
705
|
+
ok = writeTurnBase(id, turn, at);
|
|
706
|
+
} catch (error) {
|
|
707
|
+
seatCompareWriteFailures += 1;
|
|
708
|
+
throw error;
|
|
709
|
+
}
|
|
710
|
+
if (ok) seatCompareTurnRows += 1;
|
|
711
|
+
else seatCompareWriteFailures += 1;
|
|
712
|
+
return ok;
|
|
713
|
+
}
|
|
714
|
+
: writeTurnBase;
|
|
556
715
|
// 기본 신고기는 기본 manifest 쓰기와 짝일 때만. writeTurn 주입(시험)은 herdr 를 안 만든다.
|
|
557
716
|
const herdr = deps.herdr !== undefined
|
|
558
717
|
? deps.herdr
|
|
@@ -564,6 +723,7 @@ export function startTuiRunStateRecorder(surfaceId: string, deps: TuiRunStateRec
|
|
|
564
723
|
if (build) {
|
|
565
724
|
const ok = (() => { try { return (deps.writeBuild ?? updatePtyManifestBuild)(surfaceId, build); } catch { return false; } })();
|
|
566
725
|
log(ok ? 'build-recorded' : 'build-write-failed', { ptyId: surfaceId, sha: build.sha, version: build.version, source: build.source });
|
|
726
|
+
if (!ok) seatCompareWriteFailures += 1;
|
|
567
727
|
}
|
|
568
728
|
// 기동 순서: 판 → manifest 초기 idle → herdr 신고. herdr start 가 idle 을 신고하므로 초기 idle 을 turn 으로 다시 안 보낸다.
|
|
569
729
|
const recorder: ActiveRecorder = { surfaceId, now, writeTurn, writeProgress, writeAbortRequested, log, herdr, herdrLast: herdr ? 'idle' : undefined };
|
|
@@ -662,6 +822,32 @@ export function startTuiRunStateRecorder(surfaceId: string, deps: TuiRunStateRec
|
|
|
662
822
|
try { unwatch(); } catch { /* 종료 경로를 깨지 않는다 */ }
|
|
663
823
|
try { unguard(); } catch { /* 종료 경로를 깨지 않는다 */ }
|
|
664
824
|
if (herdr) { try { herdr.release(); } catch { /* 종료 경로를 깨지 않는다 */ } }
|
|
825
|
+
// 좌석 대조 판정 신호 — 두 표면의 원장 행을 «여기서» 읽어 한 줄로 남긴다.
|
|
826
|
+
if (seatCompare) {
|
|
827
|
+
try {
|
|
828
|
+
const readLedger = seatCompare.readLedger ?? readPtyEventLogLedger;
|
|
829
|
+
const line = buildSeatCompareSignalLine({
|
|
830
|
+
runId: seatCompare.runId,
|
|
831
|
+
command: seatCompare.command ?? null,
|
|
832
|
+
startedAt: seatCompareStartedAt,
|
|
833
|
+
endedAt: now(),
|
|
834
|
+
tuiRunState: {
|
|
835
|
+
surface: 'tui-run-state',
|
|
836
|
+
rows: seatCompareTurnRows,
|
|
837
|
+
lastSeq: null,
|
|
838
|
+
lastState: recorder.last ?? null,
|
|
839
|
+
},
|
|
840
|
+
ptyEventLog: readLedger(surfaceId),
|
|
841
|
+
outputBytes: seatCompare.outputBytes ?? null,
|
|
842
|
+
errors: seatCompareWriteFailures,
|
|
843
|
+
result: seatCompare.result ?? recorder.last ?? null,
|
|
844
|
+
});
|
|
845
|
+
const written = (seatCompare.write ?? appendSeatCompareSignalLine)(line);
|
|
846
|
+
log(written ? 'seat-compare-signal' : 'seat-compare-signal-write-failed', { ptyId: surfaceId, line });
|
|
847
|
+
} catch (error) {
|
|
848
|
+
log('seat-compare-signal-failed', { ptyId: surfaceId, error: error instanceof Error ? error.message : String(error) });
|
|
849
|
+
}
|
|
850
|
+
}
|
|
665
851
|
if (active === recorder) active = null;
|
|
666
852
|
};
|
|
667
853
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface TargetPathHintLine {
|
|
2
|
+
readonly fragments: readonly string[];
|
|
3
|
+
readonly labelMissing: boolean;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/** Parse the first declared target-path line shared by checklist storage and ask preflight. */
|
|
7
|
+
export function parseTargetPathHintLine(text: string): TargetPathHintLine {
|
|
8
|
+
const firstLine = text.split(/\r?\n/).find((line) => line.trim() !== '');
|
|
9
|
+
if (firstLine === undefined) return { fragments: [], labelMissing: true };
|
|
10
|
+
const match = /^\s*(?:대상\s*경로|target\s*paths?)\s*[::]\s*(.*)$/i.exec(firstLine);
|
|
11
|
+
if (!match) return { fragments: [], labelMissing: true };
|
|
12
|
+
return { fragments: match[1]!.split(/[·,;]/), labelMissing: false };
|
|
13
|
+
}
|
|
@@ -5,6 +5,9 @@ import { isAbsolute, join } from 'node:path';
|
|
|
5
5
|
import * as store from './feature-store.js';
|
|
6
6
|
import { debug } from '../debug/log.js';
|
|
7
7
|
import { CliUserError } from '../cli/cli-user-error.js';
|
|
8
|
+
import { parseTargetPathHintLine } from './checklist-target-path-hint.js';
|
|
9
|
+
export { parseTargetPathHintLine } from './checklist-target-path-hint.js';
|
|
10
|
+
export type { TargetPathHintLine } from './checklist-target-path-hint.js';
|
|
8
11
|
|
|
9
12
|
export type ChecklistStatus = 'green' | 'yellow' | 'red' | 'done';
|
|
10
13
|
export type ChecklistDisposition = 'move' | 'known-issue' | 'block';
|
|
@@ -248,6 +251,11 @@ export function isMergeOrTypecheckOnlyEvidence(value: string): boolean {
|
|
|
248
251
|
return signal;
|
|
249
252
|
}
|
|
250
253
|
|
|
254
|
+
/** Parsed target path fragments, preserving order and raw path spelling while trimming separator whitespace. */
|
|
255
|
+
export function parseChecklistTargetPaths(text: string): string[] {
|
|
256
|
+
return parseTargetPathHintLine(text).fragments.map((fragment) => fragment.trim().replace(/^`+|`+$/g, ''));
|
|
257
|
+
}
|
|
258
|
+
|
|
251
259
|
/** Shadow check at checklist authorship. Callers supply the origin/main file probe and merged-PR file reader. */
|
|
252
260
|
export function inspectChecklistTargetPaths(input: {
|
|
253
261
|
title: string; evidence?: string; refs?: readonly string[]; dispatchKind?: ChecklistDispatchKind;
|
|
@@ -256,7 +264,7 @@ export function inspectChecklistTargetPaths(input: {
|
|
|
256
264
|
} {
|
|
257
265
|
const lines = input.title.split(/\r?\n/);
|
|
258
266
|
const first = /^대상 경로:\s*(.*)$/.exec(lines[0] ?? '');
|
|
259
|
-
const rawTargets =
|
|
267
|
+
const rawTargets = parseChecklistTargetPaths(lines[0] ?? '');
|
|
260
268
|
const validPath = (path: string): boolean => path.length > 0 && path.length < 4096
|
|
261
269
|
&& !path.startsWith('/') && !path.includes('\\') && !/[\u0000-\u001f\u007f]/u.test(path)
|
|
262
270
|
&& path.split('/').every((segment) => segment !== '' && segment !== '.' && segment !== '..');
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
2
3
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
4
|
import { join } from 'node:path';
|
|
4
5
|
import { psProcessStartMs } from '../harness/harness-stop.js';
|
|
5
6
|
import { debug } from '../debug/log.js';
|
|
6
7
|
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
8
|
+
import { psProcessStart, type HostLeaseRecord, type PendingJobIdentity } from '../pod-lease/host-lease.js';
|
|
9
|
+
import { parsePodPool, podPoolHostLease, resolvePodPoolSpec, type PodPoolMember } from '../task-orchestrator/surfaces/pod-pool.js';
|
|
7
10
|
|
|
8
11
|
interface GateHostClaim {
|
|
9
12
|
token: string;
|
|
@@ -19,6 +22,147 @@ export type GateHostReservation =
|
|
|
19
22
|
| { status: 'free' }
|
|
20
23
|
| { status: 'reserved' | 'unknown'; reason: string; runId?: string; reservedAt?: number };
|
|
21
24
|
|
|
25
|
+
/** Read-only snapshots used to decide whether the resource pool behind a gate host is occupied. */
|
|
26
|
+
export interface GateHostResourceSnapshot {
|
|
27
|
+
/** null means the lease ledger was unreadable; [] is a measured empty ledger. */
|
|
28
|
+
leases: readonly HostLeaseRecord[] | null;
|
|
29
|
+
/** Active Pending/Running Jobs from the configured Pod pool; null means not measurable. */
|
|
30
|
+
activeJobs: readonly PendingJobIdentity[] | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type GateHostResourceReading =
|
|
34
|
+
| { status: 'measured'; empty: boolean; reservations: number; authoringLeases: number; waitingJobs: number; activeJobs: number }
|
|
35
|
+
| { status: 'unmeasurable'; empty: null; reason: 'lease-ledger-unavailable' | 'lease-ledger-invalid' | 'pod-list-unavailable' | 'pod-list-invalid' | 'pod-pool-invalid' };
|
|
36
|
+
|
|
37
|
+
const unavailable = (reason: Extract<GateHostResourceReading, { status: 'unmeasurable' }>['reason']): GateHostResourceReading => ({ status: 'unmeasurable', empty: null, reason });
|
|
38
|
+
|
|
39
|
+
/** Read leases and active harness Pods from the configured pool without creating, pruning, or updating any ledger. */
|
|
40
|
+
export function readGateHostResourcesForHost(host: string, env: NodeJS.ProcessEnv = process.env,
|
|
41
|
+
deps: { members?: readonly PodPoolMember[]; kubectl?: (args: readonly string[]) => { status: number | null; stdout: string };
|
|
42
|
+
processStart?: (pid: number) => string | null } = {}): GateHostResourceReading {
|
|
43
|
+
let members: readonly PodPoolMember[];
|
|
44
|
+
try {
|
|
45
|
+
const spec = resolvePodPoolSpec(undefined, env, () => {
|
|
46
|
+
try {
|
|
47
|
+
// The gate path resolves its pool from harness.podPool, unlike generic Pod launches.
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
49
|
+
return (require('../user-config.js') as typeof import('../user-config.js')).getUserConfig().harness?.podPool;
|
|
50
|
+
} catch { return undefined; }
|
|
51
|
+
});
|
|
52
|
+
members = deps.members ?? (spec ? parsePodPool(spec) : []);
|
|
53
|
+
} catch { return unavailable('pod-pool-invalid'); }
|
|
54
|
+
if (!members.length) return unavailable('pod-list-unavailable');
|
|
55
|
+
const selectedHost = host.split('@').at(-1)!;
|
|
56
|
+
const selectedMembers = members.filter(member => member.sshHost === selectedHost);
|
|
57
|
+
if (!selectedMembers.length) return unavailable('pod-list-unavailable');
|
|
58
|
+
const selectedContexts = new Set(selectedMembers.map(member => member.context));
|
|
59
|
+
|
|
60
|
+
const leasePool = podPoolHostLease(members);
|
|
61
|
+
let leases: HostLeaseRecord[];
|
|
62
|
+
try {
|
|
63
|
+
let names: string[];
|
|
64
|
+
try { names = readdirSync(leasePool.dir).filter(name => name.endsWith('.json')); }
|
|
65
|
+
catch (error) {
|
|
66
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') names = [];
|
|
67
|
+
else return unavailable('lease-ledger-unavailable');
|
|
68
|
+
}
|
|
69
|
+
leases = [];
|
|
70
|
+
const processStart = deps.processStart ?? psProcessStart;
|
|
71
|
+
for (const name of names) {
|
|
72
|
+
if (!/^[A-Za-z0-9._-]+\.json$/.test(name)) return unavailable('lease-ledger-invalid');
|
|
73
|
+
let lease: HostLeaseRecord;
|
|
74
|
+
try { lease = JSON.parse(readFileSync(join(leasePool.dir, name), 'utf8')) as HostLeaseRecord; }
|
|
75
|
+
catch { return unavailable('lease-ledger-invalid'); }
|
|
76
|
+
if (!lease || !Number.isSafeInteger(lease.pid) || lease.pid <= 0 || typeof lease.startedAt !== 'string' || !lease.startedAt ||
|
|
77
|
+
typeof lease.at !== 'string' || (lease.stage !== undefined && lease.stage !== 'authoring' && lease.stage !== 'job') ||
|
|
78
|
+
(lease.stage === 'job' && (!lease.job || !lease.context || !lease.namespace))) return unavailable('lease-ledger-invalid');
|
|
79
|
+
try { process.kill(lease.pid, 0); }
|
|
80
|
+
catch (error) {
|
|
81
|
+
if ((error as NodeJS.ErrnoException).code === 'ESRCH') continue;
|
|
82
|
+
// EPERM means the PID may still be alive; the start-time comparison below is still read-only.
|
|
83
|
+
}
|
|
84
|
+
const startedAt = processStart(lease.pid);
|
|
85
|
+
if (startedAt === null) return unavailable('lease-ledger-unavailable');
|
|
86
|
+
if (startedAt !== lease.startedAt) continue;
|
|
87
|
+
if (lease.stage !== 'job' || selectedContexts.has(lease.context!)) leases.push(lease);
|
|
88
|
+
}
|
|
89
|
+
} catch { return unavailable('lease-ledger-unavailable'); }
|
|
90
|
+
|
|
91
|
+
const kubectl = deps.kubectl ?? ((args: readonly string[]) => {
|
|
92
|
+
const result = spawnSync('kubectl', [...args], { encoding: 'utf8', timeout: 15_000, maxBuffer: 64 * 1024 * 1024 });
|
|
93
|
+
return { status: result.status, stdout: result.stdout ?? '' };
|
|
94
|
+
});
|
|
95
|
+
const activeJobs = new Map<string, PendingJobIdentity>();
|
|
96
|
+
for (const member of selectedMembers) {
|
|
97
|
+
let result: { status: number | null; stdout: string };
|
|
98
|
+
try { result = kubectl(['--context', member.context, '--request-timeout=10s', 'get', 'pods', '--all-namespaces', '-l', 'elanous.substrate=pod', '-o', 'json']); }
|
|
99
|
+
catch { return unavailable('pod-list-unavailable'); }
|
|
100
|
+
if (result.status !== 0) return unavailable('pod-list-unavailable');
|
|
101
|
+
let items: unknown;
|
|
102
|
+
try { items = (JSON.parse(result.stdout) as { items?: unknown }).items; }
|
|
103
|
+
catch { return unavailable('pod-list-invalid'); }
|
|
104
|
+
if (!Array.isArray(items)) return unavailable('pod-list-invalid');
|
|
105
|
+
for (const item of items) {
|
|
106
|
+
if (!item || typeof item !== 'object') return unavailable('pod-list-invalid');
|
|
107
|
+
const pod = item as { metadata?: { name?: unknown; namespace?: unknown; deletionTimestamp?: unknown; labels?: Record<string, unknown>; ownerReferences?: Array<{ kind?: unknown; name?: unknown }> }; status?: { phase?: unknown } };
|
|
108
|
+
const phase = pod.status?.phase;
|
|
109
|
+
if (phase === 'Succeeded' || phase === 'Failed') continue;
|
|
110
|
+
if (phase !== 'Pending' && phase !== 'Running') return unavailable('pod-list-invalid');
|
|
111
|
+
// Deleting Pods are already leaving the pool and must not keep the selected host occupied.
|
|
112
|
+
if (pod.metadata?.deletionTimestamp != null) continue;
|
|
113
|
+
const context = member.context;
|
|
114
|
+
const namespace = pod.metadata?.namespace;
|
|
115
|
+
const owner = pod.metadata?.ownerReferences?.find(ref => ref.kind === 'Job')?.name;
|
|
116
|
+
const job = owner ?? pod.metadata?.labels?.['job-name'];
|
|
117
|
+
if (typeof namespace !== 'string' || !namespace || typeof job !== 'string' || !job) return unavailable('pod-list-invalid');
|
|
118
|
+
const identity = { context, namespace, job };
|
|
119
|
+
activeJobs.set(`${context}\0${namespace}\0${job}`, identity);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const reading = readGateHostResources({ leases, activeJobs: [...activeJobs.values()] });
|
|
123
|
+
debug.log('release-loop.gate', 'host-resource-probe', { host: selectedHost, poolContexts: selectedMembers.map(member => member.context), ...reading });
|
|
124
|
+
return reading;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function activeJobKey(job: PendingJobIdentity): string | null {
|
|
128
|
+
return typeof job?.context === 'string' && job.context.length > 0 &&
|
|
129
|
+
typeof job.namespace === 'string' && job.namespace.length > 0 &&
|
|
130
|
+
typeof job.job === 'string' && job.job.length > 0
|
|
131
|
+
? `${job.context}\0${job.namespace}\0${job.job}` : null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Read the resource ledgers as the authority for host occupancy. Process argv is deliberately not an input:
|
|
136
|
+
* unrelated commands that happen to contain `bun test` do not reserve a gate host.
|
|
137
|
+
* A Job-backed lease and its active Job are one reservation; a lease without an observed Job remains reserved.
|
|
138
|
+
*/
|
|
139
|
+
export function readGateHostResources(snapshot: GateHostResourceSnapshot): GateHostResourceReading {
|
|
140
|
+
if (snapshot.leases === null) return { status: 'unmeasurable', empty: null, reason: 'lease-ledger-unavailable' };
|
|
141
|
+
if (snapshot.activeJobs === null) return { status: 'unmeasurable', empty: null, reason: 'pod-list-unavailable' };
|
|
142
|
+
if (!Array.isArray(snapshot.leases) || snapshot.leases.some((lease) => !lease ||
|
|
143
|
+
!Number.isSafeInteger(lease.pid) || lease.pid <= 0 || typeof lease.startedAt !== 'string' || !lease.startedAt || typeof lease.at !== 'string' ||
|
|
144
|
+
(lease.stage !== undefined && lease.stage !== 'authoring' && lease.stage !== 'job') ||
|
|
145
|
+
(lease.stage === 'job' && (!lease.job || !lease.context || !lease.namespace)))) {
|
|
146
|
+
return { status: 'unmeasurable', empty: null, reason: 'lease-ledger-invalid' };
|
|
147
|
+
}
|
|
148
|
+
if (!Array.isArray(snapshot.activeJobs) || snapshot.activeJobs.some((job) => !job || activeJobKey(job) === null)) {
|
|
149
|
+
return { status: 'unmeasurable', empty: null, reason: 'pod-list-invalid' };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const jobs = new Set(snapshot.activeJobs.map(activeJobKey) as string[]);
|
|
153
|
+
// Authoring leases have no host/context yet, so they conservatively occupy each selected host in the shared pool.
|
|
154
|
+
let authoringLeases = 0;
|
|
155
|
+
let waitingJobs = 0;
|
|
156
|
+
for (const lease of snapshot.leases) {
|
|
157
|
+
if (lease.stage !== 'job') { authoringLeases++; continue; }
|
|
158
|
+
const key = lease.job && lease.context && lease.namespace
|
|
159
|
+
? activeJobKey({ job: lease.job, context: lease.context, namespace: lease.namespace }) : null;
|
|
160
|
+
if (!key || !jobs.has(key)) waitingJobs++;
|
|
161
|
+
}
|
|
162
|
+
const reservations = authoringLeases + waitingJobs + jobs.size;
|
|
163
|
+
return { status: 'measured', empty: reservations === 0, reservations, authoringLeases, waitingJobs, activeJobs: jobs.size };
|
|
164
|
+
}
|
|
165
|
+
|
|
22
166
|
const hostName = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
23
167
|
const claimsDir = (root: string) => join(root, 'release', 'gate-host-reservations');
|
|
24
168
|
|
|
@@ -1,10 +1,99 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
1
4
|
import { CliUserError } from '../cli/cli-user-error.js';
|
|
2
5
|
import { debug } from '../debug/log.js';
|
|
3
|
-
import {
|
|
6
|
+
import { releaseLedgerRoot } from '../instance/resolve.js';
|
|
7
|
+
import { readSchedule, readSchedules, releasedVersion, writeSchedule, type ScheduleRow } from './feature-store.js';
|
|
4
8
|
import { checkScheduleCeoLoad } from './placement.js';
|
|
5
9
|
|
|
6
10
|
export type ReleaseSchedule = ScheduleRow;
|
|
7
11
|
|
|
12
|
+
export interface ReleaseCutDueEvent {
|
|
13
|
+
id: string;
|
|
14
|
+
type: 'release.cut.due';
|
|
15
|
+
version: string;
|
|
16
|
+
cutAt: string;
|
|
17
|
+
at: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function newerVersion(version: string, published: string): boolean {
|
|
21
|
+
if (!published) return true;
|
|
22
|
+
const left = version.split('.').map(Number), right = published.split('.').map(Number);
|
|
23
|
+
for (let index = 0; index < 3; index++) {
|
|
24
|
+
if (left[index]! !== right[index]!) return left[index]! > right[index]!;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A scheduler tick observes due cuts; it does not directly start a release run. */
|
|
30
|
+
export function dueReleaseCutEvents(now: string, root = releaseLedgerRoot()): ReleaseCutDueEvent[] {
|
|
31
|
+
const at = Date.parse(now);
|
|
32
|
+
if (!Number.isFinite(at)) throw new Error(`invalid schedule tick time: ${now}`);
|
|
33
|
+
const published = releasedVersion(root);
|
|
34
|
+
return readSchedules(root).filter(row => {
|
|
35
|
+
const cut = Date.parse(row.cutAt);
|
|
36
|
+
return newerVersion(row.version, published) && cut <= at && at - cut < 24 * 3_600_000;
|
|
37
|
+
}).map(row => ({ id: `release.cut.due:${row.version}:${row.cutAt}`, type: 'release.cut.due' as const,
|
|
38
|
+
version: row.version, cutAt: row.cutAt, at: new Date(at).toISOString() }));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function hasReleaseRunForEvent(root: string, eventId: string): boolean {
|
|
42
|
+
const dir = join(root, 'graph-runs', 'release-loop');
|
|
43
|
+
if (!existsSync(dir)) return false;
|
|
44
|
+
for (const name of readdirSync(dir)) {
|
|
45
|
+
if (!name.endsWith('.json')) continue;
|
|
46
|
+
try {
|
|
47
|
+
const run = JSON.parse(readFileSync(join(dir, name), 'utf8')) as { input?: { triggerEvent?: { id?: string } } };
|
|
48
|
+
if (run.input?.triggerEvent?.id === eventId) return true;
|
|
49
|
+
} catch { /* Ignore a partially written run; the next scheduler tick retries. */ }
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Claim each version+cut only once across scheduler processes; a dead pending owner can be retried. */
|
|
55
|
+
export async function emitDueReleaseCutEvents(now: string, emit: (event: ReleaseCutDueEvent) => Promise<void>,
|
|
56
|
+
root = releaseLedgerRoot(), subscriptionId = 'graph:release-loop'): Promise<ReleaseCutDueEvent[]> {
|
|
57
|
+
const emitted: ReleaseCutDueEvent[] = [];
|
|
58
|
+
for (const event of dueReleaseCutEvents(now, root)) {
|
|
59
|
+
const hash = createHash('sha256').update(`${subscriptionId}\0${event.id}`).digest('hex').slice(0, 16);
|
|
60
|
+
const path = join(root, 'release', 'cut-events', `${event.version}-${hash}.json`);
|
|
61
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
62
|
+
let fd: number;
|
|
63
|
+
try { fd = openSync(path, 'wx', 0o600); }
|
|
64
|
+
catch (cause) {
|
|
65
|
+
if ((cause as NodeJS.ErrnoException).code !== 'EEXIST') throw cause;
|
|
66
|
+
let prior: { status?: string; pid?: number } = {};
|
|
67
|
+
try { prior = JSON.parse(readFileSync(path, 'utf8')) as typeof prior; } catch { /* pending write */ }
|
|
68
|
+
if (prior.status !== 'pending' || !Number.isInteger(prior.pid)) {
|
|
69
|
+
// A crash between O_EXCL creation and the first write leaves an empty claim.
|
|
70
|
+
if (Date.now() - statSync(path).mtimeMs < 60_000 || prior.status === 'emitted') continue;
|
|
71
|
+
} else {
|
|
72
|
+
try { process.kill(prior.pid!, 0); continue; }
|
|
73
|
+
catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ESRCH') continue; }
|
|
74
|
+
}
|
|
75
|
+
if (hasReleaseRunForEvent(root, event.id)) {
|
|
76
|
+
writeFileSync(path, JSON.stringify({ ...event, subscriptionId, status: 'emitted', recovered: true }) + '\n', { mode: 0o600 });
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
try { unlinkSync(path); fd = openSync(path, 'wx', 0o600); }
|
|
80
|
+
catch (error) { if ((error as NodeJS.ErrnoException).code === 'EEXIST') continue; throw error; }
|
|
81
|
+
}
|
|
82
|
+
closeSync(fd);
|
|
83
|
+
writeFileSync(path, JSON.stringify({ ...event, subscriptionId, status: 'pending', pid: process.pid }) + '\n', { mode: 0o600 });
|
|
84
|
+
try {
|
|
85
|
+
await emit(event);
|
|
86
|
+
writeFileSync(path, JSON.stringify({ ...event, subscriptionId, status: 'emitted', pid: process.pid }) + '\n', { mode: 0o600 });
|
|
87
|
+
debug.log('release.schedule', 'cut-due', { version: event.version, cutAt: event.cutAt, eventId: event.id, subscriptionId });
|
|
88
|
+
emitted.push(event);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (existsSync(path)) unlinkSync(path);
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return emitted;
|
|
95
|
+
}
|
|
96
|
+
|
|
8
97
|
/** A release landing and its representative work share the same KST day boundary. */
|
|
9
98
|
export function kstDay(utc: string): string {
|
|
10
99
|
return new Date(Date.parse(utc) + 9 * 3_600_000).toISOString().slice(0, 10);
|
package/src/repl/index.ts
CHANGED
|
@@ -41,6 +41,8 @@ import {
|
|
|
41
41
|
type UserConfig,
|
|
42
42
|
} from '../user-config.js';
|
|
43
43
|
import { setAmbientSessionId, debug } from '../debug/log.js';
|
|
44
|
+
import { buildInstalledSkillCatalogMessage, type InstalledSkillSummary } from '../dashboard/skill-catalog-preamble.js';
|
|
45
|
+
import { resolveModelContextWindow } from '../models/context-window.js';
|
|
44
46
|
import { decideSigintAction } from './sigint.js';
|
|
45
47
|
import { decideSessionStart, observeSessionStart } from '../session/session-start.js';
|
|
46
48
|
import { buildReplayTurnsFromSession } from './replay.js';
|
|
@@ -275,13 +277,39 @@ export function buildReplSystemPrompt(ctx: {
|
|
|
275
277
|
sessionId?: string | undefined;
|
|
276
278
|
/** 시험·임베디드 호출부용 시임 — 기본은 실제 홈·msg 원장·process.env. */
|
|
277
279
|
seatBootDeps?: SeatBootDeps | undefined;
|
|
280
|
+
/** Installed skill summaries are injectable for deterministic prompt tests. */
|
|
281
|
+
skillCatalog?: readonly InstalledSkillSummary[] | undefined;
|
|
282
|
+
skillCatalogContextWindow?: number | null | undefined;
|
|
278
283
|
}): string | undefined {
|
|
279
284
|
const base = ctx.enabledToolNames === undefined
|
|
280
285
|
? undefined
|
|
281
286
|
: buildAgentSystemPrompt(ctx.cfg, ctx.enabledToolNames);
|
|
287
|
+
const skillToolsEnabled = ctx.enabledToolNames?.includes('skill_exec') === true
|
|
288
|
+
&& ctx.enabledToolNames.includes('elanous_skills_list');
|
|
289
|
+
let skillCatalogText = '';
|
|
290
|
+
if (skillToolsEnabled) {
|
|
291
|
+
try {
|
|
292
|
+
const catalog = ctx.skillCatalog ?? (() => {
|
|
293
|
+
const skills = require('../skills/index.js') as typeof import('../skills/index.js');
|
|
294
|
+
return skills.applySkillFilter(skills.getSkillIndex(), ctx.cfg.skills)
|
|
295
|
+
.map(({ name, description }) => ({ name, description }));
|
|
296
|
+
})();
|
|
297
|
+
const built = buildInstalledSkillCatalogMessage(
|
|
298
|
+
catalog,
|
|
299
|
+
ctx.skillCatalogContextWindow ?? resolveModelContextWindow(ctx.cfg.llm.model),
|
|
300
|
+
);
|
|
301
|
+
skillCatalogText = built.message?.content ?? '';
|
|
302
|
+
debug.log('repl.skill-catalog', 'built', {
|
|
303
|
+
skillCount: built.skillCount, estimatedTokens: built.estimatedTokens,
|
|
304
|
+
budgetTokens: built.budgetTokens, mode: built.mode,
|
|
305
|
+
});
|
|
306
|
+
} catch (error) {
|
|
307
|
+
debug.log('repl.skill-catalog', 'failed', { reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
|
|
308
|
+
}
|
|
309
|
+
}
|
|
282
310
|
const card = buildSeatBootCardText(ctx);
|
|
283
|
-
|
|
284
|
-
return
|
|
311
|
+
const parts = [skillCatalogText, base ?? '', card].filter(part => part.length > 0);
|
|
312
|
+
return parts.length > 0 ? parts.join('\n\n') : undefined;
|
|
285
313
|
}
|
|
286
314
|
|
|
287
315
|
/** 자리 부트 카드 문면(system 메시지 0~1개를 이어 붙인 것). 자리가 아니면 ''. */
|
|
@@ -344,6 +372,7 @@ async function runOneTurn(
|
|
|
344
372
|
nextTuiDelivery?: { pending: PendingTaskNotification[] },
|
|
345
373
|
onJsonDelta?: (delta: string) => void,
|
|
346
374
|
onJsonStatus?: (line: string) => void,
|
|
375
|
+
onJsonReplace?: (fullText: string) => void,
|
|
347
376
|
): Promise<{ reply: string; provider: string; model: string | null; durationMs: number; logPath: string | null }> {
|
|
348
377
|
const startedAt = Date.now();
|
|
349
378
|
const replyChunks: string[] = [];
|
|
@@ -374,6 +403,7 @@ async function runOneTurn(
|
|
|
374
403
|
userConfig: cfg,
|
|
375
404
|
sessionId,
|
|
376
405
|
userText,
|
|
406
|
+
utteranceSurface: 'tui',
|
|
377
407
|
systemPrompt,
|
|
378
408
|
userImages: userImages.length > 0 ? userImages : undefined,
|
|
379
409
|
...(process.env.ELANOUS_TEST_FAKE_LLM === '1' && Number.isFinite(Number(process.env.ELANOUS_TEST_FAKE_LLM_IDLE_TIMEOUT_MS))
|
|
@@ -387,6 +417,14 @@ async function runOneTurn(
|
|
|
387
417
|
}
|
|
388
418
|
else process.stdout.write(d);
|
|
389
419
|
},
|
|
420
|
+
onReplaceText: (fullText) => {
|
|
421
|
+
if (jsonOutput) {
|
|
422
|
+
replyChunks.splice(0, replyChunks.length, fullText);
|
|
423
|
+
onJsonReplace?.(fullText);
|
|
424
|
+
} else {
|
|
425
|
+
process.stdout.write(`\n\n [근거 반영된 답변]\n ${fullText}\n`);
|
|
426
|
+
}
|
|
427
|
+
},
|
|
390
428
|
onStatusLine: (line) => { onJsonStatus?.(line); },
|
|
391
429
|
tools: replToolSpecs,
|
|
392
430
|
dispatchTool: tools?.dispatch,
|
|
@@ -795,6 +833,9 @@ export async function runRepl(opts: ReplOpts): Promise<number> {
|
|
|
795
833
|
process.env.ELANOUS_NEXT_TUI_STREAM === '1' && typeof turn.id === 'string'
|
|
796
834
|
? (text) => { process.stdout.write(`${JSON.stringify({ event: 'status', turnId: turn.id, text })}\n`); }
|
|
797
835
|
: undefined,
|
|
836
|
+
process.env.ELANOUS_NEXT_TUI_STREAM === '1' && typeof turn.id === 'string'
|
|
837
|
+
? (text) => { process.stdout.write(`${JSON.stringify({ event: 'replace', turnId: turn.id, text })}\n`); }
|
|
838
|
+
: undefined,
|
|
798
839
|
);
|
|
799
840
|
} catch (error) {
|
|
800
841
|
if (!backgroundBridge) throw error;
|