elanous 0.2.38 → 0.2.40

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.
Files changed (615) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → HjeK7zONHfR7op1hKXp4k}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{7954.4f7a8832663ee979.js → 1060.014f1f01a17aec26.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{8911.bf5e712acb25fb6c.js → 1281.d81877e35b9068f4.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/{2104.70e086d5174a4736.js → 1350.59f40e39e02d91b1.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1452.162bb2d9d699e82a.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +286 -0
  10. package/apps/pwa/out/_next/static/chunks/1537-6bb97b5214928ea9.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +149 -0
  12. package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +90 -0
  14. package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +104 -0
  15. package/apps/pwa/out/_next/static/chunks/2047.8f23e210995d4548.js +2 -0
  16. package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{1632.7d87f998e714bede.js → 2066.a77257c8c350770a.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{8019.21ca554a821dad01.js → 2177.df8547f9d7215c4e.js} +3 -3
  20. package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{3528.e4b8ab70d339f965.js → 2226.2cf61ec781827219.js} +2 -2
  22. package/apps/pwa/out/_next/static/chunks/2281-b8cede695c6c650e.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6493.27ad77de7aac7966.js → 2499.02fbfd18126c10c0.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/{7628.6b16863ac3972333.js → 2522.f2766b76d22c8bdf.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/{3086.fb14b60ce98b53d3.js → 2566.beaffc3a5e1fcd2e.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/{9299.24e2a7d9b6d1f91b.js → 261.0d471e8aded799f3.js} +3 -3
  27. package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +27 -0
  30. package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2774-719820e3f5b2a3eb.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/2829-734fe8bf2eee7347.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{7524.ce973525d30b3d52.js → 3330.7443183b7e6fdbdf.js} +1 -1
  41. package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/{3124-561f7f037943cde2.js → 3746-f80a78f220bf37b5.js} +1 -1
  44. package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +24 -0
  45. package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +77 -0
  46. package/apps/pwa/out/_next/static/chunks/{bb6987f9.3647e1a23b0e3217.js → 3b355b3d.6f73c98bf6f9c749.js} +1 -1
  47. package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +36 -0
  48. package/apps/pwa/out/_next/static/chunks/{8994d93e.33ba491f95345fc2.js → 409c787b.e48c5bec8ec10456.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/{5041-5aada92ca215ffdd.js → 413-24c8284bda08241d.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +287 -0
  52. package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4351.0f37a6db2b34d50b.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{5638.107314dc479e2f37.js → 470.51a72a2348306455.js} +2 -2
  56. package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/{8487.291666583bebe640.js → 4769.9fd582071301f382.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/{8509.3a54d4e61893d7cb.js → 483.725e4a61be922788.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/{9fe1b809.738da85c8b17e3fb.js → 4864a2ca.1c1c280a7772c5e5.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +74 -0
  63. package/apps/pwa/out/_next/static/chunks/{8879.ac06755bcf3e44a1.js → 5383.bdfa5d886e39a826.js} +1 -1
  64. package/apps/pwa/out/_next/static/chunks/{6142.913b44e260a3f925.js → 5436.fdf6fa8ae3e9588d.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5622.94893f5aea7185d0.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +8 -0
  70. package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +62 -0
  72. package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +94 -0
  76. package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{7161-8f22db3ec5ed005e.js → 6051-0ae955eedb10adb9.js} +3 -3
  78. package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/{3291.f6c1005387d514bd.js → 6257.c0037b8949239f5e.js} +2 -2
  80. package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/6624.981ef7caeb680560.js +32 -0
  85. package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/{5203.51e5d8b5f1dcfe53.js → 6749.0744ce6eb08d40e9.js} +3 -3
  87. package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/{1938.0e6c60ee91c4d7f5.js → 6908.06008c67f6380ea9.js} +2 -2
  90. package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{de8b930d.d94c0f42acf807fc.js → 6cc1d1d6.9a98dd4622f1afc6.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7219-15bdd9a80661af8e.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +93 -0
  96. package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7515.1ad6efe157fa4448.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +24 -0
  100. package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/7611.85f045bf232053ac.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8086.1ab9103c41be884f.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8099.1cccf31c1baa7e1c.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{1026-44010f405704050c.js → 8272-025653884f9645d2.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{5307.d7328020227880c2.js → 8357.1aaa713b052a78b1.js} +4 -4
  110. package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/{4199-f7c6eb40cd0322f8.js → 8639-92c11d069792429e.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/8d173e38.18a2f7b4e1848bdb.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9069.657590a84afb8fac.js +41 -0
  115. package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9175.2de5209a5ce6f68a.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9184.45afbf44fec87574.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{eaad0cba.771200940c529df7.js → 9189505a.980427ac048c8c60.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9992.07ce73c10bd5e6a1.js +79 -0
  123. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-866aac5ff226a7f3.js → page-ba957ff875a026a0.js} +1 -1
  128. package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live/page-4edb8df90f4537ce.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83d27757e2b8060a.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/morning/page-fca2e59a81744d9e.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/term/page-139d722de1dcd6c1.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workspace/page-ccde99f07aaf71f7.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{b7478fef.5917716286213fcc.js → b84cad00.594027ebe0531fe2.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/c696986b.5dc8bb1143af16d1.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/{b7459770.6539b11860eb8a9c.js → ca3702f8.2913182e73889fa2.js} +7 -7
  177. package/apps/pwa/out/_next/static/chunks/{3f0de3de-2340c532c00395db.js → d5d3cefc-373c4eb722ed848b.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/{89d6c04f-6b8ab341748e468a.js → d8de0de2-dd0f4ac8e5ab1832.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/{framework-4b12a946f352cee2.js → framework-002b472a66935d31.js} +1 -1
  180. package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +22 -22
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +22 -22
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +22 -22
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +21 -21
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +21 -21
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +22 -22
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +21 -21
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +22 -22
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +22 -22
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +21 -21
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +22 -22
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +22 -22
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +22 -22
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +22 -22
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +21 -21
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +21 -21
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +22 -22
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +22 -22
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +22 -22
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +21 -21
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +21 -21
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +22 -22
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +22 -22
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +21 -21
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +21 -21
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +21 -21
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +22 -22
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +22 -22
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +21 -21
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +22 -22
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +22 -22
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +22 -22
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +22 -22
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +22 -22
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +21 -21
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +22 -22
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +22 -22
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +22 -22
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +22 -22
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +22 -22
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +22 -22
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +22 -22
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +22 -22
  278. package/graphs/demo/persona-marketer/fixtures/marketer-scenario.yaml +10 -0
  279. package/graphs/demo/persona-marketer/persona-marketer.yaml +25 -0
  280. package/graphs/demo/persona-marketer/recipes.yaml +19 -0
  281. package/graphs/video/explainer-line.yaml +4 -1
  282. package/package.json +1 -1
  283. package/scripts/dead-code/report.ts +169 -0
  284. package/scripts/lib/morning-report-options.ts +3 -4
  285. package/scripts/lib/tui-regress-evidence.ts +56 -0
  286. package/scripts/morning-report.ts +5 -1
  287. package/scripts/public-export.ts +15 -7
  288. package/scripts/release-loop/export-check-node.ts +21 -3
  289. package/scripts/release-loop/gate-node.ts +379 -48
  290. package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
  291. package/scripts/release-loop/gate-shard-receipts.ts +89 -0
  292. package/scripts/release-loop/gate-wall.ts +5 -5
  293. package/scripts/release-loop/preflight.ts +6 -2
  294. package/scripts/release-loop/resume-release.ts +20 -5
  295. package/scripts/release-loop/resume.ts +48 -0
  296. package/scripts/release-loop/version-node.ts +7 -2
  297. package/scripts/release-story/draft.ts +1 -1
  298. package/scripts/research-bench/README.md +53 -0
  299. package/scripts/research-bench/questions.json +66 -0
  300. package/scripts/research-bench/rubric.md +33 -0
  301. package/scripts/research-bench/run.ts +523 -0
  302. package/scripts/tui-regress.ts +85 -10
  303. package/src/acp/core-turn-bridge.ts +8 -0
  304. package/src/agent/autonomous-tools.ts +10 -3
  305. package/src/agent/monad-agent-turn.ts +4 -1
  306. package/src/agent/registry.ts +26 -2
  307. package/src/agent/shared-app-tools.ts +1 -1
  308. package/src/agent/surface-ux/build.ts +12 -3
  309. package/src/agent/surface-ux/types.ts +1 -1
  310. package/src/agent/task-notification.ts +75 -6
  311. package/src/agent/types.ts +3 -0
  312. package/src/agent-mission/driver.ts +29 -3
  313. package/src/agent-mission/mission-cli.ts +2 -1
  314. package/src/agent-substrate/review-context-pack.ts +365 -0
  315. package/src/agent-substrate/self-review-cli.ts +226 -17
  316. package/src/ask-user-question/index.ts +6 -0
  317. package/src/ask-user-question/inline-resolver.ts +49 -0
  318. package/src/auto-research/question-ladder-contract.ts +22 -3
  319. package/src/auto-research/research-turn.ts +350 -17
  320. package/src/autopilot/agent-loop.ts +1 -1
  321. package/src/autopilot/pty-control-loop.ts +8 -1
  322. package/src/boot/daemon-tools/index.ts +4 -3
  323. package/src/boot/daemon-tools/self-implement.ts +270 -2
  324. package/src/boot/daemon-tools/types.ts +2 -0
  325. package/src/budget/llm-cost.ts +44 -5
  326. package/src/budget/unified-usage.ts +17 -1
  327. package/src/capture/tui-self-report.ts +14 -0
  328. package/src/chat/index.ts +33 -7
  329. package/src/cli/agent-cli.ts +43 -8
  330. package/src/cli/intake-cli.ts +22 -1
  331. package/src/cli/lesson-cli.ts +19 -3
  332. package/src/cli/log-event-names.ts +1 -0
  333. package/src/cli/pod-cli.ts +17 -2
  334. package/src/cli/pty-takeover-cli.ts +67 -7
  335. package/src/cli/release-cli.ts +52 -6
  336. package/src/cli/repo-cli.ts +2 -1
  337. package/src/cli/tasks-cli.ts +36 -9
  338. package/src/control-plane/ledger.ts +21 -4
  339. package/src/core-turn/run-core-turn.ts +44 -3
  340. package/src/core-turn/run-goal-loop.ts +152 -8
  341. package/src/core-turn/types.ts +9 -0
  342. package/src/dashboard/chat/acp-chat.ts +2 -2
  343. package/src/dashboard/classic-sigquit.ts +16 -0
  344. package/src/dashboard/index.ts +321 -27
  345. package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
  346. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
  347. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  348. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  349. package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
  350. package/src/dashboard/input/external-input-host.ts +2 -0
  351. package/src/dashboard/sidetab-runtime.ts +228 -0
  352. package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
  353. package/src/dashboard/slash-runtime/dashboard-handlers.ts +20 -8
  354. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
  355. package/src/dashboard/term-slash-runtime.ts +16 -18
  356. package/src/dashboard/turn-preamble.ts +2 -0
  357. package/src/domains/knowledge.ts +1 -1
  358. package/src/esc-abort-gate.ts +33 -1
  359. package/src/execution-loop/launch-gate.ts +206 -1
  360. package/src/graph-runner/graph-cli.ts +6 -4
  361. package/src/graph-runner/runner.ts +31 -9
  362. package/src/graph-wizard/generate.ts +16 -7
  363. package/src/graph-wizard/mission-compose.ts +201 -0
  364. package/src/grok/agent-search.ts +8 -2
  365. package/src/grok/credential.ts +5 -0
  366. package/src/grounding/ref-index.ts +11 -0
  367. package/src/grounding/ref-vector.ts +61 -0
  368. package/src/grounding/sources-cli.ts +2 -2
  369. package/src/grounding/sources.ts +15 -1
  370. package/src/harness/harness-cli-command.ts +38 -9
  371. package/src/harness/harness-pod-dispatch.ts +7 -1
  372. package/src/index.ts +18 -4
  373. package/src/input/external-input-queue.ts +10 -0
  374. package/src/intake-plane/collect-telegram-saved.ts +36 -1
  375. package/src/intake-plane/intake-to-tasks.ts +246 -3
  376. package/src/lessons/friction-ledger.ts +154 -0
  377. package/src/live-supply/collector.ts +149 -0
  378. package/src/live-supply/probes.ts +52 -0
  379. package/src/live-supply/snapshot.ts +40 -0
  380. package/src/llm.ts +431 -76
  381. package/src/loops/orchestrator/tick.ts +8 -0
  382. package/src/nexus/api/harness-api.ts +2 -1
  383. package/src/pty/snapshot.py +132 -0
  384. package/src/pty-shell/pty-control-ipc.ts +29 -2
  385. package/src/pty-shell/pty-manifest.ts +59 -3
  386. package/src/pty-shell/registry.ts +2 -0
  387. package/src/pty-shell/tui-run-state.ts +80 -3
  388. package/src/release-loop/gate-host-reservation.ts +13 -4
  389. package/src/release-loop/gate-shard-ledger.ts +68 -0
  390. package/src/release-loop/merged-pr-checklist.ts +25 -2
  391. package/src/release-loop/rehearsal-shard-plan.ts +6 -1
  392. package/src/release-loop/rehearsal.ts +27 -0
  393. package/src/research/edge-decision.ts +124 -15
  394. package/src/research/gap-followup.ts +249 -0
  395. package/src/research/lenses/counter-evidence.ts +100 -0
  396. package/src/research/lenses/working-backwards.ts +89 -0
  397. package/src/research/plugin-discovery.ts +242 -0
  398. package/src/research-bridge/invoke.ts +4 -2
  399. package/src/research-bridge/types.ts +2 -0
  400. package/src/self-dev/ask-launch-flow.ts +34 -106
  401. package/src/self-dev/dev-cli.ts +2 -0
  402. package/src/self-dev/dev-pipeline.ts +8 -4
  403. package/src/self-dev/graph-journey-route.ts +10 -2
  404. package/src/self-dev/launch-preflight-text.ts +2 -2
  405. package/src/self-dev/launch-preflight.ts +38 -7
  406. package/src/self-dev/orchestrate-cli.ts +1 -0
  407. package/src/self-dev/run-supervisor.ts +19 -0
  408. package/src/self-implement/device-first.ts +8 -2
  409. package/src/self-implement/doctor-visit.ts +76 -58
  410. package/src/self-implement/gate-artifacts.ts +3 -0
  411. package/src/self-implement/gate-baseline.ts +75 -4
  412. package/src/self-implement/gate-cli.ts +317 -9
  413. package/src/self-implement/gate-receipt-registry.ts +180 -0
  414. package/src/self-implement/gate-remote.ts +145 -22
  415. package/src/self-implement/goal-author-clarification.ts +178 -24
  416. package/src/self-implement/goal-author-decompose.ts +24 -15
  417. package/src/self-implement/goal-author.ts +9 -5
  418. package/src/self-implement/host-regate.ts +120 -45
  419. package/src/self-implement/impl-findings-feedback.ts +188 -0
  420. package/src/self-implement/knowhow-pack.ts +189 -10
  421. package/src/self-implement/off-diff-evidence.ts +124 -0
  422. package/src/self-implement/orchestrator.ts +85 -7
  423. package/src/self-implement/run-ledger.ts +46 -8
  424. package/src/self-implement/run-stop.ts +12 -0
  425. package/src/self-implement/seams.ts +6 -3
  426. package/src/self-implement/self-implement-cli.ts +4 -2
  427. package/src/session/chat.ts +89 -15
  428. package/src/session-runtime/provider-circuit.ts +140 -0
  429. package/src/shell-runner/file-engine.ts +1 -0
  430. package/src/shell-runner/types.ts +4 -0
  431. package/src/sidetab-core/model.ts +176 -0
  432. package/src/skills/tools/schedule-wakeup.ts +23 -1
  433. package/src/skills/tools/shell.ts +51 -5
  434. package/src/steward/directive-audit.ts +354 -0
  435. package/src/surface/child-process.ts +31 -0
  436. package/src/surface/tui-stderr-owner.ts +48 -0
  437. package/src/task-agent/cover.ts +30 -12
  438. package/src/task-agent/judge.ts +56 -0
  439. package/src/task-agent/postland-card.ts +35 -2
  440. package/src/task-agent/rejudge-on-head.ts +46 -2
  441. package/src/task-agent/repair-cycle.ts +1 -1
  442. package/src/task-agent/task-hand.ts +129 -24
  443. package/src/task-agent/tier-split.ts +105 -21
  444. package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
  445. package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
  446. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +27 -2
  447. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
  448. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
  449. package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
  450. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
  451. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
  452. package/src/task-orchestrator/surfaces/self-implement-pod.ts +186 -33
  453. package/src/tool-runtime/skill-exec-runtime.ts +95 -5
  454. package/src/tui/entry.ts +15 -2
  455. package/src/tui/inline-choice.ts +188 -0
  456. package/src/tui/sidetab/list.ts +2 -176
  457. package/src/tui/slash/term.ts +12 -1
  458. package/src/tui-client/dashboard-session.ts +7 -1
  459. package/src/user-config.ts +34 -4
  460. package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
  461. package/src/ux-sim/fake-land-queue.ts +88 -0
  462. package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
  463. package/src/ux-sim/goal-interim-trace.ts +24 -0
  464. package/src/ux-sim/next-tui-seat-scenarios.ts +8 -13
  465. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
  466. package/src/version/packed-revision.json +1 -1
  467. package/src/video-pipeline/recipes/explainer.ts +54 -2
  468. package/src/web-search/grok.ts +32 -6
  469. package/src/web-search/index.ts +8 -7
  470. package/src/workflow-runtime/node-catalog.ts +53 -4
  471. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +0 -27
  472. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +0 -1
  477. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +0 -1
  479. package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +0 -93
  481. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +0 -104
  482. package/apps/pwa/out/_next/static/chunks/2415.738b777642a02233.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +0 -24
  492. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +0 -36
  494. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +0 -287
  498. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +0 -94
  504. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +0 -32
  514. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +0 -90
  515. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +0 -79
  517. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +0 -74
  520. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +0 -286
  523. package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +0 -8
  527. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +0 -62
  539. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/7488.966b116789f3d41a.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +0 -77
  544. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +0 -149
  554. package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +0 -41
  555. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +0 -24
  556. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +0 -2
  560. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +0 -1
  615. /package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → HjeK7zONHfR7op1hKXp4k}/_ssgManifest.js +0 -0
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomUUID } from 'node:crypto';
2
- import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from 'node:fs';
2
+ import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
3
3
  import { isAbsolute, join } from 'node:path';
4
4
  import { debug } from '../debug/log.js';
5
5
  import type { TaskPriority } from '../task-orchestrator/types.js';
@@ -71,15 +71,187 @@ export function interpretIntakeInput(response: string): IntakeInputInterpretatio
71
71
  return { tasks, questions };
72
72
  }
73
73
 
74
+ export const CHANNEL_PUBLISH_APPROVAL_CATEGORIES = ['first-release', 'patent', 'external-contract'] as const;
75
+ export const CHANNEL_PUBLISH_CROWN_OWNER = '\u{1F451}';
76
+ export type ChannelPublishApprovalCategory = (typeof CHANNEL_PUBLISH_APPROVAL_CATEGORIES)[number];
77
+ export type ChannelPublishStatus = 'queued' | 'approved' | 'published';
78
+ type ChannelPublishApproval = { kind: 'automatic' } | { kind: 'human'; approvedBy: string };
79
+
80
+ export interface ChannelPublishDraft {
81
+ channel: string;
82
+ cadence: string;
83
+ voice: string;
84
+ owner: string;
85
+ category: ChannelPublishApprovalCategory | (string & {});
86
+ title: string;
87
+ body: string;
88
+ }
89
+
90
+ export interface ChannelPublishPlan extends ChannelPublishDraft {
91
+ status: ChannelPublishStatus;
92
+ approvedBy?: string;
93
+ }
94
+
95
+ export interface ChannelPublishConnector {
96
+ publish(plan: ChannelPublishPlan): Promise<{ publishedId: string }>;
97
+ }
98
+
99
+ // MK·crown 소유자의 첫 공개·특허·외부 계약 초안은 사람 승인 전 자동 승인하지 않는다.
100
+ export function isChannelPublishApprovable(draft: ChannelPublishDraft): boolean {
101
+ if (draft.owner !== 'MK' && draft.owner !== CHANNEL_PUBLISH_CROWN_OWNER) return true;
102
+ return !(CHANNEL_PUBLISH_APPROVAL_CATEGORIES as readonly string[]).includes(draft.category);
103
+ }
104
+
105
+ export function toChannelPublishDraft(row: Record<string, unknown>): ChannelPublishDraft | null {
106
+ const text = (key: string, max: number): string | null => {
107
+ const value = row[key];
108
+ if (typeof value !== 'string') return null;
109
+ const trimmed = value.trim();
110
+ return trimmed && trimmed.length <= max ? trimmed : null;
111
+ };
112
+ const channel = text('channel', 200);
113
+ const cadence = text('cadence', 200);
114
+ const voice = text('voice', 200);
115
+ const owner = text('owner', 200);
116
+ const category = text('category', 200);
117
+ const title = text('title', TASK_DEFAULTS.titleMaxLen);
118
+ const body = text('body', TASK_DEFAULTS.descriptionMaxLen);
119
+ if (!channel || !cadence || !voice || !owner || !category || !title || !body) return null;
120
+ return { channel, cadence, voice, owner, category, title, body };
121
+ }
122
+
123
+ function isChannelPublishPlan(value: unknown): value is ChannelPublishPlan {
124
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
125
+ const plan = value as Record<string, unknown>;
126
+ return toChannelPublishDraft(plan) !== null
127
+ && (plan.status === 'queued' || plan.status === 'approved' || plan.status === 'published')
128
+ && (plan.approvedBy === undefined || typeof plan.approvedBy === 'string');
129
+ }
130
+
131
+ export class ChannelPublishQueue {
132
+ readonly queueDir: string;
133
+ readonly publishedFile: string;
134
+
135
+ constructor(instanceRoot: string) {
136
+ this.queueDir = join(intakeLedgerDir(instanceRoot), 'channel-publish', 'queue');
137
+ this.publishedFile = join(intakeLedgerDir(instanceRoot), 'channel-publish', 'published.jsonl');
138
+ mkdirSync(this.queueDir, { recursive: true, mode: 0o700 });
139
+ }
140
+
141
+ entryPath(id: string): string {
142
+ return join(this.queueDir, `${createHash('sha256').update(`channel:${id}`).digest('hex')}.json`);
143
+ }
144
+
145
+ tryAcquirePublish(id: string): (() => void) | null {
146
+ const path = `${this.entryPath(id)}.publishing`;
147
+ const token = randomUUID();
148
+ // Do not auto-steal stale locks: a takeover race could duplicate an irreversible external post.
149
+ // If a process dies mid-publish, reconcile the approved queue entry and lock explicitly.
150
+ let fd: number;
151
+ try {
152
+ fd = openSync(path, 'wx', 0o600);
153
+ } catch (error) {
154
+ if ((error as NodeJS.ErrnoException).code === 'EEXIST') return null;
155
+ throw error;
156
+ }
157
+ try { writeFileSync(fd, token); }
158
+ catch (error) { rmSync(path, { force: true }); throw error; }
159
+ finally { closeSync(fd); }
160
+ return () => {
161
+ // Never let a late releaser remove a lock created by another publisher.
162
+ try {
163
+ if (readFileSync(path, 'utf8') === token) rmSync(path);
164
+ } catch { /* The lock is already gone; leave a replacement untouched. */ }
165
+ };
166
+ }
167
+
168
+ plan(id: string): ChannelPublishPlan | null {
169
+ const path = this.entryPath(id);
170
+ if (!existsSync(path)) return null;
171
+ const value: unknown = JSON.parse(readFileSync(path, 'utf8'));
172
+ if (!isChannelPublishPlan(value)) throw new Error('invalid channel publish plan');
173
+ return value;
174
+ }
175
+
176
+ entries(): ChannelPublishPlan[] {
177
+ return readdirSync(this.queueDir).filter((name) => /^[a-f0-9]{64}\.json$/.test(name))
178
+ .map((name) => {
179
+ const value: unknown = JSON.parse(readFileSync(join(this.queueDir, name), 'utf8'));
180
+ if (!isChannelPublishPlan(value)) throw new Error('invalid channel publish plan');
181
+ return value;
182
+ });
183
+ }
184
+
185
+ count(): number { return this.entries().length; }
186
+
187
+ publishedIds(): Set<string> {
188
+ if (!existsSync(this.publishedFile)) return new Set();
189
+ const ids = new Set<string>();
190
+ for (const line of readFileSync(this.publishedFile, 'utf8').split('\n')) {
191
+ try {
192
+ const row: unknown = JSON.parse(line);
193
+ if (row && typeof row === 'object' && !Array.isArray(row) && typeof (row as Record<string, unknown>).id === 'string') {
194
+ ids.add((row as { id: string }).id);
195
+ }
196
+ } catch { /* ignore incomplete ledger lines */ }
197
+ }
198
+ return ids;
199
+ }
200
+
201
+ enqueue(id: string, draft: ChannelPublishDraft): ChannelPublishPlan {
202
+ if (this.publishedIds().has(id)) return { ...draft, status: 'published' };
203
+ const existing = this.plan(id);
204
+ if (existing) return existing;
205
+ const plan: ChannelPublishPlan = { ...draft, status: 'queued' };
206
+ this.savePlan(id, plan);
207
+ return plan;
208
+ }
209
+
210
+ approve(id: string, plan: ChannelPublishPlan, approval: ChannelPublishApproval): ChannelPublishPlan {
211
+ if (plan.status !== 'queued') return plan;
212
+ if (!isChannelPublishApprovable(plan) && approval.kind !== 'human') return plan;
213
+ if (approval.kind === 'human' && approval.approvedBy !== 'MK' && approval.approvedBy !== CHANNEL_PUBLISH_CROWN_OWNER) return plan;
214
+ const approvedBy = approval.kind === 'human' ? approval.approvedBy : 'automation';
215
+ const approved: ChannelPublishPlan = { ...plan, status: 'approved', approvedBy };
216
+ this.savePlan(id, approved);
217
+ return approved;
218
+ }
219
+
220
+ savePlan(id: string, plan: ChannelPublishPlan): void {
221
+ const path = this.entryPath(id);
222
+ const temporary = `${path}.${randomUUID()}.tmp`;
223
+ writeFileSync(temporary, JSON.stringify(plan));
224
+ renameSync(temporary, path);
225
+ }
226
+
227
+ recordPublished(id: string, plan: ChannelPublishPlan, publishedId: string): void {
228
+ // Ledger first, then remove the plan: a crash between the connector call and this append may
229
+ // republish (at-least-once), matching the HookQueue queue-file/seen ordering across restarts.
230
+ appendFileSync(this.publishedFile, JSON.stringify({ id, channel: plan.channel, publishedId }) + '\n');
231
+ rmSync(this.entryPath(id), { force: true });
232
+ }
233
+ }
234
+
235
+ /** Explicit approval entry point for a human-controlled API, CLI, or UI action. */
236
+ export function approveChannelPublish(instanceRoot: string, id: string, approvedBy: string): ChannelPublishPlan | null {
237
+ const queue = new ChannelPublishQueue(instanceRoot);
238
+ const plan = queue.plan(id);
239
+ if (!plan || plan.status !== 'queued' || isChannelPublishApprovable(plan)
240
+ || (approvedBy !== 'MK' && approvedBy !== CHANNEL_PUBLISH_CROWN_OWNER)) return null;
241
+ return queue.approve(id, plan, { kind: 'human', approvedBy });
242
+ }
243
+
74
244
  export type IntakeTaskInput =
75
245
  | { kind: 'goal-line'; id: string; fact: string; current: string; url?: string }
76
- | { kind: 'idea-note'; id: string; content: string; url?: string };
246
+ | { kind: 'idea-note'; id: string; content: string; url?: string }
247
+ | { kind: 'channel-post'; id: string; draft: ChannelPublishDraft | null };
77
248
 
78
249
  export interface IntakeToTasksDeps {
79
250
  llm: (input: IntakeTaskInput) => Promise<string>;
80
251
  post: (request: IntakeTaskRequest) => Promise<{ taskId: string; deduplicated?: boolean }>;
81
252
  list?: typeof listIntakeItems;
82
253
  readNote?: (path: string) => string;
254
+ connector?: ChannelPublishConnector;
83
255
  }
84
256
 
85
257
  export interface IntakeToTasksResult {
@@ -87,7 +259,19 @@ export interface IntakeToTasksResult {
87
259
  created: number;
88
260
  skipped: number;
89
261
  failed: number;
90
- items: Array<{ id: string; status: 'created' | 'deduplicated' | 'dry-run' | 'skipped' | 'failed'; taskId?: string; types?: IntakeTaskType[]; reason?: string }>;
262
+ items: Array<{
263
+ id: string;
264
+ status: 'created' | 'deduplicated' | 'dry-run' | 'skipped' | 'failed' | 'queued' | 'approved' | 'published';
265
+ taskId?: string;
266
+ types?: IntakeTaskType[];
267
+ reason?: string;
268
+ channel?: string;
269
+ cadence?: string;
270
+ voice?: string;
271
+ owner?: string;
272
+ category?: string;
273
+ publishedId?: string;
274
+ }>;
91
275
  }
92
276
 
93
277
  export function interpretIntakeItem(response: string): IntakeTaskInterpretation | null {
@@ -180,6 +364,10 @@ function goalLines(root: string): IntakeTaskInput[] {
180
364
  const value: unknown = JSON.parse(line);
181
365
  if (!value || typeof value !== 'object' || Array.isArray(value)) return;
182
366
  const row = value as Record<string, unknown>;
367
+ if (row.kind === 'channel-post') {
368
+ rows.push({ kind: 'channel-post', id: goalLineId(file, index), draft: toChannelPublishDraft(row) });
369
+ return;
370
+ }
183
371
  if (typeof row.fact !== 'string' || !row.fact.trim()) return;
184
372
  rows.push({ kind: 'goal-line', id: goalLineId(file, index), fact: row.fact, current: typeof row.current === 'string' ? row.current : '',
185
373
  ...(typeof row.url === 'string' ? { url: row.url } : {}) });
@@ -240,6 +428,61 @@ export async function runIntakeToTasks(
240
428
  .filter(({ input }) => !consumed.has(input.id)).slice(0, limit);
241
429
  const result: IntakeToTasksResult = { processed: selected.length, created: 0, skipped: 0, failed: 0, items: [] };
242
430
  for (const { input, path } of selected) {
431
+ if (input.kind === 'channel-post') {
432
+ if (opts.dryRun) {
433
+ result.items.push({ id: input.id, status: 'dry-run' });
434
+ continue;
435
+ }
436
+ if (!input.draft) {
437
+ result.skipped++;
438
+ result.items.push({ id: input.id, status: 'skipped', reason: 'invalid-channel-post-draft' });
439
+ continue;
440
+ }
441
+ const queue = new ChannelPublishQueue(instanceRoot);
442
+ try {
443
+ const queued = queue.enqueue(input.id, input.draft);
444
+ const plan = isChannelPublishApprovable(queued) ? queue.approve(input.id, queued, { kind: 'automatic' }) : queued;
445
+ if (plan.status === 'published') {
446
+ // Crash between the publish ledger and the consumed ledger: the post is already out.
447
+ appendFileSync(consumedFile(instanceRoot), JSON.stringify({ id: input.id }) + '\n');
448
+ result.items.push({ id: input.id, status: 'published', channel: plan.channel, cadence: plan.cadence, voice: plan.voice });
449
+ continue;
450
+ }
451
+ if (plan.status === 'approved' && deps.connector) {
452
+ const release = queue.tryAcquirePublish(input.id);
453
+ if (release) {
454
+ try {
455
+ // Recheck under the per-item lock; another process may have completed before it was acquired.
456
+ const current = queue.plan(input.id);
457
+ if (current?.status === 'approved' && !queue.publishedIds().has(input.id)) {
458
+ const { publishedId } = await deps.connector.publish(current);
459
+ queue.recordPublished(input.id, current, publishedId);
460
+ appendFileSync(consumedFile(instanceRoot), JSON.stringify({ id: input.id, publishedId }) + '\n');
461
+ result.items.push({
462
+ id: input.id, status: 'published', channel: current.channel, cadence: current.cadence,
463
+ voice: current.voice, owner: current.owner, category: current.category, publishedId,
464
+ });
465
+ continue;
466
+ }
467
+ if (queue.publishedIds().has(input.id)) {
468
+ appendFileSync(consumedFile(instanceRoot), JSON.stringify({ id: input.id }) + '\n');
469
+ result.items.push({ id: input.id, status: 'published', channel: plan.channel, cadence: plan.cadence, voice: plan.voice });
470
+ continue;
471
+ }
472
+ } finally { release(); }
473
+ }
474
+ // Another process owns the publish attempt. Leave this item approved for its next pass.
475
+ result.items.push({ id: input.id, status: 'approved', channel: plan.channel, cadence: plan.cadence, voice: plan.voice });
476
+ continue;
477
+ }
478
+ result.items.push({ id: input.id, status: plan.status, channel: plan.channel, cadence: plan.cadence, voice: plan.voice });
479
+ } catch {
480
+ result.failed++;
481
+ result.items.push({ id: input.id, status: 'failed', reason: 'channel publish failed' });
482
+ debug.log('intake.to-tasks', 'channel-publish-failed', { id: input.id });
483
+ }
484
+ continue;
485
+ }
243
486
  try {
244
487
  let plan = loadTaskPlan(instanceRoot, input.id);
245
488
  if (!plan) {
@@ -0,0 +1,154 @@
1
+ import { Database } from 'bun:sqlite';
2
+ import { chmodSync, mkdirSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ import { elanousStateRoot } from '../autopilot/state-paths.js';
5
+ import { debug } from '../debug/log.js';
6
+ import type { LessonLedgerOptions } from './lesson-ledger.js';
7
+
8
+ export type FrictionActor = 'OP' | 'TC' | 'MK' | 'UX' | 'ceo' | 'person';
9
+ export type FrictionKind = 'hand-step' | 'ceo-correction' | 'repeat-question';
10
+
11
+ export const FRICTION_ACTORS: readonly FrictionActor[] = ['OP', 'TC', 'MK', 'UX', 'ceo', 'person'];
12
+ export const FRICTION_KINDS: readonly FrictionKind[] = ['hand-step', 'ceo-correction', 'repeat-question'];
13
+ export const FRICTION_CANDIDATE_MIN = 3;
14
+
15
+ export interface FrictionRecordInput {
16
+ actor: FrictionActor;
17
+ kind: FrictionKind;
18
+ signature: string;
19
+ note?: string;
20
+ ref: string;
21
+ }
22
+
23
+ export interface FrictionRow {
24
+ id: number;
25
+ actor: FrictionActor;
26
+ kind: FrictionKind;
27
+ signature: string;
28
+ note: string;
29
+ ref: string;
30
+ recorded_at: string;
31
+ }
32
+
33
+ export interface FrictionCandidate {
34
+ kind: FrictionKind;
35
+ signature: string;
36
+ count: number;
37
+ firstAt: string;
38
+ lastAt: string;
39
+ refs: string[];
40
+ }
41
+
42
+ export class FrictionInputError extends Error {
43
+ override name = 'FrictionInputError';
44
+ }
45
+
46
+ /** Secret-shaped note bodies are never persisted: a token or key would be copied into the ledger. */
47
+ const SECRET_PATTERNS: readonly RegExp[] = [
48
+ /sk-[A-Za-z0-9_-]{8,}/u,
49
+ /(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{8,}/u,
50
+ /AKIA[0-9A-Z]{12,}/u,
51
+ /xox[bapr]-[A-Za-z0-9-]{8,}/u,
52
+ /-----BEGIN [A-Z ]*PRIVATE KEY-----/u,
53
+ /\b[0-9a-f]{32,}\b/u,
54
+ /\b[A-Za-z0-9+/=_-]{40,}\b/u,
55
+ /(?:api[_-]?key|access[_-]?key|token|secret|password)\s*[:=]\s*\S{8,}/iu,
56
+ ];
57
+
58
+ function required(value: unknown, field: string): string {
59
+ if (typeof value !== 'string' || !value.trim()) throw new FrictionInputError(`${field} is required`);
60
+ return value.trim();
61
+ }
62
+
63
+ function checkActor(value: FrictionActor): FrictionActor {
64
+ if (!FRICTION_ACTORS.includes(value)) throw new FrictionInputError(`actor must be one of ${FRICTION_ACTORS.join(', ')}`);
65
+ return value;
66
+ }
67
+
68
+ function checkKind(value: FrictionKind): FrictionKind {
69
+ if (!FRICTION_KINDS.includes(value)) throw new FrictionInputError(`kind must be one of ${FRICTION_KINDS.join(', ')}`);
70
+ return value;
71
+ }
72
+
73
+ /** Same hand step spelled differently is the same hand step: lower case, whitespace runs folded to one space. */
74
+ function normalizeSignature(value: unknown): string {
75
+ const signature = required(value, 'signature').replace(/\s+/gu, ' ').toLowerCase();
76
+ if (!signature) throw new FrictionInputError('signature is required');
77
+ return signature;
78
+ }
79
+
80
+ export function frictionActor(name: string): FrictionActor {
81
+ const key = name.trim().toLowerCase();
82
+ return FRICTION_ACTORS.find(actor => actor.toLowerCase() === key) ?? 'person';
83
+ }
84
+
85
+ function secretFreeNote(note: unknown): string {
86
+ const text = note === undefined || note === null ? '' : String(note);
87
+ if (SECRET_PATTERNS.some(pattern => pattern.test(text))) throw new FrictionInputError('note looks like a secret (token or key)');
88
+ return text;
89
+ }
90
+
91
+ export class FrictionLedger {
92
+ readonly path: string;
93
+ private readonly now: () => Date;
94
+
95
+ constructor(options: LessonLedgerOptions = {}) {
96
+ this.path = join(options.stateDir ?? elanousStateRoot(), 'lessons', 'friction.sqlite');
97
+ this.now = options.now ?? (() => new Date());
98
+ }
99
+
100
+ private open(): Database {
101
+ mkdirSync(dirname(this.path), { recursive: true });
102
+ const db = new Database(this.path, { create: true, strict: true });
103
+ try {
104
+ chmodSync(this.path, 0o600);
105
+ db.exec('PRAGMA busy_timeout = 10000');
106
+ db.exec('PRAGMA journal_mode = WAL');
107
+ db.exec(`CREATE TABLE IF NOT EXISTS friction (
108
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
109
+ actor TEXT NOT NULL CHECK(actor IN ('OP','TC','MK','UX','ceo','person')),
110
+ kind TEXT NOT NULL CHECK(kind IN ('hand-step','ceo-correction','repeat-question')),
111
+ signature TEXT NOT NULL, note TEXT NOT NULL DEFAULT '', ref TEXT NOT NULL, recorded_at TEXT NOT NULL);
112
+ CREATE INDEX IF NOT EXISTS friction_group ON friction (kind, signature);`);
113
+ return db;
114
+ } catch (error) { db.close(); throw error; }
115
+ }
116
+
117
+ private using<T>(work: (db: Database) => T): T {
118
+ const db = this.open();
119
+ try { return work(db); } finally { db.close(); }
120
+ }
121
+
122
+ record(input: FrictionRecordInput): FrictionRow {
123
+ const actor = checkActor(input.actor);
124
+ const kind = checkKind(input.kind);
125
+ const signature = normalizeSignature(input.signature);
126
+ const note = secretFreeNote(input.note);
127
+ const ref = required(input.ref, 'ref');
128
+ return this.using(db => {
129
+ const at = this.now().toISOString();
130
+ const inserted = db.query('INSERT INTO friction (actor, kind, signature, note, ref, recorded_at) VALUES (?, ?, ?, ?, ?, ?)')
131
+ .run(actor, kind, signature, note, ref, at);
132
+ const row = db.query('SELECT id, actor, kind, signature, note, ref, recorded_at FROM friction WHERE id = ?')
133
+ .get(Number(inserted.lastInsertRowid)) as FrictionRow | null;
134
+ if (!row) throw new FrictionInputError('friction row was not stored');
135
+ debug.log('lessons.friction', 'record', { id: row.id, kind: row.kind, actor: row.actor });
136
+ return row;
137
+ });
138
+ }
139
+
140
+ /** Same hand step three times is a proposal candidate (§4⑤ SELF-PROPOSE-BASE), not one-off noise. */
141
+ candidates(min: number = FRICTION_CANDIDATE_MIN): FrictionCandidate[] {
142
+ if (!Number.isInteger(min) || min < 1) throw new FrictionInputError('min must be a positive integer');
143
+ return this.using(db => {
144
+ const groups = db.query(`SELECT kind, signature, count(*) AS count, min(recorded_at) AS firstAt, max(recorded_at) AS lastAt
145
+ FROM friction GROUP BY kind, signature HAVING count(*) >= ?
146
+ ORDER BY count DESC, lastAt DESC, kind, signature`).all(min) as Omit<FrictionCandidate, 'refs'>[];
147
+ return groups.map(group => ({
148
+ ...group,
149
+ refs: (db.query('SELECT ref FROM friction WHERE kind = ? AND signature = ? ORDER BY id')
150
+ .all(group.kind, group.signature) as { ref: string }[]).map(row => row.ref),
151
+ }));
152
+ });
153
+ }
154
+ }
@@ -0,0 +1,149 @@
1
+ import { appendFileSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { getElanousConfigDir } from '../elanous-config-dir.js';
4
+ import { SUPPLY_AXES, type LiveSupplySnapshot, type SupplyAxis, type SupplyEvent, type SupplyProbes, type SupplySourceState, type SupplyValues } from './snapshot.js';
5
+
6
+ export interface SupplyCollectorOptions {
7
+ directory?: string;
8
+ now?: () => number;
9
+ intervalMs?: number;
10
+ probeTimeoutMs?: number;
11
+ setInterval?: typeof globalThis.setInterval;
12
+ clearInterval?: typeof globalThis.clearInterval;
13
+ }
14
+
15
+ function readLatest(path: string): LiveSupplySnapshot | null {
16
+ try {
17
+ const row = JSON.parse(readFileSync(path, 'utf8')) as LiveSupplySnapshot;
18
+ return row.version === 1 && Number.isSafeInteger(row.sequence) ? row : null;
19
+ } catch { return null; }
20
+ }
21
+
22
+ /** A failed source retains its last value only with a stale label. Each tick commits before it publishes events. */
23
+ export class LiveSupplyCollector {
24
+ readonly directory: string;
25
+ private readonly now: () => number;
26
+ private readonly intervalMs: number;
27
+ private readonly probeTimeoutMs: number;
28
+ private readonly setInterval: typeof globalThis.setInterval;
29
+ private readonly clearInterval: typeof globalThis.clearInterval;
30
+ private latest: LiveSupplySnapshot | null;
31
+ private hasFreshTick = false;
32
+ private pending: Promise<LiveSupplySnapshot> | null = null;
33
+ private timer: ReturnType<typeof globalThis.setInterval> | null = null;
34
+
35
+ constructor(private readonly probes: SupplyProbes, options: SupplyCollectorOptions = {}) {
36
+ this.directory = options.directory ?? join(getElanousConfigDir(), 'live-supply');
37
+ this.now = options.now ?? Date.now;
38
+ this.intervalMs = options.intervalMs ?? 60_000;
39
+ this.probeTimeoutMs = options.probeTimeoutMs ?? 10_000;
40
+ this.setInterval = options.setInterval ?? globalThis.setInterval;
41
+ this.clearInterval = options.clearInterval ?? globalThis.clearInterval;
42
+ this.latest = readLatest(join(this.directory, 'latest.json'));
43
+ }
44
+
45
+ /** Disk cache is diagnostic until a fresh tick; a restart never silently blesses old measurements. */
46
+ read(): LiveSupplySnapshot | null {
47
+ if (!this.latest) return null;
48
+ if (this.hasFreshTick && Date.parse(this.latest.expiresAt) > this.now()) return this.latest;
49
+ return {
50
+ ...this.latest,
51
+ sources: Object.fromEntries(SUPPLY_AXES.map(axis => [axis, {
52
+ ...this.latest!.sources[axis],
53
+ status: this.latest!.sources[axis].status === 'measured' ? 'stale' : this.latest!.sources[axis].status,
54
+ }])) as LiveSupplySnapshot['sources'],
55
+ };
56
+ }
57
+
58
+ async start(): Promise<LiveSupplySnapshot> {
59
+ const first = await this.tick();
60
+ if (this.timer === null) this.timer = this.setInterval(() => { void this.tick().catch(() => {}); }, this.intervalMs);
61
+ return first;
62
+ }
63
+
64
+ stop(): void {
65
+ if (this.timer !== null) this.clearInterval(this.timer);
66
+ this.timer = null;
67
+ }
68
+
69
+ tick(): Promise<LiveSupplySnapshot> {
70
+ if (this.pending) return this.pending;
71
+ const work = this.collect();
72
+ this.pending = work;
73
+ void work.finally(() => { if (this.pending === work) this.pending = null; }).catch(() => {});
74
+ return work;
75
+ }
76
+
77
+ private async collect(): Promise<LiveSupplySnapshot> {
78
+ const previous = this.latest;
79
+ const at = new Date(this.now()).toISOString();
80
+ const sources = {} as LiveSupplySnapshot['sources'];
81
+ const values: Partial<SupplyValues> = {};
82
+ const results = await Promise.all(SUPPLY_AXES.map(async axis => {
83
+ try { return { axis, value: await this.withTimeout(this.probes[axis]()), error: null }; }
84
+ catch (error) { return { axis, value: null, error: error instanceof Error ? error.message : 'probe-failed' }; }
85
+ }));
86
+ for (const result of results) {
87
+ const axis = result.axis;
88
+ if (result.error === null && result.value !== null) {
89
+ (values as Record<SupplyAxis, unknown>)[axis] = result.value;
90
+ sources[axis] = { status: 'measured', observedAt: at, reason: null };
91
+ } else {
92
+ const oldValue = previous?.values[axis];
93
+ if (oldValue !== undefined) (values as Record<SupplyAxis, unknown>)[axis] = oldValue;
94
+ const oldAt = previous?.sources[axis]?.observedAt ?? null;
95
+ sources[axis] = { status: oldValue === undefined ? 'unknown' : 'stale', observedAt: oldAt, reason: this.safeReason(result.error) };
96
+ }
97
+ }
98
+ const snapshot: LiveSupplySnapshot = {
99
+ version: 1, sequence: (previous?.sequence ?? 0) + 1, observedAt: at,
100
+ expiresAt: new Date(this.now() + this.intervalMs).toISOString(), sources, values,
101
+ };
102
+ const events = this.events(previous, snapshot);
103
+ mkdirSync(this.directory, { recursive: true, mode: 0o700 });
104
+ const latestPath = join(this.directory, 'latest.json');
105
+ const tempPath = join(this.directory, `.latest.${process.pid}.${snapshot.sequence}.tmp`);
106
+ try {
107
+ appendFileSync(join(this.directory, 'snapshots.jsonl'), `${JSON.stringify(snapshot)}\n`, { mode: 0o600 });
108
+ writeFileSync(tempPath, JSON.stringify(snapshot), { mode: 0o600 });
109
+ renameSync(tempPath, latestPath);
110
+ this.latest = snapshot;
111
+ this.hasFreshTick = true;
112
+ } catch (error) {
113
+ // The pointer must never claim freshness after an unsuccessful commit.
114
+ this.latest = previous;
115
+ throw error;
116
+ }
117
+ if (events.length) appendFileSync(join(this.directory, 'events.jsonl'), events.map(event => JSON.stringify(event)).join('\n') + '\n', { mode: 0o600 });
118
+ return snapshot;
119
+ }
120
+
121
+ private withTimeout<T>(value: Promise<T> | T): Promise<T> {
122
+ return new Promise((resolve, reject) => {
123
+ const timer = globalThis.setTimeout(() => reject(new Error('probe-timeout')), this.probeTimeoutMs);
124
+ Promise.resolve(value).then(
125
+ result => { globalThis.clearTimeout(timer); resolve(result); },
126
+ error => { globalThis.clearTimeout(timer); reject(error); },
127
+ );
128
+ });
129
+ }
130
+
131
+ private safeReason(reason: string | null): string {
132
+ if (reason === 'probe-timeout') return reason;
133
+ return reason === null ? 'probe-unmeasured' : 'probe-failed';
134
+ }
135
+
136
+ private events(previous: LiveSupplySnapshot | null, next: LiveSupplySnapshot): SupplyEvent[] {
137
+ const rows: SupplyEvent[] = [];
138
+ for (const axis of SUPPLY_AXES) {
139
+ const before = previous?.sources[axis] as SupplySourceState | undefined;
140
+ const after = next.sources[axis];
141
+ if (after.status !== 'measured' && (before?.status !== after.status || before?.reason !== after.reason)) {
142
+ rows.push({ kind: 'supply.unmeasured', sequence: next.sequence, axis, from: before?.status ?? 'unknown', to: after.status, reason: after.reason, observedAt: next.observedAt });
143
+ } else if (before && (before.status !== after.status || JSON.stringify(previous?.values[axis]) !== JSON.stringify(next.values[axis]))) {
144
+ rows.push({ kind: 'supply.changed', sequence: next.sequence, axis, from: before.status, to: after.status, reason: null, observedAt: next.observedAt });
145
+ }
146
+ }
147
+ return rows;
148
+ }
149
+ }
@@ -0,0 +1,52 @@
1
+ import { inspectCodexRotation, readCachedGrokQuota } from '../oauth/codex-account-store.js';
2
+ import { readParentHostCapacity, type ParentHostConfig } from '../task-agent/parent-host.js';
3
+ import { measureMemberOccupancy, parsePodPool } from '../task-orchestrator/surfaces/pod-pool.js';
4
+ import type { SupplyProbes, SupplyValues } from './snapshot.js';
5
+
6
+ /** Host credential and cost transports are caller-owned: this module never transfers secret material. */
7
+ export interface SupplyProbeDependencies {
8
+ podPoolSpec: () => string | null;
9
+ parentHosts: () => readonly ParentHostConfig[];
10
+ readCost: () => Promise<SupplyValues['cost']> | SupplyValues['cost'];
11
+ readHostCredentials: () => Promise<SupplyValues['hostCredentials']> | SupplyValues['hostCredentials'];
12
+ inspectCodex?: typeof inspectCodexRotation;
13
+ grokQuota?: typeof readCachedGrokQuota;
14
+ occupancy?: typeof measureMemberOccupancy;
15
+ parentCapacity?: typeof readParentHostCapacity;
16
+ }
17
+
18
+ /** Existing provider and pool readers are projected to the no-secret supply contract. */
19
+ export function createSupplyProbes(deps: SupplyProbeDependencies): SupplyProbes {
20
+ return {
21
+ codex: () => {
22
+ const state = (deps.inspectCodex ?? inspectCodexRotation)();
23
+ return { accounts: state.candidates.map(candidate => ({
24
+ name: candidate.name,
25
+ usedPercent: candidate.usedPercent ?? null,
26
+ signalAt: state.observedAtByHome[candidate.home] === undefined ? null : new Date(state.observedAtByHome[candidate.home]).toISOString(),
27
+ available: state.freshByHome[candidate.home] !== true ? null : candidate.reached === true ? false : null,
28
+ })) };
29
+ },
30
+ grok: () => ({ quota: (deps.grokQuota ?? readCachedGrokQuota)(), observedAt: null }),
31
+ cost: deps.readCost,
32
+ pool: () => {
33
+ const spec = deps.podPoolSpec();
34
+ if (!spec) throw new Error('pool-unconfigured');
35
+ const members = parsePodPool(spec);
36
+ const measured = (deps.occupancy ?? measureMemberOccupancy)(members);
37
+ return { members: members.map(member => ({
38
+ context: member.context, occupied: measured[member.context]?.occupied ?? null, capacity: member.capacity,
39
+ })) };
40
+ },
41
+ hostCredentials: deps.readHostCredentials,
42
+ parentHosts: () => ({ hosts: deps.parentHosts().map(host => {
43
+ const measurement = (deps.parentCapacity ?? readParentHostCapacity)(host);
44
+ return {
45
+ host: host.host,
46
+ approvalCapacity: host.approvalCapacity ?? 1,
47
+ active: measurement?.active ?? null,
48
+ headroom: measurement?.approvalHeadroom ?? null,
49
+ };
50
+ }) }),
51
+ };
52
+ }