elanous 0.2.10 → 0.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (584) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/Y4zKzL62sakG5momz3SoQ/_buildManifest.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1394-556de6d71bbdb0fb.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
  7. package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/2310-7a59f043f6db207e.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/2548-6e316138d347cefe.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/3869-a39d1d9921e10d43.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
  19. package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
  20. package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
  25. package/apps/pwa/out/_next/static/chunks/507-5acd98bd6dab2d8a.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/5445-745eb795c5963d79.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
  31. package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/8605-ea5bee9dfae512c7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1dcdc58fc2de2454.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-6a061bd97f0b9398.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/board/page-cb95a7432c9ee744.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-b12b6d2f8d2d1aea.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/app/bots/page-b9efe868bfd36255.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/chat/page-7c97dcdfe2e37a60.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/consult/page-8fd36984f549270a.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/control/page-5721537ca8a3598c.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/design-check/page-b654240a572e4c48.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/editor/page-b9750abc897508c3.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/exec/page-4cd1de371f8ad048.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/field/page-d99f89657828421c.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/app/inside/page-50cb2a0eb15e6c83.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/intake/page-c8b1ccda6ba7ae98.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/layout-d6b1d156fb95e74b.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/live/page-2a9932ddb62d76bd.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/market/page-9688f5b4f1ff950f.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6b15dd6456c5df09.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/morning/page-35414e0a007b4082.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/not-found-e7a529e0507ac86c.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/observatory/page-e001823c35c9dd67.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-371423d1a573d64b.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4b764b125339ac17.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cdf8e4b01067bcf1.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a24072b35470157.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/page-94c82eb0ae5abb32.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/reflection/page-0be8d4b2ced75ba0.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d37cb0d52f9b6bd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/sessions/page-686da0df9bf23e5c.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4dc614f3ce043e63.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/settings/page-53f80edc6b8dc07c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-d02c782fc792e2af.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/app/setup/page-239c17b911b84e72.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/app/share/page-dc6a79fb003f746c.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/app/showroom/page-0fffb84cafdc9da6.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/app/tasks/page-1218753c82d585f6.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/app/term/page-4b5935e67531efb5.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/app/today/page-3285bc87caf1eaa5.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/app/trace/page-ad553b0e06505ecd.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/app/vault/page-fca096e3e860306f.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ebfa78f0d9885c3.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/app/workflows/page-3dc5f21f7e39622d.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/app/workspace/page-c6da2b468454532d.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-93bc70e36f595414.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → f48170cc-d05d28bf87a43bf4.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +1 -0
  105. package/apps/pwa/out/_next/static/css/543f56bcb1f79fca.css +1 -0
  106. package/apps/pwa/out/approvals/index.html +1 -1
  107. package/apps/pwa/out/approvals/index.txt +23 -23
  108. package/apps/pwa/out/autopilot/index.html +1 -1
  109. package/apps/pwa/out/autopilot/index.txt +23 -23
  110. package/apps/pwa/out/board/index.html +1 -1
  111. package/apps/pwa/out/board/index.txt +23 -23
  112. package/apps/pwa/out/botlab/index.html +1 -1
  113. package/apps/pwa/out/botlab/index.txt +22 -22
  114. package/apps/pwa/out/bots/index.html +1 -1
  115. package/apps/pwa/out/bots/index.txt +22 -22
  116. package/apps/pwa/out/chat/index.html +1 -1
  117. package/apps/pwa/out/chat/index.txt +22 -22
  118. package/apps/pwa/out/consult/index.html +1 -1
  119. package/apps/pwa/out/consult/index.txt +23 -23
  120. package/apps/pwa/out/control/index.html +1 -1
  121. package/apps/pwa/out/control/index.txt +23 -23
  122. package/apps/pwa/out/design-check/index.html +1 -1
  123. package/apps/pwa/out/design-check/index.txt +23 -23
  124. package/apps/pwa/out/editor/index.html +1 -1
  125. package/apps/pwa/out/editor/index.txt +23 -23
  126. package/apps/pwa/out/exec/index.html +1 -1
  127. package/apps/pwa/out/exec/index.txt +23 -23
  128. package/apps/pwa/out/field/index.html +1 -1
  129. package/apps/pwa/out/field/index.txt +23 -23
  130. package/apps/pwa/out/healthz +1 -1
  131. package/apps/pwa/out/index.html +1 -1
  132. package/apps/pwa/out/index.txt +22 -22
  133. package/apps/pwa/out/inside/index.html +1 -0
  134. package/apps/pwa/out/inside/index.txt +31 -0
  135. package/apps/pwa/out/intake/index.html +1 -1
  136. package/apps/pwa/out/intake/index.txt +23 -23
  137. package/apps/pwa/out/live/index.html +1 -1
  138. package/apps/pwa/out/live/index.txt +23 -23
  139. package/apps/pwa/out/market/index.html +1 -1
  140. package/apps/pwa/out/market/index.txt +22 -22
  141. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  142. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  143. package/apps/pwa/out/morning/index.html +1 -1
  144. package/apps/pwa/out/morning/index.txt +23 -23
  145. package/apps/pwa/out/observatory/index.html +1 -1
  146. package/apps/pwa/out/observatory/index.txt +23 -23
  147. package/apps/pwa/out/ops/checklist/index.html +1 -1
  148. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  149. package/apps/pwa/out/ops/release/index.html +1 -1
  150. package/apps/pwa/out/ops/release/index.txt +22 -22
  151. package/apps/pwa/out/ops/seats/index.html +1 -1
  152. package/apps/pwa/out/ops/seats/index.txt +22 -22
  153. package/apps/pwa/out/outputs/index.html +1 -0
  154. package/apps/pwa/out/outputs/index.txt +30 -0
  155. package/apps/pwa/out/reflection/index.html +1 -1
  156. package/apps/pwa/out/reflection/index.txt +23 -23
  157. package/apps/pwa/out/scheduler/index.html +1 -1
  158. package/apps/pwa/out/scheduler/index.txt +23 -23
  159. package/apps/pwa/out/sessions/index.html +1 -1
  160. package/apps/pwa/out/sessions/index.txt +22 -22
  161. package/apps/pwa/out/settings/devices/index.html +1 -1
  162. package/apps/pwa/out/settings/devices/index.txt +23 -23
  163. package/apps/pwa/out/settings/index.html +1 -1
  164. package/apps/pwa/out/settings/index.txt +23 -23
  165. package/apps/pwa/out/setup/done/index.html +1 -1
  166. package/apps/pwa/out/setup/done/index.txt +23 -23
  167. package/apps/pwa/out/setup/index.html +1 -1
  168. package/apps/pwa/out/setup/index.txt +23 -23
  169. package/apps/pwa/out/share/index.html +1 -1
  170. package/apps/pwa/out/share/index.txt +23 -23
  171. package/apps/pwa/out/showroom/index.html +1 -1
  172. package/apps/pwa/out/showroom/index.txt +22 -22
  173. package/apps/pwa/out/tasks/index.html +1 -1
  174. package/apps/pwa/out/tasks/index.txt +23 -23
  175. package/apps/pwa/out/term/index.html +1 -1
  176. package/apps/pwa/out/term/index.txt +23 -24
  177. package/apps/pwa/out/today/index.html +1 -1
  178. package/apps/pwa/out/today/index.txt +23 -23
  179. package/apps/pwa/out/trace/index.html +1 -1
  180. package/apps/pwa/out/trace/index.txt +23 -23
  181. package/apps/pwa/out/vault/index.html +1 -1
  182. package/apps/pwa/out/vault/index.txt +23 -23
  183. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  184. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  185. package/apps/pwa/out/workflows/index.html +1 -1
  186. package/apps/pwa/out/workflows/index.txt +23 -23
  187. package/apps/pwa/out/workspace/index.html +1 -1
  188. package/apps/pwa/out/workspace/index.txt +23 -24
  189. package/apps/pwa/out/worktrees/index.html +1 -1
  190. package/apps/pwa/out/worktrees/index.txt +23 -23
  191. package/graphs/drafts/draft-cleanup.yaml +19 -0
  192. package/graphs/drafts/recipes.yaml +23 -0
  193. package/graphs/intake/intake-daily.yaml +2 -1
  194. package/graphs/ops/recipes.yaml +3 -0
  195. package/graphs/ops/secret-exposure.yaml +24 -0
  196. package/graphs/release/recipes.yaml +3 -0
  197. package/graphs/release/release-loop.yaml +4 -1
  198. package/graphs/video/explainer-line.yaml +2 -2
  199. package/package.json +2 -1
  200. package/plugins/elanous-hwp/README.md +25 -0
  201. package/plugins/elanous-hwp/cli.ts +22 -0
  202. package/plugins/elanous-hwp/converter.ts +237 -0
  203. package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
  204. package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
  205. package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
  206. package/plugins/elanous-hwp/plugin.json +16 -0
  207. package/plugins/elanous-hwp/plugin.ts +40 -0
  208. package/scripts/ci-public-export-leak-gate.ts +75 -14
  209. package/scripts/ci-public-leak-gate.ts +44 -9
  210. package/scripts/context-hooks/claude-stop.sh +4 -0
  211. package/scripts/context-hooks/emit.ts +24 -0
  212. package/scripts/context-hooks/post-tool-use.sh +4 -0
  213. package/scripts/coord-channel-watch.sh +12 -0
  214. package/scripts/coord-requests-bridge.ts +143 -0
  215. package/scripts/field-feed/lib.ts +4 -0
  216. package/scripts/fleet/node-setup.sh +20 -3
  217. package/scripts/homebrew-formula-bump.ts +69 -0
  218. package/scripts/marketing/measure-site-numbers.ts +169 -0
  219. package/scripts/measure-gate-shards.ts +309 -0
  220. package/scripts/mission-request-judge.ts +31 -1
  221. package/scripts/morning-report.ts +2 -2
  222. package/scripts/opportunity-scan.ts +1 -1
  223. package/scripts/release-loop/auto-approve-node.ts +21 -4
  224. package/scripts/release-loop/cut-branch.ts +84 -0
  225. package/scripts/release-loop/gate-node.ts +14 -13
  226. package/scripts/release-loop/mac-smoke-node.ts +229 -0
  227. package/scripts/release-loop/node-verdict.ts +3 -3
  228. package/scripts/release-loop/tui-node-checks.ts +42 -0
  229. package/scripts/release-loop/tui-sim-node.ts +32 -8
  230. package/scripts/release-loop/unattended-release.ts +5 -3
  231. package/scripts/release-loop/version-node.ts +61 -10
  232. package/scripts/signal-digest-cycle.ts +2 -7
  233. package/scripts/signal-digest-photo.ts +11 -0
  234. package/scripts/tech1-public-measure.ts +94 -0
  235. package/scripts/test-diet/node.ts +1 -1
  236. package/scripts/tui-regress.ts +2 -2
  237. package/scripts/ux/demo-rehearsal.ts +243 -0
  238. package/scripts/ux/lib/rehearsal-verdict.ts +73 -0
  239. package/skills/diagram-master/SKILL.md +366 -0
  240. package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
  241. package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
  242. package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
  243. package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
  244. package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
  245. package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
  246. package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
  247. package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
  248. package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
  249. package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
  250. package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
  251. package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
  252. package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
  253. package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
  254. package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
  255. package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
  256. package/skills/diagram-master/references/examples/README.md +69 -0
  257. package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
  258. package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
  259. package/skills/diagram-master/references/pyproject.toml +16 -0
  260. package/skills/diagram-master/references/quality-checklist.md +33 -0
  261. package/skills/diagram-master/references/routing-guide.md +164 -0
  262. package/skills/diagram-master/references/uv.lock +1356 -0
  263. package/skills/google-workspace/SKILL.md +33 -0
  264. package/skills/google-workspace/scripts/gws-safe.sh +177 -0
  265. package/skills/grill-me/SKILL.md +1 -1
  266. package/skills/lecture-note-digitizer/SKILL.md +926 -0
  267. package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
  268. package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
  269. package/skills/lecture-note-digitizer/references/html-template.md +167 -0
  270. package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
  271. package/skills/omni-crawl/SKILL.md +21 -11
  272. package/skills/omni-crawl/scripts/main.ts +6 -6
  273. package/skills/omni-crawl/src/router.ts +3 -3
  274. package/skills/omni-digest/SKILL.md +17 -9
  275. package/skills/omni-digest/digest.md +2 -2
  276. package/skills/omni-digest/src/fetch.ts +30 -3
  277. package/skills/pitch-deck/SKILL.md +2 -2
  278. package/skills/pitch-deck/template.html +2 -2
  279. package/skills/youtube-master/SKILL.md +163 -0
  280. package/skills/youtube-master/package-lock.json +558 -0
  281. package/skills/youtube-master/package.json +13 -0
  282. package/skills/youtube-master/references/study-note-template.md +124 -0
  283. package/skills/youtube-master/scripts/main.ts +435 -0
  284. package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
  285. package/skills/youtube-master/src/audio.ts +63 -0
  286. package/skills/youtube-master/src/domain-staging.ts +50 -0
  287. package/skills/youtube-master/src/env.ts +36 -0
  288. package/skills/youtube-master/src/obsidian.ts +155 -0
  289. package/skills/youtube-master/src/router.ts +110 -0
  290. package/skills/youtube-master/src/stt.ts +199 -0
  291. package/skills/youtube-master/src/study-note.ts +175 -0
  292. package/skills/youtube-master/src/summarize.ts +358 -0
  293. package/skills/youtube-master/src/transcript.ts +76 -0
  294. package/skills/youtube-master/src/types.ts +91 -0
  295. package/skills/youtube-master/src/util.ts +93 -0
  296. package/skills/youtube-master/src/youtube.ts +70 -0
  297. package/skills/youtube-master/tsconfig.json +13 -0
  298. package/src/acp/server.ts +5 -2
  299. package/src/agent-mission/driver.ts +80 -10
  300. package/src/agent-mission/pty-decision.ts +71 -0
  301. package/src/agent-mission/review-loop.ts +30 -0
  302. package/src/autopilot/build/llm-conflict-merge.ts +16 -3
  303. package/src/autopilot/tool-registry.ts +2 -0
  304. package/src/boot/daemon-prompt-turn.ts +5 -0
  305. package/src/boot/daemon-runtime.ts +9 -3
  306. package/src/boot/daemon-tools/web-search.ts +3 -0
  307. package/src/card-followup/core.ts +109 -0
  308. package/src/chat/index.ts +1 -0
  309. package/src/cli/drive-input-jail.ts +101 -0
  310. package/src/cli/hooks-cli.ts +17 -3
  311. package/src/cli/make-cli.ts +43 -0
  312. package/src/cli/persona-cli.ts +90 -4
  313. package/src/cli/plugin-cli.ts +31 -22
  314. package/src/cli/pod-cli.ts +19 -9
  315. package/src/cli/pr-cli.ts +51 -15
  316. package/src/cli/pty-drive-cli.ts +41 -7
  317. package/src/cli/pty-drive-verdict.ts +40 -0
  318. package/src/cli/release-cli.ts +17 -4
  319. package/src/cli/setup-cli.ts +43 -1
  320. package/src/cli/skills-cli.ts +17 -1
  321. package/src/context-bus/claude-hooks-install.ts +10 -0
  322. package/src/context-bus/context-now-surfaces.ts +48 -0
  323. package/src/context-bus/context-now.ts +104 -0
  324. package/src/context-bus/coord-events.ts +2 -2
  325. package/src/context-bus/external-events.ts +52 -0
  326. package/src/context-bus/long-term-memory.ts +108 -0
  327. package/src/dashboard/index.ts +9 -4
  328. package/src/dashboard/slash-runtime/dashboard-handlers.ts +7 -1
  329. package/src/decisions/decision-cards.ts +10 -3
  330. package/src/decisions/decision-ledger.ts +13 -5
  331. package/src/discord/sprint21-runtime.ts +5 -1
  332. package/src/discord-self-message.ts +32 -0
  333. package/src/discord-slash-wire.ts +5 -1
  334. package/src/discord.ts +17 -1
  335. package/src/domains/core-tools.ts +3 -2
  336. package/src/domains/outbound-alert.ts +6 -1
  337. package/src/domains/telegram-kind-route.ts +51 -13
  338. package/src/exec-requests/default-outputs.ts +25 -0
  339. package/src/exec-requests/planner.ts +10 -2
  340. package/src/exec-requests/runner.ts +20 -6
  341. package/src/exec-requests/store.ts +3 -0
  342. package/src/execution-loop/launch-gate.ts +100 -0
  343. package/src/field/field-reel.ts +5 -1
  344. package/src/field-note/index.ts +201 -0
  345. package/src/field-note/transcribe.ts +248 -0
  346. package/src/graph-kinds/registry.ts +3 -3
  347. package/src/graph-runner/graph-cli.ts +61 -1
  348. package/src/graph-runner/graph-grow-llm.ts +37 -0
  349. package/src/graph-runner/graph-grow.ts +47 -0
  350. package/src/graph-runner/runner.ts +317 -25
  351. package/src/grok/agent-search.ts +8 -2
  352. package/src/guardian/secret-exposure-scan.ts +101 -0
  353. package/src/harness/harness-cli-command.ts +247 -7
  354. package/src/harness/harness-pod-dispatch.ts +43 -23
  355. package/src/harness/harness-seams.ts +38 -4
  356. package/src/harness/harness-stop.ts +23 -4
  357. package/src/harness/launch-registry.ts +91 -0
  358. package/src/harness/process-garbage.ts +5 -3
  359. package/src/hooks/dispatch.ts +82 -0
  360. package/src/hooks/expose.ts +254 -0
  361. package/src/hooks/github-shadow.ts +108 -0
  362. package/src/hooks/providers.ts +71 -5
  363. package/src/hooks/queue.ts +1 -1
  364. package/src/hooks/receiver.ts +21 -20
  365. package/src/index.ts +52 -14
  366. package/src/intake-plane/categorize.ts +18 -46
  367. package/src/intake-plane/discord-seat-work.ts +10 -0
  368. package/src/intake-plane/front-route-classifier.ts +33 -39
  369. package/src/intake-plane/persona-answer.ts +30 -0
  370. package/src/intake-plane/runtime-callables.ts +8 -1
  371. package/src/intake-plane/telegram-seat-work.ts +36 -2
  372. package/src/intake-plane/wish-folder.ts +67 -0
  373. package/src/intent-gate/gate.ts +30 -10
  374. package/src/live/detail-switch.ts +5 -0
  375. package/src/llm/difficulty.ts +57 -0
  376. package/src/llm/judge-layer.ts +101 -0
  377. package/src/llm/mission-router.ts +33 -19
  378. package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
  379. package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
  380. package/src/loops/contract/examples/steward.loop.yaml +50 -0
  381. package/src/loops/contract/loop-agent.schema.json +138 -0
  382. package/src/loops/contract/validate.ts +64 -0
  383. package/src/loops/registry.ts +20 -6
  384. package/src/market/signed-index.ts +4 -0
  385. package/src/maturity/bot-command-maturity.ts +45 -0
  386. package/src/maturity/feature-maturity.ts +26 -4
  387. package/src/model-tier/index.ts +2 -2
  388. package/src/model-tier/tier-resolver.ts +20 -20
  389. package/src/model-tier/types.ts +6 -6
  390. package/src/mss/logging/log-store.ts +15 -0
  391. package/src/nexus/api/config-model-tier.ts +5 -4
  392. package/src/nexus/api/fabric-plans.ts +53 -0
  393. package/src/nexus/api/harness-api.ts +5 -1
  394. package/src/nexus/api/health.ts +2 -0
  395. package/src/nexus/api/http-server.ts +36 -0
  396. package/src/nexus/api/inside-events.ts +226 -0
  397. package/src/nexus/api/meta-api.ts +21 -8
  398. package/src/nexus/api/missions.ts +6 -1
  399. package/src/nexus/api/ops-seats.ts +33 -0
  400. package/src/nexus/api/outputs-route.ts +44 -0
  401. package/src/nexus/api/seat-requests.ts +44 -2
  402. package/src/nexus/api/sessions-store.ts +17 -38
  403. package/src/nexus/api/sub-seat-charters.ts +34 -0
  404. package/src/nexus/api/tabs-mutations.ts +3 -1
  405. package/src/nexus/api/trace.ts +18 -6
  406. package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
  407. package/src/nexus/api/workflows.ts +80 -6
  408. package/src/nexus/index.ts +2 -0
  409. package/src/nexus/kinds/webterm.ts +2 -1
  410. package/src/nexus/webterm/pty.ts +6 -2
  411. package/src/onboarding/cli-auth-status.ts +80 -0
  412. package/src/onboarding/voice-ai.ts +3 -3
  413. package/src/org/seat-budget.ts +48 -0
  414. package/src/org/stall-escalation.ts +63 -0
  415. package/src/outputs/ledger.ts +120 -0
  416. package/src/persona/persona-todo.ts +79 -0
  417. package/src/persona/presets.ts +116 -2
  418. package/src/persona/team-set.ts +155 -0
  419. package/src/plugins/install/plugin-install.ts +14 -0
  420. package/src/plugins/maker/market-bundle.ts +109 -0
  421. package/src/plugins/maker/plugin-maker.ts +254 -11
  422. package/src/plugins/maker/wizard-generate.ts +103 -0
  423. package/src/pod-lease/admission.ts +150 -0
  424. package/src/pod-lease/dependency-state.ts +85 -0
  425. package/src/pod-lease/host-lease.ts +127 -0
  426. package/src/project/project-suggestion.ts +16 -0
  427. package/src/project/session-context.ts +24 -0
  428. package/src/release-loop/checklist.ts +2 -2
  429. package/src/release-loop/feature-store.ts +5 -3
  430. package/src/release-loop/next-md-merge.ts +58 -0
  431. package/src/release-loop/release-note.ts +59 -4
  432. package/src/seat-dispatch/seat-ask.ts +130 -0
  433. package/src/seat-dispatch/seat-questions.ts +100 -0
  434. package/src/seat-loop/seat-loop.ts +548 -29
  435. package/src/seat-loop/seat-report.ts +37 -2
  436. package/src/self-dev/dev-cli.ts +4 -1
  437. package/src/self-dev/dev-pipeline.ts +37 -1
  438. package/src/self-dev/draft-sweep.ts +38 -33
  439. package/src/self-dev/draft-triage-rules.ts +8 -5
  440. package/src/self-dev/fabric-plan-core.ts +297 -0
  441. package/src/self-dev/orchestrate.ts +36 -4
  442. package/src/self-dev/release-path-guard.ts +62 -0
  443. package/src/self-dev/shard-aggregate.ts +230 -0
  444. package/src/self-dev/shard-placement.ts +60 -0
  445. package/src/self-dev/shard-plan.ts +48 -0
  446. package/src/self-dev/shard-pod-run.ts +77 -0
  447. package/src/self-dev/shard-run.ts +105 -0
  448. package/src/self-implement/gate-baseline.ts +1 -1
  449. package/src/self-implement/gate-cli.ts +40 -1
  450. package/src/self-implement/gate-scope.ts +37 -7
  451. package/src/self-implement/graph-variant.ts +171 -0
  452. package/src/self-implement/harness-policy-gates.ts +1 -1
  453. package/src/self-implement/headless-elanous-driver.ts +22 -3
  454. package/src/self-implement/host-regate.ts +22 -1
  455. package/src/self-implement/importer-test-index.ts +2 -1
  456. package/src/self-implement/l8-merge-queue.ts +130 -0
  457. package/src/self-implement/orchestrator.ts +242 -9
  458. package/src/self-implement/route-consumer-test-index.ts +122 -0
  459. package/src/self-implement/seams.ts +72 -11
  460. package/src/self-implement/test-seams.ts +1 -0
  461. package/src/self-implement/uncommitted-work.ts +59 -0
  462. package/src/session/index.ts +36 -13
  463. package/src/skills/gift-install.ts +215 -0
  464. package/src/skills/tools/web-search.ts +4 -1
  465. package/src/steward/launch.ts +42 -26
  466. package/src/steward/steward-cards.ts +17 -9
  467. package/src/steward/triage.ts +46 -14
  468. package/src/task-cards/card-cli.ts +25 -1
  469. package/src/task-orchestrator/mission.ts +5 -0
  470. package/src/task-orchestrator/store.ts +12 -3
  471. package/src/task-orchestrator/surfaces/pod-command-job.ts +29 -7
  472. package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
  473. package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
  474. package/src/task-orchestrator/surfaces/self-implement-pod.ts +214 -40
  475. package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
  476. package/src/task-orchestrator/types.ts +2 -0
  477. package/src/telegram-card-followup.ts +16 -96
  478. package/src/telegram-commands.ts +10 -1
  479. package/src/telegram-project-command.ts +71 -0
  480. package/src/telegram-report.ts +21 -17
  481. package/src/telegram.ts +29 -3
  482. package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
  483. package/src/user-config.ts +102 -20
  484. package/src/version/packed-revision.json +1 -1
  485. package/src/web-search/grok.ts +7 -1
  486. package/src/web-search/index.ts +28 -1
  487. package/src/web-search/provider.ts +4 -0
  488. package/src/web-search/x-intent.ts +5 -0
  489. package/src/workflow-runtime/executor.ts +277 -47
  490. package/src/workflow-runtime/index.ts +1 -0
  491. package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
  492. package/src/workflow-runtime/plugin-kind-node.ts +1 -1
  493. package/src/workflow-runtime/schema.ts +79 -4
  494. package/src/workflow-runtime/types.ts +35 -4
  495. package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
  505. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
  506. package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
  525. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
  583. package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
  584. /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → Y4zKzL62sakG5momz3SoQ}/_ssgManifest.js +0 -0
package/src/cli/pr-cli.ts CHANGED
@@ -18,7 +18,7 @@ import { runMockModuleRestoreGate } from '../../scripts/ci-mock-module-restore-g
18
18
  import { runModelHardcodeGate } from '../../scripts/ci-model-hardcode-gate.js';
19
19
  import { runDaemonPortGate } from '../../scripts/ci-daemon-port-gate.js';
20
20
  import { runPublicLeakGate } from '../../scripts/ci-public-leak-gate.js';
21
- import { exportLeakCheck, type ExportLeakCheck } from '../../scripts/ci-public-export-leak-gate.js';
21
+ import { exportLeakCheck, publicExportChangedFiles, type ExportLeakCheck } from '../../scripts/ci-public-export-leak-gate.js';
22
22
  import { checkCommands, extractElanousCommands, type Finding as DocsCliFinding } from '../../scripts/docs-cli-check.js';
23
23
  import { runTestInterferenceGate } from '../../scripts/ci-test-interference-gate.js';
24
24
  import { isGoalDocumentFileName } from '../self-implement/goal-document.js';
@@ -104,7 +104,7 @@ export interface PrLandDeps {
104
104
  runMockModuleRestoreGate?: (out: { log: (message: string) => void; error: (message: string) => void }) => boolean;
105
105
  runModelHardcodeGate?: (out: { log: (message: string) => void; error: (message: string) => void }) => boolean;
106
106
  runDaemonPortGate?: (out: { log: (message: string) => void; error: (message: string) => void }) => boolean;
107
- /** 공개 유출 래칫(경고 전용) — 반환 0 통과 · 1 늘었다 · 2 못 쟀다. */
107
+ /** 공개 유출 래칫(경고 전용) — 반환 0 동일 · 1 늘었다 · 2 못 쟀다 · 3 줄었다. */
108
108
  runPublicLeakGate?: (changedFiles: readonly string[], out: { log: (message: string) => void; error: (message: string) => void }) => number;
109
109
  /** Test seam — the post-transform export leak check on changed files. */
110
110
  runExportLeakCheck?: (changedFiles: readonly string[], cwd: string) => ExportLeakCheck;
@@ -275,8 +275,10 @@ export function runPrLandIsolationGate(
275
275
 
276
276
  /** ⭐ 2026-09-24 — 공개 유출 래칫은 «경고만» 낸다(착지를 막지 않는다 · 막는 것은 공개 결정 뒤 · 채널 합의).
277
277
  * 계기: 기준선 뒤 3시간 만에 🅢 착지분에서 유출 증가 다섯을 이 게이트가 잡았다 — 착지 순간에 보여야 그 자리에서 고친다. */
278
- function runPrLandPublicLeakGate(changedFiles: readonly string[], out: { log: (message: string) => void; error: (message: string) => void }): number {
279
- return runPublicLeakGate({ args: ['--changed-files', ...changedFiles], log: out.log, error: out.log });
278
+ function runPrLandPublicLeakGate(changedFiles: readonly string[], out: { log: (message: string) => void; error: (message: string) => void }, cwd: string, baselineRef: string): number {
279
+ const top = runGitCommand(cwd, ['rev-parse', '--show-toplevel'], { encoding: 'utf-8' });
280
+ if (top.status !== 0 || !String(top.stdout ?? '').trim()) return 2;
281
+ return runPublicLeakGate({ args: ['--changed-files', ...changedFiles], root: String(top.stdout).trim(), baselineRef, log: out.log, error: out.log });
280
282
  }
281
283
 
282
284
  /** The prepare check on this landing's changed files — scripts/ci-public-export-leak-gate.ts. */
@@ -285,23 +287,49 @@ export function runPrLandExportLeakCheck(changedFiles: readonly string[], cwd: s
285
287
  return exportLeakCheck(changedFiles, top.status === 0 && String(top.stdout ?? '').trim() ? String(top.stdout).trim() : cwd);
286
288
  }
287
289
 
288
- /** Blocks the landing when changed files would leak into the public export, unless allowPublicLeak. Returns false to stop. */
290
+ /** Blocks changed public files that leak or cannot be measured. */
289
291
  export function exportLeakBlock(
290
292
  changedFiles: readonly string[] | undefined,
291
293
  check: () => ExportLeakCheck,
292
294
  allow: boolean,
293
295
  out: { log: (message: string) => void; error: (message: string) => void },
296
+ cwd: string = process.cwd(),
294
297
  ): boolean {
295
298
  if (!changedFiles || changedFiles.length === 0) return true;
296
299
  let result: ExportLeakCheck;
297
- try { result = check(); } catch (error) { result = { measured: false, hits: [], detail: error instanceof Error ? error.message : String(error) }; }
298
- record('public-export-leak', result.measured ? result.hits.length === 0 || allow : true, { measured: result.measured, hits: result.hits.length, allowed: allow && result.hits.length > 0 });
299
- if (!result.measured) { out.log(`⚠ public-export-leak: 못 쟀다(${result.detail ?? '?'}) — 착지는 막지 않는다. 확인: bun scripts/public-export.ts --leak-check --files <파일…>`); return true; }
300
- if (result.hits.length === 0) { out.log('✓ public-export-leak: 바뀐 파일이 공개본에 사적 흔적을 싣지 않는다(prepare 와 같은 변환 뒤).'); return true; }
300
+ try { result = check(); } catch { result = { measured: false, hits: [], detail: '검사 실행 실패' }; }
301
+ let publicFiles: string[] = [];
302
+ if (!result.measured) {
303
+ try { publicFiles = publicExportChangedFiles(changedFiles, cwd); }
304
+ catch { publicFiles = [...changedFiles]; } // A missing/invalid manifest cannot prove these files are private.
305
+ }
306
+ const applicable = result.hits.filter((hit) => hit.marker !== 'skill-boundary' || changedFiles.includes(hit.file));
307
+ const missingReason: ExportLeakCheck['hits'][number][] = [];
308
+ const blockedHits: ExportLeakCheck['hits'][number][] = [];
309
+ let allowed = 0;
310
+ for (const hit of applicable) {
311
+ let lines: string[];
312
+ try { lines = readFileSync(join(cwd, hit.file), 'utf8').split(/\r?\n/); }
313
+ catch { blockedHits.push(hit); continue; }
314
+ const notes = [lines[hit.line - 1], lines[hit.line - 2]].filter((line): line is string => line !== undefined)
315
+ .map((line) => /(?:\/\/|\/\*|\*|#|<!--)\s*public-export-allow:\s*(.*)/u.exec(line));
316
+ if (notes.some((note) => note?.[1]?.replace(/(?:\*\/|-->)\s*$/u, '').trim())) { allowed++; continue; }
317
+ blockedHits.push(hit);
318
+ if (notes.some(Boolean)) missingReason.push(hit);
319
+ }
320
+ const blocked = (!result.measured && publicFiles.length > 0) || (blockedHits.length > 0 && !allow);
321
+ record('public-export-leak', !blocked, { measured: result.measured, hits: applicable.length, allowed });
322
+ debug.log('pr.land', 'leak-gate', { blocked, hits: applicable.map(({ file, marker }) => ({ file, marker })), measured: result.measured, allowed });
323
+ if (!result.measured) {
324
+ const write = blocked ? out.error : out.log;
325
+ write(`${blocked ? '✗' : '⚠'} public-export-leak: 못 쟀다${blocked ? ' — 막는다' : ' — 공개 대상 변경 없음'}(${result.detail ?? '?'}) · 확인: bun scripts/public-export.ts --leak-check --json --all --files <파일…>`);
326
+ return !blocked;
327
+ }
328
+ if (blockedHits.length === 0) { out.log('✓ public-export-leak: 바뀐 파일이 공개본에 사적 흔적을 싣지 않는다(prepare 와 같은 변환 뒤).'); return true; }
301
329
  const write = allow ? out.log : out.error;
302
- write(`${allow ? '⚠' : '✗'} public-export-leak: 바뀐 파일 ${result.hits.length}곳이 공개본에 사적 흔적을 싣는다 — 다음 release prepare 가 여기서 실패한다:`);
303
- for (const h of result.hits.slice(0, 20)) write(` ${h.file}:${h.line} ${h.marker}`);
304
- if (result.hits.length > 20) write(` … 외 ${result.hits.length - 20}곳`);
330
+ write(`${allow ? '⚠' : '✗'} public-export-leak: 바뀐 파일 ${blockedHits.length}곳이 공개본에 사적 흔적을 싣는다 — 다음 release prepare 가 여기서 실패한다:`);
331
+ for (const hit of blockedHits.slice(0, 20)) write(` ${hit.file}:${hit.line} · ${hit.marker}${missingReason.includes(hit) ? ' · 사유 없음' : ''}`);
332
+ if (blockedHits.length > 20) write(` … 외 ${blockedHits.length - 20}곳`);
305
333
  write(' 확인: bun scripts/public-export.ts --leak-check --all --files <파일…>');
306
334
  if (allow) { out.log(' --allow-public-leak 로 넘긴다(이유는 --land-reason).'); return true; }
307
335
  out.error(' 고치거나, 공개본과 무관한 것이 확실하면 --allow-public-leak --land-reason "<이유>" 로 넘긴다.');
@@ -322,8 +350,12 @@ export function publicLeakWarning(
322
350
  record('public-leak-gate', true, { warnOnly: true, measured: false });
323
351
  return;
324
352
  }
325
- record('public-leak-gate', true, { warnOnly: true, measured: rc !== 2, grew: rc === 1 });
353
+ record('public-leak-gate', true, { warnOnly: true, measured: rc !== 2, grew: rc === 1, shrank: rc === 3 });
326
354
  if (rc === 0) { out.log('✓ public-leak-gate(경고 전용): 공개 유출이 늘지 않았다.'); return; }
355
+ if (rc === 3) {
356
+ for (const line of captured.filter((l) => /→/.test(l))) out.log(`✓ public-leak-gate(경고 전용): 공개 유출이 줄었다 · 기준선 --update 권장 — ${line.trim()}`);
357
+ return;
358
+ }
327
359
  if (rc === 1) {
328
360
  out.log('⚠ public-leak-gate(경고 전용 · 착지는 막지 않는다): 공개 유출이 늘었다 —');
329
361
  for (const line of captured.filter((l) => /→/.test(l))) out.log(` ${line.trim()}`);
@@ -1031,6 +1063,10 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
1031
1063
  out.error('✗ body: --body와 --body-file은 함께 사용할 수 없습니다.');
1032
1064
  return 1;
1033
1065
  }
1066
+ if (opts.allowPublicLeak && !opts.landReason?.trim()) {
1067
+ out.error('✗ public-export-leak: --allow-public-leak 에는 --land-reason "<이유>" 가 필요합니다.');
1068
+ return 1;
1069
+ }
1034
1070
  if (opts.includeActiveRunFiles && opts.excludeActiveRunFiles) {
1035
1071
  out.error('✗ active-run-files: --include-active-run-files와 --exclude-active-run-files는 함께 사용할 수 없습니다.');
1036
1072
  return 1;
@@ -1343,8 +1379,8 @@ export async function runPrLand(opts: PrLandOpts = {}, deps: PrLandDeps = {}): P
1343
1379
 
1344
1380
  const changedPaths = currentChangePaths(run, cwd, staged, base, out);
1345
1381
  nextMdWarning(body ?? '', changedPaths, out);
1346
- publicLeakWarning(changedPaths, deps.runPublicLeakGate ?? runPrLandPublicLeakGate, out);
1347
- if (!exportLeakBlock(changedPaths, () => (deps.runExportLeakCheck ?? runPrLandExportLeakCheck)(changedPaths ?? [], cwd), opts.allowPublicLeak === true, out)) return 1;
1382
+ publicLeakWarning(changedPaths, deps.runPublicLeakGate ?? ((files, sink) => runPrLandPublicLeakGate(files, sink, cwd, base)), out);
1383
+ if (!exportLeakBlock(changedPaths, () => (deps.runExportLeakCheck ?? runPrLandExportLeakCheck)(changedPaths ?? [], cwd), opts.allowPublicLeak === true, out, cwd)) return 1;
1348
1384
  if (publicDocPaths(changedPaths, () => true).length > 0) {
1349
1385
  const top = run('git', ['rev-parse', '--show-toplevel'], { cwd });
1350
1386
  const docsRoot = top.ok && top.out.trim() ? top.out.trim() : cwd;
@@ -8,6 +8,7 @@ import type { StreamLLMFn } from '../autopilot/llm-control-brain.js';
8
8
  import { establishElanousTuiIsolation, elanousTuiSpawnOptions, type ElanousTuiIsolation } from '../self-implement/elanous-tui-spawn.js';
9
9
  import { resolveObserveOnlyDecision } from '../self-implement/observe-only.js';
10
10
  import { getUserConfig } from '../user-config.js';
11
+ import { verdictForFinalPtyScreen } from './pty-drive-verdict.js';
11
12
  import { debug } from '../debug/log.js';
12
13
  import { writeHarnessScreen } from '../harness/harness-screen.js';
13
14
  import { resolveControlInboxDir } from '../harness/control-inbox.js';
@@ -19,6 +20,7 @@ import { resolvePtyRef } from '../pty-shell/pty-ref.js';
19
20
  import { parsePtyWriteActor } from '../pty-shell/pty-write-arbiter.js';
20
21
  import { controlDepsForHandle, controlDepsForRemoteRef, runPtyControlLoop } from '../autopilot/pty-control-loop.js';
21
22
  import { createLlmControlBrain } from '../autopilot/llm-control-brain.js';
23
+ import { withDriveJail } from './drive-input-jail.js';
22
24
 
23
25
  /** `pty list` 한 줄의 상태 컬럼 위치 — `<id>\t<kind>\t<nickname>\t<scope>\t<state>\t<extra…>`.
24
26
  * ⚠️⛔ **회귀 테스트의 fixture 는 실측 형식의 *스냅샷*이지 형식 변경 감지기가 아니다**(리뷰 지적 · 과장 정정) —
@@ -166,6 +168,8 @@ export interface PtyDriveOpts {
166
168
  readonly maxSteps?: number;
167
169
  readonly pollMs?: number;
168
170
  readonly model?: string;
171
+ /** DRIVE-JAIL: brain inputs naming paths outside this directory are not sent to the PTY. */
172
+ readonly jailHome?: string;
169
173
  /** Enable the child SelfImplement observation-only override at boot. */
170
174
  readonly observeOnly?: boolean;
171
175
  readonly cwd?: string;
@@ -213,6 +217,8 @@ const liveAttachDriveDeps: PtyAttachDriveDeps = {
213
217
 
214
218
  export interface PtyAttachDriveOpts {
215
219
  readonly goal: string;
220
+ /** DRIVE-JAIL: brain inputs naming paths outside this directory are not sent to the PTY. */
221
+ readonly jailHome?: string;
216
222
  readonly maxSteps?: number;
217
223
  readonly pollMs?: number;
218
224
  readonly model?: string;
@@ -250,8 +256,11 @@ export async function runPtyAttachDrive(ref: string, opts: PtyAttachDriveOpts, d
250
256
  ...(opts.stream ? { stream: opts.stream } : {}),
251
257
  onDecision: (decision) => out(decision.action === 'input' ? ` → input (${decision.text.length} chars)\n` : decision.action === 'done' ? ` → done (${decision.reason})\n` : ' · wait\n'),
252
258
  });
259
+ const controlDeps = withDriveJail(handle ? deps.controlDepsForHandle(handle) : deps.controlDepsForRemoteRef?.(id, { actor }) ?? (() => { throw new Error('pty auto: remote control dependencies unavailable'); })(), opts.jailHome, (event, data) => deps.log(event, data));
260
+ const inputHistory: string[] = [];
253
261
  const result = await deps.runControlLoop(brain, {
254
- ...(handle ? deps.controlDepsForHandle(handle) : deps.controlDepsForRemoteRef?.(id, { actor }) ?? (() => { throw new Error('pty auto: remote control dependencies unavailable'); })()),
262
+ ...controlDeps,
263
+ inject: (text: string) => { inputHistory.push(text); return controlDeps.inject(text); },
255
264
  subjectPtyId: id,
256
265
  canReceiveInput: true,
257
266
  }, {
@@ -260,7 +269,14 @@ export async function runPtyAttachDrive(ref: string, opts: PtyAttachDriveOpts, d
260
269
  });
261
270
  deps.log('attach-finish', { id, termination: result.termination.kind, steps: result.steps });
262
271
  out(`\n▸ ${result.termination.kind} (${result.steps} steps)\n`);
263
- return { exitCode: result.termination.kind === 'success' ? 0 : 1, message: `pty auto: ${id} ${result.termination.kind}` };
272
+ if (result.termination.kind !== 'success') return { exitCode: 1, message: `pty auto: ${id} ${result.termination.kind}` };
273
+ // DRIVE-OK: «done» from the brain still has to show on the final screen.
274
+ let screen = '';
275
+ try { screen = String(await controlDeps.observe()); } catch { /* unreadable → unverified */ }
276
+ const verdict = verdictForFinalPtyScreen({ screen, inputHistory, exitCode: null });
277
+ out(`▸ verdict: ${verdict.kind} — ${verdict.reason}\n`);
278
+ deps.log('attach-verdict', { id, kind: verdict.kind, reason: verdict.reason.slice(0, 200) });
279
+ return { exitCode: verdict.kind === 'success' ? 0 : 1, message: `pty auto: ${id} ${verdict.kind}` };
264
280
  }
265
281
 
266
282
  export type PtyAttachDriveRunner = (start: () => Promise<{ readonly exitCode: number; readonly message: string }>) => Promise<void>;
@@ -273,14 +289,15 @@ export function registerPtyAttachDriveCommand(pty: Command, run: PtyAttachDriveR
273
289
  .option('--poll-ms <ms>', 'screen polling interval in milliseconds', '800')
274
290
  .option('--model <model>', 'LLM model override')
275
291
  .option('--actor <who>', 'remote input actor (human or agent)', 'human')
292
+ .option('--jail-home <dir>', 'DRIVE-JAIL: do not send inputs naming paths outside this directory')
276
293
  .description('Drive an existing agent-owned PTY without spawning a terminal')
277
- .action((ref: string, opts: { goal: string; maxSteps: string; pollMs: string; model?: string; actor?: string }) => run(async () => {
294
+ .action((ref: string, opts: { goal: string; maxSteps: string; pollMs: string; model?: string; actor?: string; jailHome?: string }) => run(async () => {
278
295
  const maxSteps = Number(opts.maxSteps);
279
296
  const pollMs = Number(opts.pollMs);
280
297
  const actor = parsePtyWriteActor(opts.actor);
281
298
  if (!actor) return { exitCode: 2, message: 'pty auto: --actor must be human or agent' };
282
299
  return Number.isInteger(maxSteps) && maxSteps >= 1 && Number.isInteger(pollMs) && pollMs >= 0
283
- ? runPtyAttachDrive(ref, { goal: opts.goal, maxSteps, pollMs, actor, ...(opts.model ? { model: opts.model } : {}) }, deps)
300
+ ? runPtyAttachDrive(ref, { goal: opts.goal, maxSteps, pollMs, actor, ...(opts.model ? { model: opts.model } : {}), ...(opts.jailHome ? { jailHome: opts.jailHome } : {}) }, deps)
284
301
  : { exitCode: 2, message: 'pty auto: --max-steps must be an integer >= 1 and --poll-ms must be an integer >= 0' };
285
302
  }));
286
303
  }
@@ -299,6 +316,8 @@ export interface DriveCliOpts {
299
316
  json?: boolean;
300
317
  /** Existing PTY ref. Absent = spawn a new shell PTY (the default). */
301
318
  attach?: string;
319
+ /** DRIVE-JAIL boundary directory. */
320
+ jailHome?: string;
302
321
  }
303
322
 
304
323
  export interface DriveCliDeps {
@@ -357,6 +376,7 @@ export async function runDriveCliCommand(command: string | undefined, opts: Driv
357
376
  attached = await runAttach(attach, {
358
377
  goal: opts.goal, maxSteps, pollMs,
359
378
  ...(opts.model ? { model: opts.model } : {}),
379
+ ...(opts.jailHome ? { jailHome: opts.jailHome } : {}),
360
380
  });
361
381
  } catch (err) {
362
382
  writeError(`drive: ${err instanceof Error ? err.message : String(err)}\n`);
@@ -379,6 +399,7 @@ export async function runDriveCliCommand(command: string | undefined, opts: Driv
379
399
  command, goal: opts.goal, maxSteps, pollMs,
380
400
  ...(opts.model ? { model: opts.model } : {}),
381
401
  ...(opts.cwd ? { cwd: opts.cwd } : {}),
402
+ ...(opts.jailHome ? { jailHome: opts.jailHome } : {}),
382
403
  }));
383
404
  } catch (err) {
384
405
  writeError(`drive: ${err instanceof Error ? err.message : String(err)}\n`);
@@ -827,7 +848,10 @@ async function runPtyDriveInner(opts: PtyDriveOpts): Promise<{ exitCode: number
827
848
  writeScreen(screenKey, await h!.renderScreen(), process.env);
828
849
  delivered = true;
829
850
  } : undefined;
830
- const deps = controlDepsForHandle(h);
851
+ const rawDeps = withDriveJail(controlDepsForHandle(h), opts.jailHome, (event, data) => debug.log('pty.drive', event, data));
852
+ // DRIVE-OK: keep what we typed so the final verdict can tell child output from echoed input.
853
+ const inputHistory: string[] = [];
854
+ const deps = { ...rawDeps, inject: (text: string) => { inputHistory.push(text); return rawDeps.inject(text); } };
831
855
  const autoAssist = opts.elanous ? getUserConfig().tools.selfImplement.autoAssist : undefined;
832
856
  const observe = opts.elanous ? async () => {
833
857
  const frame = await deps.observe();
@@ -851,12 +875,22 @@ async function runPtyDriveInner(opts: PtyDriveOpts): Promise<{ exitCode: number
851
875
  if (screen.trim()) out(`▸ 최종 화면:\n${screen}\n`);
852
876
  const childExit = h.exitCode;
853
877
  const alive = h.isAlive();
854
- const exitCode = childExit !== null
878
+ // DRIVE-OK (10-03 X1: every step failed yet drive said ok): the brain's «done» is not proof —
879
+ // judge the final screen. Plain drives take the verdict as the exit; elanous-TUI drives only observe it.
880
+ const verdict = result.termination.kind === 'success' ? verdictForFinalPtyScreen({ screen, inputHistory, exitCode: childExit }) : null;
881
+ if (verdict) {
882
+ out(`▸ verdict: ${verdict.kind} — ${verdict.reason}\n`);
883
+ debug.log('pty.drive', 'verdict', { kind: verdict.kind, reason: verdict.reason.slice(0, 200), enforced: !opts.elanous });
884
+ }
885
+ const verdictFails = !!verdict && !opts.elanous && verdict.kind !== 'success';
886
+ const baseExit = childExit !== null
855
887
  ? childExit
856
888
  : alive
857
889
  ? result.termination.kind === 'success' ? 0 : 1
858
890
  : null;
859
- debug.log('pty.drive', 'exit-resolve', { alive, childExit, exitCode, termination: result.termination.kind });
891
+ // The verdict only withholds a success: nonzero and unknown (null) exits keep their meaning.
892
+ const exitCode = baseExit === 0 && verdictFails ? 1 : baseExit;
893
+ debug.log('pty.drive', 'exit-resolve', { alive, childExit, exitCode, termination: result.termination.kind, ...(verdict ? { verdict: verdict.kind } : {}) });
860
894
  if (exitCode === null) out('▸ child exited without an exit code; reporting failure at the process boundary (exit 1)\n');
861
895
  return { exitCode };
862
896
  } finally {
@@ -0,0 +1,40 @@
1
+ // Final-screen evidence is independent of the controller's "done" declaration.
2
+ export type PtyDriveVerdict =
3
+ | { readonly kind: 'done-but-failed'; readonly reason: string; readonly evidence: null }
4
+ | { readonly kind: 'success'; readonly reason: string; readonly evidence: string }
5
+ | { readonly kind: 'success-unverified'; readonly reason: string; readonly evidence: null };
6
+
7
+ export interface FinalPtyEvidence {
8
+ readonly screen: string;
9
+ readonly inputHistory: readonly string[];
10
+ readonly exitCode: number | null;
11
+ }
12
+
13
+ // eslint-disable-next-line no-control-regex
14
+ const ANSI = /\x1b(?:\][^\x07\x1b]*(?:\x07|\x1b\\)|\[[0-?]*[ -/]*[@-~]|[@-Z\\-_])/g;
15
+ const FAILURE = /(?:\bcommand not found\b|\bnot recognized as (?:an internal or external )?command\b|\bno such file or directory\b|\b(?:error|fatal|exception)\s*:|\berror TS\d+\b|\b(?:build failed|tests? failed|test suite failed|failed to|compilation failed|permission denied)\b|(?:^|\s)[1-9]\d*\s+fail(?:ed|ing|ures?)?\b|\b(?:exit(?:ed)? (?:with )?(?:code |status )?)[1-9]\d*\b|\bnpm ERR!\b|^\s*(?:FAIL\b|✗|❌))/i;
16
+ const SUCCESS = /(?:\b[1-9]\d*\s+(?:pass|passed)\b|\btests?:\s*[1-9]\d*\s+passed\b|\bbuild successful\b|\b(?:successfully|succeeded)\b|\bGOAL-COMPLETE\b)/i;
17
+
18
+ /** Failure wins over success; an exit code of zero is not itself proof of the goal. */
19
+ export function verdictForFinalPtyScreen({ screen, inputHistory, exitCode }: FinalPtyEvidence): PtyDriveVerdict {
20
+ if (exitCode !== null && exitCode !== 0) {
21
+ return { kind: 'done-but-failed', reason: `child exit code ${exitCode}`, evidence: null };
22
+ }
23
+ // The PTY may echo commands (including fabricated success markers). Only child output is evidence.
24
+ const inputs = new Set(inputHistory.flatMap((input) => input.replace(/\r/g, '\n').split('\n').map((line) => line.trim()).filter(Boolean)));
25
+ // An echo/printf command prints its operand; that output is not independent proof of anything
26
+ // (`echo "7 pass"` must not count as passing tests — review round 2).
27
+ const echoedLiterals = new Set([...inputs].flatMap((input) => {
28
+ const match = /^(?:echo(?:\s+-[neE]+)?|printf)\s+(.+)$/i.exec(input);
29
+ if (!match) return [];
30
+ const operand = match[1]!.trim().replace(/^(['"])(.*)\1$/s, '$2').replace(/\\n$/, '').trim();
31
+ return operand ? [operand] : [];
32
+ }));
33
+ const lines = screen.replace(ANSI, '').replace(/\r/g, '\n').split('\n')
34
+ .map((line) => line.trim()).filter((line) => line && !inputs.has(line) && !echoedLiterals.has(line) && ![...inputs].some((input) => line.endsWith(`$ ${input}`) || line.endsWith(`> ${input}`)));
35
+ const failure = lines.find((line) => FAILURE.test(line));
36
+ if (failure) return { kind: 'done-but-failed', reason: failure, evidence: null };
37
+ const evidence = lines.find((line) => SUCCESS.test(line) && !/\b0\s+(?:pass|passed)\b/i.test(line));
38
+ if (evidence) return { kind: 'success', reason: 'final PTY screen has success evidence', evidence };
39
+ return { kind: 'success-unverified', reason: 'final PTY screen has no success evidence', evidence: null };
40
+ }
@@ -5,7 +5,8 @@
5
5
  // elanous release tag --version <x.y.z> --source <commit> [--yes]
6
6
  // elanous release verify [--version <x.y.z>]
7
7
  // elanous release notes --from <ref> [--to <ref>]
8
- // elanous release run --version <x.y.z> [--dry-run] [--json] [--if-ready]
8
+ // elanous release run --version <x.y.z> [--cut-commit <sha>] [--dry-run] [--json] [--if-ready]
9
+ // elanous release cut-branch --version <x.y.z> --base <sha> --pick <sha>... [--dry-run]
9
10
  //
10
11
  // 🩸 계기(2026-09-25 v0.1.0 첫 공개): 손으로 밟은 절차에서 둘을 빠뜨릴 뻔했다 — 공개본 git 커밋(판 커밋이 공개본 커밋이 된다) ·
11
12
  // PWA 빌드(빌드 산출은 공개본에 안 실린다 → 빠뜨리면 «웹 화면 없는 판»). 절차를 명령으로 굳힌다.
@@ -29,6 +30,7 @@ import { formatSchedule, getSchedule, listSchedules, setSchedule } from '../rele
29
30
  import { writeStdoutJson } from './stdout-json.js';
30
31
  import { CliUserError } from './cli-user-error.js';
31
32
  import { runUnattendedRelease, type UnattendedReleaseDeps } from '../../scripts/release-loop/unattended-release.js';
33
+ import { cutReleaseBranch } from '../../scripts/release-loop/cut-branch.js';
32
34
  import { releaseReadiness } from '../../scripts/release-loop/release-readiness.js';
33
35
  import { runReleaseIfReady } from './release-run-if-ready.js';
34
36
 
@@ -675,19 +677,30 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
675
677
  const { draftReleaseNotes, readLandedCommits, renderReleaseNotes } = await import('../../scripts/release-notes.js');
676
678
  console.log(renderReleaseNotes(draftReleaseNotes(readLandedCommits(o.from, o.to), o.from, o.to)));
677
679
  });
680
+ release.command('cut-branch')
681
+ .description('원래 컷에 main 의 수리 커밋만 얹은 release/<v> 가지를 만들고 push')
682
+ .requiredOption('--version <v>', '릴리스 판(x.y.z)')
683
+ .requiredOption('--base <sha>', '원래 컷 SHA')
684
+ .requiredOption('--pick <sha...>', '차례로 얹을 main 커밋 SHA')
685
+ .option('--dry-run', '가지·worktree·push 없이 계획만 출력')
686
+ .option('--json', '결과 한 줄 JSON(stdout)')
687
+ .action(async (o: { version: string; base: string; pick: string[]; dryRun?: boolean; json?: boolean }) => {
688
+ await jsonAction(o.json, async (log) => cutReleaseBranch({ ...o, log }), () => true);
689
+ });
678
690
  release.command('run')
679
691
  .description('릴리스 루프 실행 — 원장 직전 판과 release.loop 설정으로 그래프 입력 구성 · --dry-run 은 입력만 출력')
680
692
  .requiredOption('--version <v>', '공개할 판(x.y.z)')
693
+ .option('--cut-commit <sha>', 'origin/main HEAD 대신 컷으로 쓸 커밋')
681
694
  .option('--dry-run', '체크리스트·그래프 실행 없이 전체 입력 보기')
682
695
  .option('--if-ready', '준비되지 않았으면 사유를 출력하고 성공으로 건너뛴다')
683
696
  .option('--json', '결과 한 줄 JSON(stdout) · 사람 줄은 stderr')
684
- .action(async (o: { version: string; dryRun?: boolean; ifReady?: boolean; json?: boolean }) => {
697
+ .action(async (o: { version: string; cutCommit?: string; dryRun?: boolean; ifReady?: boolean; json?: boolean }) => {
685
698
  if (o.ifReady && !o.dryRun) {
686
699
  try {
687
700
  const outcome = await runReleaseIfReady(o.version, {
688
701
  ledgerRoot: releaseRunDeps.ledgerRoot,
689
702
  readiness: (version, options) => releaseReadiness(version, { ledgerRoot: releaseRunDeps.ledgerRoot, checklist: releaseRunDeps.checklist, ...options }),
690
- run: () => runUnattendedRelease({ version: o.version }, releaseRunDeps),
703
+ run: () => runUnattendedRelease({ version: o.version, cutCommit: o.cutCommit }, releaseRunDeps),
691
704
  });
692
705
  if (outcome.skipped) {
693
706
  if (o.json) await writeStdoutJson(`${JSON.stringify(outcome)}\n`);
@@ -707,7 +720,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
707
720
  return;
708
721
  }
709
722
  await jsonAction(o.json, async (log) => {
710
- const result = await runUnattendedRelease({ version: o.version, dryRun: o.dryRun }, releaseRunDeps);
723
+ const result = await runUnattendedRelease({ version: o.version, dryRun: o.dryRun, cutCommit: o.cutCommit }, releaseRunDeps);
711
724
  log(`${result.dryRun ? '· 드라이런' : '▶ 릴리스 루프'} ${result.input.version} · 입력 ${JSON.stringify(result.input)}`);
712
725
  return result;
713
726
  }, (r) => r.dryRun || r.state?.status === 'done' || r.state?.status === 'awaiting-approval');
@@ -5,6 +5,7 @@ import { Command } from 'commander';
5
5
  import { formatDoctorReport, registerDoctorCommand, runDoctor, type DoctorOptions, type DoctorReport } from './doctor-cli.js';
6
6
  import { applyClaudePluginSetup, planClaudePluginSetup } from './claude-plugin-setup.js';
7
7
  import { recommendedSetup } from './setup-recommend.js';
8
+ import { detectSkillCliAuth, type CliAuthStatus } from '../onboarding/cli-auth-status.js';
8
9
  import { debug } from '../debug/log.js';
9
10
  import { getUserConfig, saveUserConfig, type UserConfig } from '../user-config.js';
10
11
 
@@ -22,6 +23,7 @@ type SetupStep = {
22
23
  export interface SetupCliDeps extends DoctorOptions {
23
24
  runDoctor?: (options: DoctorOptions) => DoctorReport;
24
25
  runDoctorFix?: (args: readonly string[]) => Promise<number>;
26
+ detectSkillCliAuth?: typeof detectSkillCliAuth;
25
27
  readFile?: (path: string) => string;
26
28
  exists?: (path: string) => boolean;
27
29
  homeDir?: () => string;
@@ -142,10 +144,46 @@ export function formatSetupReport(doctor: DoctorReport, steps: SetupStep[], nonI
142
144
  ].join('\n');
143
145
  }
144
146
 
147
+ const CLI_SKILLS = {
148
+ gh: 'github', gws: 'google-workspace', op: '1password', himalaya: 'himalaya',
149
+ } as const;
150
+
151
+ function formatCliSkillStatus(status: CliAuthStatus, enabled: boolean, reason?: string): string {
152
+ return `${status.cli}: found=${status.found ? 'yes' : 'no'} / enabled=${enabled ? 'yes' : 'no'} / ${enabled ? 'enabled' : `skipped (${reason ?? status.skippedReason ?? 'not authenticated'})`}`;
153
+ }
154
+
155
+ function reportCliSkills(deps: SetupCliDeps, apply: boolean): string[] {
156
+ const statuses = (deps.detectSkillCliAuth ?? detectSkillCliAuth)();
157
+ const config = (deps.getUserConfig ?? getUserConfig)();
158
+ const deny = new Set(config.skills.deny ?? []);
159
+ const allow = config.skills.allow ?? [];
160
+ let changed = false;
161
+ const lines = statuses.map((status) => {
162
+ const skill = CLI_SKILLS[status.cli];
163
+ const allowed = allow.length === 0 || allow.some((name) => name.toLowerCase() === skill);
164
+ if (apply) {
165
+ if (status.authenticated && allowed && deny.has(skill)) { deny.delete(skill); changed = true; }
166
+ if (!status.authenticated && !deny.has(skill)) { deny.add(skill); changed = true; }
167
+ }
168
+ const enabled = status.authenticated && allowed && !deny.has(skill);
169
+ return formatCliSkillStatus(status, enabled,
170
+ status.authenticated && !allowed ? 'excluded by skills.allow' :
171
+ status.authenticated && !apply && deny.has(skill) ? 'not enabled; run setup to apply' : undefined);
172
+ });
173
+ if (apply && changed) (deps.saveUserConfig ?? saveUserConfig)({
174
+ ...config, skills: { ...config.skills, deny: [...deny] },
175
+ });
176
+ return lines;
177
+ }
178
+
145
179
  export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}): void {
146
180
  const out = deps.out ?? { log: (value: string) => console.log(value), error: (value: string) => console.error(value) };
147
181
  const setExitCode = deps.setExitCode ?? ((code: number) => { process.exitCode = code; });
148
182
  const doctorRunner = deps.runDoctor ?? runDoctor;
183
+ const showCliSkills = (apply: boolean) => {
184
+ out.log('Setup: CLI skills (public GitHub repository reads remain available without login)');
185
+ for (const line of reportCliSkills(deps, apply)) out.log(line);
186
+ };
149
187
  const isStdinTty = deps.isStdinTty ?? (() => process.stdin.isTTY === true);
150
188
  const prompt = deps.prompt ?? (async (message: string) => {
151
189
  const { createInterface } = await import('node:readline/promises');
@@ -161,6 +199,7 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
161
199
  const doctor = doctorRunner(deps);
162
200
  if (opts.nonInteractive) {
163
201
  out.log(formatSetupReport(doctor, setupSteps(deps), true));
202
+ showCliSkills(false);
164
203
  for (const line of recommendedSetup((deps.getUserConfig ?? getUserConfig)())) out.log(line);
165
204
  setExitCode(0);
166
205
  return;
@@ -183,6 +222,7 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
183
222
  }
184
223
  }
185
224
  out.log(formatSetupReport(doctor, steps, false));
225
+ showCliSkills(false);
186
226
  for (const line of recommendedSetup((deps.getUserConfig ?? getUserConfig)())) out.log(line);
187
227
  const accepted = opts.yes || (isStdinTty() && /^(?:y|yes)?$/i.test((await prompt('추천대로 켤까요? [Y/n] '))?.trim() ?? 'n'));
188
228
  if (accepted) {
@@ -197,7 +237,9 @@ export function registerSetupCommand(program: Command, deps: SetupCliDeps = {}):
197
237
  await doctorProgram.parseAsync([...args], { from: 'user' });
198
238
  return exitCode;
199
239
  });
200
- setExitCode(await runDoctorFix(['doctor', '--fix', '--yes']));
240
+ const fixCode = await runDoctorFix(['doctor', '--fix', '--yes']);
241
+ showCliSkills(true);
242
+ setExitCode(fixCode);
201
243
  return;
202
244
  }
203
245
  setExitCode(0);
@@ -73,7 +73,23 @@ export function registerConnectCommand(program: Command): void {
73
73
  }
74
74
 
75
75
  export function registerSkillsCommands(program: Command): void {
76
- const skills = program.command('skills').description('Check and repair installed skills');
76
+ const skills = program.command('skills').description('Check, install and repair skills');
77
+ skills.command('install <pack>')
78
+ .description('Install a gift skill pack from a code')
79
+ .option('--code <code>', 'Gift code')
80
+ .option('--email <address>', 'Email for gift delivery')
81
+ .option('--agree', 'Agree to email collection and retention')
82
+ .option('--endpoint <url>', 'Gift API origin (overrides skills.giftEndpoint)')
83
+ .option('--json', 'Print the install result as JSON')
84
+ .action(async (pack: string, opts: { code?: string; email?: string; agree?: boolean; endpoint?: string; json?: boolean }) => {
85
+ const { getUserConfig } = await import('../user-config.js');
86
+ const { installGiftPack } = await import('../skills/gift-install.js');
87
+ const result = await installGiftPack({ pack, code: opts.code, email: opts.email, agree: opts.agree,
88
+ endpoint: opts.endpoint ?? getUserConfig().skills.giftEndpoint });
89
+ if (opts.json) console.log(JSON.stringify(result));
90
+ else console.log(result.message);
91
+ if (!result.ok) process.exitCode = 1;
92
+ });
77
93
  skills.command('sources')
78
94
  .description('List every skill folder elanous reads, in order (preset · shared · connected · package)')
79
95
  .option('--json', 'JSON output')
@@ -0,0 +1,10 @@
1
+ import { resolve } from 'node:path';
2
+
3
+ /** Render a Claude Code settings fragment; never touch the user's settings file. */
4
+ export function claudeHooksSettings(repoRoot: string): string {
5
+ const command = (file: string) => `bash '${resolve(repoRoot, 'scripts/context-hooks', file).replaceAll("'", "'\\''")}'`;
6
+ return JSON.stringify({ hooks: {
7
+ Stop: [{ hooks: [{ type: 'command', command: command('claude-stop.sh') }] }],
8
+ PostToolUse: [{ hooks: [{ type: 'command', command: command('post-tool-use.sh') }] }],
9
+ } }, null, 2);
10
+ }
@@ -0,0 +1,48 @@
1
+ import { contextNow, type ContextFact, type ContextNowAnswer, type ContextNowDeps } from './context-now.js';
2
+
3
+ export function readSlashContextNow(args: string[], deps?: ContextNowDeps): ContextNowAnswer {
4
+ return contextNow({ topic: args.join(' ').trim() }, deps);
5
+ }
6
+
7
+ function factText(fact: ContextFact): string {
8
+ switch (fact.kind) {
9
+ case 'version': return fact.version;
10
+ case 'cell': return `${fact.id} ${fact.title} (${fact.status})`;
11
+ case 'decision': return `${fact.id} ${fact.title} (${fact.status})`;
12
+ case 'seat': return `${fact.seat} ${fact.id ?? ''} ${fact.title ?? ''} (${fact.status})`.trim();
13
+ }
14
+ }
15
+
16
+ export function renderTelegramNow(answer: ContextNowAnswer): string {
17
+ const rows = [
18
+ ['판', answer.facts.filter(f => f.kind === 'version')],
19
+ ['칸', answer.facts.filter(f => f.kind === 'cell')],
20
+ ['결정', answer.facts.filter(f => f.kind === 'decision')],
21
+ ['자리', answer.facts.filter(f => f.kind === 'seat')],
22
+ ] as const;
23
+ const lines = rows.map(([label, facts]) => `${label}: ${facts.length ? facts.map(f => `${factText(f)} — ${f.source}`).join(' · ') : '없음'}`);
24
+ lines.push(`최근: ${answer.events.length ? answer.events.map(e => `${e.summary} — ${e.source}`).join(' · ') : '없음'}${answer.guide.length ? ` · 안내 ${answer.guide.join(' · ')}` : ''}`);
25
+ return lines.map(line => line.replace(/\s+/g, ' ').trim()).join('\n');
26
+ }
27
+
28
+ export function renderTuiNow(answer: ContextNowAnswer): string[] {
29
+ const rows = [
30
+ ...answer.facts.map(f => [f.kind, factText(f), f.source]),
31
+ ...answer.events.map(e => [e.kind, e.summary, e.source]),
32
+ ...answer.guide.map(guide => ['안내', guide, '']),
33
+ ];
34
+ return [
35
+ `지금${answer.topic ? ` · ${answer.topic}` : ''} (${answer.at})`,
36
+ '| 종류 | 사실 | 출처 |',
37
+ '| --- | --- | --- |',
38
+ ...rows.map(row => `| ${row.map(cell => cell.replaceAll('|', '\\|').replaceAll(/\r?\n/g, ' ')).join(' | ')} |`),
39
+ ];
40
+ }
41
+
42
+ export function telegramNowSlash(args: string[], deps?: ContextNowDeps): string {
43
+ return renderTelegramNow(readSlashContextNow(args, deps));
44
+ }
45
+
46
+ export function tuiNowSlash(args: string[], deps?: ContextNowDeps): string[] {
47
+ return renderTuiNow(readSlashContextNow(args, deps));
48
+ }