elanous 0.2.13 → 0.2.15

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 (524) 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/LZcstaO9_NXypPFmujolv/_buildManifest.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/{7334.a6679d9168f37aa8.js → 1268.0840ff91e083fcbd.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1307-33ffcc49ab45123b.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/{9656-c1540088f5859c80.js → 1844-9ec4b1d12f6e80eb.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/1866-e7a6999f25548b30.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{390.c373e31b3b9d0c41.js → 1948.15f356b15a625597.js} +2 -2
  10. package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/224-798346143007ff65.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/2699-63b73fa4d3bcf6ff.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/2957-96ffab3d521fb08f.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/4144-a0041c8dc3be57ac.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/4554-3565eea1f1495ba7.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/{4685-c3c1c625b71accd1.js → 4614-21403aac730d4586.js} +1 -1
  23. package/apps/pwa/out/_next/static/chunks/{8039-df92e08fede5de8f.js → 4795-f372490b178583fc.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/5135-44008fe8b1f2aa41.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/5233-bf28bd6bd7a32099.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/5360-be1f1d8f9fcc9755.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/5977-c952712c87a1f757.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/5994-ae92c0de046ab9ba.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/{1452.93700483b9d4fc61.js → 6110.1297d4093fdfbb0d.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/6158.9c0449a9a8d0064b.js +2 -0
  31. package/apps/pwa/out/_next/static/chunks/6877-7c6208705c284124.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/{1829-b453a1b22d3999bb.js → 7327-2d69fb321ba73389.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/7395-164e238f471b5d7b.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/7787-02a1c0b04e25e811.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8827-e2f5b09a8d37e83b.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8868-10a3a4440fb0ccd8.js +25 -0
  42. package/apps/pwa/out/_next/static/chunks/{8421-1c4acfb1395a0edf.js → 8949-ecb4128a0858b911.js} +1 -1
  43. package/apps/pwa/out/_next/static/chunks/899-46946fe8363e1262.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/9070.067c106528ec1ae6.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/9103-7a3ae7f60af3b99f.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/{3869-3cd46526879f454c.js → 9247-29d889b809288e65.js} +1 -1
  47. package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/{79f8be9e-957d68913b590b08.js → a9f2b54d-7865aba0f4d2ee49.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/app/approvals/page-0e2c57fe6add4b2a.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-e05a77df7e005b04.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/board/page-f544338193a9a762.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/botlab/page-5491c115b1f9a923.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/bots/page-b8c49f6b4fa2df91.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/ceo/page-96398e364fbd4548.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/app/chat/page-976813c91d7394ea.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/consult/page-28b9448091776c06.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/control/page-1d4901eb7c2d8822.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/design-check/page-72d3e7ff35a8c954.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/editor/page-60c7a8e1a4fe62ce.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/exec/page-2a52b316cb143d9c.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/field/page-c3ce483c8d5db370.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/app/inside/page-13c7b53e0c2519a9.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/app/intake/page-96f074f6538e8a2c.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/layout-e97be5334d83a9f5.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/live/page-65e484302921a932.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/loops/page-34d08facaf08f556.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/market/page-955ec2da3be4c560.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-9f88fbc15d9058d1.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/morning/page-c1343f9499d86f3f.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/not-found-8739a2e0ae793130.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/observatory/page-c9fc5706b8abaa11.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-d23b12bb92242558.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8d47f45a0dc044ac.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c7fea475488201a8.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/outputs/page-e2ee2896811e98d0.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/page-83b19dae8619de05.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/reflection/page-5efbf81124c474ae.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f1a1fc0a82738c.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/sessions/page-da6c08aae0f92768.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-06ee266953d9c879.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/settings/page-153c2b3bcc89e8de.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-87a11e6a05f15199.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/app/setup/page-7d4182964407c09c.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/app/share/page-0d6d23b40263a7ea.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/app/showroom/page-7e8c39241f8eb6d0.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/app/tasks/page-008c1a96618a4887.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/app/term/{page-63d14a4d8fe1e1c1.js → page-f5597e894c02cd33.js} +1 -1
  91. package/apps/pwa/out/_next/static/chunks/app/today/page-0337fdf7fb5e37b6.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/app/trace/page-73735b64bfe1ae67.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/app/vault/page-8fcec4c9ea2e7f70.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-f7e631e9b4daf66e.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/app/workflows/page-4881b8f9f63694b4.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/app/workspace/page-9817c7f9007466cc.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-97f9f43172a3a90e.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{5cd7e3a9-404fd6b8d0ecd44c.js → f6231284-45726550aba08fca.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/{f48170cc-d05d28bf87a43bf4.js → f6b7c9ba.64a895b8b2fedbdc.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/framework-5c169757551134ed.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/webpack-539cde99554be20f.js +1 -0
  106. package/apps/pwa/out/_next/static/css/1f7c958c41ffa3b9.css +1 -0
  107. package/apps/pwa/out/approvals/index.html +1 -1
  108. package/apps/pwa/out/approvals/index.txt +23 -23
  109. package/apps/pwa/out/autopilot/index.html +1 -1
  110. package/apps/pwa/out/autopilot/index.txt +23 -23
  111. package/apps/pwa/out/board/index.html +1 -1
  112. package/apps/pwa/out/board/index.txt +23 -23
  113. package/apps/pwa/out/botlab/index.html +1 -1
  114. package/apps/pwa/out/botlab/index.txt +22 -22
  115. package/apps/pwa/out/bots/index.html +1 -1
  116. package/apps/pwa/out/bots/index.txt +22 -22
  117. package/apps/pwa/out/ceo/index.html +1 -0
  118. package/apps/pwa/out/ceo/index.txt +33 -0
  119. package/apps/pwa/out/chat/index.html +1 -1
  120. package/apps/pwa/out/chat/index.txt +22 -22
  121. package/apps/pwa/out/consult/index.html +1 -1
  122. package/apps/pwa/out/consult/index.txt +23 -23
  123. package/apps/pwa/out/control/index.html +1 -1
  124. package/apps/pwa/out/control/index.txt +23 -23
  125. package/apps/pwa/out/design-check/index.html +1 -1
  126. package/apps/pwa/out/design-check/index.txt +23 -23
  127. package/apps/pwa/out/editor/index.html +1 -1
  128. package/apps/pwa/out/editor/index.txt +23 -23
  129. package/apps/pwa/out/exec/index.html +1 -1
  130. package/apps/pwa/out/exec/index.txt +23 -23
  131. package/apps/pwa/out/field/index.html +1 -1
  132. package/apps/pwa/out/field/index.txt +23 -23
  133. package/apps/pwa/out/healthz +1 -1
  134. package/apps/pwa/out/index.html +1 -1
  135. package/apps/pwa/out/index.txt +22 -22
  136. package/apps/pwa/out/inside/index.html +1 -1
  137. package/apps/pwa/out/inside/index.txt +22 -22
  138. package/apps/pwa/out/intake/index.html +1 -1
  139. package/apps/pwa/out/intake/index.txt +23 -23
  140. package/apps/pwa/out/live/index.html +1 -1
  141. package/apps/pwa/out/live/index.txt +23 -23
  142. package/apps/pwa/out/loops/index.html +1 -0
  143. package/apps/pwa/out/loops/index.txt +30 -0
  144. package/apps/pwa/out/market/index.html +1 -1
  145. package/apps/pwa/out/market/index.txt +22 -22
  146. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  147. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  148. package/apps/pwa/out/morning/index.html +1 -1
  149. package/apps/pwa/out/morning/index.txt +23 -23
  150. package/apps/pwa/out/observatory/index.html +1 -1
  151. package/apps/pwa/out/observatory/index.txt +23 -23
  152. package/apps/pwa/out/ops/checklist/index.html +1 -1
  153. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  154. package/apps/pwa/out/ops/release/index.html +1 -1
  155. package/apps/pwa/out/ops/release/index.txt +22 -22
  156. package/apps/pwa/out/ops/seats/index.html +1 -1
  157. package/apps/pwa/out/ops/seats/index.txt +22 -22
  158. package/apps/pwa/out/outputs/index.html +1 -1
  159. package/apps/pwa/out/outputs/index.txt +22 -22
  160. package/apps/pwa/out/reflection/index.html +1 -1
  161. package/apps/pwa/out/reflection/index.txt +23 -23
  162. package/apps/pwa/out/scheduler/index.html +1 -1
  163. package/apps/pwa/out/scheduler/index.txt +23 -23
  164. package/apps/pwa/out/sessions/index.html +1 -1
  165. package/apps/pwa/out/sessions/index.txt +22 -22
  166. package/apps/pwa/out/settings/devices/index.html +1 -1
  167. package/apps/pwa/out/settings/devices/index.txt +23 -23
  168. package/apps/pwa/out/settings/index.html +1 -1
  169. package/apps/pwa/out/settings/index.txt +23 -23
  170. package/apps/pwa/out/setup/done/index.html +1 -1
  171. package/apps/pwa/out/setup/done/index.txt +23 -23
  172. package/apps/pwa/out/setup/index.html +1 -1
  173. package/apps/pwa/out/setup/index.txt +23 -23
  174. package/apps/pwa/out/share/index.html +1 -1
  175. package/apps/pwa/out/share/index.txt +23 -23
  176. package/apps/pwa/out/showroom/index.html +1 -1
  177. package/apps/pwa/out/showroom/index.txt +22 -22
  178. package/apps/pwa/out/tasks/index.html +1 -1
  179. package/apps/pwa/out/tasks/index.txt +23 -23
  180. package/apps/pwa/out/term/index.html +1 -1
  181. package/apps/pwa/out/term/index.txt +23 -23
  182. package/apps/pwa/out/today/index.html +1 -1
  183. package/apps/pwa/out/today/index.txt +23 -23
  184. package/apps/pwa/out/trace/index.html +1 -1
  185. package/apps/pwa/out/trace/index.txt +23 -23
  186. package/apps/pwa/out/vault/index.html +1 -1
  187. package/apps/pwa/out/vault/index.txt +23 -23
  188. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  189. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  190. package/apps/pwa/out/workflows/index.html +1 -1
  191. package/apps/pwa/out/workflows/index.txt +23 -23
  192. package/apps/pwa/out/workspace/index.html +1 -1
  193. package/apps/pwa/out/workspace/index.txt +23 -23
  194. package/apps/pwa/out/worktrees/index.html +1 -1
  195. package/apps/pwa/out/worktrees/index.txt +23 -23
  196. package/graphs/heal/heal-loop.yaml +1 -1
  197. package/graphs/implement-loop.yaml +1 -1
  198. package/graphs/orchestrator/orchestrator.yaml +59 -0
  199. package/graphs/orchestrator/recipes.yaml +18 -0
  200. package/graphs/release/recipes.yaml +6 -0
  201. package/graphs/release/release-loop.yaml +6 -1
  202. package/graphs/rhythm/daily.yaml +38 -0
  203. package/graphs/rhythm/recipes.yaml +18 -0
  204. package/graphs/rhythm/weekly.yaml +39 -0
  205. package/graphs/video/recipes.yaml +3 -0
  206. package/graphs/video/youtube-summary.yaml +17 -0
  207. package/package.json +1 -1
  208. package/scripts/audit-test-state-writes.ts +72 -17
  209. package/scripts/brand/check.ts +188 -0
  210. package/scripts/ci-typecheck-changed.ts +50 -18
  211. package/scripts/coord-post.sh +11 -1
  212. package/scripts/docs/generate-graph-anatomy.ts +315 -0
  213. package/scripts/docs-cli-check.ts +23 -6
  214. package/scripts/expose-rubric-check.ts +118 -0
  215. package/scripts/expose-rubric-suggest.ts +169 -0
  216. package/scripts/heal/run-role.ts +14 -0
  217. package/scripts/hq/standby-verify.ts +11 -7
  218. package/scripts/lecture-note/node.ts +31 -11
  219. package/scripts/lessons/handbook-page.ts +112 -0
  220. package/scripts/marketing/generate-ax-brief.ts +140 -0
  221. package/scripts/marketing/generate-feature-map.ts +118 -0
  222. package/scripts/release-loop/checklist-gate-node.ts +53 -14
  223. package/scripts/release-loop/gate-node.ts +89 -14
  224. package/scripts/release-loop/publish-node.ts +14 -1
  225. package/scripts/release-loop/unattended-release.ts +23 -1
  226. package/scripts/release-loop/vault-note-node.ts +428 -0
  227. package/scripts/release-story/draft.ts +220 -0
  228. package/scripts/rhythm/daily.ts +570 -0
  229. package/scripts/rhythm/weekly.ts +315 -0
  230. package/scripts/skills/public-check.ts +169 -0
  231. package/scripts/smart-merge/resync-shadow.ts +147 -0
  232. package/scripts/test-deterministic.ts +4 -8
  233. package/scripts/test-diet/effectiveness.ts +195 -0
  234. package/scripts/test-diet/lib.ts +16 -8
  235. package/scripts/test-diet/node.ts +77 -9
  236. package/scripts/ux/demo-rehearsal.ts +2 -2
  237. package/scripts/ux/lib/rehearsal-verdict.ts +1 -0
  238. package/scripts/video/youtube-summary.ts +133 -0
  239. package/skills/diagram-master/SKILL.md +42 -49
  240. package/skills/diagram-master/references/pyproject.toml +4 -1
  241. package/skills/diagram-master/references/routing-guide.md +4 -2
  242. package/skills/grill-me/SKILL.md +1 -0
  243. package/skills/youtube-master/SKILL.md +13 -13
  244. package/skills/youtube-master/package-lock.json +0 -545
  245. package/skills/youtube-master/package.json +2 -5
  246. package/skills/youtube-master/scripts/main.ts +2 -2
  247. package/skills/youtube-master/scripts/transcribe-local.ts +1 -1
  248. package/skills/youtube-master/src/util.ts +30 -7
  249. package/src/agent-env/profile.ts +161 -0
  250. package/src/agent-mission/driver.ts +3 -3
  251. package/src/agent-substrate/pr-reviewer.ts +2 -0
  252. package/src/ask-user-question/pending-questions.ts +5 -0
  253. package/src/auth/github-app-token.ts +112 -13
  254. package/src/autopilot/build/llm-conflict-merge.ts +73 -10
  255. package/src/autopilot/build/merge-intent.ts +53 -0
  256. package/src/briefing/brief-items.ts +121 -0
  257. package/src/chat/index.ts +2 -0
  258. package/src/claims/claims-ledger.ts +232 -0
  259. package/src/claims/claims-render.ts +166 -0
  260. package/src/cli/agent-env-cli.ts +21 -0
  261. package/src/cli/claims-cli.ts +94 -0
  262. package/src/cli/decisions-cli.ts +44 -3
  263. package/src/cli/docs-cli.ts +2 -0
  264. package/src/cli/doctor-cli.ts +23 -1
  265. package/src/cli/doctor-node-modules.ts +147 -0
  266. package/src/cli/flow-cli.ts +11 -0
  267. package/src/cli/freeze-cli.ts +45 -0
  268. package/src/cli/intake-cli.ts +46 -17
  269. package/src/cli/lesson-cli.ts +108 -0
  270. package/src/cli/logs-cli.ts +104 -2
  271. package/src/cli/logs-model-input.ts +131 -0
  272. package/src/cli/pod-cli.ts +2 -0
  273. package/src/cli/pr-cli.ts +29 -1
  274. package/src/cli/private-ledger-commands.ts +54 -4
  275. package/src/cli/pty-drive-verdict.ts +11 -2
  276. package/src/cli/release-cli.ts +190 -33
  277. package/src/cli/rfc-status.ts +91 -0
  278. package/src/cli/seat-requests-cli.ts +52 -0
  279. package/src/connectors/linear.ts +5 -3
  280. package/src/context-bus/condense.ts +15 -20
  281. package/src/context-bus/context-now-public.ts +96 -0
  282. package/src/context-bus/context-now-surfaces.ts +55 -2
  283. package/src/context-bus/context-now.ts +6 -3
  284. package/src/context-bus/coord-events.ts +6 -4
  285. package/src/context-bus/long-term-memory.ts +92 -11
  286. package/src/dashboard/index.ts +75 -22
  287. package/src/dashboard/slash-runtime/chat-persona.ts +66 -0
  288. package/src/dashboard/slash-runtime/dashboard-handlers.ts +99 -0
  289. package/src/dashboard/slash-runtime/loops-table.ts +77 -0
  290. package/src/decisions/decision-cards.ts +33 -7
  291. package/src/decisions/decision-ledger.ts +40 -1
  292. package/src/decisions/proact-meter.ts +286 -0
  293. package/src/decisions/proact1-lite.ts +86 -0
  294. package/src/decisions/web-push-decision-cards.ts +1 -1
  295. package/src/discord/sprint21-runtime.ts +16 -0
  296. package/src/discord-self-message.ts +8 -0
  297. package/src/discord-slash-wire.ts +31 -2
  298. package/src/domains/alert-audit.ts +271 -0
  299. package/src/domains/core-tools.ts +4 -3
  300. package/src/domains/ops-facts-tool.ts +31 -1
  301. package/src/domains/outbound-alert.ts +1 -1
  302. package/src/elanous-config-dir.ts +29 -4
  303. package/src/execution-loop/launch-gate.ts +29 -14
  304. package/src/flow/cards.ts +239 -0
  305. package/src/graph-runner/graph-tick.ts +4 -0
  306. package/src/graph-runner/runner.ts +30 -5
  307. package/src/harness/harness-cli-command.ts +259 -38
  308. package/src/harness/harness-incidents.ts +45 -12
  309. package/src/harness/harness-pod-dispatch.ts +102 -11
  310. package/src/harness/harness-queue-child.ts +3 -3
  311. package/src/harness/harness-queue.ts +583 -65
  312. package/src/harness/helper-repair.ts +87 -0
  313. package/src/harness/helper-scan.ts +151 -0
  314. package/src/harness/launch-stamp.ts +236 -0
  315. package/src/harness/ledger-write-guard-child.fixture.ts +12 -0
  316. package/src/harness/ledger-write-guard.ts +35 -0
  317. package/src/harness/model-input-observation.ts +37 -0
  318. package/src/harness/pod-memory-policy.ts +15 -0
  319. package/src/harness/repository-name.ts +55 -0
  320. package/src/hq/fence-audit.ts +90 -0
  321. package/src/hq/hq.ts +63 -5
  322. package/src/hq/lease.ts +4 -4
  323. package/src/hq/move-plan.ts +126 -0
  324. package/src/hq/promote.ts +332 -0
  325. package/src/index.ts +159 -27
  326. package/src/intake-plane/check.ts +63 -0
  327. package/src/intake-plane/digest.ts +37 -15
  328. package/src/intake-plane/front-classifier.ts +6 -0
  329. package/src/intake-plane/items.ts +3 -2
  330. package/src/intake-plane/lens.ts +177 -0
  331. package/src/intake-plane/linear-wish.ts +39 -11
  332. package/src/intake-plane/route.ts +145 -1
  333. package/src/intake-plane/wish-benchmark-ledger.ts +129 -0
  334. package/src/intake-plane/wish-card.ts +53 -2
  335. package/src/intake-plane/wish-folder.ts +5 -2
  336. package/src/intake-plane/wish-reply.ts +72 -0
  337. package/src/launch-head/seat-goal-queue-lock.fixture.ts +15 -0
  338. package/src/launch-head/seat-goal-queue.ts +198 -0
  339. package/src/lessons/lesson-import.ts +106 -0
  340. package/src/lessons/lesson-ledger.ts +206 -0
  341. package/src/loops/activity.ts +203 -0
  342. package/src/loops/budget.ts +63 -0
  343. package/src/loops/checker.ts +5 -3
  344. package/src/loops/contract/examples/orchestrator.loop.yaml +1 -1
  345. package/src/loops/loop-cli.ts +36 -4
  346. package/src/loops/neighbors.ts +40 -0
  347. package/src/loops/observe.ts +10 -0
  348. package/src/loops/orchestrator/author-depth.ts +220 -0
  349. package/src/loops/orchestrator/author-input-check.ts +82 -0
  350. package/src/loops/orchestrator/author-ledger.ts +232 -0
  351. package/src/loops/orchestrator/finish-rate.ts +175 -0
  352. package/src/loops/orchestrator/overlap.ts +51 -12
  353. package/src/loops/orchestrator/resync-shadow.ts +227 -0
  354. package/src/loops/orchestrator/seat-share.ts +56 -0
  355. package/src/loops/orchestrator/tick.ts +309 -0
  356. package/src/loops/orchestrator/traffic.ts +134 -13
  357. package/src/loops/registry.ts +535 -9
  358. package/src/loops/status-rows.ts +118 -0
  359. package/src/loops/verdict.ts +17 -5
  360. package/src/maturity/bot-slash-catalog.ts +66 -0
  361. package/src/maturity/feature-maturity.ts +9 -5
  362. package/src/maturity/tui-slash-availability.ts +31 -0
  363. package/src/mss/logging/log-store.ts +35 -4
  364. package/src/nexus/api/dashboard.ts +6 -1
  365. package/src/nexus/api/http-server.ts +33 -3
  366. package/src/nexus/api/loop-edges.ts +173 -0
  367. package/src/nexus/api/merge-approvals-gate.ts +1 -1
  368. package/src/nexus/api/schedules-read.ts +18 -1
  369. package/src/nexus/api/seat-requests.ts +79 -56
  370. package/src/nexus/api/task-cards-api.ts +44 -5
  371. package/src/nexus/api/workflows.ts +2 -1
  372. package/src/prompt-enhance/enhance.ts +6 -1
  373. package/src/release-loop/auto-start.ts +51 -0
  374. package/src/release-loop/checklist.ts +22 -4
  375. package/src/release-loop/feature-store.ts +71 -32
  376. package/src/release-loop/landing-freeze.ts +121 -0
  377. package/src/release-loop/merged-pr-checklist.ts +125 -0
  378. package/src/release-loop/placement.ts +302 -0
  379. package/src/release-loop/release-schedule.ts +3 -1
  380. package/src/seat-dispatch/ceo-commands.ts +2 -2
  381. package/src/seat-dispatch/seat-ask.ts +16 -3
  382. package/src/seat-dispatch/seat-questions.ts +58 -0
  383. package/src/seat-dispatch/seat-request-eligibility.ts +19 -0
  384. package/src/seat-dispatch/seat-request-ledger.ts +133 -0
  385. package/src/seat-loop/seat-loop.ts +531 -40
  386. package/src/self-dev/dev-pipeline.ts +14 -6
  387. package/src/self-dev/draft-sweep.ts +162 -6
  388. package/src/self-dev/draft-triage-rules.ts +25 -8
  389. package/src/self-dev/orchestrate.ts +15 -1
  390. package/src/self-dev/review-provider-fallback.ts +6 -1
  391. package/src/self-dev/run-store.ts +73 -1
  392. package/src/self-dev/run-supervisor.ts +57 -2
  393. package/src/self-dev/self-orchestrate-runtime.ts +5 -1
  394. package/src/self-implement/budget-gate.ts +29 -0
  395. package/src/self-implement/expose-gate.ts +47 -0
  396. package/src/self-implement/frozen-merges.ts +295 -0
  397. package/src/self-implement/gate-cli.ts +10 -4
  398. package/src/self-implement/gate-scope.ts +46 -9
  399. package/src/self-implement/goal-archive.ts +222 -0
  400. package/src/self-implement/goal-author.ts +43 -5
  401. package/src/self-implement/goal-clarification-escalation.ts +5 -0
  402. package/src/self-implement/goal-lookup.ts +147 -0
  403. package/src/self-implement/heal-intake.ts +197 -0
  404. package/src/self-implement/host-regate.ts +32 -2
  405. package/src/self-implement/l8-merge-queue.ts +132 -0
  406. package/src/self-implement/orchestrator.ts +299 -48
  407. package/src/self-implement/pipeline-shape.ts +1 -1
  408. package/src/self-implement/revert-guard.ts +97 -0
  409. package/src/self-implement/run-ledger.ts +3 -1
  410. package/src/self-implement/run-status-mapping.ts +2 -0
  411. package/src/self-implement/seams.ts +29 -9
  412. package/src/self-implement/self-implement-cli.ts +1 -0
  413. package/src/self-implement/speed-claims.ts +338 -0
  414. package/src/session/index.ts +2 -0
  415. package/src/steward/triage.ts +74 -3
  416. package/src/steward/working-backwards.ts +4 -1
  417. package/src/task-cards/card-cli.ts +10 -2
  418. package/src/task-cards/card-store.ts +10 -6
  419. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +63 -48
  420. package/src/task-orchestrator/surfaces/pod-command-job.ts +84 -9
  421. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +48 -0
  422. package/src/task-orchestrator/surfaces/pod-lease.ts +5 -2
  423. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +46 -6
  424. package/src/task-orchestrator/surfaces/pod-pool.ts +60 -8
  425. package/src/task-orchestrator/surfaces/self-implement-pod.ts +224 -49
  426. package/src/task-orchestrator/surfaces/self-implement.ts +5 -1
  427. package/src/telegram-commands.ts +27 -3
  428. package/src/telegram-loops-command.ts +44 -0
  429. package/src/telegram.ts +25 -4
  430. package/src/user-config.ts +146 -18
  431. package/src/version/packed-revision.json +1 -1
  432. package/src/workflow-runtime/nodes/bash.ts +9 -1
  433. package/src/workflow-runtime/storage.ts +31 -13
  434. package/apps/pwa/out/_next/static/D51l8jUBplJrIpWvENsDK/_buildManifest.js +0 -1
  435. package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +0 -1
  436. package/apps/pwa/out/_next/static/chunks/1394-931c9827067b2276.js +0 -1
  437. package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +0 -1
  438. package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +0 -1
  439. package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +0 -1
  440. package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +0 -1
  441. package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +0 -1
  442. package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +0 -1
  443. package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +0 -1
  444. package/apps/pwa/out/_next/static/chunks/3992-fe5c06d6b31f8b25.js +0 -25
  445. package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +0 -1
  446. package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +0 -1
  447. package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +0 -1
  448. package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +0 -2
  449. package/apps/pwa/out/_next/static/chunks/5250-c78ca295585bbf95.js +0 -1
  450. package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +0 -1
  451. package/apps/pwa/out/_next/static/chunks/5845-e6c003ce8d5fd36a.js +0 -1
  452. package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +0 -1
  453. package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +0 -1
  454. package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +0 -1
  455. package/apps/pwa/out/_next/static/chunks/6511-ff8360be3d65aaa4.js +0 -1
  456. package/apps/pwa/out/_next/static/chunks/6588-ba380869b67c4fa7.js +0 -1
  457. package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +0 -1
  458. package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +0 -1
  459. package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +0 -1
  460. package/apps/pwa/out/_next/static/chunks/7758-85c2b53f731da024.js +0 -1
  461. package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +0 -1
  463. package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/8605-9da4678f8a310d18.js +0 -1
  465. package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +0 -1
  466. package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +0 -1
  467. package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +0 -1
  468. package/apps/pwa/out/_next/static/chunks/9269.d2a4795bc6812717.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/9906-e7b8b5310a169dfe.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +0 -1
  472. package/apps/pwa/out/_next/static/chunks/app/approvals/page-e5b4e1b256f41076.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-e49b9b76c565a0b1.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/app/board/page-b4f032c893b21cc9.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/app/botlab/page-f14987d5850a31e0.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/app/bots/page-b433308aad13ceb6.js +0 -1
  477. package/apps/pwa/out/_next/static/chunks/app/chat/page-4c1dbb21861beab2.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/app/consult/page-c85b816e3b269dbb.js +0 -1
  479. package/apps/pwa/out/_next/static/chunks/app/control/page-f6bc66b919b2ea7d.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/app/design-check/page-60603c1e056c9b25.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/app/editor/page-a0ea8f5a2341ee6b.js +0 -1
  482. package/apps/pwa/out/_next/static/chunks/app/exec/page-45c5bf04b4a605e6.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/app/field/page-36c6c4183353ac9e.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/app/inside/page-cb2eb0fd809980da.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/app/intake/page-31012264da8a341f.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/app/layout-50309aeb0bdd554a.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/app/live/page-bc00e964e855f4df.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/app/market/page-0696ee3fac9fe56c.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66c27608f651b866.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/app/morning/page-6ddd2109b7fc3a80.js +0 -1
  492. package/apps/pwa/out/_next/static/chunks/app/not-found-4e50b7298c1f69a5.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/app/observatory/page-7a2bf830038a2264.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1f327f18694fabca.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-e5cef2fe6e4028df.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cf596128d2b420ba.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/app/outputs/page-f672536f14f0969f.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/app/page-b52365662232db89.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/app/reflection/page-e7a6c80f288b1948.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-29a709616df9b050.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/app/sessions/page-fee842d7c2151129.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-78b40a344ed22f24.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/app/settings/page-75d199f448171014.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-a011dd5b0bff29c5.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/app/setup/page-d92e32d51ab5157e.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/app/share/page-5f21aed6932ef375.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/app/showroom/page-1e1a53946804debf.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/app/tasks/page-a1833cd43d832601.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/app/today/page-2a511d320f762e06.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/app/trace/page-1c3e03f88dac1e21.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/app/vault/page-c4d5289c2ea97a89.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b91f8952deaeaf27.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/app/workflows/page-71b43a2588489987.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2b256feed331546f.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-505bb96d69a8622c.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +0 -1
  523. package/apps/pwa/out/_next/static/css/128fb7fb670b2fbf.css +0 -1
  524. /package/apps/pwa/out/_next/static/{D51l8jUBplJrIpWvENsDK → LZcstaO9_NXypPFmujolv}/_ssgManifest.js +0 -0
package/src/index.ts CHANGED
@@ -31,6 +31,7 @@ import { collectCommandEntrances, renderCommandEntrances } from './self-dev/entr
31
31
  import { isGoalAuthorFileName } from './self-implement/goal-document.js';
32
32
  import { DEV_PIPELINE_SINK_SURFACE } from './self-implement/self-cli-sink-surface.js';
33
33
  import { registerPrivateLedgerCommands } from './cli/private-ledger-commands.js';
34
+ import { registerSeatRequestsCommands } from './cli/seat-requests-cli.js';
34
35
  import { applyTestStateDirFlagFromArgv } from './cli/test-state-dir-flag.js';
35
36
  import { applyTestFlagFromArgv, observeTestFlagOwnership, uncoveredTestFlagPaths, staleTestFlagPaths } from './cli/test-flag.js';
36
37
  import { registerPtyTakeoverCommands } from './cli/pty-takeover-cli.js';
@@ -46,6 +47,7 @@ import { registerPublishCommands } from './cli/publish-cli.js';
46
47
  import { registerAutopilotCommands } from './cli/autopilot-cli.js';
47
48
  import { registerRoleCommands } from './cli/role-cli.js';
48
49
  import { registerMachineCommands } from './cli/machine-cli.js';
50
+ import { registerAgentEnvCommands } from './cli/agent-env-cli.js';
49
51
  import { registerScheduleCommands } from './cli/schedule-cli.js';
50
52
  export { runSchedule, scheduleCreatePlan } from './cli/schedule-cli.js';
51
53
  export type { ScheduleDispatch } from './cli/schedule-cli.js';
@@ -63,6 +65,8 @@ import { registerUsageCommand } from './cli/usage-cli.js';
63
65
  import { registerLiveCommands } from './cli/live-cli.js';
64
66
  import { registerResearchCommand } from './cli/research-cli.js';
65
67
  import { registerReleaseCommands } from './cli/release-cli.js';
68
+ import { registerFreezeCommands } from './cli/freeze-cli.js';
69
+ import { registerFlowCommands } from './cli/flow-cli.js';
66
70
  import { registerModelWatchCommand } from './cli/model-watch-cli.js';
67
71
  import { registerIntakeCommands } from './cli/intake-cli.js';
68
72
  import { registerTasksCommands } from './cli/tasks-cli.js';
@@ -78,6 +82,7 @@ import { registerStartCommand } from './cli/start-cli.js';
78
82
  import { registerGroundingSourcesCli } from './grounding/sources-cli.js';
79
83
  import { registerGraphCommands } from './graph-runner/graph-cli.js';
80
84
  import { registerLoopCommands } from './loops/loop-cli.js';
85
+ import { registerHqMovePlanCommand } from './hq/hq.js';
81
86
  import { registerCardCommand } from './task-cards/card-cli.js';
82
87
  import { registerLaunchHeadCommands } from './launch-head/launch-head-cli.js';
83
88
  import { acpServerHelpText } from './boot/acp-server-help.js';
@@ -854,6 +859,7 @@ registerPrCommands(program);
854
859
  registerRepoCommands(program);
855
860
  registerRoleCommands(program);
856
861
  registerMachineCommands(program);
862
+ registerAgentEnvCommands(program);
857
863
  // CLI entry: where action → resolveCurrentInstance → resolveInstance (instance universe).
858
864
  registerWhereCommand(program);
859
865
  registerShadowCommand(program);
@@ -869,6 +875,8 @@ registerUsageCommand(program);
869
875
  registerLiveCommands(program);
870
876
  registerResearchCommand(program);
871
877
  registerReleaseCommands(program);
878
+ registerFreezeCommands(program);
879
+ registerFlowCommands(program);
872
880
  // HQ-HB · HQ-FENCE (10-04): one writer across mbp · node-b · cloud-vm — lease on the arbiter, 2-of-3 quorum, generation fencing.
873
881
  const hqCmd = program.command('hq').description('본부 임대 — 하트비트·중재·단일 작성자 래퍼');
874
882
  async function hqSink(): Promise<void> {
@@ -897,6 +905,19 @@ hqCmd.command('lease').argument('<action>', 'acquire|renew|status|release')
897
905
  if (!result.ok) process.exitCode = 2;
898
906
  } catch (error) { if (error instanceof CliUserError) throw error; console.error(`hq lease: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
899
907
  });
908
+ hqCmd.command('promote').description('HQ 승격 런북 (기본 dry-run · --apply 일 때만 변경)')
909
+ .requiredOption('--to <host>', '승격 대상 호스트')
910
+ .option('--apply', '대기 사본을 승격 우주에 반영하고 넥서스·rescue 실행')
911
+ .option('--json', 'JSON 출력')
912
+ .action(async (opts: { to: string; apply?: boolean; json?: boolean }) => {
913
+ try {
914
+ const { promoteHq, formatPromote } = await import('./hq/promote.js');
915
+ const result = promoteHq(opts.to, opts.apply === true);
916
+ if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
917
+ else console.log(formatPromote(result));
918
+ if (!result.ok) process.exitCode = 1;
919
+ } catch (error) { console.error(`hq promote: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
920
+ });
900
921
  hqCmd.command('heartbeat').description('보유자는 갱신 · 아니면 대기(보유자에 닿는지 중재자에 보고)').option('--json', 'JSON 출력')
901
922
  .action(async (opts: { json?: boolean }) => {
902
923
  try {
@@ -920,6 +941,18 @@ hqCmd.command('seen').description('이 호스트가 본 가장 높은 임대 세
920
941
  else console.log(result.seen ? `hq seen: generation ${result.generation}` : 'hq seen: never');
921
942
  process.exitCode = result.seen ? 0 : 3;
922
943
  });
944
+ registerHqMovePlanCommand(hqCmd);
945
+ hqCmd.command('fence-audit').description('운영 crontab 의 HQ 울타리 밖 쓰기 잡 목록과 감싼 줄 제안(읽기 전용)')
946
+ .option('--json', 'JSON 출력')
947
+ .action(async (opts: { json?: boolean }) => {
948
+ try {
949
+ await hqSink();
950
+ const rows = (await import('./hq/fence-audit.js')).hqFenceAudit();
951
+ if (opts.json) await writeStdoutJson(`${JSON.stringify(rows)}\n`);
952
+ else if (!rows.length) console.log('hq fence-audit: unfenced 0');
953
+ else for (const row of rows) console.log(`${row.raw}\n role: ${row.recommendedRole}\n suggested: ${row.suggestedLine}`);
954
+ } catch (error) { console.error(`hq fence-audit: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
955
+ });
923
956
  hqCmd.command('fence').description('이 호스트가 임대를 쥐었을 때만 명령 실행(아니면 건너뜀 · exit 0)')
924
957
  .requiredOption('--role <role>', 'telegram-poller|cron|seat-loop|release-run|conatus|git-push')
925
958
  .argument('<command...>', '-- 뒤의 명령')
@@ -930,6 +963,7 @@ hqCmd.command('fence').description('이 호스트가 임대를 쥐었을 때만
930
963
  process.exitCode = hqFenceRun(opts.role as 'cron', command);
931
964
  });
932
965
  const seatCmd = program.command('seat').description('분배된 자리의 하루 루프와 보고');
966
+ registerSeatRequestsCommands(seatCmd);
933
967
  seatCmd.command('answer <askId> <answer>').description('자리 질문에 답을 남기고 원래 표면으로 회신 예약')
934
968
  .action(async (askId: string, answer: string) => {
935
969
  try {
@@ -945,10 +979,10 @@ seatCmd.command('loop').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
945
979
  try {
946
980
  // V3 F5: without the sink, the seat loop's judgment lines (seat.loop) never reach the log store when cron runs it.
947
981
  await (await import('./domains/standalone-log-sink.js')).registerStandaloneLogSink('seat-loop');
948
- const { runSeatLoopTurn } = await import('./seat-loop/seat-loop.js');
982
+ const { runSeatLoopTurn, seatLoopTickLine } = await import('./seat-loop/seat-loop.js');
949
983
  const result = await runSeatLoopTurn(opts.seat);
950
984
  if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
951
- else console.log(`seat loop ${opts.seat}: ${result.status}${'runId' in result && result.runId ? ` ${result.runId}` : ''}`);
985
+ else console.log(seatLoopTickLine(result));
952
986
  } catch (error) { console.error(`seat loop: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
953
987
  });
954
988
  seatCmd.command('report').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
@@ -3034,6 +3068,8 @@ export async function runHarnessOrchestrateExecution(
3034
3068
  prior,
3035
3069
  goals,
3036
3070
  pid,
3071
+ ...(['OP', 'TC', 'MK', 'UX'].includes(process.env.ELANOUS_HARNESS_SEAT ?? '')
3072
+ ? { seat: process.env.ELANOUS_HARNESS_SEAT as SelfDevRunState['seat'] } : {}),
3037
3073
  runIdSource,
3038
3074
  now,
3039
3075
  onPersistenceFailure: reportPersistenceFailure,
@@ -3151,7 +3187,7 @@ contextCmd.command('condense')
3151
3187
  if (!/^[1-9]\d*h$/.test(opts.since)) throw new Error('--since requires positive hours, e.g. 24h');
3152
3188
  const { runContextCondense } = await import('./context-bus/condense.js');
3153
3189
  const report = await runContextCondense({ hours: Number(opts.since.slice(0, -1)), apply: opts.apply === true });
3154
- await writeStdoutJson(JSON.stringify({ since: report.since, until: report.until, cards: report.cards, conflicts: report.conflicts, skipped: report.skipped, folded: report.folded, ...(report.applied ? { applied: report.applied } : {}) }) + '\n');
3190
+ await writeStdoutJson(JSON.stringify({ since: report.since, until: report.until, cards: report.cards, conflicts: report.conflicts, skipped: report.skipped, folded: report.folded, droppedHarnessChild: report.droppedHarnessChild, funnel: report.funnel, ...(report.applied ? { applied: report.applied } : {}) }) + '\n');
3155
3191
  if (!opts.json) await writeStdoutFully(report.markdown);
3156
3192
  } catch (error) {
3157
3193
  console.error(`context condense: ${error instanceof Error ? error.message : String(error)}`);
@@ -3438,6 +3474,22 @@ selfCmd
3438
3474
  }
3439
3475
  });
3440
3476
 
3477
+ selfCmd
3478
+ .command('speed-claims')
3479
+ .description('런 원장 발사→종결 시간의 자리별·결과별 분포를 읽기 전용으로 출력한다')
3480
+ .option('--json', '구조화된 JSON으로 출력한다')
3481
+ .action(async (opts: { json?: boolean }) => {
3482
+ try {
3483
+ const { measureSpeedClaims, renderSpeedClaims } = await import('./self-implement/speed-claims.js');
3484
+ const result = measureSpeedClaims();
3485
+ if (opts.json) await writeStdoutJson(JSON.stringify(result) + '\n');
3486
+ else console.log(renderSpeedClaims(result));
3487
+ } catch (error) {
3488
+ console.error(`speed-claims measurement failed: ${error instanceof Error ? error.message : String(error)}`);
3489
+ process.exitCode = 1;
3490
+ }
3491
+ });
3492
+
3441
3493
  selfCmd
3442
3494
  .command('goal-source-distribution')
3443
3495
  .description('self-implement 런 원장의 start goalSource 분포를 읽기 전용으로 출력한다')
@@ -4300,6 +4352,35 @@ selfCmd
4300
4352
  } catch (e) { console.error(`⛔ ${(e as Error).message}`); process.exitCode = 1; }
4301
4353
  });
4302
4354
 
4355
+ export async function announceLaunchQuotaPolicy(input: {
4356
+ runId: string;
4357
+ current: import('./oauth/codex-quota-policy.js').ResolvedCodexQuotaPolicy;
4358
+ universe: { kind: 'prod' | 'test'; root: string };
4359
+ production?: import('./oauth/codex-quota-policy.js').ResolvedCodexQuotaPolicy;
4360
+ }): Promise<{ line: string; warning?: string; quotaPolicy: {
4361
+ policy: import('./oauth/codex-quota-policy.js').CodexQuotaPolicy;
4362
+ source: import('./oauth/codex-quota-policy.js').ResolvedCodexQuotaPolicy['source'];
4363
+ universeKind: 'prod' | 'test';
4364
+ } }> {
4365
+ const { describeLaunchQuotaPolicy } = await import('./oauth/codex-quota-policy.js');
4366
+ const { appendRunLedgerEntry } = await import('./self-implement/run-ledger.js');
4367
+ const described = describeLaunchQuotaPolicy(input);
4368
+ const data = { policy: input.current.policy, source: input.current.source, universe: input.universe,
4369
+ ...(described.warning ? { warning: described.warning } : {}) };
4370
+ try {
4371
+ appendRunLedgerEntry({ runId: input.runId, timestamp: new Date().toISOString(), event: 'launch-quota-policy', data });
4372
+ } catch (error) {
4373
+ debug.log('pod.quota-policy', 'ledger-unavailable', { runId: input.runId, error: String(error) }, { level: 'warn' });
4374
+ throw new Error(`pod launch quota policy ledger write failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
4375
+ }
4376
+ debug.log('pod.quota-policy', 'announced', data);
4377
+ return { ...described, quotaPolicy: { policy: input.current.policy, source: input.current.source, universeKind: input.universe.kind } };
4378
+ }
4379
+
4380
+ export function withLaunchQuotaPolicy<T extends object>(results: readonly T[], quotaPolicy: Awaited<ReturnType<typeof announceLaunchQuotaPolicy>>['quotaPolicy'] | undefined): (T & { quotaPolicy?: Awaited<ReturnType<typeof announceLaunchQuotaPolicy>>['quotaPolicy'] })[] {
4381
+ return quotaPolicy ? results.map((result) => ({ ...result, quotaPolicy })) : [...results];
4382
+ }
4383
+
4303
4384
  // self orchestrate — 병렬 self-dev(S1·2026-07-21) — N개 독립 goal 을 각자 `elanous self implement` 서브프로세스로
4304
4385
  // TOX 디스패처 위에서 동시성캡 병렬 실행. 각 잡=자기 프로세스=자기 harness-space(병렬안전). 엔진(그래프/
4305
4386
  // 디스패처)은 기존 재사용·새 조각=self-implement surface 어댑터. [[PLAN-parallel-self-dev-orchestrator-2026-07-21]].
@@ -4331,6 +4412,9 @@ const selfOrchestrateCmd = selfCmd
4331
4412
  .option('--no-pod-rebuild', 'pod: 이미지 판(elanous.commit)이 HEAD 와 달라도 다시 굽지 않는다 — 측정은 «이미지 판»을 잰다')
4332
4413
  .option('--pod-pass-env <keys>', 'pod: 호스트 env 에서 Pod 로 넘길 키(쉼표) — 예 OPENROUTER_API_KEY,ANTHROPIC_API_KEY(벤치마크 과금 경로)')
4333
4414
  .option('--bench-arms <spec>', 'pod 벤치마크: 골 1개를 팔마다 «라벨 한 줄만 다르게» 복제해 동시에 — "id=provider[:model][@KEY+KEY];…" (예 codex=openai-codex;or-kimi=openrouter:openrouter/moonshotai/kimi-k3@OPENROUTER_API_KEY) · --auto-merge 거부 · RFC fleet 슈퍼바이저 §A3')
4415
+ .addOption(new Option('--child-llm-provider <id>', 'pod: 구현 자식 LLM provider(openai-codex|grok) — 하니스 --child-llm-provider 가 이 자리로 온다(10-05)').hideHelp())
4416
+ .addOption(new Option('--child-llm-model <id>', 'pod: 구현 자식 LLM model(--child-llm-provider 와 함께)').hideHelp())
4417
+ .addOption(new Option('--child-llm-effort <level>', 'pod: 구현 자식 추론 노력(--child-llm-provider 와 함께)').hideHelp())
4334
4418
  .option('--help-all', '모든 orchestrate 옵션 표시')
4335
4419
  .action(function (this: Command, parts: string[], opts: { goalFile?: string[]; concurrency?: string; autoMerge?: boolean; autoReview?: boolean; openPr?: boolean; base?: string; teardown?: boolean; resume?: string; board?: boolean; decompose?: boolean; fabricDecompose?: boolean; maxTasks?: string; supervise?: boolean; superviseRounds?: string; json?: boolean }) {
4336
4420
  return (async () => {
@@ -4458,6 +4542,8 @@ const selfOrchestrateCmd = selfCmd
4458
4542
  prior,
4459
4543
  goals,
4460
4544
  pid: process.pid,
4545
+ ...(['OP', 'TC', 'MK', 'UX'].includes(process.env.ELANOUS_HARNESS_SEAT ?? '')
4546
+ ? { seat: process.env.ELANOUS_HARNESS_SEAT as SelfDevRunState['seat'] } : {}),
4461
4547
  runIdSource,
4462
4548
  now: () => Date.now(),
4463
4549
  });
@@ -4492,6 +4578,7 @@ const selfOrchestrateCmd = selfCmd
4492
4578
  // coordinator 해석(decompose·run-identity·checkpoint·board)은 액션에 유지·감독 콜백은 runtime 으로 주입.
4493
4579
  // ☸️ 실행 칸 — pod 면 self-implement 자식을 k8s Job 으로(계약 동일 · 슈퍼바이저 무수정).
4494
4580
  const substrate = (opts as { substrate?: string }).substrate ?? 'local';
4581
+ let launchQuotaPolicy: Awaited<ReturnType<typeof announceLaunchQuotaPolicy>>['quotaPolicy'] | undefined;
4495
4582
  let podSpawn: import('./task-orchestrator/surfaces/self-implement.js').SelfImplementJobSpawn | undefined;
4496
4583
  let podTargets: { context: string; namespace: string }[] | undefined;
4497
4584
  if (substrate === 'pod') {
@@ -4562,6 +4649,19 @@ const selfOrchestrateCmd = selfCmd
4562
4649
  let rotationAccounts: readonly string[] | undefined;
4563
4650
  let podProvider: 'openai-codex' | 'grok' = 'openai-codex';
4564
4651
  let grokApiKeyOptIn = false;
4652
+ {
4653
+ // 10-05 PODPROVIDER: refuse child choices this Pod launch cannot honour instead of dropping them.
4654
+ const child = opts as { childLlmProvider?: string; childLlmModel?: string; childLlmEffort?: string };
4655
+ const named = child.childLlmProvider?.trim();
4656
+ const refuse = !named && (child.childLlmModel?.trim() || child.childLlmEffort?.trim())
4657
+ ? 'pod: --child-llm-model/--child-llm-effort 는 --child-llm-provider 와 함께'
4658
+ : named && benchArms
4659
+ ? 'pod: --child-llm-provider 는 --bench-arms 와 함께 못 쓴다(팔마다 모델이 하나다)'
4660
+ : named === 'grok' && explicitPodAccount
4661
+ ? 'pod: --child-llm-provider grok 은 --pod-account 와 함께 못 쓴다(그것은 codex 계정을 고정한다)'
4662
+ : undefined;
4663
+ if (refuse) { ui.error(refuse); debug.log('self-implement.pod', 'child-provider-refused', { provider: named ?? null, reason: refuse }); process.exit(2); }
4664
+ }
4565
4665
  if (!explicitPodAccount && !benchArms) {
4566
4666
  const { inspectCodexRotation } = await import('./oauth/codex-account-store.js');
4567
4667
  const { planPodProvider, makePodAccountBroker } = await import('./task-orchestrator/surfaces/pod-account-broker.js');
@@ -4574,34 +4674,57 @@ const selfOrchestrateCmd = selfCmd
4574
4674
  const resolvedQuota = resolveCodexQuotaPolicy(getUserConfig().llm);
4575
4675
  const quotaPolicy = resolvedQuota.policy;
4576
4676
  // POL1 — say which policy this launch uses and where it came from; warn when a test universe disagrees with production.
4577
- try {
4578
- const { effectiveInstanceRoot, prodInstanceRoot } = await import('./instance/resolve.js');
4579
- const { describeLaunchQuotaPolicy } = await import('./oauth/codex-quota-policy.js');
4580
- const root = effectiveInstanceRoot();
4581
- const kind = root === prodInstanceRoot() ? 'prod' as const : 'test' as const;
4582
- let production: ReturnType<typeof resolveCodexQuotaPolicy> | undefined;
4583
- if (kind === 'test') {
4584
- try {
4585
- const { readFileSync } = await import('node:fs');
4586
- const prodLlm = (JSON.parse(readFileSync(`${prodInstanceRoot()}/config.json`, 'utf8')) as { llm?: Record<string, unknown> }).llm;
4587
- production = resolveCodexQuotaPolicy(prodLlm);
4588
- } catch { /* no production config on this machine */ }
4677
+ const { effectiveInstanceRoot, prodInstanceRoot } = await import('./instance/resolve.js');
4678
+ const root = effectiveInstanceRoot();
4679
+ const kind = root === prodInstanceRoot() ? 'prod' as const : 'test' as const;
4680
+ let production: ReturnType<typeof resolveCodexQuotaPolicy> | undefined;
4681
+ if (kind === 'test') {
4682
+ try {
4683
+ const { readFileSync } = await import('node:fs');
4684
+ const prodLlm = (JSON.parse(readFileSync(`${prodInstanceRoot()}/config.json`, 'utf8')) as { llm?: Record<string, unknown> }).llm;
4685
+ production = resolveCodexQuotaPolicy(prodLlm);
4686
+ } catch { /* no production config on this machine */ }
4687
+ }
4688
+ const described = await announceLaunchQuotaPolicy({ runId, current: resolvedQuota, universe: { kind, root }, ...(production ? { production } : {}) });
4689
+ launchQuotaPolicy = described.quotaPolicy;
4690
+ debug.log('self-implement.pod', 'quota-policy', { policy: resolvedQuota.policy, source: resolvedQuota.source, universe: kind, productionPolicy: production?.policy ?? null });
4691
+ if (!opts.json) { ui.info(described.line); if (described.warning) ui.warn(described.warning); }
4692
+ // GROK-OPTIONAL (10-05): an expiring grok subscription the host cannot refresh is dropped from the chain here,
4693
+ // so the launch goes on with codex instead of dying later in hostGrokCredentials.
4694
+ let grokSubscriptionUsable = credential?.kind === 'subscription';
4695
+ if (grokSubscriptionUsable && codexPolicyAllowsFallback(quotaPolicy)) {
4696
+ const { podGrokSubscriptionUsable, podGrokSkippedLine } = await import('./task-orchestrator/surfaces/self-implement-pod.js');
4697
+ const grokCheck = podGrokSubscriptionUsable();
4698
+ if (!grokCheck.usable) {
4699
+ grokSubscriptionUsable = false;
4700
+ if (!opts.json) ui.warn(podGrokSkippedLine(grokCheck));
4589
4701
  }
4590
- const described = describeLaunchQuotaPolicy({ current: resolvedQuota, universe: { kind, root }, ...(production ? { production } : {}) });
4591
- debug.log('self-implement.pod', 'quota-policy', { policy: resolvedQuota.policy, source: resolvedQuota.source, universe: kind, productionPolicy: production?.policy ?? null });
4592
- if (!opts.json) { ui.info(described.line); if (described.warning) ui.warn(described.warning); }
4593
- } catch { /* the line is advice; the launch goes on */ }
4594
- const plan = planPodProvider({
4702
+ }
4703
+ // 10-05 PODPROVIDER: a launch that named the child provider gets it, or is refused — never a silent codex.
4704
+ const namedChild = (opts as { childLlmProvider?: string }).childLlmProvider?.trim();
4705
+ const { podNamedChildProvider, podFallbackCredentials, podGrokSubscriptionUsable: namedGrokUsable } = await import('./task-orchestrator/surfaces/self-implement-pod.js');
4706
+ const namedChildDecision = podNamedChildProvider(namedChild, {
4707
+ grokSubscription: namedChild === 'grok' && credential?.kind === 'subscription' && (grokSubscriptionUsable || namedGrokUsable().usable),
4708
+ grokApiKey: credential?.kind === 'api_key' && grokApiKeyOptIn,
4709
+ });
4710
+ if (namedChildDecision.refuse) { ui.error(namedChildDecision.refuse); debug.log('self-implement.pod', 'child-provider-refused', { provider: namedChild, reason: namedChildDecision.refuse }); process.exit(2); }
4711
+ // A named codex child must stay codex — the plan may not fall back to grok (post-review must-fix).
4712
+ const namedCodex = namedChildDecision.provider === 'openai-codex';
4713
+ const plan: import('./task-orchestrator/surfaces/pod-account-broker.js').PodProviderPlan = namedChildDecision.provider === 'grok'
4714
+ ? { provider: 'grok', excluded: [], grokSubscriptionEligible: credential?.kind === 'subscription' }
4715
+ : planPodProvider({
4595
4716
  codexCandidates: inspectCodexRotation().candidates,
4596
4717
  // Per-account caps (대표 default:97) override the Pod default cap — without them default was dropped at 60%.
4597
4718
  thresholdPercentByAccount: getUserConfig().llm?.codexAccountRotationThresholdPercentByAccount,
4598
4719
  // 대표 한도 정책 한 값(`llm.codexQuotaPolicy`) — 크레딧·폴백을 같이 정한다.
4599
4720
  creditsAllowed: codexPolicyAllowsCredits(quotaPolicy),
4600
- grokSubscription: codexPolicyAllowsFallback(quotaPolicy) && credential?.kind === 'subscription',
4601
- grokApiKey: codexPolicyAllowsFallback(quotaPolicy) && credential?.kind === 'api_key',
4721
+ ...podFallbackCredentials(namedChildDecision.provider, {
4722
+ grokSubscription: codexPolicyAllowsFallback(quotaPolicy) && grokSubscriptionUsable,
4723
+ grokApiKey: codexPolicyAllowsFallback(quotaPolicy) && credential?.kind === 'api_key',
4724
+ }),
4602
4725
  grokApiKeyOptIn,
4603
4726
  });
4604
- if (plan.provider === null) { ui.error(`pod: 쓸 codex 계정이 없다 — ${plan.reasons.join(' · ')} · 계정을 명시하려면 --pod-account <이름>`); process.exit(2); }
4727
+ if (plan.provider === null) { ui.error(`pod: 쓸 codex 계정이 없다 — ${plan.reasons.join(' · ')}${namedCodex ? ' · child provider 를 openai-codex 로 지정해 grok 으로 넘기지 않는다' : ''} · 계정을 명시하려면 --pod-account <이름>`); process.exit(2); }
4605
4728
  podProvider = plan.provider;
4606
4729
  if (plan.provider === 'openai-codex') {
4607
4730
  accountBroker = makePodAccountBroker({ usable: plan.accounts, excluded: plan.excluded });
@@ -4610,6 +4733,10 @@ const selfOrchestrateCmd = selfCmd
4610
4733
  { const { emitDecision } = await import('./live/detail-switch.js');
4611
4734
  emitDecision({ kind: 'ROUTE', what: `Pod 계정 배분 ${plan.accounts.join(' → ')}`, reason: plan.excluded.length ? `뺌 ${plan.excluded.map((x) => `${x.name}(${x.why})`).join(', ')}` : '모든 계정 여유', purpose: plan.creditAccounts ? '구독 잔량 0 — 정책상 크레딧으로 병렬 조각을 돌린다' : '병렬 조각이 한 계정에 몰리지 않게 잔량 순으로 돌려 준다', phase: 'dispatch', target: `Pod ${plan.accounts.length}계정`, paths: plan.accounts.length + plan.excluded.length }); }
4612
4735
  if (!opts.json) ui.info(`[pod] 계정 배분(잔량 순 · 돌려 가며): ${plan.accounts.join(' → ')}${plan.creditAccounts ? ' · 💳 크레딧(구독 잔량 0 · 허가됨)' : ''}${plan.excluded.length ? ` · 뺌 ${plan.excluded.map((x) => `${x.name}(${x.why})`).join(', ')}` : ''}`);
4736
+ } else if (namedChildDecision.provider === 'grok') {
4737
+ const model = (opts as { childLlmModel?: string }).childLlmModel?.trim() || defaultGrokModel().id;
4738
+ debug.log('self-implement.pod', 'provider-named', { provider: 'grok', model, credential: credential?.kind ?? null });
4739
+ if (!opts.json) ui.info(`[pod] child provider = grok(모델 ${model}) — 발사 인자로 지정됨`);
4613
4740
  } else {
4614
4741
  const model = defaultGrokModel().id;
4615
4742
  debug.log('self-implement.pod', 'provider-fallback', { from: 'openai-codex', to: 'grok', excluded: plan.excluded, model });
@@ -4637,7 +4764,10 @@ const selfOrchestrateCmd = selfCmd
4637
4764
  ...(podSource.kind === 'bundle' ? { headCommit: podSource.headCommit, sizeBytes: podSource.sizeBytes } : {}),
4638
4765
  });
4639
4766
  }
4640
- const podBase = { hostSupervised: opts.supervise === true, ...(remoteOnlyPool ? { imageCommit: image.imageCommit } : {}), account: podProvider === 'grok' ? 'grok' : explicitPodAccount ?? 'team', ...(accountBroker ? { accountBroker, rotationAccounts } : {}), ...(podProvider === 'grok' ? { provider: 'grok' as const, grokApiKeyOptIn } : {}), passEnv, ...(pool ? { pool } : {}), ...((opts as { podSkillEnv?: boolean }).podSkillEnv ? { skillEnv: true } : {}), ...(podSource ? { source: podSource } : {}) };
4767
+ const childFlags = opts as { childLlmProvider?: string; childLlmModel?: string; childLlmEffort?: string };
4768
+ const podChildLlm = childFlags.childLlmProvider?.trim() ? { childProviderExplicit: true, ...(childFlags.childLlmModel?.trim() ? { childModel: childFlags.childLlmModel.trim() } : {}), ...(childFlags.childLlmEffort?.trim() ? { childEffort: childFlags.childLlmEffort.trim() } : {}) } : {};
4769
+ if (childFlags.childLlmProvider?.trim()) debug.log('self-implement.pod', 'child-provider-named', { provider: childFlags.childLlmProvider.trim(), model: childFlags.childLlmModel ?? null, podProvider });
4770
+ const podBase = { hostSupervised: opts.supervise === true, ...podChildLlm, ...(remoteOnlyPool ? { imageCommit: image.imageCommit } : {}), account: podProvider === 'grok' ? 'grok' : explicitPodAccount ?? 'team', ...(accountBroker ? { accountBroker, rotationAccounts } : {}), ...(podProvider === 'grok' ? { provider: 'grok' as const, grokApiKeyOptIn } : {}), passEnv, ...(pool ? { pool } : {}), ...((opts as { podSkillEnv?: boolean }).podSkillEnv ? { skillEnv: true } : {}), ...(podSource ? { source: podSource } : {}) };
4641
4771
  if (benchArms) {
4642
4772
  const { benchPodSpawn } = await import('./task-orchestrator/surfaces/self-implement-pod.js');
4643
4773
  podSpawn = benchPodSpawn(benchArms, podBase);
@@ -4714,7 +4844,7 @@ const selfOrchestrateCmd = selfCmd
4714
4844
  debug.log('self-dev.reduce', 'orchestrate-reduce', { runId, shards: shards.length, kind: r.kind });
4715
4845
  }
4716
4846
  }
4717
- if (opts.json) { await writeStdoutJson(JSON.stringify(results) + '\n'); await reportRun(results); return; }
4847
+ if (opts.json) { await writeStdoutJson(JSON.stringify(withLaunchQuotaPolicy(results, launchQuotaPolicy)) + '\n'); await reportRun(results); return; }
4718
4848
  const done = results.filter((r) => r.status === 'done').length;
4719
4849
  const promoted = results.filter((r) => r.prUrl).length;
4720
4850
  const incomplete = results.length - done;
@@ -6811,7 +6941,8 @@ const selfDevCmd = program
6811
6941
  const { dispatchHarnessOnPod } = await import('./harness/harness-pod-dispatch.js');
6812
6942
  const { devAskPodDispatchInput } = await import('./harness/harness-substrate-default.js');
6813
6943
  const { classifyHarnessPodExit, harnessPodRunId, recordClassifiedHarnessPodExit, warnRecentIncidentBurst } = await import('./harness/harness-cli-command.js');
6814
- warnRecentIncidentBurst();
6944
+ warnRecentIncidentBurst(undefined, undefined, undefined,
6945
+ { entrance: 'cli-dev-ask', seat: opts.seat });
6815
6946
  let podOutput = '';
6816
6947
  let podRunId: string | undefined;
6817
6948
  const previousLeaseId = process.env.ELANOUS_POD_RESERVED_LEASE;
@@ -6831,7 +6962,8 @@ const selfDevCmd = program
6831
6962
  }
6832
6963
  if (status !== 0) {
6833
6964
  const classified = classifyHarnessPodExit({ status }, podOutput, { ...(podRunId ? { runId: podRunId } : {}) });
6834
- recordClassifiedHarnessPodExit(podRunId ?? harnessPodRunId(podOutput), classified.reason, status);
6965
+ recordClassifiedHarnessPodExit(podRunId ?? harnessPodRunId(podOutput), classified.reason, status,
6966
+ { entrance: 'cli-dev-ask', seat: opts.seat, output: podOutput });
6835
6967
  for (const line of classified.lines) console.error(line);
6836
6968
  }
6837
6969
  completionGuard.conclude();
@@ -61,8 +61,22 @@ export interface IntakeCheckEvidence {
61
61
  readonly contrary?: boolean;
62
62
  }
63
63
 
64
+ export interface IntakeReplacementCandidate {
65
+ readonly tool: string;
66
+ readonly paidDependency: string;
67
+ readonly status: '현장 시험 필요';
68
+ /** A comparison claim is not evidence that any of these checks have passed. */
69
+ readonly trial: {
70
+ readonly installation: '미검증';
71
+ readonly sampleRun: '미검증';
72
+ readonly license: '미검증';
73
+ readonly maintenanceStatus: '미검증';
74
+ };
75
+ }
76
+
64
77
  export interface IntakeCheckItem {
65
78
  readonly fact: string;
79
+ readonly replacementCandidate?: IntakeReplacementCandidate;
66
80
  /** Source identity preserved from the supplied fact for card-backed goal evidence. */
67
81
  readonly sourceRef?: string;
68
82
  readonly originalClaims?: readonly string[];
@@ -1053,6 +1067,40 @@ function factKey(text: string): string {
1053
1067
  return text.replace(/\s+/g, ' ').trim().toLowerCase();
1054
1068
  }
1055
1069
 
1070
+ /** A stated possibility is a trial candidate, not proof of a working replacement. */
1071
+ function replacementCandidate(fact: string): IntakeReplacementCandidate | undefined {
1072
+ if (!/(?:대체(?:하|한|할| 가능| 후보|재)|replace|replacement|alternative to)/i.test(fact)
1073
+ || /(?:대체하지\s*(?:는|도|조차|를)?\s*(?:않|못)|대체\s*못|대체할\s*수\s*(?:는|도|가)?\s*없|대체(?:가|는| 후보가)?\s*(?:아니|불가)|cannot replace|can't replace|does not replace|not a replacement)/i.test(fact)) return undefined;
1074
+ const paid = fact.match(/(?:유료|paid)\s*(?:(?:서비스|의존성|도구|툴|API|dependency|service|tool)\s*)?`?([a-z][\w.-]+)`?/i);
1075
+ // firecrawl is a named paid-dependency example even when the claim omits the word "paid".
1076
+ const paidDependency = paid?.[1] ?? fact.match(/(?:^|[^\w])`?(firecrawl)`?(?=$|[^\w])/i)?.[1];
1077
+ if (!paidDependency) return undefined;
1078
+ const names = [...fact.matchAll(/`([a-z][\w.-]+)`/gi)].map((match) => match[1]!);
1079
+ const explicit = names.filter((name) => name.toLowerCase() !== paidDependency.toLowerCase());
1080
+ const plain = fact.match(/^\s*([a-z][\w.-]+)\s*(?:가|이|는|은|으로|로|can\b|could\b|may\b)/i)?.[1];
1081
+ const tool = explicit.length === 1 ? explicit[0] : explicit.length === 0 ? plain : undefined;
1082
+ if (!tool || tool.toLowerCase() === paidDependency.toLowerCase() || tool.toLowerCase() === 'elanous') return undefined;
1083
+ // Names appearing together do not establish the direction of replacement.
1084
+ const clause = fact.replace(/`/g, '').replace(/(?:유료|paid)\s*(?:(?:서비스|의존성|도구|툴|API|dependency|service|tool)\s*)?/gi, '');
1085
+ const escape = (name: string): string => name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1086
+ const name = (value: string): string => `(?<![\\w.-])${escape(value)}(?![\\w.-])`;
1087
+ const toolName = name(tool);
1088
+ const dependencyName = name(paidDependency);
1089
+ const replaces = (subject: string, object: string): boolean => [
1090
+ new RegExp(`${subject}\\s*(?:이|가|은|는)?\\s+${object}\\s*(?:을|를)\\s*대체(?:하|한|할| 가능| 후보|재)`, 'i'),
1091
+ new RegExp(`${object}\\s*(?:을|를)\\s+${subject}\\s*(?:이|가|은|는)\\s*대체(?:하|한|할| 가능| 후보|재)`, 'i'),
1092
+ new RegExp(`${subject}\\s+(?:can |could |may )?replace(?:s|d)?\\s+${object}`, 'i'),
1093
+ new RegExp(`${subject}\\s+(?:is |could be |may be )?(?:an? )?(?:replacement|alternative)\\s+to\\s+${object}`, 'i'),
1094
+ ].some((pattern) => pattern.test(clause));
1095
+ if (!replaces(toolName, dependencyName) || replaces(dependencyName, toolName)) return undefined;
1096
+ return {
1097
+ tool,
1098
+ paidDependency,
1099
+ status: '현장 시험 필요',
1100
+ trial: { installation: '미검증', sampleRun: '미검증', license: '미검증', maintenanceStatus: '미검증' },
1101
+ };
1102
+ }
1103
+
1056
1104
  function isLens(value: string): value is PreprocessLens {
1057
1105
  return (PREPROCESS_LENSES as readonly string[]).includes(value);
1058
1106
  }
@@ -1414,8 +1462,17 @@ export function runIntakeCheck(
1414
1462
  }
1415
1463
  // src/index.ts intake check .action → runIntakeCheck / runIntakeCheckDocument → runIntakeCheck → judgeFact.
1416
1464
  const judged = judgeFact(fact, ruler, deps);
1465
+ const candidate = replacementCandidate(fact.text);
1466
+ const verdict = candidate && judged.verdict !== '못 쟀다' ? '판단 필요' : judged.verdict;
1467
+ const current = candidate && judged.verdict !== '못 쟀다'
1468
+ ? `${judged.current} · 대체 후보 ${candidate.tool} → ${candidate.paidDependency}: 설치·샘플 실행·라이선스·유지보수 상태 현장 시험 필요`
1469
+ : judged.current;
1417
1470
  const item: IntakeCheckItem = {
1418
1471
  ...judged,
1472
+ verdict,
1473
+ current,
1474
+ line: `${fact.text} → ${current} → ${verdict}`,
1475
+ ...(candidate ? { replacementCandidate: candidate } : {}),
1419
1476
  quotes: [quote],
1420
1477
  ...(fact.sourceRef ? { sourceRef: fact.sourceRef } : {}),
1421
1478
  ...(fact.originalClaim ? { originalClaims: [fact.originalClaim] } : {}),
@@ -1711,6 +1768,11 @@ export function renderIntakeCheckReport(report: IntakeCheckReport): string {
1711
1768
  for (const item of report.items) {
1712
1769
  lines.push(item.line);
1713
1770
  lines.push(` 판정: ${item.verdict}`);
1771
+ if (item.replacementCandidate) {
1772
+ const candidate = item.replacementCandidate;
1773
+ lines.push(` 대체 후보: ${candidate.tool} → 유료 의존성 ${candidate.paidDependency} (${candidate.status})`);
1774
+ lines.push(' 현장 시험: 설치 미검증 · 샘플 실행 미검증 · 라이선스 미검증 · 유지보수 상태 미검증');
1775
+ }
1714
1776
  if (item.goalDraftPath) lines.push(` 골 초안: ${item.goalDraftPath}`);
1715
1777
  for (const quote of item.quotes) lines.push(` 인용: ${quote}`);
1716
1778
  for (const original of item.originalClaims ?? []) lines.push(` 원 주장: ${original}`);
@@ -1746,6 +1808,7 @@ export function intakeCheckReportJson(report: IntakeCheckReport): Record<string,
1746
1808
  current: item.current,
1747
1809
  verdict: item.verdict,
1748
1810
  line: item.line,
1811
+ ...(item.replacementCandidate ? { replacementCandidate: item.replacementCandidate } : {}),
1749
1812
  quotes: item.quotes,
1750
1813
  evidence: item.evidence,
1751
1814
  patterns: item.patterns,
@@ -1,12 +1,12 @@
1
1
  // 흡수 하루 다이제스트 — 그날 흡수한 것을 사람이 «발견»하는 자리. 노트 절(마크다운) ⊕ 텔레그램 짧은 판.
2
2
  // 결정론만: 요약 한 줄은 각 노트가 이미 쓴 「한 줄 결론」을 뽑는다(LLM 을 다시 부르지 않는다).
3
3
  import { existsSync, readFileSync } from 'node:fs';
4
- import { basename, join, relative } from 'node:path';
4
+ import { basename, join } from 'node:path';
5
5
  import { loadIntakeLedger, type IntakeItem } from './items.js';
6
6
  import { readSavedCursorAt } from './collect-telegram-saved.js';
7
7
  import { intakeOutboxDir, kstDay } from './route.js';
8
8
 
9
- export interface DigestEntry { id: string; sources: string[]; url?: string; note?: string; noteName?: string; oneLiner?: string; axis: string }
9
+ export interface DigestEntry { id: string; sources: string[]; url?: string; note?: string; noteName?: string; oneLiner?: string; axis: string; impact?: { fact: string; current: string; action: string } }
10
10
  export interface IntakeDigest { day: string; absorbed: DigestEntry[]; goals: { fact: string; url?: string }[]; review?: { fact: string; note?: string }[]; grounding: number; release: number; manual: number; savedSilence?: { days: number; lastNewAt: string } }
11
11
 
12
12
  const AXIS_LABEL: Record<string, string> = {
@@ -43,17 +43,38 @@ const SAVED_SILENCE_MS = 48 * 3600_000;
43
43
  export function buildIntakeDigest(root: string, day: string, readFile: (p: string) => string | undefined = (p) => (existsSync(p) ? readFileSync(p, 'utf8') : undefined), now: Date = new Date()): IntakeDigest {
44
44
  const items = [...loadIntakeLedger(root).items.values()]
45
45
  .filter((i) => (i.status === 'absorbed' || i.status === 'routed') && kstDay(i.lastSeenAt) === day && i.outputs.some((o) => o.kind === 'note'));
46
+ const out = intakeOutboxDir(root);
47
+ const relevant = new Map<string, NonNullable<DigestEntry['impact']>>();
48
+ for (const [folder, action] of [
49
+ ['goals', '없는 기능의 골 후보를 세운다'],
50
+ ['manual', '문서·약속을 현재 동작에 맞게 보강한다'],
51
+ ['review', '대조 근거를 추가로 확인한다'],
52
+ ['release', '이미 착지한 기능의 바깥 맥락을 릴리스 노트에 반영한다'],
53
+ ] as const) {
54
+ for (const row of readJsonl(join(out, folder, `${day}.jsonl`))) {
55
+ if (typeof row.id !== 'string' || relevant.has(row.id)) continue;
56
+ const fact = folder === 'release' ? row.title : row.fact;
57
+ if (typeof fact !== 'string' || !fact.trim()) continue;
58
+ relevant.set(row.id, {
59
+ fact,
60
+ current: typeof (folder === 'release' ? row.summary : row.current) === 'string'
61
+ ? String(folder === 'release' ? row.summary : row.current) : '대조 근거 없음',
62
+ action,
63
+ });
64
+ }
65
+ }
46
66
  const absorbed = items.map((i: IntakeItem): DigestEntry => {
47
67
  const note = [...i.outputs].reverse().find((o) => o.kind === 'note')?.ref;
48
68
  const md = note ? readFile(note) : undefined;
69
+ const impact = relevant.get(i.id);
49
70
  return {
50
71
  id: i.id, sources: i.sources, ...(i.url ? { url: i.url } : {}),
51
72
  ...(note ? { note, noteName: basename(note, '.md') } : {}),
52
73
  ...(md ? { oneLiner: noteOneLiner(md) } : {}),
53
74
  axis: AXIS_LABEL[i.judgement?.axis ?? i.axis ?? ''] ?? (i.sources.includes('telegram-saved') ? '내가 저장한 것' : '그 밖'),
75
+ ...(impact ? { impact } : {}),
54
76
  };
55
77
  });
56
- const out = intakeOutboxDir(root);
57
78
  const goals = readJsonl(join(out, 'goals', `${day}.jsonl`)).map((g) => ({ fact: String(g.fact ?? ''), ...(g.url ? { url: String(g.url) } : {}) }));
58
79
  const review = readJsonl(join(out, 'review', `${day}.jsonl`)).map((r) => ({ fact: String(r.fact ?? ''), ...(r.note ? { note: String(r.note) } : {}) }));
59
80
  const grounding = readJsonl(join(out, 'grounding.jsonl')).filter((g) => typeof g.at === 'string' && kstDay(g.at) === day).length;
@@ -94,18 +115,19 @@ export function renderDigestMarkdown(d: IntakeDigest): string {
94
115
  return L.join('\n');
95
116
  }
96
117
 
97
- /** 텔레그램 짧은 판 — 수 · 한 줄 요약 다섯 · 골 후보 · 노트 자리. */
98
- export function renderDigestTelegram(d: IntakeDigest, opts: { vaultRoot?: string; notePath?: string } = {}): string {
99
- const L = [`📰 *${d.day} 흡수 ${d.absorbed.length}편*`];
100
- if (d.savedSilence) L.push(`⚠️ 저장된 메시지 새 글 ${d.savedSilence.days}일째 0 — 저장한 곳 확인`);
101
- for (const e of d.absorbed.slice(0, 5)) L.push(`• ${e.oneLiner ?? e.noteName ?? e.url ?? e.id}`);
102
- if (d.absorbed.length > 5) L.push(`… 외 ${d.absorbed.length - 5}편`);
103
- if (d.goals.length) L.push('', `🔴 엘라누스에 없는 것 ${d.goals.length}건 — 골 후보`);
104
- if (d.review?.length) L.push(`${d.goals.length ? '' : '\n'}🟡 사람이 가를 것 ${d.review.length}건 — 노트 🧭 절`);
105
- if (opts.vaultRoot && opts.notePath) {
106
- const vault = basename(opts.vaultRoot);
107
- const file = relative(opts.vaultRoot, opts.notePath).replace(/\.md$/, '');
108
- L.push('', `📂 obsidian://open?vault=${encodeURIComponent(vault)}&file=${encodeURIComponent(file)}`);
118
+ /** 텔레그램 — 흡수 렌즈가 대조한 항목만 SCQA 짧은 판으로 낸다. */
119
+ export function renderDigestTelegram(d: IntakeDigest, _opts: { vaultRoot?: string; notePath?: string } = {}): string {
120
+ const touching = d.absorbed.filter((e) => e.impact);
121
+ const L = [`흡수 ${d.absorbed.length} → 우리에게 닿는 것 ${touching.length}`];
122
+ if (!touching.length) return L[0];
123
+ for (const e of touching.slice(0, 3)) {
124
+ L.push('',
125
+ `S 무엇: ${e.impact!.fact}`,
126
+ `C 우리에게 왜: ${e.impact!.current}`,
127
+ `A 그래서 무엇을 하나: ${e.impact!.action}`,
128
+ `🔗 원문 링크: ${e.url?.trim() || '링크 없음'}`,
129
+ );
109
130
  }
131
+ if (d.absorbed.length > touching.length) L.push('', `그 밖 ${d.absorbed.length - touching.length}건 · 닿지 않음`);
110
132
  return L.join('\n');
111
133
  }
@@ -18,6 +18,12 @@ export interface FrontClassifierDecision extends IntakeFrontRouteDecision {
18
18
  urlRoute: UrlRouteDecision | null;
19
19
  }
20
20
 
21
+ /** Only Telegram links explicitly routed to saved/absorbed work enter the event lane. */
22
+ export function telegramAbsorbUrls(input: FrontClassifierInput, decision: FrontClassifierDecision): string[] {
23
+ if (input.surface !== 'telegram' || decision.track !== 'absorb' || !decision.urlRoute) return [];
24
+ return decision.urlRoute.urls;
25
+ }
26
+
21
27
  const QUESTION_WORD_RE = new RegExp(
22
28
  `(?:${INTAKE_FRONT_QUESTION_WORDS.map((word) => /^[a-z]+$/i.test(word) ? `(?<![\\p{L}\\p{N}_])${word}(?![\\p{L}\\p{N}_])` : word).join('|')})[.!?。?!]*$`,
23
29
  'iu',
@@ -5,6 +5,7 @@ import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
5
5
  import { join } from 'node:path';
6
6
  import { debug } from '../debug/log.js';
7
7
  import { findTrack } from '../autopilot/mission-phase-track.js';
8
+ import { wasIntakeEventScheduled } from './route.js';
8
9
 
9
10
  export const INTAKE_SOURCES = ['x', 'youtube', 'github', 'telegram-saved', 'telegram-bot', 'memo', 'pwa'] as const;
10
11
  export type RegisteredIntakeSourceKind = 'rss' | 'command';
@@ -243,13 +244,13 @@ export function parseRawIntakeJsonl(text: string): { raws: RawIntakeItem[]; bad:
243
244
  */
244
245
  const STALE_QUEUED_MS = 24 * 3600_000;
245
246
 
246
- export function pickAbsorbQueue(instanceRoot: string, opts: { max: number; laneMax?: number; kind?: IntakeKind; dryRun?: boolean }, now = new Date().toISOString()): IntakeItem[] {
247
+ export function pickAbsorbQueue(instanceRoot: string, opts: { max: number; laneMax?: number; kind?: IntakeKind; dryRun?: boolean }, now = new Date().toISOString(), taskStatus?: Parameters<typeof wasIntakeEventScheduled>[3]): IntakeItem[] {
247
248
  const userLeft = (i: IntakeItem) => i.sources.some((s) => s === 'telegram-saved' || s === 'memo');
248
249
  const score = (i: IntakeItem) => Math.max(0, ...Object.entries(i.signals).filter(([k]) => k.endsWith('.score')).map(([, v]) => v));
249
250
  const eligible = [...loadIntakeLedger(instanceRoot).items.values()]
250
251
  // queued 로 옮긴 뒤 흡수·표시가 없이 하루가 지난 것(흡수 도중 죽은 판)은 다시 고른다.
251
252
  .filter((i) => (i.status === 'new' || (i.status === 'queued' && Date.parse(now) - Date.parse(i.lastSeenAt) > STALE_QUEUED_MS))
252
- && !!i.url && (!opts.kind || i.kind === opts.kind))
253
+ && !!i.url && !wasIntakeEventScheduled(instanceRoot, i.url, now, taskStatus) && (!opts.kind || i.kind === opts.kind))
253
254
  .sort((a, b) => Number(userLeft(b)) - Number(userLeft(a)) || b.sources.length - a.sources.length || score(b) - score(a) || b.lastSeenAt.localeCompare(a.lastSeenAt));
254
255
  const laneMax = opts.laneMax ?? 30;
255
256
  const lane = eligible.filter((i) => i.sources.includes('telegram-saved')).slice(0, Math.max(0, laneMax));