elanous 0.2.36 → 0.2.38
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/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
- package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 1026-44010f405704050c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
- package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 1632.7d87f998e714bede.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
- package/apps/pwa/out/_next/static/chunks/{7784.1f0ac4a16d190cf4.js → 2104.70e086d5174a4736.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6566.926a1d1b7c911442.js → 214.186a430da28338f1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
- package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 2415.738b777642a02233.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 3086.fb14b60ce98b53d3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{3148-98efd4869d660a87.js → 3124-561f7f037943cde2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
- package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 3291.f6c1005387d514bd.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
- package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
- package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 3528.e4b8ab70d339f965.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
- package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3031-85328a92fcce4da6.js → 4199-f7c6eb40cd0322f8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
- package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +90 -0
- package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
- package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
- package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
- package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 5307.d7328020227880c2.js} +4 -4
- package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
- package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
- package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5638.107314dc479e2f37.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
- package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6925.562d532110879886.js → 6493.27ad77de7aac7966.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +62 -0
- package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 7161-8f22db3ec5ed005e.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 7488.966b116789f3d41a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{4116.a84a92a2492c080e.js → 7524.ce973525d30b3d52.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
- package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 7628.6b16863ac3972333.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 7954.4f7a8832663ee979.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 8019.21ca554a821dad01.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 8487.291666583bebe640.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 8879.ac06755bcf3e44a1.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
- package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 8911.bf5e712acb25fb6c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 8994d93e.33ba491f95345fc2.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{599.c39c571b6733f2a2.js → 9223.cbcc88e0e9950426.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
- package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
- package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8037.e254fd797aa224d1.js → 9581.da63ddf41acfad46.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
- package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/{page-e7abc34a48a6f71e.js → page-291ab19fe2acb173.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/{page-c15958835534404b.js → page-6b140f77593576eb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → b7459770.6539b11860eb8a9c.js} +7 -7
- package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → b7478fef.5917716286213fcc.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +122 -0
- package/apps/pwa/out/_next/static/chunks/{2812ca6a.3b9f4a7a08885744.js → de8b930d.d94c0f42acf807fc.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → eaad0cba.771200940c529df7.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +1 -0
- package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
- 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/graphs/drafts/recipes.yaml +27 -7
- package/graphs/release/recipes.yaml +9 -0
- package/graphs/release/release-loop.yaml +26 -18
- package/graphs/work/draft-close.yaml +54 -0
- package/graphs/work/green-close.yaml +37 -0
- package/graphs/work/recipes.yaml +46 -1
- package/graphs/work/run-research.yaml +35 -0
- package/package.json +1 -1
- package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
- package/scripts/ask-op-inbox-once.ts +17 -0
- package/scripts/boundary-proof-mapping-audit.ts +88 -0
- package/scripts/brand/check.ts +13 -4
- package/scripts/codex-fallback-live-probe.ts +17 -15
- package/scripts/fleet/node-setup.sh +32 -2
- package/scripts/fleet/run-light-worker.sh +9 -0
- package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
- package/scripts/gate-0226-failure-census.ts +546 -0
- package/scripts/goals/authoring-metrics.ts +258 -0
- package/scripts/graph-units/draft-close-node.ts +222 -0
- package/scripts/hook-order-sweep.ts +7 -4
- package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
- package/scripts/land-global-checks.ts +69 -1
- package/scripts/measure-nl-routing-corpus.ts +207 -2
- package/scripts/provision-export-redactions.ts +15 -0
- package/scripts/public-copy-lint.ts +122 -0
- package/scripts/public-export.ts +69 -2
- package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
- package/scripts/ratchets/train-side-invariants.sh +7 -1
- package/scripts/release-loop/cut-branch.ts +61 -12
- package/scripts/release-loop/docs-node.ts +140 -0
- package/scripts/release-loop/gate-closure.ts +48 -0
- package/scripts/release-loop/gate-diff.ts +2 -1
- package/scripts/release-loop/gate-node.ts +161 -25
- package/scripts/release-loop/gate-partial.ts +82 -3
- package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
- package/scripts/release-loop/gate-radius-live.ts +4 -2
- package/scripts/release-loop/known-issues-node.ts +6 -4
- package/scripts/release-loop/notes-repair.ts +216 -0
- package/scripts/release-loop/prepare-node.ts +61 -5
- package/scripts/release-loop/resume-cap.ts +2 -1
- package/scripts/release-loop/resume-release.ts +406 -7
- package/scripts/release-loop/resume-test-traffic.ts +10 -0
- package/scripts/release-loop/resume.ts +13 -5
- package/scripts/release-loop/traffic-node.ts +12 -4
- package/scripts/release-loop/traffic-transition.ts +53 -13
- package/scripts/release-loop/version-node.ts +109 -15
- package/scripts/train/green-leg.ts +176 -0
- package/scripts/tui-continue-real-evidence.ts +47 -0
- package/scripts/ux-sim.ts +1 -1
- package/scripts/video-pipeline.ts +2 -2
- package/src/acp/client.ts +31 -5
- package/src/acp/core-turn-bridge.ts +12 -1
- package/src/acp/stderr-summary.ts +49 -0
- package/src/agent/monad-agent-turn.ts +1 -0
- package/src/agent/run-context.ts +1 -1
- package/src/agent/task-notification.ts +3 -1
- package/src/agent/terminal-surface.ts +217 -0
- package/src/agent-substrate/pr-reviewer.ts +11 -3
- package/src/agent-substrate/review-observation.ts +10 -0
- package/src/agent-substrate/self-review-cli.ts +537 -57
- package/src/auto-research/question-ladder-contract.ts +137 -0
- package/src/auto-research/research-turn.ts +134 -0
- package/src/autopilot/discovery/doc-lint.ts +1 -1
- package/src/autopilot/lineage/sources.ts +1 -1
- package/src/autopilot/pr-manager.ts +64 -13
- package/src/boot/daemon-runtime.ts +35 -3
- package/src/boot/daemon-tools/pty-shell.ts +2 -1
- package/src/bots/screen-probe.ts +1 -1
- package/src/budget/run-usage-rollup.ts +12 -7
- package/src/budget/unified-usage.ts +20 -0
- package/src/capture/tui-self-report.ts +42 -5
- package/src/chat/index.ts +1 -0
- package/src/chat/tool-render/dispatch.ts +8 -1
- package/src/cli/autopilot-cli.ts +24 -9
- package/src/cli/decisions-cli.ts +7 -4
- package/src/cli/doctor-cli.ts +116 -7
- package/src/cli/guardian-cli.ts +3 -1
- package/src/cli/intake-cli.ts +48 -12
- package/src/cli/lesson-cli.ts +69 -9
- package/src/cli/logs-cli.ts +357 -2
- package/src/cli/memory-cli.ts +30 -1
- package/src/cli/msg-cli.ts +15 -11
- package/src/cli/pr-granularity.ts +5 -3
- package/src/cli/pr-land-overlap-evidence.ts +38 -5
- package/src/cli/pr-land-refusal.ts +1 -1
- package/src/cli/pty-takeover-cli.ts +58 -5
- package/src/cli/release-checklist-read-cli.ts +112 -4
- package/src/cli/release-cli.ts +89 -18
- package/src/cli/review-carry.ts +77 -0
- package/src/cli/self-update.ts +24 -6
- package/src/cli/self-utterances-cli.ts +13 -16
- package/src/cli/tasks-card-show.ts +31 -1
- package/src/cli/tasks-cli.ts +370 -33
- package/src/cli/tasks-read-cli.ts +13 -5
- package/src/cli/usage-cli.ts +12 -10
- package/src/context-bus/claude-memory-import.ts +99 -0
- package/src/context-bus/context-now.ts +86 -2
- package/src/context-bus/long-term-memory.ts +125 -0
- package/src/core-turn/run-core-turn.ts +9 -2
- package/src/core-turn/run-goal-loop.ts +5 -2
- package/src/core-turn/types.ts +5 -0
- package/src/dashboard/chat/acp-chat.ts +9 -0
- package/src/dashboard/index.ts +115 -30
- package/src/dashboard/input/agent-wake.ts +43 -0
- package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
- package/src/dashboard/input/terminal-modal-router.ts +8 -159
- package/src/dashboard/replay-preview.ts +25 -0
- package/src/dashboard/side-basic-runtime.ts +61 -0
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +19 -8
- package/src/dashboard/synchronized-frame-output.ts +74 -0
- package/src/dashboard/term-slash-runtime.ts +2 -0
- package/src/dashboard/turn-preamble.ts +28 -4
- package/src/display/coordinator.ts +45 -12
- package/src/display/resize-listener.ts +41 -20
- package/src/display/synchronized-output-region.ts +60 -0
- package/src/domains/guardian-tick.ts +9 -0
- package/src/domains/surface-events.ts +80 -1
- package/src/exec-requests/planner.ts +37 -2
- package/src/execution-loop/launch-gate.ts +4 -3
- package/src/git-fs/cli-stderr.ts +45 -0
- package/src/git-fs/gh-cli.ts +6 -3
- package/src/git-fs/git-cli.ts +11 -5
- package/src/git-fs/watcher.ts +27 -22
- package/src/git-fs/worktree.ts +19 -3
- package/src/graph-runner/graph-cli.ts +26 -2
- package/src/graph-runner/graph-grow.ts +37 -9
- package/src/graph-runner/graph-run-api.ts +3 -2
- package/src/graph-runner/runner.ts +34 -7
- package/src/graph-wizard/generate.ts +29 -6
- package/src/grok/credential.ts +107 -36
- package/src/harness/harness-cli-command.ts +179 -33
- package/src/harness/review-adapter.ts +26 -6
- package/src/hq/fence-wrapper.ts +1 -1
- package/src/hq/transfer.ts +1 -1
- package/src/index.ts +151 -18
- package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
- package/src/intake-plane/collect-telegram-saved.ts +54 -5
- package/src/interactive-terminal-modal.ts +3 -0
- package/src/keybindings.ts +17 -22
- package/src/llm/provider-credentials.ts +1 -1
- package/src/llm/route-decision.ts +13 -0
- package/src/llm-tool-name.ts +37 -0
- package/src/llm-tool-schema.ts +55 -0
- package/src/llm.ts +203 -21
- package/src/loops/checker.ts +100 -0
- package/src/loops/consensus.ts +26 -2
- package/src/loops/loop-cli.ts +9 -4
- package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
- package/src/loops/orchestrator/inbox-once.ts +28 -0
- package/src/loops/orchestrator/inbox.ts +130 -1
- package/src/loops/orchestrator/tick.ts +55 -7
- package/src/maturity/feature-maturity.ts +1 -0
- package/src/model-tier/llm-tier-map.ts +12 -17
- package/src/msg/msg-store.ts +17 -0
- package/src/native-tool-catalog.ts +1 -1
- package/src/nexus/api/channel-ask-op.ts +96 -0
- package/src/nexus/api/discord-trigger-bot.ts +28 -1
- package/src/nexus/api/graph-wizard-api.ts +27 -2
- package/src/nexus/api/grid.ts +24 -4
- package/src/nexus/api/http-server.ts +1 -1
- package/src/nexus/api/ops-api.ts +14 -6
- package/src/nexus/api/telegram-trigger-bot.ts +24 -0
- package/src/nexus/api/terminals.ts +28 -6
- package/src/nexus/state/state.ts +7 -1
- package/src/oauth/codex-account-store.ts +34 -1
- package/src/ops/loops-map.ts +46 -0
- package/src/ops/overview-cache.ts +22 -4
- package/src/ops/overview.ts +41 -5
- package/src/patents/ledger.ts +18 -1
- package/src/policy/llm-policy.ts +3 -1
- package/src/preview/terminal.ts +4 -2
- package/src/prompt-cache/anthropic.ts +2 -0
- package/src/prompt-enhance/enhance.ts +9 -4
- package/src/pty-shell/availability.ts +7 -0
- package/src/pty-shell/herdr-agent-report.ts +40 -31
- package/src/pty-shell/herdr-prune-stale.ts +17 -0
- package/src/pty-shell/herdr-sequence-lease.ts +60 -0
- package/src/pty-shell/pty-control-ipc.ts +187 -18
- package/src/pty-shell/pty-manifest.ts +16 -2
- package/src/pty-shell/registry.ts +25 -15
- package/src/pty-shell/tui-run-state.ts +235 -1
- package/src/release-loop/checklist.ts +50 -5
- package/src/release-loop/feature-store.ts +9 -9
- package/src/release-loop/gate-shards.ts +61 -0
- package/src/release-loop/landed-but-yellow.ts +93 -12
- package/src/release-loop/light-rc.ts +7 -4
- package/src/release-loop/rehearsal.ts +1 -1
- package/src/repl/index.ts +18 -0
- package/src/research/axis-fanout.ts +133 -0
- package/src/research/edge-decision.ts +88 -0
- package/src/research/output-router.ts +127 -0
- package/src/research-bridge/format.ts +16 -1
- package/src/research-bridge/index.ts +1 -0
- package/src/research-bridge/invoke.ts +41 -5
- package/src/seat-loop/seat-report.ts +1 -0
- package/src/self-dev/ask-launch-flow.ts +86 -10
- package/src/self-dev/decompose-proposal.ts +29 -18
- package/src/self-dev/decompose.ts +45 -9
- package/src/self-dev/dev-pipeline.ts +29 -7
- package/src/self-dev/draft-residue.ts +221 -2
- package/src/self-dev/draft-sweep.ts +254 -16
- package/src/self-dev/draft-triage-rules.ts +19 -5
- package/src/self-dev/orchestrate.ts +1 -0
- package/src/self-dev/review-provider-fallback.ts +45 -7
- package/src/self-dev/run-supervisor.ts +22 -7
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-run.ts +310 -6
- package/src/self-implement/comment-only-source.ts +54 -0
- package/src/self-implement/doctor-visit.ts +108 -0
- package/src/self-implement/gate-artifacts.ts +6 -2
- package/src/self-implement/gate-baseline.ts +99 -1
- package/src/self-implement/gate-cli.ts +231 -82
- package/src/self-implement/gate-failure-signature.ts +44 -0
- package/src/self-implement/gate-remote.ts +30 -4
- package/src/self-implement/gate-scope.ts +13 -1
- package/src/self-implement/goal-author.ts +407 -21
- package/src/self-implement/goal-doc/section.ts +22 -0
- package/src/self-implement/goal-supervisor-fill.ts +110 -27
- package/src/self-implement/importer-test-index.ts +215 -2
- package/src/self-implement/knowhow-pack.ts +125 -12
- package/src/self-implement/l8-merge-queue.ts +198 -32
- package/src/self-implement/off-diff-evidence.ts +23 -0
- package/src/self-implement/orchestrator.ts +369 -33
- package/src/self-implement/pod-inplace-worktree.ts +82 -0
- package/src/self-implement/pod-warm-pool-profile.ts +2 -2
- package/src/self-implement/premise-review.ts +7 -5
- package/src/self-implement/review-round-brief.ts +300 -0
- package/src/self-implement/rework-policy.ts +14 -0
- package/src/self-implement/run-ledger.ts +428 -6
- package/src/self-implement/run-stop.ts +1 -1
- package/src/self-implement/running-runs.ts +17 -3
- package/src/self-implement/seams.ts +45 -16
- package/src/self-implement/self-implement-cli.ts +26 -2
- package/src/self-implement/stop-autoheal.ts +1 -0
- package/src/self-implement/test-seams.ts +13 -1
- package/src/self-implement/train-reach-grouping.ts +8 -2
- package/src/session/channel-ask-op-envelope.ts +36 -0
- package/src/session/channel-op-reply-route.ts +200 -0
- package/src/session/chat.ts +10 -1
- package/src/session/id-prefix.ts +60 -0
- package/src/session/index.ts +6 -0
- package/src/session-runtime/index.ts +18 -23
- package/src/skills/runner.ts +7 -3
- package/src/skills/tools/dev-harness.ts +2 -2
- package/src/skills/tools/pty.ts +5 -0
- package/src/skills/tools/schedule-wakeup.ts +1 -6
- package/src/status/bar.ts +3 -3
- package/src/status/metrics.ts +12 -1
- package/src/steward/rejudge-tick.ts +12 -5
- package/src/steward/resync-tick.ts +31 -4
- package/src/storage/file-lock.ts +17 -4
- package/src/task-agent/actions.ts +199 -4
- package/src/task-agent/adopt-pr.ts +63 -2
- package/src/task-agent/boundary-proof-mapping.ts +12 -0
- package/src/task-agent/boundary-proof-producer.ts +147 -0
- package/src/task-agent/completion-evidence.ts +2 -1
- package/src/task-agent/evidence-command-normalize.ts +42 -0
- package/src/task-agent/export-redactions-provision.ts +43 -0
- package/src/task-agent/green-close-recipe.ts +239 -0
- package/src/task-agent/green-sweep.ts +64 -10
- package/src/task-agent/live-moves.ts +48 -3
- package/src/task-agent/map-host-adapter.ts +134 -0
- package/src/task-agent/map-reduce.ts +158 -0
- package/src/task-agent/map-run-ledger.ts +226 -0
- package/src/task-agent/parent-host.ts +74 -17
- package/src/task-agent/rejudge-on-head.ts +72 -5
- package/src/task-agent/repair-cycle.ts +108 -8
- package/src/task-agent/repair-next-move.ts +12 -2
- package/src/task-agent/repair-worker.ts +37 -1
- package/src/task-agent/review-prior-fix.ts +12 -2
- package/src/task-agent/shadow.ts +188 -5
- package/src/task-agent/task-hand.ts +253 -20
- package/src/task-agent/task-parent-role-llm.ts +9 -0
- package/src/task-agent/tier-split.ts +40 -5
- package/src/task-agent/work-order.ts +53 -2
- package/src/task-orchestrator/dispatcher.ts +46 -1
- package/src/task-orchestrator/generator-prompt.ts +6 -0
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +31 -4
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
- package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
- package/src/task-orchestrator/surfaces/pod-pool.ts +77 -8
- package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +338 -79
- package/src/task-orchestrator/surfaces/self-implement.ts +37 -2
- package/src/terminal/session-registry.ts +1 -0
- package/src/terminal/terminal-modal-router.ts +156 -0
- package/src/testing/linux-env.ts +177 -0
- package/src/tool-hints/gate.ts +6 -4
- package/src/tool-hints/signals.ts +33 -1
- package/src/tui/chat/background-job-status.ts +8 -2
- package/src/tui/chat/goal-interim.ts +5 -1
- package/src/tui/entry.ts +722 -30
- package/src/tui/input/at-picker.ts +55 -0
- package/src/tui/sidetab/attach.ts +304 -0
- package/src/tui/sidetab/list.ts +176 -0
- package/src/tui/sidetab/nl-tool.ts +136 -0
- package/src/tui/slash/resume-command.ts +23 -0
- package/src/tui/slash/resume.ts +38 -35
- package/src/tui/slash/signals.ts +114 -0
- package/src/tui/slash/term-next.ts +72 -0
- package/src/tui-client/local-chat-turn.ts +31 -9
- package/src/user-config.ts +30 -3
- package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
- package/src/ux-sim/classic-tui-seat-scenarios.ts +158 -4
- package/src/ux-sim/fake-gh.ts +174 -0
- package/src/ux-sim/fake-kubectl.ts +142 -0
- package/src/ux-sim/fake-llm.ts +17 -6
- package/src/ux-sim/next-tui-seat-scenarios.ts +176 -6
- package/src/ux-sim/resume-picker-device.ts +173 -0
- package/src/ux-sim/session-id-seed.ts +60 -0
- package/src/ux-sim/skills-tools-shell-device.ts +156 -0
- package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
- package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
- package/src/version/packed-revision.json +1 -1
- package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +0 -287
- package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/190.285c832bd9626f8c.js +0 -64
- package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +0 -36
- package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +0 -149
- package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +0 -24
- package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +0 -24
- package/apps/pwa/out/_next/static/chunks/2986.45d7652e4f13557e.js +0 -2
- package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +0 -226
- package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +0 -8
- package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +0 -32
- package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +0 -286
- package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +0 -1
- package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3757-180308bc61021b05.js +0 -1
- package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
- package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +0 -104
- package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +0 -148
- package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +0 -93
- package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +0 -122
- package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +0 -79
- package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6466-92e65a48490b68a9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +0 -1
- package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +0 -27
- package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +0 -1
- package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7481.39f7a4654907bf6e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7891.03f910124a737985.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +0 -1
- package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +0 -62
- package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +0 -90
- package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +0 -94
- package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +0 -77
- package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9514.131c52cc75fe6439.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-e2de2e59111c9aad.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2af16e62c12f22df.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ccae1c4b-0cf414f5eff1b10d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +0 -1
- package/scripts/migrate-monad-to-elanous.ts +0 -195
- package/scripts/rebrand-elanous.ts +0 -242
- /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
|
@@ -23,6 +23,8 @@ import { getSessionCwd } from '../session/working-dir.js';
|
|
|
23
23
|
import { buildPtyEnv } from '../agent/identity-env.js';
|
|
24
24
|
import { getCurrentPtyId } from '../agent/pty-identity.js';
|
|
25
25
|
import { bunNativePtyAvailable, bunSpawnPty } from './bun-native-pty.js';
|
|
26
|
+
import { ptyAvailable } from './availability.js';
|
|
27
|
+
export { ptyAvailable } from './availability.js';
|
|
26
28
|
import { resolvePtyRef, canTransitionAccessMode, ptyIdSeparatorIndex, type PtyAccessMode, type PtyTransitionPolicy } from './pty-ref.js';
|
|
27
29
|
import { resolveWriteDecision, resolveTakeover, type PtyWriteActor } from './pty-write-arbiter.js';
|
|
28
30
|
import { addPtyManifestOutputBytes, upsertPtyManifest, updatePtyManifestSnapshot, updatePtyManifestNickname, markPtyManifestClosed, removePtyManifest, touchLivePtyManifest } from './pty-manifest.js';
|
|
@@ -513,7 +515,7 @@ export function startPty(opts: StartOpts): PtyHandle {
|
|
|
513
515
|
set nickname(v: string | undefined) { nickname = v; },
|
|
514
516
|
setNickname(name: string): void {
|
|
515
517
|
nickname = name.trim() || undefined;
|
|
516
|
-
if (
|
|
518
|
+
if (ptyManifestEnabled()) updatePtyManifestNickname(id, nickname, Date.now());
|
|
517
519
|
},
|
|
518
520
|
get accessMode() { return accessMode; },
|
|
519
521
|
set accessMode(v: PtyAccessMode) { accessMode = v; },
|
|
@@ -718,7 +720,7 @@ export function startPty(opts: StartOpts): PtyHandle {
|
|
|
718
720
|
catch (error) { debug.log('pty.record', 'tap-error', { ptyId: id, error: String(error) }); }
|
|
719
721
|
emitPtyEvent({ type: 'output', id, chunk });
|
|
720
722
|
// ★ 크로스-프로세스 관측(2026-07-23) — throttled 스냅샷을 공유 매니페스트에(데몬 PWA 유니온). getter 라 throttle 통과 시에만 snapshot().
|
|
721
|
-
if (
|
|
723
|
+
if (ptyManifestEnabled()) {
|
|
722
724
|
pendingManifestOutputBytes += Buffer.byteLength(chunk, 'utf8');
|
|
723
725
|
const now = Date.now();
|
|
724
726
|
// ⛔⭐ throttle 이 막은 출력도 «반드시» 실린다 — 안 그러면 마지막 버스트 뒤 조용해진 PTY 의
|
|
@@ -741,7 +743,7 @@ export function startPty(opts: StartOpts): PtyHandle {
|
|
|
741
743
|
try { autoStopPtyRecording(id); }
|
|
742
744
|
catch (error) { debug.log('pty.record', 'auto-stop-error', { ptyId: id, error: String(error) }); }
|
|
743
745
|
emitPtyEvent({ type: 'exit', id, exitCode: code, signal });
|
|
744
|
-
if (
|
|
746
|
+
if (ptyManifestEnabled()) {
|
|
745
747
|
const now = Date.now();
|
|
746
748
|
// Manifest closure and output durability are separate: a closed row keeps retrying trailing bytes until committed.
|
|
747
749
|
manifestOutputFlush.close(now);
|
|
@@ -754,7 +756,7 @@ export function startPty(opts: StartOpts): PtyHandle {
|
|
|
754
756
|
// ★ 크로스-프로세스 관측 — startPty 를 공유 매니페스트에 등록(다른 프로세스 데몬이 /v1/terminals 로 봄). fail-soft.
|
|
755
757
|
// ⚠️ 테스트 런(NODE_ENV=test·bun test)은 skip — 테스트가 띄우는 임시 셸(self-implement gate·CI·수동 bun test)이
|
|
756
758
|
// 운영 매니페스트(~/.elanous/pty)로 새어들어 관측소를 오염시키던 근본 차단(격리). 실 세션(NODE_ENV≠test)만 등록.
|
|
757
|
-
if (
|
|
759
|
+
if (ptyManifestEnabled()) {
|
|
758
760
|
const childSpaceId = opts.env?.ELANOUS_HARNESS_SPACE_ID;
|
|
759
761
|
const childParentPtyId = opts.env?.ELANOUS_PARENT_PTY_ID ?? getCurrentPtyId();
|
|
760
762
|
const childController = opts.env?.ELANOUS_CONTROLLER?.trim();
|
|
@@ -800,8 +802,24 @@ export function startPty(opts: StartOpts): PtyHandle {
|
|
|
800
802
|
return handle;
|
|
801
803
|
}
|
|
802
804
|
|
|
803
|
-
/** 공유 PTY 매니페스트 등록 활성 여부 — 테스트 런(bun test=NODE_ENV=test)은 운영 매니페스트 오염 방지 위해 off.
|
|
804
|
-
|
|
805
|
+
/** 공유 PTY 매니페스트 등록 활성 여부 — 테스트 런(bun test=NODE_ENV=test)은 운영 매니페스트 오염 방지 위해 off.
|
|
806
|
+
*
|
|
807
|
+
* ⭐ 자리(seat) 수명주기는 이 기록자에서만 원장에 실린다 — spawned/exited 사건의 seat·
|
|
808
|
+
* 누적 outputBytesTotal·exitCode 를 남기는 곳이 `upsertPtyManifest`/`markPtyManifestClosed` 이기
|
|
809
|
+
* 때문이다. 그런데 NODE_ENV 판정만 있으면 **격리 test 우주에서는 이 경로를 한 번도 지날 수 없어**
|
|
810
|
+
* 자리 수명주기가 실행 증거를 가질 수 없다(합성 manifest 직접 호출만 남는다 — 완료 경계가 금지).
|
|
811
|
+
* ⇒ 판정을 호출 시점 함수로 두고, 격리 우주(전용 `ELANOUS_STATE_DIR`·전용 manifest db)가 **명시적으로**
|
|
812
|
+
* 켤 수 있는 seam 을 둔다. override 가 없으면 종전과 같은 NODE_ENV 판정이라 운영 동작은 불변이다. */
|
|
813
|
+
let _ptyManifestEnabledOverride: boolean | null = null;
|
|
814
|
+
|
|
815
|
+
/** 테스트 전용 seam — 격리 우주에서 생산 기록 경로를 그대로 지나기 위해 켠다. null = NODE_ENV 판정 복귀. */
|
|
816
|
+
export function setPtyManifestEnabledForTesting(enabled: boolean | null): void {
|
|
817
|
+
_ptyManifestEnabledOverride = enabled;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
function ptyManifestEnabled(): boolean {
|
|
821
|
+
return _ptyManifestEnabledOverride ?? process.env.NODE_ENV !== 'test';
|
|
822
|
+
}
|
|
805
823
|
|
|
806
824
|
// ★ 라이브 PTY 하트비트(2026-07-23) — 소유 프로세스가 자기 라이브 PTY 의 updated_at 을 주기 갱신해
|
|
807
825
|
// "살아있음"을 증명한다. 데몬의 stale reap 이 하트비트 끊긴 유령만 제거하도록(pid 재활용 견고). unref 로 프로세스 종료 방해 X.
|
|
@@ -904,7 +922,7 @@ export function renamePty(id: string, nickname: string): boolean {
|
|
|
904
922
|
// 별명은 manifest 행에만 산다. 여기서 받지 않으면 IPC rename 이 그 행에 `unknown-pty` 로 진다.
|
|
905
923
|
const target = controlTargets.get(id);
|
|
906
924
|
if (!target || !target.isAlive()) return false;
|
|
907
|
-
if (
|
|
925
|
+
if (ptyManifestEnabled()) updatePtyManifestNickname(id, nickname.trim() || undefined, Date.now());
|
|
908
926
|
debug.log('pty.rename', 'control-target-renamed', { ptyId: id, nickname: nickname.trim() });
|
|
909
927
|
return true;
|
|
910
928
|
}
|
|
@@ -1012,14 +1030,6 @@ export function killNonDetached(): number {
|
|
|
1012
1030
|
return killed;
|
|
1013
1031
|
}
|
|
1014
1032
|
|
|
1015
|
-
/** Probe-compatible. Under Bun the native PTY (Bun.spawn terminal) is
|
|
1016
|
-
* used instead of node-pty, so PTY is available even if node-pty can't
|
|
1017
|
-
* resolve. Under node we still require node-pty. */
|
|
1018
|
-
export function ptyAvailable(): boolean {
|
|
1019
|
-
if (bunNativePtyAvailable()) return true;
|
|
1020
|
-
try { require.resolve('node-pty'); return true; } catch { return false; }
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
1033
|
// ─── Adapter wiring ──────────────────────────────────────────────
|
|
1024
1034
|
|
|
1025
1035
|
let cachedSpawn: ((opts: StartOpts) => PtyAdapter) | null | undefined = undefined;
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// `reportTuiTurn` 을 부른다. 기록 실패는 `debug.log('pty.tui-state', …)` — 조용히 삼키지 않는다.
|
|
12
12
|
// 판독(CLI 쪽): `describePtyRunState` 가 행 ⊕ 설치본 기록 ⊕ (체크아웃이면) 그 뿌리의 HEAD 로 판정한다.
|
|
13
13
|
|
|
14
|
+
import { spawn } from 'node:child_process';
|
|
14
15
|
import { readFileSync } from 'node:fs';
|
|
15
16
|
import { homedir } from 'node:os';
|
|
16
17
|
import { dirname, join, resolve } from 'node:path';
|
|
@@ -307,6 +308,144 @@ export function formatTurnCell(cell: PtyTurnCell): string {
|
|
|
307
308
|
return `${cell.state},${cell.sinceSec === null ? '?' : cell.sinceSec}s`;
|
|
308
309
|
}
|
|
309
310
|
|
|
311
|
+
// ── H9 자기 재기동 — «재기동 필요» ∧ 유휴 ∧ 사람 입력 없음 ⇒ 스스로 재기동 ──
|
|
312
|
+
//
|
|
313
|
+
// 정본: seat-state/OPC/TUI-HOMEOSTASIS-SLICES-2026-10-16.md (TUI-H9-IDLE-SELF-RESTART).
|
|
314
|
+
// 판정(`decideSelfRestart`)은 순수 함수 — 실제 «새 세션 ⊕ 자리 맥락 재주입» 은 주입된 수행자(`restart`)가 한다.
|
|
315
|
+
// 낡음 판정은 기존 `BuildStaleness` 를 그대로 재사용한다(판정·문면을 두벌로 만들지 않는다).
|
|
316
|
+
// 사람 입력 대기 신호는 입력 축(대시보드)이 준다 — 이 모듈은 입력 큐를 소유하지 않는다.
|
|
317
|
+
|
|
318
|
+
/** 유휴 유예: 이만큼 조용했을 때만 재기동한다 — 턴 사이 «쉼»에서 세션을 새로 띄우지 않는다. */
|
|
319
|
+
export const DEFAULT_SELF_RESTART_IDLE_MS = 90_000;
|
|
320
|
+
|
|
321
|
+
export type SelfRestartReason =
|
|
322
|
+
| 'stale-idle-no-input'
|
|
323
|
+
| 'not-stale'
|
|
324
|
+
| 'staleness-unknown'
|
|
325
|
+
| 'turn-busy'
|
|
326
|
+
| 'turn-unknown'
|
|
327
|
+
| 'still-warm'
|
|
328
|
+
| 'human-input-pending';
|
|
329
|
+
|
|
330
|
+
export interface SelfRestartDecisionDeps {
|
|
331
|
+
/** 재기동 필요인가 — 미지(null)면 재기동하지 않는다. */
|
|
332
|
+
readonly stale: boolean | null;
|
|
333
|
+
readonly staleReason?: BuildStaleReason;
|
|
334
|
+
readonly turn: PtyTurnView;
|
|
335
|
+
/** 지금 턴 상태에 머문 시간(ms) — 모르면 null. */
|
|
336
|
+
readonly idleMs: number | null;
|
|
337
|
+
readonly humanInputPending: boolean;
|
|
338
|
+
readonly minIdleMs?: number;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export interface SelfRestartDecision {
|
|
342
|
+
readonly restart: boolean;
|
|
343
|
+
readonly reason: SelfRestartReason;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/** 판정선: 세 조건(재기동 필요 · 유휴 · 사람 입력 없음)이 모두 참일 때만 참. 거짓인 첫 조건을 이유로 낸다. */
|
|
347
|
+
export function decideSelfRestart(deps: SelfRestartDecisionDeps): SelfRestartDecision {
|
|
348
|
+
if (deps.stale === null) return { restart: false, reason: 'staleness-unknown' };
|
|
349
|
+
if (!deps.stale) return { restart: false, reason: 'not-stale' };
|
|
350
|
+
if (deps.turn === 'busy') return { restart: false, reason: 'turn-busy' };
|
|
351
|
+
if (deps.turn === 'unknown') return { restart: false, reason: 'turn-unknown' };
|
|
352
|
+
const minIdleMs = deps.minIdleMs ?? DEFAULT_SELF_RESTART_IDLE_MS;
|
|
353
|
+
if (deps.idleMs === null || deps.idleMs < minIdleMs) return { restart: false, reason: 'still-warm' };
|
|
354
|
+
if (deps.humanInputPending) return { restart: false, reason: 'human-input-pending' };
|
|
355
|
+
return { restart: true, reason: 'stale-idle-no-input' };
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/** 재기동 계획 — 새 세션 ⊕ 자리 맥락 재주입 명령까지. 세션 id 를 모르면 명령은 null(판정 근거는 남긴다). */
|
|
359
|
+
export interface TuiSelfRestartPlan {
|
|
360
|
+
readonly surfaceId: string;
|
|
361
|
+
readonly staleReason: BuildStaleReason;
|
|
362
|
+
readonly idleMs: number;
|
|
363
|
+
readonly relaunchCommand: string | null;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export interface TuiSelfRestartDeps {
|
|
367
|
+
/** 낡음 판정 재료 — 생략하면 이 프로세스의 기동 판 ⊕ 설치본 ⊕ 체크아웃 HEAD 로 잰다. */
|
|
368
|
+
readonly staleness?: () => BuildStaleness;
|
|
369
|
+
/** 사람이 지금 입력 중인가 — 생략하면 «모름» 으로 보고 재기동하지 않는다(조용한 세션을 뺏지 않는다). */
|
|
370
|
+
readonly humanInputPending?: () => boolean;
|
|
371
|
+
readonly sessionId?: string;
|
|
372
|
+
/**
|
|
373
|
+
* 지금 이 TUI 가 «소유한» 세션 — 틱마다 다시 읽어 `sessionId` 보다 우선한다.
|
|
374
|
+
* 대화가 갈아 끼워지는 TUI 는 기동 시점 값을 고정할 수 없어 이 칸을 쓴다(읽기 실패 → null → 재기동 안 함).
|
|
375
|
+
*/
|
|
376
|
+
readonly readSessionId?: () => string | null;
|
|
377
|
+
readonly minIdleMs?: number;
|
|
378
|
+
readonly intervalMs?: number;
|
|
379
|
+
/** 실제 재기동 수행자(새 세션 ⊕ 자리 맥락 재주입). 생략 시 설치본 `elanous --resume <세션>`. */
|
|
380
|
+
readonly restart?: (plan: TuiSelfRestartPlan) => void;
|
|
381
|
+
/**
|
|
382
|
+
* 낡은 TUI 가 좌석을 «놓는» 동작 — 새 세션을 띄우기 직전에 부른다.
|
|
383
|
+
* 생략해도 이 녹음기는 그 좌석 행 쓰기를 스스로 놓는다(두 TUI 가 한 좌석을 겹쳐 쓰지 않게).
|
|
384
|
+
*/
|
|
385
|
+
readonly yieldSeat?: (plan: TuiSelfRestartPlan) => void;
|
|
386
|
+
/** 유휴 감시 등록 — 틱을 받아 해제 함수를 준다. 생략 시 unref 된 setInterval. */
|
|
387
|
+
readonly watch?: (tick: () => void) => () => void;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const stalenessFromRunningBuild = (): BuildStaleness => {
|
|
391
|
+
const build = runningBuild();
|
|
392
|
+
const installed = readCurrentInstallRecord();
|
|
393
|
+
let checkoutHead: string | undefined;
|
|
394
|
+
if (build.source === 'checkout' && build.codeRoot) checkoutHead = readCheckoutHead(build.codeRoot);
|
|
395
|
+
return judgeBuildStaleness({ build, installed, ...(checkoutHead ? { checkoutHead } : {}) });
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
const defaultWatch = (tick: () => void, intervalMs: number): (() => void) => {
|
|
399
|
+
const timer = setInterval(tick, intervalMs);
|
|
400
|
+
(timer as unknown as { unref?: () => void }).unref?.();
|
|
401
|
+
return () => { clearInterval(timer); };
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
/** 재기동 인자: 새 세션은 `--resume <세션>` 으로 그 좌석의 자리 맥락을 다시 받는다. */
|
|
405
|
+
export const TUI_RELAUNCH_FLAG = '--resume';
|
|
406
|
+
|
|
407
|
+
export interface TuiRelaunchChild {
|
|
408
|
+
on(event: 'error', listener: (error: Error) => void): unknown;
|
|
409
|
+
on(event: 'spawn', listener: () => void): unknown;
|
|
410
|
+
unref(): void;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/** 프로세스 띄우기 seam — 무대는 여기만 가짜로 바꿔 «생산 argv·옵션» 을 그대로 지난다. */
|
|
414
|
+
export type TuiRelaunchSpawn = (
|
|
415
|
+
command: string,
|
|
416
|
+
args: readonly string[],
|
|
417
|
+
options: { detached: boolean; stdio: 'ignore' },
|
|
418
|
+
) => TuiRelaunchChild;
|
|
419
|
+
|
|
420
|
+
const defaultRelaunchSpawn: TuiRelaunchSpawn = (command, args, options) =>
|
|
421
|
+
spawn(command, args, options) as unknown as TuiRelaunchChild;
|
|
422
|
+
|
|
423
|
+
let relaunchSpawn: TuiRelaunchSpawn = defaultRelaunchSpawn;
|
|
424
|
+
|
|
425
|
+
/** 무대용 spawn 교체 — 인자 없이 부르면 생산 기본값(spawn)으로 되돌린다. */
|
|
426
|
+
export function setTuiRelaunchSpawnForTesting(next?: TuiRelaunchSpawn): void {
|
|
427
|
+
relaunchSpawn = next ?? defaultRelaunchSpawn;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/** 기본 재기동 수행자: 설치본 `elanous --resume <세션>` — 새 세션이 그 좌석의 자리 맥락으로 다시 뜬다. */
|
|
431
|
+
export const spawnTuiRelaunch = (sessionId: string): Promise<void> => {
|
|
432
|
+
return new Promise<void>((resolve, reject) => {
|
|
433
|
+
const child = relaunchSpawn(process.env.ELANOUS_BIN || 'elanous', [TUI_RELAUNCH_FLAG, sessionId], { detached: true, stdio: 'ignore' });
|
|
434
|
+
let settled = false;
|
|
435
|
+
child.on('error', (error: Error) => {
|
|
436
|
+
if (settled) return;
|
|
437
|
+
settled = true;
|
|
438
|
+
reject(error);
|
|
439
|
+
});
|
|
440
|
+
child.on('spawn', () => {
|
|
441
|
+
if (settled) return;
|
|
442
|
+
settled = true;
|
|
443
|
+
child.unref();
|
|
444
|
+
resolve();
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
};
|
|
448
|
+
|
|
310
449
|
// ── 기록(TUI) ──
|
|
311
450
|
|
|
312
451
|
export interface TuiRunStateRecorderDeps {
|
|
@@ -326,6 +465,11 @@ export interface TuiRunStateRecorderDeps {
|
|
|
326
465
|
* 생략 시: 기본 신고기(herdr 미주입)일 때만 실 `process` · 주입 herdr 는 지킴이 0. `null` 이면 안 건다.
|
|
327
466
|
*/
|
|
328
467
|
readonly signals?: HerdrSignalTarget | null;
|
|
468
|
+
/**
|
|
469
|
+
* H9 자기 재기동(낡은 판 ∧ 유휴 ∧ 사람 입력 없음 ⇒ 새 세션 ⊕ 자리 맥락 재주입).
|
|
470
|
+
* 생략하면 감시를 안 건다 — 이 축을 켜는 것은 호출자(생산 진입점)의 결정이다.
|
|
471
|
+
*/
|
|
472
|
+
readonly selfRestart?: TuiSelfRestartDeps;
|
|
329
473
|
}
|
|
330
474
|
|
|
331
475
|
interface ActiveRecorder {
|
|
@@ -336,6 +480,8 @@ interface ActiveRecorder {
|
|
|
336
480
|
readonly herdr: HerdrAgentReporterLike | null;
|
|
337
481
|
/** manifest 에 실제로 적힌 마지막 턴. 실패면 안 바뀐다(재시도). */
|
|
338
482
|
last?: PtyTurnState;
|
|
483
|
+
/** idle 로 «바뀐» 시각 — 유휴 경과의 0초. busy 로 가면 다시 모른다. */
|
|
484
|
+
idleSince?: number;
|
|
339
485
|
/** herdr 에 마지막으로 알린 턴. manifest 성패와 따로 둔다. */
|
|
340
486
|
herdrLast?: PtyTurnState;
|
|
341
487
|
}
|
|
@@ -366,6 +512,88 @@ export function startTuiRunStateRecorder(surfaceId: string, deps: TuiRunStateRec
|
|
|
366
512
|
active = recorder;
|
|
367
513
|
writeTurnState(recorder, 'idle');
|
|
368
514
|
if (herdr) { try { herdr.start(); } catch { /* 신고 실패가 녹음기를 깨지 않는다 */ } }
|
|
515
|
+
// H9 유휴 감시: 판·턴·사람 입력을 매 틱 다시 재고, 재기동 성공 뒤에만 좌석을 양도한다.
|
|
516
|
+
const selfRestart = deps.selfRestart;
|
|
517
|
+
let unwatch: () => void = () => {};
|
|
518
|
+
if (selfRestart) {
|
|
519
|
+
const minIdleMs = selfRestart.minIdleMs ?? DEFAULT_SELF_RESTART_IDLE_MS;
|
|
520
|
+
const restartedFor = new Set<BuildStaleReason>();
|
|
521
|
+
let restartInFlight = false;
|
|
522
|
+
const tick = (): void => {
|
|
523
|
+
if (active !== recorder) return;
|
|
524
|
+
let staleness: BuildStaleness;
|
|
525
|
+
try { staleness = (selfRestart.staleness ?? stalenessFromRunningBuild)(); } catch (error) {
|
|
526
|
+
log('self-restart-staleness-failed', { ptyId: surfaceId, error: error instanceof Error ? error.message : String(error) });
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
// 사람 입력 신호가 없거나 읽을 수 없으면 모름으로 닫는다 — 명시적 false만 «사람 입력 없음»이다.
|
|
530
|
+
let humanInputPending = true;
|
|
531
|
+
if (selfRestart.humanInputPending) {
|
|
532
|
+
try { humanInputPending = selfRestart.humanInputPending() !== false; } catch { humanInputPending = true; }
|
|
533
|
+
}
|
|
534
|
+
// 재기동은 «지금 이 TUI 가 보여 주는 대화» 로만 잇는다 — 읽기 실패는 null(대체 세션을 지어내지 않는다).
|
|
535
|
+
let sessionId: string | null = selfRestart.sessionId ?? null;
|
|
536
|
+
if (selfRestart.readSessionId) {
|
|
537
|
+
try { sessionId = selfRestart.readSessionId(); } catch { sessionId = null; }
|
|
538
|
+
}
|
|
539
|
+
const idleMs = recorder.idleSince === undefined ? null : Math.max(0, now() - recorder.idleSince);
|
|
540
|
+
const decision = decideSelfRestart({
|
|
541
|
+
stale: staleness.stale,
|
|
542
|
+
staleReason: staleness.reason,
|
|
543
|
+
turn: recorder.last ?? 'unknown',
|
|
544
|
+
idleMs,
|
|
545
|
+
humanInputPending,
|
|
546
|
+
minIdleMs,
|
|
547
|
+
});
|
|
548
|
+
if (!decision.restart || restartedFor.has(staleness.reason) || restartInFlight) return;
|
|
549
|
+
if (!sessionId) {
|
|
550
|
+
log('self-restart-no-session', { ptyId: surfaceId, staleReason: staleness.reason });
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
const plan: TuiSelfRestartPlan = {
|
|
554
|
+
surfaceId,
|
|
555
|
+
staleReason: staleness.reason,
|
|
556
|
+
idleMs: idleMs ?? 0,
|
|
557
|
+
relaunchCommand: sessionId ? buildStaleInstallRelaunchCommand(sessionId) : null,
|
|
558
|
+
};
|
|
559
|
+
log('self-restart', { ptyId: surfaceId, reason: decision.reason, staleReason: plan.staleReason, idleMs: plan.idleMs, relaunchCommand: plan.relaunchCommand });
|
|
560
|
+
restartInFlight = true;
|
|
561
|
+
const handoff = (): void => {
|
|
562
|
+
// 새 세션이 실제로 생성된 뒤에만 낡은 TUI 가 좌석 행 쓰기를 놓는다.
|
|
563
|
+
if (selfRestart.yieldSeat) {
|
|
564
|
+
try {
|
|
565
|
+
selfRestart.yieldSeat(plan);
|
|
566
|
+
} catch (error) {
|
|
567
|
+
log('self-restart-yield-failed', { ptyId: surfaceId, error: error instanceof Error ? error.message : String(error) });
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
if (active === recorder) active = null;
|
|
571
|
+
restartedFor.add(staleness.reason);
|
|
572
|
+
restartInFlight = false;
|
|
573
|
+
log('self-restart-handover', { ptyId: surfaceId, staleReason: plan.staleReason, relaunchCommand: plan.relaunchCommand });
|
|
574
|
+
};
|
|
575
|
+
const failed = (error: unknown): void => {
|
|
576
|
+
restartInFlight = false;
|
|
577
|
+
log('self-restart-failed', { ptyId: surfaceId, error: error instanceof Error ? error.message : String(error) });
|
|
578
|
+
};
|
|
579
|
+
try {
|
|
580
|
+
if (selfRestart.restart) {
|
|
581
|
+
selfRestart.restart(plan);
|
|
582
|
+
handoff();
|
|
583
|
+
} else {
|
|
584
|
+
void spawnTuiRelaunch(sessionId).then(handoff, failed);
|
|
585
|
+
}
|
|
586
|
+
} catch (error) {
|
|
587
|
+
failed(error);
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
try {
|
|
591
|
+
const watch = selfRestart.watch ?? ((fn: () => void) => defaultWatch(fn, selfRestart.intervalMs ?? Math.max(5_000, Math.round(minIdleMs / 3))));
|
|
592
|
+
unwatch = watch(tick);
|
|
593
|
+
} catch (error) {
|
|
594
|
+
log('self-restart-watch-failed', { ptyId: surfaceId, error: error instanceof Error ? error.message : String(error) });
|
|
595
|
+
}
|
|
596
|
+
}
|
|
369
597
|
// raw 모드 전 ctrl+c(SIGINT 기본 죽음)는 'exit' 훅을 안 돌린다 — 신호에서도 반납한다.
|
|
370
598
|
const signals = deps.signals !== undefined ? deps.signals : (deps.herdr === undefined ? process : null);
|
|
371
599
|
let unguard: () => void = () => {};
|
|
@@ -373,6 +601,7 @@ export function startTuiRunStateRecorder(surfaceId: string, deps: TuiRunStateRec
|
|
|
373
601
|
try { unguard = guardHerdrReleaseOnSignal(() => herdr.release(), signals); } catch { /* 지킴이 실패가 녹음기를 깨지 않는다 */ }
|
|
374
602
|
}
|
|
375
603
|
return () => {
|
|
604
|
+
try { unwatch(); } catch { /* 종료 경로를 깨지 않는다 */ }
|
|
376
605
|
try { unguard(); } catch { /* 종료 경로를 깨지 않는다 */ }
|
|
377
606
|
if (herdr) { try { herdr.release(); } catch { /* 종료 경로를 깨지 않는다 */ } }
|
|
378
607
|
if (active === recorder) active = null;
|
|
@@ -389,7 +618,12 @@ function writeTurnState(recorder: ActiveRecorder, turn: PtyTurnState): void {
|
|
|
389
618
|
const at = recorder.now();
|
|
390
619
|
let ok = false;
|
|
391
620
|
try { ok = recorder.writeTurn(recorder.surfaceId, turn, at); } catch { ok = false; }
|
|
392
|
-
if (ok)
|
|
621
|
+
if (ok) {
|
|
622
|
+
recorder.last = turn;
|
|
623
|
+
// 유휴 경과의 0초는 «idle 로 바뀐 시각» — busy 로 가면 다시 모른다.
|
|
624
|
+
if (turn === 'idle') recorder.idleSince = at;
|
|
625
|
+
else recorder.idleSince = undefined;
|
|
626
|
+
}
|
|
393
627
|
// 실패는 관측으로 남긴다 — 바깥 제어자는 그 사이 «unknown/낡은 값»을 본다. 성공은 남기지 않는다(턴마다 두 줄은 소음).
|
|
394
628
|
else recorder.log('turn-write-failed', { ptyId: recorder.surfaceId, turn, at });
|
|
395
629
|
// herdr 는 manifest 쓰기 성패와 무관하게, 값이 바뀔 때 알린다(같은 값 재시도는 한 번만).
|
|
@@ -37,6 +37,8 @@ export interface ChecklistItem {
|
|
|
37
37
|
/** 이 칸이 근거로 삼는 문서(저장소 상대 경로, 선택적으로 `#절`). 없으면 칸에 실리지 않는다. */
|
|
38
38
|
refs?: string[];
|
|
39
39
|
evidence?: string;
|
|
40
|
+
/** Public known-issue wording, independent from the internal checklist title. */
|
|
41
|
+
knownIssue?: string;
|
|
40
42
|
disposition?: ChecklistDisposition;
|
|
41
43
|
kind?: ChecklistKind;
|
|
42
44
|
/** Whether the seat dispatcher should launch a coding task. Missing in old rows means code. */
|
|
@@ -67,6 +69,49 @@ export interface Checklist {
|
|
|
67
69
|
history: ChecklistHistory[];
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
export type ChecklistEvidenceState = 'observed' | 'missing' | 'unmeasurable';
|
|
73
|
+
export type ChecklistEvidenceStageId = 'E1' | 'E3' | 'E4' | 'E5';
|
|
74
|
+
export interface ChecklistEvidenceStage {
|
|
75
|
+
id: ChecklistEvidenceStageId;
|
|
76
|
+
state: ChecklistEvidenceState;
|
|
77
|
+
source: string | null;
|
|
78
|
+
measuredAt: string | null;
|
|
79
|
+
reason: string;
|
|
80
|
+
verificationCommand?: string | null;
|
|
81
|
+
}
|
|
82
|
+
export interface ChecklistEvidenceChain {
|
|
83
|
+
id: string;
|
|
84
|
+
version: string;
|
|
85
|
+
stages: ChecklistEvidenceStage[];
|
|
86
|
+
greenEligible: boolean;
|
|
87
|
+
reason: string | null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Build a read-only, fail-closed evidence verdict. Claims are observed only when a source adapter verifies them. */
|
|
91
|
+
export function checklistEvidenceChain(input: {
|
|
92
|
+
item: ChecklistItem;
|
|
93
|
+
version: string;
|
|
94
|
+
stages: readonly ChecklistEvidenceStage[];
|
|
95
|
+
}): ChecklistEvidenceChain {
|
|
96
|
+
const required: ChecklistEvidenceStageId[] = ['E1', 'E3', 'E4', 'E5'];
|
|
97
|
+
const byId = new Map(input.stages.map((stage) => [stage.id, stage]));
|
|
98
|
+
const stages = required.map((id) => {
|
|
99
|
+
const stage = byId.get(id);
|
|
100
|
+
if (!stage) return { id, state: 'unmeasurable' as const, source: null, measuredAt: null, reason: '출처 어댑터 결과가 없다' };
|
|
101
|
+
if (stage.state === 'observed' && (!stage.source?.trim() || !stage.measuredAt || !Number.isFinite(Date.parse(stage.measuredAt))))
|
|
102
|
+
return { ...stage, state: 'unmeasurable' as const, reason: 'observed 판정에 유효한 출처와 측정 시각이 없다' };
|
|
103
|
+
return stage;
|
|
104
|
+
});
|
|
105
|
+
const unresolved = stages.filter((stage) => stage.state !== 'observed');
|
|
106
|
+
return {
|
|
107
|
+
id: input.item.id,
|
|
108
|
+
version: input.version,
|
|
109
|
+
stages,
|
|
110
|
+
greenEligible: unresolved.length === 0,
|
|
111
|
+
reason: unresolved.length ? `${unresolved.map((stage) => `${stage.id}=${stage.state}: ${stage.reason}`).join('; ')}` : null,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
70
115
|
export function devVersion(): string {
|
|
71
116
|
return (JSON.parse(readFileSync(join(import.meta.dir, '..', '..', 'package.json'), 'utf8')) as { version: string }).version;
|
|
72
117
|
}
|
|
@@ -405,7 +450,7 @@ export function addItem(v: string, input: { id: string; title: string; refs?: st
|
|
|
405
450
|
});
|
|
406
451
|
}
|
|
407
452
|
|
|
408
|
-
export function setItem(v: string, id: string, patch: { status?: ChecklistStatus; evidence?: string; refs?: string[]; owner?: string; disposition?: ChecklistDisposition; kind?: ChecklistKind; dispatchKind?: ChecklistDispatchKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean | null }, by: string): Checklist {
|
|
453
|
+
export function setItem(v: string, id: string, patch: { status?: ChecklistStatus; evidence?: string; knownIssue?: string | null; refs?: string[]; owner?: string; disposition?: ChecklistDisposition; kind?: ChecklistKind; dispatchKind?: ChecklistDispatchKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean | null }, by: string): Checklist {
|
|
409
454
|
return setItemGuarded(v, id, patch, by);
|
|
410
455
|
}
|
|
411
456
|
|
|
@@ -501,13 +546,13 @@ function setItemGuarded(v: string, id: string, patch: Parameters<typeof setItem>
|
|
|
501
546
|
throw new CliUserError(`지금 주인: ${item.owner} — --force 로만 바꾼다`, 'release checklist claim <id> --by <자리> --force');
|
|
502
547
|
}
|
|
503
548
|
}
|
|
504
|
-
const fields = (['evidence', 'owner', 'status', 'disposition', 'kind', 'dispatchKind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const).filter((field) => patch[field] !== undefined && JSON.stringify(patch[field]) !== JSON.stringify(item[field] ?? null));
|
|
549
|
+
const fields = (['evidence', 'knownIssue', 'owner', 'status', 'disposition', 'kind', 'dispatchKind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const).filter((field) => patch[field] !== undefined && JSON.stringify(patch[field]) !== JSON.stringify(item[field] ?? null));
|
|
505
550
|
if (fields.length === 0) return false;
|
|
506
551
|
const at = new Date().toISOString();
|
|
507
552
|
for (const field of fields) {
|
|
508
553
|
const from = item[field];
|
|
509
554
|
const to = patch[field]!;
|
|
510
|
-
if (field === 'accelerator' && to === null) delete item
|
|
555
|
+
if ((field === 'accelerator' || field === 'knownIssue') && to === null) delete (item as unknown as Record<string, unknown>)[field];
|
|
511
556
|
else (item as unknown as Record<string, unknown>)[field] = to;
|
|
512
557
|
item.updatedAt = at;
|
|
513
558
|
item.updatedBy = by;
|
|
@@ -585,7 +630,7 @@ export interface ChecklistGate {
|
|
|
585
630
|
undecided: string[];
|
|
586
631
|
blocked: string[];
|
|
587
632
|
moved: string[];
|
|
588
|
-
knownIssues: Array<{ id: string; title: string; evidence: string }>;
|
|
633
|
+
knownIssues: Array<{ id: string; title: string; evidence: string; knownIssue?: string }>;
|
|
589
634
|
/** Post-publication cells excluded from the pre-publication judgement. */
|
|
590
635
|
postpub?: string[];
|
|
591
636
|
/** Screen cells whose `짝:` line is missing or has an untracked ⏳ — a warning; it never changes `ok`. */
|
|
@@ -616,7 +661,7 @@ export function checklistGate(v: string): ChecklistGate {
|
|
|
616
661
|
if (item.status !== 'yellow') continue;
|
|
617
662
|
if (item.disposition === 'block') result.blocked.push(item.id);
|
|
618
663
|
else if (item.disposition === 'move') result.moved.push(item.id);
|
|
619
|
-
else if (item.disposition === 'known-issue') result.knownIssues.push({ id: item.id, title: item.title, evidence: item.evidence ?? '' });
|
|
664
|
+
else if (item.disposition === 'known-issue') result.knownIssues.push({ id: item.id, title: item.title, evidence: item.evidence ?? '', ...(item.knownIssue?.trim() ? { knownIssue: item.knownIssue.trim() } : {}) });
|
|
620
665
|
else result.undecided.push(item.id);
|
|
621
666
|
}
|
|
622
667
|
result.ok = result.red.length === 0 && result.undecided.length === 0 && result.blocked.length === 0;
|
|
@@ -36,7 +36,7 @@ const walWait = new Int32Array(new SharedArrayBuffer(4));
|
|
|
36
36
|
const SCHEMA_COLUMNS: Record<string, readonly string[]> = {
|
|
37
37
|
imported_versions: ['json_hash', 'imported_at'],
|
|
38
38
|
events: ['reason', 'generation'],
|
|
39
|
-
assignments: ['priority', 'predecessors', 'deadline_version', 'ceo_minutes', 'ceo_date', 'accelerator', 'refs', 'dispatch_kind'],
|
|
39
|
+
assignments: ['priority', 'predecessors', 'deadline_version', 'ceo_minutes', 'ceo_date', 'accelerator', 'refs', 'dispatch_kind', 'known_issue'],
|
|
40
40
|
release_schedules: ['freeze_from', 'freeze_until', 'publish_at'],
|
|
41
41
|
};
|
|
42
42
|
function schemaCurrent(db: Database): boolean {
|
|
@@ -81,7 +81,7 @@ function open(root = releaseLedgerRoot()): Database {
|
|
|
81
81
|
if (!eventColumns.some((column) => column.name === 'generation')) db.exec('ALTER TABLE events ADD COLUMN generation INTEGER');
|
|
82
82
|
db.exec('CREATE TABLE IF NOT EXISTS release_schedules (version TEXT PRIMARY KEY, cut_at TEXT NOT NULL, land_by TEXT, updated_at TEXT NOT NULL, updated_by TEXT NOT NULL)');
|
|
83
83
|
const assignmentColumns = db.query('PRAGMA table_info(assignments)').all() as Array<{ name: string }>;
|
|
84
|
-
for (const [name, sql] of [['priority', 'TEXT'], ['predecessors', 'TEXT'], ['deadline_version', 'TEXT'], ['ceo_minutes', 'INTEGER'], ['ceo_date', 'TEXT'], ['accelerator', 'INTEGER'], ['refs', 'TEXT'], ['dispatch_kind', 'TEXT']] as const) {
|
|
84
|
+
for (const [name, sql] of [['priority', 'TEXT'], ['predecessors', 'TEXT'], ['deadline_version', 'TEXT'], ['ceo_minutes', 'INTEGER'], ['ceo_date', 'TEXT'], ['accelerator', 'INTEGER'], ['refs', 'TEXT'], ['dispatch_kind', 'TEXT'], ['known_issue', 'TEXT']] as const) {
|
|
85
85
|
if (!assignmentColumns.some((column) => column.name === name)) db.exec(`ALTER TABLE assignments ADD COLUMN ${name} ${sql}`);
|
|
86
86
|
}
|
|
87
87
|
const scheduleColumns = db.query('PRAGMA table_info(release_schedules)').all() as Array<{ name: string }>;
|
|
@@ -178,7 +178,7 @@ function evidenceRefs(db: Database, version: string, id: string): string[] {
|
|
|
178
178
|
return (db.query('SELECT ref FROM evidence WHERE feature_id = ? AND version = ? ORDER BY rowid').all(id, version) as Array<{ ref: string }>).map((row) => row.ref);
|
|
179
179
|
}
|
|
180
180
|
function items(db: Database, version: string): ChecklistItem[] {
|
|
181
|
-
const rows = db.query(`SELECT f.id, COALESCE(a.title_override, f.title) AS title, a.owner, a.kind, a.dispatch_kind, a.priority, a.predecessors, a.deadline_version, a.ceo_minutes, a.ceo_date, a.accelerator, a.refs, a.status, a.disposition, a.evidence, a.updated_at, a.updated_by
|
|
181
|
+
const rows = db.query(`SELECT f.id, COALESCE(a.title_override, f.title) AS title, a.owner, a.kind, a.dispatch_kind, a.priority, a.predecessors, a.deadline_version, a.ceo_minutes, a.ceo_date, a.accelerator, a.refs, a.status, a.disposition, a.evidence, a.known_issue, a.updated_at, a.updated_by
|
|
182
182
|
FROM assignments a JOIN features f ON f.id = a.feature_id WHERE a.version = ? ORDER BY a.rowid`).all(version) as Array<Record<string, string | number | null>>;
|
|
183
183
|
return rows.map((r) => {
|
|
184
184
|
const evidence = [r.evidence, ...evidenceRefs(db, version, r.id as string)].filter((value) => value !== null).join('\n');
|
|
@@ -190,7 +190,7 @@ function items(db: Database, version: string): ChecklistItem[] {
|
|
|
190
190
|
...(r.ceo_minutes !== null ? { ceoMinutes: r.ceo_minutes as number } : {}), ...(r.ceo_date !== null ? { ceoDate: r.ceo_date as string } : {}),
|
|
191
191
|
...(r.accelerator === 1 ? { accelerator: true as const } : {}),
|
|
192
192
|
...(r.refs !== null && r.refs !== undefined ? { refs: JSON.parse(r.refs as string) as string[] } : {}),
|
|
193
|
-
...(r.evidence !== null || evidence ? { evidence } : {}), ...(r.disposition !== null ? { disposition: r.disposition as ChecklistItem['disposition'] } : {}),
|
|
193
|
+
...(r.evidence !== null || evidence ? { evidence } : {}), ...(r.known_issue !== null ? { knownIssue: r.known_issue as string } : {}), ...(r.disposition !== null ? { disposition: r.disposition as ChecklistItem['disposition'] } : {}),
|
|
194
194
|
updatedAt: r.updated_at as string, updatedBy: r.updated_by as string };
|
|
195
195
|
});
|
|
196
196
|
}
|
|
@@ -203,9 +203,9 @@ function putItem(db: Database, version: string, item: ChecklistItem): void {
|
|
|
203
203
|
if (!feature) db.query('INSERT INTO features (id, title, owner, kind, created_at) VALUES (?, ?, ?, ?, ?)').run(item.id, item.title, item.owner ?? null, item.kind ?? null, item.updatedAt);
|
|
204
204
|
// features.owner/kind follow the latest assignment so details() and the checklist never disagree after a set.
|
|
205
205
|
else if (item.owner !== undefined || item.kind !== undefined) db.query('UPDATE features SET owner = COALESCE(?, owner), kind = COALESCE(?, kind) WHERE id = ?').run(item.owner ?? null, item.kind ?? null, item.id);
|
|
206
|
-
db.query(`INSERT INTO assignments (feature_id, version, status, disposition, evidence, title_override, owner, kind, dispatch_kind, priority, predecessors, deadline_version, ceo_minutes, ceo_date, accelerator, refs, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
207
|
-
ON CONFLICT(feature_id, version) DO UPDATE SET status=excluded.status, disposition=excluded.disposition, evidence=excluded.evidence, owner=excluded.owner, kind=excluded.kind, dispatch_kind=excluded.dispatch_kind, priority=excluded.priority, predecessors=excluded.predecessors, deadline_version=excluded.deadline_version, ceo_minutes=excluded.ceo_minutes, ceo_date=excluded.ceo_date, accelerator=excluded.accelerator, refs=excluded.refs, updated_at=excluded.updated_at, updated_by=excluded.updated_by`)
|
|
208
|
-
.run(item.id, version, item.status, item.disposition ?? null, item.evidence ?? null, feature && feature.title !== item.title ? item.title : null, item.owner ?? null, item.kind ?? null, item.dispatchKind ?? null, item.priority ?? null, item.predecessors ? JSON.stringify(item.predecessors) : null, item.deadlineVersion ?? null, item.ceoMinutes ?? null, item.ceoDate ?? null, item.accelerator === true ? 1 : null, item.refs?.length ? JSON.stringify(item.refs) : null, item.updatedAt, item.updatedBy);
|
|
206
|
+
db.query(`INSERT INTO assignments (feature_id, version, status, disposition, evidence, title_override, owner, kind, dispatch_kind, priority, predecessors, deadline_version, ceo_minutes, ceo_date, accelerator, refs, known_issue, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
207
|
+
ON CONFLICT(feature_id, version) DO UPDATE SET status=excluded.status, disposition=excluded.disposition, evidence=excluded.evidence, owner=excluded.owner, kind=excluded.kind, dispatch_kind=excluded.dispatch_kind, priority=excluded.priority, predecessors=excluded.predecessors, deadline_version=excluded.deadline_version, ceo_minutes=excluded.ceo_minutes, ceo_date=excluded.ceo_date, accelerator=excluded.accelerator, refs=excluded.refs, known_issue=excluded.known_issue, updated_at=excluded.updated_at, updated_by=excluded.updated_by`)
|
|
208
|
+
.run(item.id, version, item.status, item.disposition ?? null, item.evidence ?? null, feature && feature.title !== item.title ? item.title : null, item.owner ?? null, item.kind ?? null, item.dispatchKind ?? null, item.priority ?? null, item.predecessors ? JSON.stringify(item.predecessors) : null, item.deadlineVersion ?? null, item.ceoMinutes ?? null, item.ceoDate ?? null, item.accelerator === true ? 1 : null, item.refs?.length ? JSON.stringify(item.refs) : null, item.knownIssue ?? null, item.updatedAt, item.updatedBy);
|
|
209
209
|
}
|
|
210
210
|
function jsonHash(contents: string | Buffer): string { return createHash('sha256').update(contents).digest('hex'); }
|
|
211
211
|
|
|
@@ -274,7 +274,7 @@ function importOnDb(db: Database, version: string): boolean {
|
|
|
274
274
|
record(db, version, { at: new Date().toISOString(), by: item.updatedBy, id: item.id, field: 'reimport', from: null, to: item, released: data.released, dev: data.dev });
|
|
275
275
|
continue;
|
|
276
276
|
}
|
|
277
|
-
const fields = ['title', 'status', 'evidence', 'owner', 'disposition', 'kind', 'dispatchKind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const;
|
|
277
|
+
const fields = ['title', 'status', 'evidence', 'knownIssue', 'owner', 'disposition', 'kind', 'dispatchKind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const;
|
|
278
278
|
const baseEvidence = (db.query('SELECT evidence FROM assignments WHERE feature_id = ? AND version = ?').get(item.id, version) as { evidence: string | null }).evidence ?? undefined;
|
|
279
279
|
const preserveRefs = item.evidence === baseEvidence || item.evidence === current.evidence;
|
|
280
280
|
const differs = fields.some((field) => field === 'evidence'
|
|
@@ -441,7 +441,7 @@ export function set(version: string, id: string, patch: Partial<ChecklistItem>,
|
|
|
441
441
|
return mutate(version, released, dev, (data) => {
|
|
442
442
|
const item = data.items.find((i) => i.id === id);
|
|
443
443
|
if (!item) throw new CliUserError(`없는 칸: ${id}`, 'list 로 칸 목록을 본다');
|
|
444
|
-
const fields = (['evidence', 'owner', 'status', 'disposition', 'kind'] as const).filter((field) => patch[field] !== undefined && patch[field] !== item[field]);
|
|
444
|
+
const fields = (['evidence', 'knownIssue', 'owner', 'status', 'disposition', 'kind'] as const).filter((field) => patch[field] !== undefined && patch[field] !== item[field]);
|
|
445
445
|
if (!fields.length) return false;
|
|
446
446
|
const at = new Date().toISOString();
|
|
447
447
|
for (const field of fields) {
|
|
@@ -12,6 +12,12 @@ export type ShardState = typeof SHARD_STATES[number];
|
|
|
12
12
|
export interface GateShard {
|
|
13
13
|
id: string;
|
|
14
14
|
state: ShardState;
|
|
15
|
+
/** Kubernetes Job for the current attempt; lets the gate watchdog reconcile a lost completion callback. */
|
|
16
|
+
job?: string;
|
|
17
|
+
/** Attempt identity associated with the currently recorded Job/result marker. */
|
|
18
|
+
attemptId?: string;
|
|
19
|
+
/** Result JSON for the current attempt; retries replace this so an older marker cannot close a new Job. */
|
|
20
|
+
resultFile?: string;
|
|
15
21
|
startedAt?: string;
|
|
16
22
|
endedAt?: string;
|
|
17
23
|
/** 설치(install) 단계에 쓴 초. */
|
|
@@ -61,8 +67,14 @@ function shardOf(value: unknown): GateShard | null {
|
|
|
61
67
|
const waitReason = str(raw.waitReason);
|
|
62
68
|
const plannedMin = num(raw.plannedMin);
|
|
63
69
|
const host = str(raw.host, 120);
|
|
70
|
+
const job = str(raw.job, 120);
|
|
71
|
+
const attemptId = str(raw.attemptId, 120);
|
|
72
|
+
const resultFile = str(raw.resultFile, 200);
|
|
64
73
|
return {
|
|
65
74
|
id, state,
|
|
75
|
+
...(job ? { job } : {}),
|
|
76
|
+
...(attemptId ? { attemptId } : {}),
|
|
77
|
+
...(resultFile ? { resultFile } : {}),
|
|
66
78
|
...(startedAt ? { startedAt } : {}), ...(endedAt ? { endedAt } : {}),
|
|
67
79
|
...(installSec !== undefined ? { installSec } : {}), ...(rc !== undefined ? { rc } : {}),
|
|
68
80
|
...(waitReason ? { waitReason } : {}), ...(plannedMin !== undefined ? { plannedMin } : {}),
|
|
@@ -70,6 +82,55 @@ function shardOf(value: unknown): GateShard | null {
|
|
|
70
82
|
};
|
|
71
83
|
}
|
|
72
84
|
|
|
85
|
+
export type GateJobTerminal = 'complete' | 'failed';
|
|
86
|
+
|
|
87
|
+
/** Forget the prior child Job before a shard descends into a retry/split attempt. */
|
|
88
|
+
export function beginGateShardAttempt(shard: GateShard, now = new Date()): GateShard {
|
|
89
|
+
const next: GateShard = { ...shard, state: 'retry', startedAt: now.toISOString() };
|
|
90
|
+
delete next.endedAt;
|
|
91
|
+
delete next.waitReason;
|
|
92
|
+
delete next.host;
|
|
93
|
+
delete next.job;
|
|
94
|
+
delete next.resultFile;
|
|
95
|
+
delete next.attemptId;
|
|
96
|
+
return next;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Close each stale running row when its result marker or Kubernetes Job has terminal evidence.
|
|
101
|
+
* A result marker can close a row even when the Kubernetes status read is unavailable.
|
|
102
|
+
*/
|
|
103
|
+
export function finalizeTerminalGateShards(
|
|
104
|
+
file: GateShardsFile,
|
|
105
|
+
terminalJobs: ReadonlyMap<string, GateJobTerminal>,
|
|
106
|
+
results: ReadonlyMap<string, { completed?: boolean; jobName?: string; attemptId?: string; jobFailed?: boolean; rc?: number | null; reason?: 'timeout' | 'stall' }>,
|
|
107
|
+
now: Date = new Date(),
|
|
108
|
+
staleAfterMs = 120_000,
|
|
109
|
+
): GateShardsFile {
|
|
110
|
+
const active = file.shards.filter((shard) => shard.state === 'running' || shard.state === 'retry');
|
|
111
|
+
if (!active.length) return file;
|
|
112
|
+
const at = now.getTime();
|
|
113
|
+
const ready = active.map((shard) => {
|
|
114
|
+
const result = results.get(shard.id);
|
|
115
|
+
const resultTerminal = result?.completed === true && result.jobName === shard.job && result.attemptId === shard.attemptId;
|
|
116
|
+
const k8sTerminal = shard.job ? terminalJobs.get(shard.job) : undefined;
|
|
117
|
+
const startedAt = shard.startedAt ? Date.parse(shard.startedAt) : Number.NaN;
|
|
118
|
+
if (!resultTerminal && !k8sTerminal) return undefined;
|
|
119
|
+
if (!Number.isFinite(startedAt) || at - startedAt < staleAfterMs) return undefined;
|
|
120
|
+
return { shard, result, state: resultTerminal
|
|
121
|
+
? (result!.reason === 'timeout' ? 'timeout' as const : result!.reason === 'stall' || result!.jobFailed === true ? 'failed' as const : 'done' as const)
|
|
122
|
+
: k8sTerminal === 'failed' ? 'failed' as const : 'done' as const };
|
|
123
|
+
});
|
|
124
|
+
const finalized = ready.filter((entry): entry is NonNullable<typeof entry> => entry !== undefined);
|
|
125
|
+
if (!finalized.length) return file;
|
|
126
|
+
const byId = new Map(finalized.map(({ shard, result, state }) => {
|
|
127
|
+
const current = { ...shard };
|
|
128
|
+
delete current.waitReason;
|
|
129
|
+
return [shard.id, { ...current, state, endedAt: now.toISOString(), ...(result && typeof result.rc === 'number' ? { rc: result.rc } : {}) } satisfies GateShard];
|
|
130
|
+
}));
|
|
131
|
+
return { ...file, updatedAt: now.toISOString(), shards: file.shards.map((shard) => byId.get(shard.id) ?? shard) };
|
|
132
|
+
}
|
|
133
|
+
|
|
73
134
|
function verdictOf(value: unknown): GateShardsVerdict | undefined {
|
|
74
135
|
if (!value || typeof value !== 'object') return undefined;
|
|
75
136
|
const raw = value as Record<string, unknown>;
|