elanous 0.2.40 → 0.2.41

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 (558) hide show
  1. package/README.md +7 -7
  2. package/apps/pwa/out/404/index.html +1 -1
  3. package/apps/pwa/out/404.html +1 -1
  4. package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → GiOLWmt4MqDZePubBjA4Q}/_buildManifest.js +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +149 -0
  6. package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +36 -0
  7. package/apps/pwa/out/_next/static/chunks/{9184.45afbf44fec87574.js → 1178.1aa9cad0e7695427.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/{2829-734fe8bf2eee7347.js → 1197-54da59d250a6e476.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/{6749.0744ce6eb08d40e9.js → 1219.7e17964e0e7cd8e5.js} +3 -3
  10. package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +287 -0
  11. package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +90 -0
  16. package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1765.679b29625c8e88d4.js +77 -0
  18. package/apps/pwa/out/_next/static/chunks/{2226.2cf61ec781827219.js → 1800.f7ff51dc4978a958.js} +2 -2
  19. package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{9175.2de5209a5ce6f68a.js → 2073.689dcb2680113d76.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{5383.bdfa5d886e39a826.js → 2263.e09b6edea33bad2d.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{9069.657590a84afb8fac.js → 2743.5d3f76948be32b34.js} +2 -2
  31. package/apps/pwa/out/_next/static/chunks/{6624.981ef7caeb680560.js → 2773.0e80b9d325fb5635.js} +2 -2
  32. package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{4864a2ca.1c1c280a7772c5e5.js → 2fdf2931.b431eee4fb468bc3.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/{9189505a.980427ac048c8c60.js → 2fe2c302.41b517f88d6fe502.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/{9992.07ce73c10bd5e6a1.js → 3097.864e92bdaa2f4d15.js} +2 -2
  36. package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3230-49298c3b73ef2268.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +74 -0
  41. package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{b84cad00.594027ebe0531fe2.js → 385e4574.e9886ab32759eda3.js} +3 -3
  46. package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4133.2056bb4d78f621af.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/{8086.1ab9103c41be884f.js → 4156.ba4de4a3664f04b4.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +148 -0
  53. package/apps/pwa/out/_next/static/chunks/{1281.d81877e35b9068f4.js → 4527.a69f2894d1bc9f4a.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +226 -0
  55. package/apps/pwa/out/_next/static/chunks/{8357.1aaa713b052a78b1.js → 4667.97e31aa38c95c475.js} +4 -4
  56. package/apps/pwa/out/_next/static/chunks/{5436.fdf6fa8ae3e9588d.js → 4702.4a4adc1f16d7c93b.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +94 -0
  64. package/apps/pwa/out/_next/static/chunks/{4769.9fd582071301f382.js → 5159.115f1c2ca471386c.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/530.d26346e18089640a.js +115 -0
  67. package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +8 -0
  68. package/apps/pwa/out/_next/static/chunks/{d8de0de2-dd0f4ac8e5ab1832.js → 53aeb4ee-51c92f8d683f5220.js} +1 -1
  69. package/apps/pwa/out/_next/static/chunks/{6257.c0037b8949239f5e.js → 5471.1e611302ed3a7c53.js} +2 -2
  70. package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/{2566.beaffc3a5e1fcd2e.js → 5574.f35accf4f132b29d.js} +1 -1
  73. package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +24 -0
  74. package/apps/pwa/out/_next/static/chunks/{2066.a77257c8c350770a.js → 5744.b9415e18ad623100.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/5892.2526d962339662d8.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/{4351.0f37a6db2b34d50b.js → 5937.c2df9e3447e1f667.js} +1 -1
  77. package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +286 -0
  78. package/apps/pwa/out/_next/static/chunks/{6051-0ae955eedb10adb9.js → 5947-135e26537d80a6b9.js} +3 -3
  79. package/apps/pwa/out/_next/static/chunks/{3746-f80a78f220bf37b5.js → 5964-7e21164a8f2cf0ce.js} +1 -1
  80. package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +27 -0
  84. package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +62 -0
  86. package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +24 -0
  87. package/apps/pwa/out/_next/static/chunks/{2047.8f23e210995d4548.js → 6874.d5cf7eb8edb2cabe.js} +2 -2
  88. package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +122 -0
  90. package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7191.fdc955f7d96064a4.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{8272-025653884f9645d2.js → 8050-9b364bdef8f71927.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/83184dcd-0ee6247ff41eb3f2.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +104 -0
  103. package/apps/pwa/out/_next/static/chunks/{2281-b8cede695c6c650e.js → 8464-e24f10451b658aac.js} +1 -1
  104. package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/{5622.94893f5aea7185d0.js → 8880.64c445592f04acaf.js} +1 -1
  108. package/apps/pwa/out/_next/static/chunks/{1452.162bb2d9d699e82a.js → 8981.c706964c8ba27aff.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{470.51a72a2348306455.js → 9048.212083de42d25be3.js} +2 -2
  110. package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{2177.df8547f9d7215c4e.js → 9507.7026657a2f47eb64.js} +16 -16
  117. package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +93 -0
  118. package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{7515.1ad6efe157fa4448.js → 9579.4a8169600fff2058.js} +1 -1
  120. package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +34 -0
  123. package/apps/pwa/out/_next/static/chunks/{2499.02fbfd18126c10c0.js → 9834.63ab2bbc3153172e.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/9869.81a1e24ca682d5a0.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/{409c787b.e48c5bec8ec10456.js → a0a01613.6d1cca322238d7fe.js} +1 -1
  126. package/apps/pwa/out/_next/static/chunks/{6cc1d1d6.9a98dd4622f1afc6.js → addc2b32.8c4ff8f0aefe987d.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-ba957ff875a026a0.js → page-14949db884bfa672.js} +1 -1
  132. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-40f9e19149024298.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a142dfb0331a05f5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/{c696986b.5dc8bb1143af16d1.js → b2271e54.c1de3347976e90b0.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/{ca3702f8.2913182e73889fa2.js → c0c1a699.0ba79f97005965d4.js} +1 -1
  180. package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +1 -0
  185. package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +1 -0
  186. package/apps/pwa/out/approvals/index.html +1 -1
  187. package/apps/pwa/out/approvals/index.txt +22 -22
  188. package/apps/pwa/out/autopilot/index.html +1 -1
  189. package/apps/pwa/out/autopilot/index.txt +22 -22
  190. package/apps/pwa/out/board/index.html +1 -1
  191. package/apps/pwa/out/board/index.txt +22 -22
  192. package/apps/pwa/out/botlab/index.html +1 -1
  193. package/apps/pwa/out/botlab/index.txt +21 -21
  194. package/apps/pwa/out/bots/index.html +1 -1
  195. package/apps/pwa/out/bots/index.txt +21 -21
  196. package/apps/pwa/out/ceo/index.html +1 -1
  197. package/apps/pwa/out/ceo/index.txt +22 -22
  198. package/apps/pwa/out/chat/index.html +1 -1
  199. package/apps/pwa/out/chat/index.txt +21 -21
  200. package/apps/pwa/out/consult/index.html +1 -1
  201. package/apps/pwa/out/consult/index.txt +22 -22
  202. package/apps/pwa/out/control/index.html +1 -1
  203. package/apps/pwa/out/control/index.txt +22 -22
  204. package/apps/pwa/out/decisions/index.html +1 -1
  205. package/apps/pwa/out/decisions/index.txt +21 -21
  206. package/apps/pwa/out/design-check/index.html +1 -1
  207. package/apps/pwa/out/design-check/index.txt +22 -22
  208. package/apps/pwa/out/editor/index.html +1 -1
  209. package/apps/pwa/out/editor/index.txt +22 -22
  210. package/apps/pwa/out/exec/index.html +1 -1
  211. package/apps/pwa/out/exec/index.txt +22 -22
  212. package/apps/pwa/out/field/index.html +1 -1
  213. package/apps/pwa/out/field/index.txt +22 -22
  214. package/apps/pwa/out/healthz +1 -1
  215. package/apps/pwa/out/index.html +1 -1
  216. package/apps/pwa/out/index.txt +21 -21
  217. package/apps/pwa/out/inside/index.html +1 -1
  218. package/apps/pwa/out/inside/index.txt +21 -21
  219. package/apps/pwa/out/intake/index.html +1 -1
  220. package/apps/pwa/out/intake/index.txt +22 -22
  221. package/apps/pwa/out/live/index.html +1 -1
  222. package/apps/pwa/out/live/index.txt +22 -22
  223. package/apps/pwa/out/live-run/index.html +1 -1
  224. package/apps/pwa/out/live-run/index.txt +22 -22
  225. package/apps/pwa/out/loops/index.html +1 -1
  226. package/apps/pwa/out/loops/index.txt +21 -21
  227. package/apps/pwa/out/market/index.html +1 -1
  228. package/apps/pwa/out/market/index.txt +21 -21
  229. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  230. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  231. package/apps/pwa/out/morning/index.html +1 -1
  232. package/apps/pwa/out/morning/index.txt +22 -22
  233. package/apps/pwa/out/observatory/index.html +1 -1
  234. package/apps/pwa/out/observatory/index.txt +22 -22
  235. package/apps/pwa/out/ops/checklist/index.html +1 -1
  236. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  237. package/apps/pwa/out/ops/release/index.html +1 -1
  238. package/apps/pwa/out/ops/release/index.txt +21 -21
  239. package/apps/pwa/out/ops/seats/index.html +1 -1
  240. package/apps/pwa/out/ops/seats/index.txt +21 -21
  241. package/apps/pwa/out/outputs/index.html +1 -1
  242. package/apps/pwa/out/outputs/index.txt +21 -21
  243. package/apps/pwa/out/reflection/index.html +1 -1
  244. package/apps/pwa/out/reflection/index.txt +22 -22
  245. package/apps/pwa/out/scheduler/index.html +1 -1
  246. package/apps/pwa/out/scheduler/index.txt +22 -22
  247. package/apps/pwa/out/sessions/index.html +1 -1
  248. package/apps/pwa/out/sessions/index.txt +21 -21
  249. package/apps/pwa/out/settings/devices/index.html +1 -1
  250. package/apps/pwa/out/settings/devices/index.txt +22 -22
  251. package/apps/pwa/out/settings/index.html +1 -1
  252. package/apps/pwa/out/settings/index.txt +22 -22
  253. package/apps/pwa/out/setup/done/index.html +1 -1
  254. package/apps/pwa/out/setup/done/index.txt +22 -22
  255. package/apps/pwa/out/setup/index.html +1 -1
  256. package/apps/pwa/out/setup/index.txt +22 -22
  257. package/apps/pwa/out/share/index.html +1 -1
  258. package/apps/pwa/out/share/index.txt +22 -22
  259. package/apps/pwa/out/showroom/index.html +1 -1
  260. package/apps/pwa/out/showroom/index.txt +21 -21
  261. package/apps/pwa/out/tasks/index.html +1 -1
  262. package/apps/pwa/out/tasks/index.txt +22 -22
  263. package/apps/pwa/out/term/index.html +1 -1
  264. package/apps/pwa/out/term/index.txt +22 -22
  265. package/apps/pwa/out/today/index.html +1 -1
  266. package/apps/pwa/out/today/index.txt +22 -22
  267. package/apps/pwa/out/trace/index.html +1 -1
  268. package/apps/pwa/out/trace/index.txt +22 -22
  269. package/apps/pwa/out/vault/index.html +1 -1
  270. package/apps/pwa/out/vault/index.txt +22 -22
  271. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  272. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  273. package/apps/pwa/out/workflows/index.html +1 -1
  274. package/apps/pwa/out/workflows/index.txt +22 -22
  275. package/apps/pwa/out/workspace/index.html +1 -1
  276. package/apps/pwa/out/workspace/index.txt +22 -22
  277. package/apps/pwa/out/worktrees/index.html +1 -1
  278. package/apps/pwa/out/worktrees/index.txt +22 -22
  279. package/bin/elanous.mjs +6 -1
  280. package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
  281. package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
  282. package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
  283. package/graphs/demo/persona-teacher/recipes.yaml +17 -0
  284. package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
  285. package/graphs/overlays/stop-heal-ladder.yaml +23 -2
  286. package/graphs/release/release-loop.yaml +3 -1
  287. package/graphs/units/gate/gate.yaml +20 -0
  288. package/graphs/units/git/git.yaml +26 -0
  289. package/graphs/units/implement/implement.yaml +19 -0
  290. package/graphs/units/landing/landing.yaml +18 -0
  291. package/graphs/units/review/review.yaml +20 -0
  292. package/graphs/units/verbs/recipes.yaml +3 -0
  293. package/graphs/units/verbs/research.yaml +20 -0
  294. package/graphs/work/research-report.yaml +11 -1
  295. package/package.json +1 -1
  296. package/scripts/disk-steward.ts +46 -0
  297. package/scripts/fleet/node-setup.sh +50 -0
  298. package/scripts/graph-units/verbs/research.ts +55 -0
  299. package/scripts/llm-cost-ledger.ts +179 -8
  300. package/scripts/measure-nl-routing-corpus.ts +10 -2
  301. package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
  302. package/scripts/public-copy-lint.ts +163 -19
  303. package/scripts/ratchets/train-side-invariants.sh +0 -1
  304. package/scripts/release-loop/gate-autoheal.ts +117 -0
  305. package/scripts/release-loop/gate-baseline-receipt.ts +8 -1
  306. package/scripts/release-loop/gate-diff.ts +22 -3
  307. package/scripts/release-loop/gate-node.ts +205 -17
  308. package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
  309. package/scripts/release-loop/gate-triage-node.ts +70 -10
  310. package/scripts/release-loop/resume-release.ts +247 -15
  311. package/scripts/release-loop/traffic-node.ts +6 -3
  312. package/scripts/release-loop/unattended-release.ts +4 -2
  313. package/scripts/shadow-authoring-probe.ts +20 -0
  314. package/scripts/ux-sim.ts +19 -2
  315. package/src/acp/core-turn-bridge.ts +86 -4
  316. package/src/agent-substrate/self-review-cli.ts +91 -29
  317. package/src/auto-research/research-turn.ts +10 -1
  318. package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
  319. package/src/boot/daemon-tools/self-implement.ts +46 -9
  320. package/src/budget/shadow-arms.ts +52 -0
  321. package/src/chat/pickers/state.ts +7 -1
  322. package/src/cli/log-event-names.ts +5 -0
  323. package/src/cli/mcp-login.ts +8 -18
  324. package/src/cli/msg-cli.ts +57 -1
  325. package/src/cli/pr-land-heavy-remote.ts +15 -9
  326. package/src/cli/release-cli.ts +27 -1
  327. package/src/cli/sim-cli.ts +7 -1
  328. package/src/cli/tasks-cli.ts +5 -4
  329. package/src/codex/models.ts +30 -15
  330. package/src/core-turn/run-core-turn.ts +3 -0
  331. package/src/core-turn/run-goal-loop.ts +88 -2
  332. package/src/dashboard/acp-boot.ts +72 -3
  333. package/src/dashboard/index.ts +6 -0
  334. package/src/dashboard/turn-preamble.ts +12 -1
  335. package/src/disk-steward/judge.ts +73 -0
  336. package/src/disk-steward/ledger.ts +122 -0
  337. package/src/disk-steward/steward.ts +373 -0
  338. package/src/domains/guardian-tick.ts +191 -2
  339. package/src/graph-runner/graph-cli.ts +21 -0
  340. package/src/graph-runner/in-process-registry.ts +37 -0
  341. package/src/graph-runner/runner.ts +33 -3
  342. package/src/grounding/ref-index.ts +19 -0
  343. package/src/grounding/sources-cli.ts +9 -1
  344. package/src/harness/harness-cli-command.ts +267 -14
  345. package/src/harness/harness-incidents.ts +312 -7
  346. package/src/harness/harness-space.ts +15 -1
  347. package/src/harness/progress-worker-entry.ts +59 -0
  348. package/src/harness/progress-worker-runtime.ts +11 -0
  349. package/src/index.ts +18 -2
  350. package/src/instance/dev-project.ts +25 -0
  351. package/src/intelligence-map/model-alias.ts +6 -5
  352. package/src/intelligence-map/model-catalog.ts +59 -2
  353. package/src/llm/model-defaults.ts +4 -4
  354. package/src/llm.ts +42 -11
  355. package/src/loops/orchestrator/tick.ts +48 -0
  356. package/src/mcp/mcp-oauth.ts +3 -1
  357. package/src/model-tier/llm-tier-map.ts +9 -9
  358. package/src/model-tier/turn-tier.ts +1 -1
  359. package/src/msg/msg-mirror-github.ts +80 -0
  360. package/src/msg/msg-mirror-policy.ts +61 -0
  361. package/src/msg/msg-mirror-runner.ts +219 -0
  362. package/src/msg/msg-mirror-state.ts +33 -0
  363. package/src/msg/msg-store.ts +11 -0
  364. package/src/output-truncation.ts +41 -12
  365. package/src/project/project-store.ts +48 -1
  366. package/src/release-loop/gate-host-reservation.ts +144 -0
  367. package/src/release-loop/release-schedule.ts +90 -1
  368. package/src/research/bloom-exemplars.ts +135 -0
  369. package/src/self-dev/ask-launch-flow.ts +39 -25
  370. package/src/self-dev/dev-cli.ts +17 -17
  371. package/src/self-dev/graph-front-nodes.ts +23 -0
  372. package/src/self-dev/launch-preflight.ts +9 -4
  373. package/src/self-dev/orchestrate.ts +15 -0
  374. package/src/self-dev/run-supervisor.ts +185 -3
  375. package/src/self-dev/run-types.ts +3 -0
  376. package/src/self-implement/gate-artifacts.ts +13 -0
  377. package/src/self-implement/gate-cli.ts +54 -24
  378. package/src/self-implement/gate-remote.ts +23 -5
  379. package/src/self-implement/goal-author-clarification.ts +31 -12
  380. package/src/self-implement/goal-author.ts +77 -5
  381. package/src/self-implement/graph-stage-units.ts +172 -0
  382. package/src/self-implement/graph-templates.ts +162 -1
  383. package/src/self-implement/graph-variant.ts +37 -4
  384. package/src/self-implement/host-regate.ts +4 -4
  385. package/src/self-implement/knowhow-pack.ts +38 -0
  386. package/src/self-implement/orchestrator.ts +235 -21
  387. package/src/self-implement/run-ledger.ts +64 -6
  388. package/src/self-implement/run-stop.ts +21 -2
  389. package/src/self-implement/running-runs.ts +35 -12
  390. package/src/self-implement/self-implement-cli.ts +36 -4
  391. package/src/self-implement/stop-autoheal-operational.ts +43 -0
  392. package/src/self-implement/stop-autoheal.ts +15 -6
  393. package/src/session/chat.ts +31 -54
  394. package/src/session/request-size-guard.ts +123 -0
  395. package/src/sidetab-core/model.ts +136 -0
  396. package/src/task-agent/parent-host.ts +14 -1
  397. package/src/task-agent/task-hand.ts +4 -1
  398. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +43 -0
  399. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
  400. package/src/task-orchestrator/surfaces/self-implement-pod.ts +116 -16
  401. package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
  402. package/src/tui/entry.ts +10 -3
  403. package/src/tui/sidetab/list.ts +45 -0
  404. package/src/tui/sidetab/nl-tool.ts +2 -136
  405. package/src/tui/sidetab/peek.ts +52 -0
  406. package/src/tui-client/dashboard-session.ts +3 -0
  407. package/src/user-config.ts +11 -5
  408. package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
  409. package/src/ux-sim/fault-pod-child-result.ts +42 -0
  410. package/src/ux-sim/release-sim-rig.ts +262 -0
  411. package/src/ux-sim/seminar-rehearsal.ts +109 -0
  412. package/src/ux-sim/subagent-tools-device.ts +2 -2
  413. package/src/version/packed-revision.json +1 -1
  414. package/apps/pwa/out/_next/static/chunks/1060.014f1f01a17aec26.js +0 -115
  415. package/apps/pwa/out/_next/static/chunks/1350.59f40e39e02d91b1.js +0 -1
  416. package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +0 -1
  417. package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +0 -286
  418. package/apps/pwa/out/_next/static/chunks/1537-6bb97b5214928ea9.js +0 -1
  419. package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +0 -149
  420. package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +0 -1
  421. package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +0 -90
  422. package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +0 -104
  423. package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +0 -1
  424. package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +0 -1
  425. package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +0 -1
  426. package/apps/pwa/out/_next/static/chunks/2522.f2766b76d22c8bdf.js +0 -34
  427. package/apps/pwa/out/_next/static/chunks/261.0d471e8aded799f3.js +0 -226
  428. package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +0 -1
  429. package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +0 -1
  430. package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +0 -27
  431. package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +0 -1
  432. package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +0 -1
  433. package/apps/pwa/out/_next/static/chunks/2774-719820e3f5b2a3eb.js +0 -1
  434. package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +0 -1
  435. package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +0 -1
  436. package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +0 -1
  437. package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +0 -1
  438. package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +0 -1
  439. package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +0 -1
  440. package/apps/pwa/out/_next/static/chunks/3330.7443183b7e6fdbdf.js +0 -1
  441. package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +0 -1
  442. package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +0 -1
  443. package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +0 -24
  444. package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +0 -77
  445. package/apps/pwa/out/_next/static/chunks/3b355b3d.6f73c98bf6f9c749.js +0 -122
  446. package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +0 -36
  447. package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +0 -1
  448. package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +0 -1
  449. package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +0 -287
  450. package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +0 -1
  451. package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +0 -1
  452. package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +0 -1
  453. package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +0 -1
  454. package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +0 -1
  455. package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +0 -1
  456. package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +0 -74
  457. package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +0 -1
  458. package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +0 -1
  459. package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +0 -1
  460. package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +0 -8
  461. package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +0 -62
  463. package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +0 -1
  465. package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +0 -1
  466. package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +0 -94
  467. package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +0 -1
  468. package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +0 -1
  472. package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +0 -148
  477. package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +0 -1
  479. package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/7219-15bdd9a80661af8e.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +0 -93
  482. package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +0 -24
  485. package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/7611.85f045bf232053ac.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/8099.1cccf31c1baa7e1c.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +0 -1
  492. package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/8d173e38.18a2f7b4e1848bdb.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/app/live/page-4edb8df90f4537ce.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83d27757e2b8060a.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/app/morning/page-fca2e59a81744d9e.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/app/term/page-139d722de1dcd6c1.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/app/workspace/page-ccde99f07aaf71f7.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +0 -1
  557. package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
  558. /package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → GiOLWmt4MqDZePubBjA4Q}/_ssgManifest.js +0 -0
@@ -1,10 +1,12 @@
1
1
  import { Database } from 'bun:sqlite';
2
+ import { createHash } from 'node:crypto';
2
3
  import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync } from 'node:fs';
3
4
  import { join } from 'node:path';
4
5
  import { redactSecretText } from '../debug/log.js';
5
6
  import { refuseProductionLedgerWriteInTest } from './ledger-write-guard.js';
6
7
  import type { PodChildEvidence } from '../task-orchestrator/surfaces/self-implement.js';
7
8
  import { parsePodTermination, type PodTermination } from '../task-orchestrator/surfaces/pod-failure-reason.js';
9
+ import { loadRunLedger, runLedgerDir, type RunLedgerEntry } from '../self-implement/run-ledger.js';
8
10
 
9
11
  export interface RunExit {
10
12
  runId: string;
@@ -21,6 +23,21 @@ export interface RunExit {
21
23
  childEvidence?: PodChildEvidence;
22
24
  /** JOB-FAILURE-TERMINATION-CAPTURE — the current attempt's Job/Pod termination facts, captured before GC. */
23
25
  podTermination?: PodTermination;
26
+ /** Current Pod attempt + bounded child output + container exit + parent verdict, joined under this runId. */
27
+ terminalEvidence?: {
28
+ job: string;
29
+ childRunId: string;
30
+ attempt: number | 'unknown';
31
+ childOutputTail: string[] | 'unknown';
32
+ containerExitCode: number | 'unknown';
33
+ parentVerdict: string;
34
+ failureClassification: string | 'unknown';
35
+ terminationReason: string | 'unknown';
36
+ childFailureStage: string | 'unknown';
37
+ childRunStatus: { stage: string | 'unknown'; status: string | 'unknown'; failureKind: string | 'unknown' };
38
+ shardIdentityReadFailure: string | 'none' | 'unknown';
39
+ providerFailure: 'credential-not-configured' | 'provider-failed' | 'none' | 'unknown';
40
+ };
24
41
  /** INCIDENT-REASON-FROM-LASTLINES — 기록된 reason 이 unknown 이라 lastLines 로 다시 분류했으면 원래 값. */
25
42
  recordedReason?: string;
26
43
  /** reason 을 어디서 얻었나 — 'lastLines' 면 위 분류 규칙으로 정했다(기록 원문은 recordedReason). */
@@ -40,12 +57,132 @@ export interface IncidentBurst {
40
57
  hostname?: string;
41
58
  }
42
59
 
60
+ export type TcellHealthClass = 'healthy' | 'slow' | 'stalled' | 'infected' | 'zombie';
61
+
62
+ /** A read-only health-card snapshot supplied to the guardian tick. Times are epoch milliseconds. */
63
+ export interface TcellHealthCard {
64
+ runId: string;
65
+ stage: string;
66
+ startedAt: number;
67
+ progressAt: number | null;
68
+ stageBudgetMs: number;
69
+ heartbeatAt: number | null;
70
+ parentPresent: boolean;
71
+ leaseExpiresAt: number | null;
72
+ riskSignal: boolean;
73
+ stopClass?: string;
74
+ site?: string;
75
+ /** Stable signature tail, already bounded by the producer. Raw log tails are not accepted here. */
76
+ signatureTail?: string;
77
+ /** Deliberately excluded from cause grouping. */
78
+ hostname?: string;
79
+ }
80
+
81
+ export interface TcellHealthDecision {
82
+ runId: string;
83
+ stage: string;
84
+ classification: TcellHealthClass;
85
+ reason: 'heartbeat-missing' | 'parent-missing' | 'lease-expired' | 'risk-signal' | 'cause-quorum' | 'no-progress-30m' | 'over-stage-budget' | 'within-stage-budget';
86
+ causeGroupId?: string;
87
+ causeGroupSize?: number;
88
+ }
89
+
90
+ export interface TcellHealthClassification {
91
+ total: number;
92
+ measured: number;
93
+ unmeasuredRunIds: string[];
94
+ counts: Record<TcellHealthClass, number>;
95
+ decisions: TcellHealthDecision[];
96
+ }
97
+
98
+ const TCELL_STALLED_AFTER_MS = 30 * 60_000;
99
+ const TCELL_CAUSE_QUORUM = 3;
100
+
101
+ function tcellCauseGroupId(card: TcellHealthCard): string | undefined {
102
+ const stopClass = card.stopClass?.trim();
103
+ const site = card.site?.trim();
104
+ const signatureTail = card.signatureTail?.trim();
105
+ if (!stopClass || !site || !signatureTail) return undefined;
106
+ // Hash the exact stop.class + site + signature-tail tuple. Host is deliberately absent.
107
+ return createHash('sha256').update(JSON.stringify([stopClass, site, signatureTail])).digest('hex').slice(0, 16);
108
+ }
109
+
110
+ /** Pure shadow classification. Invalid/incomplete cards are reported as unmeasured, never as healthy or zombie. */
111
+ export function classifyTcellHealthCards(cards: readonly TcellHealthCard[], now: number): TcellHealthClassification {
112
+ if (!Number.isFinite(now)) throw new RangeError('invalid T-cell patrol time');
113
+ const valid: TcellHealthCard[] = [];
114
+ const unmeasuredRunIds: string[] = [];
115
+ const seen = new Set<string>();
116
+ for (const card of cards) {
117
+ const measured = typeof card.runId === 'string' && !!card.runId.trim() && !seen.has(card.runId)
118
+ && typeof card.stage === 'string' && !!card.stage.trim()
119
+ && Number.isFinite(card.startedAt) && card.startedAt <= now
120
+ && (card.progressAt === null || (Number.isFinite(card.progressAt) && card.progressAt <= now))
121
+ && Number.isFinite(card.stageBudgetMs) && card.stageBudgetMs > 0
122
+ && (card.heartbeatAt === null || (Number.isFinite(card.heartbeatAt) && card.heartbeatAt <= now))
123
+ && typeof card.parentPresent === 'boolean'
124
+ && (card.leaseExpiresAt === null || Number.isFinite(card.leaseExpiresAt))
125
+ && typeof card.riskSignal === 'boolean';
126
+ if (!measured) {
127
+ if (typeof card.runId === 'string' && card.runId.trim()) unmeasuredRunIds.push(card.runId);
128
+ continue;
129
+ }
130
+ seen.add(card.runId);
131
+ valid.push(card);
132
+ }
133
+
134
+ const groups = new Map<string, Set<string>>();
135
+ for (const card of valid) {
136
+ const groupId = tcellCauseGroupId(card);
137
+ if (!groupId) continue;
138
+ const members = groups.get(groupId) ?? new Set<string>();
139
+ members.add(card.runId);
140
+ groups.set(groupId, members);
141
+ }
142
+
143
+ const counts: Record<TcellHealthClass, number> = { healthy: 0, slow: 0, stalled: 0, infected: 0, zombie: 0 };
144
+ const decisions = valid.map((card): TcellHealthDecision => {
145
+ const causeGroupId = tcellCauseGroupId(card);
146
+ const causeGroupSize = causeGroupId ? groups.get(causeGroupId)?.size : undefined;
147
+ const progressAge = now - (card.progressAt ?? card.startedAt);
148
+ let classification: TcellHealthClass;
149
+ let reason: TcellHealthDecision['reason'];
150
+ if (card.heartbeatAt === null) { classification = 'zombie'; reason = 'heartbeat-missing'; }
151
+ else if (!card.parentPresent) { classification = 'zombie'; reason = 'parent-missing'; }
152
+ else if (card.leaseExpiresAt === null || card.leaseExpiresAt <= now) { classification = 'zombie'; reason = 'lease-expired'; }
153
+ else if (card.riskSignal) { classification = 'infected'; reason = 'risk-signal'; }
154
+ else if ((causeGroupSize ?? 0) >= TCELL_CAUSE_QUORUM) { classification = 'infected'; reason = 'cause-quorum'; }
155
+ else if (progressAge >= TCELL_STALLED_AFTER_MS) { classification = 'stalled'; reason = 'no-progress-30m'; }
156
+ else if (progressAge > card.stageBudgetMs * 2) { classification = 'slow'; reason = 'over-stage-budget'; }
157
+ else { classification = 'healthy'; reason = 'within-stage-budget'; }
158
+ counts[classification] += 1;
159
+ return { runId: card.runId, stage: card.stage, classification, reason,
160
+ ...(causeGroupId ? { causeGroupId, causeGroupSize } : {}) };
161
+ });
162
+ return { total: cards.length, measured: valid.length, unmeasuredRunIds, counts, decisions };
163
+ }
164
+
43
165
  /** Scrub before bounding: a token crossing the 200-character boundary must not leak. */
44
166
  export function incidentLastLines(output: string): string[] {
45
167
  return output.split(/\r?\n/).filter((line) => line.trim().length > 0).slice(-3)
46
168
  .map((line) => redactSecretText(line).slice(0, 200));
47
169
  }
48
170
 
171
+ function safeChildEvidence(value: PodChildEvidence | undefined): PodChildEvidence | undefined {
172
+ if (!value) return undefined;
173
+ const safeText = (text: string): string => redactSecretText(text).slice(0, 200);
174
+ return {
175
+ ...value,
176
+ ...(typeof value.error === 'string' ? { error: safeText(value.error) } : {}),
177
+ ...(typeof value.detail === 'string' ? { detail: safeText(value.detail) } : {}),
178
+ ...(typeof value.stderr === 'string' ? { stderr: safeText(value.stderr) } : {}),
179
+ ...(typeof value.podLogUnavailable === 'string' ? { podLogUnavailable: safeText(value.podLogUnavailable) } : {}),
180
+ ...(Array.isArray(value.podLogTail) ? { podLogTail: value.podLogTail.slice(-3).map(safeText) } : {}),
181
+ ...(value.prFailure && typeof value.prFailure.errorTail === 'string'
182
+ ? { prFailure: { ...value.prFailure, errorTail: safeText(value.prFailure.errorTail) } } : {}),
183
+ };
184
+ }
185
+
49
186
  const KST_OFFSET_MS = 9 * 60 * 60_000;
50
187
  const INCIDENT_FILE = /^\d{4}-\d{2}-\d{2}\.jsonl$/;
51
188
 
@@ -55,9 +192,9 @@ function kstDate(at: number): string {
55
192
 
56
193
  // ── INCIDENT-REASON-FROM-LASTLINES (0.2.36 · 10-22 · OP 대응 피처) ───────────────────────────────
57
194
  // 기록된 reason 이 «unknown» 인데 마지막 출력 줄에 사유가 그대로 있는 사고가 다수(10-22 경보) — 읽는 쪽에서
58
- // 결정론으로 다시 분류한다. 우선순위 = 더 구체적인 종료 사유 먼저. 아무것도 안 맞으면 unknown 그대로(추측 0).
195
+ // 결정론으로 다시 분류한다. 꼬리 전체에서 서로 다른 사유가 «정확히 하나» 일 때만 그 사유를 쓰고,
196
+ // 0개(무증거)나 2개 이상(충돌)이면 unknown 그대로 둔다(추측 0). 표 순서는 «첫 매치 우선순위»가 아니다.
59
197
  const LAST_LINE_REASONS: ReadonlyArray<[RegExp, string]> = [
60
- // 근본 원인 먼저 — 뒤 조각의 DEPENDENCY_NEEDS_HUMAN 은 앞 조각 실패의 «증상»이라 맨 뒤 쪽.
61
198
  [/goal-elaboration needs-human:\s*goal-elaboration-ungrounded-path\b/, 'goal-elaboration-ungrounded-path'],
62
199
  [/goal-elaboration needs-human:\s*goal-elaboration-protected-path\b/, 'goal-elaboration-protected-path'],
63
200
  [/goal-elaboration needs-human:\s*goal-elaboration-scope-conflict\b/, 'goal-elaboration-scope-conflict'],
@@ -72,12 +209,28 @@ const LAST_LINE_REASONS: ReadonlyArray<[RegExp, string]> = [
72
209
  ];
73
210
  const DEVICE_SLICE_PATH = /src\/ux-sim\/[\w.-]*-device(?:\.test)?\.ts|DEVICE-FIRST/;
74
211
 
75
- /** lastLines 에서 종료 사유를 꺼낸다 — 안 맞으면 null(unknown 유지). */
212
+ // 한 사건을 두 이름으로 서술한 꼬리(상세 표지 ⊕ 일반 표지)는 충돌이 아니다 — 상세 표지가 일반 표지를 흡수한다.
213
+ // 서로 다른 사건을 말하는 표지끼리만 충돌이다(예: GOAL_DONE_BOUNDARY_MISSING ⊕ DEPENDENCY_NEEDS_HUMAN).
214
+ const REASON_ABSORBS: ReadonlyArray<readonly [string, readonly string[]]> = [
215
+ ['goal-elaboration-ungrounded-path', ['needs-human']],
216
+ ['goal-elaboration-protected-path', ['needs-human']],
217
+ ['goal-elaboration-scope-conflict', ['needs-human']],
218
+ ['goal-elaboration-fixed-layer-conflict', ['needs-human']],
219
+ ['goal-done-boundary-missing', ['needs-human']],
220
+ ['pod-backoff-limit', ['pod-job-failed']],
221
+ ['pod-child-no-result', ['pod-job-failed']],
222
+ ['dependency-needs-human', ['needs-human']],
223
+ ];
224
+
225
+ /** lastLines 에서 종료 사유를 꺼낸다 — 무증거·충돌이면 null(unknown 유지). */
76
226
  export function classifyIncidentReasonFromLastLines(lines: readonly string[] | undefined): string | null {
77
227
  if (!lines?.length) return null;
78
228
  const text = lines.join('\n');
79
- for (const [pattern, reason] of LAST_LINE_REASONS) if (pattern.test(text)) return reason;
80
- return null;
229
+ const matched = LAST_LINE_REASONS.filter(([pattern]) => pattern.test(text)).map(([, reason]) => reason);
230
+ const distinct = [...new Set(matched)].filter(
231
+ (reason) => !REASON_ABSORBS.some(([specific, absorbed]) => specific !== reason && matched.includes(specific) && absorbed.includes(reason)),
232
+ );
233
+ return distinct.length === 1 ? (distinct[0] ?? null) : null;
81
234
  }
82
235
 
83
236
  function refinedReasonFields(reason: string, lines: readonly string[] | undefined): Pick<RunExit, 'reason' | 'recordedReason' | 'reasonSource' | 'slice'> {
@@ -126,12 +279,54 @@ export function readRunExits(root: string): RunExit[] {
126
279
  ...(row.childEvidence && typeof row.childEvidence === 'object' && !Array.isArray(row.childEvidence)
127
280
  ? { childEvidence: row.childEvidence } : {}),
128
281
  ...podTerminationField(row.podTermination),
282
+ ...terminalEvidenceField(row.terminalEvidence),
129
283
  });
130
284
  }
131
285
  }
132
286
  return rows.sort((a, b) => Date.parse(a.at) - Date.parse(b.at) || a.runId.localeCompare(b.runId));
133
287
  }
134
288
 
289
+ function terminalEvidenceField(value: unknown): { terminalEvidence?: RunExit['terminalEvidence'] } {
290
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
291
+ const row = value as Record<string, unknown>;
292
+ const attempt = row.attempt;
293
+ const tail = row.childOutputTail;
294
+ const exitCode = row.containerExitCode;
295
+ if (typeof row.job !== 'string' || !row.job.trim() || typeof row.childRunId !== 'string' || !row.childRunId.trim()
296
+ || !(attempt === 'unknown' || (typeof attempt === 'number' && Number.isSafeInteger(attempt) && attempt > 0))
297
+ || !(tail === 'unknown' || (Array.isArray(tail) && tail.every((line) => typeof line === 'string')))
298
+ || !(exitCode === 'unknown' || (typeof exitCode === 'number' && Number.isSafeInteger(exitCode) && exitCode >= 0))
299
+ || typeof row.parentVerdict !== 'string'
300
+ || !(row.failureClassification === undefined || row.failureClassification === null || row.failureClassification === 'unknown' || typeof row.failureClassification === 'string')
301
+ || !(row.terminationReason === undefined || row.terminationReason === null || row.terminationReason === 'unknown' || typeof row.terminationReason === 'string')) return {};
302
+ const childOutputTail = tail === 'unknown' ? tail
303
+ : tail.slice(-3).map((line) => redactSecretText(line).slice(0, 200));
304
+ const failureClassification = row.failureClassification === undefined || row.failureClassification === null
305
+ ? 'unknown' : row.failureClassification === 'unknown' ? 'unknown' : redactSecretText(row.failureClassification).slice(0, 120);
306
+ const terminationReason = row.terminationReason === undefined || row.terminationReason === null
307
+ ? 'unknown' : row.terminationReason === 'unknown' ? 'unknown' : redactSecretText(row.terminationReason).slice(0, 200);
308
+ const childFailureStage = typeof row.childFailureStage === 'string' && row.childFailureStage.trim()
309
+ ? redactSecretText(row.childFailureStage).slice(0, 120) : 'unknown';
310
+ const childRunStatus = readChildRunStatus(row.childRunStatus);
311
+ const shardIdentityReadFailure = row.shardIdentityReadFailure === 'none' || row.shardIdentityReadFailure === 'unknown'
312
+ ? row.shardIdentityReadFailure
313
+ : typeof row.shardIdentityReadFailure === 'string' && row.shardIdentityReadFailure.trim()
314
+ ? redactSecretText(row.shardIdentityReadFailure).slice(0, 120) : 'unknown';
315
+ const providerFailure = row.providerFailure === 'credential-not-configured' || row.providerFailure === 'provider-failed'
316
+ || row.providerFailure === 'none' || row.providerFailure === 'unknown' ? row.providerFailure : 'unknown';
317
+ return { terminalEvidence: { job: row.job, childRunId: row.childRunId, attempt, childOutputTail,
318
+ containerExitCode: exitCode, parentVerdict: row.parentVerdict, failureClassification, terminationReason,
319
+ childFailureStage, childRunStatus, shardIdentityReadFailure, providerFailure } };
320
+ }
321
+
322
+ function readChildRunStatus(value: unknown): NonNullable<RunExit['terminalEvidence']>['childRunStatus'] {
323
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return { stage: 'unknown', status: 'unknown', failureKind: 'unknown' };
324
+ const row = value as Record<string, unknown>;
325
+ const safe = (field: unknown): string | 'unknown' => typeof field === 'string' && field.trim()
326
+ ? redactSecretText(field).slice(0, 120) : 'unknown';
327
+ return { stage: safe(row.stage), status: safe(row.status), failureKind: safe(row.failureKind) };
328
+ }
329
+
135
330
  function podTerminationField(value: unknown): { podTermination?: PodTermination } {
136
331
  const job = value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>).job : undefined;
137
332
  const parsed = typeof job === 'string' ? parsePodTermination(value, job) : undefined;
@@ -152,8 +347,12 @@ export function recordRunExit(row: RunExit, root: string): void {
152
347
  lock.exec('BEGIN IMMEDIATE');
153
348
  try {
154
349
  if (!readRunExits(root).some((record) => record.runId === row.runId)) {
155
- const safeRow = row.lastLines === undefined ? row : {
156
- ...row, lastLines: row.lastLines.slice(-3).map((line) => redactSecretText(line).slice(0, 200)),
350
+ const terminalEvidence = deriveTerminalEvidence(row, root);
351
+ const safeRow: RunExit = {
352
+ ...row,
353
+ ...(row.lastLines === undefined ? {} : { lastLines: row.lastLines.slice(-3).map((line) => redactSecretText(line).slice(0, 200)) }),
354
+ ...(row.childEvidence === undefined ? {} : { childEvidence: safeChildEvidence(row.childEvidence) }),
355
+ ...(terminalEvidence ? { terminalEvidence } : {}),
157
356
  };
158
357
  appendFileSync(join(dir, `${kstDate(at)}.jsonl`), `${JSON.stringify(safeRow)}\n`);
159
358
  }
@@ -167,6 +366,112 @@ export function recordRunExit(row: RunExit, root: string): void {
167
366
  }
168
367
  }
169
368
 
369
+ /** Join exit facts through the last pod-child-run fence; never borrow a previous Pod attempt. */
370
+ function deriveTerminalEvidence(row: RunExit, root: string): RunExit['terminalEvidence'] | undefined {
371
+ let entries: RunLedgerEntry[] | null;
372
+ try { entries = loadRunLedger(row.runId, runLedgerDir(root)); }
373
+ catch { return undefined; /* observing the child ledger cannot block the parent incident record */ }
374
+ if (!entries) return undefined;
375
+ let startIndex = -1;
376
+ entries.forEach((entry, index) => { if (entry.event === 'pod-child-run') startIndex = index; });
377
+ const startEntry = startIndex >= 0 ? entries[startIndex] : undefined;
378
+ const start = startEntry?.data;
379
+ if (!start || typeof start.job !== 'string' || !start.job.trim()
380
+ || typeof start.childRunId !== 'string' || !start.childRunId.trim()) return undefined;
381
+ const currentRows = entries.slice(startIndex + 1).filter((entry) => entry.event === 'pod-child-evidence'
382
+ && entry.data.job === start.job && entry.data.childRunId === start.childRunId).map((entry) => entry.data);
383
+ const evidenceRow = currentRows.slice().reverse().find((data) => Object.hasOwn(data, 'childEvidence'));
384
+ const childEvidence = evidenceRow?.childEvidence && typeof evidenceRow.childEvidence === 'object' && !Array.isArray(evidenceRow.childEvidence)
385
+ ? evidenceRow.childEvidence as Record<string, unknown> : undefined;
386
+ const tailSource = Array.isArray(childEvidence?.podLogTail) && childEvidence.podLogTail.every((line) => typeof line === 'string')
387
+ ? childEvidence.podLogTail
388
+ : typeof childEvidence?.stderr === 'string' ? childEvidence.stderr.split(/\r?\n/) : undefined;
389
+ const childOutputTail = tailSource?.length
390
+ ? tailSource.slice(-3).map((line) => redactSecretText(line).slice(0, 200))
391
+ : 'unknown';
392
+ let termination: PodTermination | undefined;
393
+ for (const data of currentRows.slice().reverse()) {
394
+ termination = parsePodTermination(data.podTermination, start.job);
395
+ if (termination) break;
396
+ }
397
+ const finished = entries.slice(startIndex + 1).slice().reverse().find((entry) => {
398
+ if (entry.event !== 'pod-launch-finished' || entry.data.job !== start.job) return false;
399
+ const childRunId = typeof entry.data.childRun === 'string' ? entry.data.childRun : entry.data.run;
400
+ if (childRunId !== start.childRunId) return false;
401
+ const startAttempt = Number.isSafeInteger(start.attempt) && Number(start.attempt) > 0 ? Number(start.attempt) : undefined;
402
+ const finishAttempt = Number.isSafeInteger(entry.data.attempt) && Number(entry.data.attempt) > 0 ? Number(entry.data.attempt) : undefined;
403
+ return startAttempt === undefined || finishAttempt === startAttempt;
404
+ });
405
+ const classification = finished?.data.failureClassification;
406
+ const terminationReason = finished?.data.terminationReason;
407
+ const childRunDiagnosis = childRunDiagnosisFields(start.childRunId, root, {
408
+ job: start.job,
409
+ attempt: Number.isSafeInteger(start.attempt) && Number(start.attempt) > 0 ? Number(start.attempt) : undefined,
410
+ startedAt: startEntry?.timestamp,
411
+ finishedAt: finished?.timestamp,
412
+ });
413
+ return {
414
+ job: start.job,
415
+ childRunId: start.childRunId,
416
+ attempt: Number.isSafeInteger(start.attempt) && Number(start.attempt) > 0 ? Number(start.attempt) : 'unknown',
417
+ childOutputTail,
418
+ containerExitCode: typeof termination?.exitCode === 'number' ? termination.exitCode : 'unknown',
419
+ parentVerdict: row.reason,
420
+ failureClassification: typeof finished?.data.podExitClass === 'string' && finished.data.podExitClass
421
+ ? redactSecretText(finished.data.podExitClass).slice(0, 120)
422
+ : typeof classification === 'string' && classification ? redactSecretText(classification).slice(0, 120) : 'unknown',
423
+ terminationReason: typeof terminationReason === 'string' && terminationReason ? redactSecretText(terminationReason).slice(0, 200) : 'unknown',
424
+ childFailureStage: typeof finished?.data.childFailureStage === 'string' && finished.data.childFailureStage.trim()
425
+ ? redactSecretText(finished.data.childFailureStage).slice(0, 120) : 'unknown',
426
+ ...childRunDiagnosis,
427
+ };
428
+ }
429
+
430
+ function childRunDiagnosisFields(childRunId: string, root: string, current: {
431
+ job: string; attempt?: number; startedAt?: string; finishedAt?: string;
432
+ }): Pick<NonNullable<RunExit['terminalEvidence']>, 'childRunStatus' | 'shardIdentityReadFailure' | 'providerFailure'> {
433
+ let entries: RunLedgerEntry[] | null;
434
+ try { entries = loadRunLedger(childRunId, runLedgerDir(root)); }
435
+ catch { entries = null; }
436
+ const startedAt = typeof current.startedAt === 'string' ? Date.parse(current.startedAt) : NaN;
437
+ const finishedAt = typeof current.finishedAt === 'string' ? Date.parse(current.finishedAt) : NaN;
438
+ if (!entries || !current.job.trim() || current.attempt === undefined
439
+ || !Number.isFinite(startedAt) || !Number.isFinite(finishedAt) || finishedAt < startedAt) return {
440
+ childRunStatus: { stage: 'unknown', status: 'unknown', failureKind: 'unknown' },
441
+ shardIdentityReadFailure: 'unknown', providerFailure: 'unknown',
442
+ };
443
+
444
+ // Child ledgers can outlive a Pod retry that reuses childRunId. Only trust events
445
+ // timestamped inside this parent's exact Job/attempt interval; otherwise report unknown.
446
+ const attemptEntries = entries.filter((entry) => {
447
+ const timestamp = typeof entry.timestamp === 'string' ? Date.parse(entry.timestamp) : NaN;
448
+ return Number.isFinite(timestamp) && timestamp >= startedAt && timestamp <= finishedAt;
449
+ });
450
+ const status = attemptEntries.slice().reverse().find((entry) => entry.event === 'run-status')?.data;
451
+ const shardObservation = attemptEntries.slice().reverse().find((entry) => Object.hasOwn(entry, 'shardIdentityReadFailure')
452
+ || entry.event === 'shard-sibling-query');
453
+ // RunLedgerEntry's canonical shard identity is top-level (makeRunObserver writes it there).
454
+ // Accept data.* too for older/imported child rows that nested the field.
455
+ const shardValue = shardObservation?.shardIdentityReadFailure ?? shardObservation?.data.shardIdentityReadFailure;
456
+ const shardFailure = typeof shardValue === 'string' && shardValue !== 'none' && shardValue !== 'unknown' && shardValue.trim()
457
+ ? shardValue : undefined;
458
+ const providerSkip = attemptEntries.slice().reverse().find((entry) => entry.event === 'goal-elaboration-skipped'
459
+ && entry.data.outcome === 'skipped' && entry.data.reason === 'provider-failed');
460
+ const providerError = typeof providerSkip?.data.error === 'string' ? providerSkip.data.error : '';
461
+ const providerFailure: NonNullable<RunExit['terminalEvidence']>['providerFailure'] = providerSkip
462
+ ? /unavailable:\s*configure apiKey/iu.test(providerError) ? 'credential-not-configured' : 'provider-failed'
463
+ : 'unknown';
464
+ const safe = (value: unknown): string | 'unknown' => typeof value === 'string' && value.trim()
465
+ ? redactSecretText(value).slice(0, 120) : 'unknown';
466
+ return {
467
+ childRunStatus: { stage: safe(status?.stage), status: safe(status?.runStatus), failureKind: safe(status?.failureKind) },
468
+ shardIdentityReadFailure: shardFailure ? redactSecretText(shardFailure).slice(0, 120)
469
+ : shardValue === 'unknown' ? 'unknown'
470
+ : shardObservation?.event === 'shard-sibling-query' && shardObservation.data.reason === 'not-sharded' ? 'none' : 'unknown',
471
+ providerFailure,
472
+ };
473
+ }
474
+
170
475
  const HOSTNAME_BURST_WINDOW_MS = 60 * 60_000;
171
476
 
172
477
  function uniqueRunExits(rows: readonly RunExit[]): RunExit[] {
@@ -25,7 +25,7 @@
25
25
  // spaceId 선례와 동형. 계약 = [[DESIGN-executor-pty-ref-contract-2026-07-25]] ExecutorPtyRef.runId.
26
26
 
27
27
  import { createHash, randomUUID } from 'node:crypto';
28
- import { mkdirSync } from 'node:fs';
28
+ import { appendFileSync, mkdirSync } from 'node:fs';
29
29
  import { tmpdir } from 'node:os';
30
30
  import { isAbsolute, relative, resolve } from 'node:path';
31
31
  import { ensureHostId } from '../platform/host-id.js';
@@ -101,6 +101,20 @@ export function getHarnessBoundaryPath(env: NodeJS.ProcessEnv = process.env): st
101
101
  return env[HARNESS_BOUNDARY_ENV]?.trim() ?? '';
102
102
  }
103
103
 
104
+ /** TENANT-BOUNDARY (0.2.41): 경계 회신 mailbox(HARNESS_BOUNDARY_RESPONSES_ENV)에 payload 한 줄(JSONL)을
105
+ * 남긴다 — 익명 내보내기 전용 출구. env 가 비거나 절대경로가 아니면 fail-open(빈 문자열 반환, 파일 안 만듦). */
106
+ export function appendBoundaryResponseLine(env: NodeJS.ProcessEnv, payload: object): string {
107
+ const path = env[HARNESS_BOUNDARY_RESPONSES_ENV]?.trim() ?? '';
108
+ if (!path || !isAbsolute(path)) return '';
109
+ try {
110
+ mkdirSync(resolve(path, '..'), { recursive: true });
111
+ appendFileSync(path, `${JSON.stringify(payload)}\n`);
112
+ return path;
113
+ } catch {
114
+ return '';
115
+ }
116
+ }
117
+
104
118
  /** 전 공간 종류(SSOT) — logs `--space` 필터·검증 등이 공유. */
105
119
  export const HARNESS_SPACE_KINDS: readonly HarnessSpaceKind[] = ['self-implement', 'dev-harness', 'solve-mission', 'dev-hold'];
106
120
 
@@ -0,0 +1,59 @@
1
+ import { parentPort } from 'node:worker_threads';
2
+ import { queryRunningRuns, type RunningRunsResult } from '../self-implement/running-runs.js';
3
+
4
+ /**
5
+ * HARNESS-PROGRESS-HANG — `harness progress` 하위 조회의 «전용 워커 엔트리».
6
+ * 이 모듈은 CLI 디스패치(`src/index.ts`·`bin/elanous.mjs`)를 거치지 않고 워커에 직접 적재되므로,
7
+ * 번들·컴파일 산출물에서도 `parentPort` 핸들러가 반드시 이 스레드에 등록된다.
8
+ * 그 전에는 워커가 `import.meta.url` 로 배포 엔트리를 재진입해 핸들러가 아예 안 올랐다.
9
+ */
10
+ export interface ProgressQueryWorkerRequest {
11
+ readonly kind?: 'query';
12
+ readonly caller: string;
13
+ readonly runIds?: readonly string[];
14
+ readonly timeBudgetMs?: number;
15
+ }
16
+
17
+ /** 상한 도달 뒤 부모가 보내는 정지 요청 — 워커는 «현재 행» 을 회신하고 정상 종료한다. */
18
+ export interface ProgressQueryWorkerAbortRequest {
19
+ readonly kind: 'abort';
20
+ }
21
+
22
+ export type ProgressQueryWorkerMessage = ProgressQueryWorkerRequest | ProgressQueryWorkerAbortRequest;
23
+
24
+ export interface ProgressQueryWorkerReply {
25
+ readonly ok: boolean;
26
+ readonly result?: RunningRunsResult;
27
+ readonly error?: string;
28
+ readonly stopped?: 'aborted';
29
+ }
30
+
31
+ /**
32
+ * 워커의 `parentPort` 핸들러를 등록한다.
33
+ * - `query`: 하위 조회를 실행해 결과를 회신한다.
34
+ * - `abort`: 이 스레드가 마지막으로 계산한 행(`lastResult`)을 «보존 행» 으로 회신한다 —
35
+ * 부모의 상한 뒤 유예 창 안에 도착하면 `progress-command-late` 관측으로 그대로 보존된다.
36
+ */
37
+ export function installProgressWorkerEntry(port: NonNullable<typeof parentPort> | null | undefined = parentPort): void {
38
+ if (!port) return;
39
+ let lastResult: RunningRunsResult | undefined;
40
+ port.on('message', (message: ProgressQueryWorkerMessage) => {
41
+ if (message.kind === 'abort') {
42
+ port.postMessage({ ok: true, result: lastResult, stopped: 'aborted' } satisfies ProgressQueryWorkerReply);
43
+ return;
44
+ }
45
+ try {
46
+ const result = queryRunningRuns({
47
+ caller: message.caller,
48
+ ...(message.timeBudgetMs === undefined ? {} : { timeBudgetMs: message.timeBudgetMs }),
49
+ ...(message.runIds === undefined ? {} : { runIds: message.runIds }),
50
+ });
51
+ lastResult = result;
52
+ port.postMessage({ ok: true, result } satisfies ProgressQueryWorkerReply);
53
+ } catch (error) {
54
+ port.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) } satisfies ProgressQueryWorkerReply);
55
+ }
56
+ });
57
+ }
58
+
59
+ installProgressWorkerEntry();
@@ -0,0 +1,11 @@
1
+ import { isMainThread } from 'node:worker_threads';
2
+
3
+ /**
4
+ * HARNESS-PROGRESS-HANG — `harness progress` 하위 조회는 «전용 워커 엔트리»(`./progress-worker-entry.ts`)
5
+ * 를 직접 적재한다. 그 엔트리는 CLI 디스패치를 거치지 않으므로 번들·컴파일 산출물에서도 `parentPort`
6
+ * 핸들러가 워커 스레드에 오른다. 이 판정은 배포 엔트리(`bin/elanous.mjs`)가 워커 문맥에서 재진입됐을 때
7
+ * 대시보드·provider 선택·명령 디스패치를 다시 걸지 않게 가드한다.
8
+ */
9
+ export function shouldRunCliEntry(): boolean {
10
+ return isMainThread;
11
+ }
package/src/index.ts CHANGED
@@ -4748,6 +4748,20 @@ selfCmd
4748
4748
  .option('--shard-position <n>', 'GATE-REMOTE-SHARD-PLAN — 조각 위치(1부터 정수). 원격 명령줄에 그대로 실린다')
4749
4749
  .option('--shard-plan <path>', 'GATE-REMOTE-SHARD-PLAN — 조각 계획 파일 경로. 주면 원격 명령줄에 --shard-plan 으로 실린다')
4750
4750
  .action(async (opts: { changed?: boolean; base?: string; pr?: string; shards?: string | boolean; shardConcurrency?: string; fixedShardDistribution?: boolean; includeImporters?: boolean; inherit?: boolean; remote?: string | boolean; local?: boolean; artifactDir?: string; orchestrationId?: string; shardId?: string; shardPosition?: string; shardPlan?: string }) => {
4751
+ const { observeSelfGateTrainMarker, refuseSeatSelfGateWithoutTrainMarker, writeSeatSelfGateRefusalArtifact } = require('./self-implement/gate-cli.js') as typeof import('./self-implement/gate-cli.js');
4752
+ const trainMarker = observeSelfGateTrainMarker();
4753
+ if (process.env.ELANOUS_TRACK) {
4754
+ const seatRefusal = refuseSeatSelfGateWithoutTrainMarker(trainMarker);
4755
+ if (seatRefusal) {
4756
+ if (opts.artifactDir !== undefined) {
4757
+ try { writeSeatSelfGateRefusalArtifact(process.cwd(), opts.artifactDir, trainMarker); }
4758
+ catch (error) { ui.error(`self gate artifact: ${error instanceof Error ? error.message : String(error)}`); }
4759
+ }
4760
+ ui.error(seatRefusal.message);
4761
+ process.exitCode = 2;
4762
+ return;
4763
+ }
4764
+ }
4751
4765
  if (!opts.changed && opts.shards === undefined) { ui.error('self gate requires --changed or --shards'); process.exitCode = 2; return; }
4752
4766
  if (opts.fixedShardDistribution && opts.shards === undefined) { ui.error('self gate: --fixed-shard-distribution requires --shards <n>'); process.exitCode = 2; return; }
4753
4767
  if (opts.shardConcurrency !== undefined && (!/^[1-4]$/.test(opts.shardConcurrency))) { ui.error('self gate: --shard-concurrency must be 1–4'); process.exitCode = 2; return; }
@@ -4770,7 +4784,7 @@ selfCmd
4770
4784
  ranLocal = true;
4771
4785
  try {
4772
4786
  const { runSelfGateCliAsync } = require('./self-implement/gate-cli.js') as typeof import('./self-implement/gate-cli.js');
4773
- const result = await runSelfGateCliAsync(process.cwd(), { base: opts.base, pr: opts.pr, shards, ...(opts.shardConcurrency !== undefined ? { shardConcurrency: Number(opts.shardConcurrency) } : {}), ...(opts.fixedShardDistribution ? { fixedShardDistribution: true } : {}), includeImporterTests: !!opts.includeImporters, noInherit: opts.inherit === false, ...(opts.artifactDir !== undefined ? { artifactDir: opts.artifactDir } : {}) });
4787
+ const result = await runSelfGateCliAsync(process.cwd(), { base: opts.base, pr: opts.pr, shards, ...(opts.shardConcurrency !== undefined ? { shardConcurrency: Number(opts.shardConcurrency) } : {}), ...(opts.fixedShardDistribution ? { fixedShardDistribution: true } : {}), includeImporterTests: !!opts.includeImporters, noInherit: opts.inherit === false, trainGate: trainMarker.received, ...(opts.artifactDir !== undefined ? { artifactDir: opts.artifactDir } : {}) });
4774
4788
  console.log(result.lines.join('\n'));
4775
4789
  return result.exitCode;
4776
4790
  } catch (error) {
@@ -4854,6 +4868,8 @@ selfCmd
4854
4868
  const fetched = remoteArtifacts && 'dir' in remoteArtifacts ? remoteArtifacts.fetch : undefined;
4855
4869
  try {
4856
4870
  if (fetched?.ok) {
4871
+ const { recordGateTrainMarker } = await import('./self-implement/gate-artifacts.js');
4872
+ recordGateTrainMarker(fetched.summaryPath, trainMarker.received);
4857
4873
  console.log(`artifacts: ${fetched.summaryPath} (junit ${fetched.junitFiles.length} · fetched from remote)`);
4858
4874
  if (fetched.remoteDirKept) console.log(`⚠ artifacts: 원격 산출 디렉토리를 못 지웠다 — ${(remoteArtifacts as { dir: string }).dir} (판정은 그대로다)`);
4859
4875
  }
@@ -4861,7 +4877,7 @@ selfCmd
4861
4877
  const reason = remoteArtifacts && 'unsupported' in remoteArtifacts ? 'remote-unsupported' as const : 'remote-fetch-failed' as const;
4862
4878
  if (reason === 'remote-fetch-failed') console.log(`⚠ artifacts: 원격 산출을 못 가져왔다 — ${fetched && !fetched.ok ? fetched.reason : 'no remote fetch ran'} (판정은 그대로다)`);
4863
4879
  const { writeRemoteUnavailableGateArtifacts } = await import('./self-implement/gate-artifacts.js');
4864
- const written = writeRemoteUnavailableGateArtifacts(opts.artifactDir, process.cwd(), opts.base, Number(process.exitCode ?? 0), reason);
4880
+ const written = writeRemoteUnavailableGateArtifacts(opts.artifactDir, process.cwd(), opts.base, Number(process.exitCode ?? 0), reason, undefined, undefined, trainMarker.received);
4865
4881
  console.log(`artifacts: ${written.summaryPath} (junit 0 · unavailable=${reason})`);
4866
4882
  }
4867
4883
  } catch (error) {
@@ -3,10 +3,14 @@ import { createHash, randomBytes } from 'node:crypto';
3
3
  import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
4
4
  import { basename, dirname, join, resolve } from 'node:path';
5
5
  import { elanousStateRoot } from '../autopilot/state-paths.js';
6
+ import { appendBoundaryResponseLine, HARNESS_BOUNDARY_RESPONSES_ENV } from '../harness/harness-space.js';
7
+ import { anonymousExport, suggestProjectForFolder } from '../project/project-store.js';
6
8
 
7
9
  export interface DevProjectDeps {
8
10
  git?: (dir: string, args: readonly string[]) => string | null;
9
11
  stateDir?: string;
12
+ /** TENANT-BOUNDARY (0.2.41): 회신 mailbox 경계 채널용 env — 생산은 process.env 기본값. */
13
+ env?: Record<string, string | undefined>;
10
14
  }
11
15
 
12
16
  interface DevProjectRegistry {
@@ -60,9 +64,30 @@ export function resolveDevProject(dir: string, deps: DevProjectDeps = {}): strin
60
64
  try {
61
65
  writeJsonAtomically(join(root, '.elanous', 'project.json'), { identityKey, devProject: id } satisfies DevProjectCache);
62
66
  } catch { /* cache only */ }
67
+
68
+ exportTenantBoundaryRecord(root, id, deps.env ?? process.env);
63
69
  return id;
64
70
  }
65
71
 
72
+ /**
73
+ * TENANT-BOUNDARY (0.2.41 · nfr:security): 고객 원장의 설치 밖 출구는 익명 내보내기 하나다.
74
+ * 경계 회신 mailbox(HARNESS_BOUNDARY_RESPONSES_ENV)가 열려 있을 때만, 고객 프로젝트 원장을
75
+ * `anonymousExport`(식별 필드 → 토큰)로 바꿔 한 줄(JSONL)로 남긴다. 원장 식별 원문은 절대
76
+ * 설치 밖으로 나가지 않는다. 채널이 없으면 아무 일도 일어나지 않고(기본 동작 보존),
77
+ * 채널 쓰기가 실패해도 id 해소를 막지 않는다(fail-open).
78
+ */
79
+ function exportTenantBoundaryRecord(root: string, devProject: string, env: Record<string, string | undefined>): void {
80
+ const mailbox = env[HARNESS_BOUNDARY_RESPONSES_ENV]?.trim();
81
+ if (!mailbox) return;
82
+ try {
83
+ const project = suggestProjectForFolder(root);
84
+ appendBoundaryResponseLine(env as NodeJS.ProcessEnv, {
85
+ devProject,
86
+ ...(project ? { project: anonymousExport(project) } : {}),
87
+ });
88
+ } catch { /* boundary export must never block id resolution */ }
89
+ }
90
+
66
91
  function runGit(dir: string, args: readonly string[]): string | null {
67
92
  try {
68
93
  return execFileSync('git', ['-C', dir, ...args], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
@@ -49,7 +49,7 @@ const MODEL_ALIASES: Readonly<Record<string, string>> = {
49
49
  'pro': 'gemini-3.1-pro-preview',
50
50
  'gemini-pro': 'gemini-3.1-pro-preview',
51
51
  // OpenAI / Codex
52
- 'codex': 'gpt-6-sol', // ⭐ 2026-09-25: 운영 codex 기본(gpt-6-sol)과 맞춘다 — gpt-5.5 는 두 세대 낡았다
52
+ 'codex': 'gpt-6.1-terra',
53
53
  'gpt-5': 'gpt-5.5',
54
54
  'mini': 'gpt-5-mini',
55
55
  'nano': 'gpt-5-nano',
@@ -57,15 +57,16 @@ const MODEL_ALIASES: Readonly<Record<string, string>> = {
57
57
  // 🔑 왜 — `sol`·`luna` 라는 «같은 이름»이 두 세대에 걸쳐 있다. 세대를 안 쓰면
58
58
  // «어느 세대인지 말하지 않은 것»이고, 그때 골라야 할 것은 ***최신***이다.
59
59
  // (실제로 이 겹침 때문에 커뮤니티 조사기가 5.6 과 6 을 섞어 답한 일이 있었다.)
60
- // ⛔ `terra` 는 GPT-6 에 «없다» — 중간 등급이 접혔고 GPT-6 Sol 이 그 가격대를 흡수했다.
61
- // 그래서 `terra` 는 5.6 을 계속 가리킨다(은퇴가 아니라 «후속이 없는» 것이다).
60
+ // GPT-6.1 restores a Terra tier; unsuffixed aliases follow the current 6.1 generation.
62
61
  // 📏 세대 확인 = `curl /v1/models` ⊕ `codex debug models` (2026-09-23 둘 다 실측).
63
62
  'astra': 'gpt-6-astra',
64
- 'sol': 'gpt-6-sol',
63
+ 'sol': 'gpt-6.1-sol',
65
64
  'luna': 'gpt-6-luna',
66
- 'terra': 'gpt-5.6-terra', // ⛔ GPT-6 에 후속 없음
65
+ 'terra': 'gpt-6.1-terra',
67
66
  // 세대를 «명시»해 부르는 길 — 겹치는 이름을 또렷하게 가리킬 때.
68
67
  '6-sol': 'gpt-6-sol',
68
+ '6.1-sol': 'gpt-6.1-sol',
69
+ '6.1-terra': 'gpt-6.1-terra',
69
70
  '6-luna': 'gpt-6-luna',
70
71
  '5.6-sol': 'gpt-5.6-sol',
71
72
  '5.6-terra': 'gpt-5.6-terra',