elanous 0.2.21 → 0.2.23
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/NOTICE +7 -0
- package/README.md +32 -22
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/chunks/{119fc678.6f591cdb84ca5791.js → 0673cc54.8e2ef1c23e49e190.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{a9f2b54d-40c16bd0efdb04b8.js → 0a09e062-34f747a17d8d8c2e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{f8626309.a4e5d362b1d55e59.js → 0e3acd34.d42b2ef87fdf4234.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +77 -0
- package/apps/pwa/out/_next/static/chunks/{7175-350f4ce2873bc038.js → 1325-dc3f3c21eb181cb4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +34 -0
- package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +24 -0
- package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6767.8e6c5f6e744fcd9f.js → 1505.5826671109111e75.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 1669-da843ed73aa301f5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +36 -0
- package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +122 -0
- package/apps/pwa/out/_next/static/chunks/2528.0af5c0e1fad88df6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +62 -0
- package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/272-b23d2e92161d11fd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{7899.597af4a9996c907f.js → 2721.bc9a8f36bd85c07a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +149 -0
- package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3961-fbef064c213b2b18.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +309 -0
- package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{d70879db.c66c56a95a91efc6.js → 4c5e95ce.83e9b16add6fcd8c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6158.566c890adc06a459.js → 5313.1697309c532b9856.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/{79b78388.663188133449d707.js → 53746282.1be36038d1abd949.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5578.ac963634373b28c6.js +286 -0
- package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5967-c0a80f8ffe5d4050.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 5974.360f8441eb0ac1ec.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +74 -0
- package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6571-926ddf024a6ad5df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +64 -0
- package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{9832.2ab2e818013574c7.js → 6702.ebbd165d5e4a4a14.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +32 -0
- package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +24 -0
- package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +93 -0
- package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 740.90b31555290236a9.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +148 -0
- package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +226 -0
- package/apps/pwa/out/_next/static/chunks/{9070.067c106528ec1ae6.js → 7518.49161e8f5814abdb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +27 -0
- package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +115 -0
- package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7905.b230b9d06cb4ad5d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8194.484f51e273d9abd2.js → 8264.00e434fbd02e9311.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +8 -0
- package/apps/pwa/out/_next/static/chunks/{088d8e8a.8069543d082bec12.js → 83cfc5c8.349535543c1548b6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +23 -0
- package/apps/pwa/out/_next/static/chunks/{1948.5f35b39eef222a94.js → 8438.ee7f0df3b3f6fcb4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4588.ad3364cb7fb97ada.js → 8532.a86e99acf9b761cb.js} +2 -2
- package/apps/pwa/out/_next/static/chunks/8569.b853a8daa8f31d12.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +1 -0
- package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8925-2abfb48af477fb7f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{88729267.9c6c000157c83f2f.js → 89849432.9eaa2f4c9c010965.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +90 -0
- package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +94 -0
- package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +41 -0
- package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +287 -0
- package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +79 -0
- package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{3522-1de1319d028ac89c.js → 9502-32c5dc22e8f120f5.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +104 -0
- package/apps/pwa/out/_next/static/chunks/{7630.2b9a68659053ff4e.js → 9976.8f28864317639fe6.js} +16 -16
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d5341ac96203a983.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-0160ab83c8685a12.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-55c631c032dcc47e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-ad3bd8084048bee4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e6784759a2531031.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-5c5d0e370f495ef6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-c325e21543cd48a8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/{page-111cabe4d1fd69ae.js → page-6168a7c43e6ef8f5.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-31417d3604154a6d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-e9606dc0bdec9305.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-a648bc464c9dc754.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-25bb425afdb27541.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-32d72fdef1afe11a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-d27b794c8ba76bbb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-2bd9ce9c020d02d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-a34096245e63b9f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-22170f4f00a15496.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-4cc66d22ca4ec502.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-83b14c729fcea837.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/loops/page-6e2781c523dad761.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-26dd415c8f13f341.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-ccdb83ed40c8d724.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-7ad3de8fa06fdea9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-015c02c4fec4023e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-6b0ae5b5c42f6d2f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-786111f30b6f0969.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-48fb31810693c357.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e17cce5e2ed0fee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-cb154acadb025414.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-16258e956ea93fc2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-c2dd2b19c93f90ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f35dd1dd96ae87.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-d3c007c8a0ddd7ee.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7837ce2aacb97b04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-7350ee93f4fe1033.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-00723458575f2b19.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-745d9b6c015076f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-736d33c7414a8a1a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-119be9a0444d2482.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-fa806c018833e332.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-c782041b5f5199ba.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-d431fbdea6ad93dd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-0c056abff82b9891.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-242d668e4fbf72c4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-847c3de6ca8a4416.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-81dd0d8ae923ed72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-74e69ba2c8e970d4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-70038f41ae7cf931.js +1 -0
- package/apps/pwa/out/_next/static/chunks/b4e12462-5fab4a813a63dadd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → ce383d63.d2ede338788ed18e.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{framework-5c169757551134ed.js → framework-b2763b10dc6b3836.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +1 -0
- package/apps/pwa/out/_next/static/css/5619d59e87eddf66.css +1 -0
- package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +1 -0
- package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_buildManifest.js +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 +24 -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 +24 -23
- package/apps/pwa/out/loops/index.html +1 -1
- package/apps/pwa/out/loops/index.txt +22 -22
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -1
- package/apps/pwa/out/outputs/index.txt +22 -22
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -23
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -23
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/catalog/models/anthropic/claude-haiku-5-5.yaml +32 -0
- package/catalog/models/anthropic/claude-opus-5-5.yaml +5 -0
- package/catalog/models/anthropic/claude-sonnet-5-5.yaml +31 -0
- package/catalog/models/anthropic/claude-sonnet-5.yaml +8 -2
- package/catalog/models/openai/gpt-6-astra.yaml +6 -0
- package/catalog/models/openai/gpt-6-luna.yaml +6 -0
- package/catalog/models/openai/gpt-6-sol.yaml +6 -0
- package/graphs/catalog/catalog.yaml +1 -1
- package/graphs/drafts/recipes.yaml +2 -2
- package/graphs/log-horizon/log-horizon-watch.yaml +25 -0
- package/graphs/log-horizon/recipes.yaml +3 -0
- package/graphs/release/recipes.yaml +1 -1
- package/graphs/release/release-loop.yaml +6 -2
- package/graphs/release-rehearsal/recipes.yaml +12 -0
- package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
- package/graphs/test-diet/recipes.yaml +3 -0
- package/graphs/test-diet/test-diet.yaml +3 -1
- package/package.json +4 -1
- package/scripts/bench-report.ts +82 -3
- package/scripts/ci-typecheck-changed.ts +10 -1
- package/scripts/f-session-monitor.ts +69 -0
- package/scripts/hq/hq-fence-wrapper.sh +148 -0
- package/scripts/hq/standby-snapshot.ts +7 -3
- package/scripts/knowledge-compress.ts +11 -0
- package/scripts/lib/typecheck-ratchet.ts +51 -0
- package/scripts/nightly-docops.ts +90 -3
- package/scripts/openai-relay-server.ts +5 -1
- package/scripts/release-loop/docs-node.ts +258 -43
- package/scripts/release-loop/gate-method.ts +59 -0
- package/scripts/release-loop/gate-node.ts +73 -7
- package/scripts/release-loop/gate-wall.ts +208 -0
- package/scripts/release-loop/known-issues-node.ts +53 -8
- package/scripts/release-loop/publish-at.ts +14 -0
- package/scripts/release-loop/publish-node.ts +17 -2
- package/scripts/release-loop/resume-release.ts +34 -4
- package/scripts/release-loop/resume.ts +53 -0
- package/scripts/release-loop/shard-plan.ts +3 -11
- package/scripts/release-loop/tui-node-checks.ts +22 -0
- package/scripts/release-loop/unattended-release.ts +8 -1
- package/scripts/research-coo-admin-dates.ts +39 -0
- package/scripts/rhythm/daily.ts +51 -2
- package/scripts/rhythm/weekly.ts +3 -2
- package/scripts/skills/public-check.ts +7 -2
- package/scripts/smart-merge/resync-shadow.ts +5 -3
- package/scripts/test-diet/lib.ts +81 -1
- package/scripts/test-diet/node.ts +48 -2
- package/scripts/tsc-main-safety-net.ts +189 -0
- package/scripts/usage-rollup.ts +8 -4
- package/scripts/verify-coo-admin-evidence.ts +83 -0
- package/src/acp/client.ts +4 -2
- package/src/acp/codex-plugins.ts +48 -6
- package/src/agent/monad-agent-turn.ts +67 -5
- package/src/agent/run-context.ts +14 -0
- package/src/agent/tool-profile.ts +28 -2
- package/src/agent-env/profile.ts +25 -5
- package/src/agent-mission/acp-judge.ts +8 -2
- package/src/agent-mission/capabilities-cli.ts +16 -1
- package/src/agent-mission/driver.ts +27 -13
- package/src/agent-mission/pr-review-watch.ts +6 -2
- package/src/agent-mission/review-loop.ts +33 -5
- package/src/agent-mission/supervisor-metrics.ts +17 -2
- package/src/agent-substrate/acp-reviewer.ts +25 -9
- package/src/agent-substrate/pr-reviewer.ts +175 -32
- package/src/agent-substrate/review-intent.ts +106 -5
- package/src/agent-substrate/self-review-cli.ts +111 -16
- package/src/agent-substrate/shard-boundary-intent.ts +92 -26
- package/src/ask-user-question/pending-questions.ts +8 -2
- package/src/autopilot/build/llm-conflict-merge.ts +238 -20
- package/src/autopilot/codebase-grounding.ts +44 -0
- package/src/autopilot/llm-control-brain.ts +13 -1
- package/src/autopilot/mission-codebase-gate.ts +8 -77
- package/src/autopilot/pr-manager.ts +30 -11
- package/src/away/release-watch.ts +47 -8
- package/src/boot/acp-server.ts +4 -7
- package/src/boot/acp-socket-path.ts +7 -0
- package/src/briefing/brief-items.ts +123 -22
- package/src/chat/index.ts +13 -3
- package/src/cli/agent-cli.ts +20 -0
- package/src/cli/brief-cli.ts +46 -22
- package/src/cli/cli-user-error.ts +9 -2
- package/src/cli/config-classify.ts +83 -0
- package/src/cli/control-cli.ts +14 -0
- package/src/cli/decisions-cli.ts +26 -16
- package/src/cli/log-event-names.ts +3 -0
- package/src/cli/logs-cli.ts +1 -0
- package/src/cli/logs-model-input.ts +1 -1
- package/src/cli/mcp-login.ts +111 -37
- package/src/cli/plugin-cli.ts +21 -1
- package/src/cli/pod-cli.ts +26 -0
- package/src/cli/pr-cli.ts +94 -9
- package/src/cli/pr-land-overlap-evidence.ts +131 -0
- package/src/cli/release-cli.ts +74 -15
- package/src/cli/self-update.ts +173 -10
- package/src/cli/skills-cli.ts +12 -3
- package/src/cli/tasks-cli.ts +241 -28
- package/src/connectors/types.ts +6 -6
- package/src/context-bus/context-first.ts +51 -2
- package/src/context-bus/context-now-surfaces.ts +29 -0
- package/src/context-bus/coord-events.ts +32 -4
- package/src/context-bus/long-term-memory.ts +26 -7
- package/src/context-bus/nightly-condense.ts +170 -21
- package/src/control/control-status.ts +87 -0
- package/src/control-plane/light-member.ts +5 -3
- package/src/control-plane/member.ts +172 -7
- package/src/core-turn/run-goal-loop.ts +108 -3
- package/src/dashboard/chat-fold.ts +20 -0
- package/src/dashboard/first-screen-band.ts +151 -1
- package/src/dashboard/index.ts +27 -5
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +14 -3
- package/src/dashboard/stale-install-check.ts +13 -2
- package/src/dashboard/turn-stream-formatter.ts +25 -0
- package/src/debug/log-diet.ts +159 -0
- package/src/debug/log.ts +52 -17
- package/src/decisions/decision-cards.ts +20 -1
- package/src/decisions/decision-ledger.ts +11 -8
- package/src/decisions/web-push-decision-cards.ts +19 -3
- package/src/discord-self-message.ts +2 -2
- package/src/display/coordinator.ts +25 -2
- package/src/domains/coo-admin-dates.evidence.json +876 -0
- package/src/domains/coo-admin-tool.ts +75 -14
- package/src/domains/cron-match.ts +1 -0
- package/src/domains/ops-status.ts +53 -0
- package/src/domains/outbound-alert.ts +41 -7
- package/src/domains/release-tool.ts +119 -10
- package/src/domains/schedule-registry.ts +10 -7
- package/src/domains/schedule-runner.ts +1 -0
- package/src/elanous-config-dir.ts +2 -2
- package/src/elanous-daemon.ts +3 -3
- package/src/exec-requests/planner.ts +6 -0
- package/src/execution-loop/launch-gate.ts +1 -1
- package/src/expression/i18n/messages.en.ts +5 -0
- package/src/expression/i18n/messages.ja.ts +5 -0
- package/src/expression/i18n/messages.ko.ts +5 -0
- package/src/expression/i18n/messages.zh.ts +5 -0
- package/src/expression/i18n/types.ts +8 -0
- package/src/github/pr-labels.ts +1 -0
- package/src/graph-kinds/registry.ts +6 -6
- package/src/graph-runner/graph-cli.ts +34 -2
- package/src/graph-runner/graph-run-api.ts +7 -0
- package/src/graph-runner/graph-tick.ts +73 -12
- package/src/graph-runner/runner.ts +94 -13
- package/src/graph-unify/wf-to-graph.ts +79 -0
- package/src/graph-wizard/generate.ts +34 -2
- package/src/graph-wizard/steps.ts +13 -0
- package/src/harness/dispatch-backpressure.ts +259 -0
- package/src/harness/harness-cli-command.ts +227 -50
- package/src/harness/harness-queue.ts +58 -14
- package/src/harness/harness-seams.ts +2 -20
- package/src/harness/harness-substrate-default.ts +72 -1
- package/src/harness/launch-advice.ts +23 -0
- package/src/harness/nested-elanous-policy.ts +4 -2
- package/src/hq/fence-wrapper.ts +7 -0
- package/src/hq/hq.ts +33 -2
- package/src/hq/lease.ts +13 -0
- package/src/hq/seats.ts +114 -18
- package/src/index.ts +199 -71
- package/src/intake-plane/collect-github.ts +19 -1
- package/src/intake-plane/digest.ts +45 -20
- package/src/intake-plane/lens.ts +36 -8
- package/src/intelligence-map/model-alias.ts +6 -0
- package/src/intelligence-map/model-catalog.ts +41 -0
- package/src/knowledge/conclusion-compress.ts +93 -0
- package/src/knowledge/kgs/pack.ts +5 -2
- package/src/knowledge/kgs/sqlite-store.ts +15 -0
- package/src/knowledge/know-find.ts +9 -2
- package/src/knowledge/query.ts +20 -0
- package/src/knowledge/tools/knowledge-query.ts +20 -2
- package/src/knowledge/write.ts +234 -2
- package/src/llm/bedrock-provider.ts +175 -0
- package/src/llm/bedrock.ts +345 -0
- package/src/llm/provider-credentials.ts +3 -1
- package/src/llm.ts +332 -51
- package/src/loops/budget.ts +150 -0
- package/src/loops/neighbor-runtime.ts +88 -0
- package/src/loops/orchestrator/author-depth.ts +29 -11
- package/src/loops/orchestrator/overlap.ts +7 -1
- package/src/loops/orchestrator/resync-shadow.ts +1 -1
- package/src/loops/orchestrator/seat-share.ts +6 -49
- package/src/loops/orchestrator/tick.ts +35 -2
- package/src/loops/orchestrator/traffic.ts +6 -80
- package/src/loops/registry.ts +5 -0
- package/src/market/publish.ts +17 -1
- package/src/market/signed-index.ts +42 -0
- package/src/maturity/feature-maturity.ts +2 -1
- package/src/mcp/mcp-oauth.ts +136 -17
- package/src/model-tier/llm-tier-map.ts +48 -4
- package/src/models/prompts.ts +22 -1
- package/src/mss/logging/horizon-watch.ts +168 -0
- package/src/mss/logging/log-store.ts +204 -15
- package/src/mss/logging/redaction.ts +17 -0
- package/src/native-tool-catalog.ts +1 -1
- package/src/nexus/api/consult-requests.ts +7 -10
- package/src/nexus/api/discord-trigger-bot.ts +6 -3
- package/src/nexus/api/draft-metrics.ts +22 -8
- package/src/nexus/api/error-reports.ts +30 -8
- package/src/nexus/api/graph-peer-edit.ts +77 -0
- package/src/nexus/api/graph-wizard-api.ts +9 -1
- package/src/nexus/api/graphs-api.ts +145 -7
- package/src/nexus/api/http-server.ts +101 -8
- package/src/nexus/api/loop-resources.ts +42 -0
- package/src/nexus/api/outbound-report.ts +8 -3
- package/src/nexus/api/plugins-market.ts +24 -0
- package/src/nexus/api/telegram-trigger-bot.ts +6 -3
- package/src/nexus/index.ts +13 -2
- package/src/nexus/outbound/format.ts +2 -0
- package/src/nexus/outbound/router.ts +198 -13
- package/src/oauth/claude-pty-maturity.ts +24 -0
- package/src/oauth/codex-account-rotation.ts +16 -18
- package/src/oauth/codex-account-store.ts +134 -5
- package/src/oauth/fallback-chain.ts +50 -15
- package/src/onboarding.ts +2 -1
- package/src/plugins/adapters/claude-package.ts +4 -12
- package/src/plugins/core/capability-policy.ts +141 -0
- package/src/plugins/core/host.ts +21 -8
- package/src/plugins/core/manifest.ts +19 -2
- package/src/plugins/core/trust-store.ts +15 -0
- package/src/plugins/core/types.ts +12 -0
- package/src/plugins/install/market-fetch.ts +68 -16
- package/src/plugins/install/plugin-install.ts +187 -16
- package/src/plugins/maker/market-bundle.ts +9 -0
- package/src/plugins/maker/plugin-maker.ts +32 -21
- package/src/plugins/maker/wizard-generate.ts +87 -9
- package/src/policy/llm-policy.ts +24 -6
- package/src/process/pid-liveness.ts +1 -1
- package/src/prompt-cache/openai.ts +10 -6
- package/src/prompt-cache/openrouter.ts +94 -0
- package/src/prompt-enhance/enhance.ts +46 -5
- package/src/prompt-library/family-prompt-coverage.ts +1 -0
- package/src/prompt-library/universal-preamble.ts +2 -2
- package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
- package/src/registry/loader.ts +6 -1
- package/src/release-loop/checklist-board.ts +27 -0
- package/src/release-loop/checklist.ts +62 -9
- package/src/release-loop/feature-store.ts +3 -0
- package/src/release-loop/gate-shards.ts +48 -4
- package/src/release-loop/landed-to-green.ts +81 -0
- package/src/release-loop/light-rc.ts +11 -1
- package/src/release-loop/merged-pr-checklist.ts +10 -0
- package/src/release-loop/placement.ts +91 -22
- package/src/release-loop/rehearsal.ts +317 -0
- package/src/release-loop/release-schedule.ts +13 -1
- package/src/release-loop/rubric-types.ts +1 -0
- package/src/release-loop/rubric.ts +2 -2
- package/src/retro/daily.ts +23 -9
- package/src/seat-address/seat-address.ts +1 -0
- package/src/seat-loop/seat-loop.ts +208 -21
- package/src/seat-loop/seat-report.ts +29 -1
- package/src/seat-loop/traffic-signal.ts +44 -0
- package/src/self-dev/ask-launch-flow.ts +2 -2
- package/src/self-dev/dev-cli.ts +157 -11
- package/src/self-dev/dev-pipeline.ts +18 -1
- package/src/self-dev/draft-residue.ts +463 -0
- package/src/self-dev/draft-sweep.ts +195 -17
- package/src/self-dev/draft-triage-rules.ts +27 -1
- package/src/self-dev/launch-preflight-text.ts +549 -0
- package/src/self-dev/launch-preflight.ts +10 -545
- package/src/self-dev/orchestrate-cli.ts +57 -2
- package/src/self-dev/orchestrate-summary-line.ts +13 -0
- package/src/self-dev/orchestrate.ts +9 -133
- package/src/self-dev/review-provider-fallback.ts +179 -0
- package/src/self-dev/run-store.ts +1 -3
- package/src/self-dev/run-supervisor.ts +8 -23
- package/src/self-dev/run-types.ts +178 -0
- package/src/self-dev/shard-aggregate.ts +61 -13
- package/src/self-dev/shard-plan.ts +5 -1
- package/src/self-dev/shard-run.ts +23 -5
- package/src/self-dev/supervisor-verdict-edges.ts +2 -4
- package/src/self-implement/blocked-draft-policy.ts +3 -19
- package/src/self-implement/draft-on-stop-mode.ts +18 -0
- package/src/self-implement/follow-up-goals.ts +114 -38
- package/src/self-implement/gate-baseline-reap.ts +157 -0
- package/src/self-implement/gate-baseline.ts +78 -16
- package/src/self-implement/gate-cli.ts +12 -2
- package/src/self-implement/gate-remote.ts +17 -6
- package/src/self-implement/goal-author.ts +24 -4
- package/src/self-implement/goal-digest.ts +19 -0
- package/src/self-implement/graph-overlay-condition.ts +4 -0
- package/src/self-implement/harness-policy-gates.ts +7 -5
- package/src/self-implement/headless-elanous-driver.ts +11 -9
- package/src/self-implement/host-regate.ts +148 -43
- package/src/self-implement/l8-merge-queue.ts +147 -13
- package/src/self-implement/merge-train.ts +131 -0
- package/src/self-implement/off-diff-evidence.ts +9 -0
- package/src/self-implement/orchestrator.ts +201 -43
- package/src/self-implement/review-finding-recurrence.ts +28 -0
- package/src/self-implement/rework-policy.ts +2 -1
- package/src/self-implement/round-summary-card.ts +63 -0
- package/src/self-implement/run-ledger.ts +4 -3
- package/src/self-implement/run-step-projection.ts +147 -0
- package/src/self-implement/run-stop.ts +1 -1
- package/src/self-implement/seams.ts +41 -6
- package/src/self-implement/self-implement-cli.ts +6 -0
- package/src/self-implement/train-gate-remote.ts +158 -0
- package/src/session-runtime/index.ts +10 -1
- package/src/session-runtime/retry-api.ts +11 -1
- package/src/shell-env-bootstrap.ts +19 -4
- package/src/skills/gift-install.ts +119 -0
- package/src/skills/runner.ts +59 -2
- package/src/skills/skill-feedback.ts +31 -1
- package/src/skills/skill-tier.ts +1 -0
- package/src/smart-wizard/capability-index.ts +231 -0
- package/src/smart-wizard/rung.ts +74 -0
- package/src/steward/launch.ts +20 -9
- package/src/steward/triage.ts +29 -10
- package/src/storage/file-lock.ts +40 -4
- package/src/task-agent/actions.ts +4 -0
- package/src/task-agent/card-evidence.ts +59 -13
- package/src/task-agent/completion-evidence.ts +31 -3
- package/src/task-agent/cover.ts +61 -0
- package/src/task-agent/judge.ts +4 -3
- package/src/task-agent/land-worktree.ts +201 -0
- package/src/task-agent/live-move-history.ts +133 -0
- package/src/task-agent/live-moves.ts +222 -12
- package/src/task-agent/parent-host.ts +117 -8
- package/src/task-agent/rejudge-on-head.ts +297 -0
- package/src/task-agent/review-result-capture.ts +218 -0
- package/src/task-agent/shadow.ts +118 -7
- package/src/task-agent/task-hand.ts +138 -11
- package/src/task-orchestrator/surfaces/pod-child-providers.ts +29 -0
- package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
- package/src/task-orchestrator/surfaces/pod-failure-reason.ts +16 -2
- package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
- package/src/task-orchestrator/surfaces/pod-lease.ts +93 -12
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +25 -2
- package/src/task-orchestrator/surfaces/pod-pool.ts +203 -28
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +259 -36
- package/src/task-orchestrator/surfaces/self-implement.ts +11 -0
- package/src/telegram-commands.ts +8 -0
- package/src/telegram-project-command.ts +6 -0
- package/src/telegram-service.ts +5 -1
- package/src/telegram.ts +17 -4
- package/src/time/format.ts +13 -4
- package/src/tool-runtime/goal-author-runtime.ts +1 -0
- package/src/tool-runtime/self-cognition-catalog.ts +23 -0
- package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
- package/src/typecheck-ratchet.ts +2 -1
- package/src/user-config.ts +167 -28
- package/src/ux-sim/slash-menu-frames.ts +168 -0
- package/src/version/packed-revision.json +1 -1
- package/src/web-terminal/preview-tap-registry.ts +5 -2
- package/src/workflow-runtime/executor.ts +24 -2
- package/src/workflow-runtime/triggers/registry.ts +27 -0
- package/src/workflow-runtime/triggers/schedule-source.ts +30 -3
- package/src/workflow-runtime/triggers/scheduler.ts +1 -0
- package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
- package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
- package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
- package/apps/pwa/out/_next/static/chunks/1307-c97eba9fb72a9a5e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
- package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
- package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
- package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
- package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
- package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
- package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
- package/apps/pwa/out/_next/static/chunks/2489-ff55a35b202c0f94.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
- package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3857-995ea9f5ef33d71e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
- package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
- package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
- package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
- package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
- package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5977-59fedea50d13c762.js +0 -1
- package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
- package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
- package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
- package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
- package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
- package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
- package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
- package/apps/pwa/out/_next/static/chunks/8857-f1762140ef9a96b1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
- package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9247-7581825d511a64c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
- package/apps/pwa/out/_next/static/chunks/9497-b0e758d1cd4ae8d7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-937c92292a4ab4f0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d781be3e3a9cfd74.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-b0a80997903852d8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/botlab/page-2b1263165630d9c8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ea998f7f5d156bea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ceo/page-33c328b64ca508f8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-e2d6bed48ac20120.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-544dd4bd4847eeb7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/decisions/page-3ee191319bf97d87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-e4bcb2c503dab04b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-300897dcbbd5ed76.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a449f1ed472b81c2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-9045094d6d3b5cd0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/inside/page-c06673596849ef45.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-103fa3191c1b2e08.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-9f81233f29dcd409.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-be8b4615c919e36c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live-run/page-c685b104e0dfa609.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/loops/page-8d693331cfbb6add.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-cef4f30a4c22fae1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66ea1b54fc83fa15.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-7a12f61be4a579d1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-c85b0589591a99c9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-725a4da02dd129eb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8cc707bd09a497d9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-90b55be1f15ce0e8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cb16606e08be65db.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-16dc64b74ed6a40a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-21bec4afeb2f0917.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-dc39ee7a36d26385.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-84ae759f76053672.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-3db58ddb61fe2be9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c5315e30f3528dc4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-2fe368efb6de3b6a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8d04132dd0ac5e10.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-f23484de467c9ea3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-c69762987b751174.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-5456692bda39aafb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-d75f7cd65845ce98.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-5603f5e568b25ce3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-d2cc0f4e89f42028.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-a6eb73b8a4840f1c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-c0a3f4d10edb83fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6c0b88068c143f15.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-7f8d7fcdf058a845.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-22163556cd38bc88.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-141436fd26dd56fc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
- package/apps/pwa/out/_next/static/css/e81df11490b4413b.css +0 -1
- /package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Database } from 'bun:sqlite';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
|
|
6
|
+
import { elanousStateRoot } from '../../autopilot/state-paths.js';
|
|
7
|
+
import { debug } from '../../debug/log.js';
|
|
8
|
+
import { registerStandaloneLogSink } from '../../domains/standalone-log-sink.js';
|
|
9
|
+
import { LogStore, logsDbPath } from './log-store.js';
|
|
10
|
+
|
|
11
|
+
type HorizonStatus = 'present' | 'empty' | 'unreadable';
|
|
12
|
+
type Attribution = 'first-sample' | 'none' | 'attributed' | 'unattributed-loss';
|
|
13
|
+
|
|
14
|
+
export interface HorizonSample {
|
|
15
|
+
atMs: number;
|
|
16
|
+
oldestTsMs: number | null;
|
|
17
|
+
status: HorizonStatus;
|
|
18
|
+
spanHours: number | null;
|
|
19
|
+
advancedMs: number;
|
|
20
|
+
deletedEvents: number;
|
|
21
|
+
attribution: Attribution;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type HorizonTick = HorizonSample & { outcome: 'ok' | 'fail' };
|
|
25
|
+
|
|
26
|
+
export interface HorizonWatchOptions { db?: string; state?: string }
|
|
27
|
+
export interface HorizonWatchDeps {
|
|
28
|
+
openStore?: (path: string) => Pick<LogStore, 'horizon' | 'queryAll' | 'close'>;
|
|
29
|
+
now?: () => number;
|
|
30
|
+
stateDir?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function lastReadableSample(path: string): HorizonSample | null {
|
|
34
|
+
let content = '';
|
|
35
|
+
try { content = readFileSync(path, 'utf8'); }
|
|
36
|
+
catch (error) {
|
|
37
|
+
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
|
|
38
|
+
}
|
|
39
|
+
for (const line of content.trimEnd().split('\n').reverse()) {
|
|
40
|
+
if (!line) continue;
|
|
41
|
+
const sample = JSON.parse(line) as HorizonSample;
|
|
42
|
+
if (sample.status !== 'unreadable') return sample;
|
|
43
|
+
}
|
|
44
|
+
try { return JSON.parse(readFileSync(join(dirname(path), 'last-readable.json'), 'utf8')) as HorizonSample; }
|
|
45
|
+
catch (error) {
|
|
46
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null;
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function saveReadableCheckpoint(path: string, sample: HorizonSample): void {
|
|
52
|
+
const checkpoint = join(dirname(path), 'last-readable.json');
|
|
53
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
54
|
+
const temporary = `${checkpoint}.${process.pid}.${randomUUID()}.tmp`;
|
|
55
|
+
try {
|
|
56
|
+
writeFileSync(temporary, JSON.stringify(sample) + '\n');
|
|
57
|
+
renameSync(temporary, checkpoint);
|
|
58
|
+
} finally { rmSync(temporary, { force: true }); }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function saveSample(path: string, sample: HorizonSample): void {
|
|
62
|
+
let lines: string[];
|
|
63
|
+
try { lines = readFileSync(path, 'utf8').trimEnd().split('\n').filter(Boolean); }
|
|
64
|
+
catch (error) {
|
|
65
|
+
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
|
|
66
|
+
lines = [];
|
|
67
|
+
}
|
|
68
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
69
|
+
const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
70
|
+
try {
|
|
71
|
+
writeFileSync(temporary, [...lines.slice(-499), JSON.stringify(sample)].join('\n') + '\n');
|
|
72
|
+
renameSync(temporary, path);
|
|
73
|
+
} finally { rmSync(temporary, { force: true }); }
|
|
74
|
+
if (sample.status !== 'unreadable') saveReadableCheckpoint(path, sample);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Read the store only; samples live outside logs.db and observations go through debug sinks. */
|
|
78
|
+
export function runHorizonWatchTick(opts: HorizonWatchOptions = {}, deps: HorizonWatchDeps = {}): HorizonTick {
|
|
79
|
+
const path = join(deps.stateDir ?? opts.state ?? join(elanousStateRoot(), 'log-horizon'), 'samples.jsonl');
|
|
80
|
+
// Serialize the entire read/compare/append transaction across cron and manual processes.
|
|
81
|
+
// This lock database is in the sample state directory, never in logs.db.
|
|
82
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
83
|
+
const lock = new Database(join(dirname(path), 'samples.lock.db'));
|
|
84
|
+
try {
|
|
85
|
+
lock.run('PRAGMA busy_timeout = 120000');
|
|
86
|
+
lock.run('BEGIN IMMEDIATE');
|
|
87
|
+
try {
|
|
88
|
+
return recordSample();
|
|
89
|
+
} finally {
|
|
90
|
+
lock.run('ROLLBACK');
|
|
91
|
+
}
|
|
92
|
+
} finally {
|
|
93
|
+
lock.close();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function recordSample(): HorizonTick {
|
|
97
|
+
const now = deps.now ?? Date.now;
|
|
98
|
+
// The tick clock is read *after* the horizon read (see below), so every `deleted` event logged before the
|
|
99
|
+
// horizon was observed has ts <= atMs. Windows are half-open (prev.atMs, atMs]: each event is counted once.
|
|
100
|
+
let atMs: number | undefined;
|
|
101
|
+
let oldestTsMs: number | null = null;
|
|
102
|
+
let status: HorizonStatus = 'unreadable';
|
|
103
|
+
let deletedEvents = 0;
|
|
104
|
+
let store: ReturnType<NonNullable<HorizonWatchDeps['openStore']>> | undefined;
|
|
105
|
+
let previous: HorizonSample | null = null;
|
|
106
|
+
try {
|
|
107
|
+
store = (deps.openStore ?? LogStore.openReadOnly)(opts.db ?? logsDbPath());
|
|
108
|
+
const horizon = store.horizon();
|
|
109
|
+
atMs = now();
|
|
110
|
+
status = horizon.status;
|
|
111
|
+
oldestTsMs = horizon.status === 'present' ? horizon.oldestTsMs : null;
|
|
112
|
+
previous = lastReadableSample(path);
|
|
113
|
+
if (previous) {
|
|
114
|
+
deletedEvents = store.queryAll({
|
|
115
|
+
exactCategories: ['log-store.retention'], events: ['deleted'], sinceMs: previous.atMs + 1, untilMs: atMs,
|
|
116
|
+
}).length;
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
debug.log('log-store.horizon', 'read-failed', { reason: String(error) }, { level: 'warn' });
|
|
120
|
+
status = 'unreadable';
|
|
121
|
+
oldestTsMs = null;
|
|
122
|
+
} finally { store?.close(); }
|
|
123
|
+
atMs ??= now();
|
|
124
|
+
|
|
125
|
+
const advancedMs = status === 'present' && previous?.status === 'present' && previous.oldestTsMs !== null
|
|
126
|
+
? Math.max(0, oldestTsMs! - previous.oldestTsMs) : 0;
|
|
127
|
+
const attribution: Attribution = status === 'unreadable' ? 'none'
|
|
128
|
+
: !previous ? 'first-sample'
|
|
129
|
+
: advancedMs === 0 ? 'none'
|
|
130
|
+
: deletedEvents > 0 ? 'attributed' : 'unattributed-loss';
|
|
131
|
+
const sample: HorizonSample = {
|
|
132
|
+
atMs, oldestTsMs, status,
|
|
133
|
+
spanHours: oldestTsMs === null ? null : (atMs - oldestTsMs) / 3_600_000,
|
|
134
|
+
advancedMs, deletedEvents, attribution,
|
|
135
|
+
};
|
|
136
|
+
try { saveSample(path, sample); }
|
|
137
|
+
catch (error) {
|
|
138
|
+
debug.log('log-store.horizon', 'sample-write-failed', { reason: String(error) }, { level: 'warn' });
|
|
139
|
+
return { ...sample, outcome: 'fail' };
|
|
140
|
+
}
|
|
141
|
+
debug.log('log-store.horizon', 'sample', {
|
|
142
|
+
oldestTs: oldestTsMs === null ? null : new Date(oldestTsMs).toISOString(),
|
|
143
|
+
spanHours: sample.spanHours, advancedMs, deletedEvents, attribution,
|
|
144
|
+
}, { level: attribution === 'unattributed-loss' ? 'warn' : 'info' });
|
|
145
|
+
return { ...sample, outcome: status === 'unreadable' ? 'fail' : 'ok' };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (import.meta.main) {
|
|
150
|
+
const args = process.argv.slice(2);
|
|
151
|
+
const opts: HorizonWatchOptions = {};
|
|
152
|
+
let json = false;
|
|
153
|
+
for (let i = 0; i < args.length; i++) {
|
|
154
|
+
const arg = args[i];
|
|
155
|
+
if (arg === '--json') json = true;
|
|
156
|
+
else if (arg === '--db' && args[i + 1]) opts.db = args[++i];
|
|
157
|
+
else if (arg === '--state' && args[i + 1]) opts.state = args[++i];
|
|
158
|
+
else { process.stderr.write(`Unknown or incomplete option: ${arg}\n`); process.exit(1); }
|
|
159
|
+
}
|
|
160
|
+
const sinkReady = await registerStandaloneLogSink('log-horizon');
|
|
161
|
+
// A sink failure must not suppress the sample: the store read (and an 'unreadable' record) still happens,
|
|
162
|
+
// but the tick cannot claim success because its observation never reached logs.db.
|
|
163
|
+
const tick = runHorizonWatchTick(opts);
|
|
164
|
+
const result = sinkReady ? tick : { ...tick, outcome: 'fail' as const, reason: 'log-sink-registration-failed' };
|
|
165
|
+
if (json) process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
166
|
+
else process.stdout.write(`${result.outcome}: ${result.attribution} (${result.status})${sinkReady ? '' : ' · log-sink-registration-failed'}\n`);
|
|
167
|
+
if (result.outcome === 'fail') process.exitCode = 1;
|
|
168
|
+
}
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
// severity 는 SCHEME(이벤트 접미사) → `level` 컬럼으로 물질화.
|
|
18
18
|
|
|
19
19
|
import { Database } from 'bun:sqlite';
|
|
20
|
-
import { mkdirSync } from 'node:fs';
|
|
20
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
21
|
+
import { randomUUID } from 'node:crypto';
|
|
21
22
|
import { elanousStateRoot } from '../../autopilot/state-paths.js';
|
|
22
23
|
import { dirname, join } from 'node:path';
|
|
23
24
|
|
|
@@ -81,9 +82,13 @@ export interface LogStoreRetention {
|
|
|
81
82
|
maxAgeDays: number;
|
|
82
83
|
/** DB 상한(MB). 초과 시 오래된 행부터 삭제. 0 이하 = 크기 정리 안 함. 기본 500. */
|
|
83
84
|
maxDbMb: number;
|
|
85
|
+
/** 🩸 LOGS-RETENTION-WINDOW-1(10-10): size-cap floor in hours — the size pass never deletes rows newer than
|
|
86
|
+
* this; when rows outside the floor are not enough it stops and logs `retention-floor-held`.
|
|
87
|
+
* 0 = legacy behaviour (oldest-first with no floor). Missing = 24. Age pass (`maxAgeDays`) is unaffected. */
|
|
88
|
+
minRetainHours?: number;
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
export const LOG_RETENTION_DEFAULTS: LogStoreRetention = { maxAgeDays: 7, maxDbMb: 500 };
|
|
91
|
+
export const LOG_RETENTION_DEFAULTS: LogStoreRetention = { maxAgeDays: 7, maxDbMb: 500, minRetainHours: 24 };
|
|
87
92
|
|
|
88
93
|
/** 스토어 OOM 백스톱 — 정책 상한이 아니다. 정책은 각 경계(HTTP·툴)가 갖는다. */
|
|
89
94
|
export const STORE_SAFETY_MAX = 100_000;
|
|
@@ -360,22 +365,65 @@ export class LogStore {
|
|
|
360
365
|
}
|
|
361
366
|
if (policy.maxDbMb > 0) {
|
|
362
367
|
const pageCount = (this.db.query('PRAGMA page_count').get() as { page_count: number }).page_count;
|
|
368
|
+
const freePages = (this.db.query('PRAGMA freelist_count').get() as { freelist_count: number }).freelist_count;
|
|
363
369
|
const pageSize = (this.db.query('PRAGMA page_size').get() as { page_size: number }).page_size;
|
|
364
|
-
|
|
370
|
+
// 🩸 OBS-RET-RATCHET(2026-10-09): 빈 페이지까지 세면 VACUUM 없는 파일은 안 줄어든다 → 뜰 때마다 오래된 행 ≈5% 를
|
|
371
|
+
// 또 지우는 래칫이 됐다(운영 logs.db 528MB · 01:08Z 이전 행 소실). 상한은 «쓰는 페이지»로 잰다.
|
|
372
|
+
const sizeMb = ((pageCount - freePages) * pageSize) / (1024 * 1024);
|
|
365
373
|
if (sizeMb > policy.maxDbMb) {
|
|
366
374
|
// 초과분 비율만큼 오래된 행 삭제(대략 — 정밀 계산보다 반복 수렴 선호).
|
|
367
375
|
const total = (this.db.query('SELECT COUNT(*) AS c FROM logs').get() as { c: number }).c;
|
|
368
376
|
const dropCount = Math.max(1, Math.floor(total * Math.min(0.5, 1 - policy.maxDbMb / sizeMb)));
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
)
|
|
373
|
-
|
|
377
|
+
// 🩸 LOGS-RETENTION-WINDOW-1(10-10): prod write volume made this pass keep only ≈2h of rows, so evidence
|
|
378
|
+
// for incidents a few hours old read as «0 rows». Rows inside the floor are never size-deleted.
|
|
379
|
+
const floorHours = policy.minRetainHours ?? LOG_RETENTION_DEFAULTS.minRetainHours ?? 0;
|
|
380
|
+
if (floorHours > 0) {
|
|
381
|
+
const floorCutoff = Date.now() - floorHours * 3_600_000;
|
|
382
|
+
// Byte-weighted split (payload text + fixed per-row overhead) — row counts alone misjudge mixed row sizes.
|
|
383
|
+
const split = this.db.query(
|
|
384
|
+
`SELECT COALESCE(SUM(CASE WHEN ts_ms < ? THEN w ELSE 0 END), 0) AS outsideBytes, COALESCE(SUM(w), 0) AS allBytes
|
|
385
|
+
FROM (SELECT ts_ms, 64 + LENGTH(ts) + LENGTH(category) + LENGTH(event) + COALESCE(LENGTH(data), 0) AS w FROM logs)`,
|
|
386
|
+
).get(floorCutoff) as { outsideBytes: number; allBytes: number };
|
|
387
|
+
const r = this.db.run(
|
|
388
|
+
'DELETE FROM logs WHERE id IN (SELECT id FROM logs WHERE ts_ms < ? ORDER BY ts_ms ASC LIMIT ?)',
|
|
389
|
+
[floorCutoff, dropCount],
|
|
390
|
+
);
|
|
391
|
+
deletedBySize = Number(r.changes ?? 0);
|
|
392
|
+
// dropCount is capped at 50% per run; judge the floor against the full overshoot (by bytes) so a cap the
|
|
393
|
+
// floor can never reach is reported even when this run's capped batch was fully served from outside rows.
|
|
394
|
+
const neededShare = 1 - policy.maxDbMb / sizeMb;
|
|
395
|
+
const outsideShare = split.allBytes > 0 ? split.outsideBytes / split.allBytes : 0;
|
|
396
|
+
if (outsideShare < neededShare) {
|
|
397
|
+
debug.log('mss.logging', 'retention-floor-held', {
|
|
398
|
+
totalMb: Math.round(sizeMb * 10) / 10, maxTotalMb: policy.maxDbMb, floorHours,
|
|
399
|
+
neededShare: Math.round(neededShare * 1000) / 1000, outsideShare: Math.round(outsideShare * 1000) / 1000,
|
|
400
|
+
deletedRows: deletedBySize,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
} else {
|
|
404
|
+
const r = this.db.run(
|
|
405
|
+
'DELETE FROM logs WHERE id IN (SELECT id FROM logs ORDER BY ts_ms ASC LIMIT ?)',
|
|
406
|
+
[dropCount],
|
|
407
|
+
);
|
|
408
|
+
deletedBySize = Number(r.changes ?? 0);
|
|
409
|
+
}
|
|
374
410
|
}
|
|
375
411
|
}
|
|
412
|
+
if (deletedByAge > 0 || deletedBySize > 0) {
|
|
413
|
+
const oldest = (this.db.query('SELECT MIN(ts_ms) AS t FROM logs').get() as { t: number | null }).t;
|
|
414
|
+
debug.log('log-store.retention', 'deleted', { deletedByAge, deletedBySize, oldestTs: oldest === null ? null : new Date(oldest).toISOString() });
|
|
415
|
+
}
|
|
376
416
|
return { deletedByAge, deletedBySize };
|
|
377
417
|
}
|
|
378
418
|
|
|
419
|
+
/** Reclaim a bounded number of free pages after retention; legacy databases with auto_vacuum=NONE remain unchanged. */
|
|
420
|
+
reclaimFreePages(): void {
|
|
421
|
+
const mode = (this.db.query('PRAGMA auto_vacuum').get() as { auto_vacuum: number }).auto_vacuum;
|
|
422
|
+
if (mode !== 2) return;
|
|
423
|
+
const free = (this.db.query('PRAGMA freelist_count').get() as { freelist_count: number }).freelist_count;
|
|
424
|
+
if (free > 0) this.db.run(`PRAGMA incremental_vacuum(${Math.min(free, 128)})`);
|
|
425
|
+
}
|
|
426
|
+
|
|
379
427
|
/**
|
|
380
428
|
* ⛔⭐⭐⭐ **이 스토어에 «실제로 뜬» 카테고리와 그 수**(2026-08-19 · `OBS-T122`).
|
|
381
429
|
*
|
|
@@ -658,6 +706,12 @@ export class LogStore {
|
|
|
658
706
|
return (this.db.query('SELECT COUNT(*) AS c FROM logs').get() as { c: number }).c;
|
|
659
707
|
}
|
|
660
708
|
|
|
709
|
+
/** Earliest retained event timestamp, regardless of insertion order. No schema or row writes. */
|
|
710
|
+
horizon(): { status: 'present'; oldestTsMs: number } | { status: 'empty' } {
|
|
711
|
+
const { oldestTsMs } = this.db.query('SELECT MIN(ts_ms) AS oldestTsMs FROM logs').get() as { oldestTsMs: number | null };
|
|
712
|
+
return oldestTsMs === null ? { status: 'empty' } : { status: 'present', oldestTsMs };
|
|
713
|
+
}
|
|
714
|
+
|
|
661
715
|
close(): void {
|
|
662
716
|
try { this.db.close(); } catch { /* noop */ }
|
|
663
717
|
}
|
|
@@ -850,28 +904,163 @@ export class StoreSink implements LogSink {
|
|
|
850
904
|
}
|
|
851
905
|
}
|
|
852
906
|
|
|
907
|
+
const RETENTION_INTERVAL_MS = 6 * 3600 * 1000;
|
|
908
|
+
type RetentionLockOwner = { token: string; pid: number; start: string | null };
|
|
909
|
+
|
|
910
|
+
/** PID reuse must not let a new process inherit a dead process's ownership. */
|
|
911
|
+
function processStart(pid: number): string | null {
|
|
912
|
+
try {
|
|
913
|
+
const stat = readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
914
|
+
return stat.slice(stat.lastIndexOf(')') + 2).split(' ')[19] ?? null;
|
|
915
|
+
} catch { return null; }
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
function ownerDead(owner: RetentionLockOwner): boolean {
|
|
919
|
+
if (!Number.isSafeInteger(owner.pid) || owner.pid <= 0) return false;
|
|
920
|
+
try {
|
|
921
|
+
process.kill(owner.pid, 0);
|
|
922
|
+
const currentStart = processStart(owner.pid);
|
|
923
|
+
if (owner.start !== null && currentStart !== null && owner.start !== currentStart) return true;
|
|
924
|
+
// A zombie still answers kill(pid, 0), but can no longer run retention.
|
|
925
|
+
try {
|
|
926
|
+
const stat = readFileSync(`/proc/${owner.pid}/stat`, 'utf8');
|
|
927
|
+
return stat.slice(stat.lastIndexOf(')') + 2).startsWith('Z ');
|
|
928
|
+
} catch { return false; }
|
|
929
|
+
} catch (error) {
|
|
930
|
+
return (error as NodeJS.ErrnoException).code === 'ESRCH';
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/** Only the guard row can authorize removal. A pre-publication temp file belongs to its row's token. */
|
|
935
|
+
function removeRetentionLockDirectory(lockPath: string, token: string, interrupted: boolean): void {
|
|
936
|
+
if (!existsSync(lockPath)) return;
|
|
937
|
+
const marker = join(lockPath, 'owner');
|
|
938
|
+
const temporaryName = `owner.${token}.tmp`;
|
|
939
|
+
if (readdirSync(lockPath).some((name) => name !== 'owner' && name !== temporaryName)) {
|
|
940
|
+
throw new Error('retention lock has unknown entries');
|
|
941
|
+
}
|
|
942
|
+
if (existsSync(marker)) {
|
|
943
|
+
const published = readFileSync(marker, 'utf8');
|
|
944
|
+
if (published !== token && !(interrupted && token.startsWith(published))) {
|
|
945
|
+
throw new Error('retention lock owner changed');
|
|
946
|
+
}
|
|
947
|
+
rmSync(marker);
|
|
948
|
+
}
|
|
949
|
+
rmSync(join(lockPath, temporaryName), { force: true });
|
|
950
|
+
rmdirSync(lockPath);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/** The SQLite guard serializes stale-lock recovery and ownership changes, including process death mid-acquisition. */
|
|
954
|
+
function acquireRetentionLock(lockPath: string): (() => void) | null {
|
|
955
|
+
const guard = new Database(`${lockPath}.db`);
|
|
956
|
+
const token = randomUUID();
|
|
957
|
+
let handedOff = false;
|
|
958
|
+
try {
|
|
959
|
+
guard.run('PRAGMA busy_timeout = 100');
|
|
960
|
+
guard.run('CREATE TABLE IF NOT EXISTS owner (slot INTEGER PRIMARY KEY CHECK(slot = 1), token TEXT NOT NULL, pid INTEGER NOT NULL, start TEXT)');
|
|
961
|
+
let acquired = false;
|
|
962
|
+
guard.run('BEGIN IMMEDIATE');
|
|
963
|
+
try {
|
|
964
|
+
const previous = guard.query('SELECT token, pid, start FROM owner WHERE slot = 1').get() as RetentionLockOwner | null;
|
|
965
|
+
if (previous && !ownerDead(previous)) return null;
|
|
966
|
+
if (existsSync(lockPath)) {
|
|
967
|
+
// A pre-guard lock has no provable owner: never remove it.
|
|
968
|
+
if (!previous) return null;
|
|
969
|
+
try { removeRetentionLockDirectory(lockPath, previous.token, true); }
|
|
970
|
+
catch { return null; }
|
|
971
|
+
}
|
|
972
|
+
guard.run('INSERT OR REPLACE INTO owner (slot, token, pid, start) VALUES (1, ?, ?, ?)', [token, process.pid, processStart(process.pid)]);
|
|
973
|
+
guard.run('COMMIT');
|
|
974
|
+
acquired = true;
|
|
975
|
+
} finally {
|
|
976
|
+
if (!acquired) guard.run('ROLLBACK');
|
|
977
|
+
}
|
|
978
|
+
// The ownership row is committed before mkdir: a crash in this gap is recoverable too.
|
|
979
|
+
try {
|
|
980
|
+
mkdirSync(lockPath);
|
|
981
|
+
const temporary = join(lockPath, `owner.${token}.tmp`);
|
|
982
|
+
writeFileSync(temporary, token, { flag: 'wx' });
|
|
983
|
+
renameSync(temporary, join(lockPath, 'owner'));
|
|
984
|
+
} catch (error) {
|
|
985
|
+
guard.run('BEGIN IMMEDIATE');
|
|
986
|
+
try {
|
|
987
|
+
// Keep the ownership row if cleanup fails: the next process can then
|
|
988
|
+
// prove who left the directory behind and recover it after this PID dies.
|
|
989
|
+
removeRetentionLockDirectory(lockPath, token, true);
|
|
990
|
+
guard.run('DELETE FROM owner WHERE slot = 1 AND token = ?', [token]);
|
|
991
|
+
guard.run('COMMIT');
|
|
992
|
+
} catch { guard.run('ROLLBACK'); }
|
|
993
|
+
throw error;
|
|
994
|
+
}
|
|
995
|
+
handedOff = true;
|
|
996
|
+
return () => {
|
|
997
|
+
try {
|
|
998
|
+
guard.run('BEGIN IMMEDIATE');
|
|
999
|
+
try {
|
|
1000
|
+
const current = guard.query('SELECT token FROM owner WHERE slot = 1').get() as { token: string } | null;
|
|
1001
|
+
if (current?.token === token) {
|
|
1002
|
+
removeRetentionLockDirectory(lockPath, token, false);
|
|
1003
|
+
guard.run('DELETE FROM owner WHERE slot = 1 AND token = ?', [token]);
|
|
1004
|
+
}
|
|
1005
|
+
guard.run('COMMIT');
|
|
1006
|
+
} catch (error) { guard.run('ROLLBACK'); throw error; }
|
|
1007
|
+
} finally { guard.close(); }
|
|
1008
|
+
};
|
|
1009
|
+
} finally { if (!handedOff) guard.close(); }
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
/** A shared stamp prevents short-lived non-owner processes from repeatedly pruning the same DB. */
|
|
1013
|
+
function runStampedRetention(store: LogStore, retention: LogStoreRetention, owner: boolean): void {
|
|
1014
|
+
const stampPath = `${store.path}.retention.stamp`;
|
|
1015
|
+
const lockPath = `${store.path}.retention.lock`;
|
|
1016
|
+
const isFresh = (): boolean => {
|
|
1017
|
+
try {
|
|
1018
|
+
const age = Date.now() - Number(readFileSync(stampPath, 'utf8'));
|
|
1019
|
+
return age >= 0 && age < RETENTION_INTERVAL_MS;
|
|
1020
|
+
} catch { return false; }
|
|
1021
|
+
};
|
|
1022
|
+
if (!owner && isFresh()) return;
|
|
1023
|
+
const release = acquireRetentionLock(lockPath);
|
|
1024
|
+
if (!release) return;
|
|
1025
|
+
try {
|
|
1026
|
+
if (!owner && isFresh()) return;
|
|
1027
|
+
store.enforceRetention(retention);
|
|
1028
|
+
try { store.reclaimFreePages(); }
|
|
1029
|
+
catch (error) { debug.log('log-store.retention', 'reclaim-failed', { reason: error instanceof Error ? error.message : String(error) }); }
|
|
1030
|
+
const temporary = `${stampPath}.${process.pid}.${randomUUID()}.tmp`;
|
|
1031
|
+
try {
|
|
1032
|
+
writeFileSync(temporary, String(Date.now()));
|
|
1033
|
+
renameSync(temporary, stampPath);
|
|
1034
|
+
} finally { rmSync(temporary, { force: true }); }
|
|
1035
|
+
} finally { release(); }
|
|
1036
|
+
}
|
|
1037
|
+
|
|
853
1038
|
/** 부팅 1줄 등록 헬퍼 — 데몬/TUI/러너가 자기 surface 를 선언하고 스토어
|
|
854
1039
|
* 싱크를 단다. retention 은 호출측이 config 에서 읽어 전달(user-config
|
|
855
|
-
* 순환 의존 회피). 반환 = unregister(테스트용) 또는 null(store 불가).
|
|
1040
|
+
* 순환 의존 회피). 반환 = unregister(테스트용) 또는 null(store 불가).
|
|
1041
|
+
* nexus owns the periodic job unless the caller explicitly opts in. */
|
|
856
1042
|
export function registerLogStoreSink(
|
|
857
1043
|
registerSink: (sink: LogSink) => () => void,
|
|
858
1044
|
surface: string,
|
|
859
1045
|
retention: LogStoreRetention = LOG_RETENTION_DEFAULTS,
|
|
1046
|
+
opts: { retentionOwner?: boolean } = {},
|
|
860
1047
|
): (() => void) | null {
|
|
861
1048
|
const store = getDefaultLogStore();
|
|
862
1049
|
if (!store) return null;
|
|
863
1050
|
const sink = new StoreSink(store, surface, { installExitHandlers: true });
|
|
864
1051
|
const off = registerSink(sink);
|
|
865
1052
|
try { nestDepth.observeNestAtBoot(); } catch { /* fail-soft — 관측 실패가 싱크 등록을 막지 않는다. */ }
|
|
866
|
-
|
|
1053
|
+
const owner = opts.retentionOwner ?? surface === 'nexus';
|
|
867
1054
|
const runRetention = (): void => {
|
|
868
|
-
try { store
|
|
1055
|
+
try { runStampedRetention(store, retention, owner); }
|
|
1056
|
+
catch (error) { debug.log('log-store.retention', 'failed', { reason: error instanceof Error ? error.message : String(error) }); }
|
|
869
1057
|
};
|
|
870
|
-
setImmediate(runRetention);
|
|
871
|
-
const h = setInterval(runRetention,
|
|
872
|
-
(h as unknown as { unref?: () => void })
|
|
1058
|
+
const startup = setImmediate(runRetention);
|
|
1059
|
+
const h = owner ? setInterval(runRetention, RETENTION_INTERVAL_MS) : null;
|
|
1060
|
+
(h as unknown as { unref?: () => void } | null)?.unref?.();
|
|
873
1061
|
return () => {
|
|
874
|
-
|
|
1062
|
+
clearImmediate(startup);
|
|
1063
|
+
if (h) clearInterval(h);
|
|
875
1064
|
sink.close();
|
|
876
1065
|
off();
|
|
877
1066
|
};
|
|
@@ -93,3 +93,20 @@ export function redactLogRecord(rec: LogRecord, opts: RedactOpts = {}): LogRecor
|
|
|
93
93
|
const mask = opts.mask ?? defaultMask;
|
|
94
94
|
return { ...rec, data: redactValue(rec.data, keyBlock, mask, new WeakSet()) };
|
|
95
95
|
}
|
|
96
|
+
|
|
97
|
+
/** Pre-bundle knowledge-pack DLP. Reasons are fixed labels, never source text or secret values.
|
|
98
|
+
* This is separate from the opt-in log masking path above. */
|
|
99
|
+
const KNOWLEDGE_PACK_DLP_RULES: ReadonlyArray<{ reason: string; pattern: RegExp }> = [
|
|
100
|
+
{ reason: 'secret-value', pattern: /-----BEGIN (?:[A-Z0-9_-]+ )?PRIVATE KEY(?: BLOCK)?-----|\bBearer\s+[A-Za-z0-9._~+/-]{12,}={0,2}\b|\b(?:sk-[A-Za-z0-9_-]{16,}|xai-[A-Za-z0-9_-]{20,}|gh[pousr]_[A-Za-z0-9_]{12,}|github_pat_[A-Za-z0-9_]{12,}|xox[baprs]-[A-Za-z0-9-]{12,}|(?:AKIA|ASIA|ABIA|ACCA)[A-Z2-7]{16}|AIza[A-Za-z0-9_-]{35})\b|\b(?:api[_-]?key|secret[_-]?key|access[_-]?token|private[_-]?key|token)['"]?\s*[=:]\s*['"]?[A-Za-z0-9_./+~-]{16,}/iu },
|
|
101
|
+
// A key that names a password/secret makes ANY assigned value secret: short or punctuated values count too.
|
|
102
|
+
// Schema flags (`"secret": true`) are not values.
|
|
103
|
+
{ reason: 'secret-value', pattern: /\b(?:password|passwd|pwd|passphrase|client[_-]?secret|secret)['"]?\s*[=:]\s*(?!(?:true|false|null)\b)(?:"[^"\n]+"|'[^'\n]+'|[^\s'",;{}\[\]]{4,})/iu },
|
|
104
|
+
{ reason: 'personal-information', pattern: /\b01[016789]-?\d{3,4}-?\d{4}\b|\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b|\b\d{6}-[1-8]\d{6}\b/iu },
|
|
105
|
+
{ reason: 'internal-identifier', pattern: /(?:사번|사내\s*식별자|내부\s*식별자|employee[_ -]?id|internal[_ -]?id)\s*(?:[:=]|\s)\s*[A-Za-z0-9][A-Za-z0-9_-]{3,}/iu },
|
|
106
|
+
{ reason: 'sales-confidential', pattern: /영업\s*기밀|(?:sales\s+confidential|confidential\s+sales|영업\s*비밀)/iu },
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
export function scanKnowledgePackDlp(text: string): string[] {
|
|
110
|
+
const reasons = KNOWLEDGE_PACK_DLP_RULES.filter(({ pattern }) => pattern.test(text)).map(({ reason }) => reason);
|
|
111
|
+
return [...new Set(reasons)];
|
|
112
|
+
}
|
|
@@ -9,7 +9,7 @@ import type { VerifierSpec } from './verifier/types.js';
|
|
|
9
9
|
import type { GuardianSpec } from './guardian/types.js';
|
|
10
10
|
import { ptyAvailable } from './pty-shell/registry.js';
|
|
11
11
|
import { krFlowAvailable } from './skills/tools/kr-flow.js';
|
|
12
|
-
import { SELF_COGNITION_MCP_CATALOG_ENTRIES } from './tool-runtime/self-cognition-
|
|
12
|
+
import { SELF_COGNITION_MCP_CATALOG_ENTRIES } from './tool-runtime/self-cognition-catalog.js';
|
|
13
13
|
import { SKILLS_LIST_DESCRIPTION } from './onboarding/entry-hints.js';
|
|
14
14
|
|
|
15
15
|
export type { NativeToolHost } from './tool-surface.js';
|
|
@@ -2,7 +2,7 @@ import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, re
|
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
4
|
import { debug } from '../../debug/log.js';
|
|
5
|
-
import {
|
|
5
|
+
import { sendTelegramReport } from '../../telegram-report.js';
|
|
6
6
|
import { getUserConfig } from '../../user-config.js';
|
|
7
7
|
import { effectiveInstanceRoot } from '../../instance/resolve.js';
|
|
8
8
|
import { jsonResponse } from './json-response.js';
|
|
@@ -23,7 +23,7 @@ interface ConsultRequest {
|
|
|
23
23
|
export interface ConsultRequestsDeps {
|
|
24
24
|
root?: () => string;
|
|
25
25
|
now?: () => string;
|
|
26
|
-
/** Owner alert. Default = the daemon's
|
|
26
|
+
/** Owner alert. Default = the daemon's in-process Telegram sender (operations role only).
|
|
27
27
|
* ⛔ Never `sendOutbound` here: it is a synchronous curl to this very daemon's `/v1/outbound`, so inside the
|
|
28
28
|
* daemon it blocks the event loop until it times out (~25 s · `unreachable`) and the alert is lost (CS1 · 10-01). */
|
|
29
29
|
send?: (text: string, kind: string) => unknown;
|
|
@@ -88,9 +88,9 @@ export async function handleConsultRequests(req: Request, deps: ConsultRequestsD
|
|
|
88
88
|
if (!body || typeof body !== 'object' || Array.isArray(body)) return rejected('body');
|
|
89
89
|
const input = body as Record<string, unknown>;
|
|
90
90
|
for (const field of ['name', 'contact'] as const) {
|
|
91
|
-
if (typeof input[field] !== 'string' || !input[field].trim()) return rejected(field);
|
|
91
|
+
if (typeof input[field] !== 'string' || !input[field].trim() || input[field].length > (field === 'name' ? 256 : 512)) return rejected(field);
|
|
92
92
|
}
|
|
93
|
-
if (input.org !== undefined && (typeof input.org !== 'string' || !input.org.trim())) return rejected('org');
|
|
93
|
+
if (input.org !== undefined && (typeof input.org !== 'string' || !input.org.trim() || input.org.length > 256)) return rejected('org');
|
|
94
94
|
if (input.kind !== 'company' && input.kind !== 'personal') return rejected('kind');
|
|
95
95
|
if (input.interest !== 'A' && input.interest !== 'B') return rejected('interest');
|
|
96
96
|
if (input.consent !== true) return rejected('consent');
|
|
@@ -114,15 +114,12 @@ export async function handleConsultRequests(req: Request, deps: ConsultRequestsD
|
|
|
114
114
|
const alert = `📮 상담 문의 ${entry.receiptId} · ${entry.name}(${entry.kind === 'personal' ? '개인' : (entry.org ?? '회사')}) · 관심 ${entry.interest}\n앱에서 보기`;
|
|
115
115
|
// Fire and forget — the receipt is already on disk; the answer must not wait for the channel.
|
|
116
116
|
void Promise.resolve()
|
|
117
|
-
.then(() => (deps.send ?? notifyInProcess)(alert, 'alert'))
|
|
117
|
+
.then(() => (deps.send ?? notifyInProcess)(alert, 'ops-alert'))
|
|
118
118
|
.catch((error: unknown) => { debug.log('consult.request', 'notify-failed', { receiptId: entry.receiptId, reason: error instanceof Error ? error.message : String(error) }); });
|
|
119
119
|
return jsonResponse({ receiptId: entry.receiptId, receivedAt: entry.receivedAt }, 202);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
async function notifyInProcess(text: string, kind: string): Promise<void> {
|
|
123
|
-
const
|
|
124
|
-
debug.log('consult.request',
|
|
125
|
-
delivered: result.delivered,
|
|
126
|
-
channels: result.channels.map((channel) => `${channel.type}:${channel.ok ? 'ok' : 'fail'}`),
|
|
127
|
-
});
|
|
123
|
+
const delivered = await sendTelegramReport(getUserConfig(), text, { markdown: false, kind });
|
|
124
|
+
debug.log('consult.request', delivered ? 'notified' : 'notify-failed', { delivered, channels: [`telegram:${delivered ? 'ok' : 'fail'}`] });
|
|
128
125
|
}
|
|
@@ -36,6 +36,7 @@ import { parseDiscordEndpoint, isOwnInstanceEndpoint } from '../../session/sessi
|
|
|
36
36
|
import { createDiscordStreamSink } from '../../session/streaming/discord-stream-sink.js';
|
|
37
37
|
import { splitForDiscord } from '../../discord.js';
|
|
38
38
|
import { formatForDiscord } from '../../discord-markdown.js';
|
|
39
|
+
import { receiveChannelEvent } from '../outbound/router.js';
|
|
39
40
|
|
|
40
41
|
export interface NexusDiscordTriggerBotOpts {
|
|
41
42
|
/** Bot token (without `Bot ` prefix). Production reads
|
|
@@ -109,11 +110,13 @@ export function createDiscordTriggerLogger(
|
|
|
109
110
|
* (`src/discord.ts:160-172` comment) so the wire is a near-identity
|
|
110
111
|
* with `raw` carrying the full gateway payload for debugging. */
|
|
111
112
|
export function toDiscordEvent(tap: DcTriggerEvent): DiscordEvent {
|
|
113
|
+
const envelope = receiveChannelEvent('discord', tap);
|
|
114
|
+
if (!envelope || envelope instanceof Promise) throw new Error('discord connector cannot normalize accepted tap');
|
|
112
115
|
return {
|
|
113
116
|
kind: tap.kind,
|
|
114
|
-
channel: tap.channel,
|
|
115
|
-
user: tap.user,
|
|
116
|
-
body:
|
|
117
|
+
channel: envelope.channel ?? tap.channel,
|
|
118
|
+
user: envelope.senderId ?? tap.user,
|
|
119
|
+
body: envelope.text,
|
|
117
120
|
raw: tap,
|
|
118
121
|
};
|
|
119
122
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
2
|
import { debug } from '../../debug/log.js';
|
|
3
|
-
import type { DraftMetrics } from '../../self-dev/draft-sweep.js';
|
|
3
|
+
import type { DraftMetrics, OverlapMetrics } from '../../self-dev/draft-sweep.js';
|
|
4
|
+
|
|
5
|
+
export type CeoDraftMetrics = DraftMetrics & { readonly overlap: OverlapMetrics | null };
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* DRAFT-METRIC — CEO view source. Opening the page must never trigger a GitHub read:
|
|
@@ -14,7 +16,7 @@ export type DraftMetricsState = 'measuring' | 'ready' | 'unavailable';
|
|
|
14
16
|
export interface DraftMetricsSnapshot {
|
|
15
17
|
/** measuring = no value yet and a collection is running · unavailable = no value and the last collection failed. */
|
|
16
18
|
readonly state: DraftMetricsState;
|
|
17
|
-
readonly metrics:
|
|
19
|
+
readonly metrics: CeoDraftMetrics | null;
|
|
18
20
|
/** When the served value was collected (ISO). null without a value. */
|
|
19
21
|
readonly measuredAt: string | null;
|
|
20
22
|
/** A background collection is in flight. */
|
|
@@ -24,7 +26,7 @@ export interface DraftMetricsSnapshot {
|
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
export interface DraftMetricsSourceOptions {
|
|
27
|
-
readonly collect?: () => Promise<
|
|
29
|
+
readonly collect?: () => Promise<CeoDraftMetrics>;
|
|
28
30
|
readonly ttlMs?: number;
|
|
29
31
|
readonly failureRetryMs?: number;
|
|
30
32
|
readonly now?: () => number;
|
|
@@ -43,17 +45,29 @@ function isMetrics(value: unknown): value is DraftMetrics {
|
|
|
43
45
|
&& nullableNumber('oldestAgeHours') && nullableNumber('conversion48h');
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
function isOverlapMetrics(value: unknown): value is OverlapMetrics {
|
|
49
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
50
|
+
const row = value as Record<string, unknown>;
|
|
51
|
+
const count = (key: string) => row[key] === null || (Number.isInteger(row[key]) && (row[key] as number) >= 0);
|
|
52
|
+
const nullableNumber = (key: string) => row[key] === null || (typeof row[key] === 'number' && Number.isFinite(row[key]) && (row[key] as number) >= 0);
|
|
53
|
+
return ['launches24h', 'launched', 'unmeasured', 'linked', 'autoLanded', 'salvaged', 'salvageUnmeasured'].every(count)
|
|
54
|
+
&& typeof row.sourceIncomplete === 'boolean' && nullableNumber('secondSiblingMedianHours')
|
|
55
|
+
&& (row.autoRate === null || (typeof row.autoRate === 'number' && Number.isFinite(row.autoRate) && row.autoRate >= 0 && row.autoRate <= 1));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Parses the CLI's single JSON line; malformed draft values fail, malformed overlap is unmeasured. */
|
|
59
|
+
export function parseDraftMetricsOutput(stdout: string): CeoDraftMetrics {
|
|
48
60
|
const line = stdout.trim().split('\n').reverse().find((text) => text.trim().startsWith('{'));
|
|
49
61
|
if (!line) throw new Error('draft metrics: no JSON output');
|
|
50
62
|
const parsed: unknown = JSON.parse(line);
|
|
51
63
|
if (!isMetrics(parsed)) throw new Error('draft metrics: malformed output');
|
|
52
64
|
const { inventory, oldestAgeHours, needsOwner, converted48h, cohort48h, conversion48h } = parsed;
|
|
53
|
-
|
|
65
|
+
const candidate = (parsed as DraftMetrics & { overlap?: unknown }).overlap;
|
|
66
|
+
return { inventory, oldestAgeHours, needsOwner, converted48h, cohort48h, conversion48h,
|
|
67
|
+
overlap: isOverlapMetrics(candidate) ? candidate : null };
|
|
54
68
|
}
|
|
55
69
|
|
|
56
|
-
async function collectViaCli(): Promise<
|
|
70
|
+
async function collectViaCli(): Promise<CeoDraftMetrics> {
|
|
57
71
|
const root = join(import.meta.dir, '../../..');
|
|
58
72
|
const proc = Bun.spawn(['bun', join(root, 'bin/elanous.mjs'), 'harness', 'drafts', 'metrics', '--json'], {
|
|
59
73
|
cwd: root, stdout: 'pipe', stderr: 'pipe',
|
|
@@ -75,7 +89,7 @@ export function createDraftMetricsSource(options: DraftMetricsSourceOptions = {}
|
|
|
75
89
|
const ttl = options.ttlMs ?? DRAFT_METRICS_TTL_MS;
|
|
76
90
|
const retry = options.failureRetryMs ?? DRAFT_METRICS_FAILURE_RETRY_MS;
|
|
77
91
|
const now = options.now ?? Date.now;
|
|
78
|
-
let value: { metrics:
|
|
92
|
+
let value: { metrics: CeoDraftMetrics; at: number } | null = null;
|
|
79
93
|
let failure: { reason: string; at: number } | null = null;
|
|
80
94
|
let inFlight: Promise<void> | null = null;
|
|
81
95
|
|