elanous 0.2.34 → 0.2.35

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 (611) 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/{L04y73dlwKeTW-GetaTF3 → T1mBQqmkwKDLGtyisDCOd}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{5014f970-22bef0b5210f7d60.js → 0368f25d-ad84af92fefee68f.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1165.bad13fc9151a7288.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/13.02a07436dec15f89.js +32 -0
  7. package/apps/pwa/out/_next/static/chunks/{2124.ed5bf480cea7f85b.js → 1530.0e612369b6fd7ea0.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/1540.af38731fa7c4a3e0.js +41 -0
  9. package/apps/pwa/out/_next/static/chunks/1674.2a65fd5668e1cc5f.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/1850.f2b470ba5a471da0.js +24 -0
  11. package/apps/pwa/out/_next/static/chunks/193.62da94cd0b88323b.js +74 -0
  12. package/apps/pwa/out/_next/static/chunks/1975.260f6d249fac5f7c.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1982-67cd8dfe8682325f.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1993-c0007b7ad0c0ef41.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1c735de4.f993a30bbd3c57c4.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1dc5a567.9b092bfae3d7099b.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{8368.014caa8de2f5af34.js → 2018.a741297bce759490.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/2085.8f950b4bda1cbbc7.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2159-6179a961376956b9.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/216.b5c2a421aa1d28a5.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2251.49fbe369f74c372c.js +148 -0
  23. package/apps/pwa/out/_next/static/chunks/2286-2939577360d3dcc0.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2625.5d870aa999f33db1.js +34 -0
  25. package/apps/pwa/out/_next/static/chunks/2668.34d21539e62bf111.js +77 -0
  26. package/apps/pwa/out/_next/static/chunks/2833-0fe47af99ed13c29.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2930.d0edb4f108787ef7.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2973.77318e7d85f59477.js +62 -0
  29. package/apps/pwa/out/_next/static/chunks/3103.0df8da390948bb84.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/3123.2bee9ba15d320bd2.js +90 -0
  31. package/apps/pwa/out/_next/static/chunks/3162-6cf652bf7124d8cf.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{1644.35dd25240ae24e4b.js → 3408.21d1570602f4b6c0.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/3577-7340009f7007a795.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/{3121.779fafe3e44612c5.js → 3589.5444a06bcf6e775c.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/359-2250789a2d3499e7.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3618.f514792d6c59d7fd.js +36 -0
  37. package/apps/pwa/out/_next/static/chunks/3669.343f9119aa276001.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{9131-fce7256c4180c4a5.js → 3677-4215f826f6aa68e5.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/3736.c2efad489604cc3b.js +79 -0
  40. package/apps/pwa/out/_next/static/chunks/3817.f9aeab2bb6675d73.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3f7c4ee5.3dde54f01a816613.js +122 -0
  42. package/apps/pwa/out/_next/static/chunks/4182-0b9b1251c29cc0cf.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4346.8601952e73bf5803.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/{6053-d893974de92e6198.js → 4441-875b97f5821ed58a.js} +1 -1
  45. package/apps/pwa/out/_next/static/chunks/4582.bd68683c076649e3.js +286 -0
  46. package/apps/pwa/out/_next/static/chunks/4605-6e623f55aec77422.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4607.5cc27468628eb4bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4627.f07508b3936fd6c0.js +24 -0
  49. package/apps/pwa/out/_next/static/chunks/{1895-60ed0e341c658bd4.js → 4705-194e64e47ca0fbdb.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/{5576-82d3703636d5c4b9.js → 4718-17d2af636796a330.js} +3 -3
  51. package/apps/pwa/out/_next/static/chunks/4747-c22262c093e46807.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4775-178215aed0daba61.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4815-6ffb8c3c991cc45d.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4834-beca8b47ad29a898.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5023-fb4802b6d2492b02.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/{7431.3051e9b8a4372d2d.js → 5101.e32282718f99ed6f.js} +2 -2
  57. package/apps/pwa/out/_next/static/chunks/5154.a118f3957ed14e36.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5210-a2e0015e3d4d5d9c.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5356.84ac712cc15928bf.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5401.22352141b6fd336e.js +23 -0
  61. package/apps/pwa/out/_next/static/chunks/{2987-30cf9c2eb7b8bdd5.js → 5483-dd5d7697f6bdb106.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5637.281e5dec4ea6ecf1.js +94 -0
  63. package/apps/pwa/out/_next/static/chunks/5662.02eaa029af05ad46.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/56d372f2.681ab4ec4c998fae.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/{7386.5d8e7e42e818dfb6.js → 5852.db1f7449f4f74612.js} +2 -2
  67. package/apps/pwa/out/_next/static/chunks/5891-0f11a7d7362a9072.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5943.264d14a44ca32513.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/604-1b3c39df083c02aa.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/6121-5f97072330738caf.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6193.07d8ca5af4b09086.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6203-b3fea3a60d69ff14.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/{3110.0a7065f25c841818.js → 6236.e18cced2d5ba6afb.js} +3 -3
  74. package/apps/pwa/out/_next/static/chunks/6286.d638fb5953e2e757.js +8 -0
  75. package/apps/pwa/out/_next/static/chunks/630.fe5a46428d63b013.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6301.ae0245f507e4395e.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/6673.fbbe5699f6ea5991.js +27 -0
  78. package/apps/pwa/out/_next/static/chunks/6777-f6d301efb5de828d.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6786.423f24c88de034c7.js +93 -0
  80. package/apps/pwa/out/_next/static/chunks/6854-cef64a948c5e122d.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6866-79aa5b4e47cac6aa.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6b89c8bd.24df687a820500b3.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7037-fe27f001db30d323.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7080.2d826860534fd88e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7118.8731be28c3ebb14b.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7196.44241bc1df3e26fe.js +149 -0
  87. package/apps/pwa/out/_next/static/chunks/7235.c7c4e6cb5c693c2d.js +104 -0
  88. package/apps/pwa/out/_next/static/chunks/{7005.1623d2aea78eb85f.js → 7385.50a308a477bdfc21.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/{6086.913a69e6fa3e4a8b.js → 7644.17e37ba6f1d4226e.js} +4 -4
  90. package/apps/pwa/out/_next/static/chunks/7706-58bfb1546637f217.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7839.5b91455338c9fd3f.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7857-31f13ee96f4011aa.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/81.f74cb60312fe4001.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/8219.baa715d1deee80e2.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8256.e3ac8421a71f82f4.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/8310-444a6a895c402f12.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8423.f7dda8aca4fcaae5.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{7193-cf355cca5ba6c5d5.js → 8437-8d5492094b166cfa.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/{2554.3b5e200f5f5cfcd6.js → 8444.4c26b379ca2b9596.js} +4 -4
  100. package/apps/pwa/out/_next/static/chunks/8496.75649af8652c74f4.js +226 -0
  101. package/apps/pwa/out/_next/static/chunks/8557-e7898769499cd56f.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8576.65bb654b524f3614.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8609.558ce2f8f9aea2be.js +64 -0
  104. package/apps/pwa/out/_next/static/chunks/8614.caec96cfb91f4ae7.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{2547.dd27303624cb4da8.js → 8637.47f5b35afcae5e6b.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8714.ff0b7ce3ec3e3ae2.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8732.367f44a916202353.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9141-7fd1f73a5400bdc2.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/921.c4267d0d69a65404.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{9550.d5f76828f972058c.js → 9214.63a510d39178e997.js} +2 -2
  111. package/apps/pwa/out/_next/static/chunks/9261.3962c3321b047691.js +115 -0
  112. package/apps/pwa/out/_next/static/chunks/936-26efd1a0efdd44d3.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{8548.036c344973968847.js → 938.66ad1ef0e5abae1c.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/{3414.172ad4ca2d9b08e8.js → 9512.5a76207a730e0491.js} +2 -2
  115. package/apps/pwa/out/_next/static/chunks/9627-4b9efe616b27e2e2.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/967-2aa39b2d04b4c690.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9734.40eb1e558c29ccea.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9908.3aa54f7a586a73dc.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{6740.43de73fc427c9fe2.js → 9952.5daf5f94063a2b3e.js} +1 -1
  120. package/apps/pwa/out/_next/static/chunks/9954-ca8d29752bdbb45a.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9974-507fa67cb94066dd.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-ce9e00f7fb45506a.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-fa59d6d17daa3389.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-53f68bbe7bd4b774.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-1c500fbb9f4a7a04.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-99d72673aa5c307c.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-d2d5adc1e9484c88.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c607c5aae637f1cc.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-fa8c23596d555c0f.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-bdab8c5e855c8416.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-406b47745b53f269.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-a4276386b7051f50.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8a26bab9ad375f25.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-775f48aa1dc7a2d5.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-1c4dd5f959d0c558.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-c48938a8377c9f70.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-ce9e00f7fb45506a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-c6e7905859425aa9.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-c280f4252452e830.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-cf8c57498f20970a.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-ca3a17caf409fc83.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/{page-d7bff0f0905a662c.js → page-26e6c18a1a750cf6.js} +1 -1
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-3abc872cc6aeee39.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-f7481b7b2174fe3d.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1ae7ef8077680337.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-47c5d4db587266bd.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-415f1e243c7ccb13.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-73f380f17b76f95c.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-2991073ad66ee2d9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1f5a60f70cb4dd0c.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fbad60d1e358fb2c.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-bac7dee94e5eae4a.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-398047d6949e8ca5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2d33a2231540ca89.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5bf1e6bf70bcb96c.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-ba59c19376a0917d.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-111f187139add30f.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-acaae197d5be5779.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0df20b0f546a0d7d.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-ce9e00f7fb45506a.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-27e1202d24b8fe35.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-bda78c50a78363e5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-da592691293d9c9f.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f832994317a2e9f0.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/{page-df3445b207ceceab.js → page-dc0a532f5b9196ec.js} +1 -1
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-cfccbbeae0473404.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-527e2073af84c81b.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-bac86e9112671357.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6d59dff410e9d76a.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-53a61f8be09f02d2.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-db8f559e763c17f9.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c02aa4cc66455093.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{9a8cb466.cc9fc9e6e46038aa.js → b2f6ba4d.fb56fdbbf798df33.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/b6705a4f-b9a9047de9eecfd0.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/{4fa33ebd.21c1bd5b294496e6.js → cbe38a15.5a032598e39970c6.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/{abb4b98b.163e0f56e84ae35d.js → d06f9160.a3d9062f95de8ad7.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/{9b48c871.204d5d13e7809bd0.js → da5176c6.6773b6c5994e1d99.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-50e6acebc630849b.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-7a1ae342d5ed75e6.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-7ad7d505ba1f92b4.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-02edba75232cb235.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-97d6ebae3e8eee4a.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-e986adaa429163e8.js +1 -0
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +22 -22
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +22 -22
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +22 -22
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +21 -21
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +21 -21
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +22 -22
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +21 -21
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +22 -22
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +22 -22
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +21 -21
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +22 -22
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +22 -22
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +22 -22
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +22 -22
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +21 -21
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +21 -21
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +22 -22
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +22 -22
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +22 -22
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +21 -21
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +21 -21
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +22 -22
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +22 -22
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +21 -21
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +21 -21
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +21 -21
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +22 -22
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +22 -22
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +21 -21
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +22 -22
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +22 -22
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +22 -22
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +22 -22
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +22 -22
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +21 -21
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +22 -22
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +22 -22
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +22 -22
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +22 -22
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +22 -22
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +22 -22
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +22 -22
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +22 -22
  277. package/bin/elanous.mjs +3 -2
  278. package/catalog/providers/opengateway.yaml +25 -0
  279. package/docs/goal-context/01-goal-authoring-checks.md +8 -0
  280. package/docs/goal-context/03-verification-menu.md +24 -0
  281. package/docs/goal-context/04-mock-scenarios.md +100 -0
  282. package/docs/goal-context/README.md +4 -0
  283. package/graphs/catalog/catalog.yaml +1 -1
  284. package/graphs/default-loop.yaml +57 -3
  285. package/graphs/document-loop.yaml +51 -3
  286. package/graphs/implement-loop.yaml +53 -4
  287. package/graphs/journey/ta-journey.yaml +11 -1
  288. package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
  289. package/graphs/journey/units/author-dialogue/observe.ts +96 -0
  290. package/graphs/journey/units/author-dialogue/recipes.yaml +10 -0
  291. package/graphs/operate-loop.yaml +51 -3
  292. package/graphs/research-loop.yaml +137 -3
  293. package/graphs/test-diet/test-diet.yaml +3 -0
  294. package/package.json +1 -1
  295. package/scripts/coord-role-pack.ts +19 -6
  296. package/scripts/hq/standby-snapshot.ts +17 -12
  297. package/scripts/release-loop/docs-land-node.ts +21 -5
  298. package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
  299. package/scripts/release-loop/gate-node.ts +181 -22
  300. package/scripts/release-loop/gate-partial.ts +65 -11
  301. package/scripts/release-loop/gate-radius-live.ts +177 -0
  302. package/scripts/release-loop/gate-radius-shadow.ts +1 -1
  303. package/scripts/release-loop/node-verdict.ts +12 -1
  304. package/scripts/release-loop/npm-publish-node.ts +66 -12
  305. package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
  306. package/scripts/release-loop/pwa-remote.ts +166 -0
  307. package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
  308. package/scripts/release-loop/resume-release.ts +41 -4
  309. package/scripts/release-loop/unattended-release.ts +2 -0
  310. package/scripts/test-diet/lib.ts +6 -1
  311. package/scripts/test-diet/node.ts +194 -13
  312. package/scripts/ux-sim.ts +39 -0
  313. package/src/agent/self-ambient-cache.ts +8 -0
  314. package/src/agent-substrate/acp-reviewer.ts +39 -4
  315. package/src/agent-substrate/pr-reviewer.ts +17 -0
  316. package/src/agent-substrate/self-review-cli.ts +62 -13
  317. package/src/autopilot/pr-manager.ts +215 -36
  318. package/src/budget/run-usage-rollup.ts +1 -0
  319. package/src/chat/index.ts +0 -2
  320. package/src/chat/pickers/modal-runtime.ts +10 -27
  321. package/src/cli/agent-cli.ts +13 -2
  322. package/src/cli/doctor-cli.ts +4 -1
  323. package/src/cli/light-entry-route.ts +46 -6
  324. package/src/cli/pod-cli.ts +77 -3
  325. package/src/cli/pr-cli.ts +5 -2
  326. package/src/cli/pr-land-pod-shadow-job.ts +3 -0
  327. package/src/cli/release-checklist-read-cli.ts +79 -0
  328. package/src/cli/release-cli.ts +72 -102
  329. package/src/cli/remote-resolve.ts +1 -1
  330. package/src/cli/root-tui-entry.ts +48 -0
  331. package/src/cli/sim-cli.ts +22 -0
  332. package/src/cli/tasks-cli.ts +540 -31
  333. package/src/cli/usage-cli.ts +13 -11
  334. package/src/clipboard/history.ts +179 -13
  335. package/src/config.ts +8 -1
  336. package/src/dashboard/chat/acp-chat.ts +8 -0
  337. package/src/dashboard/index.ts +78 -10
  338. package/src/dashboard/render/theme-resolver.ts +33 -4
  339. package/src/domains/schedule-registry.ts +16 -2
  340. package/src/git-fs/idle-refresh.ts +76 -0
  341. package/src/git-fs/index.ts +18 -7
  342. package/src/git-fs/worktree.ts +42 -4
  343. package/src/graph-kinds/registry.ts +2 -2
  344. package/src/graph-runner/runner.ts +153 -10
  345. package/src/grok/credential.ts +10 -3
  346. package/src/harness/harness-cli-command.ts +112 -28
  347. package/src/harness/harness-incidents.ts +33 -0
  348. package/src/harness/launch-utterance-ledger.ts +208 -0
  349. package/src/impl-discipline/detector.ts +16 -4
  350. package/src/impl-discipline/system-prompt.ts +11 -0
  351. package/src/impl-discipline/types.ts +2 -2
  352. package/src/index.ts +496 -143
  353. package/src/intake-plane/already-built-hint.ts +4 -2
  354. package/src/intake-plane/requirement-funnel.ts +29 -1
  355. package/src/light-cli.ts +27 -11
  356. package/src/llm/opengateway-models.ts +11 -0
  357. package/src/llm/provider-credentials.ts +14 -0
  358. package/src/llm/provider-detect.ts +8 -1
  359. package/src/llm/runtime-model-family.ts +2 -1
  360. package/src/llm.ts +213 -56
  361. package/src/model-tier/llm-tier-map.ts +15 -1
  362. package/src/native-tool-catalog.ts +15 -1
  363. package/src/nexus/api/loop-resources.ts +13 -1
  364. package/src/oauth/codex.ts +7 -0
  365. package/src/ops/overview-collect.ts +18 -3
  366. package/src/ops/overview.ts +20 -7
  367. package/src/pr-tool/census.ts +261 -27
  368. package/src/pty-shell/pty-manifest.ts +7 -0
  369. package/src/release-loop/checklist.ts +24 -0
  370. package/src/release-loop/landed-but-yellow.ts +129 -5
  371. package/src/release-loop/light-rc.ts +1 -0
  372. package/src/release-loop/rehearsal.ts +2 -2
  373. package/src/repl/index.ts +174 -17
  374. package/src/repl/ops-msg-bridge.ts +32 -0
  375. package/src/self-dev/ask-launch-flow.ts +44 -5
  376. package/src/self-dev/cli-help-text.ts +17 -0
  377. package/src/self-dev/dev-cli.ts +11 -9
  378. package/src/self-dev/draft-residue.ts +37 -1
  379. package/src/self-dev/draft-sweep.ts +137 -11
  380. package/src/self-dev/draft-triage-rules.ts +107 -0
  381. package/src/self-dev/fleet-reduce.ts +3 -2
  382. package/src/self-dev/graph-front-nodes.ts +112 -0
  383. package/src/self-dev/graph-journey-nodes.ts +1 -0
  384. package/src/self-dev/harness-run-cli.ts +3 -15
  385. package/src/self-dev/orchestrate-cli-text.ts +10 -0
  386. package/src/self-dev/review-provider-fallback.ts +35 -1
  387. package/src/self-dev/self-orchestrate-runtime.ts +1 -11
  388. package/src/self-dev/shard-aggregate.ts +42 -5
  389. package/src/self-dev/shard-run.ts +8 -1
  390. package/src/self-implement/blocked-draft-policy.ts +20 -0
  391. package/src/self-implement/classify-shadow.ts +3 -7
  392. package/src/self-implement/doctor-visit.ts +18 -1
  393. package/src/self-implement/gate-baseline.ts +56 -17
  394. package/src/self-implement/gate-cli.ts +1 -0
  395. package/src/self-implement/gate-remote.ts +31 -20
  396. package/src/self-implement/goal-author-decompose.ts +275 -47
  397. package/src/self-implement/goal-author.ts +250 -0
  398. package/src/self-implement/goal-elaborate.ts +295 -0
  399. package/src/self-implement/goal-refine.ts +270 -0
  400. package/src/self-implement/graph-overlay-yaml.ts +14 -3
  401. package/src/self-implement/orchestrator.ts +152 -45
  402. package/src/self-implement/rework-budget-judgment.ts +5 -8
  403. package/src/self-implement/run-stop.ts +10 -1
  404. package/src/self-implement/running-runs.ts +29 -1
  405. package/src/self-implement/scope-adjacency.ts +113 -0
  406. package/src/self-implement/seams.ts +127 -24
  407. package/src/self-implement/stop-autoheal.ts +87 -1
  408. package/src/session-runtime/index.ts +1 -1
  409. package/src/setup/llm-env-detect.ts +5 -0
  410. package/src/skills/tools/agent.ts +140 -14
  411. package/src/skills/tools/msg-ask.ts +100 -0
  412. package/src/skills/tools/ops-ledger.ts +2 -1
  413. package/src/steward/hold-hygiene.ts +24 -6
  414. package/src/steward/triage-budget.ts +194 -0
  415. package/src/steward/triage.ts +20 -3
  416. package/src/task-agent/actions.ts +69 -1
  417. package/src/task-agent/green-sweep.ts +4 -0
  418. package/src/task-agent/live-moves.ts +160 -4
  419. package/src/task-agent/parent-host.ts +123 -3
  420. package/src/task-agent/shadow.ts +7 -1
  421. package/src/task-agent/task-hand.ts +54 -41
  422. package/src/task-agent/tier-split.ts +127 -0
  423. package/src/task-agent/work-order-build.ts +2 -0
  424. package/src/task-agent/work-order.ts +3 -2
  425. package/src/task-orchestrator/generator-prompt.ts +60 -11
  426. package/src/task-orchestrator/surfaces/pod-account-broker.ts +33 -0
  427. package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
  428. package/src/task-orchestrator/surfaces/pod-command-job.ts +45 -7
  429. package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
  430. package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
  431. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +8 -2
  432. package/src/task-orchestrator/surfaces/pod-provenance.ts +76 -0
  433. package/src/task-orchestrator/surfaces/pod-source-receive.ts +18 -0
  434. package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
  435. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +6 -2
  436. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +3 -0
  437. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +37 -5
  438. package/src/task-orchestrator/surfaces/self-implement-pod.ts +368 -36
  439. package/src/task-orchestrator/surfaces/self-implement.ts +23 -0
  440. package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
  441. package/src/tui/README.md +2 -0
  442. package/src/tui/chat/background-job-status.ts +54 -0
  443. package/src/tui/chat/log-view.ts +80 -0
  444. package/src/tui/entry.ts +406 -0
  445. package/src/tui/input/composer.ts +144 -0
  446. package/src/tui/seat-mail-boot.ts +59 -0
  447. package/src/tui/slash/compact.ts +100 -0
  448. package/src/tui/slash/new-session.ts +35 -0
  449. package/src/tui-client/local-chat-turn.ts +239 -0
  450. package/src/tui-client/local-harness-command.ts +63 -0
  451. package/src/tui-client/local-provider-command.ts +184 -0
  452. package/src/user-config.ts +4 -2
  453. package/src/ux-sim/event-monkey.ts +378 -0
  454. package/src/ux-sim/fake-bin.ts +42 -7
  455. package/src/ux-sim/fault-nextmove-dispatch.ts +266 -0
  456. package/src/ux-sim/fault-pod-codex-503.ts +211 -0
  457. package/src/ux-sim/fault-scope-escape-lift.ts +189 -0
  458. package/src/version/packed-revision.json +1 -1
  459. package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +0 -79
  460. package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +0 -1
  461. package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +0 -94
  463. package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +0 -23
  465. package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +0 -1
  466. package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +0 -115
  467. package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +0 -8
  468. package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +0 -1
  472. package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/3001-5a52788c813b6113.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +0 -1
  477. package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/3103.84470c8445962f04.js +0 -34
  479. package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +0 -1
  482. package/apps/pwa/out/_next/static/chunks/3411-f87314c6c66ebc73.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/3498.cf2a15a8a9e5b926.js +0 -226
  485. package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/3819.163d4777f0a597f6.js +0 -32
  487. package/apps/pwa/out/_next/static/chunks/3837.722e053fb9f321ad.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +0 -104
  490. package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +0 -286
  491. package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +0 -149
  492. package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +0 -148
  493. package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +0 -64
  494. package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +0 -74
  497. package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/5028-f0722e6114c313e7.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/5249.96a848656b582a93.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +0 -62
  504. package/apps/pwa/out/_next/static/chunks/5446.edf141cff9ef647d.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/5489.ec2dd1b5272a19dc.js +0 -24
  506. package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +0 -77
  517. package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +0 -90
  520. package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/7448.478958ffbbba0ac0.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/7562.948255cbc3e79d33.js +0 -41
  527. package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +0 -27
  530. package/apps/pwa/out/_next/static/chunks/7952.b192c31b6a0e00cc.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +0 -36
  533. package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/8817.61bb7ffbba502ecb.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +0 -93
  547. package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +0 -24
  549. package/apps/pwa/out/_next/static/chunks/9739.8d5f36ac67a3b236.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/field/page-4fb31eb476dcbad3.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-398c0faa173203f7.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +0 -122
  603. package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/ffdc3a04.b9c23c1b28dd4a96.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +0 -1
  611. /package/apps/pwa/out/_next/static/{L04y73dlwKeTW-GetaTF3 → T1mBQqmkwKDLGtyisDCOd}/_ssgManifest.js +0 -0
@@ -22,7 +22,8 @@ import { templateForGoalType } from '../self-implement/graph-templates.js';
22
22
  import { appendRunLedgerEntry, listRunLedgers, loadFederatedRunLedger, loadRunLedger, queryRunScreenKey, runLedgerDir, type RunLedgerEntry, type RunLedgerMatch, type RunLedgerWriter } from '../self-implement/run-ledger.js';
23
23
  import { classifyPodExit, type PodExitClass } from '../task-orchestrator/surfaces/pod-failure-reason.js';
24
24
  import type { PodChildEvidence } from '../task-orchestrator/surfaces/self-implement.js';
25
- import { classifyPodExitStop, recordRunStop, runStopRecorded, RUN_STOP_EVENT } from '../self-implement/run-stop.js';
25
+ import { classifyPodExitStop, readRunStopRecord, recordRunStop, runStopRecorded, RUN_STOP_EVENT } from '../self-implement/run-stop.js';
26
+ import { captureStopKnowhowCandidate } from '../self-implement/stop-autoheal.js';
26
27
  import { ensureOpenRouterChildModelLive, resolveChildLlmEffort, resolveImplementationChildModel } from '../self-dev/dev-cli.js';
27
28
  import { resolveHarnessTarget } from '../self-implement/harness-target-options.js';
28
29
  import { buildRunProgressRows, isPartialRunningRuns, queryRunningRuns, renderRunProgressTable } from '../self-implement/running-runs.js';
@@ -450,7 +451,7 @@ export function classifyHarnessPodExit(
450
451
  loadCheckpoint?: typeof loadSelfDevRun;
451
452
  runId?: string;
452
453
  } = {},
453
- ): { lines: string[]; reason: PodExitReason | 'pod-failure' } {
454
+ ): { lines: string[]; reason: PodExitReason | 'pod-failure'; podErrorCode?: 'pod-job-failed' } {
454
455
  const occupiedNewLine = output.split('\n').find((line) =>
455
456
  /^\[self-dev\] run run-[a-z0-9_-]{8,64} \[preflight:new-path-occupied:[0-9a-f-]{36}\] /.test(line));
456
457
  const observedRunId = deps.runId ?? harnessPodRunId(output);
@@ -475,6 +476,7 @@ export function classifyHarnessPodExit(
475
476
  }
476
477
  let podFailure: string | undefined;
477
478
  let podJobFailed = false;
479
+ let podJobFailedFromResult = false;
478
480
  let podChildFailed = false;
479
481
  for (const line of output.split('\n').reverse()) {
480
482
  if (!line.trimStart().startsWith('[{') || !line.includes('"error"')) continue;
@@ -487,6 +489,7 @@ export function classifyHarnessPodExit(
487
489
  if (typeof error?.code !== 'string' || typeof error.message !== 'string' || !error.code.startsWith('pod-')) continue;
488
490
  podFailure = error.message;
489
491
  podJobFailed = error.code === 'pod-job-failed';
492
+ podJobFailedFromResult = podJobFailed;
490
493
  podChildFailed = error.code === 'pod-child-failed';
491
494
  break;
492
495
  }
@@ -505,7 +508,7 @@ export function classifyHarnessPodExit(
505
508
  if (podFailure) {
506
509
  const childError = podJobFailed ? podFailure.split('childError=')[1]?.split('\\n', 1)[0]?.split('\n', 1)[0] : undefined;
507
510
  try { debug.log('harness.pod', 'exit-classified', { runId, reason: 'pod-failure', status: exit.status, signal: exit.signal ?? null }); } catch { /* observation is fail-soft */ }
508
- return { reason: 'pod-failure', lines: [podChildFailed
511
+ return { reason: 'pod-failure', ...(podJobFailedFromResult ? { podErrorCode: 'pod-job-failed' as const } : {}), lines: [podChildFailed
509
512
  ? `Pod 안 자식이 실패했다 — ${podFailure.split('\\n', 1)[0]}`
510
513
  : podJobFailed && childError && childError !== 'no-result-line'
511
514
  ? `Pod 안 자식이 실패했다 — ${childError}`
@@ -769,7 +772,7 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
769
772
  export function recordHarnessPodStop(
770
773
  runId: string | undefined,
771
774
  status: number,
772
- classified: { reason: string; lines: string[] },
775
+ classified: { reason: string; lines: string[]; podErrorCode?: 'pod-job-failed' },
773
776
  output?: string,
774
777
  deps: { loadLedger?: typeof loadRunLedger; record?: typeof recordRunStop; write?: RunLedgerWriter } = {},
775
778
  ): boolean {
@@ -805,11 +808,32 @@ export function recordHarnessPodStop(
805
808
  }
806
809
  // The classified line is our own one-line verdict («Pod 안 자식이 실패했다 — OOMKilled»), not the raw output tail.
807
810
  const verdict = classified.lines[0]?.split(' — ').slice(1).join(' — ').trim();
808
- (deps.record ?? recordRunStop)({
811
+ const stopEntry = (deps.record ?? recordRunStop)({
809
812
  runId, site: 'pod-exit', class: scopeEscape ? 'scope-escape' : classifyPodExitStop(classified.reason),
810
813
  cause: `Pod exit ${status}: ${scopeEscape ? 'scope-escape' : classified.reason}${verdict ? ` — ${verdict}` : ''}`,
811
814
  evidenceRef, nextMove, ...(childEvidence ? { childEvidence } : {}),
815
+ ...(classified.podErrorCode === 'pod-job-failed' ? { terminationReason: classified.podErrorCode } : {}),
812
816
  }, ...(deps.write ? [deps.write] : []));
817
+ // Host-only Pod exits do not pass through orchestrator.autohealRecordedStop. Capture the
818
+ // exact Job failure here, after the durable stop write, without initiating a heal action.
819
+ if (classified.podErrorCode === 'pod-job-failed' && stopEntry) {
820
+ try {
821
+ const record = readRunStopRecord(stopEntry);
822
+ if (record) {
823
+ const goalId = ledger?.find((entry) => entry.goalId)?.goalId;
824
+ const captured = captureStopKnowhowCandidate({ runId, ...(goalId ? { goalId } : {}), record },
825
+ join(effectiveInstanceRoot(), 'self-implement', 'knowhow-candidates'));
826
+ if (captured) debug.log('self-implement.autoheal', 'knowhow-candidate', {
827
+ runId, cell: captured.candidate.cell, reason: captured.candidate.reason,
828
+ created: captured.created, occurrences: captured.candidate.occurrences, path: captured.path,
829
+ });
830
+ }
831
+ } catch (error) {
832
+ try { debug.log('self-implement.autoheal', 'knowhow-candidate-failed', {
833
+ runId, error: error instanceof Error ? error.message : String(error),
834
+ }); } catch { /* observation is fail-soft */ }
835
+ }
836
+ }
813
837
  return true;
814
838
  } catch { return false; /* ledger observation cannot change Pod output or exit */ }
815
839
  }
@@ -2378,8 +2402,9 @@ function githubRemoteRepository(url: string): string | undefined {
2378
2402
  interface GraphqlPrDetail {
2379
2403
  readonly files: string[] | null;
2380
2404
  readonly comments: string[] | null;
2381
- readonly reviews: Array<{ state?: string; body?: string }> | null;
2405
+ readonly reviews: Array<{ state?: string; body?: string; submittedAt?: string; commitOid?: string }> | null;
2382
2406
  readonly headSha: string | null;
2407
+ readonly headCommittedAt: string | null;
2383
2408
  readonly mergeCommit: { oid: string; message: string } | null;
2384
2409
  }
2385
2410
 
@@ -2407,10 +2432,10 @@ async function graphqlPrDetails(repository: string, numbers: readonly number[],
2407
2432
  // Fields the batch could not prove complete (each one is read again over REST by the caller).
2408
2433
  const incompleteFields = { files: 0, comments: 0, reviews: 0 };
2409
2434
  await mapBounded(batches, DRAFT_SWEEP_CONCURRENCY, async (batch) => {
2410
- const fields = batch.map((number) => `p${number}: pullRequest(number: ${number}) { number headRefOid `
2435
+ const fields = batch.map((number) => `p${number}: pullRequest(number: ${number}) { number headRefOid headRef { target { ... on Commit { committedDate } } } `
2411
2436
  + 'files(first: 100) { totalCount nodes { path } pageInfo { hasNextPage } } '
2412
2437
  + 'comments(first: 100) { totalCount nodes { body } pageInfo { hasNextPage } } '
2413
- + 'reviews(first: 100) { totalCount nodes { state body } pageInfo { hasNextPage } } '
2438
+ + 'reviews(first: 100) { totalCount nodes { state body submittedAt commit { oid } } pageInfo { hasNextPage } } '
2414
2439
  + 'mergeCommit { oid message } }').join(' ');
2415
2440
  const query = `query { repository(owner: ${JSON.stringify(owner)}, name: ${JSON.stringify(name)}) { ${fields} } }`;
2416
2441
  let repositoryNode: Record<string, unknown> | undefined;
@@ -2421,9 +2446,10 @@ async function graphqlPrDetails(repository: string, numbers: readonly number[],
2421
2446
  if (!repositoryNode || typeof repositoryNode !== 'object' || Array.isArray(repositoryNode)) { failedBatches += 1; return; }
2422
2447
  for (const number of batch) {
2423
2448
  const pr = repositoryNode[`p${number}`] as {
2424
- number?: number; headRefOid?: string;
2449
+ number?: number; headRefOid?: string; headRef?: { target?: { committedDate?: string } | null } | null;
2425
2450
  files?: GraphqlConnection<{ path?: string }>; comments?: GraphqlConnection<{ body?: string }>;
2426
- reviews?: GraphqlConnection<{ state?: string; body?: string }>; mergeCommit?: { oid?: string; message?: string } | null;
2451
+ reviews?: GraphqlConnection<{ state?: string; body?: string; submittedAt?: string; commit?: { oid?: string } | null }>;
2452
+ mergeCommit?: { oid?: string; message?: string } | null;
2427
2453
  } | null | undefined;
2428
2454
  if (!pr || pr.number !== number) continue;
2429
2455
  const files = completeNodes(pr.files);
@@ -2433,8 +2459,10 @@ async function graphqlPrDetails(repository: string, numbers: readonly number[],
2433
2459
  files: files && files.every((file) => typeof file?.path === 'string') ? files.map((file) => file.path!) : null,
2434
2460
  comments: comments && comments.every((comment) => typeof comment?.body === 'string') ? comments.map((comment) => comment.body!) : null,
2435
2461
  reviews: reviews && reviews.every((review) => review && typeof review === 'object')
2436
- ? reviews.map((review) => ({ state: review.state, body: review.body })) : null,
2462
+ ? reviews.map((review) => ({ state: review.state, body: review.body, submittedAt: review.submittedAt,
2463
+ commitOid: review.commit?.oid })) : null,
2437
2464
  headSha: typeof pr.headRefOid === 'string' && pr.headRefOid ? pr.headRefOid : null,
2465
+ headCommittedAt: typeof pr.headRef?.target?.committedDate === 'string' ? pr.headRef.target.committedDate : null,
2438
2466
  mergeCommit: pr.mergeCommit && typeof pr.mergeCommit.oid === 'string' && typeof pr.mergeCommit.message === 'string'
2439
2467
  ? { oid: pr.mergeCommit.oid, message: pr.mergeCommit.message } : null,
2440
2468
  };
@@ -2565,30 +2593,80 @@ export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: Dr
2565
2593
  }
2566
2594
  throw new Error(`${what === 'review' ? 'Review' : what === 'same-cell' ? 'Same-cell' : 'Landing'} comment inventory exceeded pagination limit`);
2567
2595
  };
2596
+ const reviewsFor = async (repository: string, number: number): Promise<Array<{ state?: string; body?: string; submittedAt?: string; commitOid?: string }>> => {
2597
+ const reviews: Array<{ state?: string; body?: string; submittedAt?: string; commitOid?: string }> = [];
2598
+ for (let page = 1; page <= 100; page++) {
2599
+ const batch = await ghJsonAsync<Array<{ state?: string; body?: string; submitted_at?: string; commit_id?: string }>>(
2600
+ ['api', `repos/${repository}/pulls/${number}/reviews?per_page=100&page=${page}`]);
2601
+ if (!Array.isArray(batch) || batch.length > 100) throw new Error('Incomplete review inventory');
2602
+ reviews.push(...batch.map((review) => ({ state: review.state, body: review.body,
2603
+ submittedAt: review.submitted_at, commitOid: review.commit_id })));
2604
+ if (batch.length < 100) return reviews;
2605
+ }
2606
+ throw new Error('Review inventory exceeded pagination limit');
2607
+ };
2608
+ const checkRunsFor = async (repository: string, sha: string): Promise<Array<{ conclusion?: string | null }> | undefined> => {
2609
+ const runs: Array<{ conclusion?: string | null }> = [];
2610
+ for (let page = 1; page <= 100; page++) {
2611
+ const result = await ghJsonAsync<{ total_count?: number; check_runs?: Array<{ conclusion?: string | null }> }>(
2612
+ ['api', `repos/${repository}/commits/${sha}/check-runs?per_page=100&page=${page}`]);
2613
+ if (!Array.isArray(result?.check_runs) || result.check_runs.length > 100) throw new Error('Incomplete check-run inventory');
2614
+ runs.push(...result.check_runs);
2615
+ if (Number.isSafeInteger(result.total_count) && runs.length >= result.total_count!) return runs;
2616
+ if (result.check_runs.length < 100) return Number.isSafeInteger(result.total_count) && runs.length < result.total_count! ? undefined : runs;
2617
+ }
2618
+ return undefined;
2619
+ };
2620
+ const headCommitTimeFor = async (repository: string, number: number): Promise<string | undefined> => {
2621
+ let latest: string | undefined;
2622
+ for (let page = 1; page <= 100; page++) {
2623
+ const batch = await ghJsonAsync<Array<{ commit?: { committer?: { date?: string } } }>>(
2624
+ ['api', `repos/${repository}/pulls/${number}/commits?per_page=100&page=${page}`]);
2625
+ if (!Array.isArray(batch) || batch.length > 100) throw new Error('Incomplete PR commit inventory');
2626
+ for (const commit of batch) {
2627
+ const date = commit.commit?.committer?.date;
2628
+ if (!date || !Number.isFinite(Date.parse(date))) throw new Error('Incomplete PR commit timestamp');
2629
+ latest = date;
2630
+ }
2631
+ if (batch.length < 100) return latest;
2632
+ }
2633
+ throw new Error('PR commit inventory exceeded pagination limit');
2634
+ };
2568
2635
  const reviewGateForDraft = async (draft: SweepDraft, repository: string): Promise<SweepReviewGate | undefined> => {
2569
2636
  const cached = await detailFor(repository, draft.number);
2570
2637
  const sha = cached?.headSha
2571
2638
  ?? (await ghJsonAsync<{ head?: { sha?: string } }>(['api', `repos/${repository}/pulls/${draft.number}`]))?.head?.sha;
2572
2639
  if (!sha) return undefined;
2640
+ const reviews = cached?.reviews ?? await reviewsFor(repository, draft.number);
2641
+ if (!Array.isArray(reviews)) throw new Error('Incomplete review inventory');
2573
2642
  const comments = cached?.comments ?? await issueCommentsFor(repository, draft.number, 'review');
2574
- const reviews = cached?.reviews
2575
- ?? await ghJsonAsync<Array<{ state?: string; body?: string }>>(['api', `repos/${repository}/pulls/${draft.number}/reviews?per_page=100`]);
2576
- if (!Array.isArray(reviews) || reviews.length > 100) throw new Error('Incomplete review inventory');
2577
- const text = [...comments, ...reviews.map((review) => review.body ?? '')].join('\n');
2643
+ const legacyText = [...comments, ...reviews.map((review) => review.body ?? '')].join('\n');
2644
+ const currentHeadReviews = reviews.filter((review) => review && typeof review === 'object'
2645
+ && review.commitOid === sha
2646
+ && typeof review.submittedAt === 'string' && Number.isFinite(Date.parse(review.submittedAt)))
2647
+ .sort((a, b) => Date.parse(a.submittedAt!) - Date.parse(b.submittedAt!));
2648
+ const latestHeadReview = currentHeadReviews.at(-1);
2649
+ const triageReview = latestHeadReview?.state === 'APPROVED' ? 'approved'
2650
+ : latestHeadReview?.state === 'CHANGES_REQUESTED' ? 'changes-requested'
2651
+ : latestHeadReview?.state === 'COMMENTED' ? 'commented'
2652
+ : latestHeadReview?.state === 'DISMISSED' ? 'dismissed'
2653
+ : latestHeadReview?.state === 'PENDING' ? 'pending' : 'unknown';
2578
2654
  const [status, checkRuns] = await Promise.all([
2579
2655
  ghJsonAsync<{ state?: string }>(['api', `repos/${repository}/commits/${sha}/status`]),
2580
- ghJsonAsync<{ check_runs?: Array<{ conclusion?: string | null }> }>(['api', `repos/${repository}/commits/${sha}/check-runs?per_page=100`]),
2656
+ checkRunsFor(repository, sha),
2581
2657
  ]);
2582
- if (!checkRuns || !Array.isArray(checkRuns.check_runs)) throw new Error('Incomplete check-run inventory');
2583
- const conclusions = checkRuns.check_runs.map((run) => run.conclusion ?? null);
2584
- const gatePass = (status?.state === 'success' || status?.state === undefined)
2585
- && conclusions.length > 0 && conclusions.every((conclusion) => conclusion === 'success' || conclusion === 'skipped' || conclusion === 'neutral');
2658
+ const conclusions = checkRuns?.map((run) => run.conclusion ?? null) ?? [];
2659
+ const gatePass = status?.state === 'success'
2660
+ && checkRuns !== undefined && conclusions.length > 0
2661
+ && conclusions.every((conclusion) => conclusion === 'success' || conclusion === 'skipped' || conclusion === 'neutral');
2586
2662
  const gateFail = status?.state === 'failure' || status?.state === 'error'
2587
2663
  || conclusions.some((conclusion) => conclusion === 'failure' || conclusion === 'cancelled' || conclusion === 'timed_out' || conclusion === 'action_required');
2588
2664
  return {
2589
- ...(reviews.some((review) => review.state === 'APPROVED') || /(?:^|\n)\s*VERDICT:\s*PASS\b/i.test(text) ? { review: 'pass' as const } : {}),
2590
- ...(mustFixRemains(text) ? { mustFix: true } : {}),
2665
+ ...(reviews.some((review) => review.state === 'APPROVED') || /(?:^|\n)\s*VERDICT:\s*PASS\b/i.test(legacyText)
2666
+ ? { review: 'pass' as const } : {}),
2667
+ ...(mustFixRemains(legacyText) ? { mustFix: true } : {}),
2591
2668
  ...(gatePass && !gateFail ? { gate: 'pass' as const } : gateFail ? { gate: 'fail' as const } : {}),
2669
+ triageReview,
2592
2670
  };
2593
2671
  };
2594
2672
  const claimCommentsFor = async (repository: string, number: number): Promise<string[]> => {
@@ -2618,11 +2696,15 @@ export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: Dr
2618
2696
  const prs = (await listed(open, repository, 'open')).filter((pr) => pr.draft);
2619
2697
  await prefetchDetails(repository, prs.map((pr) => pr.number));
2620
2698
  const matches = ledgerMatches ??= listRunLedgers().matches;
2621
- return mapBounded(prs, DRAFT_SWEEP_CONCURRENCY, async (pr): Promise<SweepDraft> => ({
2622
- number: pr.number, title: pr.title, branch: pr.head.ref,
2623
- labels: pr.labels.map((item) => item.name), createdAt: pr.created_at, body: pr.body ?? undefined,
2624
- changedFiles: await prFiles(repository, pr.number), ...(pr.updated_at ? { updatedAt: pr.updated_at } : {}),
2625
- runId: currentDraftSweepRunId(matches, repository, pr.number) }));
2699
+ return mapBounded(prs, DRAFT_SWEEP_CONCURRENCY, async (pr): Promise<SweepDraft> => {
2700
+ return {
2701
+ number: pr.number, title: pr.title, branch: pr.head.ref,
2702
+ labels: pr.labels.map((item) => item.name), createdAt: pr.created_at, body: pr.body ?? undefined,
2703
+ changedFiles: await prFiles(repository, pr.number),
2704
+ ...(pr.updated_at ? { updatedAt: pr.updated_at } : {}),
2705
+ runId: currentDraftSweepRunId(matches, repository, pr.number),
2706
+ };
2707
+ });
2626
2708
  })());
2627
2709
  return draftRows.get(repository)!;
2628
2710
  };
@@ -2677,6 +2759,8 @@ export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: Dr
2677
2759
  },
2678
2760
  listDrafts: async (page, perPage, repository): Promise<SweepDraft[]> =>
2679
2761
  (await enrichedDrafts(repository)).slice((page - 1) * perPage, page * perPage),
2762
+ getHeadCommitTime: async (repository, number) => (await detailFor(repository, number))?.headCommittedAt
2763
+ ?? await headCommitTimeFor(repository, number).catch(() => undefined),
2680
2764
  listMerged: async (page, perPage, repository): Promise<SweepMergedPr[]> =>
2681
2765
  (await enrichedMerged(repository)).slice((page - 1) * perPage, page * perPage),
2682
2766
  getRunStatus: async (draft, repository) => runStatusFor(draft, repository),
@@ -2943,7 +3027,7 @@ function installHarnessDraftSweepCommand(harnessCmd: Command, deps: HarnessDraft
2943
3027
  owner: 'unknown', ownerSource: 'unknown', step: 'replay', reason: sweepFailureReason(error) });
2944
3028
  }
2945
3029
  }
2946
- const result: DraftSweepResult = await runDraftSweep({ repository, apply: opts.apply === true, adapters: deps.adapters ?? github!,
3030
+ const result: DraftSweepResult = await runDraftSweep({ repository, apply: opts.apply === true, includeTriage: opts.json === true, adapters: deps.adapters ?? github!,
2947
3031
  closeCap: cap.closeCap, closeCapSource: cap.closeCapSource, alreadyClosed: replayClosed });
2948
3032
  const reason = result.error ? sweepFailureReason(result.error) : undefined;
2949
3033
  const ttlStarted = Date.now();
@@ -209,6 +209,39 @@ export function recentBurst(root: string, now: Date | number, { lookbackMs = 15
209
209
  return recent.sort((a, b) => Date.parse(a.lastAt) - Date.parse(b.lastAt)).at(-1) ?? null;
210
210
  }
211
211
 
212
+ /** 사고 선례 1건 — 현재 사고 이전의 같은 reason 종료 기록(결정론 · 기록된 실제 exit 만). */
213
+ export interface IncidentPrecedent {
214
+ runId: string;
215
+ reason: string;
216
+ status: number | null;
217
+ signal: string | null;
218
+ at: string;
219
+ lastLines?: string[];
220
+ }
221
+
222
+ /**
223
+ * 사고 선례 연결 — 현재 사고(reason·at) 이전에 같은 reason 으로 종료된 기록된 실제 exit 만
224
+ * 돌려준다(유사 과거 지어내기 금지 · readRunExits 재사용 · READ-ONLY). 현재 runId 는 제외하고
225
+ * 시간 내림차순, 기본 5건까지. 기록이 없으면 빈 배열(«기록 없음»).
226
+ */
227
+ export function findIncidentPrecedents(
228
+ current: { reason: string; at: string; runId?: string },
229
+ root: string,
230
+ { limit = 5 }: { limit?: number } = {},
231
+ ): IncidentPrecedent[] {
232
+ const at = Date.parse(current.at);
233
+ if (!current.reason.trim() || !Number.isFinite(at)) return [];
234
+ return readRunExits(root)
235
+ .filter((row) => row.reason === current.reason && row.runId !== current.runId
236
+ && Date.parse(row.at) < at)
237
+ .sort((a, b) => Date.parse(b.at) - Date.parse(a.at) || b.runId.localeCompare(a.runId))
238
+ .slice(0, Math.max(0, limit))
239
+ .map((row) => ({
240
+ runId: row.runId, reason: row.reason, status: row.status, signal: row.signal, at: row.at,
241
+ ...(Array.isArray(row.lastLines) ? { lastLines: row.lastLines } : {}),
242
+ }));
243
+ }
244
+
212
245
  export function formatIncidentBurstWarning(burst: IncidentBurst): string {
213
246
  const time = new Date(Date.parse(burst.lastAt) + KST_OFFSET_MS).toISOString().slice(11, 16);
214
247
  const owner = burst.seat || burst.entrance ? ` [seat=${burst.seat ?? '-'} entrance=${burst.entrance ?? '-'}]` : '';
@@ -0,0 +1,208 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ import { closeSync, constants, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, writeSync } from 'node:fs';
3
+ import { join, parse, resolve } from 'node:path';
4
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
5
+ import { debug } from '../debug/log.js';
6
+
7
+ /** Product ledger of the raw first text a launch entrance received (say · hand · ask-file).
8
+ * Auxiliary evidence: preparing or appending never refuses a launch — failures are observed. */
9
+ export interface LaunchUtteranceStart {
10
+ readonly event: 'start';
11
+ readonly launchId: string;
12
+ readonly source: 'say' | 'hand' | 'ask-file';
13
+ readonly utterance: string;
14
+ /** sha256 of the UTF-8 bytes of `utterance` (or of the raw bytes when given). */
15
+ readonly sha256: string;
16
+ /** Present only when the raw source bytes are not lossless UTF-8 (ask-file). */
17
+ readonly utteranceBase64?: string;
18
+ /** Present for `say`: the exact argv words the process received. */
19
+ readonly argv?: readonly string[];
20
+ /** The entrance was asked for a plan only (`--dry-run`) — the text was received, nothing launched. */
21
+ readonly dryRun?: true;
22
+ readonly at: string;
23
+ }
24
+
25
+ export interface LaunchUtteranceInput {
26
+ readonly source: LaunchUtteranceStart['source'];
27
+ readonly utterance: string;
28
+ readonly launchId: string;
29
+ readonly rawBytes?: Uint8Array;
30
+ readonly argv?: readonly string[];
31
+ readonly dryRun?: boolean;
32
+ }
33
+
34
+ const LAUNCH_ID = /^tl-[0-9a-f]{12}$/;
35
+ const DATE_FILE = /^\d{4}-\d{2}-\d{2}\.jsonl$/;
36
+ const DAY_MS = 86_400_000;
37
+
38
+ /** Env contract of the one explicit hand→say pair (set by the hand launcher, consumed once by say). */
39
+ export const HAND_LAUNCH_ID_ENV = 'ELANOUS_HAND_LAUNCH_ID';
40
+ export const HAND_LAUNCH_SHA256_ENV = 'ELANOUS_HAND_LAUNCH_SHA256';
41
+ export const HAND_LAUNCH_RUN_ENV = 'ELANOUS_HAND_LAUNCH_RUN';
42
+ /** base64 of the hand's exact original text (untrimmed), so the paired child can re-record it byte-exact. */
43
+ export const HAND_LAUNCH_ORIGINAL_ENV = 'ELANOUS_HAND_LAUNCH_ORIGINAL_B64';
44
+ const MAX_ORIGINAL_ENV_BYTES = 64 * 1024;
45
+
46
+ /** Same `tl-<12 hex>` shape the hand card contract already carries; minted fresh in every process. */
47
+ export function newLaunchUtteranceId(): string { return `tl-${randomBytes(6).toString('hex')}`; }
48
+ export function isLaunchUtteranceId(value: unknown): value is string { return typeof value === 'string' && LAUNCH_ID.test(value); }
49
+ export function utteranceSha256(value: string | Uint8Array): string { return createHash('sha256').update(value).digest('hex'); }
50
+
51
+ /** Env a hand launcher passes to its say child so that pair — and only that pair — shares the ID.
52
+ * `sentence` is the exact argv word the say child receives; `original` is the hand's untrimmed text. */
53
+ export function handLaunchPairEnv(launchId: string, sentence: string, runId: string, original?: string): Record<string, string> {
54
+ const originalB64 = original === undefined ? undefined : Buffer.from(original, 'utf8').toString('base64');
55
+ return {
56
+ [HAND_LAUNCH_ID_ENV]: launchId, [HAND_LAUNCH_SHA256_ENV]: utteranceSha256(sentence), [HAND_LAUNCH_RUN_ENV]: runId,
57
+ ...(originalB64 !== undefined && originalB64.length <= MAX_ORIGINAL_ENV_BYTES ? { [HAND_LAUNCH_ORIGINAL_ENV]: originalB64 } : {}),
58
+ };
59
+ }
60
+
61
+ /** Hand launcher seam: only a `harness say <sentence>` launch with a launchId ⊕ runId gets the pair env
62
+ * (ID ⊕ sentence sha ⊕ runId ⊕ exact original). Any other launch context passes through unchanged. */
63
+ export function withHandLaunchPairContext<C extends { launchId?: string; runId?: string; env: Record<string, string>; launchUtterance?: string }>(
64
+ args: readonly string[], context: C,
65
+ ): C {
66
+ const sayAt = args.indexOf('say');
67
+ const sentence = args.at(-1);
68
+ if (!context.launchId || !context.runId || sayAt < 1 || args[sayAt - 1] !== 'harness' || sentence === undefined || sayAt === args.length - 1) return context;
69
+ return { ...context, env: { ...context.env, ...handLaunchPairEnv(context.launchId, sentence, context.runId, context.launchUtterance) } };
70
+ }
71
+
72
+ /** Resolve the say launchId: inherit only when the env pair matches this exact sentence and run, then
73
+ * remove the pair from `env` so no descendant or later say in this process can reuse the ID.
74
+ * When paired, `utterance` is the hand's exact original text (falls back to the sentence). */
75
+ export function consumeHandLaunchId(sentence: string, env: NodeJS.ProcessEnv = process.env, runIdEnv = 'ELANOUS_RUN_ID'): {
76
+ launchId: string; inherited: boolean; utterance: string;
77
+ } {
78
+ const inherited = env[HAND_LAUNCH_ID_ENV];
79
+ const sha = env[HAND_LAUNCH_SHA256_ENV];
80
+ const run = env[HAND_LAUNCH_RUN_ENV];
81
+ const originalB64 = env[HAND_LAUNCH_ORIGINAL_ENV];
82
+ for (const key of [HAND_LAUNCH_ID_ENV, HAND_LAUNCH_SHA256_ENV, HAND_LAUNCH_RUN_ENV, HAND_LAUNCH_ORIGINAL_ENV]) delete env[key];
83
+ const paired = isLaunchUtteranceId(inherited) && sha === utteranceSha256(sentence)
84
+ && typeof run === 'string' && run.length > 0 && env[runIdEnv] === run;
85
+ if (inherited !== undefined && !paired) {
86
+ try { debug.log('harness.launch-utterance', 'inherit-refused', { hasSha: sha !== undefined, hasRun: run !== undefined }); } catch { /* fail-soft */ }
87
+ }
88
+ if (!paired) return { launchId: newLaunchUtteranceId(), inherited: false, utterance: sentence };
89
+ const original = originalB64 === undefined ? undefined : Buffer.from(originalB64, 'base64').toString('utf8');
90
+ const utterance = original !== undefined && original.trim() === sentence.trim() ? original : sentence;
91
+ return { launchId: inherited, inherited: true, utterance };
92
+ }
93
+
94
+ /** Symlink policy over every component of `path`, parents included: a symlink owned by the system
95
+ * (uid 0 — e.g. macOS `/var` · `/tmp`) is an OS alias and allowed; any other symlink is refused, so a
96
+ * user-made link can never redirect one instance's ledger into another instance. */
97
+ export function assertLedgerPathPolicy(path: string): void {
98
+ if (!path.trim()) throw new Error('ledger path must not be empty');
99
+ const absolute = resolve(path);
100
+ let part = parse(absolute).root;
101
+ for (const segment of absolute.slice(part.length).split('/').filter(Boolean)) {
102
+ part = join(part, segment);
103
+ let stat;
104
+ try { stat = lstatSync(part); } catch (error) {
105
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;
106
+ throw error;
107
+ }
108
+ if (stat.isSymbolicLink() && stat.uid !== 0) throw new Error(`ledger symlink refused: ${part}`);
109
+ }
110
+ }
111
+
112
+ export function launchUtteranceDir(root: string = effectiveInstanceRoot()): string {
113
+ return join(resolve(root), 'launch-utterances');
114
+ }
115
+
116
+ function observeFailure(operation: 'prepare' | 'append' | 'query', error: unknown, extra: Record<string, unknown> = {}): void {
117
+ const reason = error instanceof Error ? error.message : String(error);
118
+ try { debug.log('harness.launch-utterance', `${operation}-failed`, { operation, reason, ...extra }, { level: 'warn' }); } catch { /* logging must not block launch */ }
119
+ try { console.error(`[launch-utterance] ${operation} failed: ${reason}`); } catch { /* fail-soft */ }
120
+ }
121
+
122
+ function buildRow(input: LaunchUtteranceInput, now: Date): LaunchUtteranceStart {
123
+ const raw = input.rawBytes;
124
+ const lossy = raw !== undefined && !Buffer.from(input.utterance, 'utf8').equals(Buffer.from(raw));
125
+ return {
126
+ event: 'start',
127
+ launchId: input.launchId,
128
+ source: input.source,
129
+ utterance: input.utterance,
130
+ sha256: utteranceSha256(raw ?? input.utterance),
131
+ ...(lossy ? { utteranceBase64: Buffer.from(raw).toString('base64') } : {}),
132
+ ...(input.argv ? { argv: [...input.argv] } : {}),
133
+ ...(input.dryRun === true ? { dryRun: true as const } : {}),
134
+ at: now.toISOString(),
135
+ };
136
+ }
137
+
138
+ /** Append one start row to this instance's date file. Returns whether it landed; never throws. */
139
+ export function recordLaunchUtterance(
140
+ input: LaunchUtteranceInput,
141
+ root: string = effectiveInstanceRoot(),
142
+ now: Date = new Date(),
143
+ ): boolean {
144
+ let dir: string;
145
+ let row: string;
146
+ try {
147
+ if (!isLaunchUtteranceId(input.launchId)) throw new Error(`invalid launchId: ${String(input.launchId)}`);
148
+ dir = launchUtteranceDir(root);
149
+ assertLedgerPathPolicy(dir);
150
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
151
+ assertLedgerPathPolicy(dir);
152
+ if (!lstatSync(dir).isDirectory()) throw new Error(`ledger dir is not a directory: ${dir}`);
153
+ row = `${JSON.stringify(buildRow(input, now))}\n`;
154
+ } catch (error) { observeFailure('prepare', error, { source: input.source, launchId: input.launchId }); return false; }
155
+ try {
156
+ const file = join(dir, `${now.toISOString().slice(0, 10)}.jsonl`);
157
+ const fd = openSync(file, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW, 0o600);
158
+ try {
159
+ if (!fstatSync(fd).isFile()) throw new Error(`ledger file is not a regular file: ${file}`);
160
+ writeSync(fd, row);
161
+ } finally { closeSync(fd); }
162
+ try { debug.log('harness.launch-utterance', 'recorded', { source: input.source, launchId: input.launchId }); } catch { /* fail-soft */ }
163
+ return true;
164
+ } catch (error) { observeFailure('append', error, { source: input.source, launchId: input.launchId }); return false; }
165
+ }
166
+
167
+ function readNoFollow(file: string): string {
168
+ const fd = openSync(file, constants.O_RDONLY | constants.O_NOFOLLOW);
169
+ try {
170
+ if (!fstatSync(fd).isFile()) throw new Error(`ledger file is not a regular file: ${file}`);
171
+ return readFileSync(fd, 'utf8');
172
+ } finally { closeSync(fd); }
173
+ }
174
+
175
+ /** Reads only this instance's date files that overlap [now - sinceMs, now], and rows inside that window. */
176
+ export function queryLaunchUtterances(options: { root?: string; sinceMs?: number; now?: Date } = {}): LaunchUtteranceStart[] {
177
+ const now = options.now ?? new Date();
178
+ const sinceMs = options.sinceMs ?? DAY_MS;
179
+ if (!Number.isFinite(sinceMs) || sinceMs < 0 || sinceMs > 31 * DAY_MS) throw new Error('invalid ledger query window');
180
+ const until = now.getTime();
181
+ const from = until - sinceMs;
182
+ const dir = launchUtteranceDir(options.root);
183
+ let names: string[];
184
+ try {
185
+ assertLedgerPathPolicy(dir);
186
+ if (!lstatSync(dir).isDirectory()) throw new Error(`ledger dir is not a directory: ${dir}`);
187
+ names = readdirSync(dir);
188
+ } catch (error) {
189
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') observeFailure('query', error);
190
+ return [];
191
+ }
192
+ const rows: LaunchUtteranceStart[] = [];
193
+ for (const name of names.filter((n) => DATE_FILE.test(n)).sort()) {
194
+ const day = Date.parse(`${name.slice(0, 10)}T00:00:00.000Z`);
195
+ if (!Number.isFinite(day) || day > until || day + DAY_MS <= from) continue;
196
+ let text: string;
197
+ try { text = readNoFollow(join(dir, name)); } catch (error) { observeFailure('query', error, { file: name }); continue; }
198
+ for (const line of text.split('\n')) {
199
+ if (!line) continue;
200
+ try {
201
+ const row = JSON.parse(line) as LaunchUtteranceStart;
202
+ const at = Date.parse(row.at);
203
+ if (row.event === 'start' && typeof row.utterance === 'string' && Number.isFinite(at) && at >= from && at <= until) rows.push(row);
204
+ } catch { /* skip torn line */ }
205
+ }
206
+ }
207
+ return rows;
208
+ }
@@ -1,6 +1,6 @@
1
1
  // Phase detector for implementation discipline.
2
2
  //
3
- // Given the current turn's user text, classify into one of three
3
+ // Given the current turn's user text, classify into one of four
4
4
  // phases. The system-prompt builder reads this result to decide
5
5
  // which discipline guidance (if any) to inject as a system message.
6
6
  //
@@ -8,15 +8,16 @@
8
8
  // plan-loaded — PLAN-*.md / HANDOFF-*.md / SPEC-*.md file-ref
9
9
  // OR Korean/English doc keyword (핸드오프, 플랜
10
10
  // 문서, handoff, plan doc, 스펙 문서).
11
+ // design-first — implementation request contains an explicit new
12
+ // project, empty repository, or from-scratch signal.
11
13
  // implementation-ready — starts with an implementation verb
12
14
  // (구현/implement/build/포팅/port/만들어) AND
13
15
  // NOT paired with an exploration verb
14
16
  // (설명/분석/리뷰).
15
17
  // idle — everything else.
16
18
  //
17
- // plan-loaded wins over implementation-ready when both would fire —
18
- // when a plan doc is in play, the LLM must read-and-confirm before
19
- // diving into edits, even if the user also said "구현해".
19
+ // An explicit new-project request wins over plan-loaded; otherwise the
20
+ // existing plan-loaded and implementation-ready precedence is unchanged.
20
21
 
21
22
  import type { DetectInput, ImplPhase } from './types.js';
22
23
 
@@ -38,6 +39,11 @@ const DOC_KEYWORDS = [
38
39
  ];
39
40
 
40
41
  const IMPL_VERB_RE = /(^|[\s\u3000])(구현|implement|build|포팅|port|만들어)/i;
42
+ const PROJECT_IMPL_VERB_RE = /(^|[\s\u3000])(구현|implement|build|포팅|port|개발|develop|생성|create|만들어)/i;
43
+ const NEW_PROJECT_SIGNAL_RE = /(?:새(?:로운)?\s*(?:저장소|프로젝트)|빈\s*저장소|(?:new|empty)\s+(?:repository|repo|project)\b)/i;
44
+ const FROM_SCRATCH_RE = /(?:\bfrom\s+scratch\b|처음부터)/i;
45
+ const PROJECT_TARGET_RE = /(?:\b(?:project|app|service)\b|프로젝트|앱|서비스|웹앱)/i;
46
+ const FUNCTION_TARGET_RE = /(?:함수|function|method)/i;
41
47
 
42
48
  // Exploration verbs that, when co-occurring with an implementation
43
49
  // verb, downgrade the turn to idle. "이 함수 구현 방식 분석해줘"
@@ -58,6 +64,12 @@ export function detectImplPhase(input: DetectInput): ImplPhase {
58
64
  if (!trimmed) return 'idle';
59
65
  const lower = trimmed.toLowerCase();
60
66
 
67
+ const explicitProjectScope = NEW_PROJECT_SIGNAL_RE.test(trimmed)
68
+ || (FROM_SCRATCH_RE.test(trimmed) && PROJECT_TARGET_RE.test(trimmed) && !FUNCTION_TARGET_RE.test(trimmed));
69
+ if (explicitProjectScope && PROJECT_IMPL_VERB_RE.test(trimmed)) {
70
+ return 'design-first';
71
+ }
72
+
61
73
  if (FILE_REF_RE.test(trimmed) || hasDocKeyword(lower)) {
62
74
  return 'plan-loaded';
63
75
  }
@@ -23,6 +23,15 @@ const PLAN_LOADED_PROMPT = `# 플랜/핸드오프 문서 참조 감지
23
23
  5. "should I proceed?" 같은 열린 질문 금지 — 확정된 선택지(2~4개) 로 묻거나 plan 을 제출.
24
24
  6. 사용자 확인이 명확히 있을 때만 Edit/Write 로 진입.`;
25
25
 
26
+ const DESIGN_FIRST_PROMPT = `# 새 프로젝트 구현 요청 — RFC 먼저
27
+
28
+ 사용자가 새 저장소나 새 프로젝트의 구현을 요청했습니다. 앱 코드·프로젝트 설정을 쓰거나 시험을 실행하기 전에 저장소 루트에 RFC.md 초안을 작성하고 명시적 승인을 요청하세요.
29
+
30
+ 1. 요청에 PLAN/HANDOFF/SPEC 문서가 있으면 먼저 읽고 RFC 초안에 목표·범위·비목표·설계·수용 기준을 반영하세요.
31
+ 2. RFC 초안과 결정이 필요한 항목을 제시하고 승인을 요청하세요.
32
+ 3. 승인 전에는 애플리케이션 코드·설정을 만들거나 시험을 실행하지 마세요.
33
+ 4. 승인 뒤 RFC와 대조해 구현을 시작하세요.`;
34
+
26
35
  const IMPLEMENTATION_READY_PROMPT = `# 명시적 구현 요청 감지
27
36
 
28
37
  사용자가 구현을 요청했습니다. **구현 요청 자체가 실행 승인입니다.** 계획을 설명한 뒤 멈추지 말고, 이번 턴 안에서 실제 코드 편집(Edit/Write)까지 진행하세요.
@@ -79,6 +88,7 @@ function promptWithNativeStructure(phase: ImplPhase, enabledTools: readonly Nati
79
88
  const { listNativeToolDisplayNamesByKind } = require('../native-tool-catalog.js') as typeof import('../native-tool-catalog.js');
80
89
  const namesByKind = listNativeToolDisplayNamesByKind(enabledTools);
81
90
  switch (phase) {
91
+ case 'design-first': return DESIGN_FIRST_PROMPT;
82
92
  case 'plan-loaded': {
83
93
  let prompt = PLAN_LOADED_PROMPT;
84
94
  prompt = replaceDirective(prompt, '1. 먼저 Read 로 문서 전체를 읽으세요 (offset/limit 없이).', namesByKind, ['read']);
@@ -111,6 +121,7 @@ export function promptForPhase(phase: ImplPhase, options: ImplDisciplinePromptOp
111
121
  }
112
122
  switch (phase) {
113
123
  case 'plan-loaded': return PLAN_LOADED_PROMPT;
124
+ case 'design-first': return DESIGN_FIRST_PROMPT;
114
125
  case 'implementation-ready': return IMPLEMENTATION_READY_PROMPT;
115
126
  case 'idle': return '';
116
127
  }
@@ -1,11 +1,11 @@
1
1
  // Implementation-discipline phase types.
2
2
  //
3
- // The detector maps a user turn to one of three phases; the
3
+ // The detector maps a user turn to one of four phases; the
4
4
  // system-prompt builder emits different guidance per phase. State is
5
5
  // derived per-turn (stateless) so a wrong classification self-heals
6
6
  // on the next turn.
7
7
 
8
- export type ImplPhase = 'idle' | 'plan-loaded' | 'implementation-ready';
8
+ export type ImplPhase = 'idle' | 'plan-loaded' | 'design-first' | 'implementation-ready';
9
9
 
10
10
  export interface DetectInput {
11
11
  /** Raw user text for the current turn. */