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
@@ -208,6 +208,12 @@ function expectationsMet(expects: readonly NlRoutingToolExpectation[], breakdown
208
208
  return expects.every((expectation) => (breakdown[expectation.tool] ?? 0) >= (expectation.minCount ?? 1));
209
209
  }
210
210
 
211
+ /**
212
+ * v5 채점의 최소 실행 턴 — 코퍼스 예산(CORPUS_BUDGETS) 과 «독립»인 채점 턴 정책 상수.
213
+ * 낮은 예산에서 복합 발화가 예산 부족만으로 거짓 실패하지 않게 한다.
214
+ */
215
+ export const NL_ROUTING_V5_MIN_SCORING_TURNS = 6;
216
+
211
217
  /** v5 28문항을 «생산 runEvalPrompt seam» 으로 그대로 돌려 경로·복합 처리를 채점한다. */
212
218
  export async function scoreNlRoutingV5(opts: {
213
219
  runPrompt: typeof runEvalPrompt;
@@ -215,7 +221,7 @@ export async function scoreNlRoutingV5(opts: {
215
221
  cwd: string;
216
222
  maxTurns?: number;
217
223
  }): Promise<NlRoutingV5Score> {
218
- const maxTurns = opts.maxTurns ?? 6;
224
+ const maxTurns = opts.maxTurns ?? NL_ROUTING_V5_MIN_SCORING_TURNS;
219
225
  const matched = new Set<string>();
220
226
  const failed: string[] = [];
221
227
  const patternMismatches: string[] = [];
@@ -401,7 +407,9 @@ export async function main(
401
407
  // (다른 자로 재면 판정선과 비교 불가 · 형태 F3). 임계 미달은 «조용한 0» 이 아니라 거부다.
402
408
  let v5: NlRoutingV5Score | undefined;
403
409
  if (process.env.CORPUS_V5 === '1') {
404
- v5 = await scoreNlRoutingV5({ runPrompt, surface, cwd: corpusCwd, maxTurns: budgets[0] });
410
+ // ⛔ 채점 턴 정책은 코퍼스 예산과 «독립»이다 — 예산은 코퍼스 생성 실행 횟수만 제어하고
411
+ // 채점 maxTurns 는 NL_ROUTING_V5_MIN_SCORING_TURNS 기본(또는 명시적 opts)에서만 온다.
412
+ v5 = await scoreNlRoutingV5({ runPrompt, surface, cwd: corpusCwd });
405
413
  console.log(`[v5] patterns ${v5.patterns} (path ${v5.pathPatterns} · compound ${v5.compoundPatterns}) · 문항 ${v5.questions} (path ${v5.pathQuestions} · compound ${v5.compoundQuestions}) · 채점 ${v5.scored} · 통과 ${v5.passed} · 실패 ${v5.failed.length ? v5.failed.join(',') : '(없음)'} · 실행 실패 ${v5.failedRuns} · masking-leak ${v5.maskingLeaks.length} ${v5.maskingLeaks.length ? v5.maskingLeaks.join(',') : '(없음)'} · pattern-mismatch ${v5.patternMismatches.length ? v5.patternMismatches.join(',') : '(없음)'} · 판정 ${v5.verdict}`);
406
414
  if (!v5.thresholdsMet) {
407
415
  throw new Error(
@@ -0,0 +1,172 @@
1
+ /**
2
+ * SW-PERSONA-TEACHER-WEEKLY-FU (GoalId d68f0e7e17725cef) — weekly lesson node commands.
3
+ *
4
+ * 각 명령은 runner 가 심는 `ELANOUS_GRAPH_CONTEXT`(이번 노드의 input + 앞 노드들의 구조 산출)를 읽고
5
+ * 마지막 한 줄 JSON 으로 다음 간선의 `outcome` 을 낸다. 진도는 새 저장소를 만들지 않는다 —
6
+ * 첫 실행의 `record-progress` 산출이 그래프 런 원장(`graph-runs/weekly-lesson/<runId>.json`)에 남고,
7
+ * 다음 실행의 `read-progress` 가 그 원장을 그대로 읽어 다음 단원을 고른다.
8
+ */
9
+ import { mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
10
+ import { join, resolve } from 'node:path';
11
+
12
+ const SYLLABUS = ['unit-1', 'unit-2', 'unit-3', 'unit-4', 'unit-5'] as const;
13
+ const WEEKLY_TIMEZONE = 'Asia/Seoul';
14
+ const WEEKLY_CRON_WEEKDAY = 'Sun';
15
+ const WEEKLY_CRON_HOUR = 20;
16
+
17
+ type Lesson = (typeof SYLLABUS)[number] | string;
18
+
19
+ interface StepOutput {
20
+ outcome?: string;
21
+ lesson?: string;
22
+ completed?: string[];
23
+ nextLesson?: string | null;
24
+ [key: string]: unknown;
25
+ }
26
+
27
+ interface GraphContext {
28
+ graphId?: string;
29
+ runId?: string;
30
+ nodeId?: string;
31
+ input?: unknown;
32
+ outputs?: Record<string, unknown>;
33
+ }
34
+
35
+ function emit(value: Record<string, unknown>): void {
36
+ process.stdout.write(`${JSON.stringify(value)}\n`);
37
+ }
38
+
39
+ function asObject(value: unknown): Record<string, unknown> {
40
+ return value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
41
+ }
42
+
43
+ function parseStepOutput(value: unknown): StepOutput {
44
+ if (typeof value === 'string') {
45
+ const last = value.split('\n').map((line) => line.trim()).filter(Boolean).at(-1);
46
+ if (!last?.startsWith('{')) throw new Error('step output must end with a JSON object');
47
+ try { return JSON.parse(last) as StepOutput; }
48
+ catch (error) { throw new Error('step output ended with invalid JSON', { cause: error }); }
49
+ }
50
+ return asObject(value) as StepOutput;
51
+ }
52
+
53
+ function context(): { value: GraphContext; root: string } {
54
+ const path = process.env.ELANOUS_GRAPH_CONTEXT;
55
+ if (!path) throw new Error('ELANOUS_GRAPH_CONTEXT is required');
56
+ const stateRoot = process.env.ELANOUS_STATE_DIR;
57
+ if (!stateRoot) throw new Error('ELANOUS_STATE_DIR is required');
58
+ return { value: JSON.parse(readFileSync(path, 'utf8')) as GraphContext, root: resolve(stateRoot) };
59
+ }
60
+
61
+ /** 일요일 20:00 Asia/Seoul 인가 — 스케줄러가 주입한 tick 시각을 그 자리에서 검증한다. */
62
+ function isWeeklySlot(scheduledAt: unknown): boolean {
63
+ if (typeof scheduledAt !== 'string' || !Number.isFinite(Date.parse(scheduledAt))) return false;
64
+ const parts = new Intl.DateTimeFormat('en-US', {
65
+ timeZone: WEEKLY_TIMEZONE, weekday: 'short', hour: '2-digit', minute: '2-digit', hour12: false,
66
+ }).formatToParts(new Date(scheduledAt));
67
+ const get = (type: string): string => parts.find((part) => part.type === type)?.value ?? '';
68
+ return get('weekday') === WEEKLY_CRON_WEEKDAY && Number(get('hour')) === WEEKLY_CRON_HOUR && Number(get('minute')) === 0;
69
+ }
70
+
71
+ /** 저장된 진도 = 앞선 런 원장의 성공한 `record-progress` 산출(lesson·completed). */
72
+ function completedLessons(root: string): { completed: Lesson[]; runs: number } {
73
+ const dir = join(root, 'graph-runs', 'weekly-lesson');
74
+ let files: string[];
75
+ try { files = readdirSync(dir).filter((file) => file.endsWith('.json') && !file.endsWith('.decision.json')); }
76
+ catch { return { completed: [], runs: 0 }; }
77
+ const completed: Lesson[] = [];
78
+ let runs = 0;
79
+ for (const file of files) {
80
+ let state: { nodes?: Array<{ nodeId?: string; ok?: boolean; output?: unknown }> };
81
+ try { state = JSON.parse(readFileSync(join(dir, file), 'utf8')) as typeof state; }
82
+ catch { continue; }
83
+ runs += 1;
84
+ for (const node of state.nodes ?? []) {
85
+ if (node.nodeId !== 'record-progress' || node.ok !== true) continue;
86
+ const recorded = parseStepOutput(node.output);
87
+ for (const lesson of recorded.completed ?? []) if (typeof lesson === 'string' && !completed.includes(lesson)) completed.push(lesson);
88
+ if (typeof recorded.lesson === 'string' && !completed.includes(recorded.lesson)) completed.push(recorded.lesson);
89
+ }
90
+ }
91
+ return { completed, runs };
92
+ }
93
+
94
+ function nextLesson(completed: readonly string[]): Lesson | undefined {
95
+ return SYLLABUS.find((lesson) => !completed.includes(lesson));
96
+ }
97
+
98
+ function readProgress(): void {
99
+ const { value, root } = context();
100
+ const input = asObject(value.input);
101
+ if (!isWeeklySlot(input.scheduledAt)) {
102
+ emit({ outcome: 'fail', error: 'off-schedule: weekly ticks run Sunday 20:00 Asia/Seoul', scheduledAt: input.scheduledAt ?? null });
103
+ return;
104
+ }
105
+ const { completed, runs } = completedLessons(root);
106
+ emit({ outcome: 'ok', scheduledAt: input.scheduledAt, completed, nextLesson: nextLesson(completed) ?? null,
107
+ ledgerRuns: runs, source: runs === 0 ? 'empty-ledger' : 'run-ledger' });
108
+ }
109
+
110
+ function selectNext(): void {
111
+ const { value } = context();
112
+ const prior = parseStepOutput(value.outputs?.['read-progress']);
113
+ const completed = (prior.completed ?? []).filter((lesson): lesson is string => typeof lesson === 'string');
114
+ const lesson = typeof prior.nextLesson === 'string' ? prior.nextLesson : nextLesson(completed);
115
+ if (!lesson) {
116
+ emit({ outcome: 'fail', error: 'syllabus-complete', completed });
117
+ return;
118
+ }
119
+ emit({ outcome: completed.length === 0 ? 'baseline' : 'next', lesson, completed, scheduledAt: prior.scheduledAt ?? null,
120
+ requestedBy: { graphId: value.graphId ?? null, runId: value.runId ?? null } });
121
+ }
122
+
123
+ function packLesson(): void {
124
+ const { value, root } = context();
125
+ const selected = parseStepOutput(asObject(value.input)['select-next']);
126
+ if (typeof selected.lesson !== 'string') {
127
+ emit({ outcome: 'fail', error: 'lesson-pack requires a selected lesson' });
128
+ return;
129
+ }
130
+ if (!(SYLLABUS as readonly string[]).includes(selected.lesson)) {
131
+ emit({ outcome: 'fail', error: `lesson-pack received an unknown lesson: ${selected.lesson}` });
132
+ return;
133
+ }
134
+ const dir = join(root, 'lesson-pack', 'inbox');
135
+ mkdirSync(dir, { recursive: true });
136
+ writeFileSync(join(dir, `${selected.lesson}.json`), `${JSON.stringify({
137
+ lesson: selected.lesson, scheduledAt: selected.scheduledAt ?? null,
138
+ requestedBy: asObject(selected.requestedBy), packedBy: { graphId: value.graphId ?? null, runId: value.runId ?? null },
139
+ }, null, 2)}\n`);
140
+ emit({ outcome: 'ok', lesson: selected.lesson, completed: selected.completed ?? [] });
141
+ }
142
+
143
+ function recordProgress(): void {
144
+ const { value } = context();
145
+ const selected = parseStepOutput(value.outputs?.['select-next']);
146
+ const packed = parseStepOutput(value.outputs?.['lesson-pack']);
147
+ const lesson = typeof packed.lesson === 'string' ? packed.lesson : typeof selected.lesson === 'string' ? selected.lesson : undefined;
148
+ if (!lesson) {
149
+ emit({ outcome: 'fail', error: 'record-progress requires the delivered lesson' });
150
+ return;
151
+ }
152
+ const completed = (selected.completed ?? []).filter((item): item is string => typeof item === 'string');
153
+ if (!completed.includes(lesson)) completed.push(lesson);
154
+ emit({ outcome: 'ok', lesson, completed, recordedAt: asObject(value.input).scheduledAt ?? null });
155
+ }
156
+
157
+ const commands: Record<string, () => void> = {
158
+ 'read-progress': readProgress,
159
+ 'select-next': selectNext,
160
+ pack: packLesson,
161
+ 'record-progress': recordProgress,
162
+ };
163
+
164
+ if (import.meta.main) {
165
+ const command = process.argv[2] ?? '';
166
+ const run = commands[command];
167
+ if (!run) {
168
+ console.error(`unknown weekly-lesson command: ${command} (expected ${Object.keys(commands).join('|')})`);
169
+ process.exit(2);
170
+ }
171
+ run();
172
+ }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  /** Warning-only public-copy shadow scan. It never edits source or exposes private candidate text. */
3
- import { existsSync, readFileSync } from 'node:fs';
4
- import { extname, normalize, relative, resolve, sep } from 'node:path';
3
+ import { readFileSync, readdirSync, statSync } from 'node:fs';
4
+ import { extname, join, normalize, relative, resolve, sep } from 'node:path';
5
5
  import { PatentLedger } from '../src/patents/ledger.js';
6
6
  import { checkBrandText } from './brand/check.js';
7
7
 
@@ -10,7 +10,8 @@ export type PublicCopyFinding = { source: string; line: number; rule: string };
10
10
  export type PatentLineMatcher = (text: string) => number[];
11
11
  export type PublicCopyScan = {
12
12
  findings: PublicCopyFinding[];
13
- excludedSources: Array<{ source: string; reason: 'internal-goal-document' }>;
13
+ excludedSources: Array<{ source: string; reason: 'internal-goal-document' | 'internal-marketing-source' | 'asset-manifest' }>;
14
+ documents: Array<{ source: string; findings: number; companyNameMentions: number; placeholderMentions: number }>;
14
15
  brandRulesAvailable: boolean;
15
16
  patentLedgerAvailable: boolean;
16
17
  };
@@ -23,9 +24,113 @@ function normalizedLabel(label: string): string | undefined {
23
24
  return normalized;
24
25
  }
25
26
 
27
+ function publicCopyExclusion(normalized: string): PublicCopyScan['excludedSources'][number]['reason'] | undefined {
28
+ if (normalized.startsWith('docs/goals/')) return 'internal-goal-document';
29
+ if (!normalized.startsWith('docs/marketing/')) return undefined;
30
+ const relativePath = normalized.slice('docs/marketing/'.length);
31
+ const basename = relativePath.split('/').at(-1) ?? '';
32
+ // These files are published records or release-specific source notes, not
33
+ // current copy candidates. Preserve their exact product names and evidence.
34
+ if (/^(?:BLOG-02-the-agent-drives-the-agent-|BLOG-03-it-drives-the-terminal-itself-|DRAFT-0\.2\.(?:7|8)-announcement-|DRAFT-0\.2\.7-known-issues-public-wording-|DRAFT-0\.2\.10-announcement-|PRFAQ-release-0\.2\.4-|SCRIPT-ax-demo-1008-|VO-teaser-v2-)/i.test(basename)
35
+ || /^docs\/marketing\/launch\/(?:0\.2\.8-loop-final\/|0\.2\.8-rehearsal\/PRFAQ-generated\.md$|0\.2\.11-cut-)/i.test(normalized)) {
36
+ return 'internal-marketing-source';
37
+ }
38
+ if (normalized.startsWith('docs/marketing/') && /^(?:BRIEF-|DOCS-|EVENT-|GUIDE-|MANUAL-|MAP-|MATURITY-|PLAN-|RESEARCH-|RFC-|SCENARIO-|STORYBOARD-|STORYLINE-|STRATEGY-|SOURCES-)/i.test(basename)) {
39
+ return 'internal-marketing-source';
40
+ }
41
+ if (normalized.startsWith('docs/marketing/') && /^DRAFT-persona-/i.test(basename)) return 'internal-marketing-source';
42
+ if (/^docs\/marketing\/teaser-v\d+\/MANIFEST\.md$/i.test(normalized) || normalized === 'docs/marketing/decks/media/README.md') {
43
+ return 'asset-manifest';
44
+ }
45
+ return undefined;
46
+ }
47
+
48
+ function isRequestedPublicCopyPath(normalized: string): boolean {
49
+ return normalized === 'README.md' || normalized.startsWith('docs/marketing/');
50
+ }
51
+
52
+ function maskSpan(text: string, start: number, end: number): string {
53
+ return text.slice(start, end).replace(/[^\r\n]/g, ' ');
54
+ }
55
+
56
+ /** Keep line offsets while limiting brand checks to visible prose, not code, comments, metadata, or link targets. */
57
+ function visibleMarkdownProse(text: string): string {
58
+ let visible = text;
59
+ const masks: RegExp[] = [
60
+ /^---\r?\n[\s\S]*?\r?\n---\s*$/gm,
61
+ /<!--[\s\S]*?-->/g,
62
+ /^\s*(```|~~~)[^\r\n]*\r?\n[\s\S]*?^\s*\1\s*$/gm,
63
+ /`[^`\r\n]*`/g,
64
+ /\]\((?:\\.|[^)])*\)/g,
65
+ /^>\s*🧾\s*\*\*공개 전 할 일\*\*[\s\S]*?(?=^[^>\r\n]|$(?![\s\S]))/gm,
66
+ /^##\s*(?:\d+\.\s*)?(?:칸|출처 목록|sources|evidence|게시 직전 다시 잴 것|기준선|올리기 전 확인)(?:\s|$)[\s\S]*?(?=^##\s|$(?![\s\S]))/gim,
67
+ /^>\s*✏️\s*\*\*착지·실측된 것만\.[^\r\n]*$/gm,
68
+ /https?:\/\/[^\s)>]+/gi,
69
+ /\b(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,}(?:\/[^\s)>]*)?/g,
70
+ ];
71
+ for (const pattern of masks) {
72
+ const matches = [...visible.matchAll(pattern)].map((match) => ({ start: match.index!, end: match.index! + match[0].length }));
73
+ for (const match of matches.reverse()) visible = visible.slice(0, match.start) + maskSpan(visible, match.start, match.end) + visible.slice(match.end);
74
+ }
75
+ return visible;
76
+ }
77
+
78
+ const PUBLIC_COMPANY_NAMES = /\b(?:OpenAI|ChatGPT|Codex|Claude(?:\s+Code)?|Anthropic|Gemini|Google|Grok|xAI|Devin|Cognition|OpenHands|Replit(?:\s+Agent(?:\s+\d+)?)?|Factory(?:\s+AI)?|Hermes|OpenClaw|Manus)\b/gi;
79
+ const PUBLIC_PLACEHOLDER = /\b(?:another coding agent|another agent platform)\b/gi;
80
+ const PUBLIC_PLACEHOLDER_LIST = /\ba coding tool\s*[,·]\s*the coding CLI\s*[,·]\s*an AI model\s*[,·]\s*a model provider\b/gi;
81
+ const UNSUPPORTED_COMPARISON = /\b(?:better|faster|cheaper|safer|worse|superior|inferior)\s+than\b|\b(?:vs\.?|versus|compared\s+(?:with|to))\b|(?:보다\s*(?:낫|빠르|저렴|좋|강력|안전|우수))/i;
82
+
83
+ function companyNameMentions(text: string): number {
84
+ return [...text.matchAll(PUBLIC_COMPANY_NAMES)].length;
85
+ }
86
+
87
+ function placeholderMentions(text: string): number {
88
+ return [...text.matchAll(PUBLIC_PLACEHOLDER)].length + [...text.matchAll(PUBLIC_PLACEHOLDER_LIST)].length;
89
+ }
90
+
91
+ function hasSupportedComparisonEvidence(text: string): boolean {
92
+ const hasSource = /\b(?:source|citation)\b|출처/i.test(text);
93
+ const hasMeasurement = /\b(?:measur|benchmark|tested|test conditions?)\w*\b|실측|측정|측정 조건/i.test(text);
94
+ return hasSource && hasMeasurement;
95
+ }
96
+
97
+ function measuredScopeMatchesClaim(claim: string): boolean {
98
+ const quantity = String.raw`(\d+(?:\.\d+)?)`;
99
+ const unit = String.raw`(jobs?|tasks?|workflows?|items?|건|개|작업)`;
100
+ const claimScope = new RegExp(String.raw`(?:completes?|processes?|handles?|완료|처리)\s*${quantity}\s*${unit}`, 'i').exec(claim);
101
+ const measuredScope = new RegExp(String.raw`(?:measured|measurement|실측|측정).*?(?:scope|range|범위).*?(?:limited to|only|한정|범위 내)\s*${quantity}\s*${unit}`, 'i').exec(claim);
102
+ if (!claimScope || !measuredScope) return false;
103
+ const normalizeUnit = (value: string): string => {
104
+ const normalized = value.toLowerCase();
105
+ if (normalized === 'job' || normalized === 'jobs' || normalized === 'task' || normalized === 'tasks' || normalized === 'workflow' || normalized === 'workflows' || normalized === 'item' || normalized === 'items') return normalized.replace(/s$/, '');
106
+ return normalized;
107
+ };
108
+ return claimScope[1] === measuredScope[1] && normalizeUnit(claimScope[2]!) === normalizeUnit(measuredScope[2]!);
109
+ }
110
+
111
+ function oneClickFindings(text: string, source: string): PublicCopyFinding[] {
112
+ const lines = text.split(/\r?\n/);
113
+ const findings: PublicCopyFinding[] = [];
114
+ for (let index = 0; index < lines.length; index++) {
115
+ const claims = lines[index]!.split(/(?<=[.!?。!?;;])\s*/).filter((segment) => /\bone[ -]click\b|원\s*클릭/i.test(segment));
116
+ for (const claim of claims) {
117
+ const hasLimitedClaimScope = !/(?:every|all|entire|unlimited|모든|전체|무제한)/i.test(claim)
118
+ && /(?:completes?|processes?|handles?|완료|처리)/i.test(claim)
119
+ && /\b\d+(?:\.\d+)?\s+(?:jobs?|tasks?|workflows?|items?)\b|\d+(?:\.\d+)?\s*(?:건|개|작업)/i.test(claim);
120
+ const hasMeasuredScope = hasLimitedClaimScope
121
+ && measuredScopeMatchesClaim(claim)
122
+ && !/(?:no|not|without|unmeasured|측정되지 않|범위 없음|범위가 없|한정되지 않)/i.test(claim);
123
+ if (!hasMeasuredScope) findings.push({ source, line: index + 1, rule: 'ONE-CLICK-MEASURED-SCOPE' });
124
+ const hasPublicationApprovalStatus = /(?:approved for publication|publication approved|publication approval pending|publication not approved|not approved for publication|unapproved|pending|게시\s*승인(?:됨|완료)?|게시\s*미승인|게시\s*승인\s*보류|게시\s*승인\s*상태\s*:\s*(?:승인|미승인|보류)|승인되지 않)/i.test(claim);
125
+ if (!hasPublicationApprovalStatus) findings.push({ source, line: index + 1, rule: 'ONE-CLICK-APPROVAL-STATUS' });
126
+ }
127
+ }
128
+ return findings;
129
+ }
130
+
26
131
  function allowedNormalizedLabel(normalized: string | undefined): boolean {
27
132
  if (!normalized) return false;
28
- if (normalized === 'PR-BODY') return true;
133
+ if (normalized === 'PR-BODY' || normalized === 'README.md') return true;
29
134
  if (normalized.split('/').some((part) => part === '..' || part === '')) return false;
30
135
  if (!['.md', '.mdx', '.txt', '.html', '.htm'].includes(extname(normalized).toLowerCase())) return false;
31
136
  return ['docs/', 'release/public/docs/', 'blog/', 'posts/', 'content/blog/', 'content/posts/']
@@ -36,30 +141,49 @@ function allowedNormalizedLabel(normalized: string | undefined): boolean {
36
141
  export function scanPublicCopy(inputs: readonly PublicCopyInput[], matchPrivateCandidate: PatentLineMatcher, rulesPath?: string): PublicCopyScan {
37
142
  const findings: PublicCopyFinding[] = [];
38
143
  const excludedSources: PublicCopyScan['excludedSources'] = [];
144
+ const documents: PublicCopyScan['documents'] = [];
39
145
  let brandRulesAvailable = true;
40
146
  let patentLedgerAvailable = true;
41
147
  for (const input of inputs) {
42
148
  const label = normalizedLabel(input.label);
43
149
  if (!allowedNormalizedLabel(label)) throw new Error(`공개 문면 입력 경로가 허용 목록 밖입니다: ${input.label}`);
44
- // Goal specs are internal execution artifacts, not customer-facing copy.
45
- // Counting their acceptance criteria as marketing measurements created a
46
- // high false-positive rate in the 30-PR audit.
47
- if (label?.startsWith('docs/goals/')) {
48
- excludedSources.push({ source: input.label, reason: 'internal-goal-document' });
150
+ const excludedReason = label ? publicCopyExclusion(label) : undefined;
151
+ if (excludedReason) {
152
+ excludedSources.push({ source: input.label, reason: excludedReason });
49
153
  continue;
50
154
  }
155
+ const before = findings.length;
156
+ const prose = visibleMarkdownProse(input.text);
157
+ if (label && isRequestedPublicCopyPath(label)) findings.push(...oneClickFindings(prose, input.label));
51
158
  try {
52
- const brandFindings = checkBrandText(input.text, input.label, 'public-docs', rulesPath);
159
+ const brandFindings = checkBrandText(prose, input.label, 'public-docs', rulesPath)
160
+ .filter((hit) => hit.id !== 'BRAND-COMPETITOR-NAME');
53
161
  // Publication-specific promise/measurement rules apply to this explicit
54
162
  // shadow scan without changing the existing generic brand-check scopes.
55
- const publicationFindings = checkBrandText(input.text, input.label, 'release-notes', rulesPath)
163
+ const publicationFindings = checkBrandText(prose, input.label, 'release-notes', rulesPath)
56
164
  .filter((hit) => hit.id === 'BRAND-SOON' || hit.id === 'B4-NUMBER-SOURCE');
57
- for (const hit of [...brandFindings, ...publicationFindings]) {
58
- findings.push({ source: input.label, line: hit.line, rule: hit.id });
165
+ const brandLines = new Set([...brandFindings, ...publicationFindings].map((hit) => `${hit.line}:${hit.id}`));
166
+ for (const line of prose.split(/\r?\n/).map((text, index) => ({ text, line: index + 1 }))) {
167
+ if (UNSUPPORTED_COMPARISON.test(line.text) && PUBLIC_COMPANY_NAMES.test(line.text)
168
+ && !hasSupportedComparisonEvidence(line.text)) {
169
+ brandLines.add(`${line.line}:BRAND-UNSUPPORTED-COMPARISON`);
170
+ }
171
+ PUBLIC_COMPANY_NAMES.lastIndex = 0;
172
+ UNSUPPORTED_COMPARISON.lastIndex = 0;
173
+ if (PUBLIC_PLACEHOLDER.test(line.text) || PUBLIC_PLACEHOLDER_LIST.test(line.text)) {
174
+ brandLines.add(`${line.line}:PUBLIC-COPY-PLACEHOLDER`);
175
+ }
176
+ PUBLIC_PLACEHOLDER.lastIndex = 0;
177
+ PUBLIC_PLACEHOLDER_LIST.lastIndex = 0;
178
+ }
179
+ for (const key of brandLines) {
180
+ const [line, rule] = key.split(':');
181
+ findings.push({ source: input.label, line: Number(line), rule: rule! });
59
182
  }
60
183
  } catch { brandRulesAvailable = false; }
61
184
  try { for (const line of matchPrivateCandidate(input.text)) findings.push({ source: input.label, line, rule: 'PRIVATE-PATENT-CANDIDATE' }); }
62
185
  catch { patentLedgerAvailable = false; }
186
+ documents.push({ source: input.label, findings: findings.length - before, companyNameMentions: companyNameMentions(prose), placeholderMentions: placeholderMentions(prose) });
63
187
  }
64
188
  if (inputs.length === 0 || excludedSources.length === inputs.length) {
65
189
  // No scanner ran, so availability must not claim a successful measurement.
@@ -69,6 +193,7 @@ export function scanPublicCopy(inputs: readonly PublicCopyInput[], matchPrivateC
69
193
  return {
70
194
  findings: findings.sort((a, b) => a.source.localeCompare(b.source) || a.line - b.line || a.rule.localeCompare(b.rule)),
71
195
  excludedSources,
196
+ documents,
72
197
  brandRulesAvailable, patentLedgerAvailable,
73
198
  };
74
199
  }
@@ -77,6 +202,26 @@ export function lintPublicCopy(inputs: readonly PublicCopyInput[], matchPrivateC
77
202
  return scanPublicCopy(inputs, matchPrivateCandidate).findings;
78
203
  }
79
204
 
205
+ function collectPublicCopyFiles(paths: readonly string[], root: string): string[] {
206
+ const collected = new Set<string>();
207
+ const visit = (path: string): void => {
208
+ const absolute = resolve(root, path);
209
+ const stat = statSync(absolute);
210
+ if (stat.isDirectory()) {
211
+ for (const entry of readdirSync(absolute, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
212
+ if (entry.isDirectory()) visit(relative(root, join(absolute, entry.name)));
213
+ else if (entry.isFile() && ['.md', '.mdx', '.txt', '.html', '.htm'].includes(extname(entry.name).toLowerCase())) {
214
+ collected.add(relative(root, join(absolute, entry.name)));
215
+ }
216
+ }
217
+ return;
218
+ }
219
+ collected.add(relative(root, absolute));
220
+ };
221
+ for (const path of paths) visit(path);
222
+ return [...collected].sort();
223
+ }
224
+
80
225
  export function run(argv: readonly string[], root = process.cwd(), ledger = new PatentLedger()): number {
81
226
  const files: string[] = [];
82
227
  let bodyFile: string | undefined;
@@ -97,15 +242,14 @@ export function run(argv: readonly string[], root = process.cwd(), ledger = new
97
242
  } else throw new Error(`알 수 없는 옵션: ${arg}`);
98
243
  }
99
244
  if (!files.length && !bodyFile) throw new Error('usage: bun scripts/public-copy-lint.ts [--files <docs...>] [--pr-body-file <file> [--pr-body-label <repo-relative-label>]] [--json]');
100
- const inputs: PublicCopyInput[] = files.map((file) => ({
101
- label: relative(root, resolve(root, file)).split(sep).join('/'), text: readFileSync(resolve(root, file), 'utf8'),
245
+ const inputs: PublicCopyInput[] = collectPublicCopyFiles(files, root).map((file) => ({
246
+ label: file.split(sep).join('/'), text: readFileSync(resolve(root, file), 'utf8'),
102
247
  }));
103
248
  if (bodyFile) inputs.push({ label: bodyLabel, text: readFileSync(resolve(root, bodyFile), 'utf8') });
104
- const matchPrivateCandidate: PatentLineMatcher = (text) => {
105
- return ledger.unapprovedCandidateLineNumbers(text);
106
- };
249
+ const matchPrivateCandidate: PatentLineMatcher = (text) => ledger.unapprovedCandidateLineNumbers(text);
250
+ // The CLI caller uses the same scope-aware production scanner covered by focused tests.
107
251
  const scan = scanPublicCopy(inputs, matchPrivateCandidate);
108
- if (json) console.log(JSON.stringify({ mode: 'warning-only', ...scan }));
252
+ if (json) console.log(JSON.stringify({ mode: 'warning-only', documentsScanned: scan.documents.length, ...scan }));
109
253
  else {
110
254
  for (const finding of scan.findings) console.log(`${finding.source}:${finding.line}:WARN:${finding.rule}`);
111
255
  for (const excluded of scan.excludedSources) console.log(`${excluded.source}:SKIP:${excluded.reason}`);
@@ -6,7 +6,6 @@ set -u
6
6
 
7
7
  files=(
8
8
  scripts/ratchets/test-interference-patterns.test.ts
9
- scripts/ratchets/next-tui-entry-budget.test.ts
10
9
  src/domains/finance-cli.test.ts
11
10
  src/instance/state-dir-provenance-ratchet.test.ts
12
11
  src/self-implement/graph-yaml.test.ts
@@ -0,0 +1,117 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { acquireLockSync } from '../../src/storage/file-lock.js';
4
+
5
+ /** Deterministic recovery policy for release gate incidents. Side effects are supplied by callers. */
6
+ export type GateAutohealCause = 'shard-pod-death' | 'timeout' | 'host-down' | 'interference' | 'true-regression' | 'environment';
7
+ export type GateAutohealAction = 'reroute-shard' | 'retry-shard' | 'partial-resume' | 'host-switch' | 'hitl';
8
+
9
+ export interface GateAutohealInput {
10
+ cause: GateAutohealCause;
11
+ signature: string;
12
+ shardElapsedMs: number;
13
+ overallElapsedMs: number;
14
+ priorSameSignatureCount?: number;
15
+ shardKeys?: readonly string[];
16
+ }
17
+
18
+ export interface GateAutohealDecision {
19
+ action: GateAutohealAction;
20
+ cause: GateAutohealCause;
21
+ signature: string;
22
+ reason: string;
23
+ shardElapsedMs: number;
24
+ overallElapsedMs: number;
25
+ shardKey?: string;
26
+ }
27
+
28
+ export interface GateResultForAutoheal {
29
+ outcome: 'ok' | 'regression' | 'error';
30
+ introduced?: readonly string[];
31
+ error?: string;
32
+ durationMs: number;
33
+ stalledShards?: readonly { shard: number; files: readonly string[]; reason: string; detail?: string; stall?: { sinceCheckoutMs: number } }[];
34
+ interferenceErrors?: readonly string[];
35
+ loadFlaky?: readonly string[];
36
+ }
37
+
38
+ interface GateAutohealLedger {
39
+ schema: 1;
40
+ overallElapsedMs: number;
41
+ shards: Record<string, number>;
42
+ signatures: Record<string, number>;
43
+ }
44
+
45
+ const emptyLedger = (): GateAutohealLedger => ({ schema: 1, overallElapsedMs: 0, shards: {}, signatures: {} });
46
+
47
+ /** Persist the incident budget across graph-node process restarts, keyed by release version and run id. */
48
+ export function decideAndRecordGateAutoheal(input: GateAutohealInput & { version: string; runId: string; shardKey: string; storeRoot: string }): GateAutohealDecision {
49
+ const path = join(input.storeRoot, 'release', input.version, 'gate-autoheal', `${input.runId.replace(/[^a-zA-Z0-9_.-]/g, '_')}.json`);
50
+ mkdirSync(dirname(path), { recursive: true });
51
+ const unlock = acquireLockSync(`${path}.lock`, { breakDeadHolder: true });
52
+ try {
53
+ let ledger = emptyLedger();
54
+ if (existsSync(path)) {
55
+ try {
56
+ const parsed = JSON.parse(readFileSync(path, 'utf8')) as GateAutohealLedger;
57
+ if (parsed.schema !== 1 || !Number.isFinite(parsed.overallElapsedMs) || !parsed.shards || !parsed.signatures) throw new Error('invalid ledger');
58
+ ledger = parsed;
59
+ } catch {
60
+ return { action: 'hitl', cause: input.cause, signature: input.signature, reason: 'autoheal history unreadable; refusing another automatic action', shardElapsedMs: 0, overallElapsedMs: 0, shardKey: input.shardKey };
61
+ }
62
+ }
63
+ const shardKeys = [...new Set(input.shardKeys?.length ? input.shardKeys : [input.shardKey])];
64
+ const signatureKey = `${input.shardKey}:${input.signature}`;
65
+ const priorSameSignatureCount = ledger.signatures[signatureKey] ?? 0;
66
+ const elapsed = Math.max(0, input.shardElapsedMs);
67
+ const shards = { ...ledger.shards };
68
+ for (const key of shardKeys) shards[key] = (shards[key] ?? 0) + elapsed;
69
+ const shardElapsedMs = Math.max(0, ...shardKeys.map((key) => shards[key] ?? 0));
70
+ const overallElapsedMs = ledger.overallElapsedMs + Math.max(0, input.overallElapsedMs);
71
+ const decision = decideGateAutoheal({ ...input, shardElapsedMs, overallElapsedMs, priorSameSignatureCount });
72
+ ledger = { schema: 1, overallElapsedMs, shards,
73
+ signatures: { ...ledger.signatures, [signatureKey]: priorSameSignatureCount + 1 } };
74
+ const temp = `${path}.${process.pid}.tmp`;
75
+ writeFileSync(temp, `${JSON.stringify(ledger, null, 2)}\n`, { mode: 0o600 });
76
+ renameSync(temp, path);
77
+ return { ...decision, shardKey: input.shardKey };
78
+ } finally { unlock(); }
79
+ }
80
+
81
+ export const GATE_AUTOHEAL_SHARD_CAP_MS = 60 * 60 * 1000;
82
+ export const GATE_AUTOHEAL_OVERALL_CAP_MS = 90 * 60 * 1000;
83
+
84
+ /** One signature may be acted on once; seeing it again, or crossing either timebox, stops in HITL. */
85
+ export function decideGateAutoheal(input: GateAutohealInput): GateAutohealDecision {
86
+ const shardElapsedMs = Math.max(0, input.shardElapsedMs);
87
+ const overallElapsedMs = Math.max(0, input.overallElapsedMs);
88
+ let action: GateAutohealAction;
89
+ let reason: string;
90
+ if (shardElapsedMs >= GATE_AUTOHEAL_SHARD_CAP_MS) {
91
+ action = 'hitl'; reason = 'per-shard timebox exceeded';
92
+ } else if (overallElapsedMs >= GATE_AUTOHEAL_OVERALL_CAP_MS) {
93
+ action = 'hitl'; reason = 'overall timebox exceeded';
94
+ } else if ((input.priorSameSignatureCount ?? 0) >= 1) {
95
+ action = 'hitl'; reason = 'same incident signature repeated';
96
+ } else {
97
+ switch (input.cause) {
98
+ case 'shard-pod-death': action = 'reroute-shard'; reason = 'replace failed shard Pod'; break;
99
+ case 'timeout': action = 'retry-shard'; reason = 'retry the timed-out shard within its budget'; break;
100
+ case 'host-down': action = 'host-switch'; reason = 'move the gate to a healthy host'; break;
101
+ case 'interference': action = 'partial-resume'; reason = 'resume only the unmeasured or affected work'; break;
102
+ case 'true-regression': action = 'hitl'; reason = 'measured regression requires a human decision'; break;
103
+ case 'environment': action = 'hitl'; reason = 'environment cause is not safe to repair automatically'; break;
104
+ }
105
+ }
106
+ return { action, cause: input.cause, signature: input.signature, reason, shardElapsedMs, overallElapsedMs };
107
+ }
108
+
109
+ export function gateAutohealCause(result: GateResultForAutoheal): GateAutohealCause | undefined {
110
+ if (result.outcome === 'ok') return undefined;
111
+ if (result.outcome === 'regression' && (result.introduced?.length ?? 0) > 0) return 'true-regression';
112
+ if (/host.*(?:down|unreachable)|(?:down|unreachable).*host|ssh.*(?:failed|timeout)/i.test(result.error ?? '')) return 'host-down';
113
+ if (result.stalledShards?.some((shard) => /timeout/.test(shard.reason))) return 'timeout';
114
+ if ((result.interferenceErrors?.length ?? 0) > 0 || (result.loadFlaky?.length ?? 0) > 0) return 'interference';
115
+ if (result.stalledShards?.some((shard) => /pod.*(?:deleted|evicted|terminated|lost|not found)|(?:pod-dead|pod-evicted|pod-deleted)/i.test(`${shard.reason} ${shard.detail ?? ''}`))) return 'shard-pod-death';
116
+ return 'environment';
117
+ }
@@ -35,6 +35,7 @@ export interface GateBaselineReceipt {
35
35
  imageDigest: string | null;
36
36
  files: number;
37
37
  shards: number;
38
+ attributionRecheck?: { summary: number; observed: number; identified: number; baselineResult: string; targetFiles: string[] };
38
39
  }
39
40
 
40
41
  /** A direct hard rehearsal has no graph run state. Pin the graph and recipe bytes at its Git SHA. */
@@ -83,11 +84,17 @@ export function gateGraphPins(root: string, runId: string | undefined): { graphS
83
84
  }
84
85
 
85
86
  export function gateBaselineReceipt(input: { root: string; version: string; commit: string; fullSweep: boolean;
86
- graphPins: { graphSha: string; recipeSha: string } | null; envFingerprint: string }): GateBaselineReceipt {
87
+ graphPins: { graphSha: string; recipeSha: string } | null; envFingerprint: string;
88
+ attributionRecheck?: { summary: number; observed: number; identified: number; baselineResult: string; targetFiles: string[] } }): GateBaselineReceipt {
87
89
  const { root, version, commit, graphPins, envFingerprint } = input;
88
90
  const base = { schema: 1 as const, version, commit, graphSha: graphPins?.graphSha ?? null,
89
91
  recipeSha: graphPins?.recipeSha ?? null, envFingerprint, imageDigest: null as string | null, files: 0, shards: 0 };
90
92
  const invalid = (reason: string): GateBaselineReceipt => ({ ...base, valid: false, reason });
93
+ if (input.attributionRecheck) {
94
+ const evidence = input.attributionRecheck;
95
+ return { ...invalid(`failure attribution unresolved after baseline recheck (${evidence.baselineResult}): summary=${evidence.summary}, observed=${evidence.observed}, identified=${evidence.identified}`),
96
+ attributionRecheck: { ...evidence, targetFiles: [...evidence.targetFiles].sort() } };
97
+ }
91
98
  if (!input.fullSweep) return invalid('gate was not a complete clean full sweep');
92
99
  if (!graphPins) return invalid('pinned graph or recipe SHA absent');
93
100
  if (!SHA256.test(envFingerprint)) return invalid('gate environment fingerprint absent');
@@ -4,9 +4,28 @@ export interface FailureDiff {
4
4
  common: string[];
5
5
  }
6
6
 
7
+ /** One failure identity may be printed more than once when a host retries or concatenates a test run. */
8
+ export function collapseGateFailureAttempts(ids: readonly string[]): { failures: string[]; observed: number; collapsed: number } {
9
+ const failures = [...new Set(ids)].sort();
10
+ return { failures, observed: ids.length, collapsed: ids.length - failures.length };
11
+ }
12
+
13
+ export class GateFailureAttributionMismatch extends Error {
14
+ constructor(readonly label: string, readonly summary: number, readonly observed: number,
15
+ readonly identified: number, readonly collapsed: number, readonly failures: readonly string[]) {
16
+ super(`${label} incomplete (failure attribution mismatch: summary=${summary}, observed=${observed}, identified=${identified})`);
17
+ this.name = 'GateFailureAttributionMismatch';
18
+ }
19
+ }
20
+
7
21
  /** Bun's file header followed by `(fail) name` lines is the identity source. */
8
22
  export function parseFailures(output: string): string[] {
9
- const failures = new Set<string>();
23
+ return [...new Set(parseFailureAttempts(output))].sort();
24
+ }
25
+
26
+ /** Raw reporter rows, retaining repeated identities so gate attribution can distinguish retries from missing names. */
27
+ export function parseFailureAttempts(output: string): string[] {
28
+ const failures: string[] = [];
10
29
  let file: string | undefined;
11
30
  for (const raw of output.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '').split(/\r?\n/)) {
12
31
  const line = raw.trim();
@@ -14,9 +33,9 @@ export function parseFailures(output: string): string[] {
14
33
  if (header) { file = header[1]; continue; }
15
34
  // Line-start only: a title/body `(fail)` is not a reporter row. Trailing CR is still a real Bun fail row.
16
35
  const failed = /^\(fail\)[ \t]+(.+?)(?:[ \t]+\[[\d.]+(?:ms|s)\])?[ \t]*\r?$/.exec(raw);
17
- if (failed && file) failures.add(`${file} > ${failed[1]!.trim()}`);
36
+ if (failed && file) failures.push(`${file} > ${failed[1]!.trim()}`);
18
37
  }
19
- return [...failures].sort();
38
+ return failures;
20
39
  }
21
40
 
22
41
  /** GATE-INTRO-RECHECK (0.2.19) — the failures that are bun's «timed out» shape: a `(fail) name` line whose next line is