elanous 0.2.36 → 0.2.37

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 (630) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → 8kITumG9GAZ1LwT9POrAR}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/1041-5841aae848fb6403.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1087.3177e54f672dc526.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1105.efe1e13503ac7a33.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1224.2ceca6c180d5130b.js +62 -0
  8. package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 1262.a89bb27a5b2f844e.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/1417-1768233ac92f8a5d.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/1612.81bbc19af06af16c.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 1746.3563617ea64023a3.js} +1 -1
  12. package/apps/pwa/out/_next/static/chunks/1766.728d42053070bb2d.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1773.d38e945481e04125.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1974-c12f9600da3d3c26.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1ed5e8af.cf424815c7c0efad.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 2002-a43a3f380df873ec.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/2061.7232dc9dc058417f.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/210.90b2cbd64926cf34.js +32 -0
  19. package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 2283.edd9627b7bdfb546.js} +2 -2
  20. package/apps/pwa/out/_next/static/chunks/2318-450e75d07605b8fe.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 2375.bf364c85dbb6f085.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2479-fe7e188bd9402d14.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2514.03b60f266531a015.js +148 -0
  25. package/apps/pwa/out/_next/static/chunks/2526-a657538869888604.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2533-6f0341ff075809e9.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2676.e7994c695ef0f30d.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2734.3ffdf54254fb6f99.js +27 -0
  29. package/apps/pwa/out/_next/static/chunks/2770-23252bf3a37880b9.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/2969.66b8b545139d1544.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/3128.a9210d08800ea6a8.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 3199.6a1a9b0e6cd01dc6.js} +1 -1
  33. package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/{2986.45d7652e4f13557e.js → 3578.4e9f9948a9a6f2f4.js} +2 -2
  35. package/apps/pwa/out/_next/static/chunks/3760-2909ddb9279281cd.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3825.1921b5901bf33dce.js +36 -0
  37. package/apps/pwa/out/_next/static/chunks/3994-63eb884ed0547011.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/4036.d54e55e1ebf5acdc.js +90 -0
  39. package/apps/pwa/out/_next/static/chunks/4115.5b438b99f0ae729f.js +226 -0
  40. package/apps/pwa/out/_next/static/chunks/4269.d8f9f34bb0fc6c43.js +287 -0
  41. package/apps/pwa/out/_next/static/chunks/431-4eed5bd2c5fe1719.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/{7481.39f7a4654907bf6e.js → 4313.76f232c304a15bde.js} +1 -1
  43. package/apps/pwa/out/_next/static/chunks/4324.c99ba3e83eb1b691.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4337e36d.f42c3b391b3d8f20.js +122 -0
  45. package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 4383.18e5c54db3a22c88.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4599-96eff3f2a9c242c1.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{3757-180308bc61021b05.js → 4725-34bed25720cc326b.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/4825-a9d9d4e9f5892309.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4833-7934c592c5569f00.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4879-68518f547a207aff.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4896.f9b70285363b27b2.js +24 -0
  52. package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 4931.95cc6dbd230774ca.js} +3 -3
  53. package/apps/pwa/out/_next/static/chunks/4937-28d437999b77c9dd.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/49aa54ab.80f39398e0ed0f30.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5046.7fd5cbd859299448.js} +2 -2
  56. package/apps/pwa/out/_next/static/chunks/5056.482687319b82638e.js +104 -0
  57. package/apps/pwa/out/_next/static/chunks/506.16b83d56a437a9ee.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5260-20593b0a25d0afbc.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5404.cc4e9fec26fd5925.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/576.485e83e3f3dec19a.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5832-a6be14e663f65726.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5854-56648a9fe646b9a0.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 58edce7d.f1b0c72acf13b123.js} +1 -1
  64. package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +93 -0
  65. package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 5952.294fc574a8625184.js} +1 -1
  66. package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 5f6af561-f90b7a67f4f75d13.js} +1 -1
  67. package/apps/pwa/out/_next/static/chunks/6168.17749aa3905fa073.js +74 -0
  68. package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 6252.240578f10952e091.js} +1 -1
  69. package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 6680.6a693c28aae4cd19.js} +2 -2
  71. package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 6745-5a63492933959dd9.js} +3 -3
  72. package/apps/pwa/out/_next/static/chunks/6758.e7fbf532953c0783.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6795.0cb8a59730d99703.js +149 -0
  74. package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 6819.be5c9c4d67f22922.js} +3 -3
  75. package/apps/pwa/out/_next/static/chunks/6877-84d47b7e85d0c41e.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6971-fb5f9dc0a2cb5d2d.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → 709a918c.4fd3b4e2a32cb4e3.js} +1 -1
  78. package/apps/pwa/out/_next/static/chunks/717.522b08685979b814.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/7191.e41eb8f455c7f089.js +41 -0
  80. package/apps/pwa/out/_next/static/chunks/7233.8e744b7513119409.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7238-97c2226f80504bd8.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7285.307963afcf7e7660.js +24 -0
  83. package/apps/pwa/out/_next/static/chunks/7299-fbe4b8c47a87614a.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7314.df0d95930b0c3f50.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7406.c0589fdf2ee66629.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 7424.c0fe2a595d4232b5.js} +1 -1
  87. package/apps/pwa/out/_next/static/chunks/752-90e3e7daad3d8e39.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7524-bcd3d9928c6842d9.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7549.9a4de3bf231cfc52.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/757-4fbaf50942b8c424.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/765.76ae970ceb597b5b.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 7867.e8725745ddd1d940.js} +4 -4
  93. package/apps/pwa/out/_next/static/chunks/{6466-92e65a48490b68a9.js → 7893-e444a1b0809cd1e4.js} +1 -1
  94. package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{ccae1c4b-0cf414f5eff1b10d.js → 7c5ed21f-f286708e57cf88f7.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/8030-aa66b478b53dbfca.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8051.c88c07dacbbc5f21.js +8 -0
  98. package/apps/pwa/out/_next/static/chunks/{3840-5825d56d46976a92.js → 8080-40d781e7704d3671.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8149.80e402d4345e8dae.js +77 -0
  100. package/apps/pwa/out/_next/static/chunks/8205.50a5268f4e12ba0b.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8231.a128feaa6f8b6079.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/85.4ddb1dda2ea3ffa2.js +286 -0
  103. package/apps/pwa/out/_next/static/chunks/8537.26517a09e8247beb.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8595-e9b7081ab773a61f.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8821-30cc65a61a60951f.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8905.b3385aadb7b133e6.js +79 -0
  107. package/apps/pwa/out/_next/static/chunks/8983.246bb3a1ac38f50f.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → 8c58d09b.e8724a299658d86f.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/9072.18342f5941a1f3ec.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/9123.9df04866b2d6e00f.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 9151.a2c51e93f9156dae.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/9175-7d383df15a82e2be.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9181-bf89c07ce5b8f599.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/920-429bbc4504b45f71.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9207.625edf45d656151c.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9378.d2575c6ffd6dd756.js +94 -0
  117. package/apps/pwa/out/_next/static/chunks/957.db5b5c4d32a35240.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{190.285c832bd9626f8c.js → 958.53a8dcf4729e6997.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9647.8f0cd0898c592a29.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9665-26abb02665704c2c.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9703.e7d81b6faef1050a.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9882-7a9164b3c2dacbe5.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/9998.b74e033efadecd10.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c604fb980a634d88.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ec2d8a4979ca9075.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cb6add08ad3c7660.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-e2eaa321ec223fe6.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-5b8a09c475b5f844.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-91a77daedfbac191.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-f37fc5e974bda39b.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-91429a0b78415a94.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/page-b95798b58263b910.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-763d53e175e17aa1.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-d55023204055b12f.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-89d2140d78abc810.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-82dc069abfe27f55.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-25d9eee7beb552c0.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-770b4594c713ee97.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c604fb980a634d88.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-ba8e0dcae4f83985.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-5c112c6d7c33656e.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-09788e1aa9a87db6.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/{page-e2de2e59111c9aad.js → page-3337c6a1328c2674.js} +1 -1
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/{page-f2b2e4bf6e981450.js → page-89acd5d68c0bc560.js} +1 -1
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-5c13e2c76371d797.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-653a9f18642825c6.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-2af16e62c12f22df.js → page-fe986fe79b107546.js} +1 -1
  148. package/apps/pwa/out/_next/static/chunks/app/morning/page-1e5da297557d2354.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-91ea9f5869a40943.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-7824e21b999962e2.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-53d00a60cc75a922.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-88a1edbff62eaf1d.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e931248b3f9574b.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/page-443364c9e4a23b31.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/page-b9af2ac1c4737ce8.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-25ab9c614c14129b.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-dbcdcfac0a395a8a.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bf1de6645089ec58.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c4201761a5e839c9.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-c304f469ea5d70e4.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8e5a238cf5e50c9c.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c604fb980a634d88.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-32b526069ee50b3c.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-fb9e639c107f5f72.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-84220c776608cedc.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-e475618cbfd5ca2b.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/page-ac2c1e6169cfce57.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-fccd3020af2f8806.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-9c0d7198ff7b5a91.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-d54b1ec9b9c6430d.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8c4bef1791d732ca.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-46fcc0b0bbc6fbfe.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-c1c80e345fa9d6f5.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7dfda00afd172f5b.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → d9815f84.4918f682a45a8502.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → de8446d3.31b73eb239fecd7b.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/f21fd540.63ac75328926ed30.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/framework-77fdcc873519a6cd.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-app-d0d620d2ce235713.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-e0ef79c79337ba90.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-84b1bc71e3f9ce6a.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-2acb61f1363128cb.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-462ff5727ceb7824.js +1 -0
  184. package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +23 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/graphs/drafts/recipes.yaml +27 -7
  279. package/graphs/work/draft-close.yaml +54 -0
  280. package/graphs/work/green-close.yaml +37 -0
  281. package/graphs/work/recipes.yaml +46 -1
  282. package/graphs/work/run-research.yaml +35 -0
  283. package/package.json +1 -1
  284. package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
  285. package/scripts/boundary-proof-mapping-audit.ts +88 -0
  286. package/scripts/codex-fallback-live-probe.ts +17 -15
  287. package/scripts/fleet/node-setup.sh +32 -2
  288. package/scripts/fleet/run-light-worker.sh +9 -0
  289. package/scripts/gate-0226-failure-census.ts +507 -0
  290. package/scripts/goals/authoring-metrics.ts +258 -0
  291. package/scripts/graph-units/draft-close-node.ts +222 -0
  292. package/scripts/hook-order-sweep.ts +7 -4
  293. package/scripts/land-global-checks.ts +69 -1
  294. package/scripts/measure-nl-routing-corpus.ts +207 -2
  295. package/scripts/release-loop/docs-node.ts +140 -0
  296. package/scripts/release-loop/gate-closure.ts +48 -0
  297. package/scripts/release-loop/gate-diff.ts +2 -1
  298. package/scripts/release-loop/known-issues-node.ts +6 -4
  299. package/scripts/release-loop/notes-repair.ts +216 -0
  300. package/scripts/release-loop/prepare-node.ts +61 -5
  301. package/scripts/release-loop/resume-release.ts +114 -4
  302. package/scripts/release-loop/resume-test-traffic.ts +10 -0
  303. package/scripts/release-loop/version-node.ts +81 -12
  304. package/scripts/train/green-leg.ts +176 -0
  305. package/scripts/tui-continue-real-evidence.ts +47 -0
  306. package/scripts/ux-sim.ts +1 -1
  307. package/src/acp/client.ts +31 -5
  308. package/src/acp/core-turn-bridge.ts +6 -0
  309. package/src/acp/stderr-summary.ts +49 -0
  310. package/src/agent/monad-agent-turn.ts +1 -0
  311. package/src/agent/terminal-surface.ts +217 -0
  312. package/src/agent-substrate/pr-reviewer.ts +11 -3
  313. package/src/agent-substrate/self-review-cli.ts +343 -31
  314. package/src/autopilot/lineage/sources.ts +1 -1
  315. package/src/autopilot/pr-manager.ts +64 -13
  316. package/src/boot/daemon-runtime.ts +35 -3
  317. package/src/boot/daemon-tools/pty-shell.ts +2 -1
  318. package/src/budget/run-usage-rollup.ts +12 -7
  319. package/src/budget/unified-usage.ts +20 -0
  320. package/src/capture/tui-self-report.ts +32 -3
  321. package/src/cli/autopilot-cli.ts +24 -9
  322. package/src/cli/decisions-cli.ts +7 -4
  323. package/src/cli/doctor-cli.ts +116 -7
  324. package/src/cli/logs-cli.ts +357 -2
  325. package/src/cli/memory-cli.ts +30 -1
  326. package/src/cli/msg-cli.ts +15 -11
  327. package/src/cli/pr-granularity.ts +5 -3
  328. package/src/cli/release-checklist-read-cli.ts +109 -4
  329. package/src/cli/release-cli.ts +43 -10
  330. package/src/cli/self-update.ts +23 -5
  331. package/src/cli/self-utterances-cli.ts +13 -16
  332. package/src/cli/tasks-cli.ts +309 -11
  333. package/src/cli/usage-cli.ts +12 -10
  334. package/src/context-bus/claude-memory-import.ts +99 -0
  335. package/src/context-bus/long-term-memory.ts +125 -0
  336. package/src/core-turn/run-goal-loop.ts +5 -2
  337. package/src/core-turn/types.ts +2 -0
  338. package/src/dashboard/chat/acp-chat.ts +9 -0
  339. package/src/dashboard/index.ts +97 -13
  340. package/src/dashboard/input/agent-wake.ts +43 -0
  341. package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
  342. package/src/dashboard/replay-preview.ts +25 -0
  343. package/src/dashboard/slash-runtime/dashboard-handlers.ts +17 -8
  344. package/src/dashboard/synchronized-frame-output.ts +74 -0
  345. package/src/display/coordinator.ts +45 -12
  346. package/src/display/resize-listener.ts +41 -20
  347. package/src/display/synchronized-output-region.ts +60 -0
  348. package/src/domains/surface-events.ts +80 -1
  349. package/src/exec-requests/planner.ts +37 -2
  350. package/src/execution-loop/launch-gate.ts +4 -3
  351. package/src/git-fs/cli-stderr.ts +45 -0
  352. package/src/git-fs/gh-cli.ts +6 -3
  353. package/src/git-fs/git-cli.ts +11 -5
  354. package/src/graph-runner/graph-cli.ts +26 -2
  355. package/src/graph-runner/graph-run-api.ts +3 -2
  356. package/src/graph-runner/runner.ts +17 -5
  357. package/src/graph-wizard/generate.ts +29 -6
  358. package/src/harness/harness-cli-command.ts +179 -33
  359. package/src/harness/review-adapter.ts +26 -6
  360. package/src/index.ts +116 -13
  361. package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
  362. package/src/llm/route-decision.ts +13 -0
  363. package/src/llm-tool-name.ts +37 -0
  364. package/src/llm-tool-schema.ts +35 -0
  365. package/src/llm.ts +123 -11
  366. package/src/loops/checker.ts +100 -0
  367. package/src/loops/consensus.ts +26 -2
  368. package/src/loops/loop-cli.ts +9 -4
  369. package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
  370. package/src/loops/orchestrator/tick.ts +49 -4
  371. package/src/model-tier/llm-tier-map.ts +12 -17
  372. package/src/msg/msg-store.ts +17 -0
  373. package/src/native-tool-catalog.ts +1 -1
  374. package/src/nexus/api/graph-wizard-api.ts +27 -2
  375. package/src/nexus/api/grid.ts +24 -4
  376. package/src/nexus/api/http-server.ts +1 -1
  377. package/src/nexus/api/ops-api.ts +14 -6
  378. package/src/nexus/state/state.ts +7 -1
  379. package/src/oauth/codex-account-store.ts +34 -1
  380. package/src/ops/loops-map.ts +46 -0
  381. package/src/ops/overview-cache.ts +22 -4
  382. package/src/ops/overview.ts +41 -5
  383. package/src/policy/llm-policy.ts +3 -1
  384. package/src/prompt-enhance/enhance.ts +4 -4
  385. package/src/pty-shell/availability.ts +7 -0
  386. package/src/pty-shell/herdr-agent-report.ts +40 -31
  387. package/src/pty-shell/herdr-prune-stale.ts +17 -0
  388. package/src/pty-shell/herdr-sequence-lease.ts +60 -0
  389. package/src/pty-shell/pty-control-ipc.ts +187 -18
  390. package/src/pty-shell/registry.ts +25 -15
  391. package/src/pty-shell/tui-run-state.ts +235 -1
  392. package/src/release-loop/checklist.ts +50 -5
  393. package/src/release-loop/feature-store.ts +9 -9
  394. package/src/release-loop/landed-but-yellow.ts +93 -12
  395. package/src/repl/index.ts +8 -0
  396. package/src/seat-loop/seat-report.ts +1 -0
  397. package/src/self-dev/ask-launch-flow.ts +86 -10
  398. package/src/self-dev/decompose-proposal.ts +29 -18
  399. package/src/self-dev/dev-pipeline.ts +29 -7
  400. package/src/self-dev/draft-sweep.ts +241 -16
  401. package/src/self-dev/draft-triage-rules.ts +19 -5
  402. package/src/self-dev/review-provider-fallback.ts +45 -7
  403. package/src/self-dev/shard-plan.ts +48 -0
  404. package/src/self-dev/shard-run.ts +50 -3
  405. package/src/self-implement/doctor-visit.ts +83 -0
  406. package/src/self-implement/gate-artifacts.ts +6 -2
  407. package/src/self-implement/gate-baseline.ts +64 -1
  408. package/src/self-implement/gate-cli.ts +93 -9
  409. package/src/self-implement/gate-remote.ts +28 -4
  410. package/src/self-implement/gate-scope.ts +13 -1
  411. package/src/self-implement/goal-author.ts +333 -18
  412. package/src/self-implement/goal-supervisor-fill.ts +75 -26
  413. package/src/self-implement/importer-test-index.ts +215 -2
  414. package/src/self-implement/knowhow-pack.ts +5 -5
  415. package/src/self-implement/orchestrator.ts +318 -25
  416. package/src/self-implement/review-round-brief.ts +300 -0
  417. package/src/self-implement/rework-policy.ts +14 -0
  418. package/src/self-implement/run-ledger.ts +170 -6
  419. package/src/self-implement/run-stop.ts +1 -1
  420. package/src/self-implement/running-runs.ts +17 -3
  421. package/src/self-implement/seams.ts +12 -6
  422. package/src/self-implement/stop-autoheal.ts +1 -0
  423. package/src/self-implement/test-seams.ts +13 -1
  424. package/src/self-implement/train-reach-grouping.ts +8 -2
  425. package/src/session/chat.ts +7 -1
  426. package/src/session/id-prefix.ts +60 -0
  427. package/src/session/index.ts +4 -0
  428. package/src/session-runtime/index.ts +9 -1
  429. package/src/skills/tools/pty.ts +5 -0
  430. package/src/status/metrics.ts +12 -1
  431. package/src/steward/rejudge-tick.ts +12 -5
  432. package/src/steward/resync-tick.ts +31 -4
  433. package/src/task-agent/actions.ts +199 -4
  434. package/src/task-agent/boundary-proof-mapping.ts +12 -0
  435. package/src/task-agent/boundary-proof-producer.ts +147 -0
  436. package/src/task-agent/completion-evidence.ts +2 -1
  437. package/src/task-agent/green-close-recipe.ts +239 -0
  438. package/src/task-agent/green-sweep.ts +64 -10
  439. package/src/task-agent/live-moves.ts +48 -3
  440. package/src/task-agent/map-host-adapter.ts +134 -0
  441. package/src/task-agent/map-reduce.ts +158 -0
  442. package/src/task-agent/map-run-ledger.ts +226 -0
  443. package/src/task-agent/parent-host.ts +21 -11
  444. package/src/task-agent/rejudge-on-head.ts +72 -5
  445. package/src/task-agent/repair-cycle.ts +41 -0
  446. package/src/task-agent/repair-next-move.ts +12 -2
  447. package/src/task-agent/review-prior-fix.ts +12 -2
  448. package/src/task-agent/shadow.ts +188 -5
  449. package/src/task-agent/task-hand.ts +158 -13
  450. package/src/task-agent/task-parent-role-llm.ts +9 -0
  451. package/src/task-agent/tier-split.ts +4 -3
  452. package/src/task-agent/work-order.ts +53 -2
  453. package/src/task-orchestrator/dispatcher.ts +46 -1
  454. package/src/task-orchestrator/generator-prompt.ts +6 -0
  455. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
  456. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
  457. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
  458. package/src/task-orchestrator/surfaces/pod-pool.ts +50 -4
  459. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
  460. package/src/task-orchestrator/surfaces/self-implement-pod.ts +217 -36
  461. package/src/task-orchestrator/surfaces/self-implement.ts +4 -0
  462. package/src/testing/linux-env.ts +177 -0
  463. package/src/tui/chat/goal-interim.ts +5 -1
  464. package/src/tui/entry.ts +258 -4
  465. package/src/tui/input/at-picker.ts +55 -0
  466. package/src/tui/slash/resume.ts +35 -12
  467. package/src/tui/slash/signals.ts +114 -0
  468. package/src/tui/slash/term-next.ts +71 -0
  469. package/src/tui-client/local-chat-turn.ts +4 -3
  470. package/src/user-config.ts +19 -1
  471. package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
  472. package/src/ux-sim/classic-tui-seat-scenarios.ts +158 -4
  473. package/src/ux-sim/fake-gh.ts +174 -0
  474. package/src/ux-sim/fake-kubectl.ts +142 -0
  475. package/src/ux-sim/fake-llm.ts +6 -1
  476. package/src/ux-sim/next-tui-seat-scenarios.ts +124 -6
  477. package/src/ux-sim/resume-picker-device.ts +173 -0
  478. package/src/ux-sim/session-id-seed.ts +60 -0
  479. package/src/ux-sim/skills-tools-shell-device.ts +156 -0
  480. package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
  481. package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
  482. package/src/version/packed-revision.json +1 -1
  483. package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +0 -287
  484. package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +0 -36
  490. package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +0 -1
  492. package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +0 -149
  493. package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +0 -24
  498. package/apps/pwa/out/_next/static/chunks/2812ca6a.3b9f4a7a08885744.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +0 -24
  502. package/apps/pwa/out/_next/static/chunks/3031-85328a92fcce4da6.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/3148-98efd4869d660a87.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +0 -226
  505. package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +0 -8
  509. package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +0 -32
  510. package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +0 -286
  512. package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
  515. package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/4116.a84a92a2492c080e.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +0 -104
  519. package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +0 -148
  522. package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +0 -93
  524. package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +0 -122
  526. package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/599.c39c571b6733f2a2.js +0 -41
  531. package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +0 -79
  532. package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/6566.926a1d1b7c911442.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +0 -27
  544. package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/6925.562d532110879886.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/7784.1f0ac4a16d190cf4.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/7891.03f910124a737985.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/8037.e254fd797aa224d1.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +0 -62
  557. package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +0 -90
  559. package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +0 -94
  560. package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +0 -77
  565. package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/9514.131c52cc75fe6439.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/app/outputs/page-e7abc34a48a6f71e.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/app/term/page-c15958835534404b.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +0 -1
  630. /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → 8kITumG9GAZ1LwT9POrAR}/_ssgManifest.js +0 -0
@@ -32,10 +32,11 @@ import { parseWorkOrder, renderWorkOrderGoal, WORK_ORDER_FILE_PATTERN, type Work
32
32
  import { inspectPrelaunchAlreadyDone, type AlreadyDoneDecision, type AlreadyDoneCandidate,
33
33
  type PrelaunchGitRunnerForTest } from './prelaunch-already-done.js';
34
34
  import { draftClaimComment, draftClaimRecordLive, draftClaimState, draftReleaseComment } from '../self-dev/draft-triage-rules.js';
35
- import { parseAskTargetPathHints, parseAskTargetPathHintsResult } from '../self-dev/launch-preflight-text.js';
35
+ import { parseAskTargetPathHints, parseAskTargetPathHintsResult, type AskTargetPathHintsParseResult } from '../self-dev/launch-preflight-text.js';
36
36
  import { inspectGoalDoneBoundary, linesOutsideFencedCode } from '../self-implement/goal-author.js';
37
+ import { selectKnowhowPack } from '../self-implement/knowhow-pack.js';
37
38
  import { INFLIGHT_REGISTRY_FILE, registerInflight } from '../pr-tool/inflight-registry.js';
38
- import { taskParentRoleEnv } from './task-parent-role-llm.js';
39
+ import { taskParentRoleEnv, taskParentRolePinsForChild } from './task-parent-role-llm.js';
39
40
  import { runHarvestUnit, type ReviewInvocation } from './harvest-unit.js';
40
41
  import { TASK_CARD_PREFIX } from './task-card-prefix.js';
41
42
 
@@ -124,6 +125,43 @@ export function taskCardLabelContext(card: Pick<TaskCard, 'id'>): TaskCardLabelC
124
125
  export const COMPLETION_KINDS = ['code-pr', 'artifact', 'research-report', 'ops-action', 'content', 'watch-brief', 'decision-support', 'deliverable'] as const;
125
126
  export type CompletionKind = typeof COMPLETION_KINDS[number];
126
127
 
128
+ /** «실행·조사» 손의 조합 — 종결 종류별 조합이 아직 없을 때 그 손이 기본으로 쓰는 판(조사 make-doc ⊕ 확인 verify). */
129
+ export const RUN_RESEARCH_COMPOSITION = 'graphs/work/run-research.yaml';
130
+
131
+ /** 기본 손 묶음 — «개발»(자식 구현 런·PR 착지 = 코드 하니스) 또는 «실행·조사»(비코드 종결 다섯 ⊕ 콘텐츠·전달). */
132
+ export type DefaultHand = 'develop' | 'run-research';
133
+
134
+ /**
135
+ * DEFAULT-HANDS — 종결 종류마다 과제 담당이 기본으로 쥐는 손과 그 «확인 증거»(RFC-loop-agent-map §A4c).
136
+ * 기본은 «개발»이 아니라 «실행·조사»다: 마케터·산업 현장·선생님·C 레벨이 자기 일을 그대로 맡긴다.
137
+ * 코드 하니스(`harness-say` 자식 구현 런 · PR 착지)는 개발자 팩(`code-pr`)만 쓴다.
138
+ */
139
+ export interface DefaultHandSpec {
140
+ hand: DefaultHand;
141
+ /** 확인 증거 — 종류별 판정 규칙의 이름(정본 = `completion-evidence.ts` `checkCompletionEvidence`). */
142
+ evidence: string;
143
+ /** 종류별 조합 파일이 없을 때 그 손이 기본으로 쓰는 조합. */
144
+ composition: string;
145
+ /** 코드 하니스(자식 구현 런·PR 병합)를 쓰나 — 개발자 팩 전용. */
146
+ codeHarness: boolean;
147
+ }
148
+
149
+ export const DEFAULT_HANDS: Record<CompletionKind, DefaultHandSpec> = {
150
+ 'code-pr': { hand: 'develop', evidence: '구현 — PR 병합', composition: 'graphs/work/code-pr.yaml', codeHarness: true },
151
+ 'research-report': { hand: 'run-research', evidence: '조사 — 출처 인용 보고(출처 ⊕ 반대 근거)', composition: 'graphs/work/research-report.yaml', codeHarness: false },
152
+ artifact: { hand: 'run-research', evidence: '산출물 — 파일 ⊕ 미리보기', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
153
+ content: { hand: 'run-research', evidence: '콘텐츠 — 파일 ⊕ 미리보기', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
154
+ 'ops-action': { hand: 'run-research', evidence: '실행 — 실행 기록 ⊕ 되읽기', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
155
+ 'watch-brief': { hand: 'run-research', evidence: '감시·브리핑 — 일정 ⊕ 도착', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
156
+ 'decision-support': { hand: 'run-research', evidence: '결정 지원 — 카드 ⊕ 기록', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
157
+ deliverable: { hand: 'run-research', evidence: '전달 — 산출물 ⊕ 수신 확인', composition: RUN_RESEARCH_COMPOSITION, codeHarness: false },
158
+ };
159
+
160
+ /** 카드의 종결 종류가 기본으로 받는 손 — 비면 code-pr(=개발)다. */
161
+ export function defaultHandOf(completion: CompletionKind | undefined): DefaultHand {
162
+ return DEFAULT_HANDS[completion ?? 'code-pr'].hand;
163
+ }
164
+
127
165
  export interface TaskComposition {
128
166
  file: string;
129
167
  /** null = 파일은 있으나 파싱 실패로 판을 확인하지 못했다. */
@@ -143,13 +181,27 @@ export const COMPOSITION_ROOT = join(dirname(fileURLToPath(import.meta.url)), '.
143
181
 
144
182
  /** 1판은 조합을 고르고 단위 해석 결과를 기록한다. 단위 실행은 2판의 몫이다. */
145
183
  export function selectTaskComposition(completion: CompletionKind, root = COMPOSITION_ROOT): CompositionSelection {
146
- const file = `graphs/work/${completion}.yaml`;
147
- const path = join(root, file);
184
+ const requested = `graphs/work/${completion}.yaml`;
185
+ // DEFAULT-HANDS — 종류별 조합이 없으면 그 손의 기본 조합(«실행·조사»)으로 내려간다.
186
+ // 비개발 종결이 «조합 없음»으로 막히면 사람별 표본이 과제 담당에 닿지도 못한다.
187
+ let file = requested;
188
+ let path = join(root, file);
148
189
  let source: string;
149
190
  try { source = readFileSync(path, 'utf8'); } catch (error) {
150
- if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') return { unitsResolved: false, missingUnits: [] };
151
- return { composition: { file, version: null }, unitsResolved: false, missingUnits: [],
152
- error: `조합 읽기 오류: ${file}: ${error instanceof Error ? error.message : String(error)}` };
191
+ const missing = (error as NodeJS.ErrnoException)?.code === 'ENOENT';
192
+ if (!missing) {
193
+ return { composition: { file, version: null }, unitsResolved: false, missingUnits: [],
194
+ error: `조합 읽기 오류: ${file}: ${error instanceof Error ? error.message : String(error)}` };
195
+ }
196
+ const fallback = DEFAULT_HANDS[completion].composition;
197
+ if (fallback === requested) return { unitsResolved: false, missingUnits: [] };
198
+ file = fallback;
199
+ path = join(root, file);
200
+ try { source = readFileSync(path, 'utf8'); } catch (fallbackError) {
201
+ if ((fallbackError as NodeJS.ErrnoException)?.code === 'ENOENT') return { unitsResolved: false, missingUnits: [] };
202
+ return { composition: { file, version: null }, unitsResolved: false, missingUnits: [],
203
+ error: `조합 읽기 오류: ${file}: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}` };
204
+ }
153
205
  }
154
206
  const parsed = parseGraphTemplateYaml(source, path);
155
207
  if (!parsed.template || parsed.errors.length) {
@@ -763,6 +815,46 @@ export function readTaskCard(id: string, path = taskAgentStatePath()): TaskCard
763
815
  return readState(path).tasks?.[id];
764
816
  }
765
817
 
818
+ /** TA-REVIEW-PASS — runId 기준 단일 카드 멱등 생성 결과. `ok: false` 는 임의 생성 없이 사유만 남긴 보류(fail-closed)다. */
819
+ export type IdempotentRunCardCreate =
820
+ | { ok: true; card: TaskCard; created: boolean }
821
+ | { ok: false; reason: string };
822
+
823
+ /**
824
+ * TA-REVIEW-PASS — runId 기준 단일 카드 결속(멱등 생성). 단일 파일 잠금 안에서 원장을 읽어
825
+ * (a) 같은 runId 카드가 정확히 1건이면 그대로 재사용, (b) 0건이면 runId 해시로 재진입에 안정적인 id 를 만들어
826
+ * `card.runId` 를 검증된 부모 런 ID 와 정확히 일치시켜 원장에 추가한다(종전 칸·다른 카드·원장 기타 필드 보존),
827
+ * (c) 복수 카드·원격 Pod 자식 런·불명 runId·읽기 실패는 임의 생성하지 않고 사유를 남겨 보류한다.
828
+ */
829
+ export function idempotentCreateCardForRun(path: string, input: { runId: string; text: string; now?: () => Date; env?: NodeJS.ProcessEnv }): IdempotentRunCardCreate {
830
+ const runId = input.runId.trim();
831
+ if (!runId) return { ok: false, reason: 'runId 불명 — 고유한 런 소유를 검증할 수 없어 카드를 만들지 않는다' };
832
+ const env = input.env ?? process.env;
833
+ if (env.ELANOUS_POD_NAME) return { ok: false, reason: `원격 Pod 자식 런(${env.ELANOUS_POD_NAME}) — HQ 결속만 허용한다` };
834
+ const at = (input.now ?? (() => new Date()))().toISOString();
835
+ return withFileLockSync(`${path}.lock`, (): IdempotentRunCardCreate => {
836
+ let disk: TaskAgentStateFile;
837
+ try {
838
+ disk = readState(path);
839
+ } catch (error) {
840
+ return { ok: false, reason: `원장 읽기 실패 — 임의 생성하지 않는다: ${error instanceof Error ? error.message : String(error)}` };
841
+ }
842
+ const tasks = { ...(disk.tasks ?? {}) };
843
+ const bound = Object.values(tasks).filter((candidate) => candidate.runId === runId);
844
+ if (bound.length === 1) return { ok: true, card: bound[0]!, created: false };
845
+ if (bound.length > 1) return { ok: false, reason: `runId ${runId} 카드 ${bound.length}건(모호) — 고유한 런 소유가 아니므로 결속하지 않는다` };
846
+ const id = `${TASK_CARD_PREFIX}run-${createHash('sha256').update(runId).digest('hex').slice(0, 12)}`;
847
+ if (tasks[id]) return { ok: false, reason: `카드 id ${id} 충돌 — 종전 카드를 덮어쓰지 않는다` };
848
+ const card: TaskCard = {
849
+ id, text: input.text, createdAt: at, status: 'launched', runId,
850
+ history: [{ at, event: 'card-created-for-run', detail: `카드 없는 runId(${runId})의 리뷰 필요 판정 — 단일 카드 멱등 결속`, runId }],
851
+ };
852
+ mkdirSync(dirname(path), { recursive: true });
853
+ writeFileSync(path, JSON.stringify({ ...disk, tasks: { ...tasks, [id]: card } }));
854
+ return { ok: true, card, created: true };
855
+ });
856
+ }
857
+
766
858
  function canonicalTargetPaths(paths: readonly string[]): string[] {
767
859
  return [...new Set(paths.filter((path): path is string => typeof path === 'string').map((path) => posix.normalize(path))
768
860
  .filter((path) => path !== '.' && path !== '..' && !posix.isAbsolute(path)
@@ -864,6 +956,7 @@ export function launchArgs(card: Pick<TaskCard, 'text' | 'seat' | 'childLlm' | '
864
956
  ? ['--child-llm-provider', card.childLlm.provider, '--child-llm-model', card.childLlm.model, ...(card.childLlm.effort ? ['--child-llm-effort', card.childLlm.effort] : [])]
865
957
  : [];
866
958
  const runPriority = runIdentityQueuePriority(card.identity);
959
+ // Exact role model pins travel in ELANOUS_ROLE_LLM_*: harness say's argv parser only accepts provider[/tier].
867
960
  return ['harness', 'say', ...(card.seat ? ['--seat', card.seat] : []), '--substrate', 'pod', '--merge-by-host', ...(runPriority !== undefined ? ['--run-priority', String(runPriority)] : []), ...child, card.text];
868
961
  }
869
962
 
@@ -1040,6 +1133,37 @@ function goalEvidenceCommandFormViolations(document: string): string[] {
1040
1133
  return violations;
1041
1134
  }
1042
1135
 
1136
+ /**
1137
+ * FIRST-LINE-PATH-LIST-ONLY — 골 «첫 줄»의 형태 판정: `대상 경로:` 뒤의 «경로 조각» 에는 괄호·줄번호·덧말이 붙지 않는다.
1138
+ * 첫 줄만 보는 판정은 `parseAskTargetPathHintsResult` 가 이미 하므로 새 파서를 만들지 않고 그 결과에 얹는다:
1139
+ * 파서가 통과시킨 경로(`paths`)와 버린 조각(`rejected`)을 한 줄씩 보고, «경로 조각»(디렉터리 구분자·확장자가 있는 것)에
1140
+ * 장식이 붙었을 때만 이유를 붙여 거부한다. `· 동작: a 고침` 같은 «산문 조각» 은 경로 조각이 아니다 —
1141
+ * 조각 분해가 합성하는 손 문면(`handTaskWithTierSplit` 경로)이 그 모양으로 첫 줄을 만든다.
1142
+ * 라벨이 없는 문면(첫 줄이 대상 경로 목록이 아닌 손)은 이 축의 몫이 아니다 — 그 모양은 지금과 같다.
1143
+ */
1144
+ const FIRST_LINE_PATH_DECORATIONS: readonly { readonly label: string; readonly pattern: RegExp }[] = [
1145
+ { label: '괄호 장식', pattern: /[()[\]{}()【】]/ },
1146
+ { label: '줄번호', pattern: /:\d/ },
1147
+ { label: '덧말', pattern: /->|→|—|–/ },
1148
+ ];
1149
+
1150
+ function firstLinePathListViolations(hints: AskTargetPathHintsParseResult): string[] {
1151
+ if (hints.labelMissing) return [];
1152
+ const violations: string[] = [];
1153
+ for (const piece of [...hints.paths, ...hints.rejected.map((rejection) => rejection.fragment.trim())]) {
1154
+ if (!/[/.]/.test(piece)) continue;
1155
+ const decoration = FIRST_LINE_PATH_DECORATIONS.find((entry) => entry.pattern.test(piece));
1156
+ if (decoration) violations.push(`${decoration.label}: ${piece}`);
1157
+ // 공백만으로 거부하지 않는다 — «경로 자체에 공백»(`docs/foo bar.md`)은 지금처럼 통과한다.
1158
+ // 덧말은 공백 뒤에 «경로가 아닌 말»이 붙은 경우만이다(마지막 조각에 구분자·확장자가 없다).
1159
+ else {
1160
+ const trailing = piece.split(/\s+/).slice(1).join(' ').trim();
1161
+ if (trailing !== '' && !/[/.]/.test(trailing)) violations.push(`덧말(공백 섞임): ${piece}`);
1162
+ }
1163
+ }
1164
+ return violations;
1165
+ }
1166
+
1043
1167
  export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
1044
1168
  const text = opts.text.trim();
1045
1169
  if (!text) throw new Error('과제 한 줄이 비어 있다');
@@ -1072,7 +1196,8 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
1072
1196
  launcher: 'hand',
1073
1197
  }, birthTags);
1074
1198
  const childLlm = opts.childLlm !== undefined ? parseChildLlm(opts.childLlm, opts.childLlmEffort) : undefined;
1075
- const parentRoleEnv = taskParentRoleEnv(opts.parentRoleLlm ?? []); // validate before writing the card
1199
+ const parentRolePins = taskParentRolePinsForChild(opts.parentRoleLlm ?? [], childLlm);
1200
+ const parentRoleEnv = taskParentRoleEnv(parentRolePins); // validate before writing the card
1076
1201
  const completion = opts.completion ?? 'code-pr';
1077
1202
  const selected = selectTaskComposition(completion, opts.compositionRoot);
1078
1203
  // 2판 — launcher 'graph-run' 조합(단위 해석까지 완료)은 실제 graph run 으로 발사한다. 더 이상 거부하지 않는다.
@@ -1083,8 +1208,11 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
1083
1208
  : !selected.composition ? `조합 없음: graphs/work/${completion}.yaml`
1084
1209
  : selected.error ?? (selected.launcher === 'graph-run' && !selected.unitsResolved
1085
1210
  ? `조합 단위 미해석: ${selected.composition.file} — 대상 unit: ${selected.missingUnits.length ? selected.missingUnits.join(', ') : '해석 실패'} (graph-run 발사는 단위 해석이 필요하다)`
1086
- : completion !== 'code-pr' || selected.launcher !== 'harness-say'
1087
- ? `조합 실행기 없음: ${selected.composition.file} (발사 가능한 launcher: code-pr harness-say · graph-run)` : undefined);
1211
+ // DEFAULT-HANDS — 코드 하니스(harness-say 자식 구현 런)는 개발자 팩(code-pr)만 쓴다.
1212
+ : !DEFAULT_HANDS[completion].codeHarness && selected.launcher === 'harness-say'
1213
+ ? `조합 실행기 없음: ${selected.composition.file} — ${completion} 은 «실행·조사» 손이라 코드 하니스(harness-say)를 쓰지 않는다(개발자 팩 전용)`
1214
+ : selected.launcher === undefined
1215
+ ? `조합 실행기 없음: ${selected.composition.file} (발사 가능한 launcher: harness-say · graph-run)` : undefined);
1088
1216
  let project: TaskCard['project'];
1089
1217
  let targetIsGit: boolean | null = null;
1090
1218
  if (opts.project) {
@@ -1126,7 +1254,7 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
1126
1254
  ...(opts.milestone ? { milestone: opts.milestone } : {}),
1127
1255
  ...(opts.taLand === true ? { taLand: true as const } : {}),
1128
1256
  ...(childLlm ? { childLlm } : {}),
1129
- ...(opts.parentRoleLlm?.length ? { parentRoleLlm: [...opts.parentRoleLlm] } : {}),
1257
+ ...(parentRolePins.length ? { parentRoleLlm: parentRolePins } : {}),
1130
1258
  ...(opts.tier ? { tier: opts.tier } : {}),
1131
1259
  ...(opts.tierSplit ? { tierSplit: opts.tierSplit } : {}),
1132
1260
  ...(identity ? { identity } : {}),
@@ -1202,11 +1330,20 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
1202
1330
  if (formViolations.length > 0) {
1203
1331
  throw new Error(`goal-revision-required: 완료 경계 증거 명령은 명령 원문이어야 한다 ${formViolations.join(' · ')} — 증거 명령 줄에 설명 접미(예: → 0 fail)나 백틱 장식을 붙이지 말고 명령만 적은 뒤 다시 넘기세요`);
1204
1332
  }
1333
+ // FIRST-LINE-PATH-LIST-ONLY — 첫 줄 형태 판정(발사 전 거부): 괄호·줄번호·덧말이 붙은 골은 자식을 띄우지 않는다.
1334
+ // 카드 기록(writeCard)과 launcher 호출 뒤로 밀리면 «발사 전 거부·카드 0» 이 깨지므로 이 자리에서 던진다.
1335
+ const firstLineViolations = firstLinePathListViolations(targetPathHints);
1336
+ if (firstLineViolations.length > 0) {
1337
+ try { debug.log('task-agent.hand', 'first-line-path-list-rejected', { card: id, violations: firstLineViolations }); } catch { /* fail-soft */ }
1338
+ throw new Error(`goal-revision-required: 골 첫 줄은 «대상 경로:» 뒤에 경로 목록만 적어야 한다 ${firstLineViolations.join(' · ')} — 괄호·줄번호·덧말을 떼고 경로만 적은 뒤 다시 넘기세요`);
1339
+ }
1205
1340
  }
1206
1341
  writeCard(path, card);
1207
1342
  try { debug.log('task-agent.hand', 'target-paths', { card: id, count: targetPaths.length, labelMissing: targetPathHints.labelMissing }); } catch { /* fail-soft */ }
1208
1343
  try { debug.log('task-agent.graph-select', !selected.composition ? 'composition-missing' : selected.error ? 'composition-invalid' : 'composition-selected', {
1209
1344
  completion, file: selected.composition?.file ?? `graphs/work/${completion}.yaml`,
1345
+ // DEFAULT-HANDS — 어느 손으로 나가는지(«개발»/«실행·조사»)와 코드 하니스 여부를 선택 관측에 싣는다.
1346
+ hand: DEFAULT_HANDS[completion].hand, codeHarness: DEFAULT_HANDS[completion].codeHarness,
1210
1347
  unitsResolved: selected.unitsResolved, missingUnits: selected.missingUnits,
1211
1348
  ...(selected.error ? { error: selected.error } : {}),
1212
1349
  }); } catch { /* fail-soft */ }
@@ -1282,6 +1419,14 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
1282
1419
  writeCard(path, candidate);
1283
1420
  return { card: candidate, move: nextMoveFor(candidate), mode, launched: false, ...(project ? { cwd: project.target } : {}) };
1284
1421
  }
1422
+ // Only the code-PR harness Pod consumes podGoal. Keep the card and other launchers unchanged.
1423
+ const podLaunch = completion === 'code-pr' && selected.launcher === 'harness-say';
1424
+ let childGoal = card.text;
1425
+ if (podLaunch) {
1426
+ const knowhow = selectKnowhowPack(project?.target ?? resolve(import.meta.dir, '../..'), card.text, targetPaths);
1427
+ if (knowhow.text) childGoal = `${knowhow.text}\n\n${card.text}`;
1428
+ try { debug.log('task-agent', 'knowhow-pack', { taskId: id, ids: knowhow.ids, bytes: knowhow.bytes, injected: knowhow.bytes > 0 }); } catch { /* fail-soft */ }
1429
+ }
1285
1430
  const runId = mintRunId();
1286
1431
  const launchId = newLaunchUtteranceId();
1287
1432
  recordLaunchUtterance({ source: 'hand', utterance: opts.text, launchId });
@@ -1294,10 +1439,10 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
1294
1439
  // An omitted card provider uses the established Pod default. Carry the effective value explicitly so
1295
1440
  // remote-parent code never has to infer a provider from the serialized CLI argv.
1296
1441
  effectiveChildProvider: card.childLlm?.provider ?? 'openai-codex',
1297
- ...(completion === 'code-pr' && selected.launcher === 'harness-say' ? { substrate: 'pod' as const, podGoal: card.text } : {}) };
1442
+ ...(podLaunch ? { substrate: 'pod' as const, podGoal: childGoal } : {}) };
1298
1443
  let receipt: void | TaskLaunchReceipt;
1299
1444
  try {
1300
- receipt = await opts.launcher(move.command!, project?.target, context);
1445
+ receipt = await opts.launcher(podLaunch ? [...move.command!.slice(0, -1), childGoal] : move.command!, project?.target, context);
1301
1446
  } catch (error) {
1302
1447
  const reason = error instanceof Error ? error.message : String(error);
1303
1448
  const failed: TaskCard = { ...card, status: 'launch-failed', history: [{ at: (opts.now ?? (() => new Date()))().toISOString(), event: 'launch-failed', detail: reason }] };
@@ -34,3 +34,12 @@ export function taskParentRoleEnv(values: readonly string[]): Record<string, str
34
34
  }
35
35
  return env;
36
36
  }
37
+
38
+ /** A child model also powers planning unless the caller pinned planning explicitly. */
39
+ export function taskParentRolePinsForChild(
40
+ values: readonly string[], child?: { provider: string; model: string },
41
+ ): string[] {
42
+ const env = taskParentRoleEnv(values);
43
+ if (!child || env[roleLlmEnvName('planning')] !== undefined) return [...values];
44
+ return [...values, `planning=${JSON.stringify({ provider: child.provider, model: child.model })}`];
45
+ }
@@ -43,10 +43,11 @@ export function composeSliceHandText(sliceGoal: string, parentText: string, mark
43
43
  const label = INHERITED_PARENT_LABELS.exec(line)?.[1];
44
44
  return label !== undefined && !sliceHas.has(label);
45
45
  });
46
- // The slice marker also carries review scope. Device slices now own their
47
- // completion boundary, so inherited can be empty while the marker is needed.
46
+ // 표지는 리뷰 범위를 나르므로 장치 우선 조각(총 2 이상)은 상속 줄이 없어도 남는다 —
47
+ // 다만 «물려받았다» 는 물려받은 줄에 대한 주장이므로 그 줄이 있을 때만 붙인다.
48
48
  if (inherited.length === 0 && (marker.total < 2 || !sliceGoal.includes(`동작: ${DEVICE_FIRST_STEP}`))) return sliceGoal;
49
- const tag = `조각 ${marker.index}/${marker.total} — 부모 ${marker.cid ?? '(칸 없음)'}(${marker.fromTier}) 를 중 이하로 나눈 몫. 아래 계약·완료 경계는 부모 칸에서 물려받았다 — 이 조각 범위만 채운다.`;
49
+ const inheritanceClaim = inherited.length > 0 ? ' 아래 계약·완료 경계는 부모 칸에서 물려받았다 — 이 조각 범위만 채운다.' : '';
50
+ const tag = `조각 ${marker.index}/${marker.total} — 부모 ${marker.cid ?? '(칸 없음)'}(${marker.fromTier}) 를 중 이하로 나눈 몫.${inheritanceClaim}`;
50
51
  return [...sliceLines, tag, ...inherited].join('\n');
51
52
  }
52
53
 
@@ -11,7 +11,8 @@
11
11
  * 4. 판정 신호(`verdictSignal` — 조건·관측·기대) ⊕ 현재 계약 한 줄(`contract`)
12
12
  * 5. 경계(`boundary` — 대상 경로 · 건드리지 말 곳)
13
13
  * 6. 예산(`budget` — 시간 · 모델 티어 · Pod 자리 · 재작업 상한)
14
- * 7. 선행·짝 칸(`peers`)
14
+ * 7. 선행·짝 칸(`peers`) — 항목마다 조회된 상태(`state`)와 조회 시각(`observedAt`)을 보존한다
15
+ * (칸 이름만으로는 발사 시점의 상태를 알 수 없다 · 조회하지 않은 항목은 «모름»).
15
16
  * 8. 선례 묶음(`precedents` — 같은 칸 앞 생애 결말·must-fix 서명)
16
17
  * 9. 올림 규칙(`escalation` — 무엇이면 누구에게 · 돈·보안은 대표)
17
18
  *
@@ -50,6 +51,21 @@ export interface WorkOrder {
50
51
  escalation: string;
51
52
  /** 입력에 없어 «모름»으로 채운 키. */
52
53
  unknownFields: string[];
54
+ /**
55
+ * 선행 항목별 관측 — 지시서가 선행을 배열로 적었을 때만 있다(문자열 한 줄이면 종전 그대로 없다).
56
+ * 항목마다 조회된 상태와 그 상태를 조회한 시각을 보존하고, 조회하지 않은 값은 «모름»이다.
57
+ */
58
+ dependencies?: WorkOrderDependency[];
59
+ }
60
+
61
+ /** 선행 칸 하나의 관측 — 칸 이름 ⊕ 조회된 상태 ⊕ 그 상태를 본 시각. */
62
+ export interface WorkOrderDependency {
63
+ /** 선행 칸 id(또는 칸 이름). */
64
+ cell: string;
65
+ /** 조회된 상태(yellow·green·red …) — 조회하지 않았으면 «모름». */
66
+ state: string;
67
+ /** 상태를 조회한 시각(ISO 8601) — 조회하지 않았으면 «모름». */
68
+ observedAt: string;
53
69
  }
54
70
 
55
71
  export type ParseWorkOrderResult = { ok: true; order: WorkOrder } | { ok: false; reason: string };
@@ -63,6 +79,26 @@ function cellText(value: unknown): string {
63
79
  catch { return WORK_ORDER_UNKNOWN; }
64
80
  }
65
81
 
82
+ /**
83
+ * 선행 칸을 항목별 관측으로 읽는다 — 배열 원소가 객체면 `state`·`observedAt` 을 보존하고,
84
+ * 이름만 적힌 항목(문자열 등)은 조회하지 않은 것이므로 상태·시각 모두 «모름»으로 둔다.
85
+ * 선행 칸이 배열이 아니면(문자열 한 줄·없음) 항목 목록은 비어 있다 — 종전 문면 그대로다.
86
+ */
87
+ function parseDependencies(value: unknown): WorkOrderDependency[] {
88
+ if (!Array.isArray(value)) return [];
89
+ return value.map((item) => {
90
+ if (item && typeof item === 'object' && !Array.isArray(item)) {
91
+ const record = item as Record<string, unknown>;
92
+ return {
93
+ cell: cellText(record['cell'] ?? record['cellId']),
94
+ state: cellText(record['state']),
95
+ observedAt: cellText(record['observedAt']),
96
+ };
97
+ }
98
+ return { cell: cellText(item), state: WORK_ORDER_UNKNOWN, observedAt: WORK_ORDER_UNKNOWN };
99
+ });
100
+ }
101
+
66
102
  /**
67
103
  * 지시서 JSON 원문을 검증한다. 깨진 JSON 은 `JSON 이 깨졌다: …`, 칸 id(문자열)가 없으면 `칸 id 가 없다`
68
104
  * 하나로 거부하고, 그 밖의 빠진 칸은 «모름»으로 채운다(거부 아님).
@@ -84,7 +120,21 @@ export function parseWorkOrder(source: string): ParseWorkOrderResult {
84
120
  if (value == null || (typeof value === 'string' && !value.trim())) unknownFields.push(field);
85
121
  cells[field] = text;
86
122
  }
87
- return { ok: true, order: { cellId: rawCellId.trim(), ...cells, unknownFields } };
123
+ const dependencies = parseDependencies(record['peers']);
124
+ return {
125
+ ok: true,
126
+ order: {
127
+ cellId: rawCellId.trim(), ...cells,
128
+ ...(dependencies.length ? { dependencies } : {}),
129
+ unknownFields,
130
+ },
131
+ };
132
+ }
133
+
134
+ /** 선행 항목별 «상태 ⊕ 조회 시각» 한 줄 — 이름만 있는 항목은 «모름 (관측 모름)»으로 드러난다. */
135
+ function renderDependencies(dependencies: WorkOrderDependency[]): string {
136
+ const items = dependencies.map((dep) => `${dep.cell}=${dep.state} (관측 ${dep.observedAt})`);
137
+ return `선행 상태: ${items.join(' · ')}`;
88
138
  }
89
139
 
90
140
  /** 검증된 지시서를 사람이 읽는 골 문면으로 펼친다 — 첫 줄 «대상 경로:»(경계), 둘째 줄 «현재 계약:». */
@@ -99,6 +149,7 @@ export function renderWorkOrderGoal(order: WorkOrder): string {
99
149
  `판정 신호: ${order.verdictSignal}`,
100
150
  `예산: ${order.budget}`,
101
151
  `선행·짝 칸: ${order.peers}`,
152
+ ...(order.dependencies?.length ? [renderDependencies(order.dependencies)] : []),
102
153
  `선례: ${order.precedents}`,
103
154
  `올림 규칙: ${order.escalation}`,
104
155
  ].join('\n');
@@ -32,6 +32,7 @@ import {
32
32
  type AcceptanceReport,
33
33
  } from './acceptance.js';
34
34
  import { recordOpsEventSafe, type OpsEventInput } from '../domains/ops-log.js';
35
+ import { defaultAnomalyCluster, extractContainerExit, type AnomalyCluster } from '../loops/orchestrator/anomaly-cluster.js';
35
36
 
36
37
  // ───────────────────────── Concurrency caps ────────────────────────
37
38
 
@@ -82,6 +83,9 @@ export interface DispatcherOptions {
82
83
  * acceptance.checks reference fs or subprocess (file-exists /
83
84
  * file-contains / shell-zero). */
84
85
  acceptanceIo?: AcceptanceIo;
86
+ /** ANOMALY-CLUSTER — grouping state written at the failure record point; while a signature has 3+ runs
87
+ * and no cause verdict, relaunches of that goal·host are deferred instead of spawned. */
88
+ anomalyCluster?: AnomalyCluster;
85
89
  }
86
90
 
87
91
  export interface DispatchTickResult {
@@ -95,7 +99,7 @@ export interface DispatchTickResult {
95
99
  }>;
96
100
  /** Ready tasks we skipped this tick due to caps. Caller may `tick()`
97
101
  * again after any adapter completes. */
98
- deferred: Array<{ taskId: string; reason: 'cap' | 'no-adapter' | 'intake-sequential' }>;
102
+ deferred: Array<{ taskId: string; reason: 'cap' | 'no-adapter' | 'intake-sequential' | 'anomaly-hold' }>;
99
103
  }
100
104
 
101
105
  export class TaskDispatcher {
@@ -103,10 +107,13 @@ export class TaskDispatcher {
103
107
  private readonly activeByKind = new Map<TaskSurfaceKind, number>();
104
108
  private readonly abortByTask = new Map<string, AbortController>();
105
109
  private readonly now: () => number;
110
+ /** Production default is the process-wide cluster so tick-recorded failures gate relaunch here. */
111
+ private readonly anomaly: AnomalyCluster;
106
112
 
107
113
  constructor(private readonly opts: DispatcherOptions) {
108
114
  this.caps = { ...DEFAULT_CONCURRENCY_CAPS, ...(opts.concurrencyCaps ?? {}) };
109
115
  this.now = opts.now ?? Date.now;
116
+ this.anomaly = opts.anomalyCluster ?? defaultAnomalyCluster();
110
117
  }
111
118
 
112
119
  /**
@@ -147,6 +154,12 @@ export class TaskDispatcher {
147
154
  deferred.push({ taskId: task.id, reason: 'cap' });
148
155
  continue;
149
156
  }
157
+ // ANOMALY-CLUSTER relaunch gate: the task's goal·host relaunch is deferred while its signature has
158
+ // 3+ runs and no cause verdict has cleared it. Goal = task id, host = surface kind.
159
+ if (this.anomaly.hold(task.id, kind).hold) {
160
+ deferred.push({ taskId: task.id, reason: 'anomaly-hold' });
161
+ continue;
162
+ }
150
163
  const result = this.spawn(task, adapter);
151
164
  dispatched.push({
152
165
  taskId: task.id,
@@ -220,6 +233,24 @@ export class TaskDispatcher {
220
233
  }
221
234
  }
222
235
 
236
+ /** Records one failed attempt into the anomaly cluster (goal·host key, host excluded from signature). */
237
+ private recordAnomalyFailure(task: Task, observation: { runId: string; kind: string; stage: string; lastLines: string[] }): void {
238
+ try {
239
+ this.anomaly.record({
240
+ goal: task.id,
241
+ host: task.surface.kind,
242
+ runId: observation.runId,
243
+ kind: observation.kind,
244
+ containerExit: extractContainerExit(observation.lastLines.join('\n')),
245
+ stage: observation.stage,
246
+ lastLines: observation.lastLines,
247
+ at: new Date(this.now()).toISOString(),
248
+ });
249
+ } catch {
250
+ // Observability must not alter dispatch admission or completion.
251
+ }
252
+ }
253
+
223
254
  private recordOpsEvent(input: OpsEventInput): void {
224
255
  try {
225
256
  (this.opts.recordOpsEvent ?? recordOpsEventSafe)(input);
@@ -322,6 +353,8 @@ export class TaskDispatcher {
322
353
  this.recordOps(task, 'cycle_end', nextStatus, { execStatus: exec.status, durationMs: exec.durationMs });
323
354
 
324
355
  if (nextStatus === 'done') {
356
+ // Cause verdict — the same goal·host produced a clean run, so the relaunch hold is cleared.
357
+ this.anomaly.release(task.id, kind, '원인 판정: 실행이 정상 완료됨');
325
358
  this.opts.bus?.emit({
326
359
  kind: 'task-completed',
327
360
  taskId: task.id,
@@ -337,6 +370,12 @@ export class TaskDispatcher {
337
370
  reason: 'user',
338
371
  });
339
372
  } else {
373
+ this.recordAnomalyFailure(task, {
374
+ runId: exec.id,
375
+ kind: exec.status === 'timeout' ? 'timeout' : 'exit',
376
+ stage: 'monitor',
377
+ lastLines: [exec.error?.message ?? '', `Reason: ${exec.error?.code ?? 'UNKNOWN'}`],
378
+ });
340
379
  this.opts.bus?.emit({
341
380
  kind: 'task-failed',
342
381
  taskId: task.id,
@@ -368,6 +407,12 @@ export class TaskDispatcher {
368
407
  this.opts.store?.saveTask(this.opts.graph.getTask(task.id)!);
369
408
  } catch { /* ignore illegal transition */ }
370
409
  this.recordOps(task, 'cycle_end', 'failed', { errorCode: 'ADAPTER_ERROR', error: err instanceof Error ? err.message.slice(0, 120) : String(err) });
410
+ this.recordAnomalyFailure(task, {
411
+ runId: res.executionId,
412
+ kind: 'adapter-error',
413
+ stage: 'monitor',
414
+ lastLines: [err instanceof Error ? err.message : String(err)],
415
+ });
371
416
  this.opts.bus?.emit({
372
417
  kind: 'task-failed',
373
418
  taskId: task.id,
@@ -82,6 +82,8 @@ export function buildDecomposePrompt(
82
82
 
83
83
  const lines: string[] = [];
84
84
  const isGoalAuthorCoarse = opts.profile === 'goal-author-coarse';
85
+ const measuredDeviceInventory = input.context?.activeSummary?.match(/^Device inventory \(measured at goal-author repository root\): .*$/mu)?.[0];
86
+ const measuredDevice = measuredDeviceInventory?.match(/^Device inventory \(measured at goal-author repository root\): (missing|existing): (src\/ux-sim\/[^\s,]+)$/u);
85
87
  lines.push(
86
88
  'You are the monad-agent Task Orchestrator decomposition planner.',
87
89
  isGoalAuthorCoarse
@@ -205,6 +207,10 @@ export function buildDecomposePrompt(
205
207
  '## Device-first decomposition (DEVICE-FIRST-AUTHORING — follow strictly)',
206
208
  '### Existing device inventory (read from this checkout; use these names before proposing a new device)',
207
209
  ...deviceInventory(),
210
+ ...(measuredDeviceInventory
211
+ ? ['### Goal-author device check (measured at the target root; takes precedence over checkout inventory)',
212
+ measuredDeviceInventory,
213
+ ...(measuredDevice ? [`- Use the measured ${measuredDevice[1]} status for ${measuredDevice[2]} instead of this checkout's inventory when choosing the device branch.`] : [])] : []),
208
214
  '- The objective\'s verification plan (검증 계획/TDD) section picks a stage and ladder tier (무대·층) — e.g. a `src/ux-sim/*` stage at L2 (fake-llm·fake-bin·fake-clock). BEFORE writing slices, CHECK whether the mock device or injected event definition that this verification plan needs ALREADY EXISTS: look in `src/ux-sim/*`, the §1 device table of `docs/manual/MANUAL-ux-simulation-devices-2026-08-23.md`, and the event-monkey event kinds.',
209
215
  '- Two branches — exactly one applies per needed device:',
210
216
  ' - Device EXISTS: its name MUST go into the verification plan wording — the slice that tests the feature carries the device\'s exact name (device file / §1 table row / event kind) in its acceptance criteria and reuses the device; never re-create it.',
@@ -7,6 +7,8 @@ import { fromJsonl, type LogRecord } from '../../mss/logging/record.js';
7
7
 
8
8
  const FILE_LIMIT = 5 * 1024 * 1024;
9
9
  const TOTAL_LIMIT = 20 * 1024 * 1024;
10
+ export const POD_SALVAGE_BUNDLE_FILE_LIMIT = 160 * 1024 * 1024;
11
+ export const POD_SALVAGE_BUNDLE_TOTAL_LIMIT = 180 * 1024 * 1024;
10
12
 
11
13
  type Artifact = { path: string; bytes: Buffer };
12
14
  type Incomplete = { path: string; reason: string };
@@ -50,13 +52,16 @@ export function parsePodArtifactChunks(logs: string): ParseResult {
50
52
  }
51
53
  const artifacts: Artifact[] = [];
52
54
  const error: Incomplete[] = [];
53
- let bytesSoFar = 0;
55
+ let artifactBytes = 0;
56
+ let salvageBundleBytes = 0;
54
57
  for (const [token, group] of groups) {
55
58
  let path = token;
56
59
  let reason = group.reason;
57
60
  try {
58
61
  path = decodePath(token);
59
62
  if (!safeRelativePath(path)) throw new Error('unsafe relative path');
63
+ const salvageBundle = /^pod-salvage\/[a-zA-Z0-9._-]+\.bundle$/.test(path);
64
+ const fileLimit = salvageBundle ? POD_SALVAGE_BUNDLE_FILE_LIMIT : FILE_LIMIT;
60
65
  if (!reason && group.chunks.size !== group.total) reason = 'missing chunk';
61
66
  if (!reason) {
62
67
  let encoded = '';
@@ -64,15 +69,20 @@ export function parsePodArtifactChunks(logs: string): ParseResult {
64
69
  const chunk = group.chunks.get(i);
65
70
  if (!chunk) { reason = 'missing chunk'; break; }
66
71
  encoded += chunk;
67
- if (encoded.length > 8 * 1024 * 1024) { reason = 'file too large'; break; }
72
+ if (encoded.length > Math.ceil(fileLimit * 4 / 3) + 1024 * 1024) { reason = 'file too large'; break; }
68
73
  }
69
74
  if (!reason) {
70
75
  const compressed = Buffer.from(encoded, 'base64');
71
76
  if (compressed.toString('base64') !== encoded) throw new Error('invalid base64');
72
- const bytes = gunzipSync(compressed, { maxOutputLength: FILE_LIMIT + 1 });
73
- if (bytes.length > FILE_LIMIT) reason = 'file too large';
74
- else if (bytesSoFar + bytes.length > TOTAL_LIMIT) reason = 'total too large';
75
- else { artifacts.push({ path, bytes }); bytesSoFar += bytes.length; }
77
+ const bytes = gunzipSync(compressed, { maxOutputLength: fileLimit + 1 });
78
+ if (bytes.length > fileLimit) reason = 'file too large';
79
+ else if ((salvageBundle ? salvageBundleBytes : artifactBytes) + bytes.length >
80
+ (salvageBundle ? POD_SALVAGE_BUNDLE_TOTAL_LIMIT : TOTAL_LIMIT)) reason = 'total too large';
81
+ else {
82
+ artifacts.push({ path, bytes });
83
+ if (salvageBundle) salvageBundleBytes += bytes.length;
84
+ else artifactBytes += bytes.length;
85
+ }
76
86
  }
77
87
  }
78
88
  } catch (e) { reason = e instanceof Error ? e.message : String(e); }
@@ -14,6 +14,7 @@ type ParseResult = Ledger[] | { error: Incomplete[]; ledgers: Ledger[] };
14
14
  const NON_PROGRESS_EVENTS = new Set(['progress-delivery-outcome']);
15
15
  const REEMIT_EXCLUDED_PREFIX = 'progress-delivery';
16
16
  type Emit = (category: string, event: string, data: Record<string, unknown>) => void;
17
+ export interface PodLedgerMeasurement { ledgerRead: boolean; activityMeasured: boolean }
17
18
  /** Heal-loop starter seam — defaults to the real `startHealLoop` inside `recordFailureEvent`. */
18
19
  type StartHealLoop = Parameters<typeof recordFailureEvent>[2];
19
20
 
@@ -174,7 +175,7 @@ export function createPodLedgerFollower(opts: {
174
175
  stallMinutes?: number;
175
176
  now?: () => number;
176
177
  onStall?: (message: string) => void;
177
- }): { poll(): void; readonly owned: boolean } {
178
+ }): { poll(): PodLedgerMeasurement; readonly owned: boolean } {
178
179
  const dir = opts.dir ?? runLedgerDir();
179
180
  const log = opts.log ?? defaultPodReemit();
180
181
  const emit: Emit = opts.emit ?? defaultPodReemit();
@@ -208,17 +209,17 @@ export function createPodLedgerFollower(opts: {
208
209
  return {
209
210
  get owned() { return owned; },
210
211
  poll() {
211
- if (disabled) return;
212
+ if (disabled) return { ledgerRead: true, activityMeasured: false };
212
213
  if (!owned && existsSync(path)) {
213
214
  disabled = true;
214
215
  log('self-implement.pod', 'ledger-live-skipped', { runId: opts.runId, reason: 'host-ledger-exists' });
215
- return;
216
+ return { ledgerRead: true, activityMeasured: false };
216
217
  }
217
218
  const since = `${Math.floor(lastActivityMeasuredAt / 1000)}.${String(lastActivityMeasuredAt % 1000).padStart(3, '0')}`;
218
219
  const measurementStartedAt = now();
219
220
  const until = `${Math.floor(measurementStartedAt / 1000)}.${String(measurementStartedAt % 1000).padStart(3, '0')}`;
220
221
  const r = opts.exec(`s="\${ELANOUS_STATE_DIR:-$HOME/.elanous}"; f="$s/run-ledger/${opts.runId}.jsonl"; w="$s/worktrees"; if [ -f "$f" ]; then tail -c +${offset + 1} "$f" || exit 1; fi; target=''; matches=0; for tree in "$w"/*/*.worktrees/*; do [ -e "$tree/.git" ] || continue; owner=$(git -C "$tree" config --worktree --get elanous.harness.owner 2>/dev/null) || continue; [ "$owner" = 'dev:${opts.runId}' ] || continue; target="$tree"; matches=$((matches + 1)); done; if [ "$matches" -eq 1 ]; then activity=$(find "$target" -type d \\( -name .git -o -name node_modules \\) -prune -o -type f -newermt '@${since}' ! -newermt '@${until}' -printf . 2>/dev/null) && printf '\\nELANOUS_ACTIVITY %s\\n' "\${#activity}" || printf '\\nELANOUS_ACTIVITY_ERROR\\n'; else printf '\\nELANOUS_ACTIVITY_ERROR\\n'; fi`);
221
- if (r.status !== 0) { log('self-implement.pod', 'ledger-live-unavailable', { runId: opts.runId, status: r.status, stderr: r.stderr.trim().slice(0, 200) }); checkStall(false, false); return; }
222
+ if (r.status !== 0) { log('self-implement.pod', 'ledger-live-unavailable', { runId: opts.runId, status: r.status, stderr: r.stderr.trim().slice(0, 200) }); checkStall(false, false); return { ledgerRead: false, activityMeasured: false }; }
222
223
  const marker = r.stdout.lastIndexOf('\nELANOUS_ACTIVITY');
223
224
  const activityLine = marker < 0 ? '' : r.stdout.slice(marker + 1);
224
225
  const activityMatch = /^ELANOUS_ACTIVITY (0|[1-9]\d*)\n$/.exec(activityLine);
@@ -241,11 +242,11 @@ export function createPodLedgerFollower(opts: {
241
242
  }
242
243
  }
243
244
  }
244
- if (!ledgerBytes) { checkStall(true, activityMeasured); return; }
245
+ if (!ledgerBytes) { checkStall(true, activityMeasured); return { ledgerRead: true, activityMeasured }; }
245
246
  offset += Buffer.byteLength(ledgerBytes);
246
247
  const text = pending + ledgerBytes;
247
248
  const cut = text.lastIndexOf('\n');
248
- if (cut < 0) { pending = text; checkStall(true, activityMeasured); return; }
249
+ if (cut < 0) { pending = text; checkStall(true, activityMeasured); return { ledgerRead: true, activityMeasured }; }
249
250
  const complete = text.slice(0, cut + 1);
250
251
  pending = text.slice(cut + 1);
251
252
  mkdirSync(dir, { recursive: true });
@@ -278,6 +279,7 @@ export function createPodLedgerFollower(opts: {
278
279
  nextStallMinute = stallMinutes;
279
280
  }
280
281
  checkStall(true, activityMeasured);
282
+ return { ledgerRead: true, activityMeasured };
281
283
  },
282
284
  };
283
285
  }