openclaw-node-harness 2.0.0

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 (779) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +184 -0
  3. package/bin/discord-read.js +228 -0
  4. package/bin/fleet-deploy.js +365 -0
  5. package/bin/lane-watchdog.js +232 -0
  6. package/bin/mesh-agent.js +714 -0
  7. package/bin/mesh-bridge.js +535 -0
  8. package/bin/mesh-deploy-listener.js +322 -0
  9. package/bin/mesh-deploy.js +1048 -0
  10. package/bin/mesh-health-publisher.js +247 -0
  11. package/bin/mesh-task-daemon.js +451 -0
  12. package/bin/mesh-tool-discord.js +293 -0
  13. package/bin/mesh.js +649 -0
  14. package/boot/manifest.yaml +187 -0
  15. package/cli.js +35 -0
  16. package/config/daemon.json.template +16 -0
  17. package/config/obsidian-sync.json.template +39 -0
  18. package/config/openclaw.json.template +124 -0
  19. package/config/transcript-sources.json.template +22 -0
  20. package/identity/AGENTS.md +201 -0
  21. package/identity/CLAUDE.md +64 -0
  22. package/identity/DELEGATION.md +304 -0
  23. package/identity/HEARTBEAT.md +163 -0
  24. package/identity/MEMORY_SPEC.md +368 -0
  25. package/identity/PRINCIPLES.md +81 -0
  26. package/identity/SOUL.md +48 -0
  27. package/identity/TOOLS.md +47 -0
  28. package/install.sh +895 -0
  29. package/lib/agent-activity.js +390 -0
  30. package/lib/kanban-io.js +352 -0
  31. package/lib/mesh-registry.js +194 -0
  32. package/lib/mesh-roles.js +13 -0
  33. package/lib/mesh-tasks.js +306 -0
  34. package/lib/nats-resolve.js +108 -0
  35. package/mission-control/README.md +36 -0
  36. package/mission-control/drizzle/0000_simple_silhouette.sql +62 -0
  37. package/mission-control/drizzle/meta/0000_snapshot.json +413 -0
  38. package/mission-control/drizzle/meta/_journal.json +13 -0
  39. package/mission-control/drizzle.config.ts +13 -0
  40. package/mission-control/eslint.config.mjs +18 -0
  41. package/mission-control/next.config.ts +7 -0
  42. package/mission-control/package-lock.json +10518 -0
  43. package/mission-control/package.json +49 -0
  44. package/mission-control/postcss.config.mjs +7 -0
  45. package/mission-control/public/file.svg +1 -0
  46. package/mission-control/public/globe.svg +1 -0
  47. package/mission-control/public/next.svg +1 -0
  48. package/mission-control/public/vercel.svg +1 -0
  49. package/mission-control/public/window.svg +1 -0
  50. package/mission-control/scripts/enrich-descriptions.js +193 -0
  51. package/mission-control/scripts/gen-chronology.js +102 -0
  52. package/mission-control/scripts/import-pipeline-v2.js +523 -0
  53. package/mission-control/scripts/import-pipeline.js +295 -0
  54. package/mission-control/src/app/api/activity/live/route.ts +27 -0
  55. package/mission-control/src/app/api/activity/route.ts +47 -0
  56. package/mission-control/src/app/api/burndown/route.ts +112 -0
  57. package/mission-control/src/app/api/critical-path/route.ts +159 -0
  58. package/mission-control/src/app/api/dependencies/route.ts +176 -0
  59. package/mission-control/src/app/api/memory/categories/route.ts +93 -0
  60. package/mission-control/src/app/api/memory/consolidate/route.ts +107 -0
  61. package/mission-control/src/app/api/memory/doc/route.ts +89 -0
  62. package/mission-control/src/app/api/memory/flush/route.ts +129 -0
  63. package/mission-control/src/app/api/memory/graph/route.ts +105 -0
  64. package/mission-control/src/app/api/memory/items/route.ts +86 -0
  65. package/mission-control/src/app/api/memory/list/route.ts +48 -0
  66. package/mission-control/src/app/api/memory/retrieve/route.ts +51 -0
  67. package/mission-control/src/app/api/memory/search/route.ts +143 -0
  68. package/mission-control/src/app/api/memory/sync/route.ts +23 -0
  69. package/mission-control/src/app/api/memory/wikilinks/route.ts +75 -0
  70. package/mission-control/src/app/api/mesh/events/route.ts +67 -0
  71. package/mission-control/src/app/api/mesh/nodes/route.ts +221 -0
  72. package/mission-control/src/app/api/mesh/tokens/route.ts +133 -0
  73. package/mission-control/src/app/api/projects/route.ts +102 -0
  74. package/mission-control/src/app/api/resolve-path/route.ts +92 -0
  75. package/mission-control/src/app/api/scheduler/tick/route.ts +38 -0
  76. package/mission-control/src/app/api/scheduler/waves/route.ts +54 -0
  77. package/mission-control/src/app/api/screenshot/route.ts +127 -0
  78. package/mission-control/src/app/api/settings/gateway/route.ts +92 -0
  79. package/mission-control/src/app/api/skills/[id]/health/route.ts +57 -0
  80. package/mission-control/src/app/api/skills/list/route.ts +41 -0
  81. package/mission-control/src/app/api/souls/[id]/evolution/route.ts +253 -0
  82. package/mission-control/src/app/api/souls/[id]/prompt/route.ts +205 -0
  83. package/mission-control/src/app/api/souls/[id]/propagate/route.ts +146 -0
  84. package/mission-control/src/app/api/souls/route.ts +174 -0
  85. package/mission-control/src/app/api/tasks/[id]/handoff/route.ts +115 -0
  86. package/mission-control/src/app/api/tasks/[id]/route.ts +266 -0
  87. package/mission-control/src/app/api/tasks/[id]/tree/route.ts +94 -0
  88. package/mission-control/src/app/api/tasks/route.ts +253 -0
  89. package/mission-control/src/app/api/tts/route.ts +47 -0
  90. package/mission-control/src/app/api/workspace/files/route.ts +88 -0
  91. package/mission-control/src/app/api/workspace/read/route.ts +73 -0
  92. package/mission-control/src/app/burndown/page.tsx +309 -0
  93. package/mission-control/src/app/calendar/page.tsx +839 -0
  94. package/mission-control/src/app/favicon.ico +0 -0
  95. package/mission-control/src/app/globals.css +67 -0
  96. package/mission-control/src/app/graph/page.tsx +352 -0
  97. package/mission-control/src/app/layout.tsx +35 -0
  98. package/mission-control/src/app/live/page.tsx +232 -0
  99. package/mission-control/src/app/memory/page.tsx +154 -0
  100. package/mission-control/src/app/mesh/page.tsx +457 -0
  101. package/mission-control/src/app/obsidian/page.tsx +252 -0
  102. package/mission-control/src/app/page.tsx +70 -0
  103. package/mission-control/src/app/roadmap/page.tsx +1757 -0
  104. package/mission-control/src/app/settings/page.tsx +260 -0
  105. package/mission-control/src/app/souls/page.tsx +573 -0
  106. package/mission-control/src/components/board/activity-timeline.tsx +96 -0
  107. package/mission-control/src/components/board/daily-board.tsx +373 -0
  108. package/mission-control/src/components/board/kanban-board.tsx +364 -0
  109. package/mission-control/src/components/board/kanban-column.tsx +105 -0
  110. package/mission-control/src/components/board/live-stream.tsx +116 -0
  111. package/mission-control/src/components/board/skill-health-card.tsx +128 -0
  112. package/mission-control/src/components/board/status-banner.tsx +124 -0
  113. package/mission-control/src/components/board/task-card.tsx +454 -0
  114. package/mission-control/src/components/board/unified-task-dialog.tsx +1043 -0
  115. package/mission-control/src/components/layout/resizable-layout.tsx +68 -0
  116. package/mission-control/src/components/layout/sidebar.tsx +90 -0
  117. package/mission-control/src/components/live/audio-spectrum.tsx +106 -0
  118. package/mission-control/src/components/live/chat-bubble.tsx +52 -0
  119. package/mission-control/src/components/live/chat-input.tsx +92 -0
  120. package/mission-control/src/components/memory/doc-reader.tsx +172 -0
  121. package/mission-control/src/components/memory/memory-list.tsx +169 -0
  122. package/mission-control/src/components/memory/search-bar.tsx +67 -0
  123. package/mission-control/src/components/memory/search-results.tsx +149 -0
  124. package/mission-control/src/components/obsidian/backlinks-panel.tsx +52 -0
  125. package/mission-control/src/components/obsidian/file-tree.tsx +186 -0
  126. package/mission-control/src/components/obsidian/local-graph.tsx +107 -0
  127. package/mission-control/src/components/obsidian/obsidian-graph.tsx +192 -0
  128. package/mission-control/src/components/obsidian/obsidian-reader.tsx +246 -0
  129. package/mission-control/src/lib/activity.ts +29 -0
  130. package/mission-control/src/lib/config.ts +21 -0
  131. package/mission-control/src/lib/db/index.ts +429 -0
  132. package/mission-control/src/lib/db/schema.ts +218 -0
  133. package/mission-control/src/lib/gateway-notify.ts +113 -0
  134. package/mission-control/src/lib/hooks.ts +536 -0
  135. package/mission-control/src/lib/memory/categories.ts +125 -0
  136. package/mission-control/src/lib/memory/entities.ts +482 -0
  137. package/mission-control/src/lib/memory/extract.ts +369 -0
  138. package/mission-control/src/lib/memory/retrieval.ts +281 -0
  139. package/mission-control/src/lib/memory/wikilinks.ts +147 -0
  140. package/mission-control/src/lib/nats.ts +126 -0
  141. package/mission-control/src/lib/parsers/clawvault-doc.ts +98 -0
  142. package/mission-control/src/lib/parsers/daily-log.ts +73 -0
  143. package/mission-control/src/lib/parsers/memory-md.ts +81 -0
  144. package/mission-control/src/lib/parsers/task-markdown.ts +459 -0
  145. package/mission-control/src/lib/parsers/transcript.ts +209 -0
  146. package/mission-control/src/lib/scheduler.ts +394 -0
  147. package/mission-control/src/lib/speech/use-speech-pipeline.ts +176 -0
  148. package/mission-control/src/lib/sync/memory.ts +224 -0
  149. package/mission-control/src/lib/sync/tasks.ts +271 -0
  150. package/mission-control/src/lib/tts/edge.ts +31 -0
  151. package/mission-control/src/lib/tts/google.ts +78 -0
  152. package/mission-control/src/lib/tts/index.ts +39 -0
  153. package/mission-control/src/lib/tts/types.ts +18 -0
  154. package/mission-control/tsconfig.json +42 -0
  155. package/obsidian-vault/.obsidian/app.json +10 -0
  156. package/obsidian-vault/.obsidian/community-plugins.json +8 -0
  157. package/obsidian-vault/.obsidian/graph.json +40 -0
  158. package/obsidian-vault/.obsidian/plugins/obsidian-local-rest-api/main.js +58769 -0
  159. package/obsidian-vault/.obsidian/plugins/obsidian-local-rest-api/manifest.json +10 -0
  160. package/obsidian-vault/.obsidian/plugins/obsidian-local-rest-api/styles.css +47 -0
  161. package/obsidian-vault/00-meta/.gitkeep +0 -0
  162. package/obsidian-vault/01-architecture/.gitkeep +0 -0
  163. package/obsidian-vault/02-smart-contracts/.gitkeep +0 -0
  164. package/obsidian-vault/03-backend/.gitkeep +0 -0
  165. package/obsidian-vault/04-mobile/.gitkeep +0 -0
  166. package/obsidian-vault/05-ar-mapping/.gitkeep +0 -0
  167. package/obsidian-vault/06-3d-assets/.gitkeep +0 -0
  168. package/obsidian-vault/07-sound-music/.gitkeep +0 -0
  169. package/obsidian-vault/08-lore/.gitkeep +0 -0
  170. package/obsidian-vault/09-quests-playthrough/.gitkeep +0 -0
  171. package/obsidian-vault/10-economy/.gitkeep +0 -0
  172. package/obsidian-vault/11-nft-assets/.gitkeep +0 -0
  173. package/obsidian-vault/12-nft-mechanics/.gitkeep +0 -0
  174. package/obsidian-vault/13-dao-guild-social/.gitkeep +0 -0
  175. package/obsidian-vault/14-game-progression/.gitkeep +0 -0
  176. package/obsidian-vault/15-analytics/.gitkeep +0 -0
  177. package/obsidian-vault/16-security/.gitkeep +0 -0
  178. package/obsidian-vault/17-devops/.gitkeep +0 -0
  179. package/obsidian-vault/18-marketplace/.gitkeep +0 -0
  180. package/obsidian-vault/19-decisions/.gitkeep +0 -0
  181. package/obsidian-vault/20-business-strategy/.gitkeep +0 -0
  182. package/obsidian-vault/21-legal-regulatory/.gitkeep +0 -0
  183. package/obsidian-vault/nodes/.gitkeep +0 -0
  184. package/openclaw.env.example +17 -0
  185. package/package.json +45 -0
  186. package/services/launchd/ai.openclaw.gateway.plist +59 -0
  187. package/services/launchd/ai.openclaw.lane-watchdog.plist +32 -0
  188. package/services/launchd/ai.openclaw.log-rotate.plist +28 -0
  189. package/services/launchd/ai.openclaw.memory-daemon.plist +36 -0
  190. package/services/launchd/ai.openclaw.mesh-agent.plist +38 -0
  191. package/services/launchd/ai.openclaw.mesh-bridge.plist +36 -0
  192. package/services/launchd/ai.openclaw.mesh-deploy-listener.plist +33 -0
  193. package/services/launchd/ai.openclaw.mesh-health-publisher.plist +29 -0
  194. package/services/launchd/ai.openclaw.mesh-task-daemon.plist +36 -0
  195. package/services/launchd/ai.openclaw.mesh-tool-discord.plist +36 -0
  196. package/services/launchd/ai.openclaw.mission-control.plist +41 -0
  197. package/services/service-manifest.json +13 -0
  198. package/services/systemd/openclaw-gateway.service +21 -0
  199. package/services/systemd/openclaw-lane-watchdog.service +21 -0
  200. package/services/systemd/openclaw-log-rotate.service +13 -0
  201. package/services/systemd/openclaw-log-rotate.timer +9 -0
  202. package/services/systemd/openclaw-memory-daemon.service +21 -0
  203. package/services/systemd/openclaw-mesh-agent.service +19 -0
  204. package/services/systemd/openclaw-mesh-bridge.service +21 -0
  205. package/services/systemd/openclaw-mesh-deploy-listener.service +23 -0
  206. package/services/systemd/openclaw-mesh-health-publisher.service +21 -0
  207. package/services/systemd/openclaw-mesh-task-daemon.service +21 -0
  208. package/services/systemd/openclaw-mesh-tool-discord.service +21 -0
  209. package/services/systemd/openclaw-mission-control.service +22 -0
  210. package/skills/1password/.clawhub/origin.json +7 -0
  211. package/skills/1password/SKILL.md +63 -0
  212. package/skills/1password/references/cli-examples.md +29 -0
  213. package/skills/1password/references/get-started.md +17 -0
  214. package/skills/acquisition-channel-advisor/SKILL.md +643 -0
  215. package/skills/acquisition-channel-advisor/examples/conversation-flow.md +531 -0
  216. package/skills/agent-browser/.clawhub/origin.json +7 -0
  217. package/skills/agent-browser/CONTRIBUTING.md +63 -0
  218. package/skills/agent-browser/SKILL.md +338 -0
  219. package/skills/agentic-compass/.clawhub/origin.json +7 -0
  220. package/skills/agentic-compass/README.md +96 -0
  221. package/skills/agentic-compass/SKILL.md +112 -0
  222. package/skills/agentic-compass/references/README.md +5 -0
  223. package/skills/agentic-compass/scripts/agentic-compass.py +196 -0
  224. package/skills/arcane-dev-ops/SKILL.md +61 -0
  225. package/skills/arcane-dev-ops/references/checklist.md +22 -0
  226. package/skills/arcane-dev-ops/references/validation-cases.md +11 -0
  227. package/skills/arcane-dev-ops/scripts/prepush_check.sh +41 -0
  228. package/skills/auto-updater/.clawhub/origin.json +7 -0
  229. package/skills/auto-updater/SKILL.md +158 -0
  230. package/skills/auto-updater/references/agent-guide.md +152 -0
  231. package/skills/auto-updater/references/summary-examples.md +109 -0
  232. package/skills/business-health-diagnostic/SKILL.md +782 -0
  233. package/skills/byterover/.clawhub/origin.json +7 -0
  234. package/skills/byterover/SKILL.md +105 -0
  235. package/skills/byterover/TROUBLESHOOTING.md +50 -0
  236. package/skills/byterover/WORKFLOWS.md +229 -0
  237. package/skills/capability-evolver/.clawhub/origin.json +7 -0
  238. package/skills/capability-evolver/CONTRIBUTING.md +11 -0
  239. package/skills/capability-evolver/README.md +157 -0
  240. package/skills/capability-evolver/README.zh-CN.md +112 -0
  241. package/skills/capability-evolver/SKILL.md +93 -0
  242. package/skills/capability-evolver/assets/gep/capsules.json +5 -0
  243. package/skills/capability-evolver/assets/gep/genes.json +104 -0
  244. package/skills/capability-evolver/index.js +59 -0
  245. package/skills/capability-evolver/package.json +22 -0
  246. package/skills/capability-evolver/scripts/analyze_by_skill.js +121 -0
  247. package/skills/capability-evolver/scripts/build_public.js +350 -0
  248. package/skills/capability-evolver/scripts/export_history.js +98 -0
  249. package/skills/capability-evolver/scripts/extract_log.js +85 -0
  250. package/skills/capability-evolver/scripts/generate_history.js +75 -0
  251. package/skills/capability-evolver/scripts/human_report.js +147 -0
  252. package/skills/capability-evolver/scripts/publish_public.js +516 -0
  253. package/skills/capability-evolver/scripts/suggest_version.js +89 -0
  254. package/skills/capability-evolver/src/evolve.js +594 -0
  255. package/skills/capability-evolver/src/gep/assetStore.js +204 -0
  256. package/skills/capability-evolver/src/gep/candidates.js +134 -0
  257. package/skills/capability-evolver/src/gep/paths.js +23 -0
  258. package/skills/capability-evolver/src/gep/prompt.js +254 -0
  259. package/skills/capability-evolver/src/gep/selector.js +89 -0
  260. package/skills/capability-evolver/src/gep/signals.js +27 -0
  261. package/skills/cc-godmode/.clawhub/origin.json +7 -0
  262. package/skills/cc-godmode/CHANGELOG.md +66 -0
  263. package/skills/cc-godmode/README.md +293 -0
  264. package/skills/cc-godmode/SKILL.md +242 -0
  265. package/skills/cc-godmode/docs/AGENTS.md +332 -0
  266. package/skills/cc-godmode/docs/MIGRATION.md +206 -0
  267. package/skills/cc-godmode/docs/TROUBLESHOOTING.md +357 -0
  268. package/skills/cc-godmode/docs/WORKFLOWS.md +329 -0
  269. package/skills/cc-godmode/references/agents.md +433 -0
  270. package/skills/cc-godmode/scripts/build-skill.js +232 -0
  271. package/skills/clawdbot-filesystem/.clawhub/origin.json +7 -0
  272. package/skills/clawdbot-filesystem/LICENSE.md +21 -0
  273. package/skills/clawdbot-filesystem/README.md +322 -0
  274. package/skills/clawdbot-filesystem/SKILL.md +219 -0
  275. package/skills/clawdbot-filesystem/config.json +41 -0
  276. package/skills/clawdbot-filesystem/package.json +69 -0
  277. package/skills/clawdbot-security-check/.clawhub/origin.json +7 -0
  278. package/skills/clawdbot-security-check/README.md +168 -0
  279. package/skills/clawdbot-security-check/SKILL.md +145 -0
  280. package/skills/clawdbot-security-check/references/audit-checks.md +521 -0
  281. package/skills/clawdbot-security-check/skill.json +42 -0
  282. package/skills/clawddocs/.clawhub/origin.json +7 -0
  283. package/skills/clawddocs/SKILL.md +176 -0
  284. package/skills/clawddocs/package.json +9 -0
  285. package/skills/clawddocs/scripts/build-index.sh +17 -0
  286. package/skills/clawddocs/scripts/cache.sh +13 -0
  287. package/skills/clawddocs/scripts/fetch-doc.sh +7 -0
  288. package/skills/clawddocs/scripts/recent.sh +5 -0
  289. package/skills/clawddocs/scripts/search.sh +8 -0
  290. package/skills/clawddocs/scripts/sitemap.sh +23 -0
  291. package/skills/clawddocs/scripts/track-changes.sh +16 -0
  292. package/skills/clawddocs/snippets/common-configs.md +69 -0
  293. package/skills/clawguard/.clawhub/origin.json +7 -0
  294. package/skills/clawguard/SKILL.md +137 -0
  295. package/skills/company-research/SKILL.md +393 -0
  296. package/skills/company-research/examples/sample.md +164 -0
  297. package/skills/company-research/template.md +60 -0
  298. package/skills/crypto-price/.clawhub/origin.json +7 -0
  299. package/skills/crypto-price/ARCHITECTURE.md +437 -0
  300. package/skills/crypto-price/README.md +194 -0
  301. package/skills/crypto-price/SKILL.md +61 -0
  302. package/skills/crypto-price/requirements.txt +1 -0
  303. package/skills/crypto-price/scripts/get_price_chart.py +988 -0
  304. package/skills/customer-journey-map/SKILL.md +343 -0
  305. package/skills/customer-journey-map/examples/sample.md +33 -0
  306. package/skills/customer-journey-map/template.md +28 -0
  307. package/skills/customer-journey-mapping-workshop/SKILL.md +522 -0
  308. package/skills/deep-research/.clawhub/origin.json +7 -0
  309. package/skills/deep-research/SKILL.md +93 -0
  310. package/skills/deep-research/rules/logic.md +32 -0
  311. package/skills/discord-telegram-triage/SKILL.md +59 -0
  312. package/skills/discord-telegram-triage/references/discord-runbook.md +28 -0
  313. package/skills/discord-telegram-triage/references/validation-cases.md +11 -0
  314. package/skills/discord-telegram-triage/scripts/triage_snapshot.sh +23 -0
  315. package/skills/discovery-interview-prep/SKILL.md +408 -0
  316. package/skills/discovery-process/SKILL.md +503 -0
  317. package/skills/discovery-process/examples/sample.md +60 -0
  318. package/skills/discovery-process/template.md +39 -0
  319. package/skills/dist/arcane-dev-ops.skill +0 -0
  320. package/skills/dist/discord-telegram-triage.skill +0 -0
  321. package/skills/dist/founder-brief-summarizer.skill +0 -0
  322. package/skills/epic-breakdown-advisor/SKILL.md +664 -0
  323. package/skills/epic-hypothesis/SKILL.md +285 -0
  324. package/skills/epic-hypothesis/examples/sample.md +104 -0
  325. package/skills/epic-hypothesis/template.md +30 -0
  326. package/skills/excel/.clawhub/origin.json +7 -0
  327. package/skills/excel/SKILL.md +332 -0
  328. package/skills/excel/scripts/excel.py +1120 -0
  329. package/skills/fast-browser-use/.clawhub/origin.json +7 -0
  330. package/skills/fast-browser-use/CODEBUDDY.md +142 -0
  331. package/skills/fast-browser-use/Cargo.toml +77 -0
  332. package/skills/fast-browser-use/README.md +62 -0
  333. package/skills/fast-browser-use/SKILL.md +217 -0
  334. package/skills/fast-browser-use/package-lock.json +28 -0
  335. package/skills/fast-browser-use/package.json +8 -0
  336. package/skills/fast-browser-use/rustfmt.toml +10 -0
  337. package/skills/fast-browser-use/src/bin/cli.rs +373 -0
  338. package/skills/fast-browser-use/src/bin/mcp_server.rs +203 -0
  339. package/skills/fast-browser-use/src/browser/config.rs +136 -0
  340. package/skills/fast-browser-use/src/browser/debug.rs +16 -0
  341. package/skills/fast-browser-use/src/browser/mod.rs +61 -0
  342. package/skills/fast-browser-use/src/browser/session.rs +478 -0
  343. package/skills/fast-browser-use/src/dom/element.rs +442 -0
  344. package/skills/fast-browser-use/src/dom/extract_dom.js +849 -0
  345. package/skills/fast-browser-use/src/dom/mod.rs +14 -0
  346. package/skills/fast-browser-use/src/dom/tree.rs +296 -0
  347. package/skills/fast-browser-use/src/dom/yaml.rs +149 -0
  348. package/skills/fast-browser-use/src/error.rs +115 -0
  349. package/skills/fast-browser-use/src/lib.rs +17 -0
  350. package/skills/fast-browser-use/src/mcp/handler.rs +63 -0
  351. package/skills/fast-browser-use/src/mcp/mod.rs +81 -0
  352. package/skills/fast-browser-use/src/tools/Readability.min.js +1480 -0
  353. package/skills/fast-browser-use/src/tools/annotate.rs +165 -0
  354. package/skills/fast-browser-use/src/tools/click.rs +84 -0
  355. package/skills/fast-browser-use/src/tools/close.rs +35 -0
  356. package/skills/fast-browser-use/src/tools/close_tab.rs +45 -0
  357. package/skills/fast-browser-use/src/tools/convert_to_markdown.js +117 -0
  358. package/skills/fast-browser-use/src/tools/cookies.rs +58 -0
  359. package/skills/fast-browser-use/src/tools/debug.rs +44 -0
  360. package/skills/fast-browser-use/src/tools/evaluate.rs +40 -0
  361. package/skills/fast-browser-use/src/tools/extract.rs +66 -0
  362. package/skills/fast-browser-use/src/tools/go_back.rs +35 -0
  363. package/skills/fast-browser-use/src/tools/go_forward.rs +35 -0
  364. package/skills/fast-browser-use/src/tools/hover.js +33 -0
  365. package/skills/fast-browser-use/src/tools/hover.rs +97 -0
  366. package/skills/fast-browser-use/src/tools/html_to_markdown.rs +99 -0
  367. package/skills/fast-browser-use/src/tools/input.rs +93 -0
  368. package/skills/fast-browser-use/src/tools/local_storage.rs +159 -0
  369. package/skills/fast-browser-use/src/tools/markdown.rs +181 -0
  370. package/skills/fast-browser-use/src/tools/mod.rs +326 -0
  371. package/skills/fast-browser-use/src/tools/navigate.rs +55 -0
  372. package/skills/fast-browser-use/src/tools/new_tab.rs +60 -0
  373. package/skills/fast-browser-use/src/tools/press_key.rs +78 -0
  374. package/skills/fast-browser-use/src/tools/read_links.rs +59 -0
  375. package/skills/fast-browser-use/src/tools/readability_script.rs +8 -0
  376. package/skills/fast-browser-use/src/tools/screenshot.rs +47 -0
  377. package/skills/fast-browser-use/src/tools/scroll.js +22 -0
  378. package/skills/fast-browser-use/src/tools/scroll.rs +95 -0
  379. package/skills/fast-browser-use/src/tools/select.js +23 -0
  380. package/skills/fast-browser-use/src/tools/select.rs +129 -0
  381. package/skills/fast-browser-use/src/tools/sitemap.rs +426 -0
  382. package/skills/fast-browser-use/src/tools/snapshot.rs +324 -0
  383. package/skills/fast-browser-use/src/tools/switch_tab.rs +69 -0
  384. package/skills/fast-browser-use/src/tools/tab_list.rs +76 -0
  385. package/skills/fast-browser-use/src/tools/utils.rs +92 -0
  386. package/skills/fast-browser-use/src/tools/wait.rs +53 -0
  387. package/skills/fast-browser-use/test_auth.json +3 -0
  388. package/skills/fast-browser-use/test_state.json +6 -0
  389. package/skills/fast-browser-use/tests/browser_tools_integration.rs +233 -0
  390. package/skills/fast-browser-use/tests/cli_recipes_integration.rs +112 -0
  391. package/skills/fast-browser-use/tests/cookies_integration.rs +56 -0
  392. package/skills/fast-browser-use/tests/debug_integration.rs +83 -0
  393. package/skills/fast-browser-use/tests/dom_integration.rs +170 -0
  394. package/skills/fast-browser-use/tests/local_storage_integration.rs +75 -0
  395. package/skills/fast-browser-use/tests/markdown_integration.rs +448 -0
  396. package/skills/fast-browser-use/tests/navigation_integration.rs +241 -0
  397. package/skills/fast-browser-use/tests/sitemap_integration.rs +326 -0
  398. package/skills/fast-browser-use/tests/tab_management_integration.rs +300 -0
  399. package/skills/feature-investment-advisor/SKILL.md +639 -0
  400. package/skills/feature-investment-advisor/examples/conversation-flow.md +538 -0
  401. package/skills/finance-based-pricing-advisor/SKILL.md +763 -0
  402. package/skills/finance-metrics-quickref/SKILL.md +309 -0
  403. package/skills/find-skills/.clawhub/origin.json +7 -0
  404. package/skills/find-skills/SKILL.md +143 -0
  405. package/skills/flavor-text-writer/SKILL.md +27 -0
  406. package/skills/founder-brief-summarizer/SKILL.md +52 -0
  407. package/skills/founder-brief-summarizer/references/response-templates.md +15 -0
  408. package/skills/founder-brief-summarizer/references/validation-cases.md +11 -0
  409. package/skills/founder-brief-summarizer/scripts/brief_template.sh +28 -0
  410. package/skills/frontend-design/.clawhub/origin.json +7 -0
  411. package/skills/frontend-design/LICENSE.txt +190 -0
  412. package/skills/frontend-design/SKILL.md +53 -0
  413. package/skills/gemini/.clawhub/origin.json +7 -0
  414. package/skills/gemini/SKILL.md +33 -0
  415. package/skills/gemini-deep-research/.clawhub/origin.json +7 -0
  416. package/skills/gemini-deep-research/SKILL.md +78 -0
  417. package/skills/gemini-deep-research/scripts/deep_research.py +176 -0
  418. package/skills/git-essentials/.clawhub/origin.json +7 -0
  419. package/skills/git-essentials/SKILL.md +239 -0
  420. package/skills/git-essentials/references/advanced.md +211 -0
  421. package/skills/github/.clawhub/origin.json +7 -0
  422. package/skills/github/SKILL.md +57 -0
  423. package/skills/google-drive/.clawhub/origin.json +7 -0
  424. package/skills/google-drive/LICENSE.txt +21 -0
  425. package/skills/google-drive/SKILL.md +320 -0
  426. package/skills/growth-loop/SKILL.md +270 -0
  427. package/skills/growth-loop/_meta.json +9 -0
  428. package/skills/growth-loop/references/diagnosis-framework.md +84 -0
  429. package/skills/growth-loop/references/platform-benchmarks.md +79 -0
  430. package/skills/growth-loop/scripts/init-campaign.sh +274 -0
  431. package/skills/humanize-ai-text/.clawhub/origin.json +7 -0
  432. package/skills/humanize-ai-text/SKILL.md +192 -0
  433. package/skills/humanize-ai-text/scripts/compare.py +58 -0
  434. package/skills/humanize-ai-text/scripts/detect.py +160 -0
  435. package/skills/humanize-ai-text/scripts/patterns.json +191 -0
  436. package/skills/humanize-ai-text/scripts/transform.py +127 -0
  437. package/skills/humanizer/.clawhub/origin.json +7 -0
  438. package/skills/humanizer/README.md +82 -0
  439. package/skills/humanizer/SKILL.md +443 -0
  440. package/skills/jobs-to-be-done/SKILL.md +378 -0
  441. package/skills/jobs-to-be-done/examples/sample.md +80 -0
  442. package/skills/jobs-to-be-done/template.md +65 -0
  443. package/skills/lean-ux-canvas/SKILL.md +561 -0
  444. package/skills/lean-ux-canvas/examples/sample.md +88 -0
  445. package/skills/lean-ux-canvas/template.md +32 -0
  446. package/skills/markdown-formatter/.clawhub/origin.json +7 -0
  447. package/skills/markdown-formatter/README.md +137 -0
  448. package/skills/markdown-formatter/SKILL.md +369 -0
  449. package/skills/markdown-formatter/config.json +20 -0
  450. package/skills/markdown-formatter/index.js +439 -0
  451. package/skills/markdown-formatter/package.json +23 -0
  452. package/skills/markdown-formatter/test.js +23 -0
  453. package/skills/marketing-mode/.clawhub/origin.json +7 -0
  454. package/skills/marketing-mode/README.md +49 -0
  455. package/skills/marketing-mode/SKILL.md +703 -0
  456. package/skills/marketing-mode/mode-prompt.md +39 -0
  457. package/skills/marketing-mode/skill.json +51 -0
  458. package/skills/memory-hygiene/.clawhub/origin.json +7 -0
  459. package/skills/memory-hygiene/SKILL.md +91 -0
  460. package/skills/memory-setup/.clawhub/origin.json +7 -0
  461. package/skills/memory-setup/SKILL.md +180 -0
  462. package/skills/memorylayer/.clawhub/origin.json +7 -0
  463. package/skills/memorylayer/README.md +197 -0
  464. package/skills/memorylayer/SKILL.md +227 -0
  465. package/skills/memorylayer/examples/agent-integration.js +145 -0
  466. package/skills/memorylayer/examples/basic-usage.js +87 -0
  467. package/skills/memorylayer/examples/token-savings-demo.js +183 -0
  468. package/skills/memorylayer/index.js +115 -0
  469. package/skills/memorylayer/package-lock.json +295 -0
  470. package/skills/memorylayer/package.json +27 -0
  471. package/skills/memorylayer/python/memorylayer_skill.py +230 -0
  472. package/skills/memorylayer/python/requirements.txt +7 -0
  473. package/skills/mesh/SKILL.md +184 -0
  474. package/skills/model-usage/.clawhub/origin.json +7 -0
  475. package/skills/model-usage/SKILL.md +54 -0
  476. package/skills/model-usage/references/codexbar-cli.md +28 -0
  477. package/skills/model-usage/scripts/model_usage.py +310 -0
  478. package/skills/moltbook-interact/.clawhub/origin.json +7 -0
  479. package/skills/moltbook-interact/INSTALL.md +139 -0
  480. package/skills/moltbook-interact/README.md +198 -0
  481. package/skills/moltbook-interact/SKILL.md +72 -0
  482. package/skills/moltbook-interact/references/api.md +106 -0
  483. package/skills/moltbook-interact/scripts/moltbook.sh +142 -0
  484. package/skills/moltbook-registry/.clawhub/origin.json +7 -0
  485. package/skills/moltbook-registry/README.md +26 -0
  486. package/skills/moltbook-registry/SKILL.md +82 -0
  487. package/skills/moltbook-registry/index.js +180 -0
  488. package/skills/moltbook-registry/package.json +11 -0
  489. package/skills/mythril-scanner/SKILL.md +27 -0
  490. package/skills/n8n/.clawhub/origin.json +7 -0
  491. package/skills/n8n/SKILL.md +141 -0
  492. package/skills/n8n/references/api.md +156 -0
  493. package/skills/n8n/scripts/n8n_api.py +158 -0
  494. package/skills/n8n-workflow-automation/.clawhub/origin.json +7 -0
  495. package/skills/n8n-workflow-automation/SKILL.md +103 -0
  496. package/skills/n8n-workflow-automation/assets/runbook-template.md +32 -0
  497. package/skills/narrative-designer/SKILL.md +27 -0
  498. package/skills/ontology/.clawhub/origin.json +7 -0
  499. package/skills/ontology/SKILL.md +236 -0
  500. package/skills/ontology/references/queries.md +211 -0
  501. package/skills/ontology/references/schema.md +322 -0
  502. package/skills/ontology/scripts/ontology.py +374 -0
  503. package/skills/openai-image-gen/.clawhub/origin.json +7 -0
  504. package/skills/openai-image-gen/SKILL.md +45 -0
  505. package/skills/openai-image-gen/scripts/gen.py +227 -0
  506. package/skills/openclaw-agent-optimize/.clawhub/origin.json +7 -0
  507. package/skills/openclaw-agent-optimize/SKILL.md +33 -0
  508. package/skills/openclaw-agent-optimize/references/agent-orchestration.md +20 -0
  509. package/skills/openclaw-agent-optimize/references/context-management.md +15 -0
  510. package/skills/openclaw-agent-optimize/references/continuous-learning.md +14 -0
  511. package/skills/openclaw-agent-optimize/references/cron-optimization.md +16 -0
  512. package/skills/openclaw-agent-optimize/references/memory-patterns.md +14 -0
  513. package/skills/openclaw-agent-optimize/references/model-selection.md +18 -0
  514. package/skills/openclaw-skill-scanner/.clawhub/origin.json +7 -0
  515. package/skills/openclaw-skill-scanner/SKILL.md +88 -0
  516. package/skills/openclaw-skill-scanner/install-hook.sh +294 -0
  517. package/skills/openclaw-skill-scanner/report-template.md +53 -0
  518. package/skills/openclaw-skill-scanner/scanner.py +929 -0
  519. package/skills/openclaw-skill-scanner/whitelist.json +18 -0
  520. package/skills/opportunity-solution-tree/SKILL.md +428 -0
  521. package/skills/opportunity-solution-tree/examples/sample.md +104 -0
  522. package/skills/opportunity-solution-tree/template.md +33 -0
  523. package/skills/pdf/.clawhub/origin.json +7 -0
  524. package/skills/pdf/SKILL.md +304 -0
  525. package/skills/pestel-analysis/SKILL.md +384 -0
  526. package/skills/pestel-analysis/examples/sample.md +143 -0
  527. package/skills/pestel-analysis/template.md +53 -0
  528. package/skills/pol-probe/SKILL.md +217 -0
  529. package/skills/pol-probe/examples/sample.md +136 -0
  530. package/skills/pol-probe/template.md +59 -0
  531. package/skills/pol-probe-advisor/SKILL.md +492 -0
  532. package/skills/positioning-statement/SKILL.md +229 -0
  533. package/skills/positioning-statement/examples/sample.md +51 -0
  534. package/skills/positioning-statement/template.md +25 -0
  535. package/skills/positioning-workshop/SKILL.md +424 -0
  536. package/skills/prd-development/SKILL.md +654 -0
  537. package/skills/prd-development/examples/sample.md +43 -0
  538. package/skills/prd-development/template.md +55 -0
  539. package/skills/press-release/SKILL.md +277 -0
  540. package/skills/press-release/examples/sample.md +73 -0
  541. package/skills/press-release/template.md +39 -0
  542. package/skills/prioritization-advisor/SKILL.md +451 -0
  543. package/skills/proactive-messages/.clawhub/origin.json +7 -0
  544. package/skills/proactive-messages/SKILL.md +91 -0
  545. package/skills/problem-framing-canvas/SKILL.md +466 -0
  546. package/skills/problem-framing-canvas/examples/sample.md +58 -0
  547. package/skills/problem-framing-canvas/template.md +22 -0
  548. package/skills/problem-statement/SKILL.md +255 -0
  549. package/skills/problem-statement/examples/sample.md +82 -0
  550. package/skills/problem-statement/template.md +37 -0
  551. package/skills/product-strategy-session/SKILL.md +434 -0
  552. package/skills/product-strategy-session/examples/sample.md +67 -0
  553. package/skills/product-strategy-session/template.md +38 -0
  554. package/skills/prompt-guard/.clawhub/origin.json +7 -0
  555. package/skills/prompt-guard/ARCHITECTURE.md +364 -0
  556. package/skills/prompt-guard/CHANGELOG.md +200 -0
  557. package/skills/prompt-guard/README.md +215 -0
  558. package/skills/prompt-guard/SECURITY.md +66 -0
  559. package/skills/prompt-guard/SKILL.md +174 -0
  560. package/skills/prompt-guard/blog/how-i-secured-my-ai-agent.md +185 -0
  561. package/skills/prompt-guard/config.example.yaml +56 -0
  562. package/skills/prompt-guard/references/detection-patterns.md +298 -0
  563. package/skills/prompt-guard/requirements.txt +1 -0
  564. package/skills/prompt-guard/scripts/analyze_log.py +224 -0
  565. package/skills/prompt-guard/scripts/audit.py +344 -0
  566. package/skills/prompt-guard/scripts/detect.py +1587 -0
  567. package/skills/prompt-guard/scripts/hivefence.py +345 -0
  568. package/skills/proto-persona/SKILL.md +336 -0
  569. package/skills/proto-persona/examples/sample.md +97 -0
  570. package/skills/proto-persona/template.md +45 -0
  571. package/skills/recommendation-canvas/SKILL.md +382 -0
  572. package/skills/recommendation-canvas/examples/sample.md +94 -0
  573. package/skills/recommendation-canvas/template.md +86 -0
  574. package/skills/refactor-suggest/.clawhub/origin.json +7 -0
  575. package/skills/refactor-suggest/SKILL.md +94 -0
  576. package/skills/roadmap-planning/SKILL.md +506 -0
  577. package/skills/roadmap-planning/examples/sample.md +62 -0
  578. package/skills/roadmap-planning/template.md +30 -0
  579. package/skills/saas-economics-efficiency-metrics/SKILL.md +694 -0
  580. package/skills/saas-economics-efficiency-metrics/examples/cash-trap.md +365 -0
  581. package/skills/saas-economics-efficiency-metrics/examples/healthy-unit-economics.md +279 -0
  582. package/skills/saas-economics-efficiency-metrics/template.md +263 -0
  583. package/skills/saas-revenue-growth-metrics/SKILL.md +629 -0
  584. package/skills/saas-revenue-growth-metrics/examples/healthy-saas.md +131 -0
  585. package/skills/saas-revenue-growth-metrics/examples/warning-signs.md +229 -0
  586. package/skills/saas-revenue-growth-metrics/template.md +192 -0
  587. package/skills/save-money/.clawhub/origin.json +7 -0
  588. package/skills/save-money/SKILL.md +173 -0
  589. package/skills/scripts/golden_skills_v3.sh +32 -0
  590. package/skills/search/.clawhub/origin.json +7 -0
  591. package/skills/search/SKILL.md +18 -0
  592. package/skills/search/skill.json +1 -0
  593. package/skills/second-brain/.clawhub/origin.json +7 -0
  594. package/skills/second-brain/SKILL.md +278 -0
  595. package/skills/second-brain/scripts/ensue-api.sh +37 -0
  596. package/skills/self-improving-agent/.clawhub/origin.json +7 -0
  597. package/skills/self-improving-agent/.learnings/ERRORS.md +5 -0
  598. package/skills/self-improving-agent/.learnings/FEATURE_REQUESTS.md +5 -0
  599. package/skills/self-improving-agent/.learnings/LEARNINGS.md +5 -0
  600. package/skills/self-improving-agent/SKILL.md +130 -0
  601. package/skills/self-improving-agent/assets/LEARNINGS.md +45 -0
  602. package/skills/self-improving-agent/assets/SKILL-TEMPLATE.md +177 -0
  603. package/skills/self-improving-agent/hooks/openclaw/HOOK.md +23 -0
  604. package/skills/self-improving-agent/hooks/openclaw/handler.js +56 -0
  605. package/skills/self-improving-agent/hooks/openclaw/handler.ts +62 -0
  606. package/skills/self-improving-agent/references/examples.md +374 -0
  607. package/skills/self-improving-agent/references/hooks-setup.md +223 -0
  608. package/skills/self-improving-agent/references/openclaw-integration.md +248 -0
  609. package/skills/self-improving-agent/references/templates.md +480 -0
  610. package/skills/self-improving-agent/scripts/activator.sh +20 -0
  611. package/skills/self-improving-agent/scripts/error-detector.sh +55 -0
  612. package/skills/self-improving-agent/scripts/extract-skill.sh +203 -0
  613. package/skills/self-improving-agent-1-0-2/.clawhub/origin.json +7 -0
  614. package/skills/self-improving-agent-1-0-2/SKILL.md +562 -0
  615. package/skills/self-improving-agent-1-0-2/assets/LEARNINGS.md +45 -0
  616. package/skills/self-improving-agent-1-0-2/assets/SKILL-TEMPLATE.md +182 -0
  617. package/skills/self-improving-agent-1-0-2/references/clawdbot-integration.md +311 -0
  618. package/skills/self-improving-agent-1-0-2/references/examples.md +374 -0
  619. package/skills/self-improving-agent-1-0-2/references/hooks-setup.md +223 -0
  620. package/skills/self-improving-agent-1-0-2/scripts/activator.sh +20 -0
  621. package/skills/self-improving-agent-1-0-2/scripts/error-detector.sh +55 -0
  622. package/skills/self-improving-agent-1-0-2/scripts/extract-skill.sh +203 -0
  623. package/skills/self-love-confidence/.clawhub/origin.json +7 -0
  624. package/skills/self-love-confidence/SKILL.md +79 -0
  625. package/skills/self-reflection/.clawhub/origin.json +7 -0
  626. package/skills/self-reflection/README.md +292 -0
  627. package/skills/self-reflection/SKILL.md +110 -0
  628. package/skills/self-reflection/self-reflection.example.json +6 -0
  629. package/skills/slither-analyzer/SKILL.md +27 -0
  630. package/skills/solidity-audit/SKILL.md +27 -0
  631. package/skills/soulcraft/.clawhub/origin.json +7 -0
  632. package/skills/soulcraft/README.md +123 -0
  633. package/skills/soulcraft/SKILL.md +340 -0
  634. package/skills/soulcraft/references/question-bank.md +154 -0
  635. package/skills/soulcraft/references/soul-examples.md +207 -0
  636. package/skills/soulcraft/research/RESEARCH_REPORT.md +317 -0
  637. package/skills/spotify-player/.clawhub/origin.json +7 -0
  638. package/skills/spotify-player/SKILL.md +44 -0
  639. package/skills/storyboard/SKILL.md +259 -0
  640. package/skills/storyboard/examples/sample.md +71 -0
  641. package/skills/storyboard/template.md +41 -0
  642. package/skills/summarize/.clawhub/origin.json +7 -0
  643. package/skills/summarize/SKILL.md +59 -0
  644. package/skills/superdesign/.clawhub/origin.json +7 -0
  645. package/skills/superdesign/SKILL.md +224 -0
  646. package/skills/tam-sam-som-calculator/SKILL.md +399 -0
  647. package/skills/tam-sam-som-calculator/examples/sample.md +142 -0
  648. package/skills/tam-sam-som-calculator/scripts/market-sizing.py +95 -0
  649. package/skills/tam-sam-som-calculator/template.md +35 -0
  650. package/skills/tavily-search/.clawhub/origin.json +7 -0
  651. package/skills/tavily-search/SKILL.md +49 -0
  652. package/skills/tavily-search/scripts/extract.mjs +59 -0
  653. package/skills/tavily-search/scripts/search.mjs +101 -0
  654. package/skills/twitter/SKILL.md +74 -0
  655. package/skills/twitter/_meta.json +9 -0
  656. package/skills/twitter/references/validation-cases.md +53 -0
  657. package/skills/twitter/scripts/twitter.sh +421 -0
  658. package/skills/ui-ux-pro-max/.clawhub/origin.json +7 -0
  659. package/skills/ui-ux-pro-max/SKILL.md +54 -0
  660. package/skills/ui-ux-pro-max/assets/data/charts.csv +26 -0
  661. package/skills/ui-ux-pro-max/assets/data/colors.csv +97 -0
  662. package/skills/ui-ux-pro-max/assets/data/icons.csv +101 -0
  663. package/skills/ui-ux-pro-max/assets/data/landing.csv +31 -0
  664. package/skills/ui-ux-pro-max/assets/data/products.csv +97 -0
  665. package/skills/ui-ux-pro-max/assets/data/react-performance.csv +45 -0
  666. package/skills/ui-ux-pro-max/assets/data/stacks/astro.csv +54 -0
  667. package/skills/ui-ux-pro-max/assets/data/stacks/flutter.csv +53 -0
  668. package/skills/ui-ux-pro-max/assets/data/stacks/html-tailwind.csv +56 -0
  669. package/skills/ui-ux-pro-max/assets/data/stacks/jetpack-compose.csv +53 -0
  670. package/skills/ui-ux-pro-max/assets/data/stacks/nextjs.csv +53 -0
  671. package/skills/ui-ux-pro-max/assets/data/stacks/nuxt-ui.csv +51 -0
  672. package/skills/ui-ux-pro-max/assets/data/stacks/nuxtjs.csv +59 -0
  673. package/skills/ui-ux-pro-max/assets/data/stacks/react-native.csv +52 -0
  674. package/skills/ui-ux-pro-max/assets/data/stacks/react.csv +54 -0
  675. package/skills/ui-ux-pro-max/assets/data/stacks/shadcn.csv +61 -0
  676. package/skills/ui-ux-pro-max/assets/data/stacks/svelte.csv +54 -0
  677. package/skills/ui-ux-pro-max/assets/data/stacks/swiftui.csv +51 -0
  678. package/skills/ui-ux-pro-max/assets/data/stacks/vue.csv +50 -0
  679. package/skills/ui-ux-pro-max/assets/data/styles.csv +68 -0
  680. package/skills/ui-ux-pro-max/assets/data/typography.csv +58 -0
  681. package/skills/ui-ux-pro-max/assets/data/ui-reasoning.csv +101 -0
  682. package/skills/ui-ux-pro-max/assets/data/ux-guidelines.csv +100 -0
  683. package/skills/ui-ux-pro-max/assets/data/web-interface.csv +31 -0
  684. package/skills/ui-ux-pro-max/references/upstream-README.md +488 -0
  685. package/skills/ui-ux-pro-max/references/upstream-skill-content.md +288 -0
  686. package/skills/ui-ux-pro-max/scripts/__init__.py +0 -0
  687. package/skills/ui-ux-pro-max/scripts/core.py +253 -0
  688. package/skills/ui-ux-pro-max/scripts/design_system.py +1071 -0
  689. package/skills/ui-ux-pro-max/scripts/search.py +111 -0
  690. package/skills/user-story/SKILL.md +272 -0
  691. package/skills/user-story/examples/sample.md +110 -0
  692. package/skills/user-story/scripts/user-story-template.py +65 -0
  693. package/skills/user-story/template.md +32 -0
  694. package/skills/user-story-mapping/SKILL.md +296 -0
  695. package/skills/user-story-mapping/examples/sample.md +77 -0
  696. package/skills/user-story-mapping/template.md +41 -0
  697. package/skills/user-story-mapping-workshop/SKILL.md +485 -0
  698. package/skills/user-story-mapping-workshop/template.md +28 -0
  699. package/skills/user-story-splitting/SKILL.md +313 -0
  700. package/skills/user-story-splitting/examples/sample.md +147 -0
  701. package/skills/user-story-splitting/template.md +37 -0
  702. package/skills/wacli/.clawhub/origin.json +7 -0
  703. package/skills/wacli/SKILL.md +53 -0
  704. package/skills/web-search/.clawhub/origin.json +7 -0
  705. package/skills/web-search/SKILL.md +151 -0
  706. package/skills/web-search/references/api-details.md +207 -0
  707. package/skills/web-search/scripts/search.py +576 -0
  708. package/skills/workshop-facilitation/SKILL.md +88 -0
  709. package/skills/world-builder/SKILL.md +27 -0
  710. package/souls/blockchain-auditor/PRINCIPLES.md +75 -0
  711. package/souls/blockchain-auditor/SOUL.md +56 -0
  712. package/souls/blockchain-auditor/capabilities.json +33 -0
  713. package/souls/blockchain-auditor/evolution/capsules.json +4 -0
  714. package/souls/blockchain-auditor/evolution/events.jsonl +1 -0
  715. package/souls/blockchain-auditor/evolution/genes.json +62 -0
  716. package/souls/daedalus/PRINCIPLES.md +78 -0
  717. package/souls/daedalus/SOUL.md +48 -0
  718. package/souls/daedalus/capabilities.json +46 -0
  719. package/souls/identity-architect/PRINCIPLES.md +83 -0
  720. package/souls/identity-architect/SOUL.md +66 -0
  721. package/souls/identity-architect/capabilities.json +38 -0
  722. package/souls/identity-architect/evolution/capsules.json +4 -0
  723. package/souls/identity-architect/evolution/events.jsonl +0 -0
  724. package/souls/identity-architect/evolution/genes.json +4 -0
  725. package/souls/infra-ops/PRINCIPLES.md +77 -0
  726. package/souls/infra-ops/SOUL.md +56 -0
  727. package/souls/infra-ops/capabilities.json +33 -0
  728. package/souls/infra-ops/evolution/capsules.json +4 -0
  729. package/souls/infra-ops/evolution/events.jsonl +0 -0
  730. package/souls/infra-ops/evolution/genes.json +4 -0
  731. package/souls/lore-writer/PRINCIPLES.md +74 -0
  732. package/souls/lore-writer/SOUL.md +54 -0
  733. package/souls/lore-writer/capabilities.json +37 -0
  734. package/souls/lore-writer/evolution/capsules.json +4 -0
  735. package/souls/lore-writer/evolution/events.jsonl +0 -0
  736. package/souls/lore-writer/evolution/genes.json +4 -0
  737. package/souls/qa-evidence/PRINCIPLES.md +97 -0
  738. package/souls/qa-evidence/SOUL.md +66 -0
  739. package/souls/qa-evidence/capabilities.json +32 -0
  740. package/souls/qa-evidence/evolution/capsules.json +4 -0
  741. package/souls/qa-evidence/evolution/events.jsonl +0 -0
  742. package/souls/qa-evidence/evolution/genes.json +4 -0
  743. package/souls/registry.json +211 -0
  744. package/souls/sync-registry.js +65 -0
  745. package/uninstall.sh +102 -0
  746. package/workspace-bin/auto-checkpoint +60 -0
  747. package/workspace-bin/clawvault-access-control +65 -0
  748. package/workspace-bin/clawvault-local +28 -0
  749. package/workspace-bin/compile-boot +494 -0
  750. package/workspace-bin/daily-log-writer.mjs +251 -0
  751. package/workspace-bin/evolve +540 -0
  752. package/workspace-bin/fitness_score.py +395 -0
  753. package/workspace-bin/hooks/pre-commit +80 -0
  754. package/workspace-bin/install-daemon +299 -0
  755. package/workspace-bin/lane-watchdog.js +232 -0
  756. package/workspace-bin/lib/__init__.py +0 -0
  757. package/workspace-bin/lib/frontmatter.py +114 -0
  758. package/workspace-bin/memory-daemon.mjs +879 -0
  759. package/workspace-bin/memory-maintenance.mjs +531 -0
  760. package/workspace-bin/mesh-bridge.mjs +154 -0
  761. package/workspace-bin/multi-review +130 -0
  762. package/workspace-bin/obsidian +125 -0
  763. package/workspace-bin/obsidian-sync.mjs +888 -0
  764. package/workspace-bin/openclaw-register-source +102 -0
  765. package/workspace-bin/proactive-scan +147 -0
  766. package/workspace-bin/quality-gate +175 -0
  767. package/workspace-bin/screenshot +96 -0
  768. package/workspace-bin/session-recap +453 -0
  769. package/workspace-bin/skill-audit +494 -0
  770. package/workspace-bin/skill-quality-check +134 -0
  771. package/workspace-bin/skill-routing-eval +599 -0
  772. package/workspace-bin/soul-prompt +251 -0
  773. package/workspace-bin/subagent-audit.mjs +267 -0
  774. package/workspace-bin/test-multi-soul-workflow +130 -0
  775. package/workspace-bin/trust-registry +465 -0
  776. package/workspace-docs/AGENTS.md +201 -0
  777. package/workspace-docs/CLAUDE.md +64 -0
  778. package/workspace-docs/PRINCIPLES.md +81 -0
  779. package/workspace-docs/SOUL.md +48 -0
@@ -0,0 +1,1048 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * mesh-deploy.js v2 — Full-stack OpenClaw deployment across all nodes.
5
+ *
6
+ * Covers EVERYTHING: mesh daemons, Mission Control, memory system,
7
+ * soul system, skills, boot compiler, companion-bridge, OpenClaw
8
+ * gateway, database migrations, config regeneration, service definitions.
9
+ *
10
+ * ARCHITECTURE:
11
+ * Each deployable component is defined in the MANIFEST with:
12
+ * - id: unique name
13
+ * - source: where the canonical files live (repo path or npm package)
14
+ * - targets: where files get installed on each node
15
+ * - detect: how to tell if something changed
16
+ * - install: how to deploy the change
17
+ * - restart: which services to bounce
18
+ * - validate: how to confirm the deploy worked
19
+ * - risk: "safe" (auto-deploy) | "careful" (warn) | "manual" (skip unless --force)
20
+ *
21
+ * USAGE:
22
+ * mesh deploy — deploy everything that changed
23
+ * mesh deploy --dry-run — preview what would happen
24
+ * mesh deploy --component mc — deploy only Mission Control
25
+ * mesh deploy --component mesh — deploy only mesh daemons
26
+ * mesh deploy --component all — deploy everything (even unchanged)
27
+ * mesh deploy --local — this node only
28
+ * mesh deploy --node ubuntu — remote node only
29
+ * mesh deploy --include-services — also update launchd/systemd units
30
+ * mesh deploy --rollback — revert last deploy
31
+ * mesh deploy --status — show what's deployed vs what's in git
32
+ *
33
+ * ENVIRONMENT:
34
+ * OPENCLAW_DEPLOY_BRANCH — git branch (default: main)
35
+ * OPENCLAW_REPO_DIR — repo location (default: ~/openclaw-node)
36
+ * OPENCLAW_NATS — NATS server URL (from env or openclaw.env)
37
+ */
38
+
39
+ const { execSync } = require('child_process');
40
+ const fs = require('fs');
41
+ const path = require('path');
42
+ const os = require('os');
43
+ const crypto = require('crypto');
44
+
45
+ // ── Constants ────────────────────────────────────────────────────────────
46
+
47
+ const IS_MAC = os.platform() === 'darwin';
48
+ const HOME = os.homedir();
49
+ const DEPLOY_BRANCH = process.env.OPENCLAW_DEPLOY_BRANCH || 'main';
50
+ const REPO_DIR = process.env.OPENCLAW_REPO_DIR || path.join(HOME, 'openclaw-node');
51
+
52
+ // Standard directory layout
53
+ const DIRS = {
54
+ OPENCLAW_HOME: path.join(HOME, '.openclaw'),
55
+ WORKSPACE: path.join(HOME, '.openclaw', 'workspace'),
56
+ WORKSPACE_BIN: path.join(HOME, '.openclaw', 'workspace', 'bin'),
57
+ CLI_BIN: path.join(HOME, 'openclaw', 'bin'),
58
+ CLI_LIB: path.join(HOME, 'openclaw', 'lib'),
59
+ MC_PROJECT: path.join(HOME, '.openclaw', 'workspace', 'projects', 'mission-control'),
60
+ SKILLS: path.join(HOME, '.openclaw', 'skills'),
61
+ SOULS: path.join(HOME, '.openclaw', 'souls'),
62
+ CONFIG: path.join(HOME, '.openclaw', 'config'),
63
+ BOOT: path.join(HOME, '.openclaw', 'workspace', '.boot'),
64
+ BOOT_SRC: path.join(HOME, '.openclaw', 'workspace', 'bin'), // compile-boot lives here
65
+ MEMORY: path.join(HOME, '.openclaw', 'workspace', 'memory'),
66
+ MEMORY_VAULT: path.join(HOME, '.openclaw', 'workspace', 'memory-vault'),
67
+ IDENTITY: path.join(HOME, '.openclaw', 'identity'),
68
+ SERVICES_MAC: path.join(HOME, 'Library', 'LaunchAgents'),
69
+ SERVICES_LINUX: path.join(HOME, '.config', 'systemd', 'user'),
70
+ COMPANION: path.join(HOME, 'companion-adapter'),
71
+ TMP: path.join(HOME, '.openclaw', 'workspace', '.tmp'),
72
+ DEPLOY_STATE: path.join(HOME, '.openclaw', '.deploy-state.json'),
73
+ };
74
+
75
+ // Node role — determines which components deploy here.
76
+ // Reads from OPENCLAW_NODE_ROLE env, or openclaw.env, or defaults by platform.
77
+ function resolveNodeRole() {
78
+ if (process.env.OPENCLAW_NODE_ROLE) return process.env.OPENCLAW_NODE_ROLE;
79
+ try {
80
+ const envFile = path.join(HOME, '.openclaw', 'openclaw.env');
81
+ if (fs.existsSync(envFile)) {
82
+ const content = fs.readFileSync(envFile, 'utf8');
83
+ const match = content.match(/^\s*OPENCLAW_NODE_ROLE\s*=\s*(.+)/m);
84
+ if (match && match[1].trim()) return match[1].trim();
85
+ }
86
+ } catch {}
87
+ return IS_MAC ? 'lead' : 'worker';
88
+ }
89
+ const NODE_ROLE = resolveNodeRole();
90
+
91
+ // ── Console helpers ──────────────────────────────────────────────────────
92
+
93
+ const C = {
94
+ red: s => `\x1b[31m${s}\x1b[0m`,
95
+ green: s => `\x1b[32m${s}\x1b[0m`,
96
+ yellow: s => `\x1b[33m${s}\x1b[0m`,
97
+ cyan: s => `\x1b[36m${s}\x1b[0m`,
98
+ bold: s => `\x1b[1m${s}\x1b[0m`,
99
+ dim: s => `\x1b[2m${s}\x1b[0m`,
100
+ };
101
+
102
+ function ok(msg) { console.log(` ${C.green('[OK]')} ${msg}`); }
103
+ function warn(msg) { console.log(` ${C.yellow('[WARN]')} ${msg}`); }
104
+ function fail(msg) { console.log(` ${C.red('[FAIL]')} ${msg}`); }
105
+ function info(msg) { console.log(` ${C.cyan('-->>')} ${msg}`); }
106
+ function skip(msg) { console.log(` ${C.dim('[SKIP]')} ${msg}`); }
107
+ function header(msg) { console.log(`\n${C.bold(`═══ ${msg} ═══`)}\n`); }
108
+
109
+ // ── Shell helpers ────────────────────────────────────────────────────────
110
+
111
+ function exec(cmd, opts = {}) {
112
+ try {
113
+ return execSync(cmd, {
114
+ encoding: 'utf8',
115
+ timeout: opts.timeout || 120000,
116
+ stdio: ['pipe', 'pipe', 'pipe'],
117
+ cwd: opts.cwd,
118
+ ...opts,
119
+ }).trim();
120
+ } catch (err) {
121
+ if (opts.ignoreError) return err.stdout?.trim() || '';
122
+ throw err;
123
+ }
124
+ }
125
+
126
+ function fileHash(filePath) {
127
+ try {
128
+ const content = fs.readFileSync(filePath);
129
+ return crypto.createHash('md5').update(content).digest('hex').slice(0, 8);
130
+ } catch { return null; }
131
+ }
132
+
133
+ // ═══════════════════════════════════════════════════════════════════════════
134
+ // COMPONENT MANIFEST — every deployable piece of OpenClaw
135
+ // ═══════════════════════════════════════════════════════════════════════════
136
+
137
+ const MANIFEST = [
138
+
139
+ // ── MESH INFRASTRUCTURE ─────────────────────────────────────────────────
140
+
141
+ {
142
+ id: 'mesh-daemons',
143
+ name: 'Mesh Daemons',
144
+ description: 'Task daemon, bridge, agent, health publisher',
145
+ risk: 'safe',
146
+ repoPaths: ['bin/mesh-task-daemon.js', 'bin/mesh-bridge.js', 'bin/mesh-agent.js',
147
+ 'bin/mesh-health-publisher.js', 'bin/mesh-deploy-listener.js'],
148
+ targets: [DIRS.CLI_BIN],
149
+ // Lead runs all 4; worker runs only agent + health publisher.
150
+ // Service names differ: macOS=launchd labels, Linux=systemd unit names.
151
+ servicesMac: ['ai.openclaw.mesh-task-daemon', 'ai.openclaw.mesh-bridge',
152
+ 'ai.openclaw.mesh-agent', 'ai.openclaw.mesh-health-publisher'],
153
+ servicesLinux: ['openclaw-agent', 'openclaw-mesh-health-publisher'],
154
+ nodeFilter: 'all', // Every node gets daemon binaries; services are per-role
155
+ validate: () => {
156
+ const cmd = IS_MAC
157
+ ? 'launchctl list ai.openclaw.mesh-task-daemon 2>/dev/null | grep PID'
158
+ : 'systemctl is-active openclaw-agent 2>/dev/null';
159
+ return exec(cmd, { ignoreError: true }).length > 0;
160
+ },
161
+ },
162
+
163
+ {
164
+ id: 'mesh-cli',
165
+ name: 'Mesh CLI Tools',
166
+ description: 'mesh command, health check, repair, deploy, fleet-deploy',
167
+ risk: 'safe',
168
+ repoPaths: ['bin/mesh.js', 'bin/mesh-deploy.js', 'bin/fleet-deploy.js',
169
+ 'bin/mesh-health.sh', 'bin/mesh-repair.sh'],
170
+ targets: [DIRS.CLI_BIN],
171
+ servicesMac: [],
172
+ servicesLinux: [],
173
+ nodeFilter: 'all',
174
+ postInstall: () => {
175
+ const wrapperPath = path.join(DIRS.CLI_BIN, 'mesh');
176
+ if (fs.existsSync(wrapperPath)) fs.chmodSync(wrapperPath, 0o755);
177
+ },
178
+ },
179
+
180
+ {
181
+ id: 'shared-lib',
182
+ name: 'Shared Libraries',
183
+ description: 'nats-resolve.js, agent-activity.js, kanban-io.js, mesh-registry.js, mesh-tasks.js',
184
+ risk: 'safe',
185
+ repoPaths: ['lib/'],
186
+ targets: [DIRS.CLI_LIB],
187
+ servicesMac: ['ai.openclaw.mesh-task-daemon', 'ai.openclaw.mesh-bridge',
188
+ 'ai.openclaw.mesh-agent'],
189
+ servicesLinux: ['openclaw-agent'],
190
+ nodeFilter: 'all',
191
+ },
192
+
193
+ // ── MISSION CONTROL ─────────────────────────────────────────────────────
194
+
195
+ {
196
+ id: 'mc',
197
+ name: 'Mission Control',
198
+ description: 'Next.js dashboard — kanban, memory, souls, graph, calendar',
199
+ risk: 'safe',
200
+ repoPaths: ['mission-control/'],
201
+ targets: [DIRS.MC_PROJECT],
202
+ servicesMac: ['ai.openclaw.mission-control'],
203
+ servicesLinux: [], // MC only runs on lead
204
+ nodeFilter: 'lead',
205
+ postInstall: (changedFiles) => {
206
+ const needsNpm = changedFiles.some(f =>
207
+ f.includes('package.json') || f.includes('package-lock.json')
208
+ );
209
+ if (needsNpm) {
210
+ info('Running npm install for Mission Control...');
211
+ exec('npm install', { cwd: DIRS.MC_PROJECT, timeout: 180000 });
212
+ ok('npm install complete');
213
+ }
214
+ },
215
+ validate: () => {
216
+ const dbPath = path.join(DIRS.MC_PROJECT, 'data', 'mission-control.db');
217
+ return fs.existsSync(dbPath);
218
+ },
219
+ notes: 'DB migrations run automatically on MC startup via db/index.ts runMigrations(). ' +
220
+ 'New columns (ALTER TABLE) are idempotent. Schema-breaking changes need a ' +
221
+ 'migration plan before deploy.',
222
+ },
223
+
224
+ // ── MEMORY SYSTEM ───────────────────────────────────────────────────────
225
+
226
+ {
227
+ id: 'memory-daemon',
228
+ name: 'Memory Daemon',
229
+ description: 'Session recap, ClawVault maintenance, daily log generation, Obsidian sync',
230
+ risk: 'safe',
231
+ repoPaths: ['workspace-bin/memory-daemon.mjs', 'workspace-bin/memory-maintenance.mjs'],
232
+ targets: [DIRS.WORKSPACE_BIN],
233
+ servicesMac: ['ai.openclaw.memory-daemon'],
234
+ servicesLinux: [], // Lead only
235
+ nodeFilter: 'lead',
236
+ },
237
+
238
+ {
239
+ id: 'memory-harness',
240
+ name: 'Memory Harness Templates',
241
+ description: 'MEMORY.md template, extraction configs, consolidation rules',
242
+ risk: 'careful',
243
+ repoPaths: ['config/memory-config.json', 'config/extraction-rules.json'],
244
+ targets: [DIRS.CONFIG],
245
+ servicesMac: ['ai.openclaw.memory-daemon'],
246
+ servicesLinux: [],
247
+ nodeFilter: 'lead',
248
+ notes: 'Does NOT overwrite MEMORY.md, memory-vault/, or daily logs — those are user data. ' +
249
+ 'Only deploys config templates that control extraction and consolidation behavior.',
250
+ },
251
+
252
+ // ── SOUL SYSTEM ─────────────────────────────────────────────────────────
253
+
254
+ {
255
+ id: 'souls',
256
+ name: 'Soul Definitions',
257
+ description: 'Daedalus and specialist soul files, trust registry, evolution config',
258
+ risk: 'careful',
259
+ repoPaths: ['souls/'],
260
+ targets: [DIRS.SOULS],
261
+ servicesMac: [],
262
+ servicesLinux: [],
263
+ nodeFilter: 'all',
264
+ preInstall: (changedFiles) => {
265
+ for (const f of changedFiles) {
266
+ if (f.includes('genes.json') || f.includes('events.jsonl')) {
267
+ const targetPath = path.join(DIRS.SOULS, f.replace('souls/', ''));
268
+ if (fs.existsSync(targetPath)) {
269
+ const backupPath = targetPath + '.pre-deploy';
270
+ fs.copyFileSync(targetPath, backupPath);
271
+ info(`Backed up ${path.basename(targetPath)} → .pre-deploy`);
272
+ }
273
+ }
274
+ }
275
+ },
276
+ notes: 'Evolution genes (genes.json) and event logs (events.jsonl) contain ' +
277
+ 'learned behavior. Pre-deploy backup is automatic.',
278
+ },
279
+
280
+ // ── SKILLS ──────────────────────────────────────────────────────────────
281
+
282
+ {
283
+ id: 'skills',
284
+ name: 'Skill Library',
285
+ description: 'Skill definitions for AI agent capabilities',
286
+ risk: 'safe',
287
+ repoPaths: ['skills/'],
288
+ targets: [DIRS.SKILLS],
289
+ servicesMac: [],
290
+ servicesLinux: [],
291
+ nodeFilter: 'all',
292
+ },
293
+
294
+ // ── BOOT SYSTEM ─────────────────────────────────────────────────────────
295
+
296
+ {
297
+ id: 'boot',
298
+ name: 'Boot Compiler',
299
+ description: 'Profile-aware boot artifact generation (Python script)',
300
+ risk: 'safe',
301
+ repoPaths: ['workspace-bin/compile-boot'],
302
+ targets: [DIRS.BOOT_SRC], // = WORKSPACE_BIN (compile-boot lives there)
303
+ servicesMac: [],
304
+ servicesLinux: [],
305
+ nodeFilter: 'lead',
306
+ postInstall: () => {
307
+ const compilerPath = path.join(DIRS.BOOT_SRC, 'compile-boot');
308
+ if (fs.existsSync(compilerPath)) {
309
+ info('Recompiling boot profiles...');
310
+ try {
311
+ exec(`python3 "${compilerPath}"`, { cwd: DIRS.WORKSPACE });
312
+ ok('Boot profiles recompiled');
313
+ } catch (err) {
314
+ warn(`Boot recompile failed: ${err.message}`);
315
+ }
316
+ }
317
+ },
318
+ },
319
+
320
+ // ── WORKSPACE ROOT DOCUMENTS ────────────────────────────────────────────
321
+
322
+ {
323
+ id: 'workspace-docs',
324
+ name: 'Workspace Root Documents',
325
+ description: 'CLAUDE.md, SOUL.md, AGENTS.md, PRINCIPLES.md, HEARTBEAT.md',
326
+ risk: 'careful',
327
+ repoPaths: ['workspace-docs/CLAUDE.md', 'workspace-docs/SOUL.md',
328
+ 'workspace-docs/AGENTS.md', 'workspace-docs/PRINCIPLES.md'],
329
+ targets: [DIRS.WORKSPACE],
330
+ servicesMac: [],
331
+ servicesLinux: [],
332
+ nodeFilter: 'all',
333
+ preInstall: (changedFiles) => {
334
+ for (const f of changedFiles) {
335
+ const basename = path.basename(f);
336
+ const targetPath = path.join(DIRS.WORKSPACE, basename);
337
+ if (fs.existsSync(targetPath)) {
338
+ const srcPath = path.join(REPO_DIR, f);
339
+ const diff = exec(`diff "${targetPath}" "${srcPath}" | head -20`, { ignoreError: true });
340
+ if (diff) {
341
+ warn(`${basename} differs from repo version:`);
342
+ console.log(C.dim(diff.split('\n').map(l => ` ${l}`).join('\n')));
343
+ info(`Repo version saved to ${basename}.repo — merge manually if needed`);
344
+ fs.copyFileSync(srcPath, targetPath + '.repo');
345
+ return; // Don't overwrite
346
+ }
347
+ }
348
+ }
349
+ },
350
+ notes: 'These files are your agent identity docs. They are NOT auto-overwritten. ' +
351
+ 'If the repo has updates, they are saved as .repo files for manual merge.',
352
+ },
353
+
354
+ // ── IDENTITY ────────────────────────────────────────────────────────────
355
+
356
+ {
357
+ id: 'identity',
358
+ name: 'Node Identity',
359
+ description: 'Node identity files, mesh enrollment config',
360
+ risk: 'manual',
361
+ repoPaths: ['identity/'],
362
+ targets: [DIRS.IDENTITY],
363
+ servicesMac: [],
364
+ servicesLinux: [],
365
+ nodeFilter: 'all',
366
+ preInstall: () => {
367
+ if (fs.existsSync(path.join(DIRS.IDENTITY, 'device.json'))) {
368
+ skip('Identity files already exist — skipping (use --force to overwrite)');
369
+ return false;
370
+ }
371
+ },
372
+ },
373
+
374
+ // ── CONFIG TEMPLATES ────────────────────────────────────────────────────
375
+
376
+ {
377
+ id: 'config',
378
+ name: 'Configuration',
379
+ description: 'Daemon configs, transcript configs, sync settings',
380
+ risk: 'careful',
381
+ repoPaths: ['config/'],
382
+ targets: [DIRS.CONFIG],
383
+ servicesMac: [],
384
+ servicesLinux: [],
385
+ nodeFilter: 'all',
386
+ postInstall: () => {
387
+ const templatePath = path.join(DIRS.CONFIG, 'openclaw.json.template');
388
+ const envPath = path.join(DIRS.OPENCLAW_HOME, 'openclaw.env');
389
+ if (fs.existsSync(templatePath) && fs.existsSync(envPath)) {
390
+ info('Regenerating openclaw.json from template + env...');
391
+ try {
392
+ let template = fs.readFileSync(templatePath, 'utf8');
393
+ const env = fs.readFileSync(envPath, 'utf8');
394
+ for (const line of env.split('\n')) {
395
+ const match = line.match(/^\s*([A-Z_]+)\s*=\s*(.+)/);
396
+ if (match) {
397
+ template = template.replace(new RegExp(`\\$\\{${match[1]}\\}`, 'g'), match[2].trim());
398
+ }
399
+ }
400
+ const outPath = path.join(DIRS.OPENCLAW_HOME, 'openclaw.json');
401
+ fs.writeFileSync(outPath, template);
402
+ ok('openclaw.json regenerated');
403
+ } catch (err) {
404
+ warn(`Config regen failed: ${err.message}`);
405
+ }
406
+ }
407
+ },
408
+ notes: 'openclaw.env is NEVER deployed — it contains API keys and is per-node.',
409
+ },
410
+
411
+ // ── SERVICE DEFINITIONS ─────────────────────────────────────────────────
412
+
413
+ {
414
+ id: 'services',
415
+ name: 'Service Definitions',
416
+ description: 'launchd plists (macOS) / systemd units (Ubuntu)',
417
+ risk: 'manual',
418
+ repoPaths: IS_MAC ? ['services/launchd/'] : ['services/systemd/'],
419
+ targets: [IS_MAC ? DIRS.SERVICES_MAC : DIRS.SERVICES_LINUX],
420
+ servicesMac: [],
421
+ servicesLinux: [],
422
+ nodeFilter: 'all',
423
+ preInstall: () => {
424
+ warn('Service definitions require --include-services flag');
425
+ warn('A bad plist/unit can prevent services from starting');
426
+ return false;
427
+ },
428
+ postInstall: () => {
429
+ if (IS_MAC) {
430
+ info('Plists updated — run this to reload:');
431
+ console.log(' launchctl unload ~/Library/LaunchAgents/ai.openclaw.*.plist');
432
+ console.log(' launchctl load ~/Library/LaunchAgents/ai.openclaw.*.plist');
433
+ } else {
434
+ info('Units updated — run: systemctl --user daemon-reload');
435
+ exec('systemctl --user daemon-reload', { ignoreError: true });
436
+ }
437
+ },
438
+ },
439
+
440
+ // ── OPENCLAW GATEWAY (npm package) ──────────────────────────────────────
441
+
442
+ {
443
+ id: 'openclaw',
444
+ name: 'OpenClaw Gateway',
445
+ description: 'The TUI/gateway — installed globally via npm',
446
+ risk: 'careful',
447
+ repoPaths: [],
448
+ targets: [],
449
+ servicesMac: ['ai.openclaw.gateway'],
450
+ servicesLinux: ['openclaw-gateway'],
451
+ nodeFilter: 'all',
452
+ detect: () => {
453
+ try {
454
+ const current = exec('openclaw --version 2>/dev/null', { ignoreError: true });
455
+ const latest = exec('npm view openclaw version 2>/dev/null', { ignoreError: true });
456
+ if (current && latest && current !== latest) {
457
+ return { changed: true, current, latest };
458
+ }
459
+ } catch {}
460
+ return { changed: false };
461
+ },
462
+ install: (dryRun) => {
463
+ if (dryRun) {
464
+ info('Would run: npm update -g openclaw');
465
+ return;
466
+ }
467
+ info('Updating OpenClaw gateway...');
468
+ exec('npm update -g openclaw', { timeout: 180000 });
469
+ ok('OpenClaw updated');
470
+ },
471
+ },
472
+
473
+ // ── COMPANION BRIDGE ────────────────────────────────────────────────────
474
+
475
+ {
476
+ id: 'companion',
477
+ name: 'Companion Bridge',
478
+ description: 'companion-bridge npm package + local adapter.ts patches',
479
+ risk: 'careful',
480
+ repoPaths: [],
481
+ targets: [],
482
+ servicesMac: ['ai.openclaw.gateway'],
483
+ servicesLinux: ['openclaw-gateway'],
484
+ nodeFilter: 'lead',
485
+ detect: () => {
486
+ try {
487
+ if (fs.existsSync(DIRS.COMPANION)) {
488
+ const status = exec('git status --porcelain', { cwd: DIRS.COMPANION, ignoreError: true });
489
+ if (status) return { changed: true, reason: 'uncommitted local changes' };
490
+ }
491
+ const current = exec('npm ls companion-bridge --json 2>/dev/null', { ignoreError: true });
492
+ const latest = exec('npm view companion-bridge version 2>/dev/null', { ignoreError: true });
493
+ if (current && latest) {
494
+ return { changed: !current.includes(latest), current, latest };
495
+ }
496
+ } catch {}
497
+ return { changed: false };
498
+ },
499
+ install: (dryRun) => {
500
+ if (dryRun) {
501
+ info('Would update companion-bridge');
502
+ return;
503
+ }
504
+ if (fs.existsSync(DIRS.COMPANION)) {
505
+ info('Pulling companion-bridge source...');
506
+ exec('git pull origin main', { cwd: DIRS.COMPANION, ignoreError: true });
507
+ exec('npm install && npm run build', { cwd: DIRS.COMPANION, timeout: 120000 });
508
+ ok('companion-bridge rebuilt');
509
+ }
510
+ },
511
+ },
512
+
513
+ // ── LANE WATCHDOG ───────────────────────────────────────────────────────
514
+
515
+ {
516
+ id: 'lane-watchdog',
517
+ name: 'Lane Watchdog',
518
+ description: 'Kanban lane health monitoring',
519
+ risk: 'safe',
520
+ repoPaths: ['bin/lane-watchdog.js'],
521
+ targets: [DIRS.CLI_BIN],
522
+ servicesMac: ['ai.openclaw.lane-watchdog'],
523
+ servicesLinux: [], // Lead only
524
+ nodeFilter: 'lead',
525
+ },
526
+
527
+ // ── LOG ROTATION ────────────────────────────────────────────────────────
528
+
529
+ {
530
+ id: 'log-rotate',
531
+ name: 'Log Rotation',
532
+ description: 'Weekly log file rotation (copytruncate)',
533
+ risk: 'safe',
534
+ repoPaths: ['bin/log-rotate.sh'],
535
+ targets: [DIRS.CLI_BIN],
536
+ servicesMac: ['ai.openclaw.log-rotate'],
537
+ servicesLinux: [], // Ubuntu uses logrotate.d natively
538
+ nodeFilter: 'lead',
539
+ },
540
+
541
+ // ── DISCORD TOOL ────────────────────────────────────────────────────────
542
+
543
+ {
544
+ id: 'mesh-tool-discord',
545
+ name: 'Discord NATS Tool',
546
+ description: 'Discord channel history reader over NATS',
547
+ risk: 'safe',
548
+ repoPaths: ['bin/mesh-tool-discord.js', 'bin/discord-read.js'],
549
+ targets: [DIRS.CLI_BIN],
550
+ servicesMac: ['ai.openclaw.mesh-tool-discord'],
551
+ servicesLinux: [], // Lead only
552
+ nodeFilter: 'lead',
553
+ },
554
+ ];
555
+
556
+ // ═══════════════════════════════════════════════════════════════════════════
557
+ // DEPLOY ENGINE
558
+ // ═══════════════════════════════════════════════════════════════════════════
559
+
560
+ /**
561
+ * Load deploy state — tracks what was deployed when.
562
+ */
563
+ function loadDeployState() {
564
+ try {
565
+ if (fs.existsSync(DIRS.DEPLOY_STATE)) {
566
+ return JSON.parse(fs.readFileSync(DIRS.DEPLOY_STATE, 'utf8'));
567
+ }
568
+ } catch {}
569
+ return { lastDeploy: null, lastSha: null, components: {} };
570
+ }
571
+
572
+ function saveDeployState(state) {
573
+ const dir = path.dirname(DIRS.DEPLOY_STATE);
574
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
575
+ fs.writeFileSync(DIRS.DEPLOY_STATE, JSON.stringify(state, null, 2));
576
+ }
577
+
578
+ /**
579
+ * Git operations on the repo.
580
+ */
581
+ function gitFetchAndDiff(repoDir) {
582
+ if (!fs.existsSync(path.join(repoDir, '.git'))) {
583
+ fail(`Not a git repo: ${repoDir}`);
584
+ return { currentSha: null, remoteSha: null, changedFiles: [], upToDate: true };
585
+ }
586
+
587
+ exec(`git fetch origin ${DEPLOY_BRANCH}`, { cwd: repoDir });
588
+ const currentSha = exec('git rev-parse HEAD', { cwd: repoDir });
589
+ const remoteSha = exec(`git rev-parse origin/${DEPLOY_BRANCH}`, { cwd: repoDir });
590
+ const upToDate = currentSha === remoteSha;
591
+
592
+ let changedFiles = [];
593
+ if (!upToDate) {
594
+ const diff = exec(`git diff --name-only ${currentSha}..${remoteSha}`, { cwd: repoDir });
595
+ changedFiles = diff ? diff.split('\n').filter(Boolean) : [];
596
+ }
597
+
598
+ return { currentSha, remoteSha, changedFiles, upToDate };
599
+ }
600
+
601
+ function gitMerge(repoDir) {
602
+ const prevSha = exec('git rev-parse HEAD', { cwd: repoDir });
603
+ exec(`git merge origin/${DEPLOY_BRANCH} --ff-only`, { cwd: repoDir });
604
+ const newSha = exec('git rev-parse --short HEAD', { cwd: repoDir });
605
+ return { prevSha, newSha };
606
+ }
607
+
608
+ /**
609
+ * Determine which manifest components are affected by the changed files.
610
+ */
611
+ function getAffectedComponents(changedFiles, filterIds) {
612
+ const affected = [];
613
+
614
+ for (const comp of MANIFEST) {
615
+ // Skip components not meant for this node's role
616
+ if (comp.nodeFilter && comp.nodeFilter !== 'all' && comp.nodeFilter !== NODE_ROLE) {
617
+ continue;
618
+ }
619
+
620
+ // Filter by component ID if specified
621
+ if (filterIds && filterIds.length > 0 && !filterIds.includes(comp.id) && !filterIds.includes('all')) {
622
+ continue;
623
+ }
624
+
625
+ // npm-based components have their own detect() logic
626
+ if (comp.repoPaths.length === 0 && comp.detect) {
627
+ const result = comp.detect();
628
+ if (result.changed || (filterIds && filterIds.includes(comp.id))) {
629
+ affected.push({ ...comp, changedFiles: [], detectResult: result });
630
+ }
631
+ continue;
632
+ }
633
+
634
+ // Check if any changed file matches this component's repo paths
635
+ const matches = changedFiles.filter(f =>
636
+ comp.repoPaths.some(rp => {
637
+ if (rp.endsWith('/')) return f.startsWith(rp);
638
+ return f === rp;
639
+ })
640
+ );
641
+
642
+ if (matches.length > 0 || (filterIds && filterIds.includes('all'))) {
643
+ affected.push({ ...comp, changedFiles: matches });
644
+ }
645
+ }
646
+
647
+ return affected;
648
+ }
649
+
650
+ /**
651
+ * Install files from repo to target directory.
652
+ */
653
+ function installComponentFiles(comp, repoDir, dryRun) {
654
+ if (!comp.changedFiles || comp.changedFiles.length === 0) return 0;
655
+ let copied = 0;
656
+
657
+ for (const target of comp.targets) {
658
+ for (const relFile of comp.changedFiles) {
659
+ const srcPath = path.join(repoDir, relFile);
660
+ if (!fs.existsSync(srcPath)) continue;
661
+
662
+ // Strip matching repoPath prefix to determine destination subpath
663
+ let subPath = relFile;
664
+ for (const rp of comp.repoPaths) {
665
+ if (rp.endsWith('/') && relFile.startsWith(rp)) {
666
+ subPath = relFile.slice(rp.length);
667
+ break;
668
+ } else if (relFile === rp) {
669
+ subPath = path.basename(relFile);
670
+ break;
671
+ }
672
+ }
673
+ const dstPath = path.join(target, subPath);
674
+
675
+ if (dryRun) {
676
+ info(` ${relFile} → ${dstPath}`);
677
+ copied++;
678
+ continue;
679
+ }
680
+
681
+ const dstDir = path.dirname(dstPath);
682
+ if (!fs.existsSync(dstDir)) fs.mkdirSync(dstDir, { recursive: true });
683
+ fs.copyFileSync(srcPath, dstPath);
684
+
685
+ // Preserve executable bit
686
+ if (relFile.endsWith('.js') || relFile.endsWith('.sh')) {
687
+ fs.chmodSync(dstPath, 0o755);
688
+ }
689
+ copied++;
690
+ }
691
+ }
692
+ return copied;
693
+ }
694
+
695
+ /**
696
+ * Restart services for a component — rolling, one at a time.
697
+ */
698
+ function restartComponentServices(comp, dryRun) {
699
+ const services = IS_MAC ? comp.servicesMac : comp.servicesLinux;
700
+ if (!services || services.length === 0) return;
701
+
702
+ for (const svc of services) {
703
+ if (dryRun) {
704
+ info(` Would restart: ${svc}`);
705
+ continue;
706
+ }
707
+
708
+ try {
709
+ if (IS_MAC) {
710
+ const plistPath = path.join(DIRS.SERVICES_MAC, `${svc}.plist`);
711
+ if (!fs.existsSync(plistPath)) { warn(` Plist not found: ${svc}`); continue; }
712
+ exec(`launchctl unload "${plistPath}"`, { ignoreError: true });
713
+ exec(`launchctl load "${plistPath}"`);
714
+ } else {
715
+ exec(`systemctl --user restart ${svc}`, { ignoreError: true });
716
+ }
717
+ ok(` Restarted ${svc}`);
718
+ } catch (err) {
719
+ warn(` Failed to restart ${svc}: ${err.message}`);
720
+ }
721
+
722
+ // Brief pause between restarts
723
+ exec('sleep 1', { ignoreError: true });
724
+ }
725
+ }
726
+
727
+ // ═══════════════════════════════════════════════════════════════════════════
728
+ // MAIN
729
+ // ═══════════════════════════════════════════════════════════════════════════
730
+
731
+ async function main() {
732
+ const args = process.argv.slice(2);
733
+ const dryRun = args.includes('--dry-run');
734
+ const localOnly = args.includes('--local');
735
+ const noRestart = args.includes('--no-restart');
736
+ const doRollback = args.includes('--rollback');
737
+ const includeServices = args.includes('--include-services');
738
+ const forceAll = args.includes('--force');
739
+ const showStatus = args.includes('--status');
740
+
741
+ // Parse --component flag (can be repeated)
742
+ const filterIds = [];
743
+ for (let i = 0; i < args.length; i++) {
744
+ if (args[i] === '--component' && args[i + 1]) {
745
+ filterIds.push(args[i + 1]);
746
+ i++;
747
+ }
748
+ }
749
+
750
+ // Parse --node flag
751
+ let deployLocal = true, deployRemote = !localOnly;
752
+ for (let i = 0; i < args.length; i++) {
753
+ if (args[i] === '--node' && args[i + 1]) {
754
+ const target = args[i + 1].toLowerCase();
755
+ if (['ubuntu', 'linux', 'calos'].includes(target)) {
756
+ deployLocal = false;
757
+ deployRemote = true;
758
+ } else if (['mac', 'macos', 'moltymac', 'self'].includes(target)) {
759
+ deployLocal = true;
760
+ deployRemote = false;
761
+ }
762
+ i++;
763
+ }
764
+ }
765
+
766
+ // ── Status mode ──
767
+ if (showStatus) {
768
+ header('Deployment Status');
769
+ const state = loadDeployState();
770
+ const git = gitFetchAndDiff(REPO_DIR);
771
+
772
+ console.log(` Repo: ${REPO_DIR}`);
773
+ console.log(` Branch: ${DEPLOY_BRANCH}`);
774
+ console.log(` Local: ${git.currentSha?.slice(0, 8) || 'unknown'}`);
775
+ console.log(` Remote: ${git.remoteSha?.slice(0, 8) || 'unknown'}`);
776
+ console.log(` Status: ${git.upToDate ? C.green('up to date') : C.yellow(`${git.changedFiles.length} files behind`)}`);
777
+
778
+ if (state.lastDeploy) {
779
+ console.log(` Last deploy: ${state.lastDeploy}`);
780
+ }
781
+
782
+ if (!git.upToDate) {
783
+ console.log(`\n Changed files:`);
784
+ for (const f of git.changedFiles) {
785
+ console.log(` ${f}`);
786
+ }
787
+
788
+ const affected = getAffectedComponents(git.changedFiles, []);
789
+ if (affected.length > 0) {
790
+ console.log(`\n Affected components:`);
791
+ for (const comp of affected) {
792
+ const risk = comp.risk === 'safe' ? C.green(comp.risk)
793
+ : comp.risk === 'careful' ? C.yellow(comp.risk)
794
+ : C.red(comp.risk);
795
+ console.log(` ${comp.name} [${risk}] — ${comp.changedFiles.length} files`);
796
+ }
797
+ }
798
+ }
799
+
800
+ // Check npm packages
801
+ for (const comp of MANIFEST.filter(c => c.detect)) {
802
+ const result = comp.detect();
803
+ if (result.changed) {
804
+ console.log(`\n ${C.yellow('Update available:')} ${comp.name}`);
805
+ if (result.current) console.log(` Current: ${result.current}`);
806
+ if (result.latest) console.log(` Latest: ${result.latest}`);
807
+ if (result.reason) console.log(` Reason: ${result.reason}`);
808
+ }
809
+ }
810
+
811
+ return;
812
+ }
813
+
814
+ // ── Rollback mode ──
815
+ if (doRollback) {
816
+ header('Rolling Back Last Deploy');
817
+ const state = loadDeployState();
818
+ if (!state.lastSha) {
819
+ fail('No previous deploy state found — cannot rollback');
820
+ return;
821
+ }
822
+
823
+ // Validate SHA format before shell interpolation (guards against corrupted state file)
824
+ if (!/^[0-9a-f]{7,40}$/i.test(state.lastSha)) {
825
+ fail(`Invalid SHA in deploy state: ${JSON.stringify(state.lastSha).slice(0, 50)}`);
826
+ return;
827
+ }
828
+ info(`Reverting to ${state.lastSha.slice(0, 8)}`);
829
+ const dirty = exec('git status --porcelain', { cwd: REPO_DIR, ignoreError: true });
830
+ if (dirty) {
831
+ warn('Working tree has uncommitted changes — stashing before rollback');
832
+ exec('git stash push -m "pre-rollback-stash"', { cwd: REPO_DIR });
833
+ }
834
+ exec(`git reset --hard ${state.lastSha}`, { cwd: REPO_DIR });
835
+
836
+ // Full reinstall from the reverted state
837
+ const allFiles = exec('git ls-files', { cwd: REPO_DIR }).split('\n').filter(Boolean);
838
+ const affected = getAffectedComponents(allFiles, ['all']);
839
+ for (const comp of affected) {
840
+ comp.changedFiles = allFiles.filter(f =>
841
+ comp.repoPaths.some(rp => rp.endsWith('/') ? f.startsWith(rp) : f === rp)
842
+ );
843
+ installComponentFiles(comp, REPO_DIR, false);
844
+ if (!noRestart) restartComponentServices(comp, false);
845
+ }
846
+
847
+ ok(`Rolled back to ${state.lastSha.slice(0, 8)}`);
848
+
849
+ if (deployRemote) {
850
+ header('Rolling back remote nodes');
851
+ try {
852
+ const { fleetDeploy } = require('./fleet-deploy');
853
+ const { connect } = require('nats');
854
+ const { natsConnectOpts: natsOpts } = require('../lib/nats-resolve');
855
+ const nc = await connect(natsOpts({ name: 'deploy-rollback', timeout: 10000 }));
856
+ try {
857
+ // Trigger fleet deploy at the rollback SHA — nodes will git fetch + ff to it
858
+ await fleetDeploy(nc, {
859
+ components: null,
860
+ targetNodes: null,
861
+ dryRun: false,
862
+ force: true,
863
+ timeoutMs: 120000,
864
+ });
865
+ } finally {
866
+ await nc.close();
867
+ }
868
+ ok('Remote rollback triggered via fleet deploy');
869
+ } catch (err) {
870
+ if (err.code === 'MODULE_NOT_FOUND') {
871
+ warn('Fleet deploy not available — remote rollback skipped');
872
+ } else {
873
+ fail(`Remote rollback failed: ${err.message}`);
874
+ }
875
+ }
876
+ }
877
+ return;
878
+ }
879
+
880
+ // ═══ Normal deploy flow ═══
881
+
882
+ if (deployLocal) {
883
+ header(`Deploying to ${IS_MAC ? 'macOS (lead)' : 'Ubuntu (worker)'}`);
884
+
885
+ if (!fs.existsSync(REPO_DIR)) {
886
+ fail(`Repo not found at ${REPO_DIR}`);
887
+ console.log(` Clone it: git clone https://github.com/moltyguibros-design/openclaw-node.git ${REPO_DIR}`);
888
+ process.exit(1);
889
+ }
890
+
891
+ // Step 1: Git fetch and diff
892
+ const git = gitFetchAndDiff(REPO_DIR);
893
+ const state = loadDeployState();
894
+
895
+ if (git.upToDate && filterIds.length === 0 && !forceAll) {
896
+ ok('Repo is up to date — nothing to deploy');
897
+ } else {
898
+ // Save pre-deploy SHA for rollback
899
+ state.lastSha = git.currentSha;
900
+
901
+ if (!git.upToDate && !dryRun) {
902
+ const { newSha } = gitMerge(REPO_DIR);
903
+ ok(`Git updated to ${newSha}`);
904
+ }
905
+
906
+ // Step 2: Determine affected components
907
+ const affected = getAffectedComponents(
908
+ git.upToDate ? [] : git.changedFiles,
909
+ filterIds.length > 0 ? filterIds : undefined
910
+ );
911
+
912
+ if (affected.length === 0) {
913
+ ok('No components affected by changes');
914
+ } else {
915
+ info(`${affected.length} component(s) to deploy:\n`);
916
+
917
+ // Step 3: Deploy each component
918
+ for (const comp of affected) {
919
+ const risk = comp.risk === 'safe' ? C.green('●')
920
+ : comp.risk === 'careful' ? C.yellow('●')
921
+ : C.red('●');
922
+
923
+ console.log(` ${risk} ${C.bold(comp.name)} ${C.dim(`(${comp.id})`)}`);
924
+ console.log(` ${C.dim(comp.description)}`);
925
+
926
+ // Skip manual-risk components unless explicitly included
927
+ if (comp.risk === 'manual' && !forceAll) {
928
+ if (comp.id === 'services' && !includeServices) {
929
+ skip(` Skipped (use --include-services)`);
930
+ continue;
931
+ }
932
+ if (comp.id !== 'services') {
933
+ skip(` Skipped (use --force or --component ${comp.id})`);
934
+ continue;
935
+ }
936
+ }
937
+
938
+ // Pre-install hook (backup, merge protection, etc.)
939
+ if (comp.preInstall) {
940
+ const result = comp.preInstall(comp.changedFiles || []);
941
+ if (result === false) continue; // Component vetoed installation
942
+ }
943
+
944
+ // npm-based components have their own install logic
945
+ if (comp.install) {
946
+ comp.install(dryRun);
947
+ } else {
948
+ // File-based components — copy changed files
949
+ const count = installComponentFiles(comp, REPO_DIR, dryRun);
950
+ if (count > 0 && !dryRun) ok(` Installed ${count} file(s)`);
951
+ }
952
+
953
+ // Post-install hook (npm install, config regen, boot compile, etc.)
954
+ if (comp.postInstall && !dryRun) {
955
+ comp.postInstall(comp.changedFiles || []);
956
+ }
957
+
958
+ // Restart affected services
959
+ if (!noRestart && !dryRun) {
960
+ restartComponentServices(comp, dryRun);
961
+ } else if (noRestart && !dryRun) {
962
+ const services = IS_MAC ? comp.servicesMac : comp.servicesLinux;
963
+ if (services && services.length > 0) {
964
+ info(` ${services.length} service(s) need manual restart`);
965
+ }
966
+ }
967
+
968
+ // Validation
969
+ if (comp.validate && !dryRun) {
970
+ const valid = comp.validate();
971
+ if (valid) {
972
+ ok(` Validated`);
973
+ } else {
974
+ warn(` Validation failed — check manually`);
975
+ }
976
+ }
977
+
978
+ // Notes
979
+ if (comp.notes && dryRun) {
980
+ console.log(` ${C.dim('Note: ' + comp.notes)}`);
981
+ }
982
+
983
+ console.log('');
984
+
985
+ // Track component deploy
986
+ if (!dryRun) {
987
+ state.components[comp.id] = {
988
+ deployedAt: new Date().toISOString(),
989
+ sha: git.remoteSha?.slice(0, 8),
990
+ filesChanged: (comp.changedFiles || []).length,
991
+ };
992
+ }
993
+ }
994
+ }
995
+
996
+ // Save deploy state
997
+ if (!dryRun) {
998
+ state.lastDeploy = new Date().toISOString();
999
+ saveDeployState(state);
1000
+ }
1001
+ }
1002
+ }
1003
+
1004
+ // ── Fleet deploy (replaces old SSH remote block) ──
1005
+ if (deployRemote) {
1006
+ try {
1007
+ const { fleetDeploy } = require('./fleet-deploy');
1008
+ const { connect } = require('nats');
1009
+ const { natsConnectOpts: natsOpts2 } = require('../lib/nats-resolve');
1010
+
1011
+ const nc = await connect(natsOpts2({ name: 'deploy-cli', timeout: 10000 }));
1012
+ try {
1013
+ await fleetDeploy(nc, {
1014
+ components: filterIds.length > 0 ? filterIds : null,
1015
+ targetNodes: null, // all remote nodes
1016
+ dryRun,
1017
+ force: forceAll,
1018
+ timeoutMs: 120000,
1019
+ });
1020
+ } finally {
1021
+ await nc.close();
1022
+ }
1023
+ } catch (err) {
1024
+ if (err.code === 'MODULE_NOT_FOUND') {
1025
+ warn('Fleet deploy not available (fleet-deploy.js or nats not found)');
1026
+ info('Install: npm install nats && copy fleet-deploy.js to bin/');
1027
+ } else {
1028
+ fail(`Fleet deploy failed: ${err.message}`);
1029
+ }
1030
+ }
1031
+ }
1032
+
1033
+ // ── Summary ──
1034
+ if (!dryRun && (deployLocal || deployRemote)) {
1035
+ header('Deploy Complete');
1036
+ const sha = exec('git rev-parse --short HEAD', { cwd: REPO_DIR, ignoreError: true });
1037
+ console.log(` Commit: ${sha}`);
1038
+ console.log(` Branch: ${DEPLOY_BRANCH}`);
1039
+ console.log(` Local: ${deployLocal ? C.green('deployed') : C.dim('skipped')}`);
1040
+ console.log(` Remote: ${deployRemote ? C.green('deployed') : C.dim('skipped')}`);
1041
+ console.log('');
1042
+ }
1043
+ }
1044
+
1045
+ main().catch(err => {
1046
+ fail(`Deploy error: ${err.message}`);
1047
+ process.exit(1);
1048
+ });