elanous 0.2.42 → 0.2.44

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 (764) 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/{X1ucLw10Cds_h614NoEnh → HMXsxdy5MIIcHPMHv1wD4}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/08334415.f0e80896acbef722.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1032-78ba4f6391258cab.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1082-53f86a26e03d309d.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1109-7d0e264f6f2edbc7.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1124-7c26330402481143.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{2160.a097e7b138ae1c55.js → 118.2a89982fe4276880.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1244.6c435dbf1bf21d8a.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1252.9e665904d3aa3b1a.js +32 -0
  12. package/apps/pwa/out/_next/static/chunks/1266.a46cc33cb6a72d75.js +104 -0
  13. package/apps/pwa/out/_next/static/chunks/1306.967240ede9a0f757.js +24 -0
  14. package/apps/pwa/out/_next/static/chunks/1344.3b95f3bd1b77a3fe.js +94 -0
  15. package/apps/pwa/out/_next/static/chunks/{4043.6b91203436c9c86b.js → 1401.22dfe92640a2b1ac.js} +4 -4
  16. package/apps/pwa/out/_next/static/chunks/1431-f7c78bd5be21e011.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1451-cdd35a8a0b31834b.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{6632.0eac1c554f8f2ef3.js → 1694.18debfd77562e56d.js} +2 -2
  19. package/apps/pwa/out/_next/static/chunks/1708-f03d587b7a7545c8.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1775-fa7152bdeff6c95f.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/178-4da509cd7266672a.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/1850-522de4ee34957210.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/1876-c6f6e0ddcc76c6a1.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/1976.097066b072432242.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{3507.97e1977bc4d5fb0a.js → 1978.eeb60a606dc5deac.js} +2 -2
  26. package/apps/pwa/out/_next/static/chunks/2043.e233e3b5a3e790f5.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2150.71b94e3348107c83.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2158.ebc6fc5a10280ab7.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2216.802962c04f40a26e.js +64 -0
  30. package/apps/pwa/out/_next/static/chunks/2294.7890edcfa046c97d.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/235.c89aaae4bcd6233a.js +74 -0
  32. package/apps/pwa/out/_next/static/chunks/{5885.0a3e52c8faccec98.js → 239.de075467b5523469.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/249.ba7051590d603c8f.js +226 -0
  34. package/apps/pwa/out/_next/static/chunks/2571.a6ac4e26c8618403.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/2610.e149cd564a08913e.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/2705.9816f3c244f8b85f.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/2801.afeb8a4dae22f85f.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/2954.bbefc95d6b20e0d8.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/2e0f720a.a0697c08e3806a60.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3042.96ec235fe41c8d4e.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3097-8e358f158acef46b.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3205-93b1abe28b4fb16a.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3273.b4434f0dcae7eb29.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3311.9cbc43ea0c90d60c.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{1487.2f67b79444062da6.js → 3349.b5f09ee474d9533e.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/3503.a47a9755fb4d97b0.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/3506-5f429b3b7e1392b0.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/3843.bad404d008893291.js +77 -0
  49. package/apps/pwa/out/_next/static/chunks/3877-4b40e530b47e3bf9.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/435-ce2958253cf7de61.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4393.28fa5228d0eec217.js +149 -0
  52. package/apps/pwa/out/_next/static/chunks/4404.7281c847c6e10dfc.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/{8673-bab689a55f7e13b9.js → 4415-b9d6a90960920a4a.js} +3 -3
  54. package/apps/pwa/out/_next/static/chunks/447-5b304de1fe098f43.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/4484-8ebea83d431e6fae.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/{8262.ddc03e06b733f184.js → 4502.bdcc877abd437a05.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/4599-f95790fc5c65b8df.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/{1262.e804feb8fd1acb8c.js → 46.57c783fa4884714f.js} +2 -2
  59. package/apps/pwa/out/_next/static/chunks/463-b9114e411f33728e.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/4659.a57d1f0c5d754cd2.js +36 -0
  61. package/apps/pwa/out/_next/static/chunks/4722-a847e7a28115035f.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/{1063.2fb8a9dc55c731f2.js → 4757.67c6d7473a038e78.js} +1 -1
  63. package/apps/pwa/out/_next/static/chunks/4874-c86f878ec4502ad3.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{6377.bc7df239edbff244.js → 4891.3f80ba517a3b2373.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/4998.810ca8833084caa9.js +62 -0
  66. package/apps/pwa/out/_next/static/chunks/4f98febc.ea5841d4d616bfb2.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/{3482.a9ae9d2ad6a5bd97.js → 5052.7dbb12a55d4f18f5.js} +1 -1
  68. package/apps/pwa/out/_next/static/chunks/5166-ca73b3e361085a6d.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/5180-039f4a18b07ad387.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/5232.5a2ce4daf7a9e11d.js +115 -0
  71. package/apps/pwa/out/_next/static/chunks/5439.3fec6dbce29ecb36.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/5612-074d9a5e00dfac6a.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/5675-01989d524a84c505.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/5751.af641a1adf5ec697.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/5758-c6cb98714d18ab0c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/578eded8.b582637306e16964.js +122 -0
  77. package/apps/pwa/out/_next/static/chunks/5790.5eb06a653ebd8571.js +34 -0
  78. package/apps/pwa/out/_next/static/chunks/5853-4033e5bd5afbe06b.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/5904.97d70bb7f46b2db7.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/{3347.f846266b5e5f3ede.js → 5989.7ecd362c5c44b747.js} +3 -3
  81. package/apps/pwa/out/_next/static/chunks/{73d2eb0e.4966ad55293c801a.js → 5a34fb2f.52f1b4e1baebb48a.js} +3 -3
  82. package/apps/pwa/out/_next/static/chunks/{7a98bc80.fa935989e829f9c2.js → 5a5078f8.2099200e5ea95e16.js} +1 -1
  83. package/apps/pwa/out/_next/static/chunks/6036-c302c34ff0b3d410.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/606.ef81c313381f4264.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/616.1af54a928b1ba704.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/6201.bc936f71f613a8e9.js +41 -0
  87. package/apps/pwa/out/_next/static/chunks/6204-fdc86e0e64c4f92d.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/{7411.9b4b8b747dc7b802.js → 6245.1182e007e9d230d9.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/{b450776b.3db34d8d965f82d3.js → 63699a35.17262e162bc514b2.js} +1 -1
  90. package/apps/pwa/out/_next/static/chunks/6420.494801a80030160c.js +27 -0
  91. package/apps/pwa/out/_next/static/chunks/{e8543907.5b040a5f22a0b0e5.js → 6549dad0.2740b25e51bf8f05.js} +1 -1
  92. package/apps/pwa/out/_next/static/chunks/{9427.96aa912ddb5801e0.js → 6881.9e7955847640c7fe.js} +17 -17
  93. package/apps/pwa/out/_next/static/chunks/6931.fcdfb94141e67b3d.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/6991-8e081c6ce38c0ba1.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7010.1bbd17a7f2b3e376.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7029.d1466acf55fae2ed.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7152-a123aa8e129c131f.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7455.196168fffac3b9c4.js +24 -0
  99. package/apps/pwa/out/_next/static/chunks/7638.6ca4770dd1129138.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/7649-f37d76260e5e2a5a.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/7679.32c40cdd14f20b4a.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/7751.04bfbd16b4c6cd0a.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/7864.b1ff31d4030b8994.js +148 -0
  104. package/apps/pwa/out/_next/static/chunks/7869-c47bd2c075c1fefa.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{8138.6c10b2a356d52fca.js → 8442.2f09ca969d631615.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8445.2738dbd59a78c78c.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8447.5510c439f9938c6d.js +286 -0
  108. package/apps/pwa/out/_next/static/chunks/{9415.69e4a21c60c7d2db.js → 8551.f762945c2cda2e95.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/8635-57a9d8d9db70f4f1.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/86961958-4b0689a5048f756b.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/8709.3c6019bb18f8554f.js +8 -0
  112. package/apps/pwa/out/_next/static/chunks/8759.c999528a0a907bf6.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{9a852a62-6192a6ea9346ced3.js → 87f498e5-0881de09f2e44707.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/8843.c3197f904c952b81.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/{3d0154af.5331fec737ffe8c3.js → 892fd990.456232f326cc39c2.js} +1 -1
  116. package/apps/pwa/out/_next/static/chunks/8965-135a2c9eaa2464cb.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/8971-8d3b9c96f8a6c958.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9059.c8598d96f8e5e9cd.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9115.90447ae198b84eae.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9147.d9b0a02e0babc9b4.js +93 -0
  121. package/apps/pwa/out/_next/static/chunks/9204-83075f4b70c61cdc.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9244-c32ef14b5dc72bdf.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/930.2a9a30f964350c66.js +90 -0
  124. package/apps/pwa/out/_next/static/chunks/9398.1f56e3f17795f43f.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/9527.3e5ad31c891c5fcb.js +79 -0
  126. package/apps/pwa/out/_next/static/chunks/9571-4ac933e774d1225c.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-9fc644de2d8edae3.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/approvals/page-0c9dace2db62bee8.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f5e65c3dc9d89f2a.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/board/page-2a9c19b9a140b7b1.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/botlab/page-61533ad92141adfb.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/bots/page-112004ced6fd0329.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/ceo/page-f733318c237a49d8.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/chat/page-51ea677d2d33bbc0.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/consult/page-428b41f2f9566e3c.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/control/page-1b29396ea90a61e5.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/decisions/page-cf83ec613ac904bf.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/design-check/page-3f4c0ecbc284bb5f.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/editor/page-b63c322f54f70cc6.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/exec/page-fe328c4ee9aac6b4.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/field/page-bfb855c584f0fb98.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/healthz/route-9fc644de2d8edae3.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/inside/page-47b1710c110eabd7.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/intake/page-42895214458bc6d2.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/layout-d03de0ebd8366e23.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/live/page-3ed6c47e4b1c61c2.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/live-run/page-ae653e9bf261c738.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/loops/page-23f3f0a0209c0ac4.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/market/page-88c691273aae66f9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e187ac52a95538b3.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/morning/page-6e45828daed1295e.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/not-found-edb5d7287bb46186.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4a7eaacd93c3f6a5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ca073d43d74cc84.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1e9fee67b1199436.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-df1283ea963c6816.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/outputs/page-19fcf8d8301ccd18.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/page-5ab699e0303bbb40.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7cde0d29756984c5.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-9d4c598e8ee22f7a.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/sessions/page-cc1609a71f44ec62.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7659a9a1345bfaa9.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/settings/page-0afef60ecc0c4af5.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-a3553949f8f34f5f.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/setup/layout-9fc644de2d8edae3.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/setup/page-057a69702f3c67c7.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/share/page-c0f0e570f3f74c73.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/showroom/page-1825071ae34e3b89.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/tasks/page-6244e3e135d8ccfc.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/term/page-da787e8a10b8a82e.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/today/page-1316d32498e2be42.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/trace/page-4df94572e343de2e.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/vault/page-708969f7475e88c1.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-c58add08c919a1dc.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/workflows/page-a24847f45e5d5bf9.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/app/workspace/page-acfec65a3a60e22e.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-3dfc598e6fbde245.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/framework-c658a626118411b7.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-4c73685fd891445b.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-6310f7e5de7dd01d.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-51c326bf48610be1.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-d0beadf754da59b0.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-acd243bfbf3f6732.js +1 -0
  184. package/apps/pwa/out/_next/static/css/d1f8bb401740a549.css +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +23 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/catalog/external-commands.yaml +5 -3
  279. package/catalog/meta/catalogVersion.yaml +2 -1
  280. package/catalog/signing/catalog-signing-public.pem +3 -0
  281. package/graphs/intake/intake-daily.yaml +16 -0
  282. package/graphs/intake/news-sources.yaml +1 -0
  283. package/graphs/intake/recipes.yaml +7 -0
  284. package/graphs/overlays/README.md +6 -0
  285. package/graphs/overlays/examples/research-runtime-empty-terminal.yaml +28 -0
  286. package/graphs/profiles/local.yaml +5 -0
  287. package/graphs/profiles/pod.yaml +4 -0
  288. package/graphs/release/release-loop.yaml +33 -17
  289. package/graphs/units/verbs/make-doc.yaml +1 -0
  290. package/package.json +6 -2
  291. package/plugins/demo-absorption-briefing/plugin.json +18 -0
  292. package/plugins/demo-absorption-briefing/skills/demo-absorption-briefing/SKILL.md +8 -0
  293. package/plugins/demo-browser-hand/plugin.json +13 -0
  294. package/plugins/demo-browser-hand/skills/demo-browser-hand/SKILL.md +8 -0
  295. package/plugins/demo-linear-secretary/plugin.json +15 -0
  296. package/plugins/demo-linear-secretary/skills/demo-linear-secretary/SKILL.md +8 -0
  297. package/plugins/demo-plugin-wizard/plugin.json +11 -0
  298. package/plugins/demo-plugin-wizard/skills/demo-plugin-wizard/SKILL.md +8 -0
  299. package/plugins/demo-research/plugin.json +16 -0
  300. package/plugins/demo-research/skills/demo-research/SKILL.md +8 -0
  301. package/plugins/demo-video-briefing/plugin.json +15 -0
  302. package/plugins/demo-video-briefing/skills/demo-video-briefing/SKILL.md +8 -0
  303. package/scripts/bench-metering-plan.ts +229 -0
  304. package/scripts/build-signed-catalog.ts +48 -0
  305. package/scripts/ci-typecheck-main-delta.sh +88 -0
  306. package/scripts/codex-fallback-live-probe.ts +1 -1
  307. package/scripts/demo/demo1104-parallel-host.ts +56 -0
  308. package/scripts/demo/demo1104-parallel-scenes.ts +301 -0
  309. package/scripts/demo/demo1104-parallel.ts +72 -0
  310. package/scripts/demo/demo1104-stage.config.ts +21 -0
  311. package/scripts/demo/demo1104-stage.ts +316 -0
  312. package/scripts/goal-method-audit.ts +17 -1
  313. package/scripts/graph-units/land-enqueue.ts +90 -0
  314. package/scripts/hooks/codex-notify.sh +32 -0
  315. package/scripts/install.sh +10 -38
  316. package/scripts/landing-heal/land-plan.ts +57 -0
  317. package/scripts/public-leak-baseline.txt +0 -1
  318. package/scripts/release-loop/auto-approve-node.ts +1 -1
  319. package/scripts/release-loop/docs-node.ts +4 -2
  320. package/scripts/release-loop/gate-autoheal-sim-evidence.ts +60 -0
  321. package/scripts/release-loop/gate-image-pin.ts +116 -2
  322. package/scripts/release-loop/gate-method.ts +139 -0
  323. package/scripts/release-loop/gate-node.ts +395 -43
  324. package/scripts/release-loop/gate-progress-sim.ts +73 -0
  325. package/scripts/release-loop/gate-traffic-mode.ts +151 -3
  326. package/scripts/release-loop/node-verdict.ts +38 -25
  327. package/scripts/release-loop/notes-repair.ts +18 -1
  328. package/scripts/release-loop/preflight.ts +544 -10
  329. package/scripts/release-loop/render-warm-control-manifest.ts +22 -0
  330. package/scripts/release-loop/resume-release.ts +9 -7
  331. package/scripts/release-loop/resume.ts +13 -4
  332. package/scripts/release-loop/unattended-release.ts +20 -9
  333. package/scripts/release-loop/warm-control-forward.ts +178 -0
  334. package/scripts/retro-cycle.ts +30 -8
  335. package/scripts/rhythm/daily.ts +39 -4
  336. package/scripts/rhythm/linear-progress-sync.ts +311 -0
  337. package/scripts/ux-sim.ts +7 -1
  338. package/scripts/video-pipeline.ts +9 -1
  339. package/scripts/warm-pool-provider-config.ts +35 -7
  340. package/src/acp/agent-manager.ts +1 -0
  341. package/src/acp/codex-app-server-agent.ts +33 -0
  342. package/src/acp/codex-app-server-client.ts +153 -16
  343. package/src/acp/core-turn-bridge.ts +17 -12
  344. package/src/acp/event-router.ts +20 -1
  345. package/src/acp/server.ts +6 -0
  346. package/src/agent-mission/browser-roundtrip-coordinator.ts +85 -0
  347. package/src/agent-mission/claude-headless.ts +4 -1
  348. package/src/agent-mission/codex-exec.ts +105 -0
  349. package/src/agent-mission/driver.ts +192 -11
  350. package/src/agent-mission/grok-auth-status.ts +107 -0
  351. package/src/agent-mission/hand-hooks.ts +101 -0
  352. package/src/agent-mission/mission-cli.ts +56 -21
  353. package/src/agent-mission/mission-hand-reply.ts +118 -0
  354. package/src/agent-mission/mission-line.ts +180 -0
  355. package/src/agent-mission/mission-out.ts +256 -18
  356. package/src/agent-mission/tool-install.ts +122 -11
  357. package/src/agent-substrate/pr-reviewer.ts +147 -11
  358. package/src/agent-substrate/self-review-cli.ts +10 -2
  359. package/src/agents/general-purpose.md +1 -1
  360. package/src/auto-research/research-fanout.ts +221 -0
  361. package/src/auto-research/research-turn.ts +362 -31
  362. package/src/autopilot/mission-codebase-gate.ts +7 -3
  363. package/src/autopilot/pr-manager.ts +31 -3
  364. package/src/boot/daemon-tools/self-implement.ts +3 -1
  365. package/src/boot/daemon-tools/web-search.ts +1 -2
  366. package/src/briefing/brief-items.ts +55 -11
  367. package/src/cli/agent-cli.ts +2 -1
  368. package/src/cli/catalog-cli.ts +31 -0
  369. package/src/cli/connector-cli.ts +16 -0
  370. package/src/cli/control-cli.ts +15 -6
  371. package/src/cli/doctor-fix.ts +2 -2
  372. package/src/cli/intake-source-cli.ts +44 -8
  373. package/src/cli/log-event-names.ts +8 -0
  374. package/src/cli/msg-cli.ts +32 -3
  375. package/src/cli/pr-cli.ts +21 -1
  376. package/src/cli/pr-land-heavy-remote.ts +44 -6
  377. package/src/cli/pr-land-overlap-evidence.ts +13 -1
  378. package/src/cli/pr-land-pod-shadow-job.ts +143 -5
  379. package/src/cli/pr-land-pod-shadow.ts +9 -2
  380. package/src/cli/release-checklist-read-cli.ts +44 -16
  381. package/src/cli/release-cli.ts +23 -3
  382. package/src/cli/research-cli.ts +9 -0
  383. package/src/cli/setup-cli.ts +166 -6
  384. package/src/cli/setup-keys.ts +199 -0
  385. package/src/cli/task-plugin-wizard-host.ts +114 -0
  386. package/src/cli/tasks-cli.ts +54 -9
  387. package/src/cli/tui-test-cli.ts +190 -0
  388. package/src/config.ts +4 -2
  389. package/src/connectors/linear-daily-progress.ts +228 -0
  390. package/src/connectors/linear-projector.ts +34 -12
  391. package/src/connectors/linear.ts +151 -7
  392. package/src/control-plane/ledger.ts +42 -4
  393. package/src/control-plane/member-tokens.ts +25 -2
  394. package/src/control-plane/ports.ts +8 -3
  395. package/src/control-plane/server.ts +26 -5
  396. package/src/core-turn/deep-turn-bloom.ts +67 -0
  397. package/src/core-turn/research-policy.ts +43 -0
  398. package/src/core-turn/run-core-turn.ts +488 -51
  399. package/src/core-turn/types.ts +4 -0
  400. package/src/dashboard/chat/acp-chat.ts +10 -0
  401. package/src/dashboard/classic-sidetab-mission-job.ts +192 -0
  402. package/src/dashboard/classic-sidetab-mission-pair.ts +82 -0
  403. package/src/dashboard/classic-sidetab-mission-trio.ts +242 -0
  404. package/src/dashboard/classic-sidetab-mission.ts +169 -5
  405. package/src/dashboard/index.ts +387 -14
  406. package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
  407. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +8 -0
  408. package/src/dashboard/mission-cli-consumer.ts +20 -8
  409. package/src/dashboard/plugin-wizard-runtime.ts +50 -0
  410. package/src/dashboard/plugin-wizard-tool.ts +55 -0
  411. package/src/dashboard/sidetab-runtime.ts +3 -1
  412. package/src/dashboard/terminal-popup-runtime.ts +6 -3
  413. package/src/dashboard/visible-mission-diagnostics.ts +16 -0
  414. package/src/decisions/linear-progress-summary.ts +78 -0
  415. package/src/decisions/linear-progress-sync.ts +152 -0
  416. package/src/domains/outbound-alert.ts +49 -11
  417. package/src/domains/retro-cycle-observation.ts +43 -0
  418. package/src/domains/retro-cycle.ts +13 -2
  419. package/src/domains/retro-proposals.ts +92 -0
  420. package/src/domains/retro-report.ts +6 -1
  421. package/src/domains/telegram-kind-route.ts +16 -9
  422. package/src/graph-runner/arg-allowance.ts +13 -0
  423. package/src/graph-runner/graph-cli.ts +24 -1
  424. package/src/graph-runner/graph-grow-llm.ts +3 -1
  425. package/src/graph-runner/graph-run-api.ts +3 -1
  426. package/src/graph-runner/runner.ts +310 -46
  427. package/src/graph-wizard/mission-compose.ts +407 -12
  428. package/src/harness/dispatch-backpressure.ts +54 -1
  429. package/src/harness/dispatch-shadow-compare.ts +74 -0
  430. package/src/harness/harness-cli-command.ts +15 -3
  431. package/src/harness/harness-pod-dispatch.ts +3 -0
  432. package/src/harness/skill-exec.ts +21 -9
  433. package/src/harness/skill-select.ts +1 -1
  434. package/src/hooks/error-report-cloud.ts +101 -0
  435. package/src/hooks/receiver.ts +29 -2
  436. package/src/index.ts +129 -12
  437. package/src/intake-plane/actions.ts +354 -0
  438. package/src/intake-plane/adapters/telegram-ambient.ts +34 -18
  439. package/src/intake-plane/intake-sources.ts +78 -8
  440. package/src/intake-plane/items.ts +14 -4
  441. package/src/intake-plane/linear-mission-sync.ts +80 -0
  442. package/src/intake-plane/linear-secretary-runtime.ts +178 -0
  443. package/src/intake-plane/linear-wish.ts +227 -1
  444. package/src/life/life-cli.ts +168 -0
  445. package/src/life/life-kinds.ts +160 -0
  446. package/src/live-supply/budget-consumer.ts +78 -0
  447. package/src/live-supply/read.ts +3 -0
  448. package/src/live-supply/snapshot.ts +45 -0
  449. package/src/llm/child-first-llm-observation.ts +112 -0
  450. package/src/llm/provider-credentials.ts +68 -6
  451. package/src/llm/provider-failure-evidence.ts +44 -0
  452. package/src/llm.ts +172 -12
  453. package/src/maturity/feature-maturity.ts +3 -3
  454. package/src/mcp/client.ts +7 -0
  455. package/src/mcp/proxy-runtime.ts +6 -1
  456. package/src/mcp/server.ts +54 -0
  457. package/src/msg/msg-sse-server.ts +3 -3
  458. package/src/msg/msg-store.ts +177 -19
  459. package/src/native-tool-catalog.ts +36 -2
  460. package/src/nexus/api/consult-requests.ts +18 -6
  461. package/src/nexus/api/discord-trigger-bot.ts +6 -6
  462. package/src/nexus/api/graphs-api.ts +4 -2
  463. package/src/nexus/api/grokbot-trigger-bot.ts +206 -0
  464. package/src/nexus/api/http-server.ts +37 -1
  465. package/src/nexus/api/mcp-public-allowlist.ts +2 -0
  466. package/src/nexus/api/telegram-trigger-bot.ts +6 -6
  467. package/src/nexus/boot/register-mcp-clients.ts +114 -8
  468. package/src/nexus/index.ts +22 -2
  469. package/src/nexus/outbound/format.ts +9 -0
  470. package/src/nexus/outbound/grokbot-adapter.ts +71 -0
  471. package/src/nexus/outbound/router.ts +121 -16
  472. package/src/nexus/setup-status.ts +9 -0
  473. package/src/nexus/state/state.ts +3 -0
  474. package/src/oauth/codex-account-store.ts +20 -7
  475. package/src/oauth/codex-owner-mirror.ts +81 -0
  476. package/src/oauth/codex.ts +17 -2
  477. package/src/oauth/fallback-chain.ts +47 -17
  478. package/src/onboarding/first-run-doctor.ts +8 -1
  479. package/src/onboarding/first-run.ts +126 -29
  480. package/src/onboarding/key-setup.ts +103 -0
  481. package/src/onboarding/menu-answer.ts +13 -0
  482. package/src/onboarding/secret-prompt.ts +37 -0
  483. package/src/plugins/install/plugin-install.ts +59 -0
  484. package/src/pr-tool/census.ts +130 -0
  485. package/src/preview/terminal.ts +22 -7
  486. package/src/prompt-enhance/enhance.ts +10 -0
  487. package/src/pty-shell/pty-control-ipc.ts +4 -1
  488. package/src/pty-shell/pty-write-provenance.ts +21 -3
  489. package/src/pty-shell/registry.ts +9 -2
  490. package/src/registry/catalog-server.ts +232 -0
  491. package/src/registry/loader.ts +45 -1
  492. package/src/registry/types.ts +1 -2
  493. package/src/release-loop/proposal-auto-place.ts +83 -0
  494. package/src/research/axis-fanout.ts +79 -29
  495. package/src/research/lenses/second-order.ts +312 -0
  496. package/src/self-dev/ask-launch-flow.ts +72 -1
  497. package/src/self-dev/dev-cli.ts +7 -2
  498. package/src/self-dev/dev-pipeline.ts +5 -0
  499. package/src/self-dev/draft-residue.ts +64 -5
  500. package/src/self-dev/draft-sweep.ts +31 -10
  501. package/src/self-dev/draft-triage-rules.ts +60 -3
  502. package/src/self-dev/graph-front-nodes.ts +2 -1
  503. package/src/self-dev/graph-journey-route.ts +76 -21
  504. package/src/self-dev/launch-preflight.ts +58 -0
  505. package/src/self-dev/orchestrate.ts +1 -1
  506. package/src/self-dev/run-supervisor.ts +152 -2
  507. package/src/self-dev/shard-aggregate.ts +4 -0
  508. package/src/self-dev/shard-run.ts +36 -15
  509. package/src/self-implement/abandoned-classification.ts +12 -3
  510. package/src/self-implement/budget-gate.ts +7 -0
  511. package/src/self-implement/child-llm-preference.ts +10 -1
  512. package/src/self-implement/doctor-visit.ts +30 -8
  513. package/src/self-implement/elanous-tui-spawn.ts +3 -0
  514. package/src/self-implement/fixtures/tdd-green-missing-passing-child-transcript.txt +2 -0
  515. package/src/self-implement/gate-artifacts.ts +2 -1
  516. package/src/self-implement/goal-author-cli.ts +4 -2
  517. package/src/self-implement/goal-author.ts +549 -10
  518. package/src/self-implement/graph-overlay-yaml.ts +181 -4
  519. package/src/self-implement/graph-overlay.ts +3 -1
  520. package/src/self-implement/graph-profile-yaml.ts +107 -0
  521. package/src/self-implement/graph-yaml.ts +94 -5
  522. package/src/self-implement/off-diff-evidence.ts +249 -5
  523. package/src/self-implement/orchestrator.ts +298 -26
  524. package/src/self-implement/run-chart.ts +6 -3
  525. package/src/self-implement/run-ledger.ts +51 -1
  526. package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
  527. package/src/self-implement/tdd-evidence-tags.ts +9 -0
  528. package/src/self-implement/test-scenario-request.ts +37 -6
  529. package/src/self-implement/train-gate-receipt.ts +166 -0
  530. package/src/self-implement/train-gate-remote.ts +62 -18
  531. package/src/session/chat.ts +6 -4
  532. package/src/session/session-fanout.ts +2 -0
  533. package/src/session/streaming/acp-stream-sink.ts +2 -1
  534. package/src/session/streaming/chunk-producer.ts +6 -0
  535. package/src/session/streaming/stream-compositor.ts +3 -2
  536. package/src/session-runtime/index.ts +74 -6
  537. package/src/session-runtime/retry-policy.ts +1 -1
  538. package/src/setup/llm-env-detect.ts +3 -0
  539. package/src/setup/service-key-catalog.ts +46 -0
  540. package/src/setup/service-keys.ts +241 -0
  541. package/src/sidetab-core/model.ts +205 -10
  542. package/src/sidetab-core/visible-agent-mission-pair.ts +51 -0
  543. package/src/sidetab-core/visible-agent-mission.ts +182 -48
  544. package/src/skills/tools/agent.ts +23 -4
  545. package/src/skills/tools/omni-search.ts +127 -27
  546. package/src/task-agent/parent-host.ts +29 -1
  547. package/src/task-agent/recall-inject.ts +98 -0
  548. package/src/task-agent/repair-outcomes.ts +65 -0
  549. package/src/task-agent/task-hand.ts +46 -14
  550. package/src/task-orchestrator/dispatcher.ts +14 -1
  551. package/src/task-orchestrator/linear-capture-events.ts +55 -0
  552. package/src/task-orchestrator/store.ts +16 -5
  553. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +23 -1
  554. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +107 -1
  555. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
  556. package/src/task-orchestrator/surfaces/pod-si-warm-host.ts +21 -9
  557. package/src/task-orchestrator/surfaces/pod-source-receive.ts +23 -11
  558. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
  559. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +1 -1
  560. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +467 -77
  561. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +45 -3
  562. package/src/task-orchestrator/surfaces/self-implement-pod.ts +210 -14
  563. package/src/task-orchestrator/surfaces/self-implement.ts +27 -3
  564. package/src/task-orchestrator/surfaces/warm-reuse-evidence.ts +169 -0
  565. package/src/task-orchestrator/types.ts +14 -0
  566. package/src/telegram.ts +14 -16
  567. package/src/terminal/coding-agent.ts +14 -5
  568. package/src/terminal/session-registry.ts +1 -1
  569. package/src/tool-hints/gate.ts +46 -14
  570. package/src/tool-hints/signals.ts +1 -1
  571. package/src/tool-hints/types.ts +2 -0
  572. package/src/tool-runtime/agent-runtime.ts +1 -0
  573. package/src/tool-runtime/browser-hand-runtime.ts +391 -0
  574. package/src/tool-runtime/browser-runtime.ts +33 -19
  575. package/src/tool-runtime/elanous-linear-issue-runtime.ts +76 -0
  576. package/src/tool-runtime/elanous-linear-secretary-runtime.ts +173 -0
  577. package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
  578. package/src/tool-runtime/index.ts +6 -0
  579. package/src/tool-runtime/types.ts +5 -0
  580. package/src/tui/entry.ts +51 -8
  581. package/src/tui/sidetab/attach.ts +252 -11
  582. package/src/tui/sidetab/herdr-portal.ts +225 -0
  583. package/src/tui/sidetab/list.ts +3 -2
  584. package/src/tui-client/next-dashboard-runtime.ts +52 -0
  585. package/src/user-config.ts +34 -9
  586. package/src/user-intent/types.ts +4 -3
  587. package/src/ux-sim/browser-hand.ts +165 -0
  588. package/src/ux-sim/draft-inventory-builder.ts +199 -0
  589. package/src/ux-sim/fake-browser-page.ts +81 -0
  590. package/src/ux-sim/fake-linear-device.ts +31 -0
  591. package/src/ux-sim/graph-engine-sim.ts +47 -0
  592. package/src/ux-sim/linear-secretary.ts +208 -0
  593. package/src/ux-sim/mock-scenario-catalog.json +81 -26
  594. package/src/ux-sim/mock-scenario-catalog.ts +175 -5
  595. package/src/ux-sim/onboarding-first-run-device.ts +31 -21
  596. package/src/ux-sim/release-sim-rig.ts +62 -18
  597. package/src/ux-sim/scenario.ts +70 -26
  598. package/src/ux-sim/service-key-setup.ts +113 -0
  599. package/src/ux-sim/term-slash-device.ts +74 -0
  600. package/src/ux-sim/turn-throw-sim.ts +31 -0
  601. package/src/version/packed-revision.json +1 -1
  602. package/src/web-search/exa.ts +77 -0
  603. package/src/web-search/index.ts +30 -9
  604. package/src/web-search/provider.ts +4 -1
  605. package/src/web-search/x-intent.ts +5 -0
  606. package/apps/pwa/out/_next/static/chunks/0244e5b5.6fc7670f8223d82d.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/1121.13ba7a8aff19df81.js +0 -36
  608. package/apps/pwa/out/_next/static/chunks/1147-5196d19c222051b3.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/1319.b9b815ae0f181e06.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/1345-31427b833438f521.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/1455-530ca16c7e71baff.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/1574.878c18ecc97b1bd4.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/1586.fafc33a9a5835cb7.js +0 -32
  614. package/apps/pwa/out/_next/static/chunks/1744.855fd60ae4c4a8c8.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/193.21a47a3e07ef6860.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/1945.7b54990d578c119b.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/2004.e839fda7ea5a738a.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/2044-dd681a5c08779ff8.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/2101.2248decb38829b03.js +0 -286
  620. package/apps/pwa/out/_next/static/chunks/2300.41ea70ac1bef1446.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/2357-07b5eeb5fb12628d.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/2364.28652020695a6db3.js +0 -34
  623. package/apps/pwa/out/_next/static/chunks/2456.b6de0e1c05f28843.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/2526.c3e50ac1fec064bd.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/2549-cda50b716ff4250c.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/2550-5f1e88f615568045.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/261-319078c954e40d66.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/2690.0521c738b7749931.js +0 -115
  629. package/apps/pwa/out/_next/static/chunks/2974.595d1e29d040cb6a.js +0 -64
  630. package/apps/pwa/out/_next/static/chunks/3207.a756c95e9ec8c3c8.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/3285.89ee2f298682f5e5.js +0 -93
  632. package/apps/pwa/out/_next/static/chunks/3447.06edc7b092021417.js +0 -41
  633. package/apps/pwa/out/_next/static/chunks/3510-9ca392698bfe4391.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/3541.772e5ce425aaa611.js +0 -24
  635. package/apps/pwa/out/_next/static/chunks/3741.9cf76acaa2ee5298.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/3837.a210d7d0db8d8abd.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/3898-955c896f394217a6.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/3947-ef57acea76eaa8d2.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/4037-3b82ebc7d78afdc7.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/405.9022d4a478202b67.js +0 -77
  641. package/apps/pwa/out/_next/static/chunks/417-fb2cc9a9910e5968.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/4276.336d76d858fcdf1b.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/4302.6ced9aa4535de947.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/4320.583cbab64db6be02.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/4768-8eac183fd291ca53.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/4770.769c9cd9c7034eba.js +0 -148
  647. package/apps/pwa/out/_next/static/chunks/4895.65605ec3e6504e89.js +0 -74
  648. package/apps/pwa/out/_next/static/chunks/50061469.0326382241ef3b2d.js +0 -122
  649. package/apps/pwa/out/_next/static/chunks/5112.4b9f300124fab7b3.js +0 -149
  650. package/apps/pwa/out/_next/static/chunks/5335.375ee922bcd5bc83.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/5342.023a2e729689b320.js +0 -27
  652. package/apps/pwa/out/_next/static/chunks/53c73f84.373b6160adfa89a4.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/5431-72a1dbde59400691.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/5440-4236de26c5ea5856.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/5486-b318c165f645d8ba.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/5506-c7d2ec25c62a7c94.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/5570-c66ecbea26b4e3b1.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/5696.ffca5aa259d8451e.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/5793-8c584aea2aa87560.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/5848-6de6b8c173351a90.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/5999.94e3c83040200f31.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/5a7901d6-2d8d9b5587cf9042.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/6131.348b7d6bdcd267ce.js +0 -226
  664. package/apps/pwa/out/_next/static/chunks/6164.86133a0172611184.js +0 -90
  665. package/apps/pwa/out/_next/static/chunks/6515.e07e8b2b8a707a87.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/6522-c005514f87d18982.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/6642.648adb1767f39ecf.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/6848.138805a09d001d09.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/7049-c09e2b7a253a24f3.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/7072.1e00447d9fa39972.js +0 -104
  671. package/apps/pwa/out/_next/static/chunks/7106.64201c539c5e220c.js +0 -94
  672. package/apps/pwa/out/_next/static/chunks/7151-1f742b455986530e.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/7199.18d6b25e001154ce.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/7279-c199ea83f34338fa.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/728b938d.ffaa7ad583d60e58.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/7309.171c3de54e0322f1.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/733.7a1ab3342e03306f.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/7504.d5cf1e7cd89b1b08.js +0 -24
  679. package/apps/pwa/out/_next/static/chunks/7573-0fd4af62d65d4598.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/759.6f8267df4689c401.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/7825-668b046f72f14483.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/7852-1538768b6eb19388.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/7868.cff810430bb63c91.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/8084-dfcc796874ab4e07.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/8266.6bf9b131b2584678.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/8403.7b81d5e64074a725.js +0 -8
  687. package/apps/pwa/out/_next/static/chunks/8470.1998cbd0866a7eac.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/8505.fd803c6c33b54cc3.js +0 -79
  689. package/apps/pwa/out/_next/static/chunks/8546-6f03f8ea34dd61d9.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/8687-246fda8433d3477c.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/898-280022fb082936bc.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/9098-50eefc1844212e3d.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/9211-330b6736a63d4cb3.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/9249.976f1e69a9d80754.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/9255-cf88fceda5666645.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/9306-e523ba58bb8adc42.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/9324.a9866d717ba62cb6.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/9325.a8510e8aa87c8143.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/9353-12bfff0c130104cf.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/9479-154a697d4b6e4e98.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/9540-65aa6ccc31b3fd78.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/9633.ce5bddc56784da72.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/9656-374232558fd528d0.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/9832.f4a98c878ecf2c0a.js +0 -62
  705. package/apps/pwa/out/_next/static/chunks/9865.f094440645f02d98.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-e772b4710df5d936.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4361368e6a76b967.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-802f349fdd65248d.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/board/page-7f35513988a2a495.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/botlab/page-798121656540e33e.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/bots/page-20a089490affe98c.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/ceo/page-e5e4ec786d70e604.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/chat/page-d12fe5d0801430e4.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/consult/page-d8cf21022fecc026.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/control/page-21ce565c9c57ee97.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/decisions/page-b56563025f619c9b.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/design-check/page-52f14dd133da8348.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/editor/page-c0ed7fdcdba76633.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/exec/page-af8c3020cb520f15.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/field/page-72eda67af9f5e35c.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/healthz/route-e772b4710df5d936.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/inside/page-67a6620d31f0a46f.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/intake/page-f059363aa0880ec2.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/layout-f9f917d6a57f69fb.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/live/page-d3ae55eee2f0826c.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0e3d7b9421b79dac.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/loops/page-ba738f7e233eb211.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/market/page-33438b98c74fd599.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-0b34d5fd990d793a.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/morning/page-0f291d3c8fd55a3a.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/not-found-3fced192be5279c1.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/observatory/page-04cb3cf182a7c1ea.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6ccbd2ab23a21542.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-aa0518c48a5f4e56.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4b32226d341ad7d7.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3224fd8f6383b61f.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/page-efbc97459f2914e2.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2fe487d88cd5d97c.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-48861dd1a858bab7.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/sessions/page-197d5d4d21d228ea.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a763ba89fbdd9c27.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/settings/page-7edb253510b1c136.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0c875702c61965ea.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/setup/layout-e772b4710df5d936.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/setup/page-e425c951151095f7.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/share/page-9c90e0aec4e27f77.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/showroom/page-733e09a02e727d42.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/tasks/page-4f899e14c34d77a1.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/term/page-bf067887b3307423.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/today/page-7af10868ff87d04e.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/trace/page-efe5304057aa11c7.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/vault/page-76bcd29aaa8a26c3.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-4cfd88e2273ce50f.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0a1ddb47efba0a32.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2a176c707152c892.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-efe03031b8797fbf.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/framework-d0d2d673bfd8a8a9.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/main-4c9fceb2baa09cb7.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/main-app-b0ab8d8fc9a97556.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/pages/_app-7e2cc62a2e5cec96.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/pages/_error-22324935f753ec5e.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/webpack-9dc1bfa25334998a.js +0 -1
  763. package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
  764. /package/apps/pwa/out/_next/static/{X1ucLw10Cds_h614NoEnh → HMXsxdy5MIIcHPMHv1wD4}/_ssgManifest.js +0 -0
@@ -3,7 +3,13 @@ import { detectProviders, type DetectedProvider } from '../llm/provider-detect.j
3
3
  import { debug } from '../debug/log.js';
4
4
  import { detectLocale, type Locale } from '../expression/locale.js';
5
5
  import { unattendedNextStepLine } from './entry-hints.js';
6
- import { resolveProviderCredential } from '../llm/provider-credentials.js';
6
+ import { providerEnvKey, resolveProviderCredential, resolveProviderCredentialAsync } from '../llm/provider-credentials.js';
7
+ import { zaiCodingPlanAvailable } from '../llm/zai-coding-plan.js';
8
+ import { collectServiceKeys, printKeySetupReport } from './key-setup.js';
9
+ import { getSecretAsync, setSecretAsync } from '../nexus/config/secrets/index.js';
10
+ import { probeProvider } from '../llm/provider-probe.js';
11
+ import { createSecretPrompt } from './secret-prompt.js';
12
+ import { parseMenuAnswer as parseNumericMenuAnswer } from './menu-answer.js';
7
13
  import {
8
14
  getUserConfig, saveUserConfig, userConfigPath,
9
15
  type LLMProviderName, type UserConfig,
@@ -11,44 +17,45 @@ import {
11
17
 
12
18
  export interface FirstRunDeps {
13
19
  config?: UserConfig;
20
+ env?: NodeJS.ProcessEnv;
14
21
  path?: string;
15
22
  detectProviders?: () => Promise<DetectedProvider[]>;
16
23
  isTTY?: boolean;
17
24
  /** Locale for user-facing wording; defaults to the shared ambient decision (detectLocale). */
18
25
  locale?: Locale;
19
26
  chooseProvider?: (detected: readonly LLMProviderName[]) => Promise<LLMProviderName | null>;
27
+ promptSecret?: (message: string) => Promise<string | undefined>;
28
+ getSecretAsync?: typeof getSecretAsync;
29
+ setSecretAsync?: typeof setSecretAsync;
30
+ probeKey?: typeof probeProvider;
31
+ setupWhenNoProvider?: (config: UserConfig) => Promise<FirstRunProviderSetupResult>;
20
32
  print?: (message: string) => void;
21
33
  saveConfig?: (config: UserConfig, path: string) => void;
22
34
  }
23
35
 
24
- const CHOICE_BASE: readonly LLMProviderName[] = ['openai-codex', 'grok', 'anthropic'];
25
- const CHOICE_LABEL: Partial<Record<LLMProviderName, string>> = { 'openai-codex': 'Codex', grok: 'Grok', anthropic: 'Claude' };
26
- const SUBSCRIPTION_PRIORITY = ['openai-codex', 'grok', 'anthropic', 'gemini', 'openai', 'openrouter'] as const;
36
+ export type FirstRunProviderSetupResult = LLMProviderName | null | { kind: 'needs-llm' };
27
37
 
28
- /** Menu order: detected subscriptions first (in priority order), then the remaining base choices. */
38
+ const CHOICE_BASE: readonly LLMProviderName[] = ['openai-codex', 'grok', 'anthropic', 'openrouter', 'glm'];
39
+ const CHOICE_LABEL: Partial<Record<LLMProviderName, string>> = { 'openai-codex': 'Codex', grok: 'Grok', anthropic: 'Claude', openrouter: 'OpenRouter', glm: 'GLM' };
40
+ const SUBSCRIPTION_PRIORITY = ['openai-codex', 'grok', 'anthropic', 'gemini', 'openai', 'glm', 'openrouter'] as const;
41
+
42
+ /** Menu order: detected usable providers first, then the remaining supported choices. */
29
43
  export function orderProviderChoices(detected: readonly LLMProviderName[] = []): LLMProviderName[] {
30
44
  return [...detected, ...CHOICE_BASE.filter((name) => !detected.includes(name))];
31
45
  }
32
46
 
33
- export type MenuAnswer =
34
- | { kind: 'chosen'; provider: LLMProviderName }
35
- | { kind: 'cancel' }
36
- | { kind: 'miss' };
47
+ export type MenuAnswer = import('./menu-answer.js').MenuAnswer<LLMProviderName>;
37
48
 
38
49
  // FIRST10-FIX: 첫 화면의 오타 한 번이 first-run 전체를 취소하던 마찰 — 빈 입력(취소 의사)과 달리
39
50
  // 선택지를 가리키지 못하는 입력(범위 밖·전각·비정수)은 취소가 아니라 다시 묻는다.
40
51
  // 메뉴 답으로 인정하는 건 반각 십진 자릿수 문자열뿐이다 — Number() 는 '1e0'·'0x1'·'+1' 같은
41
52
  // 수식 표기를 정수로 강제 변환해 선택지로 샌다(0.2.35 재측정).
42
53
  export function parseMenuAnswer(answer: string, choices: readonly LLMProviderName[]): MenuAnswer {
43
- const trimmed = answer.trim();
44
- if (trimmed === '') return { kind: 'cancel' };
45
- if (!/^[0-9]+$/.test(trimmed)) return { kind: 'miss' };
46
- const provider = choices[Number(trimmed) - 1];
47
- return provider !== undefined ? { kind: 'chosen', provider } : { kind: 'miss' };
54
+ return parseNumericMenuAnswer(answer, choices);
48
55
  }
49
56
 
50
57
  /**
51
- * The fixed choice line of the first-run menu (`1 Codex, 2 Grok, 3 Claude`).
58
+ * The choice line of the first-run menu.
52
59
  * Single source of the wording: the prompt below renders it, and the ux-sim
53
60
  * first-run device asserts against it, so a wording change cannot drift apart.
54
61
  */
@@ -56,6 +63,8 @@ export function formatProviderMenu(choices: readonly LLMProviderName[]): string
56
63
  return choices.map((name, i) => `${i + 1} ${CHOICE_LABEL[name] ?? name}`).join(', ');
57
64
  }
58
65
 
66
+ export const FIRST_RUN_PROVIDER_MENU_PROMPT = 'Choose LLM';
67
+
59
68
  export async function promptProviderMenu(
60
69
  ask: (prompt: string) => Promise<string>,
61
70
  detected: readonly LLMProviderName[] = [],
@@ -63,7 +72,7 @@ export async function promptProviderMenu(
63
72
  const choices = orderProviderChoices(detected);
64
73
  const menu = formatProviderMenu(choices);
65
74
  for (;;) {
66
- const parsed = parseMenuAnswer(await ask(`Choose LLM (${menu}; Enter to cancel): `), choices);
75
+ const parsed = parseMenuAnswer(await ask(`${FIRST_RUN_PROVIDER_MENU_PROMPT} (${menu}; Enter to cancel): `), choices);
67
76
  if (parsed.kind === 'chosen') return parsed.provider;
68
77
  if (parsed.kind === 'cancel') return null;
69
78
  }
@@ -84,6 +93,8 @@ const FIRST_RUN_TEXT = {
84
93
  detectedPrefix: '감지: ',
85
94
  subscription: ' 구독',
86
95
  needsLlm: 'eln setup llm 으로 고르세요',
96
+ keyStoredNotReady: '키를 저장하고 검증했지만 첫 실행에서 사용할 provider 연결은 아직 완료되지 않았습니다.',
97
+ keySetupFailed: '키 설정을 완료하지 못했습니다. 비밀 값을 표시하지 않고 중단했습니다.',
87
98
  claudeNoPath: 'claude-code 구독은 구독으로 쓸 수 있는 경로가 없어 자동 선택하지 않음',
88
99
  multipleDetected: '둘 이상 감지되어 고르세요',
89
100
  },
@@ -91,6 +102,8 @@ const FIRST_RUN_TEXT = {
91
102
  detectedPrefix: 'detected: ',
92
103
  subscription: ' subscription',
93
104
  needsLlm: 'pick a provider via eln setup llm',
105
+ keyStoredNotReady: 'The key was saved and verified, but first-run provider setup is not complete yet.',
106
+ keySetupFailed: 'Key setup could not be completed. It stopped without displaying secret values.',
94
107
  claudeNoPath: 'claude-code subscription has no usable path in elanous; not auto-selecting',
95
108
  multipleDetected: 'more than one detected; pick one',
96
109
  },
@@ -105,7 +118,19 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
105
118
  const text = FIRST_RUN_TEXT[(deps.locale ?? detectLocale()) === 'en' ? 'en' : 'ko'];
106
119
  const detectionLabel = (provider: string) =>
107
120
  `${provider === 'openai-codex' ? 'codex' : provider}${text.subscription}`;
121
+ // An incomplete onboarding marker does not mean the user's LLM is unconfigured.
122
+ // Keep an already usable provider, key and model rather than replacing it with a detected subscription.
123
+ const existing = cfg.llm.provider !== 'auto'
124
+ ? await resolveProviderCredentialAsync({ provider: cfg.llm.provider, rotation: cfg.llm.rotation,
125
+ baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey, env: deps.env }, deps.getSecretAsync)
126
+ : undefined;
127
+ const configured = existing && existing.source !== 'none'
128
+ ? cfg.llm.provider
129
+ // Z.ai's coding-plan credential is stored in its dedicated cache/env, not llm.apiKey.
130
+ : cfg.llm.provider === 'glm' && zaiCodingPlanAvailable() ? 'glm' : undefined;
108
131
  let detected: DetectedProvider[] = [];
132
+ // This read-only scan is unconditional, even with an incomplete existing config;
133
+ // provider availability must not depend on the setup marker/config being absent.
109
134
  try { detected = await (deps.detectProviders ?? detectProviders)(); }
110
135
  catch { /* Detection is advisory; a TTY can still choose. */ }
111
136
  const subscriptions = detected.filter((d) => d.available && (d.auth === 'oauth' || d.auth === 'agent-cli'));
@@ -113,14 +138,6 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
113
138
  const observe = (event: 'detected' | 'chosen' | 'ready' | 'needs-llm', inputs: number) =>
114
139
  debug.log('onboarding.first-run', event, { providers, inputs });
115
140
  observe('detected', 0);
116
- // An incomplete onboarding marker does not mean the user's LLM is unconfigured.
117
- // Keep an already usable provider, key and model rather than replacing them with a detected subscription.
118
- const existing = cfg.llm.provider !== 'auto'
119
- ? resolveProviderCredential({ provider: cfg.llm.provider, rotation: cfg.llm.rotation,
120
- baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey })
121
- : undefined;
122
- const configured = existing && existing.source !== 'none'
123
- ? cfg.llm.provider : undefined;
124
141
  // claude-code is detected but has no subscription path in elanous: mapping it to the 'anthropic'
125
142
  // API-key provider would save a provider whose first call fails for a subscription-only user.
126
143
  const usable = SUBSCRIPTION_PRIORITY.filter((name) => providers.includes(name));
@@ -134,6 +151,7 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
134
151
  let provider: LLMProviderName | null | undefined = configured ?? (usable.length === 1 ? usable[0] : undefined);
135
152
  if (!configured && provider) print(detectionLine(provider));
136
153
  let inputs = 0;
154
+ let providerSetUpInPlace = false;
137
155
  if (!provider) {
138
156
  if (providers.length > 0) {
139
157
  print(detectionLine(usable.length === 0
@@ -144,23 +162,102 @@ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
144
162
  // FIRST-CHAT-NONTTY — bare `elanous` with no TTY gets the same one-line next step as the other entrances.
145
163
  return needsLlm(0, [unattendedNextStepLine()]);
146
164
  }
165
+ if (deps.setupWhenNoProvider && usable.length === 0) {
166
+ inputs = 1;
167
+ const setupResult = await deps.setupWhenNoProvider(cfg);
168
+ if (typeof setupResult === 'object' && setupResult !== null && setupResult.kind === 'needs-llm') {
169
+ return needsLlm(inputs);
170
+ }
171
+ provider = typeof setupResult === 'string' ? setupResult : null;
172
+ if (!provider) {
173
+ print('LLM 없이 첫 화면을 엽니다. LLM 기능은 사용할 수 없습니다. 다시 설정: `elanous setup keys` 또는 `elanous login openai-codex`.');
174
+ (deps.saveConfig ?? saveUserConfig)({ ...cfg, onboarding: { ...cfg.onboarding, ready: true } }, path);
175
+ observe('ready', inputs);
176
+ return { outcome: 'ready', inputs };
177
+ }
178
+ providerSetUpInPlace = true;
179
+ observe('chosen', inputs);
180
+ } else {
147
181
  inputs = 1;
148
182
  provider = await (deps.chooseProvider ?? chooseProvider)(usable);
149
183
  if (!provider) return { outcome: 'cancelled', inputs };
150
184
  observe('chosen', inputs);
185
+ }
151
186
  }
152
187
  const credential = inputs === 1 || provider !== cfg.llm.provider
153
- ? resolveProviderCredential({
188
+ ? await resolveProviderCredentialAsync({
154
189
  provider, rotation: cfg.llm.rotation,
155
190
  baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey,
156
- })
191
+ env: deps.env,
192
+ }, deps.getSecretAsync)
157
193
  : undefined;
158
- if (inputs === 1 && credential?.source === 'none') return needsLlm(inputs);
194
+ if (inputs === 1 && credential?.source === 'none'
195
+ && !(providerSetUpInPlace && provider === 'openai-codex')) {
196
+ if ((deps.isTTY ?? process.stdin.isTTY) !== true) return needsLlm(inputs);
197
+ try {
198
+ const results = await collectServiceKeys({
199
+ config: cfg,
200
+ promptSecret: deps.promptSecret ?? createSecretPrompt(),
201
+ print,
202
+ getSecret: deps.getSecretAsync,
203
+ setSecret: deps.setSecretAsync,
204
+ probe: deps.probeKey,
205
+ providers: [provider],
206
+ });
207
+ printKeySetupReport(results, print);
208
+ if (results.length === 0 || results.some((result) => result.status !== 'success')) return needsLlm(inputs);
209
+ // Probe the same lookup the runtime will use before marking first-run ready.
210
+ const secretId = providerEnvKey(provider);
211
+ let storedValue: string | undefined;
212
+ try {
213
+ storedValue = secretId
214
+ ? await (deps.getSecretAsync ?? getSecretAsync)(secretId)
215
+ : undefined;
216
+ } catch { /* keep the first-run state unready without exposing backend errors */ }
217
+ const storedCredential = resolveProviderCredential({
218
+ provider,
219
+ rotation: cfg.llm.rotation,
220
+ baseProvider: provider,
221
+ env: deps.env,
222
+ secretStoreApiKey: storedValue,
223
+ });
224
+ if (!storedValue?.trim() || storedCredential.source === 'none') return needsLlm(inputs, [text.keyStoredNotReady]);
225
+ // Only remove any legacy config key after the runtime can read its replacement.
226
+ // A failed SecretStore write/readback must leave the prior working config intact.
227
+ (deps.saveConfig ?? saveUserConfig)({
228
+ ...cfg,
229
+ llm: {
230
+ ...cfg.llm,
231
+ provider,
232
+ apiKey: undefined,
233
+ ...(provider !== cfg.llm.provider ? { baseUrl: undefined, model: undefined } : {}),
234
+ },
235
+ }, path);
236
+ (deps.saveConfig ?? saveUserConfig)({
237
+ ...cfg,
238
+ llm: {
239
+ ...cfg.llm,
240
+ provider,
241
+ apiKey: undefined,
242
+ ...(provider !== cfg.llm.provider ? { baseUrl: undefined, model: undefined } : {}),
243
+ },
244
+ onboarding: { ...cfg.onboarding, ready: true },
245
+ }, path);
246
+ observe('ready', inputs);
247
+ return { outcome: 'ready', provider, inputs };
248
+ } catch {
249
+ return needsLlm(inputs, [text.keySetupFailed]);
250
+ }
251
+ }
159
252
  (deps.saveConfig ?? saveUserConfig)({
160
253
  ...cfg,
161
254
  llm: { ...cfg.llm, provider,
162
- ...(provider !== cfg.llm.provider ? { apiKey: credential?.apiKey, baseUrl: credential?.baseUrl, model: undefined } : {}),
163
- ...(credential?.apiKey ? { apiKey: credential.apiKey } : {}),
255
+ ...(provider !== cfg.llm.provider ? {
256
+ apiKey: credential?.source === 'rotation' ? credential.apiKey : undefined,
257
+ baseUrl: credential?.baseUrl,
258
+ model: undefined,
259
+ } : {}),
260
+ ...(credential?.source === 'rotation' && credential.apiKey ? { apiKey: credential.apiKey } : {}),
164
261
  ...(credential?.baseUrl ? { baseUrl: credential.baseUrl } : {}) },
165
262
  onboarding: { ...cfg.onboarding, ready: true },
166
263
  }, path);
@@ -0,0 +1,103 @@
1
+ import { getProviderForConfig, type LLMProvider } from '../llm.js';
2
+ import { providerEnvKey, resolveProviderCredential } from '../llm/provider-credentials.js';
3
+ import { probeProvider } from '../llm/provider-probe.js';
4
+ import type { UserConfig } from '../user-config.js';
5
+ import { getSecretAsync, setSecretAsync } from '../nexus/config/secrets/index.js';
6
+
7
+ export const KEY_SETUP_SERVICES = [
8
+ { provider: 'anthropic', label: 'Anthropic' },
9
+ { provider: 'grok', label: 'Grok' },
10
+ { provider: 'gemini', label: 'Gemini' },
11
+ { provider: 'openrouter', label: 'OpenRouter' },
12
+ { provider: 'opengateway', label: 'OpenGateway' },
13
+ { provider: 'openai', label: 'OpenAI' },
14
+ ] as const;
15
+
16
+ type KeySetupService = (typeof KEY_SETUP_SERVICES)[number];
17
+ type KeyStatus = 'success' | 'failed' | 'skipped';
18
+
19
+ export interface KeySetupResult {
20
+ provider: string;
21
+ label: string;
22
+ status: KeyStatus;
23
+ }
24
+
25
+ export interface KeySetupDeps {
26
+ config: UserConfig;
27
+ promptSecret: (message: string) => Promise<string | undefined>;
28
+ print: (message: string) => void;
29
+ getSecret?: (id: string) => Promise<string | undefined>;
30
+ setSecret?: (id: string, value: string) => Promise<void>;
31
+ probe?: (provider: LLMProvider) => Promise<{ success: boolean }>;
32
+ providers?: readonly string[];
33
+ }
34
+
35
+ function importedKeys(value: string | undefined): Map<string, string> {
36
+ const keys = new Map<string, string>();
37
+ for (const line of value?.split(/\r?\n/) ?? []) {
38
+ const match = line.match(/^\s*(?:export\s+)?([A-Z][A-Z0-9_]*)\s*=\s*(.*?)\s*$/);
39
+ if (!match) continue;
40
+ const raw = match[2] ?? '';
41
+ const unquoted = (raw.startsWith('"') && raw.endsWith('"')) || (raw.startsWith("'") && raw.endsWith("'"))
42
+ ? raw.slice(1, -1) : raw;
43
+ if (unquoted) keys.set(match[1]!, unquoted);
44
+ }
45
+ return keys;
46
+ }
47
+
48
+ function serviceKey(service: KeySetupService): string | undefined {
49
+ return providerEnvKey(service.provider);
50
+ }
51
+
52
+ function serviceSelected(service: KeySetupService, providers: readonly string[] | undefined): boolean {
53
+ return providers === undefined || providers.includes(service.provider);
54
+ }
55
+
56
+ /** Collect API keys without rendering values, then probe each newly supplied key once. */
57
+ export async function collectServiceKeys(deps: KeySetupDeps): Promise<KeySetupResult[]> {
58
+ const getSecret = deps.getSecret ?? getSecretAsync;
59
+ const setSecret = deps.setSecret ?? setSecretAsync;
60
+ const probe = deps.probe ?? probeProvider;
61
+ const pasted = importedKeys(await deps.promptSecret('.env 형식 키를 붙여 넣고 빈 줄로 끝내세요 (건너뛰려면 Enter): '));
62
+ const results: KeySetupResult[] = [];
63
+ for (const service of KEY_SETUP_SERVICES) {
64
+ if (!serviceSelected(service, deps.providers)) continue;
65
+ const id = serviceKey(service);
66
+ if (!id) continue;
67
+ const existing = await getSecret(id);
68
+ const configured = resolveProviderCredential({
69
+ provider: service.provider,
70
+ rotation: deps.config.llm.rotation,
71
+ baseProvider: deps.config.llm.provider,
72
+ baseApiKey: deps.config.llm.apiKey,
73
+ }).source !== 'none';
74
+ if (existing || configured) {
75
+ results.push({ ...service, status: 'skipped' });
76
+ continue;
77
+ }
78
+ const value = pasted.get(id) ?? (await deps.promptSecret(`${service.label} 키 (${id}, 건너뛰려면 Enter): `))?.trim();
79
+ if (!value) {
80
+ results.push({ ...service, status: 'skipped' });
81
+ continue;
82
+ }
83
+ await setSecret(id, value);
84
+ let success = false;
85
+ try {
86
+ const provider = getProviderForConfig({
87
+ ...deps.config,
88
+ llm: { ...deps.config.llm, provider: service.provider as UserConfig['llm']['provider'], apiKey: value, model: undefined },
89
+ });
90
+ success = (await probe(provider)).success;
91
+ } catch { /* The status table deliberately keeps provider failures value-free. */ }
92
+ results.push({ ...service, status: success ? 'success' : 'failed' });
93
+ }
94
+ return results;
95
+ }
96
+
97
+ export function printKeySetupReport(results: readonly KeySetupResult[], print: (message: string) => void): void {
98
+ print('키 설정 결과');
99
+ for (const result of results) {
100
+ print(`${result.status === 'success' ? '✅' : result.status === 'failed' ? '❌' : '건너뜀'} ${result.label}`);
101
+ }
102
+ print('Telegram 봇 설정: https://t.me/BotFather');
103
+ }
@@ -0,0 +1,13 @@
1
+ export type MenuAnswer<T> =
2
+ | { kind: 'chosen'; provider: T }
3
+ | { kind: 'cancel' }
4
+ | { kind: 'miss' };
5
+
6
+ /** Parse a menu answer using the first-run chooser contract: blank cancels, only ASCII decimal indices select. */
7
+ export function parseMenuAnswer<T>(answer: string, choices: readonly T[]): MenuAnswer<T> {
8
+ const trimmed = answer.trim();
9
+ if (trimmed === '') return { kind: 'cancel' };
10
+ if (!/^[0-9]+$/.test(trimmed)) return { kind: 'miss' };
11
+ const provider = choices[Number(trimmed) - 1];
12
+ return provider !== undefined ? { kind: 'chosen', provider } : { kind: 'miss' };
13
+ }
@@ -0,0 +1,37 @@
1
+ import { createInterface } from 'node:readline';
2
+ import type { Readable, Writable } from 'node:stream';
3
+
4
+ /** Hidden one-line secret input, or a hidden multi-line .env paste terminated by a blank line. */
5
+ export function createSecretPrompt(input: Readable = process.stdin, output: Writable = process.stdout) {
6
+ return async (message: string): Promise<string | undefined> => {
7
+ const rl = createInterface({ input, output });
8
+ const writable = rl as unknown as { _writeToOutput?: (value: string) => void };
9
+ const original = writable._writeToOutput;
10
+ output.write(message);
11
+ writable._writeToOutput = () => {};
12
+ try {
13
+ if (!message.includes('.env')) return await new Promise((resolve) => rl.question('', resolve));
14
+ return await new Promise<string | undefined>((resolve) => {
15
+ const lines: string[] = [];
16
+ let settled = false;
17
+ const finish = (value: string | undefined) => {
18
+ if (settled) return;
19
+ settled = true;
20
+ resolve(value);
21
+ };
22
+ rl.on('line', (line) => {
23
+ if (line.length === 0) {
24
+ finish(lines.length > 0 ? lines.join('\n') : undefined);
25
+ return;
26
+ }
27
+ lines.push(line);
28
+ });
29
+ rl.on('close', () => finish(lines.length > 0 ? lines.join('\n') : undefined));
30
+ });
31
+ } finally {
32
+ writable._writeToOutput = original;
33
+ rl.close();
34
+ output.write('\n');
35
+ }
36
+ };
37
+ }
@@ -18,6 +18,65 @@ const VERSION = /^[0-9]+\.[0-9]+\.[0-9]+(?:[-+][a-zA-Z0-9.-]+)?$/;
18
18
  const SHA = /^[a-fA-F0-9]{40}$/;
19
19
  const HASH = /^[a-fA-F0-9]{64}$/;
20
20
 
21
+ /** Curated scene packages offered by the default install group. Service-key
22
+ * declarations live in each package manifest and use the shared key catalog. */
23
+ export const DEFAULT_PLUGIN_GROUP = [
24
+ { id: 'demo-research', label: '리서치', requiredServiceKeys: [], optionalServiceKeys: ['exa', 'firecrawl', 'xai', 'tavily'], requiredPrerequisites: ['llm-provider'], optionalPrerequisites: [] },
25
+ { id: 'demo-linear-secretary', label: '리니어 비서', requiredServiceKeys: ['linear'], optionalServiceKeys: ['telegram', 'telegram-chat'], requiredPrerequisites: ['llm-provider'], optionalPrerequisites: [] },
26
+ { id: 'demo-absorption-briefing', label: '흡수 브리핑', requiredServiceKeys: [], optionalServiceKeys: ['exa', 'firecrawl', 'xai', 'telegram', 'telegram-chat', 'linear'], requiredPrerequisites: ['llm-provider'], optionalPrerequisites: [] },
27
+ { id: 'demo-browser-hand', label: '브라우저 손', requiredServiceKeys: [], optionalServiceKeys: ['linear'], requiredPrerequisites: ['llm-provider', 'aside'], optionalPrerequisites: [] },
28
+ { id: 'demo-video-briefing', label: '영상 브리핑', requiredServiceKeys: [], optionalServiceKeys: ['elevenlabs', 'telegram', 'telegram-chat'], requiredPrerequisites: ['llm-provider'], optionalPrerequisites: [] },
29
+ { id: 'demo-plugin-wizard', label: '플러그인 마법사', requiredServiceKeys: [], optionalServiceKeys: [], requiredPrerequisites: ['llm-provider'], optionalPrerequisites: ['claude-cli', 'github-cli'] },
30
+ ] as const;
31
+
32
+ export type DefaultPluginStatus = {
33
+ id: typeof DEFAULT_PLUGIN_GROUP[number]['id'];
34
+ label: string;
35
+ status: 'ready' | 'key-needed';
36
+ missingRequiredKeys: string[];
37
+ missingPrerequisites: string[];
38
+ optionalKeysMissing: string[];
39
+ optionalPrerequisitesMissing: string[];
40
+ };
41
+
42
+ /** Public readiness identifiers only; callers must never pass secret values. */
43
+ export function defaultPluginStatuses(input: {
44
+ readyServiceKeyIds?: readonly string[];
45
+ satisfiedPrerequisites?: readonly string[];
46
+ } = {}): DefaultPluginStatus[] {
47
+ const readyKeys = new Set(input.readyServiceKeyIds ?? []);
48
+ const satisfied = new Set(input.satisfiedPrerequisites ?? []);
49
+ return DEFAULT_PLUGIN_GROUP.map(plugin => {
50
+ const missingRequiredKeys = plugin.requiredServiceKeys.filter(id => !readyKeys.has(id));
51
+ const missingPrerequisites = plugin.requiredPrerequisites.filter(id => !satisfied.has(id));
52
+ return {
53
+ id: plugin.id,
54
+ label: plugin.label,
55
+ status: missingRequiredKeys.length || missingPrerequisites.length ? 'key-needed' : 'ready',
56
+ missingRequiredKeys,
57
+ missingPrerequisites,
58
+ optionalKeysMissing: plugin.optionalServiceKeys.filter(id => !readyKeys.has(id)),
59
+ optionalPrerequisitesMissing: plugin.optionalPrerequisites.filter(id => !satisfied.has(id)),
60
+ };
61
+ });
62
+ }
63
+
64
+ const DEFAULT_PLUGIN_ROOT = resolve(import.meta.dir, '../../../plugins');
65
+
66
+ /** Install the curated default group from this distribution's packaged plugin assets. */
67
+ export async function installDefaultPluginGroup(opts: InstallOptions = {}): Promise<InstalledPlugin[]> {
68
+ const root = resolve(opts.root ?? elanousStateRoot());
69
+ const installed: InstalledPlugin[] = [];
70
+ for (const plugin of DEFAULT_PLUGIN_GROUP) {
71
+ const packageRoot = join(DEFAULT_PLUGIN_ROOT, plugin.id);
72
+ const manifest = loadPluginManifestFromDir(packageRoot, { id: plugin.id }).manifest;
73
+ const existing = listInstalledPlugins(root).find(item =>
74
+ item.market === 'local' && item.name === manifest.id && item.version === manifest.version);
75
+ installed.push(existing ?? await installPlugin(packageRoot, { ...opts, root }));
76
+ }
77
+ return installed;
78
+ }
79
+
21
80
  export type InstallEvent =
22
81
  | { event: 'resolve'; plugin: string; version: string; sha256: string | null }
23
82
  | { event: 'verify'; signature: 'ok' | 'missing' | 'bad'; scan: 'safe' | 'caution' | 'dangerous' }
@@ -44,6 +44,30 @@ export interface GuardVerdict { status: 'allow' | 'refuse' | 'unknown'; reasons:
44
44
  sameCellConflicts?: readonly { pr: number; branch: string | null; headSha: string; cardId: string | null; slice?: { slice: number; total: number } | null }[];
45
45
  sameCellReuse?: { number: number; branch: string; headSha: string; cellId: string; cardId: string; legacyBound?: true } }
46
46
 
47
+ export interface PrLineageField<T> {
48
+ status: 'observed' | 'unknown';
49
+ value: T | null;
50
+ evidence: string;
51
+ reason?: string;
52
+ }
53
+
54
+ /** First, read-only slice: report observed PR facts and leave every unmeasured close criterion unknown. */
55
+ export interface PrLineageObservation {
56
+ status: 'observed' | 'unknown';
57
+ pr: number;
58
+ observedAt: string;
59
+ currentHead: PrLineageField<string>;
60
+ supersedes: PrLineageField<number>;
61
+ sourceCard: PrLineageField<string>;
62
+ olderScopeCarriedForward: PrLineageField<boolean>;
63
+ newerProtected: PrLineageField<boolean>;
64
+ cellStatus: PrLineageField<string>;
65
+ owner: PrLineageField<string>;
66
+ mergeSubstitution: PrLineageField<boolean>;
67
+ closeEligible: false;
68
+ reason?: string;
69
+ }
70
+
47
71
  const SEATS = ['OP', 'TC', 'MK', 'UX'] as const;
48
72
  const DEFAULT_SEAT_CAP = 30;
49
73
  const DRAFT_STALE_MS = 2 * 24 * 60 * 60 * 1000;
@@ -554,3 +578,109 @@ export function recordGuardUnmeasured(input: { seat: Seat | null; reason: string
554
578
  return { count: 0, blocked: true, reason };
555
579
  }
556
580
  }
581
+
582
+ const LINEAGE_READ_FIELDS = 'number,headRefOid,body';
583
+ const LINEAGE_NOT_MEASURED = '첫 PR lineage 조각의 관측 범위 밖이라 아직 판정하지 않음';
584
+
585
+ function lineageUnknown<T>(reason: string, evidence: string): PrLineageField<T> {
586
+ return { status: 'unknown', value: null, evidence, reason };
587
+ }
588
+
589
+ function lineageUnmeasured<T>(): PrLineageField<T> {
590
+ return lineageUnknown<T>(LINEAGE_NOT_MEASURED, '이 필드는 조회하지 않음');
591
+ }
592
+
593
+ /**
594
+ * Read only the PR head and explicit `Supersedes: #N` marker. This deliberately
595
+ * does not infer whether the PR is safe to close; later lineage fields remain unknown.
596
+ */
597
+ export function observePrLineage(input: {
598
+ pr: number;
599
+ run?: PrToolCommand;
600
+ cwd?: string;
601
+ now?: () => Date;
602
+ }): PrLineageObservation {
603
+ const observedAt = (input.now ?? (() => new Date()))().toISOString();
604
+ const readEvidence = `gh pr view #${input.pr} --json ${LINEAGE_READ_FIELDS}`;
605
+ const unknownObservation = (reason: string, currentHead = lineageUnknown<string>(reason, readEvidence),
606
+ supersedes = lineageUnknown<number>(reason, readEvidence)): PrLineageObservation => ({
607
+ status: 'unknown', pr: input.pr, observedAt, currentHead, supersedes,
608
+ sourceCard: lineageUnmeasured<string>(),
609
+ olderScopeCarriedForward: lineageUnmeasured<boolean>(),
610
+ newerProtected: lineageUnmeasured<boolean>(),
611
+ cellStatus: lineageUnmeasured<string>(),
612
+ owner: lineageUnmeasured<string>(),
613
+ mergeSubstitution: lineageUnmeasured<boolean>(),
614
+ closeEligible: false,
615
+ reason,
616
+ });
617
+
618
+ if (!Number.isSafeInteger(input.pr) || input.pr < 1) return unknownObservation('PR 번호는 1 이상의 정수여야 함');
619
+ const run = input.run ?? ((command: string, args: readonly string[], options?: { cwd?: string }): PrToolCommandResult => {
620
+ try {
621
+ const r = spawnSync(command, [...args], {
622
+ encoding: 'utf8', timeout: 120_000, maxBuffer: 16 * 1024 * 1024,
623
+ ...(options?.cwd ? { cwd: options.cwd } : {}),
624
+ });
625
+ return {
626
+ ok: r.status === 0 && !r.error,
627
+ out: (r.stdout ?? '').trim(),
628
+ err: [(r.stderr ?? '').trim(), r.error?.message ?? ''].filter(Boolean).join('\n'),
629
+ };
630
+ } catch (error) {
631
+ return { ok: false, out: '', err: error instanceof Error ? error.message : String(error) };
632
+ }
633
+ });
634
+ const result = run('gh', ['pr', 'view', String(input.pr), '--json', LINEAGE_READ_FIELDS], { cwd: input.cwd });
635
+ if (!result.ok) return unknownObservation(`PR 읽기 실패: ${result.err?.trim() || '명령 실패'}`);
636
+
637
+ let value: unknown;
638
+ try { value = JSON.parse(result.out); }
639
+ catch { return unknownObservation('PR 읽기 결과가 JSON이 아님'); }
640
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return unknownObservation('PR 읽기 결과가 객체가 아님');
641
+ const pr = value as Record<string, unknown>;
642
+ if (pr.number !== input.pr) return unknownObservation('응답 PR 번호가 요청한 번호와 다름');
643
+
644
+ const head = typeof pr.headRefOid === 'string' && pr.headRefOid.trim() !== ''
645
+ ? { status: 'observed' as const, value: pr.headRefOid.trim(), evidence: `${readEvidence}: headRefOid` }
646
+ : lineageUnknown<string>('headRefOid가 응답에 없어 현재 head를 확인할 수 없음', `${readEvidence}: headRefOid 누락`);
647
+
648
+ const bodyWasRead = Object.hasOwn(pr, 'body') && (typeof pr.body === 'string' || pr.body === null);
649
+ let supersedes: PrLineageField<number>;
650
+ if (!bodyWasRead) {
651
+ supersedes = lineageUnknown<number>('body가 응답에 없어 Supersedes 관계를 확인할 수 없음', `${readEvidence}: body 누락`);
652
+ } else {
653
+ const lines = (typeof pr.body === 'string' ? pr.body : '').split(/\r?\n/);
654
+ const markers = lines.filter(line => /^\s*Supersedes\s*:/i.test(line));
655
+ if (markers.length === 0) {
656
+ supersedes = { status: 'observed', value: null, evidence: `${readEvidence}: body에서 명시적 Supersedes 줄 0개` };
657
+ } else if (markers.length !== 1) {
658
+ supersedes = lineageUnknown<number>('Supersedes 표지가 둘 이상이라 관계가 모호함', `${readEvidence}: Supersedes 줄 ${markers.length}개`);
659
+ } else {
660
+ const match = /^\s*Supersedes:\s*#([1-9]\d*)\s*$/i.exec(markers[0]!);
661
+ const number = match ? Number(match[1]) : NaN;
662
+ if (!Number.isSafeInteger(number) || number < 1 || number === input.pr) {
663
+ supersedes = lineageUnknown<number>('Supersedes 줄이 유효한 다른 PR 번호가 아님', `${readEvidence}: Supersedes 형식 오류`);
664
+ } else {
665
+ supersedes = { status: 'observed', value: number, evidence: `${readEvidence}: body의 명시적 줄 “Supersedes: #${number}”` };
666
+ }
667
+ }
668
+ }
669
+
670
+ const status = head.status === 'observed' && supersedes.status === 'observed' ? 'observed' : 'unknown';
671
+ return {
672
+ status,
673
+ pr: input.pr,
674
+ observedAt,
675
+ currentHead: head,
676
+ supersedes,
677
+ sourceCard: lineageUnmeasured<string>(),
678
+ olderScopeCarriedForward: lineageUnmeasured<boolean>(),
679
+ newerProtected: lineageUnmeasured<boolean>(),
680
+ cellStatus: lineageUnmeasured<string>(),
681
+ owner: lineageUnmeasured<string>(),
682
+ mergeSubstitution: lineageUnmeasured<boolean>(),
683
+ closeEligible: false,
684
+ ...(status === 'unknown' ? { reason: '일부 PR 사실을 읽지 못함' } : {}),
685
+ };
686
+ }
@@ -559,10 +559,25 @@ export class PreviewTerminal {
559
559
 
560
560
  /** 자식 stdin 으로 바이트 전송(응답 채널·public write·마우스 공유). registry 모드면 handle.write,
561
561
  * 아니면 dup-fd(기본 경로 무접촉). */
562
- private writeToChild(data: string): void {
563
- if (this.registryHandle) { try { this.registryHandle.write(data); } catch { /* pty closing */ } return; }
564
- if (!this.alive || this.dupFd < 0) return;
565
- try { fs.writeSync(this.dupFd, data); } catch { /* pty closing */ }
562
+ private writeToChild(data: string): boolean {
563
+ if (this.registryHandle) {
564
+ try {
565
+ if (!this.registryHandle.canWrite()) return false;
566
+ this.registryHandle.write(data);
567
+ return true;
568
+ } catch { return false; }
569
+ }
570
+ if (!this.alive || this.dupFd < 0) return false;
571
+ try {
572
+ const bytes = Buffer.from(data, 'utf8');
573
+ let offset = 0;
574
+ while (offset < bytes.length) {
575
+ const written = fs.writeSync(this.dupFd, bytes, offset, bytes.length - offset);
576
+ if (written <= 0) return false;
577
+ offset += written;
578
+ }
579
+ return true;
580
+ } catch { return false; }
566
581
  }
567
582
 
568
583
  private scheduleUpdate(): void {
@@ -606,9 +621,9 @@ export class PreviewTerminal {
606
621
  return () => { this.rawOscTaps.delete(cb); };
607
622
  }
608
623
 
609
- /** Send raw bytes to the PTY (stdin from the child's perspective). */
610
- write(bytes: string): void {
611
- this.writeToChild(bytes);
624
+ /** Send raw bytes to the PTY and report whether its input handle accepted them. */
625
+ write(bytes: string): boolean {
626
+ return this.writeToChild(bytes);
612
627
  }
613
628
 
614
629
  /** Notify the PTY + emulator of new pane dimensions. Called on