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,391 @@
1
+ /**
2
+ * Reliable File Lock - 可靠的文件锁实现
3
+ *
4
+ * 设计原则:
5
+ * 1. 使用 O_EXCL | O_CREAT 实现真正的原子锁获取
6
+ * 2. PID 存活检测避免死锁
7
+ * 3. 带退避的重试机制
8
+ * 4. 锁获取后二次验证
9
+ * 5. 数据不丢失:失败时抛出异常而非静默返回
10
+ */
11
+
12
+ import * as fs from 'fs';
13
+ import * as path from 'path';
14
+
15
+ export interface LockOptions {
16
+ /** 最大重试次数,默认 50 */
17
+ maxRetries?: number;
18
+ /** 基础重试延迟(ms),默认 10 */
19
+ baseRetryDelayMs?: number;
20
+ /** 最大重试延迟(ms),默认 500 */
21
+ maxRetryDelayMs?: number;
22
+ /** 锁过期时间(ms),默认 10000 (10秒) */
23
+ lockStaleMs?: number;
24
+ /** 锁文件后缀,默认 '.lock' */
25
+ lockSuffix?: string;
26
+ }
27
+
28
+ export interface LockContext {
29
+ /** 锁文件路径 */
30
+ lockPath: string;
31
+ /** 持有锁的 PID */
32
+ pid: number;
33
+ /** 获取锁的时间 */
34
+ acquiredAt: number;
35
+ }
36
+
37
+ export class LockAcquisitionError extends Error {
38
+ public readonly filePath: string;
39
+ public readonly lockPath: string;
40
+
41
+ constructor(message: string, filePath: string, lockPath: string) {
42
+ super(message);
43
+ this.name = 'LockAcquisitionError';
44
+ this.filePath = filePath;
45
+ this.lockPath = lockPath;
46
+ }
47
+ }
48
+
49
+ /** 默认锁选项 */
50
+ const DEFAULT_OPTIONS: Required<LockOptions> = {
51
+ maxRetries: 50,
52
+ baseRetryDelayMs: 10,
53
+ maxRetryDelayMs: 500,
54
+ lockStaleMs: 10000,
55
+ lockSuffix: '.lock',
56
+ };
57
+
58
+ /**
59
+ * 检查进程是否存活
60
+ */
61
+ function isProcessAlive(pid: number): boolean {
62
+ try {
63
+ // 发送信号 0 不会真正发送信号,只检查进程是否存在
64
+ process.kill(pid, 0);
65
+ return true;
66
+ } catch {
67
+ return false;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * 原子创建锁文件
73
+ * 使用 O_EXCL | O_CREAT 确保原子性
74
+ *
75
+ * @returns true 表示成功获取锁,false 表示锁被占用
76
+ */
77
+ function tryAcquireLock(lockPath: string, pid: number): boolean {
78
+ try {
79
+ // 确保锁文件的目录存在
80
+ const lockDir = path.dirname(lockPath);
81
+ if (!fs.existsSync(lockDir)) {
82
+ fs.mkdirSync(lockDir, { recursive: true });
83
+ }
84
+
85
+ // 使用 fs.constants 获取正确的 flag 值
86
+ // O_EXCL: 排他创建 - 与 O_CREAT 一起使用时,如果文件存在则失败
87
+ // O_CREAT: 文件不存在时创建
88
+ // O_WRONLY: 只写模式
89
+ const flags = fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL;
90
+
91
+ // 使用底层的 openSync 实现真正的原子操作
92
+ // 如果文件已存在,会抛出 EEXIST 错误
93
+ const fd = fs.openSync(lockPath, flags);
94
+
95
+ // 写入 PID
96
+ fs.writeSync(fd, String(pid));
97
+ fs.fsyncSync(fd); // 确保数据落盘
98
+ fs.closeSync(fd);
99
+
100
+ return true;
101
+ } catch (err: unknown) {
102
+ if ((err as NodeJS.ErrnoException).code === 'EEXIST') {
103
+ return false; // 锁已被占用
104
+ }
105
+ // 其他错误(权限、磁盘满等)向上抛出
106
+ throw err;
107
+ }
108
+ }
109
+
110
+ /**
111
+ * 读取锁文件中的 PID
112
+ * @returns PID 或 null(如果文件不存在或无法解析)
113
+ */
114
+ function readLockPid(lockPath: string): number | null {
115
+ try {
116
+ const content = fs.readFileSync(lockPath, 'utf8');
117
+ const pid = parseInt(content.trim(), 10);
118
+ return Number.isNaN(pid) ? null : pid;
119
+ } catch {
120
+ return null;
121
+ }
122
+ }
123
+
124
+ /**
125
+ * 安全删除锁文件
126
+ * 只有当锁文件包含当前进程的 PID 时才删除
127
+ */
128
+ function safeReleaseLock(lockPath: string, expectedPid: number): void {
129
+ try {
130
+ const pid = readLockPid(lockPath);
131
+ if (pid === expectedPid) {
132
+ fs.unlinkSync(lockPath);
133
+ }
134
+ // 如果 PID 不匹配,说明锁已被其他进程重新获取,不删除
135
+ } catch {
136
+ // 忽略删除错误
137
+ }
138
+ }
139
+
140
+ /**
141
+ * 检查并清理过期锁
142
+ */
143
+ function cleanupStaleLock(lockPath: string, staleMs: number): boolean {
144
+ try {
145
+ const stat = fs.statSync(lockPath);
146
+ const pid = readLockPid(lockPath);
147
+
148
+ // 检查是否过期
149
+ const isStale = Date.now() - stat.mtimeMs > staleMs;
150
+
151
+ // 检查持有者是否已死亡
152
+ // PID 为 null 表示锁文件损坏,应视为无效锁
153
+ const isDead = pid === null || !isProcessAlive(pid);
154
+
155
+ // 满足任一条件即可清理:过期、持有者死亡、PID 无效
156
+ if (isStale || isDead) {
157
+ try {
158
+ fs.unlinkSync(lockPath);
159
+ return true;
160
+ } catch {
161
+ return false;
162
+ }
163
+ }
164
+
165
+ return false;
166
+ } catch {
167
+ return false;
168
+ }
169
+ }
170
+
171
+ /**
172
+ * 计算退避延迟(指数退避 + 抖动)
173
+ */
174
+ function calculateBackoff(attempt: number, baseMs: number, maxMs: number): number {
175
+ // 指数退避:10, 20, 40, 80, 160, 320, 500, 500, ...
176
+ const exponentialDelay = Math.min(baseMs * Math.pow(2, attempt), maxMs);
177
+
178
+ // 添加 20% 的随机抖动,避免多个进程同时重试
179
+ const jitter = exponentialDelay * 0.2 * Math.random();
180
+
181
+ return Math.floor(exponentialDelay + jitter);
182
+ }
183
+
184
+ function sleep(ms: number): Promise<void> {
185
+ return new Promise((resolve) => setTimeout(resolve, ms));
186
+ }
187
+
188
+ function sleepSync(ms: number): void {
189
+ const end = Date.now() + ms;
190
+ while (Date.now() < end) {
191
+ // busy wait for synchronous retry
192
+ }
193
+ }
194
+
195
+ function buildLockError(filePath: string, lockPath: string): LockAcquisitionError {
196
+ const holderPid = readLockPid(lockPath);
197
+ const holderStatus = holderPid !== null
198
+ ? (isProcessAlive(holderPid) ? `alive (PID ${holderPid})` : `dead (PID ${holderPid})`)
199
+ : 'unknown';
200
+
201
+ return new LockAcquisitionError(
202
+ `Failed to acquire lock for ${filePath}. Lock holder: ${holderStatus}.`,
203
+ filePath,
204
+ lockPath,
205
+ );
206
+ }
207
+
208
+ function tryAcquireWithStaleCleanup(filePath: string, opts: Required<LockOptions>, pid: number): LockContext | null {
209
+ const lockPath = filePath + opts.lockSuffix;
210
+
211
+ if (tryAcquireLock(lockPath, pid)) {
212
+ const actualPid = readLockPid(lockPath);
213
+ if (actualPid === pid) {
214
+ return { lockPath, pid, acquiredAt: Date.now() };
215
+ }
216
+ }
217
+
218
+ cleanupStaleLock(lockPath, opts.lockStaleMs);
219
+
220
+ if (tryAcquireLock(lockPath, pid)) {
221
+ const actualPid = readLockPid(lockPath);
222
+ if (actualPid === pid) {
223
+ return { lockPath, pid, acquiredAt: Date.now() };
224
+ }
225
+ }
226
+
227
+ return null;
228
+ }
229
+
230
+ /**
231
+ * 获取文件锁
232
+ *
233
+ * @param filePath 要锁定的文件路径
234
+ * @param options 锁选项
235
+ * @returns 锁上下文(用于后续释放)
236
+ * @throws Error 如果无法获取锁
237
+ */
238
+ export function acquireLock(filePath: string, options: LockOptions = {}): LockContext {
239
+ const opts = { ...DEFAULT_OPTIONS, ...options };
240
+ const pid = process.pid;
241
+
242
+ for (let attempt = 0; attempt < opts.maxRetries; attempt++) {
243
+ const ctx = tryAcquireWithStaleCleanup(filePath, opts, pid);
244
+ if (ctx) {
245
+ return ctx;
246
+ }
247
+
248
+ if (attempt < opts.maxRetries - 1) {
249
+ const delay = calculateBackoff(attempt, opts.baseRetryDelayMs, opts.maxRetryDelayMs);
250
+ sleepSync(delay);
251
+ }
252
+ }
253
+
254
+ throw buildLockError(filePath, filePath + opts.lockSuffix);
255
+ }
256
+
257
+ export async function acquireLockAsync(filePath: string, options: LockOptions = {}): Promise<LockContext> {
258
+ const opts = { ...DEFAULT_OPTIONS, ...options };
259
+ const pid = process.pid;
260
+
261
+ for (let attempt = 0; attempt < opts.maxRetries; attempt++) {
262
+ const ctx = tryAcquireWithStaleCleanup(filePath, opts, pid);
263
+ if (ctx) {
264
+ return ctx;
265
+ }
266
+
267
+ if (attempt < opts.maxRetries - 1) {
268
+ const delay = calculateBackoff(attempt, opts.baseRetryDelayMs, opts.maxRetryDelayMs);
269
+ await sleep(delay);
270
+ }
271
+ }
272
+
273
+ throw buildLockError(filePath, filePath + opts.lockSuffix);
274
+ }
275
+
276
+ /**
277
+ * 释放文件锁
278
+ *
279
+ * @param ctx 锁上下文(由 acquireLock 返回)
280
+ */
281
+ export function releaseLock(ctx: LockContext): void {
282
+ safeReleaseLock(ctx.lockPath, ctx.pid);
283
+ }
284
+
285
+ /**
286
+ * 使用锁执行操作(自动获取和释放)
287
+ *
288
+ * @param filePath 要锁定的文件路径
289
+ * @param fn 要执行的操作
290
+ * @param options 锁选项
291
+ * @returns 操作的返回值
292
+ */
293
+ export function withLock<T>(
294
+ filePath: string,
295
+ fn: () => T,
296
+ options: LockOptions = {}
297
+ ): T {
298
+ const ctx = acquireLock(filePath, options);
299
+ try {
300
+ return fn();
301
+ } finally {
302
+ releaseLock(ctx);
303
+ }
304
+ }
305
+
306
+ export async function withLockAsync<T>(
307
+ filePath: string,
308
+ fn: () => Promise<T>,
309
+ options: LockOptions = {}
310
+ ): Promise<T> {
311
+ const ctx = await acquireLockAsync(filePath, options);
312
+ try {
313
+ return await fn();
314
+ } finally {
315
+ releaseLock(ctx);
316
+ }
317
+ }
318
+
319
+ /**
320
+ * 异步版本的文件锁(使用 Promise 链)
321
+ *
322
+ * 注意:这是一个简化的实现,适用于单进程内的异步并发控制
323
+ * 对于多进程场景,应使用同步版本的 acquireLock
324
+ */
325
+ const asyncLockQueues = new Map<string, Promise<void>>();
326
+
327
+ export async function withAsyncLock<T>(
328
+ filePath: string,
329
+ fn: () => Promise<T>
330
+ ): Promise<T> {
331
+ const lockPath = filePath + '.async';
332
+
333
+ // 获取或创建该文件的任务队列
334
+ let queue = asyncLockQueues.get(lockPath);
335
+
336
+ // 创建新的 Promise 链
337
+ let resolveRelease: () => void;
338
+ const releasePromise = new Promise<void>(resolve => {
339
+ resolveRelease = resolve;
340
+ });
341
+
342
+ // 将当前任务加入队列
343
+ const previousQueue = queue || Promise.resolve();
344
+ const currentQueue = previousQueue.then(() => releasePromise);
345
+ asyncLockQueues.set(lockPath, currentQueue);
346
+
347
+ // 等待前面的任务完成
348
+ await previousQueue;
349
+
350
+ try {
351
+ return await fn();
352
+ } finally {
353
+ resolveRelease!();
354
+ // 清理已完成的队列
355
+ if (asyncLockQueues.get(lockPath) === currentQueue) {
356
+ asyncLockQueues.delete(lockPath);
357
+ }
358
+ }
359
+ }
360
+
361
+ /**
362
+ * 检查锁状态(用于调试)
363
+ */
364
+ export function getLockStatus(filePath: string, options: LockOptions = {}): {
365
+ locked: boolean;
366
+ holderPid: number | null;
367
+ holderAlive: boolean;
368
+ lockAge: number | null;
369
+ } {
370
+ const opts = { ...DEFAULT_OPTIONS, ...options };
371
+ const lockPath = filePath + opts.lockSuffix;
372
+
373
+ try {
374
+ const stat = fs.statSync(lockPath);
375
+ const pid = readLockPid(lockPath);
376
+
377
+ return {
378
+ locked: true,
379
+ holderPid: pid,
380
+ holderAlive: pid !== null && isProcessAlive(pid),
381
+ lockAge: Date.now() - stat.mtimeMs,
382
+ };
383
+ } catch {
384
+ return {
385
+ locked: false,
386
+ holderPid: null,
387
+ holderAlive: false,
388
+ lockAge: null,
389
+ };
390
+ }
391
+ }
@@ -2,7 +2,9 @@
2
2
  * Glob pattern matching utilities using micromatch.
3
3
  * Provides lightweight file path pattern matching for whitelist/blacklist operations.
4
4
  */
5
+
5
6
  import micromatch from 'micromatch';
7
+
6
8
  /**
7
9
  * Checks if a file path matches any of the provided glob patterns.
8
10
  *
@@ -10,11 +12,11 @@ import micromatch from 'micromatch';
10
12
  * @param patterns - Array of glob patterns (supports *, **, ?, etc.)
11
13
  * @returns true if the path matches any pattern, false otherwise
12
14
  */
13
- export function matchesAnyPattern(filePath, patterns) {
14
- if (!patterns || patterns.length === 0)
15
- return false;
16
- return micromatch.isMatch(filePath, patterns);
15
+ export function matchesAnyPattern(filePath: string, patterns: string[]): boolean {
16
+ if (!patterns || patterns.length === 0) return false;
17
+ return micromatch.isMatch(filePath, patterns);
17
18
  }
19
+
18
20
  /**
19
21
  * Filters an array of file paths to only those that match any pattern.
20
22
  *
@@ -22,11 +24,11 @@ export function matchesAnyPattern(filePath, patterns) {
22
24
  * @param patterns - Array of glob patterns (supports *, **, ?, !)
23
25
  * @returns Array of matching file paths
24
26
  */
25
- export function filterMatchingPaths(filePaths, patterns) {
26
- if (!patterns || patterns.length === 0)
27
- return [];
28
- return micromatch.match(filePaths, patterns);
27
+ export function filterMatchingPaths(filePaths: string[], patterns: string[]): string[] {
28
+ if (!patterns || patterns.length === 0) return [];
29
+ return micromatch.match(filePaths, patterns);
29
30
  }
31
+
30
32
  /**
31
33
  * Returns all patterns that match the given file path.
32
34
  *
@@ -34,16 +36,15 @@ export function filterMatchingPaths(filePaths, patterns) {
34
36
  * @param patterns - Array of glob patterns
35
37
  * @returns Array of patterns that matched the path
36
38
  */
37
- export function getMatchingPatterns(filePath, patterns) {
38
- if (!patterns || patterns.length === 0)
39
- return [];
40
- return micromatch.match([filePath], patterns).map((match) => {
41
- // Find the pattern that produced this match
42
- for (const pattern of patterns) {
43
- if (micromatch.isMatch(match, pattern)) {
44
- return pattern;
45
- }
46
- }
47
- return '';
48
- }).filter(Boolean);
39
+ export function getMatchingPatterns(filePath: string, patterns: string[]): string[] {
40
+ if (!patterns || patterns.length === 0) return [];
41
+ return micromatch.match([filePath], patterns).map((match: string) => {
42
+ // Find the pattern that produced this match
43
+ for (const pattern of patterns) {
44
+ if (micromatch.isMatch(match, pattern)) {
45
+ return pattern;
46
+ }
47
+ }
48
+ return '';
49
+ }).filter(Boolean);
49
50
  }
@@ -1,11 +1,12 @@
1
1
  import { createHash } from 'crypto';
2
+
2
3
  /**
3
4
  * Strips timestamps, UUIDs, and hex memory addresses from error messages
4
5
  * to allow for consistent loop detection even if the raw text varies slightly.
5
6
  */
6
- export function denoiseError(text) {
7
- if (!text)
8
- return '';
7
+ export function denoiseError(text: string): string {
8
+ if (!text) return '';
9
+
9
10
  return text
10
11
  // Strip ISO timestamps and common date formats
11
12
  .replace(/\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}:\d{2}(\.\d+)?Z?/g, '[TIME]')
@@ -17,9 +18,10 @@ export function denoiseError(text) {
17
18
  .replace(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g, '[UUID]')
18
19
  .trim();
19
20
  }
21
+
20
22
  /**
21
23
  * Computes a simple SHA-256 hash of the given string.
22
24
  */
23
- export function computeHash(text) {
25
+ export function computeHash(text: string): string {
24
26
  return createHash('sha256').update(text).digest('hex');
25
27
  }
@@ -0,0 +1,110 @@
1
+ import * as path from 'path';
2
+ import * as fs from 'fs';
3
+ import { PD_FILES, resolvePdPath } from '../core/paths.js';
4
+
5
+ export function normalizePath(filePath: string, projectDir: string): string {
6
+ if (!filePath) return '';
7
+
8
+ const projectIsWin = projectDir.includes('\\') || (projectDir.length >= 2 && projectDir[1] === ':');
9
+ const fileIsWin = filePath.includes('\\') || (filePath.length >= 2 && filePath[1] === ':');
10
+
11
+ let normalizedFilePath = filePath;
12
+ if (projectIsWin !== fileIsWin) {
13
+ if (fileIsWin) {
14
+ // Basic WSL conversion D:\path -> /mnt/d/path
15
+ normalizedFilePath = `/mnt/${filePath.charAt(0).toLowerCase()}${filePath.slice(2).replace(/\\/g, '/')}`;
16
+ }
17
+ }
18
+
19
+ let rel: string;
20
+ if (projectIsWin) {
21
+ const projectAbs = path.resolve(projectDir);
22
+ const fileAbs = path.isAbsolute(normalizedFilePath) ? normalizedFilePath : path.join(projectAbs, normalizedFilePath);
23
+ rel = path.relative(projectAbs, fileAbs);
24
+ } else {
25
+ const projectPosix = projectDir.replace(/\\/g, '/');
26
+ const filePosix = path.isAbsolute(normalizedFilePath) ? normalizedFilePath : path.posix.join(projectPosix, normalizedFilePath.replace(/\\/g, '/'));
27
+ rel = path.posix.relative(projectPosix, filePosix);
28
+ }
29
+
30
+ rel = rel.replace(/\\/g, '/');
31
+ if (rel.startsWith('../')) {
32
+ return normalizedFilePath;
33
+ }
34
+ return rel;
35
+ }
36
+
37
+ export function normalizeRiskPath(p: string): string {
38
+ let normalized = p.replace(/\\/g, '/');
39
+ if (normalized.endsWith('/')) {
40
+ normalized = normalized.slice(0, -1);
41
+ }
42
+ return normalized;
43
+ }
44
+
45
+ export function isRisky(relPath: string, riskPaths: string[]): boolean {
46
+ if (!relPath || !riskPaths || riskPaths.length === 0) return false;
47
+
48
+ const normalizedRel = normalizeRiskPath(relPath);
49
+ for (const pattern of riskPaths) {
50
+ const normalizedPattern = normalizeRiskPath(pattern);
51
+ if (normalizedRel.startsWith(normalizedPattern)) {
52
+ // If it starts with the pattern, and either they are exactly equal OR the next char is a slash
53
+ // (prevents "src/db_backup" matching "src/db")
54
+ if (normalizedRel === normalizedPattern || normalizedRel.charAt(normalizedPattern.length) === '/') {
55
+ return true;
56
+ }
57
+ }
58
+ }
59
+ return false;
60
+ }
61
+
62
+ export function parseKvLines(text: string): Record<string, string> {
63
+ const result: Record<string, string> = {};
64
+ const lines = text.split('\n');
65
+ for (const line of lines) {
66
+ const idx = line.indexOf(':');
67
+ if (idx !== -1) {
68
+ const key = line.slice(0, idx).trim();
69
+ const value = line.slice(idx + 1).trim();
70
+ result[key] = value;
71
+ }
72
+ }
73
+ return result;
74
+ }
75
+
76
+ export function serializeKvLines(data: Record<string, any>): string {
77
+ const lines: string[] = [];
78
+ const keys = Object.keys(data).sort();
79
+ for (const k of keys) {
80
+ const v = data[k];
81
+ if (Array.isArray(v)) {
82
+ lines.push(`${k}: ${v.join(',')}`);
83
+ } else if (typeof v === 'object' && v !== null) {
84
+ lines.push(`${k}: ${JSON.stringify(v)}`);
85
+ } else {
86
+ lines.push(`${k}: ${v}`);
87
+ }
88
+ }
89
+ return lines.join('\n');
90
+ }
91
+
92
+ export function planStatus(projectDir: string): string {
93
+ const planPath = resolvePdPath(projectDir, 'PLAN');
94
+ try {
95
+ if (!fs.existsSync(planPath)) return '';
96
+ const content = fs.readFileSync(planPath, 'utf8');
97
+ const lines = content.split('\n');
98
+ for (const line of lines) {
99
+ if (line.startsWith('STATUS:')) {
100
+ const parts = line.split(':');
101
+ if (parts.length > 1) {
102
+ return parts[1].trim().split(/\s+/)[0] || '';
103
+ }
104
+ }
105
+ }
106
+ } catch (e) {
107
+ // Ignore read errors
108
+ }
109
+ return '';
110
+ }
@@ -1,42 +1,48 @@
1
1
  /**
2
2
  * Extracts common phrases (N-grams) that appear in a majority of the given samples.
3
3
  */
4
- export function extractCommonPhrases(samples, minOccurrence = 3) {
5
- if (samples.length < minOccurrence)
6
- return [];
7
- const phrases = new Map();
4
+ export function extractCommonPhrases(samples: string[], minOccurrence: number = 3): string[] {
5
+ if (samples.length < minOccurrence) return [];
6
+
7
+ const phrases = new Map<string, number>();
8
8
  const n = 3; // Look for 3-word n-grams as a baseline for "phrases"
9
+
9
10
  for (const sample of samples) {
10
11
  // Keep all words, lowercased, remove basic punctuation
11
12
  const words = sample.toLowerCase().replace(/[.,!?;:()]/g, '').split(/\s+/).filter(w => w.length > 0);
13
+
12
14
  for (let i = 0; i <= words.length - n; i++) {
13
15
  const ngram = words.slice(i, i + n).join(' ');
14
16
  phrases.set(ngram, (phrases.get(ngram) || 0) + 1);
15
17
  }
16
18
  }
19
+
17
20
  // Filter phrases that meet the threshold
18
21
  return Array.from(phrases.entries())
19
22
  .filter(([_, count]) => count >= minOccurrence)
20
23
  .map(([phrase, _]) => phrase);
21
24
  }
25
+
22
26
  /**
23
27
  * Extracts the longest common substring present in a high percentage of samples.
24
28
  * Suitable for Chinese or languages without clear word boundaries.
25
29
  */
26
- export function extractCommonSubstring(samples, minLen = 4) {
27
- if (samples.length < 2)
28
- return [];
30
+ export function extractCommonSubstring(samples: string[], minLen: number = 4): string[] {
31
+ if (samples.length < 2) return [];
32
+
29
33
  const requiredMatches = Math.ceil(samples.length * 0.8); // Must appear in 80% of samples
30
34
  const baseStr = samples[0];
31
- let bestSubstrings = [];
35
+ let bestSubstrings: string[] = [];
32
36
  let maxLength = 0;
37
+
33
38
  // Generate all possible substrings from the first sample
34
39
  for (let i = 0; i < baseStr.length; i++) {
35
40
  for (let j = i + minLen; j <= baseStr.length; j++) {
36
41
  const sub = baseStr.substring(i, j);
42
+
37
43
  // If we already found a longer one, we only care if this one can beat it
38
- if (sub.length < maxLength)
39
- continue;
44
+ if (sub.length < maxLength) continue;
45
+
40
46
  // Check how many other samples contain this substring
41
47
  let matchCount = 1; // It's in the first sample
42
48
  for (let k = 1; k < samples.length; k++) {
@@ -44,16 +50,17 @@ export function extractCommonSubstring(samples, minLen = 4) {
44
50
  matchCount++;
45
51
  }
46
52
  }
53
+
47
54
  if (matchCount >= requiredMatches) {
48
55
  if (sub.length > maxLength) {
49
56
  maxLength = sub.length;
50
57
  bestSubstrings = [sub];
51
- }
52
- else if (sub.length === maxLength && !bestSubstrings.includes(sub)) {
58
+ } else if (sub.length === maxLength && !bestSubstrings.includes(sub)) {
53
59
  bestSubstrings.push(sub);
54
60
  }
55
61
  }
56
62
  }
57
63
  }
64
+
58
65
  return bestSubstrings;
59
66
  }