elanous 0.2.10 → 0.2.11

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 (584) 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/Y4zKzL62sakG5momz3SoQ/_buildManifest.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1394-556de6d71bbdb0fb.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
  7. package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/2310-7a59f043f6db207e.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/2548-6e316138d347cefe.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/3869-a39d1d9921e10d43.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
  19. package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
  20. package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
  25. package/apps/pwa/out/_next/static/chunks/507-5acd98bd6dab2d8a.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/5445-745eb795c5963d79.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
  31. package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/8605-ea5bee9dfae512c7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1dcdc58fc2de2454.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-6a061bd97f0b9398.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/board/page-cb95a7432c9ee744.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-b12b6d2f8d2d1aea.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/app/bots/page-b9efe868bfd36255.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/chat/page-7c97dcdfe2e37a60.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/consult/page-8fd36984f549270a.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/control/page-5721537ca8a3598c.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/design-check/page-b654240a572e4c48.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/editor/page-b9750abc897508c3.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/exec/page-4cd1de371f8ad048.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/field/page-d99f89657828421c.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/app/inside/page-50cb2a0eb15e6c83.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/intake/page-c8b1ccda6ba7ae98.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/layout-d6b1d156fb95e74b.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/live/page-2a9932ddb62d76bd.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/market/page-9688f5b4f1ff950f.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6b15dd6456c5df09.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/morning/page-35414e0a007b4082.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/not-found-e7a529e0507ac86c.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/observatory/page-e001823c35c9dd67.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-371423d1a573d64b.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4b764b125339ac17.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cdf8e4b01067bcf1.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a24072b35470157.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/page-94c82eb0ae5abb32.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/reflection/page-0be8d4b2ced75ba0.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d37cb0d52f9b6bd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/sessions/page-686da0df9bf23e5c.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4dc614f3ce043e63.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/settings/page-53f80edc6b8dc07c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-d02c782fc792e2af.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/app/setup/page-239c17b911b84e72.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/app/share/page-dc6a79fb003f746c.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/app/showroom/page-0fffb84cafdc9da6.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/app/tasks/page-1218753c82d585f6.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/app/term/page-4b5935e67531efb5.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/app/today/page-3285bc87caf1eaa5.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/app/trace/page-ad553b0e06505ecd.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/app/vault/page-fca096e3e860306f.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ebfa78f0d9885c3.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/app/workflows/page-3dc5f21f7e39622d.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/app/workspace/page-c6da2b468454532d.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-93bc70e36f595414.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → f48170cc-d05d28bf87a43bf4.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +1 -0
  105. package/apps/pwa/out/_next/static/css/543f56bcb1f79fca.css +1 -0
  106. package/apps/pwa/out/approvals/index.html +1 -1
  107. package/apps/pwa/out/approvals/index.txt +23 -23
  108. package/apps/pwa/out/autopilot/index.html +1 -1
  109. package/apps/pwa/out/autopilot/index.txt +23 -23
  110. package/apps/pwa/out/board/index.html +1 -1
  111. package/apps/pwa/out/board/index.txt +23 -23
  112. package/apps/pwa/out/botlab/index.html +1 -1
  113. package/apps/pwa/out/botlab/index.txt +22 -22
  114. package/apps/pwa/out/bots/index.html +1 -1
  115. package/apps/pwa/out/bots/index.txt +22 -22
  116. package/apps/pwa/out/chat/index.html +1 -1
  117. package/apps/pwa/out/chat/index.txt +22 -22
  118. package/apps/pwa/out/consult/index.html +1 -1
  119. package/apps/pwa/out/consult/index.txt +23 -23
  120. package/apps/pwa/out/control/index.html +1 -1
  121. package/apps/pwa/out/control/index.txt +23 -23
  122. package/apps/pwa/out/design-check/index.html +1 -1
  123. package/apps/pwa/out/design-check/index.txt +23 -23
  124. package/apps/pwa/out/editor/index.html +1 -1
  125. package/apps/pwa/out/editor/index.txt +23 -23
  126. package/apps/pwa/out/exec/index.html +1 -1
  127. package/apps/pwa/out/exec/index.txt +23 -23
  128. package/apps/pwa/out/field/index.html +1 -1
  129. package/apps/pwa/out/field/index.txt +23 -23
  130. package/apps/pwa/out/healthz +1 -1
  131. package/apps/pwa/out/index.html +1 -1
  132. package/apps/pwa/out/index.txt +22 -22
  133. package/apps/pwa/out/inside/index.html +1 -0
  134. package/apps/pwa/out/inside/index.txt +31 -0
  135. package/apps/pwa/out/intake/index.html +1 -1
  136. package/apps/pwa/out/intake/index.txt +23 -23
  137. package/apps/pwa/out/live/index.html +1 -1
  138. package/apps/pwa/out/live/index.txt +23 -23
  139. package/apps/pwa/out/market/index.html +1 -1
  140. package/apps/pwa/out/market/index.txt +22 -22
  141. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  142. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  143. package/apps/pwa/out/morning/index.html +1 -1
  144. package/apps/pwa/out/morning/index.txt +23 -23
  145. package/apps/pwa/out/observatory/index.html +1 -1
  146. package/apps/pwa/out/observatory/index.txt +23 -23
  147. package/apps/pwa/out/ops/checklist/index.html +1 -1
  148. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  149. package/apps/pwa/out/ops/release/index.html +1 -1
  150. package/apps/pwa/out/ops/release/index.txt +22 -22
  151. package/apps/pwa/out/ops/seats/index.html +1 -1
  152. package/apps/pwa/out/ops/seats/index.txt +22 -22
  153. package/apps/pwa/out/outputs/index.html +1 -0
  154. package/apps/pwa/out/outputs/index.txt +30 -0
  155. package/apps/pwa/out/reflection/index.html +1 -1
  156. package/apps/pwa/out/reflection/index.txt +23 -23
  157. package/apps/pwa/out/scheduler/index.html +1 -1
  158. package/apps/pwa/out/scheduler/index.txt +23 -23
  159. package/apps/pwa/out/sessions/index.html +1 -1
  160. package/apps/pwa/out/sessions/index.txt +22 -22
  161. package/apps/pwa/out/settings/devices/index.html +1 -1
  162. package/apps/pwa/out/settings/devices/index.txt +23 -23
  163. package/apps/pwa/out/settings/index.html +1 -1
  164. package/apps/pwa/out/settings/index.txt +23 -23
  165. package/apps/pwa/out/setup/done/index.html +1 -1
  166. package/apps/pwa/out/setup/done/index.txt +23 -23
  167. package/apps/pwa/out/setup/index.html +1 -1
  168. package/apps/pwa/out/setup/index.txt +23 -23
  169. package/apps/pwa/out/share/index.html +1 -1
  170. package/apps/pwa/out/share/index.txt +23 -23
  171. package/apps/pwa/out/showroom/index.html +1 -1
  172. package/apps/pwa/out/showroom/index.txt +22 -22
  173. package/apps/pwa/out/tasks/index.html +1 -1
  174. package/apps/pwa/out/tasks/index.txt +23 -23
  175. package/apps/pwa/out/term/index.html +1 -1
  176. package/apps/pwa/out/term/index.txt +23 -24
  177. package/apps/pwa/out/today/index.html +1 -1
  178. package/apps/pwa/out/today/index.txt +23 -23
  179. package/apps/pwa/out/trace/index.html +1 -1
  180. package/apps/pwa/out/trace/index.txt +23 -23
  181. package/apps/pwa/out/vault/index.html +1 -1
  182. package/apps/pwa/out/vault/index.txt +23 -23
  183. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  184. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  185. package/apps/pwa/out/workflows/index.html +1 -1
  186. package/apps/pwa/out/workflows/index.txt +23 -23
  187. package/apps/pwa/out/workspace/index.html +1 -1
  188. package/apps/pwa/out/workspace/index.txt +23 -24
  189. package/apps/pwa/out/worktrees/index.html +1 -1
  190. package/apps/pwa/out/worktrees/index.txt +23 -23
  191. package/graphs/drafts/draft-cleanup.yaml +19 -0
  192. package/graphs/drafts/recipes.yaml +23 -0
  193. package/graphs/intake/intake-daily.yaml +2 -1
  194. package/graphs/ops/recipes.yaml +3 -0
  195. package/graphs/ops/secret-exposure.yaml +24 -0
  196. package/graphs/release/recipes.yaml +3 -0
  197. package/graphs/release/release-loop.yaml +4 -1
  198. package/graphs/video/explainer-line.yaml +2 -2
  199. package/package.json +2 -1
  200. package/plugins/elanous-hwp/README.md +25 -0
  201. package/plugins/elanous-hwp/cli.ts +22 -0
  202. package/plugins/elanous-hwp/converter.ts +237 -0
  203. package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
  204. package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
  205. package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
  206. package/plugins/elanous-hwp/plugin.json +16 -0
  207. package/plugins/elanous-hwp/plugin.ts +40 -0
  208. package/scripts/ci-public-export-leak-gate.ts +75 -14
  209. package/scripts/ci-public-leak-gate.ts +44 -9
  210. package/scripts/context-hooks/claude-stop.sh +4 -0
  211. package/scripts/context-hooks/emit.ts +24 -0
  212. package/scripts/context-hooks/post-tool-use.sh +4 -0
  213. package/scripts/coord-channel-watch.sh +12 -0
  214. package/scripts/coord-requests-bridge.ts +143 -0
  215. package/scripts/field-feed/lib.ts +4 -0
  216. package/scripts/fleet/node-setup.sh +20 -3
  217. package/scripts/homebrew-formula-bump.ts +69 -0
  218. package/scripts/marketing/measure-site-numbers.ts +169 -0
  219. package/scripts/measure-gate-shards.ts +309 -0
  220. package/scripts/mission-request-judge.ts +31 -1
  221. package/scripts/morning-report.ts +2 -2
  222. package/scripts/opportunity-scan.ts +1 -1
  223. package/scripts/release-loop/auto-approve-node.ts +21 -4
  224. package/scripts/release-loop/cut-branch.ts +84 -0
  225. package/scripts/release-loop/gate-node.ts +14 -13
  226. package/scripts/release-loop/mac-smoke-node.ts +229 -0
  227. package/scripts/release-loop/node-verdict.ts +3 -3
  228. package/scripts/release-loop/tui-node-checks.ts +42 -0
  229. package/scripts/release-loop/tui-sim-node.ts +32 -8
  230. package/scripts/release-loop/unattended-release.ts +5 -3
  231. package/scripts/release-loop/version-node.ts +61 -10
  232. package/scripts/signal-digest-cycle.ts +2 -7
  233. package/scripts/signal-digest-photo.ts +11 -0
  234. package/scripts/tech1-public-measure.ts +94 -0
  235. package/scripts/test-diet/node.ts +1 -1
  236. package/scripts/tui-regress.ts +2 -2
  237. package/scripts/ux/demo-rehearsal.ts +243 -0
  238. package/scripts/ux/lib/rehearsal-verdict.ts +73 -0
  239. package/skills/diagram-master/SKILL.md +366 -0
  240. package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
  241. package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
  242. package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
  243. package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
  244. package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
  245. package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
  246. package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
  247. package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
  248. package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
  249. package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
  250. package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
  251. package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
  252. package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
  253. package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
  254. package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
  255. package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
  256. package/skills/diagram-master/references/examples/README.md +69 -0
  257. package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
  258. package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
  259. package/skills/diagram-master/references/pyproject.toml +16 -0
  260. package/skills/diagram-master/references/quality-checklist.md +33 -0
  261. package/skills/diagram-master/references/routing-guide.md +164 -0
  262. package/skills/diagram-master/references/uv.lock +1356 -0
  263. package/skills/google-workspace/SKILL.md +33 -0
  264. package/skills/google-workspace/scripts/gws-safe.sh +177 -0
  265. package/skills/grill-me/SKILL.md +1 -1
  266. package/skills/lecture-note-digitizer/SKILL.md +926 -0
  267. package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
  268. package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
  269. package/skills/lecture-note-digitizer/references/html-template.md +167 -0
  270. package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
  271. package/skills/omni-crawl/SKILL.md +21 -11
  272. package/skills/omni-crawl/scripts/main.ts +6 -6
  273. package/skills/omni-crawl/src/router.ts +3 -3
  274. package/skills/omni-digest/SKILL.md +17 -9
  275. package/skills/omni-digest/digest.md +2 -2
  276. package/skills/omni-digest/src/fetch.ts +30 -3
  277. package/skills/pitch-deck/SKILL.md +2 -2
  278. package/skills/pitch-deck/template.html +2 -2
  279. package/skills/youtube-master/SKILL.md +163 -0
  280. package/skills/youtube-master/package-lock.json +558 -0
  281. package/skills/youtube-master/package.json +13 -0
  282. package/skills/youtube-master/references/study-note-template.md +124 -0
  283. package/skills/youtube-master/scripts/main.ts +435 -0
  284. package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
  285. package/skills/youtube-master/src/audio.ts +63 -0
  286. package/skills/youtube-master/src/domain-staging.ts +50 -0
  287. package/skills/youtube-master/src/env.ts +36 -0
  288. package/skills/youtube-master/src/obsidian.ts +155 -0
  289. package/skills/youtube-master/src/router.ts +110 -0
  290. package/skills/youtube-master/src/stt.ts +199 -0
  291. package/skills/youtube-master/src/study-note.ts +175 -0
  292. package/skills/youtube-master/src/summarize.ts +358 -0
  293. package/skills/youtube-master/src/transcript.ts +76 -0
  294. package/skills/youtube-master/src/types.ts +91 -0
  295. package/skills/youtube-master/src/util.ts +93 -0
  296. package/skills/youtube-master/src/youtube.ts +70 -0
  297. package/skills/youtube-master/tsconfig.json +13 -0
  298. package/src/acp/server.ts +5 -2
  299. package/src/agent-mission/driver.ts +80 -10
  300. package/src/agent-mission/pty-decision.ts +71 -0
  301. package/src/agent-mission/review-loop.ts +30 -0
  302. package/src/autopilot/build/llm-conflict-merge.ts +16 -3
  303. package/src/autopilot/tool-registry.ts +2 -0
  304. package/src/boot/daemon-prompt-turn.ts +5 -0
  305. package/src/boot/daemon-runtime.ts +9 -3
  306. package/src/boot/daemon-tools/web-search.ts +3 -0
  307. package/src/card-followup/core.ts +109 -0
  308. package/src/chat/index.ts +1 -0
  309. package/src/cli/drive-input-jail.ts +101 -0
  310. package/src/cli/hooks-cli.ts +17 -3
  311. package/src/cli/make-cli.ts +43 -0
  312. package/src/cli/persona-cli.ts +90 -4
  313. package/src/cli/plugin-cli.ts +31 -22
  314. package/src/cli/pod-cli.ts +19 -9
  315. package/src/cli/pr-cli.ts +51 -15
  316. package/src/cli/pty-drive-cli.ts +41 -7
  317. package/src/cli/pty-drive-verdict.ts +40 -0
  318. package/src/cli/release-cli.ts +17 -4
  319. package/src/cli/setup-cli.ts +43 -1
  320. package/src/cli/skills-cli.ts +17 -1
  321. package/src/context-bus/claude-hooks-install.ts +10 -0
  322. package/src/context-bus/context-now-surfaces.ts +48 -0
  323. package/src/context-bus/context-now.ts +104 -0
  324. package/src/context-bus/coord-events.ts +2 -2
  325. package/src/context-bus/external-events.ts +52 -0
  326. package/src/context-bus/long-term-memory.ts +108 -0
  327. package/src/dashboard/index.ts +9 -4
  328. package/src/dashboard/slash-runtime/dashboard-handlers.ts +7 -1
  329. package/src/decisions/decision-cards.ts +10 -3
  330. package/src/decisions/decision-ledger.ts +13 -5
  331. package/src/discord/sprint21-runtime.ts +5 -1
  332. package/src/discord-self-message.ts +32 -0
  333. package/src/discord-slash-wire.ts +5 -1
  334. package/src/discord.ts +17 -1
  335. package/src/domains/core-tools.ts +3 -2
  336. package/src/domains/outbound-alert.ts +6 -1
  337. package/src/domains/telegram-kind-route.ts +51 -13
  338. package/src/exec-requests/default-outputs.ts +25 -0
  339. package/src/exec-requests/planner.ts +10 -2
  340. package/src/exec-requests/runner.ts +20 -6
  341. package/src/exec-requests/store.ts +3 -0
  342. package/src/execution-loop/launch-gate.ts +100 -0
  343. package/src/field/field-reel.ts +5 -1
  344. package/src/field-note/index.ts +201 -0
  345. package/src/field-note/transcribe.ts +248 -0
  346. package/src/graph-kinds/registry.ts +3 -3
  347. package/src/graph-runner/graph-cli.ts +61 -1
  348. package/src/graph-runner/graph-grow-llm.ts +37 -0
  349. package/src/graph-runner/graph-grow.ts +47 -0
  350. package/src/graph-runner/runner.ts +317 -25
  351. package/src/grok/agent-search.ts +8 -2
  352. package/src/guardian/secret-exposure-scan.ts +101 -0
  353. package/src/harness/harness-cli-command.ts +247 -7
  354. package/src/harness/harness-pod-dispatch.ts +43 -23
  355. package/src/harness/harness-seams.ts +38 -4
  356. package/src/harness/harness-stop.ts +23 -4
  357. package/src/harness/launch-registry.ts +91 -0
  358. package/src/harness/process-garbage.ts +5 -3
  359. package/src/hooks/dispatch.ts +82 -0
  360. package/src/hooks/expose.ts +254 -0
  361. package/src/hooks/github-shadow.ts +108 -0
  362. package/src/hooks/providers.ts +71 -5
  363. package/src/hooks/queue.ts +1 -1
  364. package/src/hooks/receiver.ts +21 -20
  365. package/src/index.ts +52 -14
  366. package/src/intake-plane/categorize.ts +18 -46
  367. package/src/intake-plane/discord-seat-work.ts +10 -0
  368. package/src/intake-plane/front-route-classifier.ts +33 -39
  369. package/src/intake-plane/persona-answer.ts +30 -0
  370. package/src/intake-plane/runtime-callables.ts +8 -1
  371. package/src/intake-plane/telegram-seat-work.ts +36 -2
  372. package/src/intake-plane/wish-folder.ts +67 -0
  373. package/src/intent-gate/gate.ts +30 -10
  374. package/src/live/detail-switch.ts +5 -0
  375. package/src/llm/difficulty.ts +57 -0
  376. package/src/llm/judge-layer.ts +101 -0
  377. package/src/llm/mission-router.ts +33 -19
  378. package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
  379. package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
  380. package/src/loops/contract/examples/steward.loop.yaml +50 -0
  381. package/src/loops/contract/loop-agent.schema.json +138 -0
  382. package/src/loops/contract/validate.ts +64 -0
  383. package/src/loops/registry.ts +20 -6
  384. package/src/market/signed-index.ts +4 -0
  385. package/src/maturity/bot-command-maturity.ts +45 -0
  386. package/src/maturity/feature-maturity.ts +26 -4
  387. package/src/model-tier/index.ts +2 -2
  388. package/src/model-tier/tier-resolver.ts +20 -20
  389. package/src/model-tier/types.ts +6 -6
  390. package/src/mss/logging/log-store.ts +15 -0
  391. package/src/nexus/api/config-model-tier.ts +5 -4
  392. package/src/nexus/api/fabric-plans.ts +53 -0
  393. package/src/nexus/api/harness-api.ts +5 -1
  394. package/src/nexus/api/health.ts +2 -0
  395. package/src/nexus/api/http-server.ts +36 -0
  396. package/src/nexus/api/inside-events.ts +226 -0
  397. package/src/nexus/api/meta-api.ts +21 -8
  398. package/src/nexus/api/missions.ts +6 -1
  399. package/src/nexus/api/ops-seats.ts +33 -0
  400. package/src/nexus/api/outputs-route.ts +44 -0
  401. package/src/nexus/api/seat-requests.ts +44 -2
  402. package/src/nexus/api/sessions-store.ts +17 -38
  403. package/src/nexus/api/sub-seat-charters.ts +34 -0
  404. package/src/nexus/api/tabs-mutations.ts +3 -1
  405. package/src/nexus/api/trace.ts +18 -6
  406. package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
  407. package/src/nexus/api/workflows.ts +80 -6
  408. package/src/nexus/index.ts +2 -0
  409. package/src/nexus/kinds/webterm.ts +2 -1
  410. package/src/nexus/webterm/pty.ts +6 -2
  411. package/src/onboarding/cli-auth-status.ts +80 -0
  412. package/src/onboarding/voice-ai.ts +3 -3
  413. package/src/org/seat-budget.ts +48 -0
  414. package/src/org/stall-escalation.ts +63 -0
  415. package/src/outputs/ledger.ts +120 -0
  416. package/src/persona/persona-todo.ts +79 -0
  417. package/src/persona/presets.ts +116 -2
  418. package/src/persona/team-set.ts +155 -0
  419. package/src/plugins/install/plugin-install.ts +14 -0
  420. package/src/plugins/maker/market-bundle.ts +109 -0
  421. package/src/plugins/maker/plugin-maker.ts +254 -11
  422. package/src/plugins/maker/wizard-generate.ts +103 -0
  423. package/src/pod-lease/admission.ts +150 -0
  424. package/src/pod-lease/dependency-state.ts +85 -0
  425. package/src/pod-lease/host-lease.ts +127 -0
  426. package/src/project/project-suggestion.ts +16 -0
  427. package/src/project/session-context.ts +24 -0
  428. package/src/release-loop/checklist.ts +2 -2
  429. package/src/release-loop/feature-store.ts +5 -3
  430. package/src/release-loop/next-md-merge.ts +58 -0
  431. package/src/release-loop/release-note.ts +59 -4
  432. package/src/seat-dispatch/seat-ask.ts +130 -0
  433. package/src/seat-dispatch/seat-questions.ts +100 -0
  434. package/src/seat-loop/seat-loop.ts +548 -29
  435. package/src/seat-loop/seat-report.ts +37 -2
  436. package/src/self-dev/dev-cli.ts +4 -1
  437. package/src/self-dev/dev-pipeline.ts +37 -1
  438. package/src/self-dev/draft-sweep.ts +38 -33
  439. package/src/self-dev/draft-triage-rules.ts +8 -5
  440. package/src/self-dev/fabric-plan-core.ts +297 -0
  441. package/src/self-dev/orchestrate.ts +36 -4
  442. package/src/self-dev/release-path-guard.ts +62 -0
  443. package/src/self-dev/shard-aggregate.ts +230 -0
  444. package/src/self-dev/shard-placement.ts +60 -0
  445. package/src/self-dev/shard-plan.ts +48 -0
  446. package/src/self-dev/shard-pod-run.ts +77 -0
  447. package/src/self-dev/shard-run.ts +105 -0
  448. package/src/self-implement/gate-baseline.ts +1 -1
  449. package/src/self-implement/gate-cli.ts +40 -1
  450. package/src/self-implement/gate-scope.ts +37 -7
  451. package/src/self-implement/graph-variant.ts +171 -0
  452. package/src/self-implement/harness-policy-gates.ts +1 -1
  453. package/src/self-implement/headless-elanous-driver.ts +22 -3
  454. package/src/self-implement/host-regate.ts +22 -1
  455. package/src/self-implement/importer-test-index.ts +2 -1
  456. package/src/self-implement/l8-merge-queue.ts +130 -0
  457. package/src/self-implement/orchestrator.ts +242 -9
  458. package/src/self-implement/route-consumer-test-index.ts +122 -0
  459. package/src/self-implement/seams.ts +72 -11
  460. package/src/self-implement/test-seams.ts +1 -0
  461. package/src/self-implement/uncommitted-work.ts +59 -0
  462. package/src/session/index.ts +36 -13
  463. package/src/skills/gift-install.ts +215 -0
  464. package/src/skills/tools/web-search.ts +4 -1
  465. package/src/steward/launch.ts +42 -26
  466. package/src/steward/steward-cards.ts +17 -9
  467. package/src/steward/triage.ts +46 -14
  468. package/src/task-cards/card-cli.ts +25 -1
  469. package/src/task-orchestrator/mission.ts +5 -0
  470. package/src/task-orchestrator/store.ts +12 -3
  471. package/src/task-orchestrator/surfaces/pod-command-job.ts +29 -7
  472. package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
  473. package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
  474. package/src/task-orchestrator/surfaces/self-implement-pod.ts +214 -40
  475. package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
  476. package/src/task-orchestrator/types.ts +2 -0
  477. package/src/telegram-card-followup.ts +16 -96
  478. package/src/telegram-commands.ts +10 -1
  479. package/src/telegram-project-command.ts +71 -0
  480. package/src/telegram-report.ts +21 -17
  481. package/src/telegram.ts +29 -3
  482. package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
  483. package/src/user-config.ts +102 -20
  484. package/src/version/packed-revision.json +1 -1
  485. package/src/web-search/grok.ts +7 -1
  486. package/src/web-search/index.ts +28 -1
  487. package/src/web-search/provider.ts +4 -0
  488. package/src/web-search/x-intent.ts +5 -0
  489. package/src/workflow-runtime/executor.ts +277 -47
  490. package/src/workflow-runtime/index.ts +1 -0
  491. package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
  492. package/src/workflow-runtime/plugin-kind-node.ts +1 -1
  493. package/src/workflow-runtime/schema.ts +79 -4
  494. package/src/workflow-runtime/types.ts +35 -4
  495. package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
  505. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
  506. package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
  525. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
  583. package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
  584. /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → Y4zKzL62sakG5momz3SoQ}/_ssgManifest.js +0 -0
@@ -1,8 +1,10 @@
1
1
  import { execFileSync } from 'node:child_process';
2
+ import { dlopen, FFIType } from 'bun:ffi';
2
3
  import { createHash } from 'node:crypto';
3
4
  import { existsSync, readFileSync } from 'node:fs';
4
5
  import { constants as osConstants } from 'node:os';
5
- import { resolve } from 'node:path';
6
+ import { resolve, sep } from 'node:path';
7
+ import { findGitDir } from '../git-fs/locate.js';
6
8
  import { LogStore, logsDbPath } from '../mss/logging/log-store.js';
7
9
  import { loadSelfDevRun } from '../self-dev/run-store.js';
8
10
  import { normalizeRunId } from './harness-space.js';
@@ -20,8 +22,10 @@ import { DevPipelineError } from '../self-dev/dev-pipeline.js';
20
22
  import { runDraftSweep, type DraftSweepAdapters, type DraftSweepResult, type SweepDraft, type SweepMergedPr } from '../self-dev/draft-sweep.js';
21
23
  import { debug } from '../debug/log.js';
22
24
  import { dispatchTask, type DispatchTaskInput, type DispatchTaskDeps } from '../execution-loop/dispatch-task.js';
25
+ import { launchRequestId, preLaunchGate, type PreLaunchGateDeps } from '../execution-loop/launch-gate.js';
23
26
  import { PR_LABELS } from '../github/pr-labels.js';
24
- import { decideBudget, readBudgetInputsLive, type BudgetDecision, type BudgetInputs } from '../self-implement/budget-gate.js';
27
+ import { CODEX_PROVIDER, GROK_PROVIDER, decideBudget, readBudgetInputsLive, type BudgetDecision, type BudgetInputs } from '../self-implement/budget-gate.js';
28
+ import { DEFAULT_FALLBACK_CHAIN } from '../oauth/fallback-chain.js';
25
29
  import { installDeliverableVerifyCliCommand, type InstallDeliverableVerifyCliDeps } from './deliverable-verify-cli.js';
26
30
  import { getUserConfig } from '../user-config.js';
27
31
  import { installHarnessCliSinkHook } from './harness-cli-sink.js';
@@ -92,6 +96,7 @@ export interface HarnessAskSayOptions {
92
96
  target?: string;
93
97
  yes?: boolean;
94
98
  forcePreflight?: boolean;
99
+ forceGate?: boolean;
95
100
  autoMerge?: boolean;
96
101
  mergeByHost?: boolean;
97
102
  observeOnly?: boolean;
@@ -249,12 +254,14 @@ function registerHarnessAskSayOptions(command: Command): Command {
249
254
  .option('--correlation <id>', '요청과 런을 잇는 불투명 correlation 값')
250
255
  .addOption(new Option('--goal-type <type>', `골 종류 (${GOAL_TYPES.join('|')})`).choices([...GOAL_TYPES]))
251
256
  .option('--force-preflight', '전제 검사 막힘을 명시 요청으로 우회(관측에 남음)')
257
+ .option('--force-gate', '같은 골 실행 중 막힘을 명시 요청으로 우회(관측에 남음; 예산 막힘은 우회 불가)')
252
258
  .option('--child-llm-provider <id>', 'self: 구현 자식 LLM provider(--child-llm-model과 함께)')
253
259
  .option('--child-llm-model <id>', 'self: 구현 자식 LLM model(--child-llm-provider와 함께)')
254
260
  .option('--child-llm-effort <level>', 'self: 구현 자식 추론 노력 minimal|low|medium|high|xhigh|max — 모델 상한을 넘으면 «거부»한다(--child-llm-provider와 함께)')
255
261
  .addOption(new Option('--substrate <kind>', '실행 칸 — local(설정 없을 때 기본 · 이 기계) | pod(k8s Pod · 같은 그래프가 원격에서 돈다)').choices(['local', 'pod']))
256
262
  .option('--pod-pool <spec>', 'pod: 풀 — 인자 > ELANOUS_POD_POOL > harness.podPool > 기존 pod.pool > 현재 컨텍스트')
257
- .addOption(new Option('--pod-memory <tier>', 'pod: 메모리 등급 — standard(16Gi) | high(32Gi) · 없으면 골 문면 `Pod 메모리: high` 줄 · 그것도 없으면 골이 apps/pwa/ 를 담을 때 high').choices(['standard', 'high']))
263
+ .addOption(new Option('--pod-memory <tier>', 'pod: 메모리 등급 — lite(2Gi · 문서·조사·네트워크 스킬 골 · OOM 이면 high 로 한 번 재시도) | standard(16Gi) | high(32Gi) · 없으면 골 문면 `Pod 메모리: <등급>` 한 줄 · 그것도 없으면 골이 apps/pwa/ 를 담을 때 high').choices(['lite', 'standard', 'high']))
264
+ .option('--after <goal-or-pr>', 'pod: 선행 — 이 골 ID(16자) 또는 PR(#N) 이 병합될 때까지 Pod 발사가 큐에서 이유와 함께 기다린다(병합 없이 닫히면 blocked) · 골 문면 `선행: #N` 한 줄과 같다 · 대상 파일만 겹치면 선행이 아니다(경고만)')
258
265
  .option('--source <spec>', 'pod: 원천 — commit:<40자 sha> | pr:<정수> | worktree:<경로> | files:<경로>[,<경로>…] · `--substrate pod` 와 함께');
259
266
  }
260
267
 
@@ -320,7 +327,7 @@ function assertHarnessChildLlmModel(opts: HarnessAskSayChildLlmOptions): void {
320
327
  }
321
328
 
322
329
  /** Shared post-parse gate: validate child model before any ask/say early return (including `--dry-run`). */
323
- type HarnessSubstrateOpts = { substrate?: 'local' | 'pod'; podPool?: string; podMemory?: string; autoMerge?: boolean; base?: string; json?: boolean; target?: string; source?: string };
330
+ type HarnessSubstrateOpts = { substrate?: 'local' | 'pod'; podPool?: string; podMemory?: string; after?: string; autoMerge?: boolean; base?: string; json?: boolean; target?: string; source?: string };
324
331
  function resolveLaunchSubstrate(opts: HarnessSubstrateOpts): ResolvedHarnessSubstrate {
325
332
  const resolved = resolveHarnessSubstrate({ flag: opts, config: getUserConfig(), env: process.env });
326
333
  debug.log('harness.substrate', 'resolved', resolved);
@@ -525,6 +532,11 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
525
532
  process.exitCode = 2;
526
533
  return;
527
534
  }
535
+ if (o.after !== undefined && !/^(?:#?[1-9]\d*|[a-f0-9]{16})$/.test(o.after.trim())) {
536
+ console.error(`--after 는 PR 번호(#N) 또는 골 ID(16자 16진수)여야 한다: ${o.after}`);
537
+ process.exitCode = 2;
538
+ return;
539
+ }
528
540
  warnRecentIncidentBurst();
529
541
  let dispatchRecorded = false;
530
542
  try {
@@ -544,7 +556,7 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
544
556
  const { dispatchHarnessOnPod } = await import('./harness-pod-dispatch.js');
545
557
  let output = '';
546
558
  let runId: string | undefined;
547
- const status = await dispatchHarnessOnPod({ entrance, input, podPool: pool, ...(dispatchRecorded ? { dispatchRecorded: true } : {}), ...(o.podMemory ? { podMemory: o.podMemory } : {}), ...(o.autoMerge === false ? { autoMerge: false } : {}), ...(o.base ? { base: o.base } : {}), ...(o.json ? { json: true } : {}), ...(o.source ? { source: o.source } : {}) },
559
+ const status = await dispatchHarnessOnPod({ entrance, input, podPool: pool, ...(dispatchRecorded ? { dispatchRecorded: true } : {}), ...(o.podMemory ? { podMemory: o.podMemory } : {}), ...(o.after ? { after: o.after } : {}), ...(o.autoMerge === false ? { autoMerge: false } : {}), ...(o.base ? { base: o.base } : {}), ...(o.json ? { json: true } : {}), ...(o.source ? { source: o.source } : {}) },
548
560
  { onOutput: (text) => {
549
561
  runId ??= harnessPodRunId(output + text);
550
562
  output = (output + text).slice(-16_000);
@@ -557,6 +569,52 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
557
569
  }
558
570
  }
559
571
 
572
+ const LAUNCH_BUDGET_PROVIDER: Readonly<Record<string, string>> = { 'codex-rotate': CODEX_PROVIDER, grok: GROK_PROVIDER };
573
+
574
+ /**
575
+ * L6 발사 관문의 예산 입력 보정 — 발사 우주의 config 에 체인이 없으면(작업 트리 = 시험 우주) 막지 않고
576
+ * 코드 기본 체인으로 판단한다. `--child-llm-provider` 를 명시했으면 그것이 체인이다(예산 판정 밖 provider 는 통과).
577
+ */
578
+ export function harnessLaunchBudgetDecision(
579
+ inputs: BudgetInputs,
580
+ opts: { readonly childLlmProvider?: string; readonly childLlmModel?: string } = {},
581
+ ): { readonly decision: BudgetDecision; readonly warning?: string } {
582
+ const explicit = opts.childLlmProvider?.trim();
583
+ if (explicit) {
584
+ if (explicit !== CODEX_PROVIDER && explicit !== GROK_PROVIDER) {
585
+ return {
586
+ decision: { action: 'proceed', provider: explicit, ...(opts.childLlmModel ? { model: opts.childLlmModel } : {}), reasons: [`${explicit}: 명시 provider — 예산 판정 밖`] },
587
+ warning: `budget: ${explicit} is outside the budget gate — launched as requested`,
588
+ };
589
+ }
590
+ const chain = [{ provider: explicit, ...(opts.childLlmModel ? { model: opts.childLlmModel } : {}) }];
591
+ return { decision: decideBudget({ ...inputs, preference: { ...inputs.preference, chain } }) };
592
+ }
593
+ if (inputs.preference.chain.length > 0) return { decision: decideBudget(inputs) };
594
+ const chain = DEFAULT_FALLBACK_CHAIN.map((step) => ({ provider: LAUNCH_BUDGET_PROVIDER[step] ?? step }));
595
+ return {
596
+ decision: decideBudget({ ...inputs, preference: { ...inputs.preference, chain } }),
597
+ warning: `budget: no chain in this universe's config — judged with the code default ${DEFAULT_FALLBACK_CHAIN.join(',')}`,
598
+ };
599
+ }
600
+
601
+ async function readHarnessLaunchBudget(
602
+ opts: { readonly childLlmProvider?: string; readonly childLlmModel?: string } = {},
603
+ ): Promise<BudgetDecision | 'unknown'> {
604
+ try {
605
+ const { decision, warning } = harnessLaunchBudgetDecision(await readBudgetInputsLive(), opts);
606
+ if (warning) {
607
+ console.error(`⚠️ launch gate: ${warning}`);
608
+ try { debug.log('execution-loop.launch-gate', 'budget-chain-defaulted', { warning, action: decision.action, provider: decision.provider }); } catch { /* observation is fail-soft */ }
609
+ }
610
+ return decision;
611
+ }
612
+ catch (error) {
613
+ try { debug.log('execution-loop.launch-gate', 'budget-unavailable', { reason: String(error) }); } catch { /* observation is fail-soft */ }
614
+ return 'unknown';
615
+ }
616
+ }
617
+
560
618
  async function dispatchHarnessAskSay(
561
619
  opts: HarnessAskSayChildLlmOptions & HarnessDryRunOpts,
562
620
  dryRunPreview: {
@@ -566,6 +624,7 @@ async function dispatchHarnessAskSay(
566
624
  readonly goalPath?: string;
567
625
  },
568
626
  dispatch: (resolved: ResolvedHarnessSubstrate) => Promise<void>,
627
+ gate: PreLaunchGateDeps & { readBudget?: () => Promise<BudgetDecision | 'unknown'> } = {},
569
628
  ): Promise<void> {
570
629
  await runInjectedHarnessHandler(async () => {
571
630
  assertHarnessChildLlmModel(opts);
@@ -574,6 +633,35 @@ async function dispatchHarnessAskSay(
574
633
  printHarnessLaunchDryRun(dryRunPreview);
575
634
  return;
576
635
  }
636
+ // Without a GoalId, match the request to a live run's exact verbatim original ask; still check budget.
637
+ let identity = dryRunPreview.input;
638
+ let goalId: string | null = null;
639
+ if (dryRunPreview.goalPath) {
640
+ try {
641
+ identity = readFileSync(dryRunPreview.goalPath, 'utf8');
642
+ goalId = parseGoalId(identity);
643
+ } catch { /* The launch handler owns file-read errors. */ }
644
+ }
645
+ goalId ??= launchRequestId(identity);
646
+ // Under bun test with no injected gate deps, skip the live reads (≈5 s of codex rotation + run scans) —
647
+ // CLI wiring tests time out on them. Gate tests inject deps and still run the gate (0.2.11 gate 10-03).
648
+ if (process.env.NODE_ENV === 'test' && Object.keys(gate).length === 0) {
649
+ try { debug.log('execution-loop.launch-gate', 'skipped-test-env', { goalId }); } catch { /* observation is fail-soft */ }
650
+ await dispatch(resolved);
651
+ return;
652
+ }
653
+ const budget = await (gate.readBudget ?? (() => readHarnessLaunchBudget(opts)))();
654
+ const decision = preLaunchGate({ goalId, budget, forceLaunch: opts.forceGate === true }, gate);
655
+ if (decision.action !== 'proceed') {
656
+ console.error(`❌ launch gate: ${decision.action} — ${decision.reason.split(/\r?\n/, 1)[0]}`);
657
+ process.exitCode = 3;
658
+ return;
659
+ }
660
+ const warnings = [
661
+ ...(decision.sameGoalActiveRuns === 'unknown' ? ['active runs unknown'] : []),
662
+ ...(decision.budget === 'unknown' ? ['budget unknown'] : decision.budget.action === 'next-provider' ? [decision.budget.reasons.join(' · ') || 'next-provider'] : []),
663
+ ];
664
+ if (warnings.length > 0) console.error(`⚠️ launch gate: ${warnings.join(' · ').split(/\r?\n/, 1)[0]}`);
577
665
  await dispatch(resolved);
578
666
  });
579
667
  }
@@ -707,6 +795,8 @@ export const HARNESS_PROCESS_LAST_ACTIVITY_SCOPE_LINE =
707
795
 
708
796
  export interface HarnessProcessLedgerEntry {
709
797
  readonly timestamp?: string;
798
+ readonly event?: string;
799
+ readonly data?: Record<string, unknown>;
710
800
  }
711
801
 
712
802
  export type HarnessProcessLedgerLookup = (
@@ -741,6 +831,9 @@ export interface HarnessProcessObservationDeps {
741
831
  listWorktrees?: () => HarnessWorktreeListObservation | readonly string[];
742
832
  observeLaunchdPids?: () => HarnessLaunchdPidObservation;
743
833
  lookupLedger?: HarnessProcessLedgerLookup;
834
+ openProcessHandle?: (pid: number) => HarnessProcessSignalHandle;
835
+ readStartTime?: (pid: number) => string;
836
+ repositoryRoot?: string;
744
837
  nowMs?: number;
745
838
  thresholds?: HarnessProcessClassificationThresholds;
746
839
  write?: (text: string) => void;
@@ -1714,6 +1807,140 @@ function installHarnessBudgetCommand(harnessCmd: Command): Command {
1714
1807
  });
1715
1808
  }
1716
1809
 
1810
+ export interface HarnessProcessSignalHandle {
1811
+ signal(signal: NodeJS.Signals): void;
1812
+ close(): void;
1813
+ }
1814
+
1815
+ // macOS has no pidfd: bind to the process by its microsecond start time (libproc PROC_PIDTBSDINFO) and
1816
+ // re-read it immediately before signalling — a reused pid within the same microsecond is not distinguishable, anything else is.
1817
+ function readDarwinStartMicros(pid: number): bigint | null {
1818
+ const libproc = dlopen('/usr/lib/libproc.dylib', {
1819
+ proc_pidinfo: { args: [FFIType.i32, FFIType.i32, FFIType.u64, FFIType.ptr, FFIType.i32], returns: FFIType.i32 },
1820
+ });
1821
+ try {
1822
+ const buf = new Uint8Array(136); // sizeof(struct proc_bsdinfo)
1823
+ const n = libproc.symbols.proc_pidinfo(pid, 3 /* PROC_PIDTBSDINFO */, 0n, buf, buf.length);
1824
+ if (n !== buf.length) return null;
1825
+ const view = new DataView(buf.buffer);
1826
+ if (view.getUint32(12, true) !== pid) return null; // pbi_pid
1827
+ return view.getBigUint64(120, true) * 1_000_000n + view.getBigUint64(128, true); // pbi_start_tvsec · pbi_start_tvusec
1828
+ } finally { libproc.close(); }
1829
+ }
1830
+
1831
+ function openDarwinProcessHandle(pid: number): HarnessProcessSignalHandle {
1832
+ const start = readDarwinStartMicros(pid);
1833
+ if (start === null) throw new Error('proc_pidinfo failed');
1834
+ let closed = false;
1835
+ return {
1836
+ signal(signal) {
1837
+ if (closed) throw new Error('process handle already closed');
1838
+ if (signal !== 'SIGTERM') throw new Error('only SIGTERM is supported');
1839
+ if (readDarwinStartMicros(pid) !== start) throw new Error('pid no longer names the same process');
1840
+ process.kill(pid, 'SIGTERM');
1841
+ },
1842
+ close() { closed = true; },
1843
+ };
1844
+ }
1845
+
1846
+ export function openHarnessProcessHandle(pid: number): HarnessProcessSignalHandle {
1847
+ if (process.platform === 'darwin') return openDarwinProcessHandle(pid);
1848
+ if (process.platform !== 'linux' || !['x64', 'arm64'].includes(process.arch)) {
1849
+ throw new Error('pid-bound signaling unavailable on this platform');
1850
+ }
1851
+ const libc = dlopen('libc.so.6', {
1852
+ syscall: { args: [FFIType.i64, FFIType.i64, FFIType.i64, FFIType.i64, FFIType.i64], returns: FFIType.i64 },
1853
+ close: { args: [FFIType.i32], returns: FFIType.i32 },
1854
+ });
1855
+ const fd = Number(libc.symbols.syscall(434, pid, 0, 0, 0)); // pidfd_open
1856
+ if (fd < 0) {
1857
+ libc.close();
1858
+ throw new Error('pidfd_open failed');
1859
+ }
1860
+ let closed = false;
1861
+ return {
1862
+ signal(signal) {
1863
+ if (closed) throw new Error('pidfd already closed');
1864
+ if (signal !== 'SIGTERM' || libc.symbols.syscall(424, fd, osConstants.signals.SIGTERM, 0, 0) !== 0n) {
1865
+ throw new Error('pidfd_send_signal failed');
1866
+ }
1867
+ },
1868
+ close() {
1869
+ if (closed) return;
1870
+ closed = true;
1871
+ libc.symbols.close(fd);
1872
+ libc.close();
1873
+ },
1874
+ };
1875
+ }
1876
+
1877
+ export function killHarnessProcess(
1878
+ pid: number,
1879
+ force: boolean,
1880
+ deps: HarnessProcessObservationDeps = {},
1881
+ ): { outcome: 'sent' | 'refused'; owned: boolean; runState: string; reason: string } {
1882
+ const refuse = (reason: string, owned = false, runState = 'unknown') => ({ outcome: 'refused' as const, owned, runState, reason });
1883
+ let result: ReturnType<typeof refuse> | { outcome: 'sent'; owned: true; runState: string; reason: string };
1884
+ let handle: HarnessProcessSignalHandle | undefined;
1885
+ let handleFailure: string | undefined;
1886
+ if (Number.isSafeInteger(pid) && pid > 1) {
1887
+ try { handle = (deps.openProcessHandle ?? openHarnessProcessHandle)(pid); }
1888
+ catch (error) { handleFailure = observationFailureReason(error); }
1889
+ }
1890
+ try {
1891
+ const root = deps.repositoryRoot ?? findGitDir(process.cwd())?.root;
1892
+ const listed = normalizeProcessListObservation(deps.listProcesses?.() ?? defaultListHarnessProcesses());
1893
+ const row = listed.status === 'ok' ? listed.records.find((record) => record.pid === pid) : undefined;
1894
+ const prefix = root ? `${resolve(root)}${sep}` : '';
1895
+ const entry = prefix ? `${prefix}bin/elanous.mjs` : '';
1896
+ const argv = row?.command ?? '';
1897
+ const entryIndex = entry && [
1898
+ `bun ${entry} `, `${process.execPath} ${entry} `,
1899
+ `bun bin/elanous.mjs `,
1900
+ ].find((start) => argv.startsWith(start));
1901
+ const fromRepo = Boolean(entryIndex && (entryIndex !== 'bun bin/elanous.mjs ' || row?.cwd && resolve(row.cwd) === resolve(root!)));
1902
+ if (!Number.isSafeInteger(pid) || pid <= 1) result = refuse('invalid pid');
1903
+ else if (listed.status !== 'ok') result = refuse('process observation incomplete');
1904
+ else if (!row) result = refuse('pid not found in harness process population');
1905
+ else if (!fromRepo || !/\belanous\.mjs\s+(?:(?:--test|--config-dir\s+\S+)\s+)?(?:self\s+(?:orchestrate|implement)|harness\s+(?:ask|say))\b/.test(row.command)) result = refuse('not a harness process from this repository');
1906
+ else if (!handle) result = refuse(`pid-bound signaling unavailable: ${handleFailure ?? 'unknown failure'}`);
1907
+ else {
1908
+ let startTime: string | undefined;
1909
+ try {
1910
+ startTime = (deps.readStartTime ?? ((target) => execFileSync('ps', ['-p', String(target), '-o', 'lstart='], { encoding: 'utf8', timeout: 2_000 }).trim()))(pid);
1911
+ } catch { /* unavailable is not a timestamp */ }
1912
+ if (!startTime || !Number.isFinite(Date.parse(startTime))) result = refuse('process start time unreadable');
1913
+ else {
1914
+ const ownership = row.ownership ?? readProcessOwnership(pid);
1915
+ const runId = ownership.status === 'observed' ? ownership.runId : undefined;
1916
+ if (!runId) result = refuse('owning run unconfirmed');
1917
+ else {
1918
+ let ledger: readonly HarnessProcessLedgerEntry[] | null = null;
1919
+ try { ledger = (deps.lookupLedger ?? defaultLookupHarnessProcessLedger)(runId, ownership.status === 'observed' ? ownership.stateDir : undefined); }
1920
+ catch { /* fail closed */ }
1921
+ const last = [...(ledger ?? [])].reverse().find((entry) => entry.event === 'run-status');
1922
+ const runState = typeof last?.data?.runStatus === 'string' ? last.data.runStatus : 'unknown';
1923
+ if (!ledger || !last) result = refuse('owning run ledger unavailable', true, runState);
1924
+ else if (!['running', 'completed', 'failed', 'cancelled', 'abandoned'].includes(runState)) result = refuse('owning run status unconfirmed', true, runState);
1925
+ else if (runState === 'running' && !force) result = refuse('owning run is not terminal (use --force)', true, runState);
1926
+ else {
1927
+ try {
1928
+ const currentStart = (deps.readStartTime ?? ((target) => execFileSync('ps', ['-p', String(target), '-o', 'lstart='], { encoding: 'utf8', timeout: 2_000 }).trim()))(pid);
1929
+ if (currentStart !== startTime) result = refuse('pid start time changed', true, runState);
1930
+ else {
1931
+ handle.signal('SIGTERM');
1932
+ result = { outcome: 'sent', owned: true, runState, reason: 'SIGTERM sent' };
1933
+ }
1934
+ } catch (error) { result = refuse(`SIGTERM failed: ${observationFailureReason(error)}`, true, runState); }
1935
+ }
1936
+ }
1937
+ }
1938
+ }
1939
+ debug.log('harness.processes', 'kill', { pid, ...result });
1940
+ return result;
1941
+ } finally { handle?.close(); }
1942
+ }
1943
+
1717
1944
  function installHarnessProcessObservationCommand(
1718
1945
  harnessCmd: Command,
1719
1946
  deps: HarnessProcessObservationDeps = {},
@@ -1721,8 +1948,18 @@ function installHarnessProcessObservationCommand(
1721
1948
  const write = deps.write ?? ((text: string) => { console.log(text); });
1722
1949
  return harnessCmd
1723
1950
  .command('processes')
1724
- .description('이 저장소가 띄운 OS 프로세스를 읽기 전용으로 분류한다. 자원을 먹는 무리와 오래 떠 있는 무리를 가른다. 죽이지 않는다.')
1725
- .action(() => {
1951
+ .description('기본 읽기 전용 분류. --kill <pid> 는 소유 런 확인 후 단일 PID 에만 SIGTERM 한다.')
1952
+ .option('--kill <pid>', '소유 런을 확인한 뒤 지정한 PID 하나만 SIGTERM')
1953
+ .option('--force', '소유 런이 진행 중이어도 지정한 PID 하나를 종료')
1954
+ .action((opts: { kill?: string; force?: boolean }) => {
1955
+ if (opts.kill !== undefined) {
1956
+ const pid = Number(opts.kill);
1957
+ const result = killHarnessProcess(pid, opts.force === true, deps);
1958
+ write(`pid=${opts.kill} ${result.outcome}: ${result.reason}`);
1959
+ if (result.outcome === 'refused') process.exitCode = 1;
1960
+ return;
1961
+ }
1962
+ if (opts.force) { write('--force requires --kill <pid>'); process.exitCode = 2; return; }
1726
1963
  const records = deps.listProcesses?.() ?? defaultListHarnessProcesses();
1727
1964
  const worktrees = deps.listWorktrees?.() ?? defaultListHarnessWorktreePaths();
1728
1965
  const launchd = deps.observeLaunchdPids?.() ?? observeHarnessLaunchdPids();
@@ -1749,6 +1986,7 @@ export interface HarnessCliCommandDeps {
1749
1986
  say?: HarnessSayHandler;
1750
1987
  /** Observe-only Pod host dispatch seam. */
1751
1988
  podDispatchTask?: (input: DispatchTaskInput, deps?: DispatchTaskDeps) => ReturnType<typeof dispatchTask>;
1989
+ launchGate?: PreLaunchGateDeps & { readBudget?: () => Promise<BudgetDecision | 'unknown'> };
1752
1990
  plan?: HarnessPlanHandler;
1753
1991
  /** ⭐ `plan` 주입이 «없을 때» 가는 기본 분기. 시험이 이 자리로 «CLI 의 기본 배선»을 문다
1754
1992
  * (⛔ 주입된 `plan` 이 파일을 스스로 만들면 그 시험은 배선을 «못 답한다» — 무인 리뷰 GOODHART 지적). */
@@ -1819,6 +2057,7 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
1819
2057
  }
1820
2058
  return resolved.substrate === 'pod' ? onPod(opts, 'cli-harness-ask', goalPath, resolved.pool!, deps.podDispatchTask) : ask(goalPath, normalizeHarnessAskSayOptions(opts));
1821
2059
  },
2060
+ deps.launchGate,
1822
2061
  );
1823
2062
  });
1824
2063
  }
@@ -1843,6 +2082,7 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
1843
2082
  }
1844
2083
  return resolved.substrate === 'pod' ? onPod(opts, 'cli-harness-say', sentence.join(' '), resolved.pool!, deps.podDispatchTask) : say(sentence, normalizeHarnessAskSayOptions(opts));
1845
2084
  },
2085
+ deps.launchGate,
1846
2086
  );
1847
2087
  });
1848
2088
  }
@@ -7,8 +7,9 @@
7
7
  * 매니페스트가 실은 런 계약(`ELANOUS_RUN_CONTRACT`)으로 자기가 Pod 인 줄 안다(graph-run-contract.ts).
8
8
  */
9
9
  import { spawn } from 'node:child_process';
10
- import { readFileSync, realpathSync } from 'node:fs';
11
- import { isAbsolute, relative, resolve, sep } from 'node:path';
10
+ import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
11
+ import { isAbsolute, join, relative, resolve, sep } from 'node:path';
12
+ import { selfDevRunsDir } from '../self-dev/run-store.js';
12
13
  import { findGitDir } from '../git-fs/locate.js';
13
14
  import { debug } from '../debug/log.js';
14
15
  import { ELANOUS_ENTRY_SCRIPT } from '../self-implement/seams.js';
@@ -23,6 +24,8 @@ export interface HarnessPodDispatchInput {
23
24
  readonly dispatchRecorded?: boolean;
24
25
  /** Pod 메모리 등급(standard|high) — 오케스트레이터 환경 `ELANOUS_POD_MEMORY_TIER` 로 Job 까지 간다. */
25
26
  readonly podMemory?: string;
27
+ /** L7c — Pod queue predecessor (goal ID or PR) — `ELANOUS_POD_AFTER` carries it to every Pod Job admission. */
28
+ readonly after?: string;
26
29
  readonly autoMerge?: boolean;
27
30
  readonly base?: string;
28
31
  readonly json?: boolean;
@@ -30,16 +33,9 @@ export interface HarnessPodDispatchInput {
30
33
  readonly source?: string;
31
34
  }
32
35
 
33
- /** 오케스트레이터가 `;;` 로 골을 나누므로 한 골 안의 `;;` 는 풀어 둔다(한 발 = 한 골). */
34
- export function podGoalText(input: HarnessPodDispatchInput, readFile: (path: string) => string = (p) => readFileSync(p, 'utf8')): string {
35
- // 오케스트레이터에는 내용도 보내고, 저장소 안의 ask 는 별도로 Secret 을 통해 Pod 클론에 심는다.
36
- const text = input.entrance === 'cli-harness-ask' ? readFile(input.input) : input.input;
37
- return text.replace(/;;/gu, '; ;');
38
- }
39
-
40
- export function podOrchestrateArgs(input: HarnessPodDispatchInput, goal: string): string[] {
36
+ export function podOrchestrateArgs(input: HarnessPodDispatchInput, goalFile: string): string[] {
41
37
  return [
42
- ELANOUS_ENTRY_SCRIPT, 'self', 'orchestrate', goal,
38
+ ELANOUS_ENTRY_SCRIPT, 'self', 'orchestrate', '--goal-file', goalFile,
43
39
  '--substrate', 'pod',
44
40
  ...(input.podPool ? ['--pod-pool', input.podPool] : []),
45
41
  // 하니스 기본(자동 병합)을 따른다 · 끄면 PR 까지 — 어느 쪽이든 Pod 가 사라져도 결과가 남는다.
@@ -66,13 +62,30 @@ export function dispatchHarnessOnPod(input: HarnessPodDispatchInput, deps: PodDi
66
62
  return 2;
67
63
  }
68
64
  }
69
- const goal = podGoalText(input, deps.readFile ?? ((p) => readFileSync(resolve(cwd, p), 'utf8')));
70
- const args = podOrchestrateArgs(input, goal);
65
+ let tempDir: string | undefined;
66
+ let goalFile: string;
67
+ let goalChars: number;
68
+ if (input.entrance === 'cli-harness-ask') {
69
+ goalFile = resolve(cwd, input.input);
70
+ goalChars = (deps.readFile ?? ((p) => readFileSync(p, 'utf8')))(goalFile).length;
71
+ } else {
72
+ const goal = input.input;
73
+ const runsDir = selfDevRunsDir();
74
+ mkdirSync(runsDir, { recursive: true });
75
+ tempDir = mkdtempSync(join(runsDir, 'pod-goal-'));
76
+ goalFile = join(tempDir, 'goal.txt');
77
+ writeFileSync(goalFile, goal, { mode: 0o600 });
78
+ goalChars = goal.length;
79
+ }
80
+ const args = podOrchestrateArgs(input, goalFile);
81
+ debug.log('harness.substrate', 'goal-file', { entrance: input.entrance, mode: tempDir ? 'temp' : 'path' });
71
82
  const env = { ...process.env };
72
83
  delete env.ELANOUS_POD_GOAL_DOC;
73
84
  delete env.ELANOUS_DISPATCH_RECORDED;
74
85
  if (input.dispatchRecorded) env.ELANOUS_DISPATCH_RECORDED = '1';
75
86
  if (input.podMemory) env.ELANOUS_POD_MEMORY_TIER = input.podMemory;
87
+ delete env.ELANOUS_POD_AFTER;
88
+ if (input.after) env.ELANOUS_POD_AFTER = input.after;
76
89
  if (input.entrance === 'cli-harness-ask') {
77
90
  const root = findGitDir(cwd)?.root;
78
91
  const path = resolve(cwd, input.input);
@@ -84,8 +97,8 @@ export function dispatchHarnessOnPod(input: HarnessPodDispatchInput, deps: PodDi
84
97
  }
85
98
  }
86
99
  debug.log('harness.substrate', 'dispatch-pod', {
87
- entrance: input.entrance, podPool: input.podPool ?? null, podMemory: input.podMemory ?? null, autoMerge: input.autoMerge !== false,
88
- goalChars: goal.length, ...(input.entrance === 'cli-harness-ask' ? { goalPath: input.input } : {}),
100
+ entrance: input.entrance, podPool: input.podPool ?? null, podMemory: input.podMemory ?? null, after: input.after ?? null, autoMerge: input.autoMerge !== false,
101
+ goalChars, ...(input.entrance === 'cli-harness-ask' ? { goalPath: input.input } : {}),
89
102
  });
90
103
  const run = deps.run ?? ((cmd: string, a: readonly string[], childEnv: NodeJS.ProcessEnv) => new Promise<number>((resolveStatus) => {
91
104
  const child = (deps.spawnChild ?? spawn)(cmd, [...a], { stdio: deps.onOutput ? ['inherit', 'pipe', 'inherit'] : 'inherit', env: childEnv });
@@ -104,13 +117,20 @@ export function dispatchHarnessOnPod(input: HarnessPodDispatchInput, deps: PodDi
104
117
  child.once('error', () => { cleanup(); resolveStatus(1); });
105
118
  child.once('close', (code, signal) => { cleanup(); resolveStatus(code ?? ((signal ?? forwarded) === 'SIGINT' ? 130 : 143)); });
106
119
  }));
107
- const status = run(process.execPath, args, env);
108
- if (typeof status === 'number' || status === null) {
109
- debug.log('harness.substrate', 'dispatch-pod-exit', { entrance: input.entrance, status });
110
- return status ?? 1;
120
+ const cleanup = () => { if (tempDir) rmSync(tempDir, { recursive: true, force: true }); };
121
+ try {
122
+ const status = run(process.execPath, args, env);
123
+ if (typeof status === 'number' || status === null) {
124
+ cleanup();
125
+ debug.log('harness.substrate', 'dispatch-pod-exit', { entrance: input.entrance, status });
126
+ return status ?? 1;
127
+ }
128
+ return status.then((code) => {
129
+ debug.log('harness.substrate', 'dispatch-pod-exit', { entrance: input.entrance, status: code });
130
+ return code;
131
+ }).finally(cleanup);
132
+ } catch (error) {
133
+ cleanup();
134
+ throw error;
111
135
  }
112
- return status.then((code) => {
113
- debug.log('harness.substrate', 'dispatch-pod-exit', { entrance: input.entrance, status: code });
114
- return code;
115
- });
116
136
  }
@@ -23,6 +23,7 @@ import { buildReviewSeam, gateEvidenceNote, reviewResultToCritiqueLike, type Gat
23
23
  import { buildExecuteProgressJudge } from './execute-progress-judge.js';
24
24
  import type { StagedHarnessSeams } from './staged-harness.js';
25
25
  import { debug } from '../debug/log.js';
26
+ import { releasePathHold, releasePathHoldComment, RELEASE_PATH_LABEL } from '../self-dev/release-path-guard.js';
26
27
  import { setEventLoopActivity } from '../debug/event-loop-watchdog.js';
27
28
  import { nestInfo } from '../agent/nest-depth.js';
28
29
  import { originObservationFields } from '../agent/origin-observation.js';
@@ -721,10 +722,43 @@ export function buildHarnessSeams(deps: HarnessSeamsDeps): StagedHarnessSeams {
721
722
  suppressedRiskHits: eligibility?.suppressedRiskHits.length ?? 0,
722
723
  ...(declineReasons ? { reasons: declineReasons } : {}),
723
724
  });
724
- const pr = await deps.seams.openPr({ title, body, head: branch, ...(deps.base ? { base: deps.base } : {}), draft: true, ...(labels ? { labels } : {}), cwd });
725
- // ★ 리뷰 반영(#5338) — 라벨 관측은 openPr 성공 후 PR 번호와 함께(생성 실패 시 거짓 운영 증거 방지).
726
- if (labels) observe('auto-review-labeled', { branch, number: pr.number, label: AUTO_REVIEW_LABEL });
727
- observe('deployed-pr', { number: pr.number, url: pr.url, autoReview: !!labels });
725
+ const pr = await deps.seams.openPr({ title, body, head: branch, ...(deps.base ? { base: deps.base } : {}), draft: true, cwd });
726
+ let holdPath: string | undefined;
727
+ let inspectionError: string | undefined;
728
+ try {
729
+ if (!deps.seams.readPrFiles) throw new Error('readPrFiles seam unavailable');
730
+ const prFiles = await deps.seams.readPrFiles({ number: pr.number, cwd });
731
+ if (!Array.isArray(prFiles) || !prFiles.every((path) => typeof path === 'string')) throw new Error('invalid PR file list');
732
+ holdPath = releasePathHold(prFiles);
733
+ } catch (error) { inspectionError = String(error); }
734
+ if (holdPath) {
735
+ const protectedPath = holdPath;
736
+ const prCwd = cwd;
737
+ debug.log('self-dev.merge', 'release-path-hold', { number: pr.number, path: protectedPath, label: RELEASE_PATH_LABEL });
738
+ for (const [action, annotate] of [
739
+ ['add-label', deps.seams.addPrLabel && (() => deps.seams.addPrLabel!({ number: pr.number, label: RELEASE_PATH_LABEL, cwd: prCwd }))],
740
+ ['comment', deps.seams.postPrComment && (() => deps.seams.postPrComment!({ number: pr.number, body: releasePathHoldComment(protectedPath), cwd: prCwd }))],
741
+ ] as const) {
742
+ if (!annotate) { observe('release-path-annotation-failed', { number: pr.number, action, error: 'annotation seam unavailable' }); continue; }
743
+ try { await annotate(); } catch (error) { observe('release-path-annotation-failed', { number: pr.number, action, error: String(error) }); }
744
+ }
745
+ observe('deployed-pr', { number: pr.number, url: pr.url, autoReview: false, mergeReason: 'release-path-hold' });
746
+ } else if (inspectionError) {
747
+ observe('release-path-inspection-failed', { number: pr.number, error: inspectionError });
748
+ observe('deployed-pr', { number: pr.number, url: pr.url, autoReview: false, mergeReason: 'release-path-inspection-failed' });
749
+ } else {
750
+ let autoReviewLabeled = false;
751
+ if (labels?.includes(AUTO_REVIEW_LABEL)) {
752
+ if (deps.seams.addPrLabel) {
753
+ try {
754
+ await deps.seams.addPrLabel({ number: pr.number, label: AUTO_REVIEW_LABEL, cwd });
755
+ autoReviewLabeled = true;
756
+ observe('auto-review-labeled', { branch, number: pr.number, label: AUTO_REVIEW_LABEL });
757
+ } catch (error) { observe('auto-review-label-failed', { number: pr.number, error: String(error) }); }
758
+ } else observe('auto-review-label-failed', { number: pr.number, error: 'addPrLabel seam unavailable' });
759
+ }
760
+ observe('deployed-pr', { number: pr.number, url: pr.url, autoReview: autoReviewLabeled });
761
+ }
728
762
  // B(대표 2026-07-21): post-PR 자율 리뷰 — 리뷰기가 PR 에 커멘트(fail-soft). 게이트가 놓친 품질 블로커 표면화.
729
763
  await postPrReview(cwd, pr.number, objective, deps.llmReview, deps.spawnSyncFn ?? spawnSync, deps.goalDocument);
730
764
  return { ok: true, ref: pr.url, kind: 'pr' };
@@ -14,6 +14,7 @@ import { isAbsolute, join, resolve } from 'node:path';
14
14
  import { spawnSync } from 'node:child_process';
15
15
  import { debug } from '../debug/log.js';
16
16
  import { selfDevRunsDir } from '../self-dev/run-store.js';
17
+ import { launchBindingRunIds, launchRegistryDir, readLaunchBinding } from './launch-registry.js';
17
18
  import { loadRunLedger, resolveFederatedRunLedgerDirectories, runLedgerDir } from '../self-implement/run-ledger.js';
18
19
 
19
20
  const RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
@@ -173,6 +174,16 @@ export function readPidRecordFrom(runsDir: string, runId: string): PidRecord | n
173
174
  }
174
175
  }
175
176
 
177
+ /** The launching universe's pid.json when the binding names it, else the binding's own pid — both still pass the start-time check. */
178
+ export function pidRecordFromLaunchBinding(runId: string, registryDir = launchRegistryDir()): PidRecord | null {
179
+ const binding = readLaunchBinding(runId, registryDir);
180
+ if (!binding) return null;
181
+ const fromRunsDir = binding.runsDir ? readPidRecordFrom(binding.runsDir, runId) : null;
182
+ if (fromRunsDir) return fromRunsDir;
183
+ debug.log('harness.stop', 'pid-from-launch-binding', { runId, pid: binding.pid });
184
+ return { pid: binding.pid, startedAt: binding.startedAt, ...(binding.argv0 ? { argv0: binding.argv0 } : {}) };
185
+ }
186
+
176
187
  /** macOS·Linux 공통 — `ps -o lstart=` 는 로컬 시각 문자열(초 단위)이다. */
177
188
  export function psProcessStartMs(pid: number): number | null {
178
189
  const r = spawnSync('ps', ['-o', 'lstart=', '-p', String(pid)], { encoding: 'utf8', timeout: 5_000 });
@@ -183,7 +194,8 @@ export function psProcessStartMs(pid: number): number | null {
183
194
  return Number.isFinite(ms) ? ms : null;
184
195
  }
185
196
 
186
- export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {}): HarnessStopDeps {
197
+ export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {}, opts: { launchRegistryDir?: string } = {}): HarnessStopDeps {
198
+ const registry = opts.launchRegistryDir ?? launchRegistryDir();
187
199
  const env = { ...process.env };
188
200
  for (const key of ['HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy', 'ALL_PROXY', 'all_proxy']) delete env[key];
189
201
  const kubectl = (args: readonly string[]) => {
@@ -191,12 +203,19 @@ export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {})
191
203
  return { status: r.status, stdout: r.stdout ?? '', stderr: r.stderr ?? String(r.error ?? '') };
192
204
  };
193
205
  return {
194
- readPidRecord: (runId) => readPidRecordFrom(selfDevRunsDir(), runId),
206
+ // This universe first; then the host-wide launch binding, so a run launched from another worktree is still found.
207
+ readPidRecord: (runId) => readPidRecordFrom(selfDevRunsDir(), runId) ?? pidRecordFromLaunchBinding(runId, registry),
195
208
  runIdCandidates: (given) => {
196
209
  const ledgerDirs = new Set([runLedgerDir(), ...resolveFederatedRunLedgerDirectories({})]);
197
- return stopRunIdCandidates(given, [...ledgerDirs], selfDevRunsDir());
210
+ const found = new Set(stopRunIdCandidates(given, [...ledgerDirs], selfDevRunsDir()));
211
+ for (const id of launchBindingRunIds(registry)) if (id.startsWith(given) && FULL_RUN_ID.test(id)) found.add(id);
212
+ return [...found].sort();
213
+ },
214
+ readGoalPath: (runId) => {
215
+ let fromLedger: string | null = null;
216
+ try { fromLedger = stopGoalPathFromLedger(runId); } catch { fromLedger = null; }
217
+ return fromLedger ?? readLaunchBinding(runId, registry)?.goalPath ?? null;
198
218
  },
199
- readGoalPath: stopGoalPathFromLedger,
200
219
  scanProcesses: scanStopProcessTable,
201
220
  processStartMs: psProcessStartMs,
202
221
  kill: (pid, signal) => { process.kill(pid, signal); },