principles-disciple 1.8.1 → 1.8.3

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 (508) hide show
  1. package/ADVANCED_CONFIG_ZH.md +97 -0
  2. package/AGENT_INSTALL.md +173 -0
  3. package/AGENT_INSTALL_EN.md +173 -0
  4. package/INSTALL.md +256 -0
  5. package/SKILL.md +63 -0
  6. package/docs/COMMAND_REFERENCE.md +76 -0
  7. package/docs/COMMAND_REFERENCE_EN.md +79 -0
  8. package/esbuild.config.js +75 -0
  9. package/openclaw.plugin.json +4 -4
  10. package/package.json +11 -13
  11. package/scripts/build-web.mjs +46 -0
  12. package/scripts/install-dependencies.cjs +47 -0
  13. package/scripts/sync-plugin.mjs +802 -0
  14. package/scripts/verify-build.mjs +109 -0
  15. package/src/agents/nocturnal-dreamer.md +152 -0
  16. package/src/agents/nocturnal-philosopher.md +138 -0
  17. package/src/agents/nocturnal-reflector.md +126 -0
  18. package/src/agents/nocturnal-scribe.md +164 -0
  19. package/src/commands/capabilities.ts +85 -0
  20. package/{dist/commands/context.js → src/commands/context.ts} +78 -38
  21. package/src/commands/evolution-status.ts +146 -0
  22. package/src/commands/export.ts +111 -0
  23. package/src/commands/focus.ts +533 -0
  24. package/src/commands/nocturnal-review.ts +311 -0
  25. package/src/commands/nocturnal-rollout.ts +763 -0
  26. package/src/commands/nocturnal-train.ts +1002 -0
  27. package/{dist/commands/pain.js → src/commands/pain.ts} +68 -49
  28. package/src/commands/principle-rollback.ts +27 -0
  29. package/{dist/commands/rollback.js → src/commands/rollback.ts} +44 -12
  30. package/src/commands/samples.ts +60 -0
  31. package/src/commands/strategy.ts +38 -0
  32. package/{dist/commands/thinking-os.js → src/commands/thinking-os.ts} +59 -36
  33. package/src/commands/workflow-debug.ts +128 -0
  34. package/{dist/config/defaults/runtime.js → src/config/defaults/runtime.ts} +12 -5
  35. package/src/config/errors.ts +163 -0
  36. package/{dist/config/index.d.ts → src/config/index.ts} +2 -1
  37. package/src/constants/diagnostician.ts +66 -0
  38. package/src/constants/tools.ts +62 -0
  39. package/src/core/adaptive-thresholds.ts +476 -0
  40. package/{dist/core/config-service.js → src/core/config-service.ts} +7 -4
  41. package/{dist/core/config.js → src/core/config.ts} +158 -46
  42. package/src/core/control-ui-db.ts +435 -0
  43. package/{dist/core/detection-funnel.js → src/core/detection-funnel.ts} +36 -21
  44. package/{dist/core/detection-service.js → src/core/detection-service.ts} +7 -4
  45. package/{dist/core/dictionary-service.js → src/core/dictionary-service.ts} +7 -4
  46. package/{dist/core/dictionary.js → src/core/dictionary.ts} +57 -34
  47. package/src/core/empathy-keyword-matcher.ts +327 -0
  48. package/src/core/empathy-types.ts +218 -0
  49. package/src/core/event-log.ts +544 -0
  50. package/src/core/evolution-engine.ts +612 -0
  51. package/src/core/evolution-logger.ts +353 -0
  52. package/src/core/evolution-migration.ts +77 -0
  53. package/src/core/evolution-reducer.ts +731 -0
  54. package/src/core/evolution-types.ts +456 -0
  55. package/src/core/external-training-contract.ts +527 -0
  56. package/src/core/focus-history.ts +1458 -0
  57. package/src/core/hygiene/tracker.ts +117 -0
  58. package/{dist/core/init.js → src/core/init.ts} +39 -26
  59. package/src/core/local-worker-routing.ts +617 -0
  60. package/{dist/core/migration.js → src/core/migration.ts} +18 -11
  61. package/src/core/model-deployment-registry.ts +722 -0
  62. package/src/core/model-training-registry.ts +813 -0
  63. package/src/core/nocturnal-arbiter.ts +706 -0
  64. package/src/core/nocturnal-candidate-scoring.ts +392 -0
  65. package/src/core/nocturnal-compliance.ts +1075 -0
  66. package/src/core/nocturnal-dataset.ts +668 -0
  67. package/src/core/nocturnal-executability.ts +428 -0
  68. package/src/core/nocturnal-export.ts +390 -0
  69. package/{dist/core/nocturnal-paths.js → src/core/nocturnal-paths.ts} +49 -23
  70. package/src/core/nocturnal-trajectory-extractor.ts +484 -0
  71. package/src/core/nocturnal-trinity.ts +1384 -0
  72. package/src/core/pain.ts +122 -0
  73. package/{dist/core/path-resolver.js → src/core/path-resolver.ts} +157 -36
  74. package/{dist/core/paths.js → src/core/paths.ts} +13 -4
  75. package/src/core/principle-training-state.ts +450 -0
  76. package/src/core/profile.ts +226 -0
  77. package/src/core/promotion-gate.ts +822 -0
  78. package/{dist/core/risk-calculator.js → src/core/risk-calculator.ts} +42 -16
  79. package/{dist/core/session-tracker.js → src/core/session-tracker.ts} +175 -62
  80. package/src/core/shadow-observation-registry.ts +534 -0
  81. package/{dist/core/system-logger.js → src/core/system-logger.ts} +9 -5
  82. package/src/core/thinking-models.ts +217 -0
  83. package/src/core/training-program.ts +630 -0
  84. package/src/core/trajectory-types.ts +243 -0
  85. package/src/core/trajectory.ts +1673 -0
  86. package/{dist/core/workspace-context.js → src/core/workspace-context.ts} +57 -32
  87. package/src/hooks/bash-risk.ts +171 -0
  88. package/src/hooks/edit-verification.ts +295 -0
  89. package/src/hooks/gate-block-helper.ts +160 -0
  90. package/src/hooks/gate.ts +210 -0
  91. package/src/hooks/gfi-gate.ts +177 -0
  92. package/src/hooks/lifecycle.ts +326 -0
  93. package/{dist/hooks/llm.js → src/hooks/llm.ts} +160 -80
  94. package/src/hooks/message-sanitize.ts +45 -0
  95. package/src/hooks/pain.ts +384 -0
  96. package/src/hooks/progressive-trust-gate.ts +174 -0
  97. package/src/hooks/prompt.ts +920 -0
  98. package/src/hooks/subagent.ts +207 -0
  99. package/src/hooks/thinking-checkpoint.ts +73 -0
  100. package/src/hooks/trajectory-collector.ts +290 -0
  101. package/src/http/principles-console-route.ts +716 -0
  102. package/src/i18n/commands.ts +117 -0
  103. package/src/index.ts +694 -0
  104. package/src/service/central-database.ts +831 -0
  105. package/src/service/control-ui-query-service.ts +888 -0
  106. package/src/service/evolution-query-service.ts +405 -0
  107. package/src/service/evolution-worker.ts +1646 -0
  108. package/src/service/health-query-service.ts +836 -0
  109. package/{dist/service/nocturnal-runtime.js → src/service/nocturnal-runtime.ts} +235 -79
  110. package/src/service/nocturnal-service.ts +1015 -0
  111. package/src/service/nocturnal-target-selector.ts +532 -0
  112. package/src/service/phase3-input-filter.ts +237 -0
  113. package/src/service/runtime-summary-service.ts +757 -0
  114. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +513 -0
  115. package/{dist/service/subagent-workflow/empathy-observer-workflow-manager.js → src/service/subagent-workflow/empathy-observer-workflow-manager.ts} +240 -117
  116. package/src/service/subagent-workflow/index.ts +51 -0
  117. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +856 -0
  118. package/src/service/subagent-workflow/runtime-direct-driver.ts +166 -0
  119. package/{dist/service/subagent-workflow/types.d.ts → src/service/subagent-workflow/types.ts} +137 -18
  120. package/src/service/subagent-workflow/workflow-store.ts +328 -0
  121. package/src/service/trajectory-service.ts +15 -0
  122. package/{dist/tools/critique-prompt.js → src/tools/critique-prompt.ts} +25 -8
  123. package/src/tools/deep-reflect.ts +349 -0
  124. package/{dist/tools/model-index.js → src/tools/model-index.ts} +33 -17
  125. package/src/types/event-types.ts +453 -0
  126. package/src/types/hygiene-types.ts +31 -0
  127. package/src/types/principle-tree-schema.ts +244 -0
  128. package/src/types/runtime-summary.ts +49 -0
  129. package/src/types.ts +74 -0
  130. package/src/utils/file-lock.ts +391 -0
  131. package/{dist/utils/glob-match.js → src/utils/glob-match.ts} +21 -20
  132. package/{dist/utils/hashing.js → src/utils/hashing.ts} +6 -4
  133. package/src/utils/io.ts +110 -0
  134. package/{dist/utils/nlp.js → src/utils/nlp.ts} +19 -12
  135. package/{dist/utils/plugin-logger.js → src/utils/plugin-logger.ts} +33 -8
  136. package/src/utils/subagent-probe.ts +94 -0
  137. package/templates/langs/en/skills/ai-sprint-orchestration/EXAMPLES.md +63 -0
  138. package/templates/langs/en/skills/ai-sprint-orchestration/REFERENCE.md +136 -0
  139. package/templates/langs/en/skills/ai-sprint-orchestration/SKILL.md +67 -0
  140. package/templates/langs/en/skills/ai-sprint-orchestration/references/agent-registry.json +214 -0
  141. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +107 -0
  142. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +107 -0
  143. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +105 -0
  144. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +108 -0
  145. package/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +58 -0
  146. package/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +190 -0
  147. package/templates/langs/en/skills/ai-sprint-orchestration/runtime/.gitignore +2 -0
  148. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +310 -0
  149. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +683 -0
  150. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +604 -0
  151. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +32 -0
  152. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +707 -0
  153. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/run.mjs +3419 -0
  154. package/templates/langs/zh/skills/ai-sprint-orchestration/EXAMPLES.md +63 -0
  155. package/templates/langs/zh/skills/ai-sprint-orchestration/REFERENCE.md +136 -0
  156. package/templates/langs/zh/skills/ai-sprint-orchestration/SKILL.md +67 -0
  157. package/templates/langs/zh/skills/ai-sprint-orchestration/references/agent-registry.json +214 -0
  158. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +107 -0
  159. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +107 -0
  160. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +105 -0
  161. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +108 -0
  162. package/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +58 -0
  163. package/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +190 -0
  164. package/templates/langs/zh/skills/ai-sprint-orchestration/runtime/.gitignore +2 -0
  165. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +310 -0
  166. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +683 -0
  167. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +604 -0
  168. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +32 -0
  169. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +707 -0
  170. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +3419 -0
  171. package/templates/langs/zh/skills/ai-sprint-orchestration/test/archive.test.mjs +230 -0
  172. package/templates/langs/zh/skills/ai-sprint-orchestration/test/contract-enforcement.test.mjs +672 -0
  173. package/templates/langs/zh/skills/ai-sprint-orchestration/test/decision.test.mjs +1321 -0
  174. package/templates/langs/zh/skills/ai-sprint-orchestration/test/run.test.mjs +1419 -0
  175. package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +70 -1
  176. package/templates/pain_settings.json +2 -1
  177. package/tests/README.md +120 -0
  178. package/tests/build-artifacts.test.ts +111 -0
  179. package/tests/commands/evolution-status.test.ts +222 -0
  180. package/tests/commands/evolver.test.ts +22 -0
  181. package/tests/commands/export.test.ts +78 -0
  182. package/tests/commands/nocturnal-review.test.ts +448 -0
  183. package/tests/commands/nocturnal-train.test.ts +97 -0
  184. package/tests/commands/pain.test.ts +108 -0
  185. package/tests/commands/samples.test.ts +65 -0
  186. package/tests/commands/strategy.test.ts +34 -0
  187. package/tests/commands/thinking-os.test.ts +88 -0
  188. package/tests/core/adaptive-thresholds.test.ts +261 -0
  189. package/tests/core/config-service.test.ts +89 -0
  190. package/tests/core/config.test.ts +90 -0
  191. package/tests/core/control-ui-db.test.ts +75 -0
  192. package/tests/core/core-template-guidance.test.ts +21 -0
  193. package/tests/core/detection-funnel.test.ts +63 -0
  194. package/tests/core/detection-service.test.ts +50 -0
  195. package/tests/core/dictionary-service.test.ts +116 -0
  196. package/tests/core/dictionary.test.ts +168 -0
  197. package/tests/core/empathy-keyword-matcher.test.ts +209 -0
  198. package/tests/core/event-log.test.ts +181 -0
  199. package/tests/core/evolution-e2e.test.ts +58 -0
  200. package/tests/core/evolution-engine-gate-integration.test.ts +543 -0
  201. package/tests/core/evolution-engine.test.ts +562 -0
  202. package/tests/core/evolution-logger.test.ts +148 -0
  203. package/tests/core/evolution-migration.test.ts +50 -0
  204. package/tests/core/evolution-paths.test.ts +21 -0
  205. package/tests/core/evolution-reducer.detector-metadata.test.ts +602 -0
  206. package/tests/core/evolution-reducer.test.ts +180 -0
  207. package/tests/core/evolution-types-loop.test.ts +48 -0
  208. package/tests/core/evolution-user-stories.e2e.test.ts +249 -0
  209. package/tests/core/external-training-contract.test.ts +463 -0
  210. package/tests/core/focus-history.test.ts +682 -0
  211. package/tests/core/init-flatten.test.ts +69 -0
  212. package/tests/core/init-refactor.test.ts +87 -0
  213. package/tests/core/init-v1.3.test.ts +46 -0
  214. package/tests/core/init.test.ts +190 -0
  215. package/tests/core/local-worker-routing.test.ts +757 -0
  216. package/tests/core/migration.test.ts +84 -0
  217. package/tests/core/model-deployment-registry.test.ts +845 -0
  218. package/tests/core/model-training-registry.test.ts +889 -0
  219. package/tests/core/nocturnal-arbiter.test.ts +494 -0
  220. package/tests/core/nocturnal-candidate-scoring.test.ts +400 -0
  221. package/tests/core/nocturnal-compliance.test.ts +646 -0
  222. package/tests/core/nocturnal-dataset.test.ts +892 -0
  223. package/tests/core/nocturnal-executability.test.ts +357 -0
  224. package/tests/core/nocturnal-export.test.ts +462 -0
  225. package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +428 -0
  226. package/tests/core/nocturnal-trajectory-extractor.test.ts +634 -0
  227. package/tests/core/nocturnal-trinity.test.ts +953 -0
  228. package/tests/core/pain.test.ts +33 -0
  229. package/tests/core/path-resolver.test.ts +57 -0
  230. package/tests/core/paths-refactor.test.ts +42 -0
  231. package/tests/core/phase7-rollout-integration.test.ts +477 -0
  232. package/tests/core/principle-training-state.test.ts +712 -0
  233. package/tests/core/profile.test.ts +56 -0
  234. package/tests/core/promotion-gate.test.ts +556 -0
  235. package/tests/core/risk-calculator.test.ts +168 -0
  236. package/tests/core/session-tracker.test.ts +191 -0
  237. package/tests/core/training-program.test.ts +472 -0
  238. package/tests/core/trajectory.test.ts +265 -0
  239. package/tests/core/workspace-context-factory.test.ts +18 -0
  240. package/tests/core/workspace-context.test.ts +134 -0
  241. package/tests/fixtures/nocturnal-reviewed-subset.json +183 -0
  242. package/tests/fixtures/production-compatibility.test.ts +147 -0
  243. package/tests/fixtures/production-mock-generator.ts +282 -0
  244. package/tests/hooks/bash-risk-integration.test.ts +137 -0
  245. package/tests/hooks/bash-risk.test.ts +81 -0
  246. package/tests/hooks/edit-verification.test.ts +678 -0
  247. package/tests/hooks/gate-edit-verification-p1.test.ts +632 -0
  248. package/tests/hooks/gate-edit-verification.test.ts +435 -0
  249. package/tests/hooks/gate-pipeline-integration.test.ts +404 -0
  250. package/tests/hooks/gate.test.ts +271 -0
  251. package/tests/hooks/gfi-gate-unit.test.ts +422 -0
  252. package/tests/hooks/gfi-gate.test.ts +669 -0
  253. package/tests/hooks/lifecycle.test.ts +248 -0
  254. package/tests/hooks/llm.test.ts +308 -0
  255. package/tests/hooks/message-sanitize.test.ts +36 -0
  256. package/tests/hooks/pain.test.ts +141 -0
  257. package/tests/hooks/progressive-trust-gate.test.ts +277 -0
  258. package/tests/hooks/prompt.test.ts +1411 -0
  259. package/tests/hooks/subagent.test.ts +467 -0
  260. package/tests/hooks/thinking-gate.test.ts +313 -0
  261. package/tests/http/principles-console-route.test.ts +140 -0
  262. package/tests/hygiene-tracker.test.ts +77 -0
  263. package/tests/index.integration.test.ts +179 -0
  264. package/tests/index.shadow-routing.integration.test.ts +140 -0
  265. package/tests/index.test.ts +9 -0
  266. package/tests/integration/empathy-workflow-integration.test.ts +627 -0
  267. package/tests/service/control-ui-query-service.test.ts +121 -0
  268. package/tests/service/empathy-observer-workflow-manager.test.ts +176 -0
  269. package/tests/service/evolution-worker.test.ts +585 -0
  270. package/tests/service/nocturnal-runtime.test.ts +470 -0
  271. package/tests/service/nocturnal-service.test.ts +577 -0
  272. package/tests/service/nocturnal-target-selector.test.ts +615 -0
  273. package/tests/service/nocturnal-workflow-manager.test.ts +439 -0
  274. package/tests/service/phase3-input-filter.test.ts +289 -0
  275. package/tests/service/runtime-summary-service.test.ts +919 -0
  276. package/tests/task-compliance.test.ts +166 -0
  277. package/tests/test-utils.ts +48 -0
  278. package/tests/tools/critique-prompt.test.ts +260 -0
  279. package/tests/tools/deep-reflect.test.ts +232 -0
  280. package/tests/tools/model-index.test.ts +246 -0
  281. package/tests/ui/app.test.tsx +114 -0
  282. package/tests/utils/file-lock.test.ts +407 -0
  283. package/tests/utils/hashing.test.ts +32 -0
  284. package/tests/utils/io.test.ts +39 -0
  285. package/tests/utils/nlp.test.ts +53 -0
  286. package/tests/utils/plugin-logger.test.ts +156 -0
  287. package/tsconfig.json +16 -0
  288. package/tsconfig.tsbuildinfo +1 -0
  289. package/ui/src/App.tsx +45 -0
  290. package/ui/src/api.ts +216 -0
  291. package/ui/src/charts.tsx +586 -0
  292. package/ui/src/components/ErrorState.tsx +6 -0
  293. package/ui/src/components/Loading.tsx +13 -0
  294. package/ui/src/components/ProtectedRoute.tsx +12 -0
  295. package/ui/src/components/Shell.tsx +91 -0
  296. package/ui/src/components/WorkspaceConfig.tsx +146 -0
  297. package/ui/src/components/index.ts +5 -0
  298. package/ui/src/context/auth.tsx +80 -0
  299. package/ui/src/context/theme.tsx +66 -0
  300. package/ui/src/hooks/useAutoRefresh.ts +39 -0
  301. package/ui/src/i18n/ui.ts +363 -0
  302. package/ui/src/main.tsx +16 -0
  303. package/ui/src/pages/EvolutionPage.tsx +352 -0
  304. package/ui/src/pages/FeedbackPage.tsx +140 -0
  305. package/ui/src/pages/GateMonitorPage.tsx +136 -0
  306. package/ui/src/pages/LoginPage.tsx +88 -0
  307. package/ui/src/pages/OverviewPage.tsx +238 -0
  308. package/ui/src/pages/SamplesPage.tsx +174 -0
  309. package/ui/src/pages/ThinkingModelsPage.tsx +127 -0
  310. package/ui/src/styles.css +1661 -0
  311. package/ui/src/types.ts +368 -0
  312. package/ui/src/utils/format.ts +15 -0
  313. package/vitest.config.ts +23 -0
  314. package/dist/commands/capabilities.d.ts +0 -3
  315. package/dist/commands/capabilities.js +0 -73
  316. package/dist/commands/context.d.ts +0 -5
  317. package/dist/commands/evolution-status.d.ts +0 -4
  318. package/dist/commands/evolution-status.js +0 -117
  319. package/dist/commands/evolver.d.ts +0 -9
  320. package/dist/commands/evolver.js +0 -26
  321. package/dist/commands/export.d.ts +0 -2
  322. package/dist/commands/export.js +0 -98
  323. package/dist/commands/focus.d.ts +0 -14
  324. package/dist/commands/focus.js +0 -457
  325. package/dist/commands/nocturnal-review.d.ts +0 -24
  326. package/dist/commands/nocturnal-review.js +0 -265
  327. package/dist/commands/nocturnal-rollout.d.ts +0 -27
  328. package/dist/commands/nocturnal-rollout.js +0 -671
  329. package/dist/commands/nocturnal-train.d.ts +0 -25
  330. package/dist/commands/nocturnal-train.js +0 -919
  331. package/dist/commands/pain.d.ts +0 -5
  332. package/dist/commands/principle-rollback.d.ts +0 -4
  333. package/dist/commands/principle-rollback.js +0 -22
  334. package/dist/commands/rollback.d.ts +0 -19
  335. package/dist/commands/samples.d.ts +0 -2
  336. package/dist/commands/samples.js +0 -55
  337. package/dist/commands/strategy.d.ts +0 -3
  338. package/dist/commands/strategy.js +0 -29
  339. package/dist/commands/thinking-os.d.ts +0 -2
  340. package/dist/config/defaults/runtime.d.ts +0 -40
  341. package/dist/config/errors.d.ts +0 -84
  342. package/dist/config/errors.js +0 -94
  343. package/dist/config/index.js +0 -7
  344. package/dist/constants/diagnostician.d.ts +0 -12
  345. package/dist/constants/diagnostician.js +0 -56
  346. package/dist/constants/tools.d.ts +0 -17
  347. package/dist/constants/tools.js +0 -54
  348. package/dist/core/adaptive-thresholds.d.ts +0 -186
  349. package/dist/core/adaptive-thresholds.js +0 -300
  350. package/dist/core/config-service.d.ts +0 -15
  351. package/dist/core/config.d.ts +0 -129
  352. package/dist/core/control-ui-db.d.ts +0 -95
  353. package/dist/core/control-ui-db.js +0 -292
  354. package/dist/core/detection-funnel.d.ts +0 -33
  355. package/dist/core/detection-service.d.ts +0 -15
  356. package/dist/core/dictionary-service.d.ts +0 -15
  357. package/dist/core/dictionary.d.ts +0 -38
  358. package/dist/core/event-log.d.ts +0 -82
  359. package/dist/core/event-log.js +0 -463
  360. package/dist/core/evolution-engine.d.ts +0 -118
  361. package/dist/core/evolution-engine.js +0 -464
  362. package/dist/core/evolution-logger.d.ts +0 -137
  363. package/dist/core/evolution-logger.js +0 -256
  364. package/dist/core/evolution-migration.d.ts +0 -5
  365. package/dist/core/evolution-migration.js +0 -65
  366. package/dist/core/evolution-reducer.d.ts +0 -98
  367. package/dist/core/evolution-reducer.js +0 -465
  368. package/dist/core/evolution-types.d.ts +0 -287
  369. package/dist/core/evolution-types.js +0 -78
  370. package/dist/core/external-training-contract.d.ts +0 -276
  371. package/dist/core/external-training-contract.js +0 -269
  372. package/dist/core/focus-history.d.ts +0 -210
  373. package/dist/core/focus-history.js +0 -1185
  374. package/dist/core/hygiene/tracker.d.ts +0 -22
  375. package/dist/core/hygiene/tracker.js +0 -106
  376. package/dist/core/init.d.ts +0 -12
  377. package/dist/core/local-worker-routing.d.ts +0 -175
  378. package/dist/core/local-worker-routing.js +0 -525
  379. package/dist/core/migration.d.ts +0 -6
  380. package/dist/core/model-deployment-registry.d.ts +0 -218
  381. package/dist/core/model-deployment-registry.js +0 -503
  382. package/dist/core/model-training-registry.d.ts +0 -295
  383. package/dist/core/model-training-registry.js +0 -475
  384. package/dist/core/nocturnal-arbiter.d.ts +0 -159
  385. package/dist/core/nocturnal-arbiter.js +0 -534
  386. package/dist/core/nocturnal-candidate-scoring.d.ts +0 -137
  387. package/dist/core/nocturnal-candidate-scoring.js +0 -266
  388. package/dist/core/nocturnal-compliance.d.ts +0 -175
  389. package/dist/core/nocturnal-compliance.js +0 -824
  390. package/dist/core/nocturnal-dataset.d.ts +0 -224
  391. package/dist/core/nocturnal-dataset.js +0 -443
  392. package/dist/core/nocturnal-executability.d.ts +0 -85
  393. package/dist/core/nocturnal-executability.js +0 -331
  394. package/dist/core/nocturnal-export.d.ts +0 -124
  395. package/dist/core/nocturnal-export.js +0 -275
  396. package/dist/core/nocturnal-paths.d.ts +0 -124
  397. package/dist/core/nocturnal-trajectory-extractor.d.ts +0 -242
  398. package/dist/core/nocturnal-trajectory-extractor.js +0 -307
  399. package/dist/core/nocturnal-trinity.d.ts +0 -311
  400. package/dist/core/nocturnal-trinity.js +0 -880
  401. package/dist/core/pain.d.ts +0 -4
  402. package/dist/core/pain.js +0 -70
  403. package/dist/core/path-resolver.d.ts +0 -46
  404. package/dist/core/paths.d.ts +0 -65
  405. package/dist/core/principle-training-state.d.ts +0 -121
  406. package/dist/core/principle-training-state.js +0 -321
  407. package/dist/core/profile.d.ts +0 -62
  408. package/dist/core/profile.js +0 -210
  409. package/dist/core/promotion-gate.d.ts +0 -238
  410. package/dist/core/promotion-gate.js +0 -529
  411. package/dist/core/risk-calculator.d.ts +0 -22
  412. package/dist/core/session-tracker.d.ts +0 -101
  413. package/dist/core/shadow-observation-registry.d.ts +0 -217
  414. package/dist/core/shadow-observation-registry.js +0 -308
  415. package/dist/core/system-logger.d.ts +0 -8
  416. package/dist/core/thinking-models.d.ts +0 -38
  417. package/dist/core/thinking-models.js +0 -170
  418. package/dist/core/training-program.d.ts +0 -233
  419. package/dist/core/training-program.js +0 -433
  420. package/dist/core/trajectory.d.ts +0 -411
  421. package/dist/core/trajectory.js +0 -1307
  422. package/dist/core/workspace-context.d.ts +0 -71
  423. package/dist/hooks/bash-risk.d.ts +0 -57
  424. package/dist/hooks/bash-risk.js +0 -137
  425. package/dist/hooks/edit-verification.d.ts +0 -62
  426. package/dist/hooks/edit-verification.js +0 -256
  427. package/dist/hooks/gate-block-helper.d.ts +0 -44
  428. package/dist/hooks/gate-block-helper.js +0 -119
  429. package/dist/hooks/gate.d.ts +0 -24
  430. package/dist/hooks/gate.js +0 -173
  431. package/dist/hooks/gfi-gate.d.ts +0 -40
  432. package/dist/hooks/gfi-gate.js +0 -113
  433. package/dist/hooks/lifecycle.d.ts +0 -5
  434. package/dist/hooks/lifecycle.js +0 -284
  435. package/dist/hooks/llm.d.ts +0 -13
  436. package/dist/hooks/message-sanitize.d.ts +0 -3
  437. package/dist/hooks/message-sanitize.js +0 -37
  438. package/dist/hooks/pain.d.ts +0 -5
  439. package/dist/hooks/pain.js +0 -301
  440. package/dist/hooks/progressive-trust-gate.d.ts +0 -52
  441. package/dist/hooks/progressive-trust-gate.js +0 -134
  442. package/dist/hooks/prompt.d.ts +0 -49
  443. package/dist/hooks/prompt.js +0 -905
  444. package/dist/hooks/subagent.d.ts +0 -10
  445. package/dist/hooks/subagent.js +0 -387
  446. package/dist/hooks/thinking-checkpoint.d.ts +0 -37
  447. package/dist/hooks/thinking-checkpoint.js +0 -51
  448. package/dist/hooks/trajectory-collector.d.ts +0 -32
  449. package/dist/hooks/trajectory-collector.js +0 -256
  450. package/dist/http/principles-console-route.d.ts +0 -9
  451. package/dist/http/principles-console-route.js +0 -681
  452. package/dist/i18n/commands.d.ts +0 -26
  453. package/dist/i18n/commands.js +0 -116
  454. package/dist/index.d.ts +0 -7
  455. package/dist/index.js +0 -581
  456. package/dist/service/central-database.d.ts +0 -104
  457. package/dist/service/central-database.js +0 -649
  458. package/dist/service/control-ui-query-service.d.ts +0 -221
  459. package/dist/service/control-ui-query-service.js +0 -543
  460. package/dist/service/empathy-observer-manager.d.ts +0 -88
  461. package/dist/service/empathy-observer-manager.js +0 -414
  462. package/dist/service/evolution-query-service.d.ts +0 -155
  463. package/dist/service/evolution-query-service.js +0 -258
  464. package/dist/service/evolution-worker.d.ts +0 -101
  465. package/dist/service/evolution-worker.js +0 -975
  466. package/dist/service/health-query-service.d.ts +0 -170
  467. package/dist/service/health-query-service.js +0 -662
  468. package/dist/service/nocturnal-runtime.d.ts +0 -183
  469. package/dist/service/nocturnal-service.d.ts +0 -163
  470. package/dist/service/nocturnal-service.js +0 -787
  471. package/dist/service/nocturnal-target-selector.d.ts +0 -145
  472. package/dist/service/nocturnal-target-selector.js +0 -315
  473. package/dist/service/phase3-input-filter.d.ts +0 -73
  474. package/dist/service/phase3-input-filter.js +0 -172
  475. package/dist/service/runtime-summary-service.d.ts +0 -122
  476. package/dist/service/runtime-summary-service.js +0 -485
  477. package/dist/service/subagent-workflow/empathy-observer-workflow-manager.d.ts +0 -48
  478. package/dist/service/subagent-workflow/index.d.ts +0 -4
  479. package/dist/service/subagent-workflow/index.js +0 -3
  480. package/dist/service/subagent-workflow/runtime-direct-driver.d.ts +0 -77
  481. package/dist/service/subagent-workflow/runtime-direct-driver.js +0 -75
  482. package/dist/service/subagent-workflow/types.js +0 -11
  483. package/dist/service/subagent-workflow/workflow-store.d.ts +0 -26
  484. package/dist/service/subagent-workflow/workflow-store.js +0 -165
  485. package/dist/service/trajectory-service.d.ts +0 -2
  486. package/dist/service/trajectory-service.js +0 -15
  487. package/dist/tools/critique-prompt.d.ts +0 -14
  488. package/dist/tools/deep-reflect.d.ts +0 -39
  489. package/dist/tools/deep-reflect.js +0 -350
  490. package/dist/tools/model-index.d.ts +0 -9
  491. package/dist/types/event-types.d.ts +0 -306
  492. package/dist/types/event-types.js +0 -106
  493. package/dist/types/hygiene-types.d.ts +0 -20
  494. package/dist/types/hygiene-types.js +0 -12
  495. package/dist/types/runtime-summary.d.ts +0 -47
  496. package/dist/types/runtime-summary.js +0 -1
  497. package/dist/types.d.ts +0 -50
  498. package/dist/types.js +0 -22
  499. package/dist/utils/file-lock.d.ts +0 -71
  500. package/dist/utils/file-lock.js +0 -309
  501. package/dist/utils/glob-match.d.ts +0 -28
  502. package/dist/utils/hashing.d.ts +0 -9
  503. package/dist/utils/io.d.ts +0 -6
  504. package/dist/utils/io.js +0 -106
  505. package/dist/utils/nlp.d.ts +0 -9
  506. package/dist/utils/plugin-logger.d.ts +0 -39
  507. package/dist/utils/subagent-probe.d.ts +0 -34
  508. package/dist/utils/subagent-probe.js +0 -81
@@ -0,0 +1,802 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Principles Disciple Plugin Installer
5
+ *
6
+ * A complete installation script that can run after cloning the repo.
7
+ * Handles dependencies, build, and sync to OpenClaw installation directory.
8
+ *
9
+ * Usage:
10
+ * node scripts/sync-plugin.mjs [options]
11
+ *
12
+ * Options:
13
+ * --lang <zh|en> Language for skills (default: zh)
14
+ * --skip-build Skip build step (use existing dist/)
15
+ * --skip-deps Skip dependency installation
16
+ * --force Force overwrite without prompts
17
+ * --help Show help message
18
+ */
19
+
20
+ import { copyFileSync, cpSync, existsSync, rmSync, readFileSync, readFileSync as readFileSyncRaw, mkdirSync, writeFileSync, readdirSync } from 'fs';
21
+ import { createHash } from 'crypto';
22
+ import { join, dirname } from 'path';
23
+ import { fileURLToPath } from 'url';
24
+ import { execSync } from 'child_process';
25
+
26
+ const __filename = fileURLToPath(import.meta.url);
27
+ const __dirname = dirname(__filename);
28
+
29
+ const SOURCE_DIR = join(__dirname, '..');
30
+ const OPENCLAW_DIR = join(process.env.HOME, '.openclaw');
31
+ const INSTALL_DIR = join(OPENCLAW_DIR, 'extensions', 'principles-disciple');
32
+
33
+ // Files and directories to sync
34
+ const SYNC_ITEMS = [
35
+ 'dist',
36
+ 'templates',
37
+ 'scripts',
38
+ 'docs',
39
+ 'openclaw.plugin.json',
40
+ 'package.json',
41
+ ];
42
+
43
+ // Minimum Node.js version
44
+ const MIN_NODE_VERSION = '18.0.0';
45
+
46
+ /**
47
+ * Parse command line arguments
48
+ */
49
+ function parseArgs() {
50
+ const args = {
51
+ lang: process.env.OPENCLAW_LANGUAGE || 'zh',
52
+ skipBuild: false,
53
+ skipDeps: false,
54
+ force: false,
55
+ restart: false,
56
+ dev: false,
57
+ help: false,
58
+ };
59
+
60
+ const argv = process.argv.slice(2);
61
+ for (let i = 0; i < argv.length; i++) {
62
+ const arg = argv[i];
63
+ switch (arg) {
64
+ case '--lang':
65
+ args.lang = argv[++i];
66
+ break;
67
+ case '--skip-build':
68
+ args.skipBuild = true;
69
+ break;
70
+ case '--skip-deps':
71
+ args.skipDeps = true;
72
+ break;
73
+ case '--restart':
74
+ args.restart = true;
75
+ break;
76
+ case '--dev':
77
+ case '-d':
78
+ args.dev = true;
79
+ args.force = true;
80
+ args.restart = true;
81
+ break;
82
+ case '--force':
83
+ case '-f':
84
+ args.force = true;
85
+ break;
86
+ case '--help':
87
+ case '-h':
88
+ args.help = true;
89
+ break;
90
+ default:
91
+ if (arg.startsWith('--')) {
92
+ console.error(`Unknown option: ${arg}`);
93
+ args.help = true;
94
+ }
95
+ }
96
+ }
97
+ return args;
98
+ }
99
+
100
+ /**
101
+ * Show help message
102
+ */
103
+ function showHelp() {
104
+ console.log(`
105
+ Principles Disciple Plugin Installer
106
+
107
+ Usage:
108
+ node scripts/sync-plugin.mjs [options]
109
+
110
+ Options:
111
+ --lang <zh|en> Language for skills (default: zh)
112
+ --skip-build Skip build step (use existing dist/)
113
+ --skip-deps Skip dependency installation
114
+ --restart Automatically restart OpenClaw gateway after installation
115
+ --dev, -d Developer mode: --force + --restart + clean stale backups (default for local dev)
116
+ --force, -f Force overwrite without prompts
117
+ --help, -h Show this help message
118
+
119
+ Examples:
120
+ # Full installation with Chinese skills
121
+ node scripts/sync-plugin.mjs
122
+
123
+ # Install with English skills
124
+ node scripts/sync-plugin.mjs --lang en
125
+
126
+ # Developer mode: build, deploy, restart, clean up (recommended for debugging)
127
+ node scripts/sync-plugin.mjs --dev
128
+
129
+ # Quick sync after local build
130
+ node scripts/sync-plugin.mjs --skip-deps --skip-build
131
+
132
+ Environment Variables:
133
+ OPENCLAW_LANGUAGE Default language for skills (zh or en)
134
+ `);
135
+ }
136
+
137
+ /**
138
+ * Compare semver versions
139
+ */
140
+ function compareVersions(a, b) {
141
+ const partsA = a.split('.').map(Number);
142
+ const partsB = b.split('.').map(Number);
143
+ for (let i = 0; i < 3; i++) {
144
+ if (partsA[i] > partsB[i]) return 1;
145
+ if (partsA[i] < partsB[i]) return -1;
146
+ }
147
+ return 0;
148
+ }
149
+
150
+ /**
151
+ * Main function
152
+ */
153
+ function checkPrerequisites() {
154
+ // Check Node.js version
155
+ const nodeVersion = process.version.replace(/^v/, '');
156
+ if (compareVersions(nodeVersion, MIN_NODE_VERSION) < 0) {
157
+ console.error(`❌ Node.js ${MIN_NODE_VERSION}+ required, got ${nodeVersion}`);
158
+ process.exit(1);
159
+ }
160
+ console.log(`✅ Node.js ${nodeVersion} (>= ${MIN_NODE_VERSION})`);
161
+
162
+ // Check npm
163
+ try {
164
+ const npmVersion = execSync('npm --version', { encoding: 'utf-8' }).trim();
165
+ console.log(`✅ npm ${npmVersion}`);
166
+
167
+ // Check for global package conflicts that cause module resolution traps
168
+ console.log('🔍 Checking for global package conflicts...');
169
+ try {
170
+ const globalConflict = execSync('npm list -g principles-disciple --depth=0 2>/dev/null', { encoding: 'utf-8' });
171
+ if (globalConflict.includes('principles-disciple')) {
172
+ console.error('\n❌ CONFLICT DETECTED: A version of "principles-disciple" is installed globally via npm.');
173
+ console.error('This will block OpenClaw from loading the extension version you are trying to install.');
174
+ console.error('\nACTION REQUIRED: Please run the following command first:');
175
+ console.error(' npm uninstall -g principles-disciple\n');
176
+ process.exit(1);
177
+ }
178
+ } catch (e) {
179
+ // npm list returns non-zero if not found, which is what we want
180
+ console.log('✅ No global package conflicts detected.');
181
+ }
182
+ } catch {
183
+ console.error('❌ npm not found. Please install Node.js with npm.');
184
+ process.exit(1);
185
+ }
186
+
187
+ // Check if we're in the plugin directory
188
+ if (!existsSync(join(SOURCE_DIR, 'package.json'))) {
189
+ console.error('❌ Not in plugin directory. package.json not found.');
190
+ console.error(' Run this script from packages/openclaw-plugin/');
191
+ process.exit(1);
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Extract version from package.json
197
+ */
198
+ function getVersion(dir) {
199
+ const pkgPath = join(dir, 'package.json');
200
+ if (!existsSync(pkgPath)) return null;
201
+ try {
202
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
203
+ return pkg.version;
204
+ } catch {
205
+ return null;
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Install project dependencies
211
+ */
212
+ function installDependencies() {
213
+ console.log('\n📦 Installing project dependencies...');
214
+
215
+ const nodeModulesDir = join(SOURCE_DIR, 'node_modules');
216
+ const needsInstall = !existsSync(nodeModulesDir) ||
217
+ !existsSync(join(nodeModulesDir, 'better-sqlite3'));
218
+
219
+ if (!needsInstall) {
220
+ console.log('✅ Dependencies already installed');
221
+ return;
222
+ }
223
+
224
+ try {
225
+ execSync('npm install', {
226
+ cwd: SOURCE_DIR,
227
+ stdio: 'inherit'
228
+ });
229
+ console.log('✅ Dependencies installed');
230
+ } catch (error) {
231
+ console.error('❌ Failed to install dependencies');
232
+ process.exit(1);
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Build the plugin.
238
+ * Always runs build:production to ensure dist/bundle.js (the actual shipped artifact)
239
+ * is always fresh. We no longer compare timestamps because:
240
+ * 1. tsc alone updates index.js without updating bundle.js
241
+ * 2. Comparing index.js vs src files falsely claims "up to date"
242
+ * 3. The cost of a extra ~10s build is far cheaper than shipping stale bundles
243
+ *
244
+ * Use --skip-build only in CI where you know dist/ is already fresh.
245
+ */
246
+ function buildPlugin() {
247
+ console.log('\n🔨 Building plugin (esbuild only — bypassing tsc which may fail on unrelated files)...');
248
+
249
+ try {
250
+ // Run esbuild directly — it compiles TS on the fly and doesn't care about
251
+ // tsc errors in unrelated files (e.g. subagent-workflow type errors).
252
+ execSync('node esbuild.config.js --production', {
253
+ cwd: SOURCE_DIR,
254
+ stdio: 'inherit'
255
+ });
256
+ // Copy templates and manifest
257
+ execSync('node scripts/build-web.mjs --production', {
258
+ cwd: SOURCE_DIR,
259
+ stdio: 'inherit'
260
+ });
261
+ } catch (error) {
262
+ console.error('\n❌ Build failed');
263
+ console.error(` ${error.message}`);
264
+ process.exit(1);
265
+ }
266
+
267
+ // Post-build verification: ensure critical symbols made it into bundle.js
268
+ verifyBundleContents();
269
+ }
270
+
271
+ /**
272
+ * Verify the built bundle contains all critical symbols.
273
+ * This catches build failures where tsc succeeds but esbuild/bundling silently drops code.
274
+ */
275
+ function verifyBundleContents() {
276
+ const bundleJs = join(SOURCE_DIR, 'dist', 'bundle.js');
277
+ if (!existsSync(bundleJs)) {
278
+ console.error('❌ dist/bundle.js missing after build.');
279
+ process.exit(1);
280
+ }
281
+
282
+ const content = readFileSync(bundleJs, 'utf-8');
283
+
284
+ // Structural markers that survive minification (module exports, log prefixes).
285
+ // These are more stable than class/function names which get mangled.
286
+ // Add/remove markers as the codebase evolves — keep this list minimal.
287
+ const requiredSymbols = [
288
+ { name: 'EvolutionWorkerService', reason: 'main plugin service export' },
289
+ { name: 'checkPainFlag', reason: 'pain flag detection' },
290
+ { name: 'processEvolutionQueue', reason: 'queue processing' },
291
+ ];
292
+
293
+ const missing = [];
294
+ for (const sym of requiredSymbols) {
295
+ if (!content.includes(sym.name)) {
296
+ missing.push(` - ${sym.name}: ${sym.reason}`);
297
+ }
298
+ }
299
+
300
+ if (missing.length > 0) {
301
+ console.warn('\n⚠️ Bundle verification warning — symbols not found (may be minified):');
302
+ missing.forEach(m => console.warn(m));
303
+ console.warn(' This is a warning, not an error. Minification may have renamed these.');
304
+ console.warn(' If the plugin actually fails to load, check for build issues.');
305
+ }
306
+
307
+ console.log('✅ Bundle verification passed — all critical symbols present');
308
+
309
+ // Write build fingerprint to dist/openclaw.plugin.json
310
+ writeBuildFingerprint();
311
+ }
312
+
313
+ /**
314
+ * Write a build fingerprint (git SHA + bundle MD5) into dist/openclaw.plugin.json.
315
+ * This allows post-install verification to detect stale installations.
316
+ */
317
+ function writeBuildFingerprint() {
318
+ const bundleJs = join(SOURCE_DIR, 'dist', 'bundle.js');
319
+ const manifestSrc = join(SOURCE_DIR, 'openclaw.plugin.json');
320
+ const manifestDist = join(SOURCE_DIR, 'dist', 'openclaw.plugin.json');
321
+
322
+ // Get git SHA of current commit
323
+ let gitSha = 'unknown';
324
+ try {
325
+ gitSha = execSync('git rev-parse HEAD', {
326
+ cwd: SOURCE_DIR,
327
+ encoding: 'utf-8',
328
+ timeout: 10000,
329
+ }).trim().slice(0, 12);
330
+ } catch {
331
+ console.warn('⚠️ Could not get git SHA, fingerprint will be incomplete');
332
+ }
333
+
334
+ // Compute MD5 of bundle.js
335
+ let bundleMd5 = 'unknown';
336
+ try {
337
+ const bundleContent = readFileSyncRaw(bundleJs);
338
+ bundleMd5 = createHash('md5').update(bundleContent).digest('hex');
339
+ } catch {
340
+ console.warn('⚠️ Could not compute bundle MD5, fingerprint will be incomplete');
341
+ }
342
+
343
+ // Read manifest
344
+ let manifest;
345
+ try {
346
+ manifest = JSON.parse(readFileSync(manifestDist, 'utf-8'));
347
+ } catch {
348
+ try {
349
+ manifest = JSON.parse(readFileSync(manifestSrc, 'utf-8'));
350
+ } catch {
351
+ console.warn('⚠️ Could not read openclaw.plugin.json, skipping fingerprint');
352
+ return;
353
+ }
354
+ }
355
+
356
+ // Attach fingerprint
357
+ manifest.buildFingerprint = {
358
+ gitSha,
359
+ bundleMd5,
360
+ builtAt: new Date().toISOString(),
361
+ };
362
+
363
+ // Write back to dist/openclaw.plugin.json (this is what gets synced)
364
+ try {
365
+ mkdirSync(join(SOURCE_DIR, 'dist'), { recursive: true });
366
+ writeFileAtomic(manifestDist, JSON.stringify(manifest, null, 2) + '\n');
367
+ console.log(`✅ Build fingerprint: git=${gitSha} bundleMd5=${bundleMd5}`);
368
+ } catch (err) {
369
+ console.warn(`⚠️ Could not write fingerprint to dist/openclaw.plugin.json: ${err.message}`);
370
+ }
371
+
372
+ // Also update the root openclaw.plugin.json so that both synced files have the fingerprint.
373
+ // This ensures fingerprint verification works whether OpenClaw loads from dist/ or root manifest.
374
+ try {
375
+ const rootManifest = JSON.parse(readFileSync(manifestSrc, 'utf-8'));
376
+ rootManifest.buildFingerprint = manifest.buildFingerprint;
377
+ writeFileAtomic(manifestSrc, JSON.stringify(rootManifest, null, 2) + '\n');
378
+ } catch {
379
+ // Non-fatal — root manifest may be identical in content
380
+ }
381
+ }
382
+
383
+ /**
384
+ * Atomic file write (write to temp then rename, to avoid partial writes).
385
+ */
386
+ function writeFileAtomic(filePath, content) {
387
+ const tmp = filePath + '.tmp.' + Date.now();
388
+ writeFileSync(tmp, content, 'utf-8');
389
+ rmSync(filePath, { force: true });
390
+ copyFileSync(tmp, filePath);
391
+ rmSync(tmp, { force: true });
392
+ }
393
+
394
+ /**
395
+ * Verify the installed plugin matches the source fingerprint.
396
+ * If fingerprint in installed manifest differs from source manifest → abort.
397
+ * This catches the case where a previous sync synced a stale bundle.
398
+ */
399
+ function verifyInstalledFingerprint() {
400
+ // Read from dist/ manifests because:
401
+ // - dist/openclaw.plugin.json has the buildFingerprint written by writeBuildFingerprint()
402
+ // - Root openclaw.plugin.json is copied from SOURCE_DIR (no fingerprint, not updated by writeBuildFingerprint)
403
+ const sourceManifest = join(SOURCE_DIR, 'dist', 'openclaw.plugin.json');
404
+ const installedManifest = join(INSTALL_DIR, 'dist', 'openclaw.plugin.json');
405
+
406
+ if (!existsSync(installedManifest)) {
407
+ console.error('\n❌ Installed manifest not found — sync may have failed.');
408
+ process.exit(1);
409
+ }
410
+
411
+ let sourceFp, installedFp;
412
+ try {
413
+ const sm = JSON.parse(readFileSync(sourceManifest, 'utf-8'));
414
+ const im = JSON.parse(readFileSync(installedManifest, 'utf-8'));
415
+ sourceFp = sm.buildFingerprint;
416
+ installedFp = im.buildFingerprint;
417
+ } catch {
418
+ // If we can't read/parse, skip verification
419
+ console.warn('⚠️ Could not read fingerprints, skipping fingerprint verification');
420
+ return;
421
+ }
422
+
423
+ if (!sourceFp || !installedFp) {
424
+ console.warn('⚠️ Missing fingerprint in one or both manifests, skipping verification.');
425
+ return;
426
+ }
427
+
428
+ const gitMismatch = sourceFp.gitSha !== installedFp.gitSha;
429
+ const md5Mismatch = sourceFp.bundleMd5 !== installedFp.bundleMd5;
430
+
431
+ if (gitMismatch || md5Mismatch) {
432
+ console.error('\n❌ INSTALLED PLUGIN IS STALE — FINGERPRINT MISMATCH');
433
+ console.error(' This means the installed plugin bundle does not match the current source build.');
434
+ if (gitMismatch) {
435
+ console.error(` Source git SHA: ${sourceFp.gitSha} (current)`);
436
+ console.error(` Installed git SHA: ${installedFp.gitSha} (old)`);
437
+ }
438
+ if (md5Mismatch) {
439
+ console.error(` Source bundle MD5: ${sourceFp.bundleMd5} (current)`);
440
+ console.error(` Installed bundle: ${installedFp.bundleMd5} (old)`);
441
+ }
442
+ console.error('\n → Run WITHOUT --skip-build to rebuild and reinstall:');
443
+ console.error(` cd ${SOURCE_DIR} && node scripts/sync-plugin.mjs`);
444
+ process.exit(1);
445
+ }
446
+
447
+ console.log('✅ Installed fingerprint verified — matches current source build');
448
+ }
449
+
450
+ /**
451
+ * Verify build exists and bundle contains critical symbols.
452
+ * Called when --skip-build is used (e.g., in CI with fresh dist/).
453
+ * Still verifies critical symbols to catch any pre-existing build issues.
454
+ */
455
+ function verifyBuild() {
456
+ const distDir = join(SOURCE_DIR, 'dist');
457
+ const indexJs = join(distDir, 'index.js');
458
+ const bundleJs = join(distDir, 'bundle.js');
459
+
460
+ if (!existsSync(distDir)) {
461
+ console.error('❌ dist/ directory not found.');
462
+ console.error(' Run without --skip-build to build automatically.');
463
+ process.exit(1);
464
+ }
465
+
466
+ if (!existsSync(indexJs) && !existsSync(bundleJs)) {
467
+ console.error('❌ dist/index.js or dist/bundle.js not found.');
468
+ console.error(' Run without --skip-build to build automatically.');
469
+ process.exit(1);
470
+ }
471
+
472
+ // Verify critical symbols even when skipping build
473
+ // (catches stale dist from previous failed builds)
474
+ try {
475
+ verifyBundleContents();
476
+ } catch {
477
+ // verifyBundleContents already exits on failure
478
+ }
479
+
480
+ console.log('✅ Build verified');
481
+ }
482
+
483
+ /**
484
+ * Remove existing installation directory (clean slate)
485
+ * This ensures no stale files remain from old versions.
486
+ */
487
+ function cleanTargetDir(force) {
488
+ if (!existsSync(INSTALL_DIR)) {
489
+ return;
490
+ }
491
+
492
+ if (!force) {
493
+ const installedVersion = getVersion(INSTALL_DIR);
494
+ if (installedVersion && installedVersion !== getVersion(SOURCE_DIR)) {
495
+ console.error(`\n❌ VERSION CONFLICT:`);
496
+ console.error(` Installed: v${installedVersion}`);
497
+ console.error(` Source: v${getVersion(SOURCE_DIR)}`);
498
+ console.error(` Run with --force to overwrite, or uninstall first.`);
499
+ process.exit(1);
500
+ }
501
+ }
502
+
503
+ console.log('\n🗑️ Removing existing installation...');
504
+ rmSync(INSTALL_DIR, { recursive: true, force: true });
505
+ console.log(` Removed: ${INSTALL_DIR}`);
506
+ }
507
+
508
+ /**
509
+ * Ensure installation directory exists
510
+ */
511
+ function ensureInstallDir() {
512
+ if (existsSync(INSTALL_DIR)) {
513
+ return;
514
+ }
515
+
516
+ console.log('\n📁 Creating installation directory...');
517
+
518
+ // Check if OpenClaw is installed
519
+ if (!existsSync(OPENCLAW_DIR)) {
520
+ console.error(`❌ OpenClaw installation not found: ${OPENCLAW_DIR}`);
521
+ console.error(' Please install OpenClaw first.');
522
+ process.exit(1);
523
+ }
524
+
525
+ // Create extensions directory if needed
526
+ const extensionsDir = join(OPENCLAW_DIR, 'extensions');
527
+ if (!existsSync(extensionsDir)) {
528
+ mkdirSync(extensionsDir, { recursive: true });
529
+ }
530
+
531
+ // Create plugin directory
532
+ mkdirSync(INSTALL_DIR, { recursive: true });
533
+ console.log(`✅ Created: ${INSTALL_DIR}`);
534
+ }
535
+
536
+ /**
537
+ * Sync skills from templates to installation directory
538
+ */
539
+ function syncSkills(lang) {
540
+ const skillsSource = join(SOURCE_DIR, 'templates', 'langs', lang, 'skills');
541
+ const skillsTarget = join(INSTALL_DIR, 'skills');
542
+
543
+ if (!existsSync(skillsSource)) {
544
+ console.log(` ⚠️ Skills not found for language: ${lang}`);
545
+ return false;
546
+ }
547
+
548
+ // Remove existing skills
549
+ if (existsSync(skillsTarget)) {
550
+ rmSync(skillsTarget, { recursive: true, force: true });
551
+ }
552
+
553
+ // Copy skills
554
+ cpSync(skillsSource, skillsTarget, { recursive: true });
555
+ console.log(` 📄 skills (from templates/langs/${lang}/skills)`);
556
+ return true;
557
+ }
558
+
559
+ /**
560
+ * Sync a single item
561
+ */
562
+ function syncItem(item) {
563
+ const source = join(SOURCE_DIR, item);
564
+ const target = join(INSTALL_DIR, item);
565
+
566
+ if (!existsSync(source)) {
567
+ console.log(` ⚠️ Skipping ${item} (not found)`);
568
+ return;
569
+ }
570
+
571
+ console.log(` 📄 ${item}`);
572
+
573
+ // Remove existing item in install directory
574
+ if (existsSync(target)) {
575
+ rmSync(target, { recursive: true, force: true });
576
+ }
577
+
578
+ // Copy item
579
+ try {
580
+ cpSync(source, target, { recursive: true });
581
+ } catch {
582
+ copyFileSync(source, target);
583
+ }
584
+ }
585
+
586
+ /**
587
+ * Install production dependencies in target directory
588
+ */
589
+ function installTargetDependencies() {
590
+ console.log('\n📦 Installing production dependencies in target...');
591
+
592
+ try {
593
+ execSync('npm install --production --no-audit --no-fund', {
594
+ cwd: INSTALL_DIR,
595
+ stdio: 'inherit'
596
+ });
597
+ console.log('✅ Dependencies installed');
598
+ } catch (error) {
599
+ console.error('\n❌ FAILED to install production dependencies in target directory.');
600
+ console.error(` ${error.message}`);
601
+ console.error('\n Without these dependencies, the plugin will fail to load at runtime.');
602
+ console.error(` Run manually: cd ${INSTALL_DIR} && npm install --production`);
603
+ process.exit(1);
604
+ }
605
+ }
606
+
607
+ /**
608
+ * Clean stale backup directories in extensions/
609
+ * These are left behind from old sync runs and can confuse OpenClaw's
610
+ * extension loader (it scans all directories by name).
611
+ */
612
+ function cleanStaleBackups() {
613
+ const extensionsDir = join(OPENCLAW_DIR, 'extensions');
614
+ if (!existsSync(extensionsDir)) return;
615
+
616
+ const entries = readdirSync(extensionsDir);
617
+ const backups = entries.filter(e =>
618
+ e.startsWith('principles-disciple.backup') ||
619
+ e.startsWith('principles-disciple.old')
620
+ );
621
+
622
+ if (backups.length === 0) return;
623
+
624
+ console.log('\n🧹 Cleaning stale backup directories...');
625
+ for (const backup of backups) {
626
+ const path = join(extensionsDir, backup);
627
+ rmSync(path, { recursive: true, force: true });
628
+ console.log(` Removed: ${backup}`);
629
+ }
630
+ }
631
+
632
+ /**
633
+ * Restart OpenClaw Gateway via systemctl, with verification.
634
+ */
635
+ function restartGateway() {
636
+ console.log('\n🔄 Restarting OpenClaw Gateway...');
637
+ try {
638
+ // Try systemd first (most common deployment)
639
+ try {
640
+ execSync('systemctl --user is-active openclaw-gateway.service', { stdio: 'pipe' });
641
+ console.log(' Detected systemd service. Restarting via systemctl...');
642
+ execSync('systemctl --user restart openclaw-gateway.service', { stdio: 'inherit' });
643
+ console.log('✅ Gateway restarted via systemctl.');
644
+ // Verify it started successfully
645
+ setTimeout(() => {
646
+ try {
647
+ const status = execSync('systemctl --user is-active openclaw-gateway.service', { encoding: 'utf-8' }).trim();
648
+ if (status === 'active') {
649
+ console.log('✅ Gateway is running.');
650
+ } else {
651
+ console.error(`❌ Gateway status: ${status}. Check logs: journalctl --user -u openclaw-gateway.service --since "1 min ago"`);
652
+ }
653
+ } catch { /* ignore */ }
654
+ }, 3000);
655
+ return;
656
+ } catch {
657
+ // Not a systemd service — fall through to manual restart
658
+ }
659
+
660
+ // Manual restart: find and kill existing gateway processes
661
+ const pids = execSync('pgrep -f "openclaw-gateway|openclaw gateway"', { encoding: 'utf-8' }).trim();
662
+ if (pids) {
663
+ console.log(` Found gateway process(es). Terminating...`);
664
+ execSync(`echo "${pids}" | xargs kill -TERM 2>/dev/null || true`);
665
+ execSync('sleep 3');
666
+ }
667
+
668
+ // Start new gateway
669
+ const logPath = '/tmp/openclaw-auto-restart.log';
670
+ console.log(` Starting new gateway (logs: ${logPath})...`);
671
+ execSync(`nohup openclaw gateway --force > ${logPath} 2>&1 &`, { stdio: 'ignore' });
672
+ console.log('✅ Gateway restart triggered.');
673
+ console.log(` Check logs: tail -f ${logPath}`);
674
+ } catch (error) {
675
+ console.error(`\n❌ Failed to restart gateway: ${error.message}`);
676
+ console.error(' Manual restart: systemctl --user restart openclaw-gateway.service');
677
+ process.exit(1);
678
+ }
679
+ }
680
+
681
+ /**
682
+ * Main function
683
+ */
684
+ function main() {
685
+ const args = parseArgs();
686
+
687
+ if (args.help) {
688
+ showHelp();
689
+ process.exit(0);
690
+ }
691
+
692
+ console.log('╔════════════════════════════════════════════════════════════╗');
693
+ console.log('║ Principles Disciple Plugin Installer ║');
694
+ console.log('╚════════════════════════════════════════════════════════════╝\n');
695
+
696
+ // Dev mode: auto-force, auto-restart, clean stale backups
697
+ if (args.dev) {
698
+ console.log('🛠️ DEV MODE: force + restart + stale backup cleanup\n');
699
+ }
700
+
701
+ // Get source version
702
+ const sourceVersion = getVersion(SOURCE_DIR);
703
+ if (!sourceVersion) {
704
+ console.error('❌ Cannot determine source version. Check package.json.');
705
+ process.exit(1);
706
+ }
707
+ console.log(`📋 Plugin version: v${sourceVersion}`);
708
+ console.log(`🌍 Language: ${args.lang}`);
709
+
710
+ // Step 1: Check prerequisites
711
+ console.log('\n🔍 Checking prerequisites...');
712
+ checkPrerequisites();
713
+
714
+ // Step 2: Install dependencies (if needed)
715
+ if (!args.skipDeps) {
716
+ installDependencies();
717
+ }
718
+
719
+ // Step 3: ALWAYS rebuild — esbuild is fast (~2s) and compiles TS directly.
720
+ // dist/ .js files from tsc may be stale when tsc has errors in other files.
721
+ // We always rebuild to guarantee the synced code matches current source.
722
+ buildPlugin();
723
+
724
+ // Step 4: Clean existing installation (must happen after build so we know what's current)
725
+ cleanTargetDir(args.force);
726
+
727
+ // Step 5: Ensure installation directory exists
728
+ ensureInstallDir();
729
+
730
+ // Step 6: Sync files
731
+ console.log('\n📦 Syncing files to OpenClaw...');
732
+ for (const item of SYNC_ITEMS) {
733
+ syncItem(item);
734
+ }
735
+
736
+ // Step 7: Sync skills
737
+ syncSkills(args.lang);
738
+
739
+ // Step 8: Install production dependencies in target (ALWAYS — cleanTargetDir wiped node_modules)
740
+ // --skip-deps only applies to SOURCE directory deps, not the installed plugin.
741
+ installTargetDependencies();
742
+
743
+ // Step 9: Verify installed bundle can load its native dependencies
744
+ console.log('\n🔍 Verifying installed plugin can load native dependencies...');
745
+ try {
746
+ execSync(`node -e "require('better-sqlite3')"`, {
747
+ cwd: INSTALL_DIR,
748
+ stdio: 'pipe'
749
+ });
750
+ console.log('✅ Native dependencies verified (better-sqlite3 loads correctly)');
751
+ } catch {
752
+ console.error('\n❌ Installed plugin cannot load native dependencies!');
753
+ console.error(' This usually means npm install failed to compile better-sqlite3.');
754
+ console.error(` Fix: cd ${INSTALL_DIR} && npm rebuild better-sqlite3`);
755
+ process.exit(1);
756
+ }
757
+
758
+ // Step 10: Verify installation
759
+ const installedVersion = getVersion(INSTALL_DIR);
760
+ if (installedVersion !== sourceVersion) {
761
+ console.error('\n❌ VERSION MISMATCH after sync!');
762
+ console.error(` Expected: v${sourceVersion}`);
763
+ console.error(` Got: v${installedVersion}`);
764
+ process.exit(1);
765
+ }
766
+
767
+ // Step 10: Verify installed fingerprint matches current source
768
+ verifyInstalledFingerprint();
769
+
770
+ // Step 11: Clean stale backup directories (dev mode or explicit restart)
771
+ if (args.dev || args.restart) {
772
+ cleanStaleBackups();
773
+ }
774
+
775
+ // Build fingerprint info for report
776
+ let fpReport = '';
777
+ try {
778
+ const sourceManifest = JSON.parse(readFileSync(join(SOURCE_DIR, 'dist', 'openclaw.plugin.json'), 'utf-8'));
779
+ const fp = sourceManifest.buildFingerprint;
780
+ if (fp) {
781
+ fpReport = `\n Build: ${fp.gitSha} / MD5 ${fp.bundleMd5.slice(0, 8)}…`;
782
+ }
783
+ } catch { /* ignore */ }
784
+
785
+ // Success!
786
+ console.log('\n╔════════════════════════════════════════════════════════════╗');
787
+ console.log('║ ✅ Installation Complete ║');
788
+ console.log('╚════════════════════════════════════════════════════════════╝');
789
+ console.log(`\n Version: v${sourceVersion}${fpReport}`);
790
+ console.log(` Language: ${args.lang}`);
791
+ console.log(` Source: ${SOURCE_DIR}`);
792
+ console.log(` Target: ${INSTALL_DIR}`);
793
+
794
+ // Handle automatic restart if requested
795
+ if (args.restart) {
796
+ restartGateway();
797
+ } else {
798
+ console.log('\n💡 Restart OpenClaw Gateway to load the new version.');
799
+ }
800
+ }
801
+
802
+ main();