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
@@ -43,6 +43,157 @@ export interface OverlayParseResult {
43
43
  readonly errors: readonly GraphParseIssue[];
44
44
  }
45
45
 
46
+ /** Injected ARG promotion evidence used by the graph-promote rehearsal.
47
+ * This input is deliberately separate from the production run ledger: a fixture
48
+ * can exercise the decision path, but its output is always labelled mock-only. */
49
+ export interface ArgPromotionEvidenceEvent {
50
+ readonly runId: string;
51
+ readonly timestamp: string;
52
+ readonly trigger: string;
53
+ readonly phase: 'adaptation' | 'baseline' | 'shadow';
54
+ readonly landed?: boolean;
55
+ readonly shadowAccepted?: boolean;
56
+ }
57
+
58
+ export interface ArgPromotionCandidate {
59
+ readonly overlayId: string;
60
+ readonly target: string;
61
+ readonly appliesWhen: string;
62
+ readonly patch: readonly OverlayPatchOp[];
63
+ }
64
+
65
+ export interface ArgPromotionEvaluation {
66
+ readonly mockOnly: true;
67
+ readonly verdict: 'eligible-for-human-pr' | 'held';
68
+ readonly blockers: readonly string[];
69
+ readonly metrics: {
70
+ readonly trigger: string;
71
+ readonly adaptationRuns: number;
72
+ readonly adaptationLandingRate: number | null;
73
+ readonly baselineRuns: number;
74
+ readonly baselineLandingRate: number | null;
75
+ readonly landingDelta: number | null;
76
+ readonly adaptationWindowDays: number | null;
77
+ readonly shadowObservations: number;
78
+ readonly shadowWindowDays: number | null;
79
+ };
80
+ readonly proposal?: {
81
+ readonly action: 'proposal-only';
82
+ readonly promoted_from: readonly string[];
83
+ readonly evidence: Readonly<Record<string, unknown>>;
84
+ readonly overlay: {
85
+ readonly overlay_id: string;
86
+ readonly target: string;
87
+ readonly stage: 'launch';
88
+ readonly applies_when: string;
89
+ readonly patch: readonly OverlayPatchOp[];
90
+ };
91
+ readonly rollback: 'open a human-reviewed demotion PR if the 7-day landing rate declines';
92
+ readonly patentReview: 'ELA-53 human review pending';
93
+ };
94
+ }
95
+
96
+ const PROMOTION_DAY_MS = 24 * 60 * 60 * 1000;
97
+
98
+ function promotionSpanDays(events: readonly ArgPromotionEvidenceEvent[]): number | null {
99
+ if (events.length < 2) return null;
100
+ const times = events.map((event) => Date.parse(event.timestamp));
101
+ if (times.some((time) => !Number.isFinite(time))) return null;
102
+ return (Math.max(...times) - Math.min(...times)) / PROMOTION_DAY_MS;
103
+ }
104
+
105
+ /** Evaluate injected evidence without reading a production ledger, writing an overlay, or opening a PR. */
106
+ export function evaluateArgPromotionFixture(input: {
107
+ readonly trigger: string;
108
+ readonly candidate: ArgPromotionCandidate;
109
+ readonly events: readonly ArgPromotionEvidenceEvent[];
110
+ }): ArgPromotionEvaluation {
111
+ if (input === null || typeof input !== 'object' || Array.isArray(input)) throw new Error('ARG promotion fixture root must be an object');
112
+ const { trigger, candidate, events } = input;
113
+ if (typeof trigger !== 'string' || typeof candidate !== 'object' || candidate === null || Array.isArray(candidate)
114
+ || typeof candidate.overlayId !== 'string' || typeof candidate.target !== 'string' || typeof candidate.appliesWhen !== 'string'
115
+ || !Array.isArray(candidate.patch) || !Array.isArray(events)) {
116
+ throw new Error('ARG promotion fixture requires trigger, candidate object, patch array and events array');
117
+ }
118
+ if (!trigger.trim() || !candidate.overlayId.trim() || !candidate.target.trim() || !candidate.appliesWhen.trim()) {
119
+ throw new Error('ARG promotion fixture requires trigger, overlayId, target and appliesWhen');
120
+ }
121
+ if (candidate.patch.length === 0) throw new Error('ARG promotion candidate patch must not be empty');
122
+ for (const operation of candidate.patch) {
123
+ if (operation === null || typeof operation !== 'object' || !['add', 'replace', 'remove'].includes(operation.op)
124
+ || typeof operation.path !== 'string' || !operation.path.startsWith('/')
125
+ || (operation.op !== 'remove' && !('value' in operation))) {
126
+ throw new Error('ARG promotion candidate contains an invalid JSON Patch operation');
127
+ }
128
+ }
129
+ const runIds = new Set<string>();
130
+ for (const rawEvent of events) {
131
+ if (rawEvent === null || typeof rawEvent !== 'object' || Array.isArray(rawEvent)) throw new Error('ARG promotion fixture contains a non-object event');
132
+ const event = rawEvent as ArgPromotionEvidenceEvent;
133
+ if (typeof event.runId !== 'string' || !event.runId.trim() || typeof event.timestamp !== 'string'
134
+ || !Number.isFinite(Date.parse(event.timestamp)) || typeof event.trigger !== 'string' || !event.trigger.trim()
135
+ || !['adaptation', 'baseline', 'shadow'].includes(event.phase)) {
136
+ throw new Error('ARG promotion fixture contains an invalid event');
137
+ }
138
+ if (runIds.has(event.runId)) throw new Error(`ARG promotion fixture repeats runId ${event.runId}`);
139
+ runIds.add(event.runId);
140
+ if ((event.phase === 'adaptation' || event.phase === 'baseline') && typeof event.landed !== 'boolean') {
141
+ throw new Error(`ARG promotion ${event.phase} event requires landed`);
142
+ }
143
+ if (event.phase === 'shadow' && typeof event.shadowAccepted !== 'boolean') {
144
+ throw new Error('ARG promotion shadow event requires shadowAccepted');
145
+ }
146
+ }
147
+
148
+ const matching = events.filter((event) => event.trigger === trigger);
149
+ const adaptations = matching.filter((event) => event.phase === 'adaptation');
150
+ const baseline = matching.filter((event) => event.phase === 'baseline');
151
+ const shadow = matching.filter((event) => event.phase === 'shadow');
152
+ const rate = (rows: readonly ArgPromotionEvidenceEvent[]): number | null => rows.length === 0
153
+ ? null : rows.filter((event) => event.landed === true).length / rows.length;
154
+ const adaptationLandingRate = rate(adaptations);
155
+ const baselineLandingRate = rate(baseline);
156
+ const landingDelta = adaptationLandingRate === null || baselineLandingRate === null
157
+ ? null : adaptationLandingRate - baselineLandingRate;
158
+ const adaptationSpanDays = promotionSpanDays(adaptations);
159
+ const baselineSpanDays = promotionSpanDays(baseline);
160
+ const adaptationWindowDays = adaptationSpanDays === null || baselineSpanDays === null
161
+ ? null : Math.min(adaptationSpanDays, baselineSpanDays);
162
+ const shadowWindowDays = promotionSpanDays(shadow);
163
+ const evidenceEnd = Math.max(...[...adaptations, ...baseline].map((event) => Date.parse(event.timestamp)));
164
+ const shadowStart = Math.min(...shadow.map((event) => Date.parse(event.timestamp)));
165
+ const blockers: string[] = [];
166
+ if (adaptations.length < 5) blockers.push('same-trigger-adaptations-below-5');
167
+ if (baseline.length === 0) blockers.push('same-trigger-baseline-missing');
168
+ if (landingDelta === null || landingDelta < 0.2 - Number.EPSILON) blockers.push('landing-improvement-below-20pp');
169
+ if (adaptationWindowDays === null || adaptationWindowDays < 7) blockers.push('adaptation-evidence-window-under-7-days');
170
+ if (shadow.length < 2 || shadowWindowDays === null || shadowWindowDays < 7) blockers.push('shadow-window-under-7-days');
171
+ if (!Number.isFinite(evidenceEnd) || !Number.isFinite(shadowStart) || shadowStart < evidenceEnd) blockers.push('shadow-starts-before-evidence-window');
172
+ if (shadow.some((event) => event.shadowAccepted !== true)) blockers.push('shadow-evaluation-declined');
173
+
174
+ const metrics = { trigger, adaptationRuns: adaptations.length, adaptationLandingRate,
175
+ baselineRuns: baseline.length, baselineLandingRate, landingDelta, adaptationWindowDays,
176
+ shadowObservations: shadow.length, shadowWindowDays };
177
+ if (blockers.length > 0) return { mockOnly: true, verdict: 'held', blockers, metrics };
178
+ const promotedFrom = adaptations.map((event) => event.runId).sort();
179
+ return {
180
+ mockOnly: true, verdict: 'eligible-for-human-pr', blockers, metrics,
181
+ proposal: {
182
+ action: 'proposal-only', promoted_from: promotedFrom,
183
+ evidence: {
184
+ source: 'injected-mock-fixture', trigger, adaptationRuns: promotedFrom,
185
+ baselineRuns: baseline.map((event) => event.runId).sort(),
186
+ adaptationLandingRate, baselineLandingRate, landingDelta,
187
+ adaptationWindowDays, shadowRunIds: shadow.map((event) => event.runId).sort(), shadowWindowDays,
188
+ },
189
+ overlay: { overlay_id: candidate.overlayId, target: candidate.target, stage: 'launch',
190
+ applies_when: candidate.appliesWhen, patch: candidate.patch },
191
+ rollback: 'open a human-reviewed demotion PR if the 7-day landing rate declines',
192
+ patentReview: 'ELA-53 human review pending',
193
+ },
194
+ };
195
+ }
196
+
46
197
  const STAGES = new Set<OverlayStage>(['launch', 'runtime', 'heal']);
47
198
  const OPS = new Set(['add', 'replace', 'remove']);
48
199
 
@@ -167,8 +318,10 @@ export function applyGraphOverlays(
167
318
  rejections.push({ kind: 'unknown-target', overlayId: overlay.overlayId, target: overlay.target });
168
319
  continue;
169
320
  }
321
+ const beforeNodes = new Map(next.nodes.map((node) => [node.nodeId, node]));
170
322
  const beforeVisits = new Map(next.nodes.map((node) => [node.nodeId, node.maxVisits]));
171
- const beforeRoutes = edgeMapOf(next);
323
+ const beforeRoutes = graphRouteMap(next);
324
+ const beforeEdgeMap = edgeMapOf(next);
172
325
  for (const op of overlay.patch) {
173
326
  const resolved = resolvePointer(next, op.path);
174
327
  if (!resolved) { rejections.push({ kind: 'bad-pointer', overlayId: overlay.overlayId, path: op.path }); continue; }
@@ -190,15 +343,27 @@ export function applyGraphOverlays(
190
343
  if (op.op === 'remove') delete bag[key]; else bag[key] = op.value;
191
344
  } else rejections.push({ kind: 'bad-pointer', overlayId: overlay.overlayId, path: op.path });
192
345
  }
346
+ for (const node of next.nodes) {
347
+ if (beforeNodes.has(node.nodeId)) continue;
348
+ patches.push({ overlayId: overlay.overlayId, field: 'node-added', node: node.nodeId, kind: node.kind, maxVisits: node.maxVisits });
349
+ }
350
+ const afterRoutes = graphRouteMap(next);
351
+ for (const [key, route] of afterRoutes) {
352
+ const before = beforeRoutes.get(key);
353
+ if (before && before.to !== route.to) {
354
+ patches.push({ overlayId: overlay.overlayId, field: 'edge-rerouted', from: route.from, outcome: route.outcome, was: before.to, to: route.to });
355
+ }
356
+ }
193
357
  for (const node of next.nodes) {
194
358
  const before = beforeVisits.get(node.nodeId);
195
359
  if (before !== undefined && before !== node.maxVisits) {
196
360
  patches.push({ overlayId: overlay.overlayId, field: 'maxVisits', node: node.nodeId, before, after: node.maxVisits });
197
361
  }
198
362
  }
199
- const afterRoutes = edgeMapOf(next);
200
- for (const [node, before] of Object.entries(beforeRoutes)) {
201
- const after = afterRoutes[node] ?? [];
363
+ const afterEdgeMap = edgeMapOf(next);
364
+ for (const node of Object.keys(beforeEdgeMap)) {
365
+ const before = beforeEdgeMap[node] ?? [];
366
+ const after = afterEdgeMap[node] ?? [];
202
367
  if (before.length !== after.length || before.some((destination, index) => destination !== after[index])) {
203
368
  patches.push({ overlayId: overlay.overlayId, field: 'routes', node, before, after });
204
369
  }
@@ -246,6 +411,18 @@ export function applyGraphOverlays(
246
411
  return { ok: true, template: next, overlayIds: applied, patches };
247
412
  }
248
413
 
414
+ /** Keep outcome names while comparing route changes; the compiled edge map deliberately drops them. */
415
+ function graphRouteMap(template: GraphTemplateSpec): Map<string, { from: string; outcome: string; to: string }> {
416
+ const routes = new Map<string, { from: string; outcome: string; to: string }>();
417
+ for (const [index, edge] of template.edges.entries()) {
418
+ if (edge.to) routes.set(`${edge.from}\u0000direct\u0000${index}`, { from: edge.from, outcome: '', to: edge.to });
419
+ for (const [outcome, to] of Object.entries(edge.map ?? {})) {
420
+ routes.set(`${edge.from}\u0000${edge.on ?? 'outcome'}\u0000${outcome}`, { from: edge.from, outcome, to });
421
+ }
422
+ }
423
+ return routes;
424
+ }
425
+
249
426
  export interface OverlayLoadResult {
250
427
  readonly overlays: readonly GraphOverlaySpec[];
251
428
  readonly errors: readonly GraphParseIssue[];
@@ -26,7 +26,9 @@ export type OverlayRejection =
26
26
 
27
27
  export type OverlayPatch =
28
28
  | { readonly overlayId: string; readonly field: 'maxVisits'; readonly node: string; readonly before: number; readonly after: number }
29
- | { readonly overlayId: string; readonly field: 'routes'; readonly node: string; readonly before: readonly string[]; readonly after: readonly string[] };
29
+ | { readonly overlayId: string; readonly field: 'routes'; readonly node: string; readonly before: readonly string[]; readonly after: readonly string[] }
30
+ | { readonly overlayId: string; readonly field: 'node-added'; readonly node: string; readonly kind: string; readonly maxVisits: number }
31
+ | { readonly overlayId: string; readonly field: 'edge-rerouted'; readonly from: string; readonly outcome: string; readonly was: string; readonly to: string };
30
32
 
31
33
  export type OverlayResult =
32
34
  | { ok: true; template: GraphTemplate; patches: readonly OverlayPatch[] }
@@ -0,0 +1,107 @@
1
+ import { readFileSync, readdirSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { parse as parseYaml } from 'yaml';
5
+ import { evaluateOverlayCondition, parseOverlayCondition } from './graph-overlay-condition.js';
6
+ import type { GraphParseIssue } from './graph-yaml.js';
7
+
8
+ /** L1 profile: a deterministic state bundle and references to already-declared overlays. */
9
+ export interface GraphProfileSpec {
10
+ readonly profileId: string;
11
+ readonly appliesWhen: string;
12
+ readonly state: Readonly<Record<string, string | number | boolean>>;
13
+ readonly overlays: readonly string[];
14
+ }
15
+
16
+ export interface GraphProfileParseResult {
17
+ readonly profile?: GraphProfileSpec;
18
+ readonly errors: readonly GraphParseIssue[];
19
+ }
20
+
21
+ export function parseGraphProfileYaml(source: string, label = '<inline>'): GraphProfileParseResult {
22
+ let raw: unknown;
23
+ try { raw = parseYaml(source); }
24
+ catch (error) {
25
+ return { errors: [{ path: label, message: `YAML 파싱 실패: ${error instanceof Error ? error.message : String(error)}` }] };
26
+ }
27
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
28
+ return { errors: [{ path: label, message: 'YAML 최상위가 맵이 아니다' }] };
29
+ const doc = raw as Record<string, unknown>;
30
+ const errors: GraphParseIssue[] = [];
31
+ const profileId = typeof doc.profile_id === 'string' && /^[a-z][a-z0-9-]*$/.test(doc.profile_id) ? doc.profile_id : undefined;
32
+ if (!profileId) errors.push({ path: `${label}/profile_id`, message: 'profile_id는 소문자·숫자·하이픈 식별자여야 한다' });
33
+ const appliesWhen = typeof doc.applies_when === 'string' ? doc.applies_when : undefined;
34
+ if (!appliesWhen || !parseOverlayCondition(appliesWhen).ok)
35
+ errors.push({ path: `${label}/applies_when`, message: 'applies_when은 오버레이 조건 한 개(key op literal)여야 한다' });
36
+ const stateRaw = doc.state;
37
+ const state: Record<string, string | number | boolean> = {};
38
+ if (!stateRaw || typeof stateRaw !== 'object' || Array.isArray(stateRaw)) {
39
+ errors.push({ path: `${label}/state`, message: 'state는 스칼라 값만 담는 맵이어야 한다' });
40
+ } else {
41
+ for (const [key, value] of Object.entries(stateRaw as Record<string, unknown>)) {
42
+ if (!/^[a-z_][a-z0-9_]*$/i.test(key) || !['string', 'number', 'boolean'].includes(typeof value)
43
+ || (typeof value === 'number' && !Number.isFinite(value))) {
44
+ errors.push({ path: `${label}/state/${key}`, message: 'state 키와 값은 조건 파서가 다루는 키·문자열·유한수·불리언이어야 한다' });
45
+ } else state[key] = value as string | number | boolean;
46
+ }
47
+ }
48
+ const overlaysRaw = doc.overlays;
49
+ const overlays = Array.isArray(overlaysRaw) ? overlaysRaw.filter((value): value is string => typeof value === 'string') : undefined;
50
+ if (!Array.isArray(overlaysRaw) || !overlays || overlays.length !== overlaysRaw.length || new Set(overlays).size !== overlays.length)
51
+ errors.push({ path: `${label}/overlays`, message: 'overlays는 중복 없는 문자열 목록이어야 한다' });
52
+ if (errors.length > 0) return { errors };
53
+ return { profile: { profileId: profileId!, appliesWhen: appliesWhen!, state, overlays: overlays! }, errors };
54
+ }
55
+
56
+ export interface GraphProfileLoadResult {
57
+ readonly profiles: readonly GraphProfileSpec[];
58
+ readonly errors: readonly GraphParseIssue[];
59
+ readonly scannedFiles: number;
60
+ }
61
+
62
+ export function loadGraphProfiles(dir: string): GraphProfileLoadResult {
63
+ let files: string[];
64
+ try { files = readdirSync(dir).filter((file) => file.endsWith('.yaml') || file.endsWith('.yml')).sort(); }
65
+ catch (error) { return { profiles: [], errors: [{ path: dir, message: `프로필 디렉토리를 못 읽었다: ${error instanceof Error ? error.message : String(error)}` }], scannedFiles: 0 }; }
66
+ const errors: GraphParseIssue[] = [];
67
+ const profiles: GraphProfileSpec[] = [];
68
+ for (const file of files) {
69
+ try {
70
+ const parsed = parseGraphProfileYaml(readFileSync(join(dir, file), 'utf8'), file);
71
+ errors.push(...parsed.errors);
72
+ if (parsed.profile) profiles.push(parsed.profile);
73
+ } catch (error) { errors.push({ path: file, message: `읽기 실패: ${error instanceof Error ? error.message : String(error)}` }); }
74
+ }
75
+ const seen = new Set<string>();
76
+ for (const profile of profiles) {
77
+ if (seen.has(profile.profileId)) errors.push({ path: `${dir}/${profile.profileId}`, message: `profile_id '${profile.profileId}'가 중복이다` });
78
+ seen.add(profile.profileId);
79
+ }
80
+ return errors.length ? { profiles: [], errors, scannedFiles: files.length } : { profiles, errors, scannedFiles: files.length };
81
+ }
82
+
83
+ export function defaultProfilesDir(): string {
84
+ return join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'graphs', 'profiles');
85
+ }
86
+
87
+ export interface GraphProfileSelection {
88
+ readonly applied: readonly GraphProfileSpec[];
89
+ readonly errors: readonly string[];
90
+ readonly state: Readonly<Record<string, unknown>>;
91
+ }
92
+
93
+ /** Match all profiles deterministically; conflicting owned state rejects the whole profile set. */
94
+ export function selectGraphProfiles(
95
+ profiles: readonly GraphProfileSpec[],
96
+ state: Readonly<Record<string, unknown>>,
97
+ ): GraphProfileSelection {
98
+ const applied = profiles.filter((profile) => evaluateOverlayCondition(profile.appliesWhen, state).kind === 'applies');
99
+ const owned = new Map<string, string | number | boolean>();
100
+ const errors: string[] = [];
101
+ for (const profile of applied) for (const [key, value] of Object.entries(profile.state)) {
102
+ if (owned.has(key) && owned.get(key) !== value) errors.push(`profile state conflict: ${key} (${String(owned.get(key))} vs ${String(value)})`);
103
+ else owned.set(key, value);
104
+ }
105
+ if (errors.length) return { applied: [], errors, state };
106
+ return { applied, errors, state: { ...state, ...Object.fromEntries(owned) } };
107
+ }
@@ -37,6 +37,8 @@ export interface GraphNodeSpec {
37
37
  /** Entry selected by this call when a unit exposes more than one entry. */
38
38
  readonly callEntry?: string;
39
39
  readonly budget?: { readonly innerSteps: number };
40
+ /** ARG L upper bound inherited by this child graph call. */
41
+ readonly allowance?: { readonly innerSteps: number };
40
42
  /** L1: skip this optional node when a measured state condition holds. */
41
43
  readonly skipWhen?: string;
42
44
  }
@@ -48,6 +50,11 @@ export interface GraphEdgeSpec {
48
50
  /** 조건부 엣지 — 라우터가 읽는 «상태 키». ⛔ 값은 코드가 낸다(RFC §4.3 ⑵). */
49
51
  readonly on?: string;
50
52
  readonly map?: Readonly<Record<string, string>>;
53
+ /** Explicit fan-out destinations keyed by outcome. Each selected branch runs concurrently and joins at `join`. */
54
+ readonly branches?: Readonly<Record<string, readonly string[]>>;
55
+ readonly join?: string;
56
+ /** Failed warning branches remain visible in the join output but do not fail the barrier. */
57
+ readonly warningBranches?: readonly string[];
51
58
  /** 심이 «주입 안 됐을 때» 내려가는 순서. `requires` 는 그 심 이름들. */
52
59
  readonly fallback?: readonly { readonly node: string; readonly requires: readonly string[]; readonly observed?: number }[];
53
60
  readonly observed?: number;
@@ -65,6 +72,8 @@ export interface GraphTemplateSpec {
65
72
  /** 문서 전용 변경이면 gate 노드를 건너뛸 수 있다는 템플릿 정책. */
66
73
  readonly docsOnlyGateSkip?: boolean;
67
74
  readonly state?: readonly string[];
75
+ /** ARG L upper bound for this graph's total executed steps. */
76
+ readonly allowance?: { readonly innerSteps: number };
68
77
  /** ⭐ 런 계약(선택) — 이 그래프가 «기본으로» 요구하는 실행 칸 등. 발사 인자가 덮는다(graph-run-contract.ts). */
69
78
  readonly runContract?: GraphRunContractSpec;
70
79
  readonly unit?: { readonly inputs: readonly string[]; readonly outputs: readonly string[]; readonly exits: readonly string[]; readonly entries?: readonly string[] };
@@ -148,6 +157,14 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
148
157
 
149
158
  const terminalNodes = asArray(doc.terminal_nodes).filter((v): v is string => typeof v === 'string');
150
159
  if (terminalNodes.length === 0) errors.push({ path: `${label}/terminal_nodes`, message: 'terminal_nodes 가 비었다 — 끝날 수 없는 그래프다' });
160
+ let allowance: GraphTemplateSpec['allowance'];
161
+ if (doc.allowance !== undefined) {
162
+ const value = doc.allowance as Record<string, unknown> | undefined;
163
+ if (!value || typeof value !== 'object' || Array.isArray(value) || !Number.isSafeInteger(value.inner_steps) ||
164
+ (value.inner_steps as number) < 1 || Object.keys(value).some(key => key !== 'inner_steps'))
165
+ errors.push({ path: `${label}/allowance/inner_steps`, message: 'inner_steps 는 1 이상의 안전한 정수여야 한다' });
166
+ else allowance = { innerSteps: value.inner_steps as number };
167
+ }
151
168
 
152
169
  const journeyStages = doc.journey_stages;
153
170
  if (journeyStages !== undefined && (!Array.isArray(journeyStages) || journeyStages.length === 0
@@ -202,21 +219,28 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
202
219
  : undefined;
203
220
  // A subgraph node becomes a unit call only when it names `call:`; without it the node keeps the
204
221
  // pre-unit meaning (catalog role / recipe node), so existing declarations stay valid.
205
- if (kind === 'subgraph' && (n.call !== undefined || n.budget !== undefined || n.call_entry !== undefined)) {
222
+ if (kind === 'subgraph' && (n.call !== undefined || n.budget !== undefined || n.allowance !== undefined || n.call_entry !== undefined)) {
206
223
  if (typeof n.call !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]*@(?:\^?[1-9]\d*)$/.test(n.call))
207
224
  errors.push({ path: `${at}/call`, message: 'call 은 id@정수판 또는 id@^주판이어야 한다' });
208
225
  const budget = n.budget as Record<string, unknown> | undefined;
209
226
  if (!budget || typeof budget !== 'object' || Array.isArray(budget) ||
210
227
  !Number.isSafeInteger(budget.inner_steps) || (budget.inner_steps as number) < 1 || Object.keys(budget).some(key => key !== 'inner_steps'))
211
228
  errors.push({ path: `${at}/budget/inner_steps`, message: 'inner_steps 는 1 이상의 안전한 정수여야 한다' });
229
+ if (n.allowance !== undefined) {
230
+ const childAllowance = n.allowance as Record<string, unknown> | undefined;
231
+ if (!childAllowance || typeof childAllowance !== 'object' || Array.isArray(childAllowance) ||
232
+ !Number.isSafeInteger(childAllowance.inner_steps) || (childAllowance.inner_steps as number) < 1 ||
233
+ Object.keys(childAllowance).some(key => key !== 'inner_steps'))
234
+ errors.push({ path: `${at}/allowance/inner_steps`, message: 'inner_steps 는 1 이상의 안전한 정수여야 한다' });
235
+ }
212
236
  if (!contractRaw || !Array.isArray(contractRaw.inputs) || !contractRaw.inputs.every(v => typeof v === 'string') ||
213
237
  !Array.isArray(contractRaw.outputs) || !contractRaw.outputs.every(v => typeof v === 'string'))
214
238
  errors.push({ path: `${at}/contract`, message: 'subgraph 에는 inputs·outputs 계약이 필요하다' });
215
239
  if (recipe !== 'none') errors.push({ path: `${at}/recipe`, message: 'subgraph 는 recipe 를 실행하지 않는다' });
216
240
  if (n.call_entry !== undefined && (typeof n.call_entry !== 'string' || !n.call_entry.trim()))
217
241
  errors.push({ path: `${at}/call_entry`, message: 'call_entry 는 비어 있지 않은 노드 id 여야 한다' });
218
- } else if (kind !== 'subgraph' && (n.call !== undefined || n.budget !== undefined || n.call_entry !== undefined)) {
219
- errors.push({ path: at, message: 'call·call_entry·budget 은 subgraph 전용이다' });
242
+ } else if (kind !== 'subgraph' && (n.call !== undefined || n.budget !== undefined || n.allowance !== undefined || n.call_entry !== undefined)) {
243
+ errors.push({ path: at, message: 'call·call_entry·budget·allowance 은 subgraph 전용이다' });
220
244
  }
221
245
  // ⛔ 계약이 없으면 「이 노드가 무엇을 할 수 있나」를 답할 수 없다 — 경고로 남긴다(거절은 오버레이 쪽).
222
246
  if (contract === undefined) warnings.push({ path: `${at}/contract`, message: '계약(inputs·tools·outputs)이 없다 — 권한을 코드에서만 알 수 있다' });
@@ -235,6 +259,9 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
235
259
  ...(kind === 'subgraph' && n.budget && typeof n.budget === 'object' && !Array.isArray(n.budget) &&
236
260
  typeof (n.budget as Record<string, unknown>).inner_steps === 'number'
237
261
  ? { budget: { innerSteps: (n.budget as { inner_steps: number }).inner_steps } } : {}),
262
+ ...(kind === 'subgraph' && n.allowance && typeof n.allowance === 'object' && !Array.isArray(n.allowance) &&
263
+ typeof (n.allowance as Record<string, unknown>).inner_steps === 'number'
264
+ ? { allowance: { innerSteps: (n.allowance as { inner_steps: number }).inner_steps } } : {}),
238
265
  ...(typeof n.skip_when === 'string' ? { skipWhen: n.skip_when } : {}),
239
266
  });
240
267
  }
@@ -251,14 +278,19 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
251
278
  if (!known.has(from)) { errors.push({ path: `${at}/from`, message: `'${from}' 은 선언된 노드가 아니다` }); continue; }
252
279
  const hasTo = typeof e.to === 'string';
253
280
  const hasMap = e.map !== null && typeof e.map === 'object';
281
+ const hasBranches = e.branches !== null && typeof e.branches === 'object' && !Array.isArray(e.branches);
254
282
  if (e.when !== undefined && (typeof e.when !== 'string' || !parseOverlayCondition(e.when).ok))
255
283
  errors.push({ path: `${at}/when`, message: 'when 은 오버레이 조건 한 개(key op literal)여야 한다' });
256
284
  if (e.when !== undefined && (L1_PROTECTED_ROUTE_NODES.has(from) || nodes.some(node => node.nodeId === from && node.kind === 'gate') || terminalNodes.includes(from)))
257
285
  errors.push({ path: `${at}/when`, message: `'${from}' 의 필수 검증·착지 결과는 when 간선으로 덮을 수 없다` });
258
286
  if (e.when !== undefined && (!hasTo || hasMap || e.on !== undefined))
259
287
  errors.push({ path: `${at}/when`, message: 'when 은 to 간선에서만 쓴다' });
260
- if (hasTo === hasMap) {
261
- errors.push({ path: at, message: 'to 와 map 중 «정확히 하나»를 써야 한다' });
288
+ if (!hasTo && !hasMap && !hasBranches) {
289
+ errors.push({ path: at, message: 'to 또는 map/branches 조합을 써야 한다' });
290
+ continue;
291
+ }
292
+ if (hasTo && (hasMap || hasBranches)) {
293
+ errors.push({ path: at, message: 'to 는 map·branches 와 함께 쓸 수 없다' });
262
294
  continue;
263
295
  }
264
296
  const map: Record<string, string> = {};
@@ -270,6 +302,35 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
270
302
  }
271
303
  if (typeof e.on !== 'string') errors.push({ path: `${at}/on`, message: 'map 을 쓰면 on(라우터가 읽는 상태 키)이 필요하다' });
272
304
  }
305
+ let branches: Record<string, readonly string[]> | undefined;
306
+ let warningBranches: readonly string[] | undefined;
307
+ if (hasBranches) {
308
+ branches = {};
309
+ for (const [outcome, destinations] of Object.entries(e.branches as Record<string, unknown>)) {
310
+ if (!Array.isArray(destinations) || destinations.length < 2 || !destinations.every((value) => typeof value === 'string')) {
311
+ errors.push({ path: `${at}/branches/${outcome}`, message: 'branches 목적지는 두 개 이상의 노드 id 목록이어야 한다' });
312
+ continue;
313
+ }
314
+ if (new Set(destinations).size !== destinations.length)
315
+ errors.push({ path: `${at}/branches/${outcome}`, message: 'branches 목적지는 중복될 수 없다' });
316
+ for (const [index, destination] of destinations.entries()) {
317
+ if (!known.has(destination)) errors.push({ path: `${at}/branches/${outcome}/${index}`, message: `'${destination}' 는 선언된 노드가 아니다` });
318
+ }
319
+ branches[outcome] = destinations as string[];
320
+ }
321
+ if (typeof e.on !== 'string' || typeof e.join !== 'string' || !known.has(e.join))
322
+ errors.push({ path: at, message: 'branches 에는 on 과 선언된 join 노드가 필요하다' });
323
+ if (e.fallback !== undefined || e.when !== undefined) errors.push({ path: at, message: 'branches 는 fallback·when 과 함께 쓸 수 없다' });
324
+ if (hasMap && Object.keys(map).some((outcome) => Object.hasOwn(e.branches as object, outcome)))
325
+ errors.push({ path: `${at}/branches`, message: 'map 과 branches 의 outcome 키는 겹칠 수 없다' });
326
+ if (e.warning_branches !== undefined) {
327
+ if (!Array.isArray(e.warning_branches) || e.warning_branches.some((branch) => typeof branch !== 'string' || !branch.trim()) ||
328
+ new Set(e.warning_branches).size !== e.warning_branches.length ||
329
+ e.warning_branches.some((branch) => !Object.values(branches!).some((destinations) => destinations.includes(branch as string)))) {
330
+ errors.push({ path: `${at}/warning_branches`, message: 'warning_branches 는 중복 없는 branches 목적지 목록이어야 한다' });
331
+ } else warningBranches = e.warning_branches as string[];
332
+ }
333
+ }
273
334
  if (hasTo && !known.has(e.to as string)) { errors.push({ path: `${at}/to`, message: `'${String(e.to)}' 는 선언된 노드가 아니다` }); continue; }
274
335
 
275
336
  const fallback = asArray(e.fallback).flatMap((f, fi) => {
@@ -287,6 +348,7 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
287
348
  from,
288
349
  ...(hasTo ? { to: e.to as string } : {}),
289
350
  ...(hasMap ? { on: String(e.on), map } : {}),
351
+ ...(branches ? { on: String(e.on), branches, join: String(e.join), ...(warningBranches ? { warningBranches } : {}) } : {}),
290
352
  ...(fallback.length > 0 ? { fallback } : {}),
291
353
  ...(typeof e.observed === 'number' ? { observed: e.observed } : {}),
292
354
  ...(typeof e.when === 'string' ? { when: e.when } : {}),
@@ -304,6 +366,25 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
304
366
  if (!edges.some(candidate => candidate.from === edge.from && candidate.when === undefined))
305
367
  errors.push({ path: `${label}/edges/${edge.from}/when`, message: 'when 간선에는 모호·미관측 때 탈 무조건 기본 간선이 필요하다' });
306
368
  }
369
+ const fanOutDestinations = new Map<string, string>();
370
+ const fanOutJoins = new Map<string, string>();
371
+ for (const edge of edges) {
372
+ if (!edge.branches || !edge.join) continue;
373
+ const sourceNode = nodes.find(node => node.nodeId === edge.from);
374
+ if (sourceNode && sourceNode.maxVisits !== 1) errors.push({ path: `${label}/edges/${edge.from}/branches`, message: 'fan-out 출발 노드는 재방문할 수 없어 max_visits: 1 이어야 한다' });
375
+ if (fanOutJoins.has(edge.join) && fanOutJoins.get(edge.join) !== edge.from) errors.push({ path: `${label}/edges/${edge.from}/join`, message: 'join 노드는 하나의 fan-out barrier만 소유할 수 있다' });
376
+ fanOutJoins.set(edge.join, edge.from);
377
+ if (edge.join === edge.from || Object.values(edge.branches).some((branches) => branches.includes(edge.join!)))
378
+ errors.push({ path: `${label}/edges/${edge.from}/join`, message: 'join 노드는 fan-out source나 branch 목적지일 수 없다' });
379
+ for (const branch of new Set(Object.values(edge.branches).flat())) {
380
+ if (fanOutDestinations.has(branch) && fanOutDestinations.get(branch) !== edge.from) errors.push({ path: `${label}/edges/${edge.from}/branches`, message: `branch '${branch}' 는 하나의 fan-out source 에서만 실행할 수 있다` });
381
+ fanOutDestinations.set(branch, edge.from);
382
+ if (edges.some(candidate => candidate.from === branch)) errors.push({ path: `${label}/edges/${edge.from}/branches`, message: `branch '${branch}' 는 단일 노드만 지원하며 후속 간선은 허용되지 않는다` });
383
+ }
384
+ const joinEdge = edges.find((candidate) => candidate.from === edge.join && candidate.on === 'outcome');
385
+ if (!joinEdge?.map || !Object.hasOwn(joinEdge.map, 'ok') || !Object.hasOwn(joinEdge.map, 'fail'))
386
+ errors.push({ path: `${label}/edges/${edge.join}`, message: 'fan-out join 은 ok·fail 출구를 모두 선언해야 한다' });
387
+ }
307
388
 
308
389
  if (entryNode !== undefined && !known.has(entryNode)) errors.push({ path: `${label}/entry_node`, message: `'${entryNode}' 는 선언된 노드가 아니다` });
309
390
  for (const t of terminalNodes) if (!known.has(t)) errors.push({ path: `${label}/terminal_nodes`, message: `'${t}' 는 선언된 노드가 아니다` });
@@ -358,6 +439,7 @@ export function parseGraphTemplateYaml(source: string, label = '<inline>'): Grap
358
439
  ...(loop ? { loop } : {}),
359
440
  ...(typeof doc.docs_only_gate_skip === 'boolean' ? { docsOnlyGateSkip: doc.docs_only_gate_skip } : {}),
360
441
  ...(Array.isArray(doc.state) ? { state: doc.state.filter((v): v is string => typeof v === 'string') } : {}),
442
+ ...(allowance ? { allowance } : {}),
361
443
  ...(runContract.spec ? { runContract: runContract.spec } : {}),
362
444
  },
363
445
  errors, warnings,
@@ -512,6 +594,13 @@ export function edgeMapOf(template: GraphTemplateSpec): Record<string, string[]>
512
594
  const push = (t: string) => { if (!targets.includes(t)) targets.push(t); };
513
595
  if (edge.to) push(edge.to);
514
596
  for (const t of Object.values(edge.map ?? {})) push(t);
597
+ for (const destinations of Object.values(edge.branches ?? {})) for (const destination of destinations) {
598
+ push(destination);
599
+ if (edge.join) {
600
+ const branchTargets = edges[destination] ?? (edges[destination] = []);
601
+ if (!branchTargets.includes(edge.join)) branchTargets.push(edge.join);
602
+ }
603
+ }
515
604
  for (const fb of edge.fallback ?? []) push(fb.node);
516
605
  }
517
606
  return edges;