elanous 0.2.10 → 0.2.12

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 (615) 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/-6XrAoD3eU7NyMHAE4xPS/_buildManifest.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/1147-466ec15afacc1a65.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1394-ee3795b112907122.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
  8. package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/3869-3cd46526879f454c.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
  18. package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
  19. package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
  24. package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/7277-0b2fc7c16ba2d64b.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/7758-0b018a9e4fc56200.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8605-0259994816604c49.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
  47. package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/9920-5cfdc5e8fd209825.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-cb169620945d1952.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cefe8169e36cf62a.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/board/page-d2e35228bc497119.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-5c05b0da4bc1392c.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/app/bots/page-e0ccdb576812b523.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/chat/page-813c4a52c9d05ca8.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/consult/page-4731f2c215358937.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/control/page-a022b257950f39e6.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/design-check/page-a2ffc717e04b8b0a.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/editor/page-b59ee4e70fc18fcf.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/exec/page-a67e11ba962337b5.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/field/page-c172dabd796eb7a3.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-1efd0cb9e0ed9d13.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/intake/page-d5dc7ff69a37b4cf.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/layout-e71c84189e8c683e.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/live/page-1d6a533ce5a6efcb.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/market/page-dfca9b7d2de0b135.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-793fa536b3a6ef37.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/morning/page-6dd3bfbbde2a5c2c.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/not-found-490653e8d4cc8852.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/observatory/page-77447356baad75d2.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-29e961191f6057df.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-c822f55b884d9104.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fa4ccfc432424e52.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/outputs/page-6d604227e1664b71.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/page-9c7e8f744a765daf.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/reflection/page-4048543b4b7ad5e0.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-4c3a3126abed551a.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/sessions/page-64b0aecb1ca75e75.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4292d0149020e8a7.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/settings/page-db14d0be7f1c460c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-e5d8072cd7cfef73.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-9547b5cec7cf76bf.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/app/share/page-e6dcb83265530636.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/app/showroom/page-45248f08d6aecae5.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/app/tasks/page-2cddeb9e2aeedc55.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/app/term/page-e297866051595d81.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/app/today/page-baba2e047872fb0f.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/app/trace/page-e895da4ec9cac345.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/app/vault/page-4344faf20216233b.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-698bb29f11864b89.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/app/workflows/page-bd6a6dc1ddc273f2.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2e9e2fb01c9da1c9.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d62ceb13411ebba4.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/128fb7fb670b2fbf.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/context/nightly-condense.yaml +21 -0
  192. package/graphs/context/recipes.yaml +12 -0
  193. package/graphs/demo/inside-seed.yaml +20 -0
  194. package/graphs/demo/recipes.yaml +12 -0
  195. package/graphs/drafts/draft-cleanup.yaml +19 -0
  196. package/graphs/drafts/recipes.yaml +23 -0
  197. package/graphs/intake/intake-daily.yaml +2 -1
  198. package/graphs/ops/recipes.yaml +3 -0
  199. package/graphs/ops/secret-exposure.yaml +24 -0
  200. package/graphs/release/recipes.yaml +3 -0
  201. package/graphs/release/release-loop.yaml +4 -1
  202. package/graphs/video/explainer-line.yaml +2 -2
  203. package/package.json +2 -1
  204. package/plugins/card-followup/examples/sample-card.png +0 -0
  205. package/plugins/elanous-hwp/README.md +25 -0
  206. package/plugins/elanous-hwp/cli.ts +22 -0
  207. package/plugins/elanous-hwp/converter.ts +237 -0
  208. package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
  209. package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
  210. package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
  211. package/plugins/elanous-hwp/plugin.json +16 -0
  212. package/plugins/elanous-hwp/plugin.ts +40 -0
  213. package/scripts/ci-public-export-leak-gate.ts +75 -14
  214. package/scripts/ci-public-leak-gate.ts +44 -9
  215. package/scripts/context-hooks/claude-stop.sh +4 -0
  216. package/scripts/context-hooks/emit.ts +24 -0
  217. package/scripts/context-hooks/post-tool-use.sh +4 -0
  218. package/scripts/coord-channel-watch.sh +12 -0
  219. package/scripts/coord-requests-bridge.ts +143 -0
  220. package/scripts/field-feed/lib.ts +4 -0
  221. package/scripts/fleet/node-setup.sh +20 -3
  222. package/scripts/homebrew-formula-bump.ts +69 -0
  223. package/scripts/lib/telegram-inject-args.ts +31 -0
  224. package/scripts/marketing/measure-site-numbers.ts +169 -0
  225. package/scripts/measure-gate-shards.ts +309 -0
  226. package/scripts/measure-pod-memory-by-goal.ts +130 -0
  227. package/scripts/mission-request-judge.ts +31 -1
  228. package/scripts/morning-report.ts +2 -2
  229. package/scripts/opportunity-scan.ts +1 -1
  230. package/scripts/release-loop/auto-approve-node.ts +21 -4
  231. package/scripts/release-loop/checklist-gate-node.ts +2 -1
  232. package/scripts/release-loop/cut-branch.ts +84 -0
  233. package/scripts/release-loop/gate-node.ts +22 -15
  234. package/scripts/release-loop/mac-smoke-node.ts +229 -0
  235. package/scripts/release-loop/node-verdict.ts +3 -3
  236. package/scripts/release-loop/ops-upgrade-node.ts +47 -6
  237. package/scripts/release-loop/publish-node.ts +4 -1
  238. package/scripts/release-loop/tui-node-checks.ts +42 -0
  239. package/scripts/release-loop/tui-sim-node.ts +32 -8
  240. package/scripts/release-loop/unattended-release.ts +5 -3
  241. package/scripts/release-loop/version-node.ts +74 -13
  242. package/scripts/signal-digest-cycle.ts +2 -7
  243. package/scripts/signal-digest-photo.ts +11 -0
  244. package/scripts/tech1-public-measure.ts +94 -0
  245. package/scripts/telegram-inject.ts +14 -6
  246. package/scripts/test-diet/node.ts +1 -1
  247. package/scripts/test-diet/remeasure-list.ts +112 -0
  248. package/scripts/tui-regress.ts +2 -2
  249. package/scripts/ux/demo-rehearsal.ts +247 -0
  250. package/scripts/ux/demo-seed.ts +108 -0
  251. package/scripts/ux/lib/rehearsal-verdict.ts +80 -0
  252. package/skills/diagram-master/SKILL.md +366 -0
  253. package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
  254. package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
  255. package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
  256. package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
  257. package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
  258. package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
  259. package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
  260. package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
  261. package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
  262. package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
  263. package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
  264. package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
  265. package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
  266. package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
  267. package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
  268. package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
  269. package/skills/diagram-master/references/examples/README.md +69 -0
  270. package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
  271. package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
  272. package/skills/diagram-master/references/pyproject.toml +16 -0
  273. package/skills/diagram-master/references/quality-checklist.md +33 -0
  274. package/skills/diagram-master/references/routing-guide.md +164 -0
  275. package/skills/diagram-master/references/uv.lock +1356 -0
  276. package/skills/google-workspace/SKILL.md +33 -0
  277. package/skills/google-workspace/scripts/gws-safe.sh +177 -0
  278. package/skills/grill-me/SKILL.md +1 -1
  279. package/skills/lecture-note-digitizer/SKILL.md +926 -0
  280. package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
  281. package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
  282. package/skills/lecture-note-digitizer/references/html-template.md +167 -0
  283. package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
  284. package/skills/omni-crawl/SKILL.md +21 -11
  285. package/skills/omni-crawl/scripts/main.ts +6 -6
  286. package/skills/omni-crawl/src/router.ts +3 -3
  287. package/skills/omni-digest/SKILL.md +17 -9
  288. package/skills/omni-digest/digest.md +2 -2
  289. package/skills/omni-digest/src/fetch.ts +30 -3
  290. package/skills/pitch-deck/SKILL.md +2 -2
  291. package/skills/pitch-deck/template.html +2 -2
  292. package/skills/youtube-master/SKILL.md +163 -0
  293. package/skills/youtube-master/package-lock.json +558 -0
  294. package/skills/youtube-master/package.json +13 -0
  295. package/skills/youtube-master/references/study-note-template.md +124 -0
  296. package/skills/youtube-master/scripts/main.ts +435 -0
  297. package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
  298. package/skills/youtube-master/src/audio.ts +63 -0
  299. package/skills/youtube-master/src/domain-staging.ts +50 -0
  300. package/skills/youtube-master/src/env.ts +36 -0
  301. package/skills/youtube-master/src/obsidian.ts +155 -0
  302. package/skills/youtube-master/src/router.ts +110 -0
  303. package/skills/youtube-master/src/stt.ts +199 -0
  304. package/skills/youtube-master/src/study-note.ts +175 -0
  305. package/skills/youtube-master/src/summarize.ts +358 -0
  306. package/skills/youtube-master/src/transcript.ts +76 -0
  307. package/skills/youtube-master/src/types.ts +91 -0
  308. package/skills/youtube-master/src/util.ts +93 -0
  309. package/skills/youtube-master/src/youtube.ts +70 -0
  310. package/skills/youtube-master/tsconfig.json +13 -0
  311. package/src/acp/server.ts +5 -2
  312. package/src/agent-mission/driver.ts +215 -23
  313. package/src/agent-mission/pty-decision.ts +71 -0
  314. package/src/agent-mission/review-loop.ts +30 -0
  315. package/src/autopilot/build/llm-conflict-merge.ts +16 -3
  316. package/src/autopilot/pty-control-loop.ts +4 -1
  317. package/src/autopilot/tool-registry.ts +2 -0
  318. package/src/boot/daemon-prompt-turn.ts +5 -0
  319. package/src/boot/daemon-runtime.ts +9 -3
  320. package/src/boot/daemon-tools/web-search.ts +3 -0
  321. package/src/card-followup/core.ts +109 -0
  322. package/src/chat/index.ts +2 -0
  323. package/src/cli/drive-input-jail.ts +101 -0
  324. package/src/cli/hooks-cli.ts +17 -3
  325. package/src/cli/make-cli.ts +43 -0
  326. package/src/cli/persona-cli.ts +98 -9
  327. package/src/cli/plugin-cli.ts +31 -22
  328. package/src/cli/pod-cli.ts +36 -9
  329. package/src/cli/pod-memory-advice.ts +35 -0
  330. package/src/cli/pr-cli.ts +51 -15
  331. package/src/cli/pty-drive-cli.ts +41 -7
  332. package/src/cli/pty-drive-verdict.ts +40 -0
  333. package/src/cli/release-cli.ts +63 -10
  334. package/src/cli/setup-cli.ts +43 -1
  335. package/src/cli/skills-cli.ts +17 -1
  336. package/src/context-bus/claude-hooks-install.ts +10 -0
  337. package/src/context-bus/context-now-surfaces.ts +65 -0
  338. package/src/context-bus/context-now.ts +104 -0
  339. package/src/context-bus/coord-events.ts +2 -2
  340. package/src/context-bus/external-events.ts +52 -0
  341. package/src/context-bus/long-term-memory.ts +108 -0
  342. package/src/context-bus/nightly-condense.ts +153 -0
  343. package/src/context-bus/session-events.ts +35 -0
  344. package/src/dashboard/dashboard-status-lines.ts +2 -0
  345. package/src/dashboard/index.ts +17 -4
  346. package/src/dashboard/slash-runtime/dashboard-handlers.ts +31 -1
  347. package/src/decisions/decision-cards.ts +10 -3
  348. package/src/decisions/decision-ledger.ts +13 -5
  349. package/src/discord/sprint21-runtime.ts +5 -1
  350. package/src/discord-self-message.ts +32 -0
  351. package/src/discord-slash-wire.ts +5 -1
  352. package/src/discord.ts +17 -1
  353. package/src/domains/core-tools.ts +3 -2
  354. package/src/domains/outbound-alert.ts +105 -32
  355. package/src/domains/outbound-log-probe.ts +8 -0
  356. package/src/domains/telegram-kind-route.ts +51 -13
  357. package/src/exec-requests/default-outputs.ts +25 -0
  358. package/src/exec-requests/planner.ts +10 -2
  359. package/src/exec-requests/runner.ts +20 -6
  360. package/src/exec-requests/store.ts +3 -0
  361. package/src/execution-loop/launch-gate.ts +109 -0
  362. package/src/field/field-reel.ts +5 -1
  363. package/src/field-note/index.ts +201 -0
  364. package/src/field-note/telegram.ts +142 -0
  365. package/src/field-note/transcribe.ts +248 -0
  366. package/src/graph-kinds/registry.ts +3 -3
  367. package/src/graph-runner/graph-cli.ts +61 -1
  368. package/src/graph-runner/graph-grow-llm.ts +47 -0
  369. package/src/graph-runner/graph-grow.ts +50 -0
  370. package/src/graph-runner/runner.ts +329 -33
  371. package/src/grok/agent-search.ts +8 -2
  372. package/src/guardian/secret-exposure-scan.ts +101 -0
  373. package/src/harness/harness-cli-command.ts +375 -13
  374. package/src/harness/harness-pod-dispatch.ts +43 -23
  375. package/src/harness/harness-seams.ts +38 -4
  376. package/src/harness/harness-stop.ts +23 -4
  377. package/src/harness/launch-registry.ts +91 -0
  378. package/src/harness/process-garbage.ts +5 -3
  379. package/src/hooks/consult-intake.ts +153 -0
  380. package/src/hooks/dispatch.ts +82 -0
  381. package/src/hooks/expose.ts +254 -0
  382. package/src/hooks/github-shadow.ts +108 -0
  383. package/src/hooks/providers.ts +71 -5
  384. package/src/hooks/queue.ts +1 -1
  385. package/src/hooks/receiver.ts +94 -16
  386. package/src/index.ts +76 -14
  387. package/src/intake-plane/categorize.ts +18 -46
  388. package/src/intake-plane/discord-seat-work.ts +38 -2
  389. package/src/intake-plane/front-route-classifier.ts +33 -39
  390. package/src/intake-plane/persona-answer.ts +30 -0
  391. package/src/intake-plane/runtime-callables.ts +8 -1
  392. package/src/intake-plane/telegram-seat-work.ts +36 -2
  393. package/src/intake-plane/wish-card.ts +33 -0
  394. package/src/intake-plane/wish-folder.ts +67 -0
  395. package/src/intent-gate/gate.ts +30 -10
  396. package/src/live/detail-switch.ts +5 -0
  397. package/src/llm/difficulty.ts +57 -0
  398. package/src/llm/judge-layer.ts +101 -0
  399. package/src/llm/mission-router.ts +33 -19
  400. package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
  401. package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
  402. package/src/loops/contract/examples/steward.loop.yaml +50 -0
  403. package/src/loops/contract/loop-agent.schema.json +138 -0
  404. package/src/loops/contract/validate.ts +64 -0
  405. package/src/loops/registry.ts +20 -6
  406. package/src/market/signed-index.ts +4 -0
  407. package/src/maturity/bot-command-maturity.ts +45 -0
  408. package/src/maturity/feature-maturity.ts +27 -4
  409. package/src/model-tier/index.ts +2 -2
  410. package/src/model-tier/tier-resolver.ts +20 -20
  411. package/src/model-tier/types.ts +6 -6
  412. package/src/mss/logging/log-store.ts +15 -0
  413. package/src/nexus/api/config-model-tier.ts +5 -4
  414. package/src/nexus/api/fabric-plans.ts +53 -0
  415. package/src/nexus/api/harness-api.ts +5 -1
  416. package/src/nexus/api/health.ts +2 -0
  417. package/src/nexus/api/http-server.ts +67 -8
  418. package/src/nexus/api/inside-events.ts +226 -0
  419. package/src/nexus/api/meta-api.ts +21 -8
  420. package/src/nexus/api/missions.ts +6 -1
  421. package/src/nexus/api/ops-seats.ts +33 -0
  422. package/src/nexus/api/outbound-report.ts +40 -7
  423. package/src/nexus/api/outputs-route.ts +44 -0
  424. package/src/nexus/api/personas.ts +95 -53
  425. package/src/nexus/api/seat-requests.ts +44 -2
  426. package/src/nexus/api/sessions-store.ts +17 -38
  427. package/src/nexus/api/sub-seat-charters.ts +34 -0
  428. package/src/nexus/api/tabs-mutations.ts +3 -1
  429. package/src/nexus/api/task-cards-api.ts +19 -0
  430. package/src/nexus/api/trace.ts +18 -6
  431. package/src/nexus/api/workflow-history.ts +88 -0
  432. package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
  433. package/src/nexus/api/workflows.ts +132 -6
  434. package/src/nexus/index.ts +2 -0
  435. package/src/nexus/kinds/webterm.ts +2 -1
  436. package/src/nexus/outbound/delivery-ledger.ts +17 -8
  437. package/src/nexus/outbound/router.ts +8 -3
  438. package/src/nexus/webterm/pty.ts +6 -2
  439. package/src/onboarding/cli-auth-status.ts +80 -0
  440. package/src/onboarding/voice-ai.ts +3 -3
  441. package/src/org/seat-budget.ts +48 -0
  442. package/src/org/stall-escalation.ts +63 -0
  443. package/src/outputs/ledger.ts +120 -0
  444. package/src/persona/persona-todo.ts +79 -0
  445. package/src/persona/presets.ts +123 -2
  446. package/src/persona/team-set.ts +155 -0
  447. package/src/plugins/install/plugin-install.ts +14 -0
  448. package/src/plugins/maker/market-bundle.ts +110 -0
  449. package/src/plugins/maker/plugin-maker.ts +254 -11
  450. package/src/plugins/maker/wizard-generate.ts +103 -0
  451. package/src/pod-lease/admission.ts +150 -0
  452. package/src/pod-lease/dependency-state.ts +85 -0
  453. package/src/pod-lease/host-lease.ts +127 -0
  454. package/src/project/project-suggestion.ts +16 -0
  455. package/src/project/session-context.ts +24 -0
  456. package/src/release-loop/checklist.ts +17 -5
  457. package/src/release-loop/feature-store.ts +29 -13
  458. package/src/release-loop/landed-but-yellow.ts +48 -0
  459. package/src/release-loop/next-md-merge.ts +58 -0
  460. package/src/release-loop/release-note.ts +59 -4
  461. package/src/seat-dispatch/seat-ask.ts +130 -0
  462. package/src/seat-dispatch/seat-questions.ts +100 -0
  463. package/src/seat-loop/seat-loop.ts +709 -29
  464. package/src/seat-loop/seat-report.ts +37 -2
  465. package/src/self-dev/dev-cli.ts +4 -1
  466. package/src/self-dev/dev-pipeline.ts +37 -1
  467. package/src/self-dev/draft-sweep.ts +79 -40
  468. package/src/self-dev/draft-triage-rules.ts +62 -7
  469. package/src/self-dev/fabric-plan-core.ts +297 -0
  470. package/src/self-dev/orchestrate.ts +36 -4
  471. package/src/self-dev/release-path-guard.ts +62 -0
  472. package/src/self-dev/shard-aggregate.ts +230 -0
  473. package/src/self-dev/shard-placement.ts +60 -0
  474. package/src/self-dev/shard-plan.ts +48 -0
  475. package/src/self-dev/shard-pod-run.ts +77 -0
  476. package/src/self-dev/shard-run.ts +105 -0
  477. package/src/self-implement/budget-gate.ts +29 -12
  478. package/src/self-implement/gate-baseline.ts +1 -1
  479. package/src/self-implement/gate-candidate-ranking.ts +60 -0
  480. package/src/self-implement/gate-cli.ts +40 -1
  481. package/src/self-implement/gate-scope.ts +44 -13
  482. package/src/self-implement/graph-variant.ts +171 -0
  483. package/src/self-implement/harness-policy-gates.ts +1 -1
  484. package/src/self-implement/headless-elanous-driver.ts +27 -3
  485. package/src/self-implement/host-regate.ts +22 -1
  486. package/src/self-implement/importer-test-index.ts +2 -1
  487. package/src/self-implement/l8-merge-queue.ts +130 -0
  488. package/src/self-implement/orchestrator.ts +257 -9
  489. package/src/self-implement/route-consumer-test-index.ts +122 -0
  490. package/src/self-implement/seams.ts +72 -11
  491. package/src/self-implement/test-seams.ts +2 -0
  492. package/src/self-implement/uncommitted-work.ts +59 -0
  493. package/src/session/index.ts +36 -13
  494. package/src/skills/gift-install.ts +215 -0
  495. package/src/skills/tools/web-search.ts +4 -1
  496. package/src/steward/launch.ts +42 -26
  497. package/src/steward/steward-cards.ts +17 -9
  498. package/src/steward/triage.ts +46 -14
  499. package/src/task-cards/card-cli.ts +25 -1
  500. package/src/task-orchestrator/mission.ts +5 -0
  501. package/src/task-orchestrator/store.ts +12 -3
  502. package/src/task-orchestrator/surfaces/pod-command-job.ts +43 -17
  503. package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
  504. package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
  505. package/src/task-orchestrator/surfaces/self-implement-pod.ts +222 -40
  506. package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
  507. package/src/task-orchestrator/types.ts +2 -0
  508. package/src/telegram-card-followup.ts +16 -96
  509. package/src/telegram-commands.ts +31 -1
  510. package/src/telegram-project-command.ts +145 -0
  511. package/src/telegram-report.ts +21 -17
  512. package/src/telegram.ts +61 -8
  513. package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
  514. package/src/user-config.ts +110 -24
  515. package/src/version/packed-revision.json +1 -1
  516. package/src/web-search/grok.ts +7 -1
  517. package/src/web-search/index.ts +28 -1
  518. package/src/web-search/provider.ts +4 -0
  519. package/src/web-search/x-intent.ts +5 -0
  520. package/src/workflow-runtime/executor.ts +277 -47
  521. package/src/workflow-runtime/index.ts +1 -0
  522. package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
  523. package/src/workflow-runtime/plugin-kind-node.ts +1 -1
  524. package/src/workflow-runtime/schema.ts +79 -4
  525. package/src/workflow-runtime/types.ts +35 -4
  526. package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
  536. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
  537. package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
  556. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
  614. package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
  615. /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → -6XrAoD3eU7NyMHAE4xPS}/_ssgManifest.js +0 -0
@@ -0,0 +1,101 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { elanousStateRoot } from '../autopilot/state-paths.js';
4
+ import { listCoordEvents, type CoordEvent } from '../context-bus/coord-events.js';
5
+ import { DecisionLedger } from '../decisions/decision-ledger.js';
6
+ import { LogStore } from '../mss/logging/log-store.js';
7
+
8
+ export type SecretKind = 'token-prefix' | 'key' | 'bearer' | 'private-key';
9
+ export interface SecretCandidate { store: 'logs' | 'decisions' | 'context'; rowId: string; kind: SecretKind; prefix: string; length: number }
10
+ export interface SecretScanResult { mode: 'shadow' | 'publish'; candidates: SecretCandidate[]; raised: number }
11
+
12
+ const PATTERNS: Array<{ kind: SecretKind; pattern: RegExp }> = [
13
+ { kind: 'private-key', pattern: /-----BEGIN (?:[A-Z0-9_-]+ )?PRIVATE KEY(?: BLOCK)?-----/g },
14
+ { kind: 'bearer', pattern: /\bBearer\s+([A-Za-z0-9._~+/-]{12,}={0,2})/gi },
15
+ { kind: 'token-prefix', pattern: /\b(?:sk-[A-Za-z0-9_-]{16,}|xai-[A-Za-z0-9_-]{20,}|gh[pousr]_[A-Za-z0-9_]{12,}|github_pat_[A-Za-z0-9_]{12,}|xox[baprs]-[A-Za-z0-9-]{12,}|(?:AKIA|ASIA|ABIA|ACCA)[A-Z2-7]{16}|AIza[A-Za-z0-9_-]{35})\b/g },
16
+ { kind: 'key', pattern: /\b(?:[A-Za-z][A-Za-z0-9_]*_)?(?:api[_-]?key|secret[_-]?key|access[_-]?key|token)(?:\\?["'])?\s*[=:]\s*(?:\\?["'])?([A-Za-z0-9_./+~-]{16,}={0,2})/gi },
17
+ ];
18
+
19
+ function scanText(store: SecretCandidate['store'], rowId: string, text: string): SecretCandidate[] {
20
+ const found: SecretCandidate[] = [];
21
+ const spans: Array<[number, number]> = [];
22
+ for (const { kind, pattern } of PATTERNS) {
23
+ for (const match of text.matchAll(pattern)) {
24
+ const value = match[1] ?? match[0];
25
+ const start = match.index! + (match[1] ? match[0].lastIndexOf(value) : 0);
26
+ const end = start + value.length;
27
+ if (spans.some(([a, b]) => start < b && end > a)) continue;
28
+ spans.push([start, end]);
29
+ found.push({ store, rowId, kind, prefix: value.slice(0, 4), length: value.length });
30
+ }
31
+ }
32
+ return found;
33
+ }
34
+
35
+ export interface SecretScanDeps {
36
+ now?: () => Date;
37
+ stateRoot?: string;
38
+ logs?: Pick<LogStore, 'queryAll'>;
39
+ decisions?: Pick<DecisionLedger, 'list' | 'raise'>;
40
+ context?: (since: string) => CoordEvent[];
41
+ }
42
+
43
+ /** Only source coordinates and a four-character prefix leave the scanner. Missing stores are empty; unreadable stores throw. */
44
+ export function scanSecretExposures(options: { publish?: boolean } = {}, deps: SecretScanDeps = {}): SecretScanResult {
45
+ const root = deps.stateRoot ?? elanousStateRoot();
46
+ const nowMs = (deps.now ?? (() => new Date()))().getTime();
47
+ const sinceMs = nowMs - 86_400_000;
48
+ const since = new Date(sinceMs).toISOString();
49
+ const candidates: SecretCandidate[] = [];
50
+ const logPath = join(root, 'logs', 'logs.db');
51
+ const opened = !deps.logs && existsSync(logPath) ? LogStore.openReadOnly(logPath) : undefined;
52
+ const logs = deps.logs ?? opened;
53
+ try {
54
+ for (const row of logs?.queryAll({ sinceMs, untilMs: nowMs }) ?? []) {
55
+ if (!Number.isSafeInteger(row.id) || row.ts_ms < sinceMs || row.ts_ms > nowMs) continue;
56
+ const id = String(row.id);
57
+ candidates.push(...scanText('logs', id, JSON.stringify(row)));
58
+ }
59
+ } finally { opened?.close(); }
60
+
61
+ const ledger = deps.decisions ?? new DecisionLedger({ stateDir: root });
62
+ const entries = ledger.list({ status: 'all' });
63
+ for (const entry of entries) {
64
+ if (entry.raisedBy.agent === 'secret-exposure-scan' || !/^D-\d{8}-\d+$/.test(entry.id)) continue;
65
+ candidates.push(...scanText('decisions', entry.id, JSON.stringify(entry)));
66
+ }
67
+ for (const event of (deps.context ?? (s => listCoordEvents({ since: s })))(since)) {
68
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(event.id) || Date.parse(event.at) < sinceMs || Date.parse(event.at) > nowMs) continue;
69
+ candidates.push(...scanText('context', event.id, JSON.stringify(event)));
70
+ }
71
+ // One card per location/kind; do not put any untrusted source text into logs.
72
+ const unique = [...new Map(candidates.map(c => [`${c.store}:${c.rowId}:${c.kind}`, c])).values()];
73
+ let raised = 0;
74
+ if (options.publish) {
75
+ const existing = new Set(entries.flatMap(entry => entry.refs ?? []));
76
+ for (const candidate of unique) {
77
+ const ref = `secret-exposure:${candidate.store}:${candidate.rowId}:${candidate.kind}`;
78
+ if (existing.has(ref)) continue;
79
+ ledger.raise({ title: `비밀 노출 후보 — ${candidate.store} / ${candidate.rowId}`,
80
+ category: 'secret', scqa: { s: `${candidate.store} 행 ${candidate.rowId}에서 ${candidate.kind} 꼴이 발견됐다.`,
81
+ c: `값은 보관하지 않는다. 앞 4자 ${candidate.prefix} · 길이 ${candidate.length}.` },
82
+ options: [{ key: 'a', label: '원장 위치 확인 및 폐기', consequence: '사람이 원장에서 확인 후 폐기한다' },
83
+ { key: 'b', label: '오탐으로 닫기', consequence: '사람이 오탐 여부를 확인한다' }],
84
+ recommendation: { skipped: true, reason: '사람 확인 필요' }, raisedBy: { agent: 'secret-exposure-scan' }, refs: [ref] });
85
+ existing.add(ref);
86
+ raised++;
87
+ }
88
+ }
89
+ return { mode: options.publish ? 'publish' : 'shadow', candidates: unique, raised };
90
+ }
91
+
92
+ if (import.meta.main) {
93
+ // The graph runs without flags: shadow only. Publishing requires an explicit operator opt-in.
94
+ try {
95
+ const result = scanSecretExposures({ publish: process.argv.slice(2).includes('--publish') });
96
+ console.log(JSON.stringify(result));
97
+ } catch {
98
+ console.error('secret-exposure-scan: source unreadable');
99
+ process.exitCode = 1;
100
+ }
101
+ }
@@ -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, decideLaunchBudget, 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);
@@ -331,6 +338,8 @@ function resolveLaunchSubstrate(opts: HarnessSubstrateOpts): ResolvedHarnessSubs
331
338
  }
332
339
  type PodExit = { status: number | null; signal?: string | null };
333
340
  type PodExitReason = 'signal' | 'human-stop' | 'supervisor' | 'no-launch' | 'unknown';
341
+ /** GitHub lists at most this many files for one pull request; a list that reaches it is not provably complete. */
342
+ export const GITHUB_PR_FILES_LIST_CAP = 3000;
334
343
  const STOPPING_SUPERVISOR_VERDICTS = new Set(['UNCONVERGEABLE', 'CONTRACT-CONFLICT']);
335
344
  // Ledger events that only exist once the child actually ran — any of them rules out «never reached the Pod».
336
345
  const LAUNCH_EVIDENCE_EVENTS = new Set(['job-applied', 'pod-child-run', 'reviewed', 'rework-budget', 'pr-opened']);
@@ -525,6 +534,11 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
525
534
  process.exitCode = 2;
526
535
  return;
527
536
  }
537
+ if (o.after !== undefined && !/^(?:#?[1-9]\d*|[a-f0-9]{16})$/.test(o.after.trim())) {
538
+ console.error(`--after 는 PR 번호(#N) 또는 골 ID(16자 16진수)여야 한다: ${o.after}`);
539
+ process.exitCode = 2;
540
+ return;
541
+ }
528
542
  warnRecentIncidentBurst();
529
543
  let dispatchRecorded = false;
530
544
  try {
@@ -544,7 +558,7 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
544
558
  const { dispatchHarnessOnPod } = await import('./harness-pod-dispatch.js');
545
559
  let output = '';
546
560
  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 } : {}) },
561
+ 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
562
  { onOutput: (text) => {
549
563
  runId ??= harnessPodRunId(output + text);
550
564
  output = (output + text).slice(-16_000);
@@ -557,6 +571,60 @@ async function onPod(opts: unknown, entrance: 'cli-harness-ask' | 'cli-harness-s
557
571
  }
558
572
  }
559
573
 
574
+ const LAUNCH_BUDGET_PROVIDER: Readonly<Record<string, string>> = { 'codex-rotate': CODEX_PROVIDER, grok: GROK_PROVIDER };
575
+
576
+ /**
577
+ * L6 발사 관문의 예산 입력 보정 — 발사 우주의 config 에 체인이 없으면(작업 트리 = 시험 우주) 막지 않고
578
+ * 코드 기본 체인으로 판단한다. `--child-llm-provider` 를 명시했으면 그것이 체인이다(예산 판정 밖 provider 는 통과).
579
+ */
580
+ export function harnessLaunchBudgetDecision(
581
+ inputs: BudgetInputs,
582
+ opts: { readonly childLlmProvider?: string; readonly childLlmModel?: string } = {},
583
+ ): { readonly decision: BudgetDecision; readonly warning?: string; readonly unmeasuredProvider?: string } {
584
+ const explicit = opts.childLlmProvider?.trim();
585
+ const judged = (selected: BudgetInputs) => {
586
+ const { decision, unmeasuredProvider } = decideLaunchBudget(selected);
587
+ return { decision, ...(unmeasuredProvider ? { unmeasuredProvider, warning: `budget: ${unmeasuredProvider} usage unmeasured — launching` } : {}) };
588
+ };
589
+ if (explicit) {
590
+ if (explicit !== CODEX_PROVIDER && explicit !== GROK_PROVIDER) {
591
+ return {
592
+ decision: { action: 'proceed', provider: explicit, ...(opts.childLlmModel ? { model: opts.childLlmModel } : {}), reasons: [`${explicit}: 명시 provider — 예산 판정 밖`] },
593
+ warning: `budget: ${explicit} is outside the budget gate — launched as requested`,
594
+ };
595
+ }
596
+ const chain = [{ provider: explicit, ...(opts.childLlmModel ? { model: opts.childLlmModel } : {}) }];
597
+ return judged({ ...inputs, preference: { ...inputs.preference, chain } });
598
+ }
599
+ if (inputs.preference.chain.length > 0) return judged(inputs);
600
+ const chain = DEFAULT_FALLBACK_CHAIN.map((step) => ({ provider: LAUNCH_BUDGET_PROVIDER[step] ?? step }));
601
+ const result = judged({ ...inputs, preference: { ...inputs.preference, chain } });
602
+ return {
603
+ ...result,
604
+ warning: `budget: no chain in this universe's config — judged with the code default ${DEFAULT_FALLBACK_CHAIN.join(',')}${result.warning ? ` · ${result.warning}` : ''}`,
605
+ };
606
+ }
607
+
608
+ async function readHarnessLaunchBudget(
609
+ opts: { readonly childLlmProvider?: string; readonly childLlmModel?: string } = {},
610
+ ): Promise<BudgetDecision | 'unknown'> {
611
+ try {
612
+ const { decision, warning, unmeasuredProvider } = harnessLaunchBudgetDecision(await readBudgetInputsLive(), opts);
613
+ if (warning) {
614
+ console.error(`⚠️ launch gate: ${warning}`);
615
+ try {
616
+ if (unmeasuredProvider) debug.log('execution-loop.launch-gate', 'budget-unmeasured', { provider: unmeasuredProvider });
617
+ if (!opts.childLlmProvider?.trim() && warning.includes('code default')) debug.log('execution-loop.launch-gate', 'budget-chain-defaulted', { warning, action: decision.action, provider: decision.provider });
618
+ } catch { /* observation is fail-soft */ }
619
+ }
620
+ return decision;
621
+ }
622
+ catch (error) {
623
+ try { debug.log('execution-loop.launch-gate', 'budget-unavailable', { reason: String(error) }); } catch { /* observation is fail-soft */ }
624
+ return 'unknown';
625
+ }
626
+ }
627
+
560
628
  async function dispatchHarnessAskSay(
561
629
  opts: HarnessAskSayChildLlmOptions & HarnessDryRunOpts,
562
630
  dryRunPreview: {
@@ -566,6 +634,7 @@ async function dispatchHarnessAskSay(
566
634
  readonly goalPath?: string;
567
635
  },
568
636
  dispatch: (resolved: ResolvedHarnessSubstrate) => Promise<void>,
637
+ gate: PreLaunchGateDeps & { readBudget?: () => Promise<BudgetDecision | 'unknown'> } = {},
569
638
  ): Promise<void> {
570
639
  await runInjectedHarnessHandler(async () => {
571
640
  assertHarnessChildLlmModel(opts);
@@ -574,6 +643,35 @@ async function dispatchHarnessAskSay(
574
643
  printHarnessLaunchDryRun(dryRunPreview);
575
644
  return;
576
645
  }
646
+ // Without a GoalId, match the request to a live run's exact verbatim original ask; still check budget.
647
+ let identity = dryRunPreview.input;
648
+ let goalId: string | null = null;
649
+ if (dryRunPreview.goalPath) {
650
+ try {
651
+ identity = readFileSync(dryRunPreview.goalPath, 'utf8');
652
+ goalId = parseGoalId(identity);
653
+ } catch { /* The launch handler owns file-read errors. */ }
654
+ }
655
+ goalId ??= launchRequestId(identity);
656
+ // Under bun test with no injected gate deps, skip the live reads (≈5 s of codex rotation + run scans) —
657
+ // CLI wiring tests time out on them. Gate tests inject deps or opt in with ELANOUS_LAUNCH_GATE_LIVE=1.
658
+ if (process.env.NODE_ENV === 'test' && Object.keys(gate).length === 0 && process.env.ELANOUS_LAUNCH_GATE_LIVE !== '1') {
659
+ try { debug.log('execution-loop.launch-gate', 'skipped-test-env', { goalId }); } catch { /* observation is fail-soft */ }
660
+ await dispatch(resolved);
661
+ return;
662
+ }
663
+ const budget = await (gate.readBudget ?? (() => readHarnessLaunchBudget(opts)))();
664
+ const decision = preLaunchGate({ goalId, budget, forceLaunch: opts.forceGate === true }, gate);
665
+ if (decision.action !== 'proceed') {
666
+ console.error(`❌ launch gate: ${decision.action} — ${decision.reason.split(/\r?\n/, 1)[0]}`);
667
+ process.exitCode = 3;
668
+ return;
669
+ }
670
+ const warnings = [
671
+ ...(decision.sameGoalActiveRuns === 'unknown' ? ['active runs unknown'] : []),
672
+ ...(decision.budget === 'unknown' ? ['budget unknown'] : decision.budget.action === 'next-provider' ? [decision.budget.reasons.join(' · ') || 'next-provider'] : []),
673
+ ];
674
+ if (warnings.length > 0) console.error(`⚠️ launch gate: ${warnings.join(' · ').split(/\r?\n/, 1)[0]}`);
577
675
  await dispatch(resolved);
578
676
  });
579
677
  }
@@ -707,6 +805,8 @@ export const HARNESS_PROCESS_LAST_ACTIVITY_SCOPE_LINE =
707
805
 
708
806
  export interface HarnessProcessLedgerEntry {
709
807
  readonly timestamp?: string;
808
+ readonly event?: string;
809
+ readonly data?: Record<string, unknown>;
710
810
  }
711
811
 
712
812
  export type HarnessProcessLedgerLookup = (
@@ -741,6 +841,9 @@ export interface HarnessProcessObservationDeps {
741
841
  listWorktrees?: () => HarnessWorktreeListObservation | readonly string[];
742
842
  observeLaunchdPids?: () => HarnessLaunchdPidObservation;
743
843
  lookupLedger?: HarnessProcessLedgerLookup;
844
+ openProcessHandle?: (pid: number) => HarnessProcessSignalHandle;
845
+ readStartTime?: (pid: number) => string;
846
+ repositoryRoot?: string;
744
847
  nowMs?: number;
745
848
  thresholds?: HarnessProcessClassificationThresholds;
746
849
  write?: (text: string) => void;
@@ -1484,10 +1587,13 @@ type GithubPull = {
1484
1587
  draft: boolean;
1485
1588
  state: 'open' | 'closed';
1486
1589
  head: { ref: string };
1590
+ base?: { ref: string };
1487
1591
  labels: Array<{ name: string }>;
1488
1592
  created_at: string;
1489
1593
  updated_at?: string;
1490
1594
  merged_at: string | null;
1595
+ body?: string | null;
1596
+ merge_commit_sha?: string | null;
1491
1597
  };
1492
1598
 
1493
1599
  type GhExecute = (args: string[]) => string;
@@ -1536,9 +1642,25 @@ export function draftSweepRunStatus(ledgerMatches: readonly RunLedgerMatch[], ru
1536
1642
  ['completed', 'failed', 'cancelled', 'abandoned'].includes(terminal) ? terminal : undefined);
1537
1643
  if (status && status !== 'unknown') statuses.add(status);
1538
1644
  }
1645
+ if (statuses.has('running')) return 'running';
1646
+ if (statuses.has('probable-running')) return 'probable-running';
1539
1647
  return statuses.size === 1 ? [...statuses][0] : undefined;
1540
1648
  }
1541
1649
 
1650
+ function currentDraftSweepRunId(matches: readonly RunLedgerMatch[], repository: string, number: number): string | undefined {
1651
+ const owners = matches.flatMap((match) => {
1652
+ const events = match.entries.filter((entry) => entry.event === 'pr-opened' && entry.data.number === number);
1653
+ if (events.length === 0 || events.some((entry) => ledgerPrRepository(entry.data, number) !== repository)) return [];
1654
+ const times = events.map((entry) => Date.parse(entry.timestamp ?? ''));
1655
+ return [{ runId: match.runId, time: times.every(Number.isFinite) ? Math.max(...times) : NaN }];
1656
+ });
1657
+ if (owners.length === 1) return owners[0]!.runId;
1658
+ if (owners.some((owner) => !Number.isFinite(owner.time))) return undefined;
1659
+ owners.sort((a, b) => b.time - a.time);
1660
+ if (owners.length > 1 && owners[0]!.time === owners[1]!.time) return undefined;
1661
+ return owners[0]?.runId;
1662
+ }
1663
+
1542
1664
  type DraftSweepGitExecute = (cwd: string, args: string[]) => Pick<ReturnType<typeof runGitCommand>, 'status' | 'stdout' | 'stderr'>;
1543
1665
 
1544
1666
  function githubRemoteRepository(url: string): string | undefined {
@@ -1576,24 +1698,117 @@ export function githubDraftSweepAdapters(execute: GhExecute = executeGh, git: Dr
1576
1698
  if (!cache.has(repository)) cache.set(repository, inventory(repository, state));
1577
1699
  return cache.get(repository)!;
1578
1700
  };
1701
+ // GitHub stops listing a pull request's files at 3,000, and the cut looks like a normal last page.
1702
+ // A list that reaches the cap cannot prove it is complete, so it is reported as unknown (undefined):
1703
+ // a draft without a provable file list never qualifies for the all-files-landed close.
1704
+ const filesFor = (repository: string, number: number): string[] | undefined => {
1705
+ const files: string[] = [];
1706
+ for (let page = 1; page <= 100; page++) {
1707
+ const batch = ghJson<Array<{ filename: string }>>(['api', `repos/${repository}/pulls/${number}/files?per_page=100&page=${page}`], execute);
1708
+ if (!Array.isArray(batch) || batch.length > 100 || batch.some((file) => typeof file.filename !== 'string')) throw new Error('Incomplete PR file inventory');
1709
+ files.push(...batch.map((file) => file.filename));
1710
+ if (files.length >= GITHUB_PR_FILES_LIST_CAP) {
1711
+ debug.log('drafts.cleanup', 'file-inventory-capped', { number, listed: files.length });
1712
+ return undefined;
1713
+ }
1714
+ if (batch.length < 100) return files;
1715
+ }
1716
+ throw new Error('PR file inventory exceeded pagination limit');
1717
+ };
1718
+ const latestFileChangesFor = (draft: SweepDraft, repository: string): Record<string, string> | undefined => {
1719
+ if (!draft.changedFiles?.length) return undefined;
1720
+ const changes: Record<string, string> = {};
1721
+ for (let page = 1; page <= 100; page++) {
1722
+ const batch = ghJson<Array<{ sha: string; commit: { committer: { date: string } } }>>(
1723
+ ['api', `repos/${repository}/pulls/${draft.number}/commits?per_page=100&page=${page}`], execute);
1724
+ if (!Array.isArray(batch) || batch.length > 100) throw new Error('Incomplete draft commit inventory');
1725
+ for (const commit of batch) {
1726
+ const changedAt = commit.commit?.committer?.date;
1727
+ if (!commit.sha || !changedAt || !Number.isFinite(Date.parse(changedAt))) return undefined;
1728
+ const detail = ghJson<{ files?: Array<{ filename: string; previous_filename?: string }> }>(
1729
+ ['api', `repos/${repository}/commits/${commit.sha}?per_page=100`], execute);
1730
+ // GitHub truncates very large commit file lists; never infer coverage from a partial list.
1731
+ if (!Array.isArray(detail.files) || detail.files.length >= 100) return undefined;
1732
+ for (const file of detail.files) {
1733
+ for (const name of [file.filename, file.previous_filename]) {
1734
+ if (!name || !draft.changedFiles.includes(name)) continue;
1735
+ if (!changes[name] || Date.parse(changes[name]) < Date.parse(changedAt)) changes[name] = changedAt;
1736
+ }
1737
+ }
1738
+ }
1739
+ if (batch.length < 100) return draft.changedFiles.every((file) => changes[file]) ? changes : undefined;
1740
+ }
1741
+ return undefined;
1742
+ };
1743
+ const landingCommentsFor = (repository: string, number: number): string[] => {
1744
+ const comments: string[] = [];
1745
+ for (let page = 1; page <= 100; page++) {
1746
+ const batch = ghJson<Array<{ body?: string }>>(['api', `repos/${repository}/issues/${number}/comments?per_page=100&page=${page}`], execute);
1747
+ if (!Array.isArray(batch) || batch.length > 100) throw new Error('Incomplete landing comment inventory');
1748
+ comments.push(...batch.filter((comment) => /\blanding-verified\b/i.test(comment.body ?? '')).map((comment) => comment.body!));
1749
+ if (batch.length < 100) return comments;
1750
+ }
1751
+ throw new Error('Landing comment inventory exceeded pagination limit');
1752
+ };
1579
1753
  let ledgerMatches: readonly RunLedgerMatch[] | undefined;
1580
1754
  let running: ReadonlyMap<string, string> | undefined;
1581
- const runStatusFor = (repository: string, number: number): string | undefined => {
1755
+ const runStatusFor = (draft: SweepDraft, repository: string): string | undefined => {
1582
1756
  ledgerMatches ??= listRunLedgers().matches;
1583
1757
  running ??= new Map(queryRunningRuns().entries.map((entry) => [entry.runId, entry.status]));
1584
- return draftSweepRunStatus(ledgerMatches, running, repository, number);
1758
+ if (draft.runId) {
1759
+ const match = ledgerMatches.find((entry) => entry.runId === draft.runId);
1760
+ return match ? draftSweepRunStatus([match], running, repository, draft.number) : undefined;
1761
+ }
1762
+ return draftSweepRunStatus(ledgerMatches, running, repository, draft.number);
1585
1763
  };
1586
1764
  return {
1587
1765
  listDrafts: async (page, perPage, repository): Promise<SweepDraft[]> =>
1588
1766
  (await listed(open, repository, 'open')).filter((pr) => pr.draft)
1589
1767
  .slice((page - 1) * perPage, page * perPage)
1590
1768
  .map((pr) => ({ number: pr.number, title: pr.title, branch: pr.head.ref,
1591
- labels: pr.labels.map((item) => item.name), createdAt: pr.created_at, ...(pr.updated_at ? { updatedAt: pr.updated_at } : {}) })),
1769
+ labels: pr.labels.map((item) => item.name), createdAt: pr.created_at, body: pr.body ?? undefined,
1770
+ changedFiles: filesFor(repository, pr.number), ...(pr.updated_at ? { updatedAt: pr.updated_at } : {}),
1771
+ runId: currentDraftSweepRunId(ledgerMatches ??= listRunLedgers().matches, repository, pr.number) })),
1592
1772
  listMerged: async (page, perPage, repository): Promise<SweepMergedPr[]> =>
1593
- (await listed(closed, repository, 'closed')).filter((pr) => pr.merged_at !== null)
1773
+ (await listed(closed, repository, 'closed')).filter((pr) => pr.merged_at !== null && pr.base?.ref === 'main')
1594
1774
  .slice((page - 1) * perPage, page * perPage)
1595
- .map((pr) => ({ number: pr.number, title: pr.title, branch: pr.head.ref })),
1596
- getRunStatus: async (draft, repository) => runStatusFor(repository, draft.number),
1775
+ .map((pr) => ({ number: pr.number, title: pr.title, branch: pr.head.ref, body: pr.body ?? undefined,
1776
+ mergedAt: pr.merged_at ?? undefined, changedFiles: filesFor(repository, pr.number),
1777
+ mergeCommitMessage: pr.merge_commit_sha ? ghJson<{ commit: { message: string } }>(
1778
+ ['api', `repos/${repository}/commits/${pr.merge_commit_sha}`], execute).commit.message : undefined,
1779
+ landingVerifiedComments: landingCommentsFor(repository, pr.number) })),
1780
+ getRunStatus: async (draft, repository) => runStatusFor(draft, repository),
1781
+ getLatestFileChanges: async (draft, repository) => latestFileChangesFor(draft, repository),
1782
+ hasFinalRunResult: async (draft, repository) => {
1783
+ ledgerMatches ??= listRunLedgers().matches;
1784
+ const ownedRuns = new Set(ledgerMatches.filter((match) => {
1785
+ const prEvents = match.entries.filter((entry) => entry.event === 'pr-opened' && entry.data.number === draft.number);
1786
+ return prEvents.length > 0 && prEvents.every((entry) => ledgerPrRepository(entry.data, draft.number) === repository);
1787
+ }).map((match) => match.runId));
1788
+ if (ownedRuns.size === 0) return false;
1789
+ // A previous owner's final does not establish finality for a later owner of this PR.
1790
+ if (draft.runId && !ownedRuns.has(draft.runId)) return false;
1791
+ if (!draft.runId && ownedRuns.size > 1) return false;
1792
+ const currentOwners = draft.runId ? new Set([draft.runId]) : ownedRuns;
1793
+ const path = logsDbPath();
1794
+ if (!existsSync(path)) return false;
1795
+ const store = LogStore.openReadOnly(path);
1796
+ try {
1797
+ let beforeId: number | undefined;
1798
+ for (;;) {
1799
+ const rows = store.query({ exactCategories: ['self-implement.result'], events: ['final'], grep: String(draft.number),
1800
+ limit: 1_000, ...(beforeId === undefined ? {} : { beforeId }) });
1801
+ for (const row of rows) {
1802
+ try {
1803
+ const data = JSON.parse(row.data ?? '{}') as { runId?: string; prNumber?: number };
1804
+ if (data.prNumber === draft.number && data.runId && currentOwners.has(data.runId)) return true;
1805
+ } catch { /* A malformed result cannot establish finality. */ }
1806
+ }
1807
+ if (rows.length < 1_000) return false;
1808
+ beforeId = rows.at(-1)!.id;
1809
+ }
1810
+ } finally { store.close(); }
1811
+ },
1597
1812
  listLiveBranches: async (repository) => {
1598
1813
  const cwd = process.cwd();
1599
1814
  const remote = git(cwd, ['config', '--get', 'remote.origin.url']);
@@ -1714,6 +1929,140 @@ function installHarnessBudgetCommand(harnessCmd: Command): Command {
1714
1929
  });
1715
1930
  }
1716
1931
 
1932
+ export interface HarnessProcessSignalHandle {
1933
+ signal(signal: NodeJS.Signals): void;
1934
+ close(): void;
1935
+ }
1936
+
1937
+ // macOS has no pidfd: bind to the process by its microsecond start time (libproc PROC_PIDTBSDINFO) and
1938
+ // re-read it immediately before signalling — a reused pid within the same microsecond is not distinguishable, anything else is.
1939
+ function readDarwinStartMicros(pid: number): bigint | null {
1940
+ const libproc = dlopen('/usr/lib/libproc.dylib', {
1941
+ proc_pidinfo: { args: [FFIType.i32, FFIType.i32, FFIType.u64, FFIType.ptr, FFIType.i32], returns: FFIType.i32 },
1942
+ });
1943
+ try {
1944
+ const buf = new Uint8Array(136); // sizeof(struct proc_bsdinfo)
1945
+ const n = libproc.symbols.proc_pidinfo(pid, 3 /* PROC_PIDTBSDINFO */, 0n, buf, buf.length);
1946
+ if (n !== buf.length) return null;
1947
+ const view = new DataView(buf.buffer);
1948
+ if (view.getUint32(12, true) !== pid) return null; // pbi_pid
1949
+ return view.getBigUint64(120, true) * 1_000_000n + view.getBigUint64(128, true); // pbi_start_tvsec · pbi_start_tvusec
1950
+ } finally { libproc.close(); }
1951
+ }
1952
+
1953
+ function openDarwinProcessHandle(pid: number): HarnessProcessSignalHandle {
1954
+ const start = readDarwinStartMicros(pid);
1955
+ if (start === null) throw new Error('proc_pidinfo failed');
1956
+ let closed = false;
1957
+ return {
1958
+ signal(signal) {
1959
+ if (closed) throw new Error('process handle already closed');
1960
+ if (signal !== 'SIGTERM') throw new Error('only SIGTERM is supported');
1961
+ if (readDarwinStartMicros(pid) !== start) throw new Error('pid no longer names the same process');
1962
+ process.kill(pid, 'SIGTERM');
1963
+ },
1964
+ close() { closed = true; },
1965
+ };
1966
+ }
1967
+
1968
+ export function openHarnessProcessHandle(pid: number): HarnessProcessSignalHandle {
1969
+ if (process.platform === 'darwin') return openDarwinProcessHandle(pid);
1970
+ if (process.platform !== 'linux' || !['x64', 'arm64'].includes(process.arch)) {
1971
+ throw new Error('pid-bound signaling unavailable on this platform');
1972
+ }
1973
+ const libc = dlopen('libc.so.6', {
1974
+ syscall: { args: [FFIType.i64, FFIType.i64, FFIType.i64, FFIType.i64, FFIType.i64], returns: FFIType.i64 },
1975
+ close: { args: [FFIType.i32], returns: FFIType.i32 },
1976
+ });
1977
+ const fd = Number(libc.symbols.syscall(434, pid, 0, 0, 0)); // pidfd_open
1978
+ if (fd < 0) {
1979
+ libc.close();
1980
+ throw new Error('pidfd_open failed');
1981
+ }
1982
+ let closed = false;
1983
+ return {
1984
+ signal(signal) {
1985
+ if (closed) throw new Error('pidfd already closed');
1986
+ if (signal !== 'SIGTERM' || libc.symbols.syscall(424, fd, osConstants.signals.SIGTERM, 0, 0) !== 0n) {
1987
+ throw new Error('pidfd_send_signal failed');
1988
+ }
1989
+ },
1990
+ close() {
1991
+ if (closed) return;
1992
+ closed = true;
1993
+ libc.symbols.close(fd);
1994
+ libc.close();
1995
+ },
1996
+ };
1997
+ }
1998
+
1999
+ export function killHarnessProcess(
2000
+ pid: number,
2001
+ force: boolean,
2002
+ deps: HarnessProcessObservationDeps = {},
2003
+ ): { outcome: 'sent' | 'refused'; owned: boolean; runState: string; reason: string } {
2004
+ const refuse = (reason: string, owned = false, runState = 'unknown') => ({ outcome: 'refused' as const, owned, runState, reason });
2005
+ let result: ReturnType<typeof refuse> | { outcome: 'sent'; owned: true; runState: string; reason: string };
2006
+ let handle: HarnessProcessSignalHandle | undefined;
2007
+ let handleFailure: string | undefined;
2008
+ if (Number.isSafeInteger(pid) && pid > 1) {
2009
+ try { handle = (deps.openProcessHandle ?? openHarnessProcessHandle)(pid); }
2010
+ catch (error) { handleFailure = observationFailureReason(error); }
2011
+ }
2012
+ try {
2013
+ const root = deps.repositoryRoot ?? findGitDir(process.cwd())?.root;
2014
+ const listed = normalizeProcessListObservation(deps.listProcesses?.() ?? defaultListHarnessProcesses());
2015
+ const row = listed.status === 'ok' ? listed.records.find((record) => record.pid === pid) : undefined;
2016
+ const prefix = root ? `${resolve(root)}${sep}` : '';
2017
+ const entry = prefix ? `${prefix}bin/elanous.mjs` : '';
2018
+ const argv = row?.command ?? '';
2019
+ const entryIndex = entry && [
2020
+ `bun ${entry} `, `${process.execPath} ${entry} `,
2021
+ `bun bin/elanous.mjs `,
2022
+ ].find((start) => argv.startsWith(start));
2023
+ const fromRepo = Boolean(entryIndex && (entryIndex !== 'bun bin/elanous.mjs ' || row?.cwd && resolve(row.cwd) === resolve(root!)));
2024
+ if (!Number.isSafeInteger(pid) || pid <= 1) result = refuse('invalid pid');
2025
+ else if (listed.status !== 'ok') result = refuse('process observation incomplete');
2026
+ else if (!row) result = refuse('pid not found in harness process population');
2027
+ 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');
2028
+ else if (!handle) result = refuse(`pid-bound signaling unavailable: ${handleFailure ?? 'unknown failure'}`);
2029
+ else {
2030
+ let startTime: string | undefined;
2031
+ try {
2032
+ startTime = (deps.readStartTime ?? ((target) => execFileSync('ps', ['-p', String(target), '-o', 'lstart='], { encoding: 'utf8', timeout: 2_000 }).trim()))(pid);
2033
+ } catch { /* unavailable is not a timestamp */ }
2034
+ if (!startTime || !Number.isFinite(Date.parse(startTime))) result = refuse('process start time unreadable');
2035
+ else {
2036
+ const ownership = row.ownership ?? readProcessOwnership(pid);
2037
+ const runId = ownership.status === 'observed' ? ownership.runId : undefined;
2038
+ if (!runId) result = refuse('owning run unconfirmed');
2039
+ else {
2040
+ let ledger: readonly HarnessProcessLedgerEntry[] | null = null;
2041
+ try { ledger = (deps.lookupLedger ?? defaultLookupHarnessProcessLedger)(runId, ownership.status === 'observed' ? ownership.stateDir : undefined); }
2042
+ catch { /* fail closed */ }
2043
+ const last = [...(ledger ?? [])].reverse().find((entry) => entry.event === 'run-status');
2044
+ const runState = typeof last?.data?.runStatus === 'string' ? last.data.runStatus : 'unknown';
2045
+ if (!ledger || !last) result = refuse('owning run ledger unavailable', true, runState);
2046
+ else if (!['running', 'completed', 'failed', 'cancelled', 'abandoned'].includes(runState)) result = refuse('owning run status unconfirmed', true, runState);
2047
+ else if (runState === 'running' && !force) result = refuse('owning run is not terminal (use --force)', true, runState);
2048
+ else {
2049
+ try {
2050
+ const currentStart = (deps.readStartTime ?? ((target) => execFileSync('ps', ['-p', String(target), '-o', 'lstart='], { encoding: 'utf8', timeout: 2_000 }).trim()))(pid);
2051
+ if (currentStart !== startTime) result = refuse('pid start time changed', true, runState);
2052
+ else {
2053
+ handle.signal('SIGTERM');
2054
+ result = { outcome: 'sent', owned: true, runState, reason: 'SIGTERM sent' };
2055
+ }
2056
+ } catch (error) { result = refuse(`SIGTERM failed: ${observationFailureReason(error)}`, true, runState); }
2057
+ }
2058
+ }
2059
+ }
2060
+ }
2061
+ debug.log('harness.processes', 'kill', { pid, ...result });
2062
+ return result;
2063
+ } finally { handle?.close(); }
2064
+ }
2065
+
1717
2066
  function installHarnessProcessObservationCommand(
1718
2067
  harnessCmd: Command,
1719
2068
  deps: HarnessProcessObservationDeps = {},
@@ -1721,8 +2070,18 @@ function installHarnessProcessObservationCommand(
1721
2070
  const write = deps.write ?? ((text: string) => { console.log(text); });
1722
2071
  return harnessCmd
1723
2072
  .command('processes')
1724
- .description('이 저장소가 띄운 OS 프로세스를 읽기 전용으로 분류한다. 자원을 먹는 무리와 오래 떠 있는 무리를 가른다. 죽이지 않는다.')
1725
- .action(() => {
2073
+ .description('기본 읽기 전용 분류. --kill <pid> 는 소유 런 확인 후 단일 PID 에만 SIGTERM 한다.')
2074
+ .option('--kill <pid>', '소유 런을 확인한 뒤 지정한 PID 하나만 SIGTERM')
2075
+ .option('--force', '소유 런이 진행 중이어도 지정한 PID 하나를 종료')
2076
+ .action((opts: { kill?: string; force?: boolean }) => {
2077
+ if (opts.kill !== undefined) {
2078
+ const pid = Number(opts.kill);
2079
+ const result = killHarnessProcess(pid, opts.force === true, deps);
2080
+ write(`pid=${opts.kill} ${result.outcome}: ${result.reason}`);
2081
+ if (result.outcome === 'refused') process.exitCode = 1;
2082
+ return;
2083
+ }
2084
+ if (opts.force) { write('--force requires --kill <pid>'); process.exitCode = 2; return; }
1726
2085
  const records = deps.listProcesses?.() ?? defaultListHarnessProcesses();
1727
2086
  const worktrees = deps.listWorktrees?.() ?? defaultListHarnessWorktreePaths();
1728
2087
  const launchd = deps.observeLaunchdPids?.() ?? observeHarnessLaunchdPids();
@@ -1749,6 +2108,7 @@ export interface HarnessCliCommandDeps {
1749
2108
  say?: HarnessSayHandler;
1750
2109
  /** Observe-only Pod host dispatch seam. */
1751
2110
  podDispatchTask?: (input: DispatchTaskInput, deps?: DispatchTaskDeps) => ReturnType<typeof dispatchTask>;
2111
+ launchGate?: PreLaunchGateDeps & { readBudget?: () => Promise<BudgetDecision | 'unknown'> };
1752
2112
  plan?: HarnessPlanHandler;
1753
2113
  /** ⭐ `plan` 주입이 «없을 때» 가는 기본 분기. 시험이 이 자리로 «CLI 의 기본 배선»을 문다
1754
2114
  * (⛔ 주입된 `plan` 이 파일을 스스로 만들면 그 시험은 배선을 «못 답한다» — 무인 리뷰 GOODHART 지적). */
@@ -1819,6 +2179,7 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
1819
2179
  }
1820
2180
  return resolved.substrate === 'pod' ? onPod(opts, 'cli-harness-ask', goalPath, resolved.pool!, deps.podDispatchTask) : ask(goalPath, normalizeHarnessAskSayOptions(opts));
1821
2181
  },
2182
+ deps.launchGate,
1822
2183
  );
1823
2184
  });
1824
2185
  }
@@ -1843,6 +2204,7 @@ export function installHarnessCliCommand(program: Command, deps: HarnessCliComma
1843
2204
  }
1844
2205
  return resolved.substrate === 'pod' ? onPod(opts, 'cli-harness-say', sentence.join(' '), resolved.pool!, deps.podDispatchTask) : say(sentence, normalizeHarnessAskSayOptions(opts));
1845
2206
  },
2207
+ deps.launchGate,
1846
2208
  );
1847
2209
  });
1848
2210
  }