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
@@ -120,6 +120,8 @@ export interface EnhanceOpts {
120
120
  groundedFacts?: readonly string[];
121
121
  /** Relevant prior-failure lessons for goal-authoring prompts only; never part of the original ask. */
122
122
  authoringLessons?: string;
123
+ /** Canonical reusable mock-device and event-injection inventory; reference only, not a completion gate. */
124
+ mockScenarioCatalog?: string;
123
125
  /** Clock seam for the first-token observation (ms epoch); defaults to `Date.now`. */
124
126
  now?: () => number;
125
127
  }
@@ -439,6 +441,14 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
439
441
  ...(opts.authoringLessons?.trim()
440
442
  ? ['', '## 지난 실패에서 배운 것', opts.authoringLessons.trim(), '위 교훈은 현재 ask의 대상 경로와 범위에 맞을 때만 적용하고, 맞지 않으면 무시하라.']
441
443
  : []),
444
+ ...(opts.mockScenarioCatalog?.trim()
445
+ ? [
446
+ '',
447
+ '## 재사용 가능한 목장치·사건 주입 카탈로그 (참고 자료 · 완료 조건이 아님)',
448
+ opts.mockScenarioCatalog.trim(),
449
+ '골의 완료 경계가 실물 점검만 요구하면 먼저 제약을 의심하라: 그 제약은 저작 문면의 세계와 구현의 세계에서 같은가? 카탈로그의 목장치나 사건 주입으로 같은 동작을 관찰할 수 있는가? 실제 외부 시스템 확인이 사용자의 의도인 경우에만 실물 점검을 유지하고, 목장치가 맞으면 해당 장치·입력·관측 신호를 제안하라.',
450
+ ]
451
+ : []),
442
452
  ].join('\n'),
443
453
  },
444
454
  ];
@@ -48,6 +48,8 @@ export type PtyControlPayload =
48
48
  export interface PtyControlRequestOptions {
49
49
  /** 요청자가 주장하는 쓰기 주체. `'agent'` 는 run-identity 일치를 요구한다(`resolveRemoteControlActor`). */
50
50
  readonly actor?: PtyWriteActor;
51
+ /** Bound child identity for an agent-originated control message (e.g. mission HandReply). */
52
+ readonly requesterRunId?: string;
51
53
  readonly timeoutMs?: number;
52
54
  /** 대상 PTY를 발견한 매니페스트 뿌리. 연합 조회는 이 DB에 제어 요청을 남겨 그 행의 owner가 처리하게 한다. */
53
55
  readonly manifestDbPath?: string;
@@ -467,7 +469,8 @@ export async function requestRemotePtyControl(id: string, action: PtyControlActi
467
469
  const now = Date.now();
468
470
  // ⭐ 요청자의 run anchor 를 요청에 실어 보낸다 — 인가는 **owner 가** 자기 PTY 의 run 과 대조해 내린다
469
471
  // (요청자 자기 신고를 그대로 믿지 않는다는 뜻이 아니라, 판정 지점이 자원 소유자라는 뜻).
470
- d.run(`INSERT INTO pty_control_requests (request_id, pty_id, action, payload_json, actor, requester_run_id, owner_pid, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [requestId, targetId, action, payload ? JSON.stringify(payload) : null, actor, getHarnessRunId(process.env), ownerPid, 'pending', now, now]);
472
+ const requesterRunId = actor === 'agent' ? (options.requesterRunId?.trim() || getHarnessRunId(process.env)) : getHarnessRunId(process.env);
473
+ d.run(`INSERT INTO pty_control_requests (request_id, pty_id, action, payload_json, actor, requester_run_id, owner_pid, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [requestId, targetId, action, payload ? JSON.stringify(payload) : null, actor, requesterRunId, ownerPid, 'pending', now, now]);
471
474
  // ⭐ 깊은 유휴 감속 중인 owner 를 즉시 깨운다 — 행을 넣은 «뒤» 표식을 남기므로 그 재읽기가 이 행을 본다.
472
475
  // 표식은 그 행의 `ownerPid` «별» 파일이다 — 같은 원장을 공유하는 다른 owner 가 가져가지 못한다.
473
476
  signalPtyControlWake(queuePath ?? ptyManifestDbPath(), ownerPid);
@@ -24,14 +24,32 @@
24
24
  * 장수 owner(데몬)는 PTY 를 계속 만든다. 훅만 믿으면 «한 번 새면 영영» 샌다. */
25
25
  const MAX_TRACKED_PTYS = 512;
26
26
 
27
- const writes = new Map<string, { count: number; lastAt: number; lastActor: string }>();
27
+ const writes = new Map<string, { count: number; lastAt: number; lastActor: string | null; accessMode?: 'read' | 'write' | 'auto' }>();
28
+
29
+ export function notePtyAccessMode(ptyId: string, accessMode: 'read' | 'write' | 'auto'): void {
30
+ const prev = writes.get(ptyId);
31
+ writes.delete(ptyId);
32
+ writes.set(ptyId, { count: prev?.count ?? 0, lastAt: prev?.lastAt ?? 0, lastActor: prev?.lastActor ?? null, accessMode });
33
+ while (writes.size > MAX_TRACKED_PTYS) {
34
+ const oldest = writes.keys().next();
35
+ if (oldest.done) break;
36
+ writes.delete(oldest.value);
37
+ }
38
+ }
39
+
40
+ export function ptyWriteControlState(ptyId: string): { accessMode: 'read' | 'write' | 'auto'; lastWriter: 'agent' | 'human' | null } | undefined {
41
+ const rec = writes.get(ptyId);
42
+ if (!rec?.accessMode) return undefined;
43
+ const lastWriter = rec.lastActor === 'agent' || rec.lastActor === 'human' ? rec.lastActor : null;
44
+ return { accessMode: rec.accessMode, lastWriter };
45
+ }
28
46
 
29
47
  /** 성공한 쓰기 1건을 기록한다. ⛔ 거부·실패는 세지 않는다(자식이 «본» 것만 세야 수가 뜻을 갖는다). */
30
48
  export function noteExternalWrite(ptyId: string, actor: string, now = Date.now()): void {
31
49
  const prev = writes.get(ptyId);
32
50
  // 재삽입으로 **삽입 순서를 갱신**한다 — 아래 축출이 「가장 오래 안 쓰인 것」을 버리게.
33
51
  writes.delete(ptyId);
34
- writes.set(ptyId, { count: (prev?.count ?? 0) + 1, lastAt: now, lastActor: actor });
52
+ writes.set(ptyId, { count: (prev?.count ?? 0) + 1, lastAt: now, lastActor: actor, ...(prev?.accessMode ? { accessMode: prev.accessMode } : {}) });
35
53
  while (writes.size > MAX_TRACKED_PTYS) {
36
54
  const oldest = writes.keys().next();
37
55
  if (oldest.done) break;
@@ -49,7 +67,7 @@ export function noteExternalWrite(ptyId: string, actor: string, now = Date.now()
49
67
  */
50
68
  export function externalWriteProvenance(ptyId: string, now = Date.now()): { externalWrites: number; externalWriteAgoMs: number; externalWriteActor: string } | undefined {
51
69
  const rec = writes.get(ptyId);
52
- if (!rec) return undefined;
70
+ if (!rec || rec.lastActor === null) return undefined;
53
71
  return { externalWrites: rec.count, externalWriteAgoMs: Math.max(0, now - rec.lastAt), externalWriteActor: rec.lastActor };
54
72
  }
55
73
 
@@ -30,7 +30,7 @@ import { resolveWriteDecision, resolveTakeover, type PtyWriteActor } from './pty
30
30
  import { addPtyManifestOutputBytes, upsertPtyManifest, updatePtyManifestSnapshot, updatePtyManifestNickname, markPtyManifestClosed, removePtyManifest, touchLivePtyManifest } from './pty-manifest.js';
31
31
  import { processPtyControlRequests } from './pty-control-ipc.js';
32
32
  import { tapPtyOutput, autoStopPtyRecording } from './pty-recording.js';
33
- import { forgetExternalWriteProvenance, noteExternalWrite } from './pty-write-provenance.js';
33
+ import { forgetExternalWriteProvenance, noteExternalWrite, notePtyAccessMode } from './pty-write-provenance.js';
34
34
  import { resolveRunIdentity } from '../harness/harness-space.js';
35
35
  import { addSelfDevRunParticipant, selfDevRunsDir } from '../self-dev/run-store.js';
36
36
  import { debug } from '../debug/log.js';
@@ -192,6 +192,8 @@ export interface PtyControlTarget {
192
192
  export interface PtyHandle extends PtyControlTarget {
193
193
  /** 고유 id — `<kind>_<hex>`. 같은 PTY 객체를 부르는 캐논 이름. */
194
194
  readonly id: string;
195
+ /** Actor of the last successful PTY write in this process; denied or failed writes do not update it. */
196
+ readonly lastWriteActor: PtyWriteActor | null;
195
197
  /**
196
198
  * 접근 모드(관찰 read / 인터랙션 write / 자율 auto). ⭐정책 매트릭스(§ 입력 중재):
197
199
  * - auto+locked = 보호된 자율(brain 소유·사람 write 불가). 위험 미션 무간섭.
@@ -508,10 +510,13 @@ export function startPty(opts: StartOpts): PtyHandle {
508
510
  } catch { term = null; }
509
511
 
510
512
  let nickname = opts.nickname;
513
+ let lastWriteActor: PtyWriteActor | null = null;
511
514
  let accessMode: PtyAccessMode = opts.accessMode ?? 'write';
512
515
  let transitionPolicy: PtyTransitionPolicy = opts.transitionPolicy ?? 'open';
516
+ notePtyAccessMode(id, accessMode);
513
517
  const handle: PtyHandle = {
514
518
  id,
519
+ get lastWriteActor() { return lastWriteActor; },
515
520
  kind: ptyKindOf(id),
516
521
  get nickname() { return nickname; },
517
522
  set nickname(v: string | undefined) { nickname = v; },
@@ -520,13 +525,14 @@ export function startPty(opts: StartOpts): PtyHandle {
520
525
  if (ptyManifestEnabled()) updatePtyManifestNickname(id, nickname, Date.now());
521
526
  },
522
527
  get accessMode() { return accessMode; },
523
- set accessMode(v: PtyAccessMode) { accessMode = v; },
528
+ set accessMode(v: PtyAccessMode) { accessMode = v; notePtyAccessMode(id, v); },
524
529
  get transitionPolicy() { return transitionPolicy; },
525
530
  set transitionPolicy(v: PtyTransitionPolicy) { transitionPolicy = v; },
526
531
  setAccessMode(mode: PtyAccessMode): boolean {
527
532
  // 정책 SSOT(canTransitionAccessMode): locked 면 다른 모드로 못 감(read+locked→write = write 불가).
528
533
  if (!canTransitionAccessMode(accessMode, mode, transitionPolicy)) return false;
529
534
  accessMode = mode;
535
+ notePtyAccessMode(id, mode);
530
536
  return true;
531
537
  },
532
538
  setTransitionPolicy(policy: PtyTransitionPolicy): void { transitionPolicy = policy; },
@@ -598,6 +604,7 @@ export function startPty(opts: StartOpts): PtyHandle {
598
604
  return;
599
605
  }
600
606
  adapter.write(chars);
607
+ lastWriteActor = actor;
601
608
  debug.log('pty.control', 'write', { ptyId: id, actor, mode: accessMode, bytes: chars.length });
602
609
  // ⭐⭐ 여기가 진짜 초크포인트다 — 허용 판정 뒤·바이트가 «실제로» 들어간 뒤. 모든 쓰기가
603
610
  // 이 자리로 모인다(크로스-프로세스 IPC · 같은 프로세스 감독 autoAssist · PtyShellSend).
@@ -0,0 +1,232 @@
1
+ import { createPublicKey, sign, verify, type KeyObject } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { debug } from '../debug/log.js';
6
+ import { getElanousConfigDir } from '../elanous-config-dir.js';
7
+ import type { ModelSpec, ProviderRegistration } from './types.js';
8
+
9
+ export const CATALOG_SERVER_URL = 'https://storage.googleapis.com/elanous-catalog/v1/catalog.json';
10
+ export const CATALOG_REFRESH_INTERVAL_MS = 24 * 60 * 60 * 1000;
11
+ export const CATALOG_STARTUP_TIMEOUT_MS = 2_000;
12
+
13
+ export interface SignedCatalogPayload {
14
+ catalogVersion: number;
15
+ generatedAt: string;
16
+ providers: ProviderRegistration[];
17
+ models: ModelSpec[];
18
+ }
19
+
20
+ export interface SignedCatalogDocument extends SignedCatalogPayload {
21
+ signature: string;
22
+ }
23
+
24
+ export interface VerifiedCatalog {
25
+ payload: SignedCatalogPayload;
26
+ stale: boolean;
27
+ }
28
+
29
+ function catalogVersionFromFile(path: string): number | undefined {
30
+ try {
31
+ const match = readFileSync(path, 'utf8').match(/^catalogVersion:\s*(\d+)\s*$/m);
32
+ const version = match ? Number(match[1]) : NaN;
33
+ return Number.isSafeInteger(version) && version >= 1 ? version : undefined;
34
+ } catch { return undefined; }
35
+ }
36
+
37
+ function bundledCatalogVersion(): number | undefined {
38
+ let current = dirname(fileURLToPath(import.meta.url));
39
+ for (let depth = 0; depth < 8; depth += 1) {
40
+ const candidate = join(current, 'catalog', 'meta', 'catalogVersion.yaml');
41
+ if (existsSync(candidate)) return catalogVersionFromFile(candidate);
42
+ current = dirname(current);
43
+ }
44
+ return undefined;
45
+ }
46
+
47
+ export function catalogCachePath(): string {
48
+ const override = process.env.ELANOUS_CATALOG_SERVER_CACHE?.trim();
49
+ if (override) return override;
50
+ return join(getElanousConfigDir(), 'catalog', 'cache.json');
51
+ }
52
+
53
+ function bundledPublicKeyPath(): string {
54
+ const override = process.env.ELANOUS_CATALOG_PUBLIC_KEY_FILE?.trim();
55
+ if (override) return override;
56
+ let current = dirname(fileURLToPath(import.meta.url));
57
+ for (let depth = 0; depth < 8; depth += 1) {
58
+ const candidate = join(current, 'catalog', 'signing', 'catalog-signing-public.pem');
59
+ if (existsSync(candidate)) return candidate;
60
+ current = dirname(current);
61
+ }
62
+ return join(dirname(fileURLToPath(import.meta.url)), '../../catalog/signing/catalog-signing-public.pem');
63
+ }
64
+
65
+ export function canonicalCatalogPayload(payload: SignedCatalogPayload): string {
66
+ return JSON.stringify({
67
+ catalogVersion: payload.catalogVersion,
68
+ generatedAt: payload.generatedAt,
69
+ providers: payload.providers,
70
+ models: payload.models,
71
+ });
72
+ }
73
+
74
+ export function signCatalogPayload(payload: SignedCatalogPayload, privateKey: string | Buffer | KeyObject): SignedCatalogDocument {
75
+ return { ...payload, signature: sign(null, Buffer.from(canonicalCatalogPayload(payload)), privateKey).toString('base64') };
76
+ }
77
+
78
+ function parsePayload(value: unknown): SignedCatalogPayload | null {
79
+ if (!value || typeof value !== 'object') return null;
80
+ const raw = value as Record<string, unknown>;
81
+ if (!Number.isSafeInteger(raw.catalogVersion) || (raw.catalogVersion as number) < 1) return null;
82
+ if (typeof raw.generatedAt !== 'string' || !Number.isFinite(Date.parse(raw.generatedAt))) return null;
83
+ if (!Array.isArray(raw.providers) || !Array.isArray(raw.models)) return null;
84
+ if (!raw.providers.every((p) => p && typeof p === 'object' && typeof (p as Record<string, unknown>).id === 'string')) return null;
85
+ if (!raw.models.every((m) => m && typeof m === 'object'
86
+ && typeof (m as Record<string, unknown>).id === 'string'
87
+ && typeof (m as Record<string, unknown>).provider === 'string')) return null;
88
+ return {
89
+ catalogVersion: raw.catalogVersion as number,
90
+ generatedAt: raw.generatedAt,
91
+ providers: raw.providers as ProviderRegistration[],
92
+ models: raw.models as ModelSpec[],
93
+ };
94
+ }
95
+
96
+ export function verifyCatalogDocument(
97
+ value: unknown,
98
+ publicKeyPem: string,
99
+ ): SignedCatalogPayload | null {
100
+ if (!value || typeof value !== 'object') return null;
101
+ const raw = value as Record<string, unknown>;
102
+ if (typeof raw.signature !== 'string') return null;
103
+ const payload = parsePayload(raw);
104
+ if (!payload) return null;
105
+ try {
106
+ const signature = Buffer.from(raw.signature, 'base64');
107
+ return verify(null, Buffer.from(canonicalCatalogPayload(payload)), createPublicKey(publicKeyPem), signature)
108
+ ? payload
109
+ : null;
110
+ } catch {
111
+ return null;
112
+ }
113
+ }
114
+
115
+ export function readVerifiedCatalogCache(opts: {
116
+ cachePath?: string;
117
+ publicKeyPem?: string;
118
+ now?: number;
119
+ } = {}): VerifiedCatalog | null {
120
+ const path = opts.cachePath ?? catalogCachePath();
121
+ try {
122
+ const key = opts.publicKeyPem ?? readFileSync(bundledPublicKeyPath(), 'utf8');
123
+ const payload = verifyCatalogDocument(JSON.parse(readFileSync(path, 'utf8')), key);
124
+ if (!payload) return null;
125
+ const age = Math.max(0, (opts.now ?? Date.now()) - Date.parse(payload.generatedAt));
126
+ const stale = age > CATALOG_REFRESH_INTERVAL_MS;
127
+ debug.log('registry.catalog', 'catalog.source', { source: 'server-cache', stale, catalogVersion: payload.catalogVersion });
128
+ if (stale) debug.log('registry.catalog', 'catalog.stale', { source: 'server-cache', stale: true, ageMs: age, catalogVersion: payload.catalogVersion }, { level: 'warn' });
129
+ return { payload, stale };
130
+ } catch {
131
+ return null;
132
+ }
133
+ }
134
+
135
+ export type RefreshCatalogResult =
136
+ | { ok: true; payload: SignedCatalogPayload }
137
+ | { ok: false; reason: 'key-unavailable' | 'fetch-failed' | 'http-error' | 'invalid-json' | 'signature-rejected' | 'version-rejected' | 'cache-write-failed' };
138
+
139
+ export async function refreshServerCatalog(opts: {
140
+ fetchImpl?: typeof fetch;
141
+ url?: string;
142
+ cachePath?: string;
143
+ publicKeyPem?: string;
144
+ timeoutMs?: number;
145
+ } = {}): Promise<RefreshCatalogResult> {
146
+ const fetchImpl = opts.fetchImpl ?? fetch;
147
+ const cachePath = opts.cachePath ?? catalogCachePath();
148
+ const timeoutMs = opts.timeoutMs ?? CATALOG_STARTUP_TIMEOUT_MS;
149
+ let key: string;
150
+ try {
151
+ key = opts.publicKeyPem ?? readFileSync(bundledPublicKeyPath(), 'utf8');
152
+ } catch (error) {
153
+ debug.log('registry.catalog', 'catalog.refresh-failed', { source: 'server', reason: 'key-unavailable', message: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
154
+ return { ok: false, reason: 'key-unavailable' };
155
+ }
156
+ const previous = readVerifiedCatalogCache({ cachePath, publicKeyPem: key });
157
+ let response: Response;
158
+ try {
159
+ response = await fetchImpl(opts.url ?? CATALOG_SERVER_URL, { signal: AbortSignal.timeout(timeoutMs) });
160
+ } catch (error) {
161
+ debug.log('registry.catalog', 'catalog.refresh-failed', { source: 'server', reason: 'fetch-failed', message: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
162
+ return { ok: false, reason: 'fetch-failed' };
163
+ }
164
+ if (!response.ok) return { ok: false, reason: 'http-error' };
165
+ let document: unknown;
166
+ try { document = await response.json(); }
167
+ catch { return { ok: false, reason: 'invalid-json' }; }
168
+ const payload = verifyCatalogDocument(document, key);
169
+ if (!payload) {
170
+ debug.log('registry.catalog', 'catalog.signature-rejected', { source: 'server', reason: 'invalid-signature-or-schema' }, { level: 'warn' });
171
+ return { ok: false, reason: 'signature-rejected' };
172
+ }
173
+ // A cold install has no signed server receipt yet, so the packaged catalog is its rollback floor.
174
+ const versionFloor = Math.max(previous?.payload.catalogVersion ?? 0,
175
+ bundledCatalogVersion() ?? 0);
176
+ if (payload.catalogVersion < versionFloor) {
177
+ debug.log('registry.catalog', 'catalog.version-rejected', {
178
+ source: 'server', reason: 'version-rollback', currentVersion: versionFloor, receivedVersion: payload.catalogVersion,
179
+ }, { level: 'warn' });
180
+ return { ok: false, reason: 'version-rejected' };
181
+ }
182
+ const signedDocument = document as SignedCatalogDocument;
183
+ try {
184
+ mkdirSync(dirname(cachePath), { recursive: true });
185
+ const temporary = `${cachePath}.${process.pid}.tmp`;
186
+ writeFileSync(temporary, `${JSON.stringify(signedDocument, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
187
+ renameSync(temporary, cachePath);
188
+ } catch (error) {
189
+ debug.log('registry.catalog', 'catalog.refresh-failed', { source: 'server', reason: 'cache-write-failed', message: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
190
+ return { ok: false, reason: 'cache-write-failed' };
191
+ }
192
+ const ageMs = Math.max(0, Date.now() - Date.parse(payload.generatedAt));
193
+ debug.log('registry.catalog', 'catalog.source', {
194
+ source: 'server', stale: ageMs > CATALOG_REFRESH_INTERVAL_MS, catalogVersion: payload.catalogVersion,
195
+ });
196
+ return { ok: true, payload };
197
+ }
198
+
199
+ let scheduledRefresh: Promise<void> | null = null;
200
+ let lastRefreshAttempt = 0;
201
+ let refreshTimer: ReturnType<typeof setTimeout> | null = null;
202
+
203
+ /** Kick remote refresh behind startup; the callback rebuilds the catalog only after a verified cache write. */
204
+ export function scheduleServerCatalogRefresh(onUpdated: () => void): void {
205
+ if (process.env.NODE_ENV === 'test') return;
206
+ if (scheduledRefresh || refreshTimer) return;
207
+ const now = Date.now();
208
+ const cached = readVerifiedCatalogCache();
209
+ const cacheAgeMs = cached ? Math.max(0, now - Date.parse(cached.payload.generatedAt)) : Number.POSITIVE_INFINITY;
210
+ const untilCacheStale = cached && !cached.stale ? Math.max(1_000, CATALOG_REFRESH_INTERVAL_MS - cacheAgeMs) : 0;
211
+ const untilRetry = Math.max(0, CATALOG_REFRESH_INTERVAL_MS - (now - lastRefreshAttempt));
212
+ const delay = Math.max(untilCacheStale, untilRetry);
213
+ if (delay > 0) {
214
+ refreshTimer = setTimeout(() => {
215
+ refreshTimer = null;
216
+ scheduleServerCatalogRefresh(onUpdated);
217
+ }, delay);
218
+ refreshTimer.unref?.();
219
+ return;
220
+ }
221
+ lastRefreshAttempt = now;
222
+ scheduledRefresh = refreshServerCatalog().then((result) => {
223
+ if (result.ok) onUpdated();
224
+ }).finally(() => {
225
+ scheduledRefresh = null;
226
+ refreshTimer = setTimeout(() => {
227
+ refreshTimer = null;
228
+ scheduleServerCatalogRefresh(onUpdated);
229
+ }, CATALOG_REFRESH_INTERVAL_MS);
230
+ refreshTimer.unref?.();
231
+ });
232
+ }
@@ -31,6 +31,8 @@ import type {
31
31
  } from './types.js';
32
32
  import { PROVIDER_CAPABILITIES_NONE } from './types.js';
33
33
  import { readDiscoveryCache, type DiscoverySnapshot } from './discovery/cache.js';
34
+ import { debug } from '../debug/log.js';
35
+ import { readVerifiedCatalogCache, scheduleServerCatalogRefresh } from './catalog-server.js';
34
36
 
35
37
  const HERE = dirname(fileURLToPath(import.meta.url));
36
38
 
@@ -85,6 +87,15 @@ function listYamlFiles(dir: string): string[] {
85
87
  .map((e) => join(dir, e));
86
88
  }
87
89
 
90
+ function readCatalogVersion(builtinDir: string): number {
91
+ const path = join(builtinDir, 'meta', 'catalogVersion.yaml');
92
+ if (!existsSync(path)) return 1;
93
+ const raw = safeReadYaml(path) as { catalogVersion?: unknown } | null;
94
+ return Number.isSafeInteger(raw?.catalogVersion) && (raw?.catalogVersion as number) >= 1
95
+ ? raw?.catalogVersion as number
96
+ : 1;
97
+ }
98
+
88
99
  // ── Provider parse + validate ─────────────────────────────────────────
89
100
 
90
101
  function parseProvider(raw: unknown, source: string): ProviderRegistration | null {
@@ -282,11 +293,13 @@ let cachedCatalog: Catalog | null = null;
282
293
 
283
294
  function buildCatalog(): Catalog {
284
295
  const builtinDir = resolveBuiltinCatalogDir();
296
+ const catalogVersion = readCatalogVersion(builtinDir);
285
297
  const globalDir = resolveGlobalCatalogDir();
286
298
 
287
299
  const providers = new Map<string, ProviderRegistration>();
288
300
  const models = new Map<string, ModelSpec>();
289
301
  const patterns = new Map<string, ModelPatternFallback>();
302
+ const sourceLayers = ['package'];
290
303
  let fileCount = 0;
291
304
 
292
305
  // --- builtin tier ---
@@ -326,12 +339,36 @@ function buildCatalog(): Catalog {
326
339
  }
327
340
  }
328
341
 
342
+ // --- signed server catalog; package YAML remains available if cache is absent/stale-invalid ---
343
+ // Keep isolated tests hermetic; an explicit cache path opts a test into the signed-server layer.
344
+ const serverCatalog = isolatedCatalogTestUniverse() && !process.env.ELANOUS_CATALOG_SERVER_CACHE?.trim()
345
+ ? null
346
+ : readVerifiedCatalogCache();
347
+ if (serverCatalog) {
348
+ sourceLayers.push('server-cache');
349
+ for (const raw of serverCatalog.payload.providers) {
350
+ const provider = parseProvider(raw, 'signed-server-catalog');
351
+ if (!provider) continue;
352
+ const base = providers.get(provider.id);
353
+ providers.set(provider.id, base ? mergeProviders(base, provider) : provider);
354
+ fileCount++;
355
+ }
356
+ for (const raw of serverCatalog.payload.models) {
357
+ const model = parseModel(raw, 'signed-server-catalog');
358
+ if (!model) continue;
359
+ models.set(model.id, model);
360
+ fileCount++;
361
+ }
362
+ }
363
+
329
364
  // --- global tier overlay ---
330
365
  const globalProviderDir = join(globalDir, 'providers');
366
+ let hasUserOverlay = false;
331
367
  for (const path of listYamlFiles(globalProviderDir)) {
332
368
  const raw = safeReadYaml(path);
333
369
  const overlay = parseProvider(raw, path);
334
370
  if (!overlay) continue;
371
+ hasUserOverlay = true;
335
372
  fileCount++;
336
373
  const base = providers.get(overlay.id);
337
374
  providers.set(overlay.id, base ? mergeProviders(base, overlay) : overlay);
@@ -359,6 +396,7 @@ function buildCatalog(): Catalog {
359
396
  }
360
397
  const model = parseModel(raw, path);
361
398
  if (model) {
399
+ hasUserOverlay = true;
362
400
  // global wins on dup id (RFC §6.4 — single-value fields replace).
363
401
  models.set(model.id, model);
364
402
  fileCount++;
@@ -370,9 +408,14 @@ function buildCatalog(): Catalog {
370
408
  // --- discovery fold (대표 2026-09-23 «파생한다») ---
371
409
  const folded = foldDiscoveredModels(providers, models, loadFoldSnapshot());
372
410
  for (const m of folded) models.set(m.id, m);
411
+ if (hasUserOverlay) sourceLayers.push('user');
412
+ if (folded.length > 0) sourceLayers.push('live-discovery');
413
+ debug.log('registry.catalog', 'catalog.source', {
414
+ source: 'merged', layers: sourceLayers, ...(serverCatalog ? { stale: serverCatalog.stale } : {}),
415
+ });
373
416
 
374
417
  return {
375
- catalogVersion: 1,
418
+ catalogVersion,
376
419
  providers,
377
420
  models,
378
421
  patterns,
@@ -435,6 +478,7 @@ export function foldDiscoveredModels(
435
478
  export function getCatalog(): Catalog {
436
479
  if (cachedCatalog) return cachedCatalog;
437
480
  cachedCatalog = buildCatalog();
481
+ scheduleServerCatalogRefresh(() => { cachedCatalog = buildCatalog(); });
438
482
  return cachedCatalog;
439
483
  }
440
484
 
@@ -196,8 +196,7 @@ export interface ModelPatternFallback {
196
196
  // ── Top-level catalog (loader output) ─────────────────────────────────
197
197
 
198
198
  export interface Catalog {
199
- /** Schema version — bumps when ProviderRegistration / ModelSpec
200
- * shape changes in a non-backwards-compat way. */
199
+ /** Catalog release version from catalog/meta/catalogVersion.yaml. */
201
200
  catalogVersion: number;
202
201
  /** Indexed by provider id. */
203
202
  providers: Map<string, ProviderRegistration>;
@@ -0,0 +1,83 @@
1
+ import { runRequirementFunnel, type FunnelCandidate, type FunnelOptions, type RequirementDecision } from '../intake-plane/requirement-funnel.js';
2
+ import type { ConsensusEngine, ConsensusRepresentative } from '../loops/consensus.js';
3
+ import { placeCell, type PlacementDeps, type PlacementDecision } from './placement.js';
4
+ import { parseRubric, rubricGrade, rubricScore } from './rubric.js';
5
+
6
+ export interface ProposalPlacementInput {
7
+ /** The current funnel inputs; ledger capture and adoption hooks are intentionally not accepted here. */
8
+ funnel: Omit<FunnelOptions, 'ledger' | 'adopt' | 'mode' | 'placement'>;
9
+ rubricCandidate: FunnelCandidate;
10
+ consensus: Pick<ConsensusEngine, 'show'>;
11
+ consensusProposalId: string;
12
+ placement: PlacementDeps;
13
+ }
14
+
15
+ export type ProposalPlacementPlan =
16
+ | { status: 'not-eligible'; reason: string; decision?: RequirementDecision }
17
+ | { status: 'awaiting-consensus'; consensusProposalId: string; decision: RequirementDecision }
18
+ | { status: 'planned'; consensus: { id: string; status: 'agreed'; proposedBy: ConsensusRepresentative; agreedBy: ConsensusRepresentative };
19
+ decision: RequirementDecision; rubric: { score: number; grade: NonNullable<FunnelCandidate['grade']> }; placement: PlacementDecision };
20
+
21
+ /**
22
+ * Safe first slice for the proposal→placement path. It accepts a pre-collected rubric candidate and an existing
23
+ * dual-root card; the requirement funnel and both placement calculations run in shadow/dry-run only. There is no
24
+ * ledger writer, live adopter, proposal creator, or operational scheduler in this seam.
25
+ */
26
+ export function planAgreedProposalPlacement(input: ProposalPlacementInput): ProposalPlacementPlan {
27
+ const rubric = input.rubricCandidate;
28
+ if (rubric.score === null || rubric.grade === null) return { status: 'not-eligible', reason: 'candidate has no explicit rubric' };
29
+ const funnel = runRequirementFunnel({
30
+ ...input.funnel,
31
+ mode: 'shadow',
32
+ placement: { ...input.placement, dryRun: true },
33
+ });
34
+ const decision = funnel.decisions.find(({ candidate }) => candidate.id === rubric.id);
35
+ if (!decision) return { status: 'not-eligible', reason: `funnel candidate not found: ${rubric.id}` };
36
+ if (decision.status !== 'would-adopt') return { status: 'not-eligible', reason: decision.reason ?? `funnel status: ${decision.status}`, decision };
37
+ const sourceRubric = parseRubric(decision.candidate.text);
38
+ const sourceTitle = decision.candidate.text.split(/\s+루브릭:/, 1)[0]!.trim().slice(0, 80);
39
+ if (sourceTitle !== rubric.title) return { status: 'not-eligible', reason: 'rubric candidate title does not match funnel source', decision };
40
+ if (!sourceRubric || rubric.score !== rubricScore(sourceRubric) || rubric.grade !== rubricGrade(rubricScore(sourceRubric)))
41
+ return { status: 'not-eligible', reason: 'rubric score or grade does not match funnel source', decision };
42
+
43
+ let proposal;
44
+ try { proposal = input.consensus.show(input.consensusProposalId); }
45
+ catch (error) {
46
+ if (error instanceof Error && error.message === `consensus proposal not found: ${input.consensusProposalId}`)
47
+ return { status: 'awaiting-consensus', consensusProposalId: input.consensusProposalId, decision };
48
+ throw error;
49
+ }
50
+ if (proposal.category !== 'period-budget' || proposal.factId !== decision.candidate.id
51
+ || proposal.title !== rubric.title || proposal.thresholds.length > 0 || proposal.status !== 'agreed')
52
+ return { status: 'awaiting-consensus', consensusProposalId: input.consensusProposalId, decision };
53
+ const agreement = proposal.reviews.find((review) => review.verdict === 'agree' && review.by !== proposal.proposedBy);
54
+ if (!agreement) return { status: 'awaiting-consensus', consensusProposalId: input.consensusProposalId, decision };
55
+
56
+ const candidate = decision.candidate;
57
+ if (candidate.priority !== 'P1' && candidate.priority !== 'P2')
58
+ return { status: 'not-eligible', reason: 'funnel candidate priority is missing or unsupported', decision };
59
+ if (!candidate.owner) return { status: 'not-eligible', reason: 'funnel candidate owner is missing', decision };
60
+ let placement: PlacementDecision;
61
+ try {
62
+ // The funnel checks urgency/capacity eligibility; this second dry run applies the rubric's deferral grade.
63
+ placement = placeCell({
64
+ id: candidate.id,
65
+ title: candidate.text,
66
+ owner: candidate.owner,
67
+ priority: candidate.priority,
68
+ predecessors: [],
69
+ grade: rubric.grade,
70
+ ...(candidate.deadlineVersion ? { deadlineVersion: candidate.deadlineVersion } : {}),
71
+ }, { ...input.placement, dryRun: true });
72
+ } catch (error) {
73
+ return { status: 'not-eligible', reason: error instanceof Error ? error.message : String(error), decision };
74
+ }
75
+
76
+ return {
77
+ status: 'planned',
78
+ consensus: { id: proposal.id, status: 'agreed', proposedBy: proposal.proposedBy, agreedBy: agreement.by },
79
+ decision,
80
+ rubric: { score: rubric.score, grade: rubric.grade },
81
+ placement,
82
+ };
83
+ }