elanous 0.2.42 → 0.2.43

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 (685) 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 → Om5xS9jpjSXJCeTNGYEi4}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{7a98bc80.fa935989e829f9c2.js → 0966f8a1.745fcd44f64a87ea.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{73d2eb0e.4966ad55293c801a.js → 0ad6802e.ae7afb63fdcb4491.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/114.2b90424d1a3ce84c.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1151-5c2bb8f002ca2dd6.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1200.6a37c202f9f17e9a.js +226 -0
  9. package/apps/pwa/out/_next/static/chunks/1261-a616d5728e02e624.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/1313-19f737e0222c4444.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1357.3bbef3976c37f94a.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1362-20adddfaf662b0fa.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/{3507.97e1977bc4d5fb0a.js → 1406.a1dc2ab6f8449374.js} +2 -2
  14. package/apps/pwa/out/_next/static/chunks/1737-9491fc6ab29b9ec6.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1803-4f91a8e7dcaf042c.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1961.a81b12872c3e93a9.js +23 -0
  17. package/apps/pwa/out/_next/static/chunks/{53c73f84.373b6160adfa89a4.js → 1970cf59.2d4d8ce5d6c81853.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{9211-330b6736a63d4cb3.js → 2073-ba274e00e4f9efb4.js} +1 -1
  20. package/apps/pwa/out/_next/static/chunks/{7411.9b4b8b747dc7b802.js → 2144.25b292396712196d.js} +2 -2
  21. package/apps/pwa/out/_next/static/chunks/2268-53861f339e0b65a2.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2312.0c8b61e22d3136d7.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6632.0eac1c554f8f2ef3.js → 2573.387a707f6f9d720c.js} +2 -2
  24. package/apps/pwa/out/_next/static/chunks/273.f156eee28f11af77.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2873.d2140e5a82546401.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/{1262.e804feb8fd1acb8c.js → 3072.01338851ca21a6f7.js} +2 -2
  27. package/apps/pwa/out/_next/static/chunks/3091.a5a4143dea33d197.js +90 -0
  28. package/apps/pwa/out/_next/static/chunks/{2456.b6de0e1c05f28843.js → 3095.dc44586a5f83b86d.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/{3207.a756c95e9ec8c3c8.js → 3113.d7472bbc27d580c7.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/3228-9650b6447b6fa288.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/3402.44b565b314f2263c.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/3557ac4a.c8931684475018ad.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{8505.fd803c6c33b54cc3.js → 360.ae9f9f4c33c395e8.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +286 -0
  35. package/apps/pwa/out/_next/static/chunks/{b450776b.3db34d8d965f82d3.js → 363bfab3.9623b9f89363541f.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/3694.e0099884345f0198.js +64 -0
  37. package/apps/pwa/out/_next/static/chunks/3744.54f87db52acfd1ab.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3903.3ef4656c67572764.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3935.16701e33f8982dc9.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3955.6922286237f2ac2b.js +24 -0
  41. package/apps/pwa/out/_next/static/chunks/3969.272ee7f9fd6c62e5.js +34 -0
  42. package/apps/pwa/out/_next/static/chunks/{8138.6c10b2a356d52fca.js → 4199.ce86b281fd0a60b7.js} +1 -1
  43. package/apps/pwa/out/_next/static/chunks/4311-6dd3144002cc0c2d.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4426-2b230fad00c88930.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{2690.0521c738b7749931.js → 4445.7990c76b3751a918.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4447-14c5161fa59166c7.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4856-b0b8075bba8c53f4.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4870-de370d65e73c0bb5.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4885-2c989165c4b29fad.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/{1945.7b54990d578c119b.js → 4894.fec2ca9e99caefa2.js} +1 -1
  51. package/apps/pwa/out/_next/static/chunks/5093.8f04b7f8cb899a95.js +94 -0
  52. package/apps/pwa/out/_next/static/chunks/5122-2bb177cebf89e19a.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/5154.5f56dc3902e3d275.js +36 -0
  54. package/apps/pwa/out/_next/static/chunks/529.64ff7257180b2ac9.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5394.5dabeb0c62293a28.js +93 -0
  56. package/apps/pwa/out/_next/static/chunks/5461.08bf2404ff38ec85.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5474-22e08a85583209b2.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/{9427.96aa912ddb5801e0.js → 5564.9e72532188f57586.js} +16 -16
  59. package/apps/pwa/out/_next/static/chunks/5567-265df39ed8fe9dcb.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5570-a94ae19811cb2046.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5574-b47c9ef2dceff1fd.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/{4043.6b91203436c9c86b.js → 5628.6ddb2d5ffba4ff4c.js} +4 -4
  63. package/apps/pwa/out/_next/static/chunks/{1319.b9b815ae0f181e06.js → 5730.43d7ccc09988e646.js} +1 -1
  64. package/apps/pwa/out/_next/static/chunks/{3482.a9ae9d2ad6a5bd97.js → 5789.2da35c258292e1e5.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5824.da9527b15a3221e5.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5866.366966af47fdde5d.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/{1487.2f67b79444062da6.js → 5930.8b4df3b46c32b05a.js} +1 -1
  68. package/apps/pwa/out/_next/static/chunks/5963-c4d8469c52a0828b.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/6001.ec4049ceb3c43418.js +27 -0
  70. package/apps/pwa/out/_next/static/chunks/6120-471f03db1e299c0c.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6175-41479e643aca1878.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6291.a2de4f9787637075.js +104 -0
  73. package/apps/pwa/out/_next/static/chunks/6400-6699907c3537436a.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/6428.1f4327d6ae5fdf9a.js +287 -0
  75. package/apps/pwa/out/_next/static/chunks/644.02cb026fa44bcd0a.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6466-6c87d60d3dd174fb.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{3347.f846266b5e5f3ede.js → 6540.c7bef57ad8f90a87.js} +3 -3
  78. package/apps/pwa/out/_next/static/chunks/6773.d4264665ab31bec0.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6822.3c789f1a8443e774.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/{8262.ddc03e06b733f184.js → 6944.309f4e3ea54d1537.js} +1 -1
  81. package/apps/pwa/out/_next/static/chunks/7261-8ff69d3b2ee671fd.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7266.084c6bbc70035140.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7271.5c0100e7320aa856.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7429-bf5731358c8f2f68.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7464.01f7a0ae1215fbe7.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7479.0fcad5f37eb64f0c.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/{4770.769c9cd9c7034eba.js → 7483.427a2fe2049e388d.js} +2 -2
  88. package/apps/pwa/out/_next/static/chunks/{1147-5196d19c222051b3.js → 7502-be74718178e13e56.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/7530.0889722b19572065.js +24 -0
  90. package/apps/pwa/out/_next/static/chunks/7645.5b2ee3ad45c55ea3.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7788.7d1c79f1a8e18946.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7900.096f455c7c1efc53.js +77 -0
  93. package/apps/pwa/out/_next/static/chunks/7910-6f139bcafd238b9f.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7966.f71c8958d1637548.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{8673-bab689a55f7e13b9.js → 8062-7cd0bcc7f01455ba.js} +3 -3
  96. package/apps/pwa/out/_next/static/chunks/8073.f6cf2f2c71aafbd0.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8201.190b94088980f430.js +74 -0
  98. package/apps/pwa/out/_next/static/chunks/8205.282ca4bb62d54a0a.js +62 -0
  99. package/apps/pwa/out/_next/static/chunks/8313-dfa1021bb58a46d6.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/837-81336ebaca8198a8.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8447.7963352ef5f71b76.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8574-868e8129525ef6d9.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8588.d1c6a2903727ce87.js +149 -0
  104. package/apps/pwa/out/_next/static/chunks/8637.90f92d5c8db4732c.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/868.6e953be05bcf6dca.js +41 -0
  106. package/apps/pwa/out/_next/static/chunks/8706-e1fe0309343a2273.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8749-06384cdfc4520add.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{9656-374232558fd528d0.js → 8861-cc1fa1c7b920fa8e.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{5440-4236de26c5ea5856.js → 8967-7dfebf710c9dec9d.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/{1063.2fb8a9dc55c731f2.js → 8986.8e2e4efbfa655c59.js} +1 -1
  111. package/apps/pwa/out/_next/static/chunks/8997-3c564dbb3b58b055.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/{4320.583cbab64db6be02.js → 923.2034d10ae91e9c20.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{1574.878c18ecc97b1bd4.js → 943.39ae5e82f4f1893f.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/9469.0500480de55fb205.js +32 -0
  116. package/apps/pwa/out/_next/static/chunks/9770.5f75bc6088b16109.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9810-2543267050e58b82.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9870.8419702475254745.js +8 -0
  119. package/apps/pwa/out/_next/static/chunks/9941-376d1b74d51b01a4.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9958.385434ab04241758.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/aa57532f.510551854ff239b1.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-deea1450b17cb8dc.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-70985b904f8650ef.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a2e15e33e56a4353.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-fc72ce2db12d6ca9.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-be03e41f9436ebd9.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-35a35999382da3f2.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-3ff5b1e6ca88b848.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-a65101300a0ee5c1.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-3aca5b6d67dba511.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-45b8ab0a71e61314.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-53046e282d4cda8e.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-17809e60e8354c17.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-fd2442d347bf5898.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-e9d720d6fc082e21.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-6b8b4267bab0a677.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-deea1450b17cb8dc.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-8bcf6233ac7c17af.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-7cc25591cfc2126f.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-053e871f35c9beba.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-eff819f0c2d5e084.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-4d7e9d8db5274a87.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-2b2d8f5aa5f69ad4.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-0b8f92c5062e68b1.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1bd9d0fdac2ced3d.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/{page-0f291d3c8fd55a3a.js → page-9ee28f7df07428ea.js} +1 -1
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-44b7a1ff468c6648.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-cbc6523711dc1b65.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-fdad47899c2695be.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-79a8b5fee4c20871.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-03e8ac9606aeaffb.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-4cd55c55ec287e2f.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-db17b4305404161e.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-30041d848350fd02.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c540da022dbf86b0.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9399efc538da057f.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ca2d09128c585ca4.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-0e2635aecd343038.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ef7f4399b6b7726e.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-deea1450b17cb8dc.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-caf530535b875468.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-eaa20c1543a5fd8e.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c541eb1b75120f61.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-ab5e213eda9479f4.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-0a815f34367b6db6.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-e858ba0ed9393b68.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-1638ee9dd6e0582f.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-4cf5a399109391f2.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b4396321238798ec.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-cb72bfd21006781a.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6135d0242afbc434.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a1dccf907eddb856.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/c7945435-b44d4dbe90ba0dcb.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{3d0154af.5331fec737ffe8c3.js → cb0f8df8.09a4a6be97e3fc5f.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/{e8543907.5b040a5f22a0b0e5.js → d96660fb.cbc21a2a88539dbb.js} +7 -7
  176. package/apps/pwa/out/_next/static/chunks/{50061469.0326382241ef3b2d.js → ea514caa.05a24f78d9dffe5f.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/fb7d20d5-6892502b6ee39ca6.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/framework-e8a911e19b1be41f.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-7022f418fabba021.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-e5f15df755756a1e.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-4525f91e36940c9b.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-140f0e519c085b0f.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-8f22ef63dcb865b1.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/examples/research-runtime-empty-terminal.yaml +28 -0
  285. package/graphs/profiles/local.yaml +5 -0
  286. package/graphs/profiles/pod.yaml +4 -0
  287. package/package.json +6 -2
  288. package/plugins/demo-absorption-briefing/plugin.json +18 -0
  289. package/plugins/demo-absorption-briefing/skills/demo-absorption-briefing/SKILL.md +8 -0
  290. package/plugins/demo-browser-hand/plugin.json +13 -0
  291. package/plugins/demo-browser-hand/skills/demo-browser-hand/SKILL.md +8 -0
  292. package/plugins/demo-linear-secretary/plugin.json +15 -0
  293. package/plugins/demo-linear-secretary/skills/demo-linear-secretary/SKILL.md +8 -0
  294. package/plugins/demo-plugin-wizard/plugin.json +11 -0
  295. package/plugins/demo-plugin-wizard/skills/demo-plugin-wizard/SKILL.md +8 -0
  296. package/plugins/demo-research/plugin.json +16 -0
  297. package/plugins/demo-research/skills/demo-research/SKILL.md +8 -0
  298. package/plugins/demo-video-briefing/plugin.json +15 -0
  299. package/plugins/demo-video-briefing/skills/demo-video-briefing/SKILL.md +8 -0
  300. package/scripts/build-signed-catalog.ts +48 -0
  301. package/scripts/ci-typecheck-main-delta.sh +88 -0
  302. package/scripts/codex-fallback-live-probe.ts +1 -1
  303. package/scripts/demo/demo1104-parallel-scenes.ts +301 -0
  304. package/scripts/demo/demo1104-stage.config.ts +21 -0
  305. package/scripts/demo/demo1104-stage.ts +316 -0
  306. package/scripts/goal-method-audit.ts +17 -1
  307. package/scripts/graph-units/land-enqueue.ts +90 -0
  308. package/scripts/hooks/codex-notify.sh +32 -0
  309. package/scripts/install.sh +10 -38
  310. package/scripts/landing-heal/land-plan.ts +57 -0
  311. package/scripts/release-loop/auto-approve-node.ts +1 -1
  312. package/scripts/release-loop/gate-autoheal-sim-evidence.ts +60 -0
  313. package/scripts/release-loop/gate-method.ts +139 -0
  314. package/scripts/release-loop/gate-node.ts +180 -20
  315. package/scripts/release-loop/gate-traffic-mode.ts +151 -3
  316. package/scripts/release-loop/node-verdict.ts +38 -25
  317. package/scripts/release-loop/preflight.ts +362 -8
  318. package/scripts/release-loop/unattended-release.ts +20 -9
  319. package/scripts/rhythm/daily.ts +36 -4
  320. package/scripts/rhythm/linear-progress-sync.ts +298 -0
  321. package/scripts/video-pipeline.ts +9 -1
  322. package/scripts/warm-pool-provider-config.ts +29 -6
  323. package/src/acp/agent-manager.ts +1 -0
  324. package/src/acp/codex-app-server-agent.ts +33 -0
  325. package/src/acp/codex-app-server-client.ts +153 -16
  326. package/src/acp/core-turn-bridge.ts +17 -12
  327. package/src/acp/event-router.ts +20 -1
  328. package/src/acp/server.ts +6 -0
  329. package/src/agent-mission/browser-roundtrip-coordinator.ts +85 -0
  330. package/src/agent-mission/claude-headless.ts +4 -1
  331. package/src/agent-mission/codex-exec.ts +105 -0
  332. package/src/agent-mission/driver.ts +192 -11
  333. package/src/agent-mission/grok-auth-status.ts +47 -0
  334. package/src/agent-mission/hand-hooks.ts +101 -0
  335. package/src/agent-mission/mission-cli.ts +56 -21
  336. package/src/agent-mission/mission-hand-reply.ts +118 -0
  337. package/src/agent-mission/mission-line.ts +180 -0
  338. package/src/agent-mission/mission-out.ts +256 -18
  339. package/src/agent-mission/tool-install.ts +122 -11
  340. package/src/agents/general-purpose.md +1 -1
  341. package/src/auto-research/research-turn.ts +95 -10
  342. package/src/autopilot/pr-manager.ts +31 -3
  343. package/src/boot/daemon-tools/self-implement.ts +3 -1
  344. package/src/boot/daemon-tools/web-search.ts +1 -2
  345. package/src/briefing/brief-items.ts +55 -11
  346. package/src/cli/agent-cli.ts +2 -1
  347. package/src/cli/catalog-cli.ts +31 -0
  348. package/src/cli/connector-cli.ts +16 -0
  349. package/src/cli/doctor-fix.ts +2 -2
  350. package/src/cli/intake-source-cli.ts +44 -8
  351. package/src/cli/msg-cli.ts +32 -3
  352. package/src/cli/pr-cli.ts +21 -1
  353. package/src/cli/pr-land-heavy-remote.ts +44 -6
  354. package/src/cli/pr-land-overlap-evidence.ts +13 -1
  355. package/src/cli/pr-land-pod-shadow-job.ts +143 -5
  356. package/src/cli/pr-land-pod-shadow.ts +9 -2
  357. package/src/cli/release-checklist-read-cli.ts +44 -16
  358. package/src/cli/release-cli.ts +23 -3
  359. package/src/cli/research-cli.ts +9 -0
  360. package/src/cli/setup-cli.ts +166 -6
  361. package/src/cli/setup-keys.ts +187 -0
  362. package/src/cli/task-plugin-wizard-host.ts +114 -0
  363. package/src/cli/tasks-cli.ts +54 -9
  364. package/src/cli/tui-test-cli.ts +186 -0
  365. package/src/config.ts +4 -2
  366. package/src/connectors/linear-daily-progress.ts +228 -0
  367. package/src/connectors/linear-projector.ts +34 -12
  368. package/src/connectors/linear.ts +151 -7
  369. package/src/core-turn/deep-turn-bloom.ts +67 -0
  370. package/src/core-turn/research-policy.ts +37 -0
  371. package/src/core-turn/run-core-turn.ts +320 -30
  372. package/src/core-turn/types.ts +2 -0
  373. package/src/dashboard/chat/acp-chat.ts +10 -0
  374. package/src/dashboard/classic-sidetab-mission-job.ts +103 -0
  375. package/src/dashboard/classic-sidetab-mission-pair.ts +81 -0
  376. package/src/dashboard/classic-sidetab-mission-trio.ts +219 -0
  377. package/src/dashboard/classic-sidetab-mission.ts +167 -5
  378. package/src/dashboard/index.ts +378 -13
  379. package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
  380. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +8 -0
  381. package/src/dashboard/mission-cli-consumer.ts +20 -8
  382. package/src/dashboard/plugin-wizard-runtime.ts +50 -0
  383. package/src/dashboard/plugin-wizard-tool.ts +55 -0
  384. package/src/dashboard/sidetab-runtime.ts +1 -1
  385. package/src/dashboard/terminal-popup-runtime.ts +6 -3
  386. package/src/decisions/linear-progress-summary.ts +78 -0
  387. package/src/decisions/linear-progress-sync.ts +152 -0
  388. package/src/domains/outbound-alert.ts +49 -11
  389. package/src/domains/telegram-kind-route.ts +16 -9
  390. package/src/graph-runner/arg-allowance.ts +13 -0
  391. package/src/graph-runner/graph-run-api.ts +3 -1
  392. package/src/graph-runner/runner.ts +85 -17
  393. package/src/graph-wizard/mission-compose.ts +407 -12
  394. package/src/harness/dispatch-backpressure.ts +54 -1
  395. package/src/harness/dispatch-shadow-compare.ts +74 -0
  396. package/src/harness/harness-cli-command.ts +11 -1
  397. package/src/harness/skill-exec.ts +21 -9
  398. package/src/harness/skill-select.ts +1 -1
  399. package/src/hooks/error-report-cloud.ts +101 -0
  400. package/src/hooks/receiver.ts +29 -2
  401. package/src/index.ts +127 -10
  402. package/src/intake-plane/actions.ts +354 -0
  403. package/src/intake-plane/adapters/telegram-ambient.ts +34 -18
  404. package/src/intake-plane/intake-sources.ts +78 -8
  405. package/src/intake-plane/items.ts +14 -4
  406. package/src/intake-plane/linear-mission-sync.ts +80 -0
  407. package/src/intake-plane/linear-secretary-runtime.ts +178 -0
  408. package/src/intake-plane/linear-wish.ts +227 -1
  409. package/src/life/life-cli.ts +168 -0
  410. package/src/life/life-kinds.ts +160 -0
  411. package/src/live-supply/budget-consumer.ts +78 -0
  412. package/src/live-supply/read.ts +3 -0
  413. package/src/live-supply/snapshot.ts +45 -0
  414. package/src/llm/provider-credentials.ts +8 -2
  415. package/src/llm.ts +2 -1
  416. package/src/maturity/feature-maturity.ts +3 -3
  417. package/src/msg/msg-sse-server.ts +3 -3
  418. package/src/msg/msg-store.ts +177 -19
  419. package/src/native-tool-catalog.ts +36 -2
  420. package/src/nexus/api/http-server.ts +37 -1
  421. package/src/nexus/api/mcp-public-allowlist.ts +2 -0
  422. package/src/nexus/index.ts +7 -2
  423. package/src/nexus/outbound/format.ts +9 -0
  424. package/src/nexus/outbound/router.ts +98 -13
  425. package/src/nexus/setup-status.ts +9 -0
  426. package/src/nexus/state/state.ts +3 -0
  427. package/src/oauth/codex-account-store.ts +20 -7
  428. package/src/oauth/codex-owner-mirror.ts +44 -0
  429. package/src/oauth/codex.ts +17 -2
  430. package/src/oauth/fallback-chain.ts +47 -17
  431. package/src/onboarding/first-run-doctor.ts +8 -1
  432. package/src/onboarding/first-run.ts +85 -26
  433. package/src/onboarding/key-setup.ts +103 -0
  434. package/src/onboarding/menu-answer.ts +13 -0
  435. package/src/onboarding/secret-prompt.ts +37 -0
  436. package/src/plugins/install/plugin-install.ts +59 -0
  437. package/src/pr-tool/census.ts +130 -0
  438. package/src/pty-shell/pty-control-ipc.ts +4 -1
  439. package/src/registry/catalog-server.ts +232 -0
  440. package/src/registry/loader.ts +45 -1
  441. package/src/registry/types.ts +1 -2
  442. package/src/research/axis-fanout.ts +43 -28
  443. package/src/self-dev/ask-launch-flow.ts +72 -1
  444. package/src/self-dev/dev-cli.ts +4 -1
  445. package/src/self-dev/dev-pipeline.ts +5 -0
  446. package/src/self-dev/draft-residue.ts +64 -5
  447. package/src/self-dev/graph-front-nodes.ts +2 -1
  448. package/src/self-dev/graph-journey-route.ts +76 -21
  449. package/src/self-dev/launch-preflight.ts +58 -0
  450. package/src/self-dev/orchestrate.ts +1 -1
  451. package/src/self-dev/shard-aggregate.ts +4 -0
  452. package/src/self-dev/shard-run.ts +36 -15
  453. package/src/self-implement/abandoned-classification.ts +12 -3
  454. package/src/self-implement/budget-gate.ts +7 -0
  455. package/src/self-implement/child-llm-preference.ts +10 -1
  456. package/src/self-implement/doctor-visit.ts +30 -8
  457. package/src/self-implement/elanous-tui-spawn.ts +3 -0
  458. package/src/self-implement/fixtures/tdd-green-missing-passing-child-transcript.txt +2 -0
  459. package/src/self-implement/gate-artifacts.ts +2 -1
  460. package/src/self-implement/goal-author-cli.ts +4 -2
  461. package/src/self-implement/goal-author.ts +358 -4
  462. package/src/self-implement/graph-overlay-yaml.ts +30 -4
  463. package/src/self-implement/graph-overlay.ts +3 -1
  464. package/src/self-implement/graph-profile-yaml.ts +107 -0
  465. package/src/self-implement/graph-yaml.ts +26 -3
  466. package/src/self-implement/off-diff-evidence.ts +249 -5
  467. package/src/self-implement/orchestrator.ts +240 -15
  468. package/src/self-implement/run-chart.ts +6 -3
  469. package/src/self-implement/run-ledger.ts +51 -1
  470. package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
  471. package/src/self-implement/tdd-evidence-tags.ts +9 -0
  472. package/src/self-implement/train-gate-receipt.ts +166 -0
  473. package/src/self-implement/train-gate-remote.ts +62 -18
  474. package/src/session/chat.ts +4 -2
  475. package/src/session/session-fanout.ts +2 -0
  476. package/src/session/streaming/acp-stream-sink.ts +2 -1
  477. package/src/session/streaming/chunk-producer.ts +6 -0
  478. package/src/session/streaming/stream-compositor.ts +3 -2
  479. package/src/session-runtime/index.ts +37 -1
  480. package/src/session-runtime/retry-policy.ts +1 -1
  481. package/src/setup/llm-env-detect.ts +3 -0
  482. package/src/setup/service-key-catalog.ts +46 -0
  483. package/src/setup/service-keys.ts +241 -0
  484. package/src/sidetab-core/visible-agent-mission.ts +98 -22
  485. package/src/skills/tools/agent.ts +23 -4
  486. package/src/skills/tools/omni-search.ts +123 -25
  487. package/src/task-agent/parent-host.ts +10 -0
  488. package/src/task-agent/repair-outcomes.ts +65 -0
  489. package/src/task-agent/task-hand.ts +20 -7
  490. package/src/task-orchestrator/dispatcher.ts +14 -1
  491. package/src/task-orchestrator/linear-capture-events.ts +55 -0
  492. package/src/task-orchestrator/store.ts +16 -5
  493. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +4 -0
  494. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +92 -1
  495. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
  496. package/src/task-orchestrator/surfaces/pod-source-receive.ts +23 -11
  497. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
  498. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +35 -9
  499. package/src/task-orchestrator/surfaces/self-implement-pod.ts +172 -6
  500. package/src/task-orchestrator/surfaces/self-implement.ts +27 -3
  501. package/src/task-orchestrator/surfaces/warm-reuse-evidence.ts +169 -0
  502. package/src/task-orchestrator/types.ts +14 -0
  503. package/src/telegram.ts +14 -16
  504. package/src/terminal/coding-agent.ts +14 -5
  505. package/src/terminal/session-registry.ts +1 -1
  506. package/src/tool-hints/gate.ts +1 -0
  507. package/src/tool-runtime/agent-runtime.ts +1 -0
  508. package/src/tool-runtime/browser-hand-runtime.ts +381 -0
  509. package/src/tool-runtime/browser-runtime.ts +2 -1
  510. package/src/tool-runtime/elanous-linear-issue-runtime.ts +76 -0
  511. package/src/tool-runtime/elanous-linear-secretary-runtime.ts +57 -0
  512. package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
  513. package/src/tool-runtime/index.ts +6 -0
  514. package/src/tool-runtime/types.ts +3 -0
  515. package/src/tui/entry.ts +24 -1
  516. package/src/tui/sidetab/attach.ts +140 -11
  517. package/src/tui/sidetab/herdr-portal.ts +225 -0
  518. package/src/user-config.ts +34 -9
  519. package/src/user-intent/types.ts +4 -3
  520. package/src/ux-sim/browser-hand.ts +165 -0
  521. package/src/ux-sim/draft-inventory-builder.ts +198 -0
  522. package/src/ux-sim/fake-browser-page.ts +81 -0
  523. package/src/ux-sim/fake-linear-device.ts +31 -0
  524. package/src/ux-sim/graph-engine-sim.ts +47 -0
  525. package/src/ux-sim/linear-secretary.ts +216 -0
  526. package/src/ux-sim/mock-scenario-catalog.json +75 -23
  527. package/src/ux-sim/mock-scenario-catalog.ts +120 -2
  528. package/src/ux-sim/onboarding-first-run-device.ts +31 -21
  529. package/src/ux-sim/scenario.ts +70 -26
  530. package/src/ux-sim/service-key-setup.ts +50 -0
  531. package/src/ux-sim/term-slash-device.ts +74 -0
  532. package/src/ux-sim/turn-throw-sim.ts +31 -0
  533. package/src/version/packed-revision.json +1 -1
  534. package/src/web-search/exa.ts +77 -0
  535. package/src/web-search/index.ts +30 -9
  536. package/src/web-search/provider.ts +4 -1
  537. package/src/web-search/x-intent.ts +5 -0
  538. package/apps/pwa/out/_next/static/chunks/0244e5b5.6fc7670f8223d82d.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/1121.13ba7a8aff19df81.js +0 -36
  540. package/apps/pwa/out/_next/static/chunks/1345-31427b833438f521.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/1455-530ca16c7e71baff.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/1586.fafc33a9a5835cb7.js +0 -32
  543. package/apps/pwa/out/_next/static/chunks/1744.855fd60ae4c4a8c8.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/193.21a47a3e07ef6860.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/2004.e839fda7ea5a738a.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/2044-dd681a5c08779ff8.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/2101.2248decb38829b03.js +0 -286
  548. package/apps/pwa/out/_next/static/chunks/2160.a097e7b138ae1c55.js +0 -23
  549. package/apps/pwa/out/_next/static/chunks/2300.41ea70ac1bef1446.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/2357-07b5eeb5fb12628d.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/2364.28652020695a6db3.js +0 -34
  552. package/apps/pwa/out/_next/static/chunks/2526.c3e50ac1fec064bd.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/2549-cda50b716ff4250c.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/2550-5f1e88f615568045.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/261-319078c954e40d66.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/2974.595d1e29d040cb6a.js +0 -64
  557. package/apps/pwa/out/_next/static/chunks/3285.89ee2f298682f5e5.js +0 -93
  558. package/apps/pwa/out/_next/static/chunks/3447.06edc7b092021417.js +0 -41
  559. package/apps/pwa/out/_next/static/chunks/3510-9ca392698bfe4391.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/3541.772e5ce425aaa611.js +0 -24
  561. package/apps/pwa/out/_next/static/chunks/3741.9cf76acaa2ee5298.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/3837.a210d7d0db8d8abd.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/3898-955c896f394217a6.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/3947-ef57acea76eaa8d2.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/4037-3b82ebc7d78afdc7.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/405.9022d4a478202b67.js +0 -77
  567. package/apps/pwa/out/_next/static/chunks/417-fb2cc9a9910e5968.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/4276.336d76d858fcdf1b.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/4302.6ced9aa4535de947.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/4768-8eac183fd291ca53.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/4895.65605ec3e6504e89.js +0 -74
  572. package/apps/pwa/out/_next/static/chunks/5112.4b9f300124fab7b3.js +0 -149
  573. package/apps/pwa/out/_next/static/chunks/5335.375ee922bcd5bc83.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/5342.023a2e729689b320.js +0 -27
  575. package/apps/pwa/out/_next/static/chunks/5431-72a1dbde59400691.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/5486-b318c165f645d8ba.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/5506-c7d2ec25c62a7c94.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/5570-c66ecbea26b4e3b1.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/5696.ffca5aa259d8451e.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/5793-8c584aea2aa87560.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/5848-6de6b8c173351a90.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/5885.0a3e52c8faccec98.js +0 -287
  583. package/apps/pwa/out/_next/static/chunks/5999.94e3c83040200f31.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/5a7901d6-2d8d9b5587cf9042.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/6131.348b7d6bdcd267ce.js +0 -226
  586. package/apps/pwa/out/_next/static/chunks/6164.86133a0172611184.js +0 -90
  587. package/apps/pwa/out/_next/static/chunks/6377.bc7df239edbff244.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/6515.e07e8b2b8a707a87.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/6522-c005514f87d18982.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/6642.648adb1767f39ecf.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/6848.138805a09d001d09.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/7049-c09e2b7a253a24f3.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/7072.1e00447d9fa39972.js +0 -104
  594. package/apps/pwa/out/_next/static/chunks/7106.64201c539c5e220c.js +0 -94
  595. package/apps/pwa/out/_next/static/chunks/7151-1f742b455986530e.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/7199.18d6b25e001154ce.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/7279-c199ea83f34338fa.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/728b938d.ffaa7ad583d60e58.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/7309.171c3de54e0322f1.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/733.7a1ab3342e03306f.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/7504.d5cf1e7cd89b1b08.js +0 -24
  602. package/apps/pwa/out/_next/static/chunks/7573-0fd4af62d65d4598.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/759.6f8267df4689c401.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/7825-668b046f72f14483.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/7852-1538768b6eb19388.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/7868.cff810430bb63c91.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/8084-dfcc796874ab4e07.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/8266.6bf9b131b2584678.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/8403.7b81d5e64074a725.js +0 -8
  610. package/apps/pwa/out/_next/static/chunks/8470.1998cbd0866a7eac.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/8546-6f03f8ea34dd61d9.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/8687-246fda8433d3477c.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/898-280022fb082936bc.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/9098-50eefc1844212e3d.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/9249.976f1e69a9d80754.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/9255-cf88fceda5666645.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/9306-e523ba58bb8adc42.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/9324.a9866d717ba62cb6.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/9325.a8510e8aa87c8143.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/9353-12bfff0c130104cf.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/9415.69e4a21c60c7d2db.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/9479-154a697d4b6e4e98.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/9540-65aa6ccc31b3fd78.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/9633.ce5bddc56784da72.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/9832.f4a98c878ecf2c0a.js +0 -62
  626. package/apps/pwa/out/_next/static/chunks/9865.f094440645f02d98.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/9a852a62-6192a6ea9346ced3.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-e772b4710df5d936.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4361368e6a76b967.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-802f349fdd65248d.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/app/board/page-7f35513988a2a495.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/app/botlab/page-798121656540e33e.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/app/bots/page-20a089490affe98c.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/app/ceo/page-e5e4ec786d70e604.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/app/chat/page-d12fe5d0801430e4.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/app/consult/page-d8cf21022fecc026.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/app/control/page-21ce565c9c57ee97.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/app/decisions/page-b56563025f619c9b.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/app/design-check/page-52f14dd133da8348.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/app/editor/page-c0ed7fdcdba76633.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/app/exec/page-af8c3020cb520f15.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/app/field/page-72eda67af9f5e35c.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/app/healthz/route-e772b4710df5d936.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/app/inside/page-67a6620d31f0a46f.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/intake/page-f059363aa0880ec2.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/layout-f9f917d6a57f69fb.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/live/page-d3ae55eee2f0826c.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0e3d7b9421b79dac.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/loops/page-ba738f7e233eb211.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/market/page-33438b98c74fd599.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-0b34d5fd990d793a.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/not-found-3fced192be5279c1.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/observatory/page-04cb3cf182a7c1ea.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6ccbd2ab23a21542.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-aa0518c48a5f4e56.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4b32226d341ad7d7.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3224fd8f6383b61f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/page-efbc97459f2914e2.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2fe487d88cd5d97c.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-48861dd1a858bab7.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/sessions/page-197d5d4d21d228ea.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a763ba89fbdd9c27.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/settings/page-7edb253510b1c136.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0c875702c61965ea.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/setup/layout-e772b4710df5d936.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/setup/page-e425c951151095f7.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/share/page-9c90e0aec4e27f77.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/showroom/page-733e09a02e727d42.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/tasks/page-4f899e14c34d77a1.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/term/page-bf067887b3307423.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/today/page-7af10868ff87d04e.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/trace/page-efe5304057aa11c7.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/vault/page-76bcd29aaa8a26c3.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-4cfd88e2273ce50f.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0a1ddb47efba0a32.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2a176c707152c892.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-efe03031b8797fbf.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/framework-d0d2d673bfd8a8a9.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/main-4c9fceb2baa09cb7.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/main-app-b0ab8d8fc9a97556.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/pages/_app-7e2cc62a2e5cec96.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/pages/_error-22324935f753ec5e.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/webpack-9dc1bfa25334998a.js +0 -1
  684. package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
  685. /package/apps/pwa/out/_next/static/{X1ucLw10Cds_h614NoEnh → Om5xS9jpjSXJCeTNGYEi4}/_ssgManifest.js +0 -0
@@ -4,6 +4,8 @@ import { applyGraphOverlays, defaultOverlaysDir, loadGraphOverlays, selectOverla
4
4
  import { L1_PROTECTED_ROUTE_NODES, type GraphTemplateSpec } from '../self-implement/graph-yaml.js';
5
5
  import { evaluateOverlayCondition } from '../self-implement/graph-overlay-condition.js';
6
6
  import { journeyJoinFields } from './graph-journey-nodes.js';
7
+ import { defaultProfilesDir, loadGraphProfiles, selectGraphProfiles, type GraphProfileSpec } from '../self-implement/graph-profile-yaml.js';
8
+ import { appendRunLedgerEntry, runLedgerDir } from '../self-implement/run-ledger.js';
7
9
 
8
10
  /** ⭐ HARNESS-FULL-GRAPH 2판 — 「다음 노드」를 코드가 아니라 «그래프»가 정한다.
9
11
  *
@@ -29,11 +31,14 @@ export interface JourneyRoute {
29
31
  readonly skippedNode?: string;
30
32
  readonly skipCondition?: string;
31
33
  readonly skippedNodes?: readonly { readonly node: string; readonly condition: string }[];
34
+ readonly profileIds?: readonly string[];
35
+ readonly profileRejections?: readonly string[];
32
36
  }
33
37
 
34
38
  /** ⛔ 캐시하지 않는다 — 여러 런을 처리하는 프로세스(데몬·대기열 tick)가 다음 발사에서 오버레이 변경을 봐야 한다.
35
39
  * 여정 판정은 발사당 몇 번뿐이라 디렉터리 한 번 읽기가 싸다. */
36
40
  let overlaysForTesting: readonly GraphOverlaySpec[] | undefined;
41
+ let profilesForTesting: readonly GraphProfileSpec[] | undefined;
37
42
  function launchOverlays(): readonly GraphOverlaySpec[] {
38
43
  if (overlaysForTesting !== undefined) return overlaysForTesting;
39
44
  try { return loadGraphOverlays(defaultOverlaysDir()).overlays; }
@@ -45,21 +50,50 @@ export function setJourneyOverlaysForTesting(overlays: readonly GraphOverlaySpec
45
50
  overlaysForTesting = overlays;
46
51
  }
47
52
 
53
+ /** Test seam for a stable profile set; undefined reads the profile directory beside the graph sources. */
54
+ export function setJourneyProfilesForTesting(profiles: readonly GraphProfileSpec[] | undefined): void {
55
+ profilesForTesting = profiles;
56
+ }
57
+
58
+ function launchProfiles(): { readonly profiles: readonly GraphProfileSpec[]; readonly errors: readonly string[] } {
59
+ if (profilesForTesting !== undefined) return { profiles: profilesForTesting, errors: [] };
60
+ const loaded = loadGraphProfiles(defaultProfilesDir());
61
+ return { profiles: loaded.profiles, errors: loaded.errors.map((issue) => `${issue.path}: ${issue.message}`) };
62
+ }
63
+
48
64
  /** 상태 값으로 고른 «이 런의 여정 선언» — 기준 YAML ⊕ 조건이 맞는 launch 오버레이. */
49
65
  export function journeySpec(
50
66
  state: Readonly<Record<string, unknown>>,
51
67
  base: GraphTemplateSpec | undefined = GRAPH_SPECS['self-implement'],
52
68
  overlays: readonly GraphOverlaySpec[] = launchOverlays(),
53
- ): { readonly spec: GraphTemplateSpec | undefined; readonly applied: readonly string[] } {
54
- if (base === undefined) return { spec: undefined, applied: [] };
69
+ profiles: readonly GraphProfileSpec[] = launchProfiles().profiles,
70
+ profileLoadErrors: readonly string[] = [],
71
+ ): { readonly spec: GraphTemplateSpec | undefined; readonly applied: readonly string[]; readonly profileIds: readonly string[]; readonly profileRejections: readonly string[] } {
72
+ if (base === undefined) return { spec: undefined, applied: [], profileIds: [], profileRejections: [] };
55
73
  try {
56
- const { applied } = selectOverlays(overlays, { graphId: base.graphId, stage: 'launch', state });
57
- if (applied.length === 0) return { spec: base, applied: [] };
74
+ const selection = selectGraphProfiles(profiles, state);
75
+ const profileIds = selection.applied.map((profile) => profile.profileId);
76
+ const profileOverlayIds = new Set(selection.applied.flatMap((profile) => profile.overlays));
77
+ const overlayRejections = [...profileOverlayIds].flatMap((id) => {
78
+ const overlay = overlays.find((candidate) => candidate.overlayId === id);
79
+ if (!overlay) return [`profile overlay not found: ${id}`];
80
+ if (overlay.target !== base.graphId) return [`profile overlay target mismatch: ${id} (${overlay.target})`];
81
+ if (overlay.stage !== 'launch') return [`profile overlay wrong stage: ${id} (${overlay.stage})`];
82
+ return [];
83
+ });
84
+ const profileRejections = [...profileLoadErrors, ...selection.errors, ...overlayRejections];
85
+ if (profileRejections.length > 0) return { spec: base, applied: [], profileIds: [], profileRejections };
86
+ const { applied: candidates } = selectOverlays(overlays, { graphId: base.graphId, stage: 'launch', state: selection.state });
87
+ const ownedState = Object.assign({}, ...selection.applied.map((profile) => profile.state));
88
+ const applied = candidates.filter((overlay) => !profileOverlayIds.has(overlay.overlayId)
89
+ || evaluateOverlayCondition(overlay.appliesWhen, ownedState).kind === 'applies');
90
+ if (applied.length === 0) return { spec: base, applied: [], profileIds, profileRejections: [] };
58
91
  const result = applyGraphOverlays(base, applied);
59
92
  // ⛔ 거절된 오버레이는 길을 바꾸지 않는다 — 기준 선언으로 간다.
60
- return result.ok ? { spec: result.template, applied: result.overlayIds } : { spec: base, applied: [] };
93
+ return result.ok ? { spec: result.template, applied: result.overlayIds, profileIds, profileRejections: [] }
94
+ : { spec: base, applied: [], profileIds: [], profileRejections: result.rejections.map((item) => `${item.kind}: ${item.overlayId}`) };
61
95
  } catch {
62
- return { spec: base, applied: [] };
96
+ return { spec: base, applied: [], profileIds: [], profileRejections: ['profile selection failed'] };
63
97
  }
64
98
  }
65
99
 
@@ -69,10 +103,11 @@ export function readJourneyEdge(
69
103
  from: string,
70
104
  label: string,
71
105
  state: Readonly<Record<string, unknown>> = {},
72
- deps: { readonly base?: GraphTemplateSpec; readonly overlays?: readonly GraphOverlaySpec[] } = {},
106
+ deps: { readonly base?: GraphTemplateSpec; readonly overlays?: readonly GraphOverlaySpec[]; readonly profiles?: readonly GraphProfileSpec[] } = {},
73
107
  ): JourneyRoute {
74
- const { spec, applied } = journeySpec(state, deps.base ?? GRAPH_SPECS['self-implement'], deps.overlays ?? launchOverlays());
75
- let route: JourneyRoute = { from, on: null, label, to: null, source: 'code-default', overlays: applied };
108
+ const profileSet = deps.profiles === undefined ? launchProfiles() : { profiles: deps.profiles, errors: [] as readonly string[] };
109
+ const { spec, applied, profileIds, profileRejections } = journeySpec(state, deps.base ?? GRAPH_SPECS['self-implement'], deps.overlays ?? launchOverlays(), profileSet.profiles, profileSet.errors);
110
+ let route: JourneyRoute = { from, on: null, label, to: null, source: 'code-default', overlays: applied, profileIds, profileRejections };
76
111
  const outgoing = (spec?.edges ?? []).filter(edge => edge.from === from);
77
112
  const protectedFrom = L1_PROTECTED_ROUTE_NODES.has(from) || spec?.nodes.some(node => node.nodeId === from && node.kind === 'gate') ||
78
113
  spec?.terminalNodes.includes(from);
@@ -80,14 +115,14 @@ export function readJourneyEdge(
80
115
  const matching = conditions.filter(({ verdict }) => verdict.kind === 'applies').map(({ edge }) => edge);
81
116
  const unobservedConditions = conditions.filter(({ verdict }) => verdict.kind === 'key-absent').map(({ edge }) => edge.when!);
82
117
  if (matching.length === 1 && unobservedConditions.length === 0 && matching[0]!.to !== undefined) {
83
- route = { from, on: null, label, to: matching[0]!.to!, source: 'graph', overlays: applied,
118
+ route = { ...route, from, on: null, label, to: matching[0]!.to!, source: 'graph', overlays: applied,
84
119
  via: 'when', condition: matching[0]!.when };
85
120
  } else {
86
121
  const mapped = outgoing.find(edge => edge.when === undefined && edge.map !== undefined && Object.hasOwn(edge.map, label));
87
122
  const defaultEdge = mapped ?? outgoing.find(edge => edge.when === undefined && edge.to !== undefined);
88
- if (defaultEdge?.map !== undefined) route = { from, on: defaultEdge.on ?? null, label,
123
+ if (defaultEdge?.map !== undefined) route = { ...route, from, on: defaultEdge.on ?? null, label,
89
124
  to: defaultEdge.map[label]!, source: 'graph', overlays: applied, via: 'outcome' };
90
- else if (defaultEdge?.to !== undefined) route = { from, on: null, label,
125
+ else if (defaultEdge?.to !== undefined) route = { ...route, from, on: null, label,
91
126
  to: defaultEdge.to, source: 'graph', overlays: applied, via: 'outcome' };
92
127
  if (matching.length > 1) route = { ...route, ambiguousConditions: matching.map(edge => edge.when!) };
93
128
  if (unobservedConditions.length > 0) route = { ...route, unobservedConditions };
@@ -129,31 +164,51 @@ export interface JourneyEdgeFields {
129
164
  readonly [key: string]: unknown;
130
165
  }
131
166
 
167
+ function recordGraphPathEvent(event: string, data: Record<string, unknown>, runId?: string): void {
168
+ try { debug.log('graph.path', event, data); } catch { /* fail-soft */ }
169
+ if (!runId) return;
170
+ try { appendRunLedgerEntry({ timestamp: new Date().toISOString(), runId, event: 'graph.path', data: { event, ...data } }, runLedgerDir()); }
171
+ catch { /* path observation must not change execution */ }
172
+ }
173
+
132
174
  /** 실제로 탄 간선을 남긴다 — `taken` 은 실제 다음 노드(그래프 답과 다르면 `honored: false` · 그 이유를 `reason` 에). */
133
175
  export function recordJourneyEdge(route: JourneyRoute, taken: string, reason?: string, data: JourneyEdgeFields = {}): void {
134
176
  try {
177
+ const runId = typeof data.runId === 'string' ? data.runId : undefined;
178
+ for (const rejection of route.profileRejections ?? []) recordGraphPathEvent('profile-rejected', {
179
+ graphId: 'self-implement', reason: rejection, profileIds: route.profileIds ?? [],
180
+ ...(runId === undefined ? {} : { runId }), ...journeyJoinFields(),
181
+ }, runId);
135
182
  if (route.ambiguousConditions?.length) debug.log('self-implement', 'edge-ambiguous', {
136
183
  graphId: 'self-implement', from: route.from, conditions: route.ambiguousConditions,
137
184
  fallback: taken, ...journeyJoinFields(),
138
185
  });
186
+ if (route.ambiguousConditions?.length) recordGraphPathEvent('edge-ambiguous', {
187
+ graphId: 'self-implement', from: route.from, conditions: route.ambiguousConditions,
188
+ fallback: taken, profileIds: route.profileIds ?? [], ...(runId === undefined ? {} : { runId }), ...journeyJoinFields(),
189
+ }, runId);
139
190
  if (route.unobservedConditions?.length) debug.log('self-implement', 'edge-unobserved', {
140
191
  graphId: 'self-implement', from: route.from, conditions: route.unobservedConditions,
141
192
  fallback: taken, ...journeyJoinFields(),
142
193
  });
143
- if (route.to === taken) for (const skipped of route.skippedNodes ?? []) debug.log('self-implement', 'node-skipped', {
144
- graphId: 'self-implement', node: skipped.node, reason: 'condition', condition: skipped.condition,
145
- ...journeyJoinFields(),
146
- });
194
+ if (route.to === taken) for (const skipped of route.skippedNodes ?? []) {
195
+ const skippedData = { graphId: 'self-implement', node: skipped.node, reason: 'condition', condition: skipped.condition,
196
+ profileIds: route.profileIds ?? [], ...(runId === undefined ? {} : { runId }), ...journeyJoinFields() };
197
+ debug.log('self-implement', 'node-skipped', skippedData);
198
+ recordGraphPathEvent('node-skipped', skippedData, runId);
199
+ }
147
200
  // Evidence never overrides an edge field: the later spread wins. Explicit repair join keys win over ambient context.
148
201
  const { reason: _reservedReason, journeyKey: _reservedJourney, queueLaunchId: _reservedLaunch,
149
- runId, card, pr, head, moveId, ...evidence } = data ?? {};
150
- debug.log('self-implement', 'graph-edge-taken', {
202
+ runId: _reservedRunId, card, pr, head, moveId, ...evidence } = data ?? {};
203
+ const edgeData = {
151
204
  ...evidence, graphId: 'self-implement', ...route, taken, honored: route.to === null || route.to === taken,
152
205
  ...(reason === undefined ? {} : { reason }), ...journeyJoinFields(),
153
206
  ...(runId === undefined ? {} : { runId }), ...(card === undefined ? {} : { card }),
154
207
  ...(pr === undefined ? {} : { pr }), ...(head === undefined ? {} : { head }),
155
208
  ...(moveId === undefined ? {} : { moveId }),
156
- });
209
+ };
210
+ debug.log('self-implement', 'graph-edge-taken', edgeData);
211
+ recordGraphPathEvent('edge-taken', edgeData, runId);
157
212
  } catch { /* 관측은 fail-soft */ }
158
213
  }
159
214
 
@@ -162,10 +217,10 @@ export function routeJourneyEdge(
162
217
  from: string,
163
218
  label: string,
164
219
  state: Readonly<Record<string, unknown>> = {},
165
- deps: { readonly base?: GraphTemplateSpec; readonly overlays?: readonly GraphOverlaySpec[] } = {},
220
+ deps: { readonly base?: GraphTemplateSpec; readonly overlays?: readonly GraphOverlaySpec[]; readonly profiles?: readonly GraphProfileSpec[]; readonly runId?: string } = {},
166
221
  ): JourneyRoute {
167
222
  const route = readJourneyEdge(from, label, state, deps);
168
- recordJourneyEdge(route, route.to ?? label);
223
+ recordJourneyEdge(route, route.to ?? label, undefined, deps.runId === undefined ? {} : { runId: deps.runId });
169
224
  return route;
170
225
  }
171
226
 
@@ -340,6 +340,64 @@ export interface LaunchPreflightInput {
340
340
  /** AUTO-TARGET: blocker name for a NOT-GROUNDED goal whose only target paths were machine-suggested (a scope card). */
341
341
  export const NOT_GROUNDED_SCOPE_CARD_BLOCKER = '(NOT-GROUNDED 범위 카드)';
342
342
 
343
+ /** CARD-TARGET-PATHS 가 읽기 전용으로 제공하는 같은-경로 카드 맥락. */
344
+ export interface SiblingContextCard {
345
+ readonly cardId: string;
346
+ readonly runId?: string;
347
+ readonly overlapPaths: readonly string[];
348
+ }
349
+
350
+ function siblingContextPaths(result: LaunchPreflightResult, warning: LaunchPreflightBlocker): readonly string[] {
351
+ return warning.overlapPaths?.map(({ path }) => path)
352
+ ?? result.paths.filter((path) => warning.detail.includes(path));
353
+ }
354
+
355
+ function siblingContextAxis(
356
+ label: string,
357
+ status: PreflightAxisStatus,
358
+ entries: readonly string[],
359
+ ): string {
360
+ if (status.state === 'unknown') return `[sibling-context] ${label}: 못 쟀다 (${status.reason})`;
361
+ if (entries.length === 0) return `[sibling-context] ${label}: 없음`;
362
+ const partial = status.state === 'truncated' ? ` · 부분 측정(상한 ${status.limit})` : '';
363
+ return `[sibling-context] ${label}: ${entries.join(' · ')}${partial}`;
364
+ }
365
+
366
+ /** 같은 대상 경로의 비차단 형제 관측을 골 문서 머리에 넣을 정확히 세 줄로 렌더한다. */
367
+ export function renderSiblingContextLines(
368
+ result: LaunchPreflightResult,
369
+ cards: readonly SiblingContextCard[] = [],
370
+ ): readonly [string, string, string] {
371
+ const liveRuns = result.warnings
372
+ .filter((warning) => warning.kind === 'live-run')
373
+ .map((warning) => {
374
+ const paths = siblingContextPaths(result, warning);
375
+ const cardIds = cards
376
+ .filter((card) => card.runId === warning.name && card.overlapPaths.some((path) => paths.includes(path)))
377
+ .map((card) => card.cardId);
378
+ return [warning.name, ...cardIds.map((cardId) => `카드 ${cardId}`), ...paths].join(' · ');
379
+ });
380
+ const openPrs = result.warnings
381
+ .filter((warning) => warning.kind === 'open-pr' || warning.kind === 'sibling-pr')
382
+ .map((warning) => {
383
+ const draft = /\bdraft\b|초안/u.test(warning.detail) ? ' (draft)' : '';
384
+ const paths = siblingContextPaths(result, warning);
385
+ return `${warning.name}${draft}${paths.length > 0 ? ` · ${paths.join(', ')}` : ''}`;
386
+ });
387
+ const recentLanded = result.warnings
388
+ .filter((warning) => warning.kind === 'recent-change' && result.paths.includes(warning.name))
389
+ .map((warning) => {
390
+ const count = /최근 \d+일 안에 (\d+)건 변경됨/u.exec(warning.detail)?.[1];
391
+ return `sha·PR 미상 · ${warning.name}${count === undefined ? '' : ` ${count}건`}`;
392
+ });
393
+
394
+ return [
395
+ siblingContextAxis('같은 경로 도는 런', result.liveRuns, liveRuns),
396
+ siblingContextAxis('같은 경로 열린 PR', result.openPrs, openPrs),
397
+ siblingContextAxis(`같은 경로 최근 ${result.recentChangeWindowDays}일 착지`, result.recentChanges, recentLanded),
398
+ ];
399
+ }
400
+
343
401
  export function evaluateLaunchPreflight(input: LaunchPreflightInput): LaunchPreflightResult {
344
402
  const paths = [...new Set(input.paths.filter((path) => path.trim().length > 0))];
345
403
  const blockers: LaunchPreflightBlocker[] = [];
@@ -1185,7 +1185,7 @@ export function orchestrateSelfDev(opts: OrchestrateSelfDevOptions): Promise<Sel
1185
1185
  const taskId = [...spaceIdByTask.entries()].find(([, id]) => id === input.spaceId)?.[0];
1186
1186
  const goal = taskId ? taskByGoal.get(taskId) : undefined;
1187
1187
  if (cancelling) throw new Error('orchestration cancelled by signal');
1188
- const started = baseSpawn({ ...input, feature: dependencyOutputFeature(input.spaceId, input.feature) });
1188
+ const started = baseSpawn({ ...input, ...(taskId ? { taskId } : {}), feature: dependencyOutputFeature(input.spaceId, input.feature) });
1189
1189
  if (goal && taskId) {
1190
1190
  try { opts.onTaskLaunched?.(goal, taskId, priorByResumeKey.get(resumeKey(goal.feature))?.taskId); }
1191
1191
  catch { /* observation must not interrupt execution */ }
@@ -12,6 +12,10 @@ import type { GateTestShard } from './shard-plan.js';
12
12
  export interface GateShardAttempt {
13
13
  shardId: string;
14
14
  attempt: number;
15
+ /** Wall time for this shard attempt across current and baseline processes. */
16
+ elapsedMs?: number;
17
+ currentUnmeasuredReason?: string;
18
+ baselineUnmeasuredReason?: string;
15
19
  /** A process death, missing report, or incomplete XML is not a test failure. */
16
20
  currentJUnit?: string;
17
21
  baselineJUnit?: string;
@@ -130,6 +130,8 @@ export function maxAutomaticShardCount(requested: number, budgetGiB: number, res
130
130
  export type ShardProcess = (cwd: string, files: readonly string[]) => {
131
131
  exitCode: number | null;
132
132
  signal?: string | null;
133
+ elapsedMs?: number;
134
+ unmeasuredReason?: string;
133
135
  junit?: string;
134
136
  rssMb?: number;
135
137
  seconds?: number;
@@ -337,12 +339,16 @@ function runPlannedShards(
337
339
  if (baselineFiles.length < shard.files.length) {
338
340
  debug.log('self-dev.shard', 'baseline-files-absent', { shardId: shard.id, round, absent: shard.files.filter((file) => !baselineFiles.includes(file)) });
339
341
  }
342
+ const shardStartedAt = performance.now();
340
343
  const current = runSafely(cwd, shard.files);
341
344
  const base = baselineFiles.length ? runSafely(dir, baselineFiles) : { exitCode: 0 };
342
345
  keepFailure(shard.id, 'current', round, shard.files, current);
343
346
  keepFailure(shard.id, 'baseline', round, baselineFiles, base);
344
347
  attempts.push({
345
348
  shardId: shard.id, attempt: round,
349
+ elapsedMs: Math.round(performance.now() - shardStartedAt),
350
+ currentUnmeasuredReason: current.unmeasuredReason,
351
+ baselineUnmeasuredReason: base.unmeasuredReason,
346
352
  currentJUnit: current.junit, baselineJUnit: base.junit,
347
353
  currentExitCode: current.exitCode, baselineExitCode: base.exitCode,
348
354
  currentSignal: current.signal, baselineSignal: base.signal,
@@ -471,6 +477,8 @@ export async function runShardedGateTestsAsync(
471
477
  if (concurrency > 1 && baselineFiles.length && base.exitCode === 0 && !base.signal && base.junit) baselinePassCache.set(shard.id, base);
472
478
  roundAttempts[index] = {
473
479
  shardId: shard.id, attempt: round, currentJUnit: current.junit, baselineJUnit: base.junit,
480
+ elapsedMs: Math.round(performance.now() - currentStartedAt),
481
+ currentUnmeasuredReason: current.unmeasuredReason, baselineUnmeasuredReason: base.unmeasuredReason,
474
482
  currentExitCode: current.exitCode, baselineExitCode: base.exitCode,
475
483
  currentSignal: current.signal, baselineSignal: base.signal,
476
484
  currentDiagnostic: current.diagnostic, baselineDiagnostic: base.diagnostic,
@@ -523,23 +531,31 @@ function incompleteShardReasons(shardIds: readonly string[], attempts: readonly
523
531
  return Object.fromEntries(shardIds.map((id) => {
524
532
  const latest = attempts.filter((attempt) => attempt.shardId === id).at(-1);
525
533
  if (!latest) return [id, 'no shard attempt recorded'];
526
- const side = (name: string, rc: number | null, signal: string | null | undefined, junit: string | undefined, diagnostic: string | undefined): string => {
534
+ const side = (name: string, rc: number | null, signal: string | null | undefined, junit: string | undefined, diagnostic: string | undefined, unmeasuredReason?: string): string => {
535
+ if (unmeasuredReason) return `${name}: ${unmeasuredReason}`;
527
536
  const safeDiagnostic = diagnostic ? redactSecretText(diagnostic).replace(/[\r\n\t\x00-\x1f\x7f]+/g, ' ').slice(0, 500) : undefined;
528
537
  return `${name}: exit ${rc ?? 'unavailable'}, signal ${signal ?? 'none'}, JUnit ${junit === undefined ? 'missing' : 'present'}`
529
538
  + (safeDiagnostic ? `; ${safeDiagnostic}` : '');
530
539
  };
531
540
  const statuses = [
532
- side('current', latest.currentExitCode, latest.currentSignal, latest.currentJUnit, latest.currentDiagnostic),
533
- ...(latest.baselineFiles?.length === 0 ? [] : [side('baseline', latest.baselineExitCode, latest.baselineSignal, latest.baselineJUnit, latest.baselineDiagnostic)]),
541
+ side('current', latest.currentExitCode, latest.currentSignal, latest.currentJUnit, latest.currentDiagnostic, latest.currentUnmeasuredReason),
542
+ ...(latest.baselineFiles?.length === 0 ? [] : [side('baseline', latest.baselineExitCode, latest.baselineSignal, latest.baselineJUnit, latest.baselineDiagnostic, latest.baselineUnmeasuredReason)]),
534
543
  ];
535
544
  return [id, `${statuses.join(' · ')} · aggregate rejected (incomplete, malformed JUnit, or exit/JUnit mismatch)`];
536
545
  }));
537
546
  }
538
547
 
539
- export function selfGateShardTimeoutMs(files: readonly string[]): number {
548
+ export const DEFAULT_SELF_GATE_SHARD_TIMEOUT_MS = 900_000;
549
+ export const SELF_GATE_SHARD_TIMEOUT_ENV = 'ELANOUS_SELF_GATE_SHARD_TIMEOUT_MS';
550
+
551
+ export function selfGateShardTimeoutMs(files: readonly string[], env: NodeJS.ProcessEnv = process.env): number {
540
552
  const spawnFiles = files.filter(isGateSpawnLaneFile);
541
553
  if (spawnFiles.length && spawnFiles.length !== files.length) throw new Error('self gate spawn lane mixed with regular tests');
542
- return spawnFiles.length ? 120_000 : 300_000;
554
+ const configured = env[SELF_GATE_SHARD_TIMEOUT_ENV];
555
+ if (configured !== undefined && (!/^\d+$/.test(configured) || !Number.isSafeInteger(Number(configured)) || Number(configured) < 1)) {
556
+ throw new Error(`${SELF_GATE_SHARD_TIMEOUT_ENV} must be a positive integer number of milliseconds`);
557
+ }
558
+ return configured === undefined ? (spawnFiles.length ? 120_000 : DEFAULT_SELF_GATE_SHARD_TIMEOUT_MS) : Number(configured);
543
559
  }
544
560
 
545
561
  export function runBunShard(cwd: string, files: readonly string[]): ReturnType<ShardProcess> {
@@ -547,25 +563,29 @@ export function runBunShard(cwd: string, files: readonly string[]): ReturnType<S
547
563
  }
548
564
 
549
565
  /** Child launch seam for verifying the actual command and process timeout. */
550
- export function runBunShardWithSpawn(cwd: string, files: readonly string[], spawn: typeof Bun.spawnSync): ReturnType<ShardProcess> {
551
- const timeout = selfGateShardTimeoutMs(files);
552
- const spawnLane = timeout === 120_000;
566
+ export function runBunShardWithSpawn(cwd: string, files: readonly string[], spawn: typeof Bun.spawnSync, env: NodeJS.ProcessEnv = process.env): ReturnType<ShardProcess> {
567
+ const timeout = selfGateShardTimeoutMs(files, env);
568
+ const spawnLane = files.some(isGateSpawnLaneFile);
553
569
  const dir = mkdtempSync(join(tmpdir(), 'elanous-shard-junit-'));
554
570
  const report = join(dir, 'result.xml');
555
571
  const isolated = prepareDeterministicChildEnvironment('elanous-shard-test-env-', { env: withGateTestEnv(process.env) });
556
572
  try {
557
573
  const measured = files.length === 1;
558
- const args = ['test', ...(spawnLane ? ['--timeout=120000'] : []), '--reporter=junit', `--reporter-outfile=${report}`, ...files];
574
+ const args = ['test', ...(spawnLane ? [`--timeout=${timeout}`] : []), '--reporter=junit', `--reporter-outfile=${report}`, ...files];
559
575
  const started = performance.now();
560
576
  const result = spawn(['bun', ...args], {
561
577
  cwd, env: isolated.env, stdout: 'pipe', stderr: 'pipe', timeout,
562
578
  });
563
579
  const durationMs = performance.now() - started;
564
580
  const junit = existsSync(report) ? readFileSync(report, 'utf8') : undefined;
581
+ const timedOut = (result as typeof result & { error?: { code?: string } }).error?.code === 'ETIMEDOUT'
582
+ || (durationMs >= timeout && (result.exitCode !== 0 || !!result.signalCode));
565
583
  const failed = result.exitCode !== 0 || !!result.signalCode || junit === undefined;
566
584
  return {
567
585
  exitCode: result.exitCode,
568
- signal: result.signalCode ? String(result.signalCode) : undefined,
586
+ signal: timedOut ? undefined : result.signalCode ? String(result.signalCode) : undefined,
587
+ elapsedMs: Math.round(durationMs),
588
+ ...(timedOut ? { unmeasuredReason: `timeout ${timeout / 1000}s 초과` } : {}),
569
589
  junit,
570
590
  ...(junit === undefined && (result.exitCode !== 0 || result.signalCode)
571
591
  ? { diagnostic: boundedDiagnostic(result.stdout, result.stderr) } : {}),
@@ -580,9 +600,9 @@ export function runBunShardWithSpawn(cwd: string, files: readonly string[], spaw
580
600
  }
581
601
 
582
602
  /** Nonblocking child runner; each bundle still owns its own deterministic environment and JUnit path. */
583
- export async function runBunShardAsync(cwd: string, files: readonly string[], drainTimeoutMs = 5_000): Promise<ReturnType<ShardProcess>> {
584
- const timeout = selfGateShardTimeoutMs(files);
585
- const spawnLane = timeout === 120_000;
603
+ export async function runBunShardAsync(cwd: string, files: readonly string[], drainTimeoutMs = 5_000, env: NodeJS.ProcessEnv = process.env): Promise<ReturnType<ShardProcess>> {
604
+ const timeout = selfGateShardTimeoutMs(files, env);
605
+ const spawnLane = files.some(isGateSpawnLaneFile);
586
606
  const dir = mkdtempSync(join(tmpdir(), 'elanous-shard-junit-'));
587
607
  const report = join(dir, 'result.xml');
588
608
  const isolated = prepareDeterministicChildEnvironment('elanous-shard-test-env-', { env: withGateTestEnv(process.env) });
@@ -590,7 +610,7 @@ export async function runBunShardAsync(cwd: string, files: readonly string[], dr
590
610
  let drainTimer: ReturnType<typeof setTimeout> | undefined;
591
611
  const drainAbort = new AbortController();
592
612
  try {
593
- const args = ['test', ...(spawnLane ? ['--timeout=120000'] : []), '--reporter=junit', `--reporter-outfile=${report}`, ...files];
613
+ const args = ['test', ...(spawnLane ? [`--timeout=${timeout}`] : []), '--reporter=junit', `--reporter-outfile=${report}`, ...files];
594
614
  const started = performance.now();
595
615
  const child = Bun.spawn(['bun', ...args], { cwd, env: isolated.env, stdout: 'pipe', stderr: 'pipe' });
596
616
  let timedOut = false;
@@ -624,7 +644,8 @@ export async function runBunShardAsync(cwd: string, files: readonly string[], dr
624
644
  const signal = drainTimedOut ? 'DRAIN_TIMEOUT' : timedOut ? 'SIGKILL' : child.signalCode ? String(child.signalCode) : undefined;
625
645
  const failed = exitCode !== 0 || !!signal || junit === undefined;
626
646
  return {
627
- exitCode, signal, junit,
647
+ exitCode, signal: timedOut ? undefined : signal, elapsedMs: Math.round(durationMs),
648
+ ...(timedOut ? { unmeasuredReason: `timeout ${timeout / 1000}s 초과` } : {}), junit,
628
649
  ...(files.length === 1 ? { rssMb: usage ? usage.maxRSS / (1024 * 1024) : undefined, seconds: durationMs / 1000 } : {}),
629
650
  ...(junit === undefined && (exitCode !== 0 || signal) ? { diagnostic: boundedDiagnostic(stdout, stderr) } : {}),
630
651
  ...(failed ? { failure: { durationMs: Math.round(durationMs), stdoutTail: outputTail(stdout), stderrTail: outputTail(stderr) } } : {}),
@@ -68,6 +68,7 @@ type AbandonedClassificationBasis =
68
68
  | 'merge-approval-received'
69
69
  // 기한 사망은 호스트가 읽은 Job 종료 이유다. 사후 쿼터 상관보다 앞선다.
70
70
  | 'substrate-deadline-outranks-postmortem-quota'
71
+ | 'tdd-evidence-missing'
71
72
  // 🩸 2026-09-20: 이 셋은 분류 «이름을 되풀이»했다 — 근거 칸이 동어반복이면 중재를 못 한다.
72
73
  // 📏 실물(block 아티팩트)에서 네 칸이 2:2 로 갈렸다:
73
74
  // reason·stage = 게이트 ↔ 중단원인·classification = 쿼타
@@ -115,6 +116,8 @@ interface AbandonedClassificationInput {
115
116
  /** 호스트가 k8s Job 종료 reason `DeadlineExceeded` 를 읽었을 때만 참이다.
116
117
  * ⛔ 사후 쿼터 상관(`quotaExhausted`)보다 앞선다 — 기한 사망을 할당량 소진으로 읽지 않는다. */
117
118
  readonly substrateDeadlineExceeded?: boolean;
119
+ /** Structured child termination cause survives classification instead of being flattened into report-deficit. */
120
+ readonly terminationReason?: 'tdd-evidence-missing';
118
121
  /** ⭐ provider 쿼터가 «찬 것으로 관측»되었을 때만 참이다.
119
122
  * ⛔ 이 값은 «추론하지 않는다» — 호출자가 provider 응답(`rateLimitReachedType`)을 읽어 넘긴다.
120
123
  * ⚠️ 그 읽기는 런이 죽은 «뒤»에 일어나므로 「죽은 원인」이 아니라 「죽을 무렵 쿼터가 찼다」는 상관이다.
@@ -151,6 +154,7 @@ export interface AbandonedClassificationResult {
151
154
  readonly classification: AbandonedClassification;
152
155
  /** The condition that selected `classification`, so consumers need not reconstruct the branch. */
153
156
  readonly classificationBasis: AbandonedClassificationBasis;
157
+ readonly terminationReason?: 'tdd-evidence-missing';
154
158
  readonly worktreeClean: boolean | undefined;
155
159
  readonly completionDisposition?: SelfImplementCompletionDisposition;
156
160
  readonly supervisorVerdict?: ReworkBudgetVerdict;
@@ -221,6 +225,8 @@ export function classifyAbandonedRun(input: AbandonedClassificationInput): Aband
221
225
  ? 'credential-failure'
222
226
  : input.providerError === true
223
227
  ? 'provider-error'
228
+ : input.terminationReason === 'tdd-evidence-missing'
229
+ ? 'implementation-deficit'
224
230
  // A candidate is selected only from two structured observations. This deliberately does not prove a defect.
225
231
  : input.supervisorVerdict === 'UNCONVERGEABLE' && input.goalCauseObserved === true
226
232
  ? 'goal-unconvergeable-candidate'
@@ -247,6 +253,11 @@ export function classifyAbandonedRun(input: AbandonedClassificationInput): Aband
247
253
  case 'provider-error': return input.providerErrorCategory === 'request'
248
254
  ? 'provider-request-rejection-outranks-account-availability'
249
255
  : 'environment-provider-error-outranks-run-stage-evidence';
256
+ case 'implementation-deficit': return input.terminationReason === 'tdd-evidence-missing'
257
+ ? 'tdd-evidence-missing'
258
+ : mustFixReported
259
+ ? 'must-fix-reported'
260
+ : 'no-must-fix-without-clean-worktree-or-completed-without-changes';
250
261
  case 'already-satisfied': return 'cited-evidence-exists-without-changes';
251
262
  case 'report-deficit': return input.reviewResultObserved === true
252
263
  ? input.citedEvidenceExists === false
@@ -259,9 +270,6 @@ export function classifyAbandonedRun(input: AbandonedClassificationInput): Aband
259
270
  : input.reviewResultObserved === false
260
271
  ? 'terminal-state-not-reviewed'
261
272
  : 'review-result-observation-unmeasured';
262
- case 'implementation-deficit': return mustFixReported
263
- ? 'must-fix-reported'
264
- : 'no-must-fix-without-clean-worktree-or-completed-without-changes';
265
273
  }
266
274
  })();
267
275
 
@@ -269,6 +277,7 @@ export function classifyAbandonedRun(input: AbandonedClassificationInput): Aband
269
277
  return {
270
278
  classification,
271
279
  classificationBasis,
280
+ ...(input.terminationReason ? { terminationReason: input.terminationReason } : {}),
272
281
  worktreeClean,
273
282
  ...(input.completionDisposition ? { completionDisposition: input.completionDisposition } : {}),
274
283
  ...(input.supervisorVerdict ? { supervisorVerdict: input.supervisorVerdict } : {}),
@@ -71,6 +71,7 @@ function budgetCreditReserve(config: ChildLlmPreferenceInput): number {
71
71
  }
72
72
 
73
73
  const WEEKLY_WINDOW_MINUTES = 7 * 24 * 60;
74
+ const UNMEASURED_API_KEY_PROVIDERS = new Set(['glm', 'openrouter']);
74
75
 
75
76
  function capFor(maxUsedPercent: BudgetGateMaxUsedPercent, provider: string): number | undefined {
76
77
  if (!Object.prototype.hasOwnProperty.call(maxUsedPercent, provider)) {
@@ -179,6 +180,12 @@ function slotUsable(
179
180
  ...(unmeasured ? { unmeasured: true } : {}),
180
181
  };
181
182
  }
183
+ // The launch gate has no usage meter for API-key providers such as GLM/OpenRouter.
184
+ // A provider explicitly selected in the resolved child chain may launch, with the
185
+ // missing measurement surfaced; ordinary budget decisions remain fail-closed.
186
+ if (allowUnmeasured && UNMEASURED_API_KEY_PROVIDERS.has(provider)) {
187
+ return { usable: true, reason: `${provider}: 예산 미측정`, unmeasured: true };
188
+ }
182
189
  return { usable: false, reason: `${provider}: 예산 판정 없음` };
183
190
  }
184
191
 
@@ -10,6 +10,7 @@ import type {
10
10
  } from '../user-config.js';
11
11
  import { DEFAULT_BUDGET_GATE } from '../user-config.js';
12
12
  import { debug } from '../debug/log.js';
13
+ import { fallbackChainForProvider, normalizeFallbackChain } from '../oauth/fallback-chain.js';
13
14
 
14
15
  /** 체인 한 칸. `codexCredits` = `llm.fallbackChain` 의 `codex-credits` 칸(codex 를 선불 크레딧으로 · 마지막 수단). */
15
16
  export type ChildLlmChainSlot = ChildLlmChainEntry & { readonly codexCredits?: true };
@@ -32,6 +33,8 @@ const FALLBACK_NAME_TO_PROVIDER: Readonly<Record<string, string>> = {
32
33
  grok: 'grok',
33
34
  // CODEX-CREDITS-STEP — provider 는 같은 codex 지만 «크레딧 칸»이라 따로 센다(아래 중복 판정).
34
35
  'codex-credits': 'openai-codex',
36
+ zai: 'glm',
37
+ openrouter: 'openrouter',
35
38
  };
36
39
 
37
40
  function warnPreference(detail: string): void {
@@ -83,7 +86,13 @@ export function resolveChildLlmPreference(config: ChildLlmPreferenceInput): Reso
83
86
  }));
84
87
  chainSource = 'config';
85
88
  } else {
86
- chain = chainFromFallbackNames(config.llm.fallbackChain);
89
+ const configuredFallback = config.llm.fallbackChain;
90
+ const derived = normalizeFallbackChain(configuredFallback, config.llm.provider);
91
+ // Preserve auto's empty preference: the launch gate applies its legacy code
92
+ // default there. An explicitly selected provider gets its own derived chain.
93
+ const steps = configuredFallback === undefined && !fallbackChainForProvider(config.llm.provider)
94
+ ? [] : derived.chain;
95
+ chain = chainFromFallbackNames(steps);
87
96
  chainSource = 'fallbackChain';
88
97
  }
89
98
 
@@ -483,6 +483,26 @@ export interface DoctorComparisonRecord {
483
483
  opResult: string;
484
484
  }
485
485
 
486
+ /**
487
+ * 하류 계약: 비교 판정의 명명된 실패는 message 문자열이 아니라 typed identity(`reason`)로도 도착한다.
488
+ * 사람이 읽는 문면은 종전과 같은 문장 그대로다(문장 접두사 = reason). 실제로 없는 원장만
489
+ * `run-ledger-missing` 이고, 운영/시험 원장 쓰기 거부는 이 클래스가 아니라
490
+ * `DoctorComparisonLedgerWriteRefusedError` 다.
491
+ */
492
+ export type DoctorComparisonFailureReason =
493
+ | 'run-ledger-missing'
494
+ | 'shadow-rx-missing'
495
+ | 'visit-missing'
496
+ | 'comparison-corrupt'
497
+ | 'comparison-conflict';
498
+
499
+ export class DoctorComparisonFailureError extends Error {
500
+ constructor(readonly reason: DoctorComparisonFailureReason, message: string) {
501
+ super(message);
502
+ this.name = 'DoctorComparisonFailureError';
503
+ }
504
+ }
505
+
486
506
  /**
487
507
  * 하류 계약: 운영/시험 원장 쓰기 거부는 message 문자열이 아니라 typed identity(`reason`·`runId`·
488
508
  * `ledgerDir`)로 도착한다. 사람이 읽는 문면은 종전과 같은 문장 그대로다.
@@ -507,8 +527,10 @@ export class DoctorComparisonLedgerWriteRefusedError extends Error {
507
527
  * 하류 계약(typed identity) — ① 원장 쓰기 거부는 DoctorComparisonLedgerWriteRefusedError
508
528
  * (`reason='ledger-write-refused'`·`runId`·`ledgerDir`), ② runId 불일치는 원장 바이트와 checked
509
529
  * append 양쪽 모두 RunLedgerCheckedAppendRunIdMismatchError(`reason='runId-mismatch'`·
510
- * `decisionRunId`·`lockedRunId`)로 도착한다. 문자열 파싱 없이 분류하고, 실제로 없는 원장만
511
- * `run-ledger-missing` 이다.
530
+ * `decisionRunId`·`lockedRunId`)로 도착한다, ③ 나머지 명명된 실패(run-ledger-missing·
531
+ * shadow-rx-missing·visit-missing·comparison-corrupt·comparison-conflict)는
532
+ * DoctorComparisonFailureError(`reason` = 그 이름, 사람 문면은 접두사 그대로)로 도착한다.
533
+ * 문자열 파싱 없이 분류하고, 실제로 없는 원장만 `run-ledger-missing` 이다.
512
534
  *
513
535
  * 배선 경계(의도적): 이 슬라이스의 호출자는 시험 경로뿐이다 — live dispatch·stall-watch retirement
514
536
  * 은 후속 cross-judgment 증거 슬라이스에서 붙는다(현행 `eln doctor status --json` = total 0
@@ -531,7 +553,7 @@ export function recordDoctorComparison(input: RecordDoctorComparisonInput): Doct
531
553
  // lock 안에서 appendRunLedgerEntry 를 다시 부르지 않는다(중첩 lock 시간초과).
532
554
  const outcome: RunLedgerCheckedAppendOutcome<DoctorComparisonRecord> = appendRunLedgerEntryChecked<DoctorComparisonRecord>(runId, (entries) => {
533
555
  if (entries === null) {
534
- throw new Error(`run-ledger-missing: 런 원장이 없습니다 (runId=${runId}) — 새 원장을 만들지 않습니다`);
556
+ throw new DoctorComparisonFailureError('run-ledger-missing', `run-ledger-missing: 런 원장이 없습니다 (runId=${runId}) — 새 원장을 만들지 않습니다`);
535
557
  }
536
558
  let shadowRxIndex = -1;
537
559
  for (let index = 0; index < entries.length; index++) {
@@ -539,7 +561,7 @@ export function recordDoctorComparison(input: RecordDoctorComparisonInput): Doct
539
561
  if (entry.event === 'doctor-rx' && entry.data.shadow === true) shadowRxIndex = index;
540
562
  }
541
563
  if (shadowRxIndex < 0) {
542
- throw new Error(`shadow-rx-missing: 이 runId 의 shadow doctor-rx 가 없습니다 (runId=${runId}) — shadow 결과를 지어내지 않습니다`);
564
+ throw new DoctorComparisonFailureError('shadow-rx-missing', `shadow-rx-missing: 이 runId 의 shadow doctor-rx 가 없습니다 (runId=${runId}) — shadow 결과를 지어내지 않습니다`);
543
565
  }
544
566
  const shadowRx = entries[shadowRxIndex]!;
545
567
  const rx = typeof shadowRx.data.rx === 'string' ? shadowRx.data.rx : null;
@@ -547,17 +569,17 @@ export function recordDoctorComparison(input: RecordDoctorComparisonInput): Doct
547
569
  const visitIndex = typeof shadowRx.data.visitIndex === 'number' ? shadowRx.data.visitIndex : -1;
548
570
  const visit = visitIndex >= 0 && visitIndex < entries.length ? entries[visitIndex] : undefined;
549
571
  if (visit === undefined || visit.event !== 'doctor-visit' || visit.runId !== runId) {
550
- throw new Error(`visit-missing: shadow doctor-rx 가 가리키는 doctor-visit 행이 없습니다 (runId=${runId}, visitIndex=${visitIndex})`);
572
+ throw new DoctorComparisonFailureError('visit-missing', `visit-missing: shadow doctor-rx 가 가리키는 doctor-visit 행이 없습니다 (runId=${runId}, visitIndex=${visitIndex})`);
551
573
  }
552
574
  const existing = entries.find((entry) => entry.event === 'doctor-compare' && entry.data.shadowRxIndex === shadowRxIndex);
553
575
  if (existing !== undefined) {
554
576
  const stored = existing.data.opJudgment as { timestamp?: unknown; result?: unknown };
555
577
  if (typeof stored?.timestamp !== 'string' || stored.timestamp.length === 0
556
578
  || typeof stored?.result !== 'string' || stored.result.length === 0) {
557
- throw new Error(`comparison-corrupt: 이미 기록된 doctor-compare 의 저장 판단이 손상됐습니다 (runId=${runId}, shadowRxIndex=${shadowRxIndex}, stored=${JSON.stringify(stored)}) — 거짓 already-recorded 를 승인하지 않습니다`);
579
+ throw new DoctorComparisonFailureError('comparison-corrupt', `comparison-corrupt: 이미 기록된 doctor-compare 의 저장 판단이 손상됐습니다 (runId=${runId}, shadowRxIndex=${shadowRxIndex}, stored=${JSON.stringify(stored)}) — 거짓 already-recorded 를 승인하지 않습니다`);
558
580
  }
559
581
  if (stored.timestamp !== judgment.timestamp || stored.result !== judgment.result) {
560
- throw new Error(`comparison-conflict: 이미 기록된 doctor-compare 와 손판정이 다릅니다 (runId=${runId}, shadowRxIndex=${shadowRxIndex}, stored=${JSON.stringify(stored)}, received=${JSON.stringify(judgment)}) — 기존 행을 유지합니다`);
582
+ throw new DoctorComparisonFailureError('comparison-conflict', `comparison-conflict: 이미 기록된 doctor-compare 와 손판정이 다릅니다 (runId=${runId}, shadowRxIndex=${shadowRxIndex}, stored=${JSON.stringify(stored)}, received=${JSON.stringify(judgment)}) — 기존 행을 유지합니다`);
561
583
  }
562
584
  return { append: false as const, result: { status: 'already-recorded' as const, visitIndex, shadowRxIndex, rx, outcome: shadowOutcome, opResult: judgment.result } };
563
585
  }
@@ -579,7 +601,7 @@ export function recordDoctorComparison(input: RecordDoctorComparisonInput): Doct
579
601
  return outcome.result;
580
602
  }
581
603
  if (holder.recorded === undefined) {
582
- throw new Error(`run-ledger-missing: 런 원장이 없습니다 (runId=${runId}) — 새 원장을 만들지 않습니다`);
604
+ throw new DoctorComparisonFailureError('run-ledger-missing', `run-ledger-missing: 런 원장이 없습니다 (runId=${runId}) — 새 원장을 만들지 않습니다`);
583
605
  }
584
606
  const record = holder.recorded;
585
607
  debug.log('run-doctor', 'compare', { runId, visitIndex: record.visitIndex, shadowRxIndex: record.shadowRxIndex, opResult: judgment.result, executed: false });
@@ -17,6 +17,9 @@ import { debug } from '../debug/log.js';
17
17
  * 같은 값인지는 elanous-tui-spawn-identity.test.ts 가 잡는다. */
18
18
  export const PREAMBLE_SYNC_BLOCK_ENV = 'ELANOUS_TEST_PREAMBLE_SYNC_BLOCK_MS';
19
19
 
20
+ /** Bare held TUI startup includes Nexus/test-universe initialization; 30s is below observed cold-start latency. */
21
+ export const DEFAULT_TUI_TEST_READY_TIMEOUT_MS = 180_000;
22
+
20
23
  export interface ElanousTuiSpawnOptions {
21
24
  readonly repoRoot: string;
22
25
  readonly cwd: string;
@@ -0,0 +1,2 @@
1
+ ⏺ Bash({\"command\":\"bun test -- 'src/ux-sim/service-key-setup.test.ts'\",\"timeout\":120000,\"sandbox\":\"off\",\"network\":\"inherit\"})
2
+ ↳ bun test v1.4.2 (744846f84) --- stderr --- 2 pass 0 fail 32 expect() calls Ran 2 tests across 1 file. [1099.00ms]