elanous 0.2.9 → 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 (694) 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/5845-e6c003ce8d5fd36a.js +1 -0
  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-f972fc1c00a62e88.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-adfbd2ba9598e59a.js → page-35414e0a007b4082.js} +1 -1
  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 -0
  152. package/apps/pwa/out/ops/seats/index.txt +30 -0
  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 -0
  178. package/apps/pwa/out/today/index.txt +33 -0
  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/field/field-feed.yaml +2 -0
  194. package/graphs/implement-loop.yaml +1 -1
  195. package/graphs/intake/intake-daily.yaml +2 -1
  196. package/graphs/ops/recipes.yaml +3 -0
  197. package/graphs/ops/secret-exposure.yaml +24 -0
  198. package/graphs/release/recipes.yaml +3 -0
  199. package/graphs/release/release-loop.yaml +4 -1
  200. package/graphs/video/explainer-line.yaml +2 -2
  201. package/package.json +2 -1
  202. package/plugins/card-followup/graphs/run-step.ts +48 -13
  203. package/plugins/doc-draft/graphs/doc-draft.yaml +3 -3
  204. package/plugins/doc-draft/graphs/run-step.ts +13 -6
  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/ci-pwa-build-gate.ts +160 -0
  216. package/scripts/context-hooks/claude-stop.sh +4 -0
  217. package/scripts/context-hooks/emit.ts +24 -0
  218. package/scripts/context-hooks/post-tool-use.sh +4 -0
  219. package/scripts/coord-channel-watch.sh +54 -8
  220. package/scripts/coord-digest.ts +199 -0
  221. package/scripts/coord-post.sh +60 -3
  222. package/scripts/coord-requests-bridge.ts +143 -0
  223. package/scripts/field-feed/lib.ts +4 -0
  224. package/scripts/fleet/node-setup.sh +20 -3
  225. package/scripts/homebrew-formula-bump.ts +69 -0
  226. package/scripts/install.ps1 +68 -9
  227. package/scripts/install.sh +39 -12
  228. package/scripts/lib/pwa-scenarios/scenarios.ts +20 -0
  229. package/scripts/lib/tui-regress-checks.ts +146 -0
  230. package/scripts/marketing/measure-site-numbers.ts +169 -0
  231. package/scripts/measure-gate-shards.ts +309 -0
  232. package/scripts/memory-lifecycle-cycle.ts +2 -2
  233. package/scripts/mission-request-judge.ts +31 -1
  234. package/scripts/morning-report.ts +2 -2
  235. package/scripts/opportunity-scan.ts +1 -1
  236. package/scripts/ops-now-probe.ts +327 -0
  237. package/scripts/publish-internal-dist.ts +11 -1
  238. package/scripts/release-loop/auto-approve-node.ts +21 -4
  239. package/scripts/release-loop/cut-branch.ts +84 -0
  240. package/scripts/release-loop/cutoff.ts +19 -8
  241. package/scripts/release-loop/gate-node.ts +14 -13
  242. package/scripts/release-loop/mac-smoke-node.ts +229 -0
  243. package/scripts/release-loop/node-verdict.ts +3 -3
  244. package/scripts/release-loop/ops-upgrade-node.ts +72 -16
  245. package/scripts/release-loop/release-readiness.ts +9 -0
  246. package/scripts/release-loop/tui-node-checks.ts +42 -0
  247. package/scripts/release-loop/tui-sim-node.ts +32 -8
  248. package/scripts/release-loop/unattended-release.ts +5 -3
  249. package/scripts/release-loop/version-node.ts +112 -13
  250. package/scripts/repo-watch-cycle.ts +1 -1
  251. package/scripts/retro-cycle.ts +2 -2
  252. package/scripts/schedule-health-report.ts +1 -1
  253. package/scripts/signal-digest-cycle.ts +2 -7
  254. package/scripts/signal-digest-photo.ts +11 -0
  255. package/scripts/storyboard/storyboard.ts +5 -161
  256. package/scripts/tech1-public-measure.ts +94 -0
  257. package/scripts/test-diet/lib.ts +30 -1
  258. package/scripts/test-diet/node.ts +83 -8
  259. package/scripts/test-timeout-audit.ts +114 -0
  260. package/scripts/tree-sync-alert.ts +1 -1
  261. package/scripts/tui-regress.ts +71 -0
  262. package/scripts/ux/demo-rehearsal.ts +243 -0
  263. package/scripts/ux/lib/rehearsal-verdict.ts +73 -0
  264. package/scripts/waitlist-daily-digest.ts +1 -1
  265. package/skills/diagram-master/SKILL.md +366 -0
  266. package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
  267. package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
  268. package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
  269. package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
  270. package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
  271. package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
  272. package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
  273. package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
  274. package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
  275. package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
  276. package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
  277. package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
  278. package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
  279. package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
  280. package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
  281. package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
  282. package/skills/diagram-master/references/examples/README.md +69 -0
  283. package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
  284. package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
  285. package/skills/diagram-master/references/pyproject.toml +16 -0
  286. package/skills/diagram-master/references/quality-checklist.md +33 -0
  287. package/skills/diagram-master/references/routing-guide.md +164 -0
  288. package/skills/diagram-master/references/uv.lock +1356 -0
  289. package/skills/explainer-video/SKILL.md +4 -0
  290. package/skills/explainer-video/engine/reel.mjs +18 -13
  291. package/skills/explainer-video/engine/reel.sh +24 -5
  292. package/skills/explainer-video/engine/stitch.mjs +145 -0
  293. package/skills/google-workspace/SKILL.md +33 -0
  294. package/skills/google-workspace/scripts/gws-safe.sh +177 -0
  295. package/skills/grill-me/SKILL.md +1 -1
  296. package/skills/lecture-note-digitizer/SKILL.md +926 -0
  297. package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
  298. package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
  299. package/skills/lecture-note-digitizer/references/html-template.md +167 -0
  300. package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
  301. package/skills/omni-crawl/SKILL.md +21 -11
  302. package/skills/omni-crawl/scripts/main.ts +6 -6
  303. package/skills/omni-crawl/src/router.ts +3 -3
  304. package/skills/omni-digest/SKILL.md +17 -9
  305. package/skills/omni-digest/digest.md +2 -2
  306. package/skills/omni-digest/src/fetch.ts +30 -3
  307. package/skills/pitch-deck/SKILL.md +36 -0
  308. package/skills/pitch-deck/template.html +80 -0
  309. package/skills/youtube-master/SKILL.md +163 -0
  310. package/skills/youtube-master/package-lock.json +558 -0
  311. package/skills/youtube-master/package.json +13 -0
  312. package/skills/youtube-master/references/study-note-template.md +124 -0
  313. package/skills/youtube-master/scripts/main.ts +435 -0
  314. package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
  315. package/skills/youtube-master/src/audio.ts +63 -0
  316. package/skills/youtube-master/src/domain-staging.ts +50 -0
  317. package/skills/youtube-master/src/env.ts +36 -0
  318. package/skills/youtube-master/src/obsidian.ts +155 -0
  319. package/skills/youtube-master/src/router.ts +110 -0
  320. package/skills/youtube-master/src/stt.ts +199 -0
  321. package/skills/youtube-master/src/study-note.ts +175 -0
  322. package/skills/youtube-master/src/summarize.ts +358 -0
  323. package/skills/youtube-master/src/transcript.ts +76 -0
  324. package/skills/youtube-master/src/types.ts +91 -0
  325. package/skills/youtube-master/src/util.ts +93 -0
  326. package/skills/youtube-master/src/youtube.ts +70 -0
  327. package/skills/youtube-master/tsconfig.json +13 -0
  328. package/src/acp/codex-approval-adapter.ts +9 -3
  329. package/src/acp/core-turn-bridge.ts +117 -18
  330. package/src/acp/fact-question.ts +11 -0
  331. package/src/acp/server.ts +53 -9
  332. package/src/acp/tool-approval.ts +126 -0
  333. package/src/acp/turn-runner.ts +36 -0
  334. package/src/agent/monad-agent-turn.ts +8 -0
  335. package/src/agent-mission/driver.ts +80 -10
  336. package/src/agent-mission/pty-decision.ts +71 -0
  337. package/src/agent-mission/review-loop.ts +30 -0
  338. package/src/ask-user-question/pending-questions.ts +25 -10
  339. package/src/ask-user-question/types.ts +9 -0
  340. package/src/auth/setup-link-tokens.ts +16 -5
  341. package/src/autopilot/build/integrity-gate.ts +12 -0
  342. package/src/autopilot/build/llm-conflict-merge.ts +16 -3
  343. package/src/autopilot/tool-registry.ts +2 -0
  344. package/src/boot/daemon-prompt-turn.ts +8 -0
  345. package/src/boot/daemon-runtime.ts +9 -3
  346. package/src/boot/daemon-tools/index.ts +8 -0
  347. package/src/boot/daemon-tools/types.ts +2 -0
  348. package/src/boot/daemon-tools/web-search.ts +4 -0
  349. package/src/card-followup/core.ts +109 -0
  350. package/src/chat/ctrl-c-in-input.ts +14 -0
  351. package/src/chat/index.ts +53 -0
  352. package/src/chat/pickers/state.ts +6 -2
  353. package/src/cli/agent-cli.ts +7 -0
  354. package/src/cli/decisions-cli.ts +25 -3
  355. package/src/cli/doctor-bundle-upload.ts +68 -0
  356. package/src/cli/doctor-cli.ts +38 -4
  357. package/src/cli/drive-input-jail.ts +101 -0
  358. package/src/cli/hooks-cli.ts +17 -3
  359. package/src/cli/make-cli.ts +43 -0
  360. package/src/cli/ops-cli.ts +20 -0
  361. package/src/cli/persona-cli.ts +90 -4
  362. package/src/cli/plugin-cli.ts +31 -22
  363. package/src/cli/pod-cli.ts +61 -2
  364. package/src/cli/pr-cli.ts +82 -17
  365. package/src/cli/pty-drive-cli.ts +41 -7
  366. package/src/cli/pty-drive-verdict.ts +40 -0
  367. package/src/cli/pwa-stop.ts +163 -13
  368. package/src/cli/pwa-test.ts +3 -0
  369. package/src/cli/release-cli.ts +80 -24
  370. package/src/cli/self-update.ts +14 -0
  371. package/src/cli/setup-cli.ts +43 -1
  372. package/src/cli/skills-cli.ts +17 -1
  373. package/src/cli/storyboard-cli.ts +37 -0
  374. package/src/cli/test-state-dir-flag.ts +11 -4
  375. package/src/connectors/linear.ts +146 -0
  376. package/src/context-bus/claude-hooks-install.ts +10 -0
  377. package/src/context-bus/context-now-surfaces.ts +48 -0
  378. package/src/context-bus/context-now.ts +104 -0
  379. package/src/context-bus/coord-events.ts +115 -0
  380. package/src/context-bus/external-events.ts +52 -0
  381. package/src/context-bus/long-term-memory.ts +108 -0
  382. package/src/dashboard/dashboard-boot-fixture.ts +23 -0
  383. package/src/dashboard/index.ts +63 -21
  384. package/src/dashboard/slash-runtime/dashboard-handlers.ts +14 -1
  385. package/src/dashboard/slash-runtime/help-from-registry.ts +43 -28
  386. package/src/decisions/decision-cards.ts +58 -3
  387. package/src/decisions/decision-ledger.ts +85 -6
  388. package/src/decisions/decision-linear-projection.ts +157 -0
  389. package/src/decisions/web-push-decision-cards.ts +50 -0
  390. package/src/directive/interpretation-card.ts +36 -0
  391. package/src/discord/sprint21-runtime.ts +5 -1
  392. package/src/discord-self-message.ts +32 -0
  393. package/src/discord-slash-wire.ts +5 -1
  394. package/src/discord.ts +19 -2
  395. package/src/domains/coo-admin-tool.ts +62 -0
  396. package/src/domains/core-tools.ts +13 -4
  397. package/src/domains/elanous-card.ts +29 -0
  398. package/src/domains/ops-facts-tool.ts +76 -0
  399. package/src/domains/outbound-alert.ts +46 -13
  400. package/src/domains/release-tool.ts +168 -0
  401. package/src/domains/telegram-kind-route.ts +65 -9
  402. package/src/exec-requests/default-outputs.ts +25 -0
  403. package/src/exec-requests/planner.ts +106 -28
  404. package/src/exec-requests/runner.ts +123 -12
  405. package/src/exec-requests/store.ts +11 -2
  406. package/src/execution-loop/launch-gate.ts +100 -0
  407. package/src/field/field-media.ts +10 -7
  408. package/src/field/field-reel.ts +19 -5
  409. package/src/field-note/index.ts +201 -0
  410. package/src/field-note/transcribe.ts +248 -0
  411. package/src/git-fs/worktree.ts +45 -6
  412. package/src/graph-kinds/registry.ts +3 -3
  413. package/src/graph-runner/graph-approval-card.ts +113 -0
  414. package/src/graph-runner/graph-cli.ts +189 -4
  415. package/src/graph-runner/graph-grow-llm.ts +37 -0
  416. package/src/graph-runner/graph-grow.ts +47 -0
  417. package/src/graph-runner/graph-notify.ts +25 -3
  418. package/src/graph-runner/runner.ts +453 -35
  419. package/src/grok/agent-search.ts +8 -2
  420. package/src/guardian/secret-exposure-scan.ts +101 -0
  421. package/src/harness/browser-verify.ts +25 -2
  422. package/src/harness/harness-cli-command.ts +478 -42
  423. package/src/harness/harness-incidents-writer.fixture.ts +24 -0
  424. package/src/harness/harness-incidents.ts +129 -0
  425. package/src/harness/harness-pod-dispatch.ts +43 -23
  426. package/src/harness/harness-seams.ts +38 -4
  427. package/src/harness/harness-stop.ts +75 -6
  428. package/src/harness/launch-registry.ts +91 -0
  429. package/src/harness/process-garbage.ts +5 -3
  430. package/src/hitl/clarification-policy.ts +3 -1
  431. package/src/hooks/dispatch.ts +82 -0
  432. package/src/hooks/expose.ts +254 -0
  433. package/src/hooks/github-shadow.ts +108 -0
  434. package/src/hooks/providers.ts +71 -5
  435. package/src/hooks/queue.ts +1 -1
  436. package/src/hooks/receiver.ts +21 -20
  437. package/src/index.ts +206 -49
  438. package/src/intake-plane/author-goals.ts +37 -4
  439. package/src/intake-plane/categorize.ts +18 -46
  440. package/src/intake-plane/check.ts +3 -0
  441. package/src/intake-plane/discord-seat-work.ts +57 -2
  442. package/src/intake-plane/front-route-classifier.ts +33 -39
  443. package/src/intake-plane/persona-answer.ts +30 -0
  444. package/src/intake-plane/runtime-callables.ts +8 -1
  445. package/src/intake-plane/seat-doc-route.ts +170 -6
  446. package/src/intake-plane/telegram-seat-work.ts +80 -4
  447. package/src/intake-plane/telegram-work.ts +1 -0
  448. package/src/intake-plane/wish-folder.ts +67 -0
  449. package/src/intent-gate/gate.ts +30 -10
  450. package/src/live/detail-switch.ts +5 -0
  451. package/src/llm/difficulty.ts +57 -0
  452. package/src/llm/judge-layer.ts +101 -0
  453. package/src/llm/mission-router.ts +33 -19
  454. package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
  455. package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
  456. package/src/loops/contract/examples/steward.loop.yaml +50 -0
  457. package/src/loops/contract/loop-agent.schema.json +138 -0
  458. package/src/loops/contract/validate.ts +64 -0
  459. package/src/loops/registry.ts +20 -6
  460. package/src/market/signed-index.ts +4 -0
  461. package/src/maturity/bot-command-maturity.ts +45 -0
  462. package/src/maturity/cli-maturity.ts +34 -0
  463. package/src/maturity/feature-maturity.ts +120 -1
  464. package/src/maturity/tui-slash-maturity.ts +31 -0
  465. package/src/memory.ts +32 -4
  466. package/src/model-tier/index.ts +2 -2
  467. package/src/model-tier/tier-resolver.ts +20 -20
  468. package/src/model-tier/types.ts +6 -6
  469. package/src/mss/logging/log-store.ts +15 -0
  470. package/src/nexus/api/config-model-tier.ts +5 -4
  471. package/src/nexus/api/exec-requests.ts +33 -3
  472. package/src/nexus/api/fabric-plans.ts +53 -0
  473. package/src/nexus/api/harness-api.ts +5 -1
  474. package/src/nexus/api/health.ts +2 -0
  475. package/src/nexus/api/http-server.ts +89 -1
  476. package/src/nexus/api/inside-events.ts +226 -0
  477. package/src/nexus/api/meta-api.ts +32 -8
  478. package/src/nexus/api/missions.ts +6 -1
  479. package/src/nexus/api/ops-api.ts +10 -1
  480. package/src/nexus/api/ops-seats-sources.ts +37 -7
  481. package/src/nexus/api/ops-seats.ts +49 -6
  482. package/src/nexus/api/outputs-route.ts +44 -0
  483. package/src/nexus/api/seat-requests.ts +132 -10
  484. package/src/nexus/api/sessions-store.ts +42 -0
  485. package/src/nexus/api/setup-codex-login.ts +160 -0
  486. package/src/nexus/api/sub-seat-charters.ts +34 -0
  487. package/src/nexus/api/tabs-mutations.ts +3 -1
  488. package/src/nexus/api/trace.ts +18 -6
  489. package/src/nexus/api/usage-api.ts +102 -0
  490. package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
  491. package/src/nexus/api/workflows.ts +80 -6
  492. package/src/nexus/index.ts +47 -4
  493. package/src/nexus/kinds/webterm.ts +2 -1
  494. package/src/nexus/webterm/pty.ts +6 -2
  495. package/src/onboarding/cli-auth-status.ts +80 -0
  496. package/src/onboarding/first-run.ts +89 -0
  497. package/src/onboarding/lan-address.ts +45 -0
  498. package/src/onboarding/voice-ai.ts +3 -3
  499. package/src/onboarding/web-first.ts +119 -24
  500. package/src/onboarding.ts +4 -0
  501. package/src/ops-now/ops-now-refresh.ts +100 -0
  502. package/src/org/seat-budget.ts +48 -0
  503. package/src/org/stall-escalation.ts +63 -0
  504. package/src/outputs/ledger.ts +120 -0
  505. package/src/persona/persona-todo.ts +79 -0
  506. package/src/persona/presets.ts +116 -2
  507. package/src/persona/team-set.ts +155 -0
  508. package/src/plugins/install/plugin-install.ts +14 -0
  509. package/src/plugins/maker/market-bundle.ts +109 -0
  510. package/src/plugins/maker/plugin-maker.ts +254 -11
  511. package/src/plugins/maker/wizard-generate.ts +103 -0
  512. package/src/pod-lease/admission.ts +150 -0
  513. package/src/pod-lease/dependency-state.ts +85 -0
  514. package/src/pod-lease/host-lease.ts +127 -0
  515. package/src/project/project-store.ts +115 -0
  516. package/src/project/project-suggestion.ts +16 -0
  517. package/src/project/session-context.ts +24 -0
  518. package/src/release-loop/checklist.ts +79 -5
  519. package/src/release-loop/feature-store.ts +159 -24
  520. package/src/release-loop/next-md-merge.ts +58 -0
  521. package/src/release-loop/release-note.ts +59 -4
  522. package/src/release-loop/release-schedule.ts +53 -0
  523. package/src/repl/index.ts +7 -0
  524. package/src/seat-dispatch/ceo-commands.ts +41 -8
  525. package/src/seat-dispatch/ceo-intent.ts +38 -0
  526. package/src/seat-dispatch/seat-ask.ts +130 -0
  527. package/src/seat-dispatch/seat-questions.ts +100 -0
  528. package/src/seat-loop/seat-loop.ts +750 -0
  529. package/src/seat-loop/seat-report.ts +99 -0
  530. package/src/self-dev/decompose.ts +66 -11
  531. package/src/self-dev/dev-cli.ts +4 -1
  532. package/src/self-dev/dev-pipeline.ts +37 -1
  533. package/src/self-dev/draft-sweep.ts +38 -33
  534. package/src/self-dev/draft-triage-rules.ts +8 -5
  535. package/src/self-dev/fabric-plan-core.ts +297 -0
  536. package/src/self-dev/orchestrate.ts +36 -4
  537. package/src/self-dev/release-path-guard.ts +62 -0
  538. package/src/self-dev/run-store.ts +10 -1
  539. package/src/self-dev/shard-aggregate.ts +230 -0
  540. package/src/self-dev/shard-placement.ts +60 -0
  541. package/src/self-dev/shard-plan.ts +48 -0
  542. package/src/self-dev/shard-pod-run.ts +77 -0
  543. package/src/self-dev/shard-run.ts +105 -0
  544. package/src/self-implement/execution-clarification.ts +115 -0
  545. package/src/self-implement/gate-baseline.ts +1 -1
  546. package/src/self-implement/gate-cli.ts +46 -4
  547. package/src/self-implement/gate-scope.ts +37 -7
  548. package/src/self-implement/graph-variant.ts +171 -0
  549. package/src/self-implement/harness-policy-gates.ts +1 -1
  550. package/src/self-implement/headless-elanous-driver.ts +22 -3
  551. package/src/self-implement/host-regate.ts +22 -1
  552. package/src/self-implement/importer-test-index.ts +2 -1
  553. package/src/self-implement/l8-merge-queue.ts +130 -0
  554. package/src/self-implement/orchestrator.ts +279 -12
  555. package/src/self-implement/pipeline-shape.ts +1 -1
  556. package/src/self-implement/route-consumer-test-index.ts +122 -0
  557. package/src/self-implement/run-status-mapping.ts +5 -3
  558. package/src/self-implement/seams.ts +72 -11
  559. package/src/self-implement/test-seams.ts +1 -0
  560. package/src/self-implement/uncommitted-work.ts +59 -0
  561. package/src/session/chat.ts +2 -0
  562. package/src/session/index.ts +45 -13
  563. package/src/shell-env-bootstrap.ts +17 -0
  564. package/src/skills/gift-install.ts +215 -0
  565. package/src/skills/tools/web-search.ts +4 -1
  566. package/src/steward/directive.ts +51 -2
  567. package/src/steward/launch.ts +266 -0
  568. package/src/steward/outcome-notify.ts +115 -0
  569. package/src/steward/steward-cards.ts +25 -11
  570. package/src/steward/triage-plan.ts +32 -4
  571. package/src/steward/triage.ts +129 -13
  572. package/src/steward/working-backwards.ts +64 -0
  573. package/src/storyboard/storyboard.ts +141 -0
  574. package/src/task-cards/card-cli.ts +25 -1
  575. package/src/task-cards/card-store.ts +2 -2
  576. package/src/task-orchestrator/mission.ts +5 -0
  577. package/src/task-orchestrator/store.ts +12 -3
  578. package/src/task-orchestrator/surfaces/pod-command-job.ts +29 -7
  579. package/src/task-orchestrator/surfaces/pod-lease.ts +397 -0
  580. package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
  581. package/src/task-orchestrator/surfaces/self-implement-pod.ts +214 -40
  582. package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
  583. package/src/task-orchestrator/types.ts +2 -0
  584. package/src/telegram-card-followup.ts +153 -0
  585. package/src/telegram-commands.ts +10 -1
  586. package/src/telegram-project-command.ts +71 -0
  587. package/src/telegram-report.ts +29 -19
  588. package/src/telegram-run.ts +7 -0
  589. package/src/telegram.ts +58 -11
  590. package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
  591. package/src/tool-runtime/types.ts +4 -0
  592. package/src/tui-client/dashboard-session.ts +2 -0
  593. package/src/user-config.ts +216 -27
  594. package/src/version/packed-revision.json +1 -1
  595. package/src/web-push/notify-exec-request.ts +32 -0
  596. package/src/web-search/grok.ts +7 -1
  597. package/src/web-search/index.ts +28 -1
  598. package/src/web-search/provider.ts +4 -0
  599. package/src/web-search/x-intent.ts +5 -0
  600. package/src/workflow-runtime/executor.ts +277 -47
  601. package/src/workflow-runtime/index.ts +1 -0
  602. package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
  603. package/src/workflow-runtime/plugin-kind-node.ts +1 -1
  604. package/src/workflow-runtime/schema.ts +79 -4
  605. package/src/workflow-runtime/types.ts +35 -4
  606. package/apps/pwa/out/_next/static/bFI5EEwg7T6aG88ibX4Zq/_buildManifest.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
  617. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
  618. package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/5080-1613752891fcadb4.js +0 -10
  622. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/6090-85a3f05f954e5697.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6284-69db415193d5f8bd.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7032-f4ef698518fba61c.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/8067-d976b441a104ab74.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/8519-5632377cce994f86.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8630-cdfc61e82c653ffc.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8894-e263b332208e3957.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/9454-139040d37c79dbc9.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/9740-8f5ff96c522b5f55.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/approvals/page-fb7c2d458f32fcad.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-35e2713597dd24d1.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/board/page-918b656f064577ba.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/bots/page-5f30e00693527ebd.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/chat/page-7fbae173b3c103a7.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b4edcce364062ea.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/control/page-c5794f484c251f44.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1130d8eefcd87e76.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/editor/page-973996d584f008c1.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/exec/page-016e2bda04eecb1f.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/field/page-b4d6d9a3b56f2940.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/intake/page-ec49a466121233ba.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/layout-f72db356744ceade.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/live/page-a6fd9b50d1b85378.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/market/page-8b0402a46a749a3d.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-037f83e2a1edc8e2.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/not-found-46fedff57d4bec67.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/observatory/page-0cf318e9dcee2bbf.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-899b327cb8b6845c.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6c1e6ba743a29dfe.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/page-1a8e4807292f6b17.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/reflection/page-28deba6bcb834916.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-de68e2205794037d.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/sessions/page-c71c33a573230672.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-0df30e0c7e50148a.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/settings/page-4fc56790fe0d2682.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-59df2aebb38a7c1e.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/setup/page-4647be5dbcbd0795.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/share/page-e025892bda74b743.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/showroom/page-a0955de73b89f078.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/tasks/page-369846d2921af584.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/term/page-72cbc1c8cdd0f65d.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/trace/page-77b28bfb0996d5ea.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/vault/page-3220c4934f49c6c2.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-90670589b87abea8.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/workflows/page-7df9243ed021a4cc.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/workspace/page-4498c3853f4f688d.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-35bedde6d885f08f.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/main-app-6870f30ea99f8346.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
  692. package/apps/pwa/out/_next/static/css/f92f63a5df0ba229.css +0 -1
  693. package/src/dashboard/turn-typeahead-echo.ts +0 -23
  694. /package/apps/pwa/out/_next/static/{bFI5EEwg7T6aG88ibX4Zq → Y4zKzL62sakG5momz3SoQ}/_ssgManifest.js +0 -0
@@ -0,0 +1,24 @@
1
+ import { Database } from 'bun:sqlite';
2
+ import { existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { recordRunExit, type RunExit } from './harness-incidents.js';
5
+
6
+ const [root, json, mode] = process.argv.slice(2);
7
+ if (!root || !json) throw new Error('root and exit are required');
8
+ const exit = JSON.parse(json) as RunExit;
9
+ if (mode === 'hold') {
10
+ const db = new Database(join(root, '.incident-write-lock.sqlite'));
11
+ db.exec('BEGIN IMMEDIATE');
12
+ process.stdout.write('locked\n');
13
+ // Released by a file, not a signal: SIGUSR2 handlers are not delivered reliably under Bun on macOS.
14
+ const release = join(root, 'release-hold');
15
+ await new Promise<void>((done) => {
16
+ const timer = setInterval(() => { if (existsSync(release)) { clearInterval(timer); done(); } }, 20);
17
+ });
18
+ db.exec('COMMIT');
19
+ db.close();
20
+ recordRunExit(exit, root);
21
+ process.exit(0);
22
+ } else {
23
+ recordRunExit(exit, root);
24
+ }
@@ -0,0 +1,129 @@
1
+ import { Database } from 'bun:sqlite';
2
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+
5
+ export interface RunExit {
6
+ runId: string;
7
+ reason: string;
8
+ status: number | null;
9
+ signal: string | null;
10
+ at: string;
11
+ }
12
+
13
+ export interface IncidentBurst {
14
+ reason: string;
15
+ count: number;
16
+ firstAt: string;
17
+ lastAt: string;
18
+ runIds: string[];
19
+ }
20
+
21
+ const KST_OFFSET_MS = 9 * 60 * 60_000;
22
+ const INCIDENT_FILE = /^\d{4}-\d{2}-\d{2}\.jsonl$/;
23
+
24
+ function kstDate(at: number): string {
25
+ return new Date(at + KST_OFFSET_MS).toISOString().slice(0, 10);
26
+ }
27
+
28
+ /** Read only recorded exits. Missing ledgers are not evidence that no runs failed. */
29
+ export function readRunExits(root: string): RunExit[] {
30
+ const dir = join(root, 'incidents');
31
+ if (!existsSync(dir)) return [];
32
+ const rows: RunExit[] = [];
33
+ const seen = new Set<string>();
34
+ for (const file of readdirSync(dir).filter((name) => INCIDENT_FILE.test(name)).sort()) {
35
+ const path = join(dir, file);
36
+ let text: string;
37
+ try {
38
+ if (!statSync(path).isFile()) continue;
39
+ text = readFileSync(path, 'utf8');
40
+ } catch (error) {
41
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') continue;
42
+ throw error;
43
+ }
44
+ for (const line of text.split('\n')) {
45
+ if (!line.trim()) continue;
46
+ let value: unknown;
47
+ try { value = JSON.parse(line); } catch { continue; }
48
+ if (!value || typeof value !== 'object') continue;
49
+ const row = value as Partial<RunExit>;
50
+ if (typeof row.runId !== 'string' || !row.runId.trim() || seen.has(row.runId)
51
+ || typeof row.reason !== 'string' || typeof row.at !== 'string' || !Number.isFinite(Date.parse(row.at))
52
+ || !(row.status === null || typeof row.status === 'number')
53
+ || !(row.signal === null || typeof row.signal === 'string')) continue;
54
+ seen.add(row.runId);
55
+ rows.push(row as RunExit);
56
+ }
57
+ }
58
+ return rows.sort((a, b) => Date.parse(a.at) - Date.parse(b.at) || a.runId.localeCompare(b.runId));
59
+ }
60
+
61
+ /** SQLite's process-owned write lock serializes ledger checks and appends across processes. */
62
+ export function recordRunExit(row: RunExit, root: string): void {
63
+ if (!row.runId?.trim()) return;
64
+ const at = Date.parse(row.at);
65
+ if (!Number.isFinite(at)) throw new Error('invalid incident exit time');
66
+ const dir = join(root, 'incidents');
67
+ mkdirSync(dir, { recursive: true });
68
+ const lock = new Database(join(root, '.incident-write-lock.sqlite'));
69
+ try {
70
+ lock.exec('PRAGMA busy_timeout = 60000');
71
+ lock.exec('BEGIN IMMEDIATE');
72
+ try {
73
+ if (!readRunExits(root).some((record) => record.runId === row.runId)) {
74
+ appendFileSync(join(dir, `${kstDate(at)}.jsonl`), `${JSON.stringify(row)}\n`);
75
+ }
76
+ lock.exec('COMMIT');
77
+ } catch (error) {
78
+ lock.exec('ROLLBACK');
79
+ throw error;
80
+ }
81
+ } finally {
82
+ lock.close();
83
+ }
84
+ }
85
+
86
+ /** Non-overlapping, maximal same-reason windows; no run contributes to two bursts. */
87
+ export function detectBursts(rows: readonly RunExit[], { windowMs = 60_000, threshold = 3 }: {
88
+ windowMs?: number; threshold?: number;
89
+ } = {}): IncidentBurst[] {
90
+ const bursts: IncidentBurst[] = [];
91
+ const byReason = new Map<string, RunExit[]>();
92
+ const seen = new Set<string>();
93
+ for (const row of rows) {
94
+ if (!row.runId || seen.has(row.runId) || !Number.isFinite(Date.parse(row.at))) continue;
95
+ seen.add(row.runId);
96
+ const group = byReason.get(row.reason) ?? [];
97
+ group.push(row);
98
+ byReason.set(row.reason, group);
99
+ }
100
+ for (const [reason, group] of byReason) {
101
+ group.sort((a, b) => Date.parse(a.at) - Date.parse(b.at) || a.runId.localeCompare(b.runId));
102
+ for (let start = 0; start < group.length;) {
103
+ let end = start + 1;
104
+ while (end < group.length && Date.parse(group[end]!.at) - Date.parse(group[start]!.at) <= windowMs) end++;
105
+ if (end - start < threshold) { start++; continue; }
106
+ const members = group.slice(start, end);
107
+ bursts.push({ reason, count: members.length, firstAt: members[0]!.at,
108
+ lastAt: members[members.length - 1]!.at, runIds: members.map((row) => row.runId) });
109
+ start = end;
110
+ }
111
+ }
112
+ return bursts.sort((a, b) => Date.parse(a.firstAt) - Date.parse(b.firstAt) || a.reason.localeCompare(b.reason));
113
+ }
114
+
115
+ export function recentBurst(root: string, now: Date | number, { lookbackMs = 15 * 60_000 }: {
116
+ lookbackMs?: number;
117
+ } = {}): IncidentBurst | null {
118
+ const time = typeof now === 'number' ? now : now.getTime();
119
+ const recent = detectBursts(readRunExits(root)).filter((burst) => {
120
+ const last = Date.parse(burst.lastAt);
121
+ return last <= time && last >= time - lookbackMs;
122
+ });
123
+ return recent.sort((a, b) => Date.parse(a.lastAt) - Date.parse(b.lastAt)).at(-1) ?? null;
124
+ }
125
+
126
+ export function formatIncidentBurstWarning(burst: IncidentBurst): string {
127
+ const time = new Date(Date.parse(burst.lastAt) + KST_OFFSET_MS).toISOString().slice(11, 16);
128
+ return `⚠ 최근 묶음 사고: ${burst.reason} ×${burst.count} (${time} KST) — 원인 확인 전 재발사는 중복·재사고 위험 · elanous harness incidents`;
129
+ }
@@ -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' };
@@ -7,15 +7,52 @@
7
7
  //
8
8
  // ⛔ 불변식: 기록된 시작 시각과 실제 프로세스 시작 시각이 다르면 신호를 보내지 않는다(PID 재사용 방지).
9
9
  // ⛔ 불변식: `elanous.run=<runId>` 라벨이 붙은 Job 만 지운다.
10
+ // ⛔ 불변식: 짧은 runId 의 후보가 둘 이상이면 프로세스 신호·Job 삭제 전에 중단한다.
10
11
 
11
- import { readFileSync, readlinkSync } from 'node:fs';
12
+ import { existsSync, readdirSync, readFileSync, readlinkSync } from 'node:fs';
12
13
  import { isAbsolute, join, resolve } from 'node:path';
13
14
  import { spawnSync } from 'node:child_process';
14
15
  import { debug } from '../debug/log.js';
15
16
  import { selfDevRunsDir } from '../self-dev/run-store.js';
16
- import { loadRunLedger, runLedgerDir } from '../self-implement/run-ledger.js';
17
+ import { launchBindingRunIds, launchRegistryDir, readLaunchBinding } from './launch-registry.js';
18
+ import { loadRunLedger, resolveFederatedRunLedgerDirectories, runLedgerDir } from '../self-implement/run-ledger.js';
17
19
 
18
20
  const RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
21
+ const FULL_RUN_ID = /^run-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
22
+
23
+ export class AmbiguousHarnessStopRunIdError extends Error {
24
+ constructor(given: string, candidates: readonly string[]) {
25
+ super(`harness stop ${given}: 더 긴 id 를 주십시오\n${candidates.map((id) => ` ${id}`).join('\n')}`);
26
+ this.name = 'AmbiguousHarnessStopRunIdError';
27
+ }
28
+ }
29
+
30
+ /** List names, not ledger bodies: a run may have written its pid.json before its ledger. */
31
+ export function stopRunIdCandidates(given: string, ledgerDirs: readonly string[], runsDir: string): string[] {
32
+ const found = new Set<string>();
33
+ for (const dir of ledgerDirs) {
34
+ let names: string[];
35
+ try { names = readdirSync(dir); }
36
+ catch (error) {
37
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') continue;
38
+ throw error;
39
+ }
40
+ for (const name of names) {
41
+ if (!name.endsWith('.jsonl')) continue;
42
+ const id = name.slice(0, -'.jsonl'.length);
43
+ if (FULL_RUN_ID.test(id) && id.startsWith(given)) found.add(id);
44
+ }
45
+ }
46
+ try {
47
+ for (const entry of readdirSync(runsDir, { withFileTypes: true })) {
48
+ if (entry.isDirectory() && entry.name.startsWith(given) && FULL_RUN_ID.test(entry.name)
49
+ && existsSync(join(runsDir, entry.name, 'pid.json'))) found.add(entry.name);
50
+ }
51
+ } catch (error) {
52
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
53
+ }
54
+ return [...found].sort();
55
+ }
19
56
  /** `pid.json` 의 `startedAt` 은 `Date.now() − uptime` 근삿값이다 — 이만큼의 차이는 같은 프로세스로 본다. */
20
57
  export const START_TOLERANCE_MS = 5_000;
21
58
 
@@ -101,6 +138,7 @@ function scanStopProcessTable(runId: string, goalPath: string | null): StopProce
101
138
 
102
139
  export interface HarnessStopDeps {
103
140
  readPidRecord: (runId: string) => PidRecord | null;
141
+ runIdCandidates?: (given: string) => string[];
104
142
  readGoalPath: (runId: string) => string | null;
105
143
  scanProcesses: (runId: string, goalPath: string | null) => StopProcessScan;
106
144
  /** 살아 있는 프로세스의 시작 시각(ms) · 없으면 null. */
@@ -115,6 +153,7 @@ export interface HarnessStopDeps {
115
153
 
116
154
  export interface HarnessStopResult {
117
155
  runId: string;
156
+ givenRunId?: string;
118
157
  process: 'stopped' | 'killed' | 'absent' | 'owner-mismatch' | 'unmeasured' | 'dry-run';
119
158
  pid?: number;
120
159
  candidates: StopProcessCandidate[];
@@ -135,6 +174,16 @@ export function readPidRecordFrom(runsDir: string, runId: string): PidRecord | n
135
174
  }
136
175
  }
137
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
+
138
187
  /** macOS·Linux 공통 — `ps -o lstart=` 는 로컬 시각 문자열(초 단위)이다. */
139
188
  export function psProcessStartMs(pid: number): number | null {
140
189
  const r = spawnSync('ps', ['-o', 'lstart=', '-p', String(pid)], { encoding: 'utf8', timeout: 5_000 });
@@ -145,7 +194,8 @@ export function psProcessStartMs(pid: number): number | null {
145
194
  return Number.isFinite(ms) ? ms : null;
146
195
  }
147
196
 
148
- export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {}): HarnessStopDeps {
197
+ export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {}, opts: { launchRegistryDir?: string } = {}): HarnessStopDeps {
198
+ const registry = opts.launchRegistryDir ?? launchRegistryDir();
149
199
  const env = { ...process.env };
150
200
  for (const key of ['HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy', 'ALL_PROXY', 'all_proxy']) delete env[key];
151
201
  const kubectl = (args: readonly string[]) => {
@@ -153,8 +203,19 @@ export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {})
153
203
  return { status: r.status, stdout: r.stdout ?? '', stderr: r.stderr ?? String(r.error ?? '') };
154
204
  };
155
205
  return {
156
- readPidRecord: (runId) => readPidRecordFrom(selfDevRunsDir(), runId),
157
- readGoalPath: stopGoalPathFromLedger,
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),
208
+ runIdCandidates: (given) => {
209
+ const ledgerDirs = new Set([runLedgerDir(), ...resolveFederatedRunLedgerDirectories({})]);
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;
218
+ },
158
219
  scanProcesses: scanStopProcessTable,
159
220
  processStartMs: psProcessStartMs,
160
221
  kill: (pid, signal) => { process.kill(pid, signal); },
@@ -172,6 +233,13 @@ export function defaultHarnessStopDeps(overrides: Partial<HarnessStopDeps> = {})
172
233
 
173
234
  export async function stopHarnessRun(runId: string, deps: HarnessStopDeps, contexts?: readonly string[], dryRun = false): Promise<HarnessStopResult> {
174
235
  if (!RUN_ID.test(runId)) throw new Error(`invalid run id: ${runId}`);
236
+ const given = runId;
237
+ if (!FULL_RUN_ID.test(given)) {
238
+ const matches = [...new Set(deps.runIdCandidates?.(given) ?? [])].sort();
239
+ if (matches.length === 1) runId = matches[0]!;
240
+ debug.log('harness.stop', 'run-id-resolved', { given, resolved: runId, candidates: matches });
241
+ if (matches.length > 1) throw new AmbiguousHarnessStopRunIdError(given, matches);
242
+ }
175
243
  // ── ⓐ 프로세스 ────────────────────────────────────────────
176
244
  let processState: HarnessStopResult['process'] = 'absent';
177
245
  const record = deps.readPidRecord(runId);
@@ -235,7 +303,7 @@ export async function stopHarnessRun(runId: string, deps: HarnessStopDeps, conte
235
303
  if (r.status === 0) jobsDeleted += r.stdout.split('\n').filter((line) => line.startsWith('job.batch/')).length;
236
304
  else debug.log('harness.stop', 'job-delete-failed', { runId, context, error: r.stderr.slice(0, 200) }, { level: 'warn' });
237
305
  }
238
- const result: HarnessStopResult = { runId, process: processState, ...(record ? { pid: record.pid } : {}), candidates, scanned: scan.status === 'ok', pidRecordFound: record !== null, dryRun, jobsDeleted, contexts: targets };
306
+ const result: HarnessStopResult = { runId, ...(given !== runId ? { givenRunId: given } : {}), process: processState, ...(record ? { pid: record.pid } : {}), candidates, scanned: scan.status === 'ok', pidRecordFound: record !== null, dryRun, jobsDeleted, contexts: targets };
239
307
  debug.log('harness.stop', 'stopped', { runId, process: processState, jobsDeleted, contexts: targets.length });
240
308
  return result;
241
309
  }
@@ -249,6 +317,7 @@ export function formatHarnessStop(r: HarnessStopResult): string {
249
317
  'owner-mismatch': '소유 불일치(건드리지 않음 — PID 가 다른 프로세스로 재사용됐다)',
250
318
  };
251
319
  return [
320
+ ...(r.givenRunId ? [`↳ ${r.givenRunId} → ${r.runId}(전체)`] : []),
252
321
  `harness stop ${r.runId}`,
253
322
  ` 프로세스: ${label[r.process]}${r.pid ? ` · pid ${r.pid}` : ''}`,
254
323
  ...(!r.scanned && r.process !== 'unmeasured' ? [' 프로세스 표: 못 잼(기록 밖 발사 프로세스는 확인하지 못함)'] : []),
@@ -0,0 +1,91 @@
1
+ /** Host-wide run → process binding for `harness stop`, independent of the launching worktree and its universe.
2
+ * A run launched from another worktree writes `pid.json` and its ledger under that tree's state dir, so a stop from
3
+ * any other tree found «no pid.json · goal path 0» while the launcher was alive (10-03 · 09-29). The binding below lives
4
+ * in a per-user directory under the OS temp dir — it only has to outlive the process it names, not a reboot. */
5
+ import { closeSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
6
+ import { tmpdir, userInfo } from 'node:os';
7
+ import { isAbsolute, join, resolve } from 'node:path';
8
+ import { randomUUID } from 'node:crypto';
9
+ import { debug } from '../debug/log.js';
10
+
11
+ export interface LaunchBinding {
12
+ readonly pid: number;
13
+ /** Same approximation as `pid.json` (`Date.now() − uptime`) — compared with `ps` start time before any signal. */
14
+ readonly startedAt: number;
15
+ readonly argv0?: string;
16
+ /** The launching process's working directory (absolute). */
17
+ readonly cwd: string;
18
+ /** Absolute goal document path when the launcher was given one (`--goal-file`/`--ask`/`--goal`). */
19
+ readonly goalPath?: string;
20
+ /** The `self-dev-runs` directory that holds this run's `pid.json` — tells a stop which universe launched it. */
21
+ readonly runsDir?: string;
22
+ }
23
+
24
+ const RUN_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
25
+
26
+ /** One directory per OS user: `$TMPDIR` is per-user on macOS, `/tmp` is shared on Linux. */
27
+ export function launchRegistryDir(): string {
28
+ let uid: string;
29
+ try { uid = String(userInfo().uid); } catch { uid = 'unknown'; }
30
+ return join(tmpdir(), `elanous-harness-launches-${uid}`);
31
+ }
32
+
33
+ /** The goal document named in an argv, resolved against `cwd` — the same option set `harness stop` already matches. */
34
+ export function goalPathFromArgv(argv: readonly string[], cwd: string): string | undefined {
35
+ for (let i = 0; i < argv.length; i++) {
36
+ const arg = argv[i]!;
37
+ let value: string | undefined;
38
+ for (const flag of ['--goal-file', '--ask', '--goal']) {
39
+ if (arg === flag) value = argv[i + 1];
40
+ else if (arg.startsWith(`${flag}=`)) value = arg.slice(flag.length + 1);
41
+ }
42
+ if (value?.trim()) return isAbsolute(value) ? resolve(value) : resolve(cwd, value);
43
+ }
44
+ return undefined;
45
+ }
46
+
47
+ export function writeLaunchBinding(runId: string, binding: LaunchBinding, dir = launchRegistryDir()): string | null {
48
+ if (!RUN_ID.test(runId)) return null;
49
+ try {
50
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
51
+ const path = join(dir, `${runId}.json`);
52
+ const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
53
+ const fd = openSync(temporary, 'wx', 0o600);
54
+ try { writeFileSync(fd, JSON.stringify(binding)); } finally { closeSync(fd); }
55
+ renameSync(temporary, path);
56
+ debug.log('harness.launch-registry', 'bound', { runId, pid: binding.pid, goalPath: binding.goalPath ?? null });
57
+ return path;
58
+ } catch (error) {
59
+ debug.log('harness.launch-registry', 'bind-failed', { runId, error: String(error) }, { level: 'warn' });
60
+ return null;
61
+ }
62
+ }
63
+
64
+ export function readLaunchBinding(runId: string, dir = launchRegistryDir()): LaunchBinding | null {
65
+ if (!RUN_ID.test(runId)) return null;
66
+ try {
67
+ const value = JSON.parse(readFileSync(join(dir, `${runId}.json`), 'utf8')) as Partial<LaunchBinding>;
68
+ if (!Number.isSafeInteger(value.pid) || (value.pid as number) <= 0 || !Number.isFinite(value.startedAt)) return null;
69
+ if (typeof value.cwd !== 'string' || !isAbsolute(value.cwd)) return null;
70
+ return {
71
+ pid: value.pid as number, startedAt: value.startedAt as number, cwd: value.cwd,
72
+ ...(typeof value.argv0 === 'string' ? { argv0: value.argv0 } : {}),
73
+ ...(typeof value.goalPath === 'string' && isAbsolute(value.goalPath) ? { goalPath: value.goalPath } : {}),
74
+ ...(typeof value.runsDir === 'string' && isAbsolute(value.runsDir) ? { runsDir: value.runsDir } : {}),
75
+ };
76
+ } catch { return null; }
77
+ }
78
+
79
+ export function removeLaunchBinding(runId: string, dir = launchRegistryDir()): void {
80
+ if (!RUN_ID.test(runId)) return;
81
+ try { unlinkSync(join(dir, `${runId}.json`)); }
82
+ catch (error) {
83
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') debug.log('harness.launch-registry', 'unbind-failed', { runId, error: String(error) }, { level: 'warn' });
84
+ }
85
+ }
86
+
87
+ /** Run IDs with a live-looking binding — used for stop's prefix resolution next to ledgers and `pid.json` names. */
88
+ export function launchBindingRunIds(dir = launchRegistryDir()): string[] {
89
+ try { return readdirSync(dir).filter((name) => name.endsWith('.json')).map((name) => name.slice(0, -5)).filter((id) => RUN_ID.test(id)); }
90
+ catch { return []; }
91
+ }
@@ -12,7 +12,9 @@ export interface GarbageProcess extends Pick<GarbageProcessRow, 'pid' | 'ppid' |
12
12
 
13
13
  const TEST_PATH = /elanous|repo\.worktrees|self-impl|\.elanous-test|gate-baseline/i;
14
14
  const TEST_DAEMON = /(?:^|[\s/])daemon\.ts(?:\s|$)/;
15
- const TEST_RUNNER = /\bbun\s+test\b|\bgate(?:[-\s]baseline|\b)/i;
15
+ const TEST_RUNNER = /^(?:\S*\/)?bun\s+test(?:\s|$)/i;
16
+ // Only the command itself counts — `bun [run|x] <…gate…>`; goal text later in argv must not (PROC1).
17
+ const GATE_RUNNER = /^(?:\S*\/)?bun\s+(?:(?:run|x)\s+)?\S*gate(?:[-\s]baseline|\b)/i;
16
18
  const NEXUS_RUN = /\bnexus\s+run\b/;
17
19
  const TEST_MARKER = /\.elanous-test|(?:^|\s)--test(?:\s|$)/;
18
20
 
@@ -20,7 +22,7 @@ const TEST_MARKER = /\.elanous-test|(?:^|\s)--test(?:\s|$)/;
20
22
  export function isGarbageProcessTarget(command: string): boolean {
21
23
  return command.includes('elanous.mjs')
22
24
  || (TEST_DAEMON.test(command) && /elanous-nexus-|\.elanous-test/.test(command))
23
- || (TEST_RUNNER.test(command) && TEST_PATH.test(command));
25
+ || ((TEST_RUNNER.test(command) || GATE_RUNNER.test(command)) && TEST_PATH.test(command));
24
26
  }
25
27
 
26
28
  export function classifyGarbage(
@@ -36,7 +38,7 @@ export function classifyGarbage(
36
38
  const reason: GarbageProcess['reason'] = TEST_DAEMON.test(row.command)
37
39
  && /elanous-nexus-|\.elanous-test/.test(row.command)
38
40
  ? 'orphan-test-daemon'
39
- : TEST_RUNNER.test(row.command) && TEST_PATH.test(row.command)
41
+ : (TEST_RUNNER.test(row.command) || GATE_RUNNER.test(row.command)) && TEST_PATH.test(row.command)
40
42
  ? 'orphan-test-runner'
41
43
  : 'orphan-elanous';
42
44
  garbage.push({ pid: row.pid, ppid: row.ppid, elapsedSeconds: row.elapsedSeconds, command: row.command, reason });
@@ -182,7 +182,7 @@ export function decideAndObserveClarification(
182
182
  impact: candidate.impact,
183
183
  action: decision.action,
184
184
  reason: decision.reason,
185
- recommendedOption: decision.recommendedOption,
185
+ ...(context.phase === 'execution' ? {} : { recommendedOption: decision.recommendedOption }),
186
186
  budgetUsed: context.budget.used,
187
187
  budgetLimit: context.budget.limit,
188
188
  });
@@ -210,6 +210,8 @@ export function toAskUserQuestionRequest(decision: ClarificationDecision): AskUs
210
210
  header: 'Direction',
211
211
  question: `${candidate.prompt}\n\nRecommended: ${decision.recommendedOption}. ${candidate.whyNow}`,
212
212
  options: candidate.options.map(({ recommended: _recommended, ...option }) => option),
213
+ impact: candidate.impact,
214
+ recommendedIndex: candidate.options.findIndex(option => option.recommended),
213
215
  includeOther: true,
214
216
  };
215
217
  return { questions: [question] };