principles-disciple 1.8.1 → 1.8.2

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 (470) 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/zh/skills/pd-diagnostician/SKILL.md +70 -1
  138. package/templates/pain_settings.json +2 -1
  139. package/tests/README.md +120 -0
  140. package/tests/build-artifacts.test.ts +111 -0
  141. package/tests/commands/evolution-status.test.ts +222 -0
  142. package/tests/commands/evolver.test.ts +22 -0
  143. package/tests/commands/export.test.ts +78 -0
  144. package/tests/commands/nocturnal-review.test.ts +448 -0
  145. package/tests/commands/nocturnal-train.test.ts +97 -0
  146. package/tests/commands/pain.test.ts +108 -0
  147. package/tests/commands/samples.test.ts +65 -0
  148. package/tests/commands/strategy.test.ts +34 -0
  149. package/tests/commands/thinking-os.test.ts +88 -0
  150. package/tests/core/adaptive-thresholds.test.ts +261 -0
  151. package/tests/core/config-service.test.ts +89 -0
  152. package/tests/core/config.test.ts +90 -0
  153. package/tests/core/control-ui-db.test.ts +75 -0
  154. package/tests/core/core-template-guidance.test.ts +21 -0
  155. package/tests/core/detection-funnel.test.ts +63 -0
  156. package/tests/core/detection-service.test.ts +50 -0
  157. package/tests/core/dictionary-service.test.ts +116 -0
  158. package/tests/core/dictionary.test.ts +168 -0
  159. package/tests/core/empathy-keyword-matcher.test.ts +209 -0
  160. package/tests/core/event-log.test.ts +181 -0
  161. package/tests/core/evolution-e2e.test.ts +58 -0
  162. package/tests/core/evolution-engine-gate-integration.test.ts +543 -0
  163. package/tests/core/evolution-engine.test.ts +562 -0
  164. package/tests/core/evolution-logger.test.ts +148 -0
  165. package/tests/core/evolution-migration.test.ts +50 -0
  166. package/tests/core/evolution-paths.test.ts +21 -0
  167. package/tests/core/evolution-reducer.detector-metadata.test.ts +602 -0
  168. package/tests/core/evolution-reducer.test.ts +180 -0
  169. package/tests/core/evolution-types-loop.test.ts +48 -0
  170. package/tests/core/evolution-user-stories.e2e.test.ts +249 -0
  171. package/tests/core/external-training-contract.test.ts +463 -0
  172. package/tests/core/focus-history.test.ts +682 -0
  173. package/tests/core/init-flatten.test.ts +69 -0
  174. package/tests/core/init-refactor.test.ts +87 -0
  175. package/tests/core/init-v1.3.test.ts +46 -0
  176. package/tests/core/init.test.ts +190 -0
  177. package/tests/core/local-worker-routing.test.ts +757 -0
  178. package/tests/core/migration.test.ts +84 -0
  179. package/tests/core/model-deployment-registry.test.ts +845 -0
  180. package/tests/core/model-training-registry.test.ts +889 -0
  181. package/tests/core/nocturnal-arbiter.test.ts +494 -0
  182. package/tests/core/nocturnal-candidate-scoring.test.ts +400 -0
  183. package/tests/core/nocturnal-compliance.test.ts +646 -0
  184. package/tests/core/nocturnal-dataset.test.ts +892 -0
  185. package/tests/core/nocturnal-executability.test.ts +357 -0
  186. package/tests/core/nocturnal-export.test.ts +462 -0
  187. package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +428 -0
  188. package/tests/core/nocturnal-trajectory-extractor.test.ts +634 -0
  189. package/tests/core/nocturnal-trinity.test.ts +953 -0
  190. package/tests/core/pain.test.ts +33 -0
  191. package/tests/core/path-resolver.test.ts +57 -0
  192. package/tests/core/paths-refactor.test.ts +42 -0
  193. package/tests/core/phase7-rollout-integration.test.ts +477 -0
  194. package/tests/core/principle-training-state.test.ts +712 -0
  195. package/tests/core/profile.test.ts +56 -0
  196. package/tests/core/promotion-gate.test.ts +556 -0
  197. package/tests/core/risk-calculator.test.ts +168 -0
  198. package/tests/core/session-tracker.test.ts +191 -0
  199. package/tests/core/training-program.test.ts +472 -0
  200. package/tests/core/trajectory.test.ts +265 -0
  201. package/tests/core/workspace-context-factory.test.ts +18 -0
  202. package/tests/core/workspace-context.test.ts +134 -0
  203. package/tests/fixtures/nocturnal-reviewed-subset.json +183 -0
  204. package/tests/fixtures/production-compatibility.test.ts +147 -0
  205. package/tests/fixtures/production-mock-generator.ts +282 -0
  206. package/tests/hooks/bash-risk-integration.test.ts +137 -0
  207. package/tests/hooks/bash-risk.test.ts +81 -0
  208. package/tests/hooks/edit-verification.test.ts +678 -0
  209. package/tests/hooks/gate-edit-verification-p1.test.ts +632 -0
  210. package/tests/hooks/gate-edit-verification.test.ts +435 -0
  211. package/tests/hooks/gate-pipeline-integration.test.ts +404 -0
  212. package/tests/hooks/gate.test.ts +271 -0
  213. package/tests/hooks/gfi-gate-unit.test.ts +422 -0
  214. package/tests/hooks/gfi-gate.test.ts +669 -0
  215. package/tests/hooks/lifecycle.test.ts +248 -0
  216. package/tests/hooks/llm.test.ts +308 -0
  217. package/tests/hooks/message-sanitize.test.ts +36 -0
  218. package/tests/hooks/pain.test.ts +141 -0
  219. package/tests/hooks/progressive-trust-gate.test.ts +277 -0
  220. package/tests/hooks/prompt.test.ts +1411 -0
  221. package/tests/hooks/subagent.test.ts +467 -0
  222. package/tests/hooks/thinking-gate.test.ts +313 -0
  223. package/tests/http/principles-console-route.test.ts +140 -0
  224. package/tests/hygiene-tracker.test.ts +77 -0
  225. package/tests/index.integration.test.ts +179 -0
  226. package/tests/index.shadow-routing.integration.test.ts +140 -0
  227. package/tests/index.test.ts +9 -0
  228. package/tests/integration/empathy-workflow-integration.test.ts +627 -0
  229. package/tests/service/control-ui-query-service.test.ts +121 -0
  230. package/tests/service/empathy-observer-workflow-manager.test.ts +176 -0
  231. package/tests/service/evolution-worker.test.ts +585 -0
  232. package/tests/service/nocturnal-runtime.test.ts +470 -0
  233. package/tests/service/nocturnal-service.test.ts +577 -0
  234. package/tests/service/nocturnal-target-selector.test.ts +615 -0
  235. package/tests/service/nocturnal-workflow-manager.test.ts +439 -0
  236. package/tests/service/phase3-input-filter.test.ts +289 -0
  237. package/tests/service/runtime-summary-service.test.ts +919 -0
  238. package/tests/task-compliance.test.ts +166 -0
  239. package/tests/test-utils.ts +48 -0
  240. package/tests/tools/critique-prompt.test.ts +260 -0
  241. package/tests/tools/deep-reflect.test.ts +232 -0
  242. package/tests/tools/model-index.test.ts +246 -0
  243. package/tests/ui/app.test.tsx +114 -0
  244. package/tests/utils/file-lock.test.ts +407 -0
  245. package/tests/utils/hashing.test.ts +32 -0
  246. package/tests/utils/io.test.ts +39 -0
  247. package/tests/utils/nlp.test.ts +53 -0
  248. package/tests/utils/plugin-logger.test.ts +156 -0
  249. package/tsconfig.json +16 -0
  250. package/tsconfig.tsbuildinfo +1 -0
  251. package/ui/src/App.tsx +45 -0
  252. package/ui/src/api.ts +216 -0
  253. package/ui/src/charts.tsx +586 -0
  254. package/ui/src/components/ErrorState.tsx +6 -0
  255. package/ui/src/components/Loading.tsx +13 -0
  256. package/ui/src/components/ProtectedRoute.tsx +12 -0
  257. package/ui/src/components/Shell.tsx +91 -0
  258. package/ui/src/components/WorkspaceConfig.tsx +146 -0
  259. package/ui/src/components/index.ts +5 -0
  260. package/ui/src/context/auth.tsx +80 -0
  261. package/ui/src/context/theme.tsx +66 -0
  262. package/ui/src/hooks/useAutoRefresh.ts +39 -0
  263. package/ui/src/i18n/ui.ts +363 -0
  264. package/ui/src/main.tsx +16 -0
  265. package/ui/src/pages/EvolutionPage.tsx +352 -0
  266. package/ui/src/pages/FeedbackPage.tsx +140 -0
  267. package/ui/src/pages/GateMonitorPage.tsx +136 -0
  268. package/ui/src/pages/LoginPage.tsx +88 -0
  269. package/ui/src/pages/OverviewPage.tsx +238 -0
  270. package/ui/src/pages/SamplesPage.tsx +174 -0
  271. package/ui/src/pages/ThinkingModelsPage.tsx +127 -0
  272. package/ui/src/styles.css +1661 -0
  273. package/ui/src/types.ts +368 -0
  274. package/ui/src/utils/format.ts +15 -0
  275. package/vitest.config.ts +23 -0
  276. package/dist/commands/capabilities.d.ts +0 -3
  277. package/dist/commands/capabilities.js +0 -73
  278. package/dist/commands/context.d.ts +0 -5
  279. package/dist/commands/evolution-status.d.ts +0 -4
  280. package/dist/commands/evolution-status.js +0 -117
  281. package/dist/commands/evolver.d.ts +0 -9
  282. package/dist/commands/evolver.js +0 -26
  283. package/dist/commands/export.d.ts +0 -2
  284. package/dist/commands/export.js +0 -98
  285. package/dist/commands/focus.d.ts +0 -14
  286. package/dist/commands/focus.js +0 -457
  287. package/dist/commands/nocturnal-review.d.ts +0 -24
  288. package/dist/commands/nocturnal-review.js +0 -265
  289. package/dist/commands/nocturnal-rollout.d.ts +0 -27
  290. package/dist/commands/nocturnal-rollout.js +0 -671
  291. package/dist/commands/nocturnal-train.d.ts +0 -25
  292. package/dist/commands/nocturnal-train.js +0 -919
  293. package/dist/commands/pain.d.ts +0 -5
  294. package/dist/commands/principle-rollback.d.ts +0 -4
  295. package/dist/commands/principle-rollback.js +0 -22
  296. package/dist/commands/rollback.d.ts +0 -19
  297. package/dist/commands/samples.d.ts +0 -2
  298. package/dist/commands/samples.js +0 -55
  299. package/dist/commands/strategy.d.ts +0 -3
  300. package/dist/commands/strategy.js +0 -29
  301. package/dist/commands/thinking-os.d.ts +0 -2
  302. package/dist/config/defaults/runtime.d.ts +0 -40
  303. package/dist/config/errors.d.ts +0 -84
  304. package/dist/config/errors.js +0 -94
  305. package/dist/config/index.js +0 -7
  306. package/dist/constants/diagnostician.d.ts +0 -12
  307. package/dist/constants/diagnostician.js +0 -56
  308. package/dist/constants/tools.d.ts +0 -17
  309. package/dist/constants/tools.js +0 -54
  310. package/dist/core/adaptive-thresholds.d.ts +0 -186
  311. package/dist/core/adaptive-thresholds.js +0 -300
  312. package/dist/core/config-service.d.ts +0 -15
  313. package/dist/core/config.d.ts +0 -129
  314. package/dist/core/control-ui-db.d.ts +0 -95
  315. package/dist/core/control-ui-db.js +0 -292
  316. package/dist/core/detection-funnel.d.ts +0 -33
  317. package/dist/core/detection-service.d.ts +0 -15
  318. package/dist/core/dictionary-service.d.ts +0 -15
  319. package/dist/core/dictionary.d.ts +0 -38
  320. package/dist/core/event-log.d.ts +0 -82
  321. package/dist/core/event-log.js +0 -463
  322. package/dist/core/evolution-engine.d.ts +0 -118
  323. package/dist/core/evolution-engine.js +0 -464
  324. package/dist/core/evolution-logger.d.ts +0 -137
  325. package/dist/core/evolution-logger.js +0 -256
  326. package/dist/core/evolution-migration.d.ts +0 -5
  327. package/dist/core/evolution-migration.js +0 -65
  328. package/dist/core/evolution-reducer.d.ts +0 -98
  329. package/dist/core/evolution-reducer.js +0 -465
  330. package/dist/core/evolution-types.d.ts +0 -287
  331. package/dist/core/evolution-types.js +0 -78
  332. package/dist/core/external-training-contract.d.ts +0 -276
  333. package/dist/core/external-training-contract.js +0 -269
  334. package/dist/core/focus-history.d.ts +0 -210
  335. package/dist/core/focus-history.js +0 -1185
  336. package/dist/core/hygiene/tracker.d.ts +0 -22
  337. package/dist/core/hygiene/tracker.js +0 -106
  338. package/dist/core/init.d.ts +0 -12
  339. package/dist/core/local-worker-routing.d.ts +0 -175
  340. package/dist/core/local-worker-routing.js +0 -525
  341. package/dist/core/migration.d.ts +0 -6
  342. package/dist/core/model-deployment-registry.d.ts +0 -218
  343. package/dist/core/model-deployment-registry.js +0 -503
  344. package/dist/core/model-training-registry.d.ts +0 -295
  345. package/dist/core/model-training-registry.js +0 -475
  346. package/dist/core/nocturnal-arbiter.d.ts +0 -159
  347. package/dist/core/nocturnal-arbiter.js +0 -534
  348. package/dist/core/nocturnal-candidate-scoring.d.ts +0 -137
  349. package/dist/core/nocturnal-candidate-scoring.js +0 -266
  350. package/dist/core/nocturnal-compliance.d.ts +0 -175
  351. package/dist/core/nocturnal-compliance.js +0 -824
  352. package/dist/core/nocturnal-dataset.d.ts +0 -224
  353. package/dist/core/nocturnal-dataset.js +0 -443
  354. package/dist/core/nocturnal-executability.d.ts +0 -85
  355. package/dist/core/nocturnal-executability.js +0 -331
  356. package/dist/core/nocturnal-export.d.ts +0 -124
  357. package/dist/core/nocturnal-export.js +0 -275
  358. package/dist/core/nocturnal-paths.d.ts +0 -124
  359. package/dist/core/nocturnal-trajectory-extractor.d.ts +0 -242
  360. package/dist/core/nocturnal-trajectory-extractor.js +0 -307
  361. package/dist/core/nocturnal-trinity.d.ts +0 -311
  362. package/dist/core/nocturnal-trinity.js +0 -880
  363. package/dist/core/pain.d.ts +0 -4
  364. package/dist/core/pain.js +0 -70
  365. package/dist/core/path-resolver.d.ts +0 -46
  366. package/dist/core/paths.d.ts +0 -65
  367. package/dist/core/principle-training-state.d.ts +0 -121
  368. package/dist/core/principle-training-state.js +0 -321
  369. package/dist/core/profile.d.ts +0 -62
  370. package/dist/core/profile.js +0 -210
  371. package/dist/core/promotion-gate.d.ts +0 -238
  372. package/dist/core/promotion-gate.js +0 -529
  373. package/dist/core/risk-calculator.d.ts +0 -22
  374. package/dist/core/session-tracker.d.ts +0 -101
  375. package/dist/core/shadow-observation-registry.d.ts +0 -217
  376. package/dist/core/shadow-observation-registry.js +0 -308
  377. package/dist/core/system-logger.d.ts +0 -8
  378. package/dist/core/thinking-models.d.ts +0 -38
  379. package/dist/core/thinking-models.js +0 -170
  380. package/dist/core/training-program.d.ts +0 -233
  381. package/dist/core/training-program.js +0 -433
  382. package/dist/core/trajectory.d.ts +0 -411
  383. package/dist/core/trajectory.js +0 -1307
  384. package/dist/core/workspace-context.d.ts +0 -71
  385. package/dist/hooks/bash-risk.d.ts +0 -57
  386. package/dist/hooks/bash-risk.js +0 -137
  387. package/dist/hooks/edit-verification.d.ts +0 -62
  388. package/dist/hooks/edit-verification.js +0 -256
  389. package/dist/hooks/gate-block-helper.d.ts +0 -44
  390. package/dist/hooks/gate-block-helper.js +0 -119
  391. package/dist/hooks/gate.d.ts +0 -24
  392. package/dist/hooks/gate.js +0 -173
  393. package/dist/hooks/gfi-gate.d.ts +0 -40
  394. package/dist/hooks/gfi-gate.js +0 -113
  395. package/dist/hooks/lifecycle.d.ts +0 -5
  396. package/dist/hooks/lifecycle.js +0 -284
  397. package/dist/hooks/llm.d.ts +0 -13
  398. package/dist/hooks/message-sanitize.d.ts +0 -3
  399. package/dist/hooks/message-sanitize.js +0 -37
  400. package/dist/hooks/pain.d.ts +0 -5
  401. package/dist/hooks/pain.js +0 -301
  402. package/dist/hooks/progressive-trust-gate.d.ts +0 -52
  403. package/dist/hooks/progressive-trust-gate.js +0 -134
  404. package/dist/hooks/prompt.d.ts +0 -49
  405. package/dist/hooks/prompt.js +0 -905
  406. package/dist/hooks/subagent.d.ts +0 -10
  407. package/dist/hooks/subagent.js +0 -387
  408. package/dist/hooks/thinking-checkpoint.d.ts +0 -37
  409. package/dist/hooks/thinking-checkpoint.js +0 -51
  410. package/dist/hooks/trajectory-collector.d.ts +0 -32
  411. package/dist/hooks/trajectory-collector.js +0 -256
  412. package/dist/http/principles-console-route.d.ts +0 -9
  413. package/dist/http/principles-console-route.js +0 -681
  414. package/dist/i18n/commands.d.ts +0 -26
  415. package/dist/i18n/commands.js +0 -116
  416. package/dist/index.d.ts +0 -7
  417. package/dist/index.js +0 -581
  418. package/dist/service/central-database.d.ts +0 -104
  419. package/dist/service/central-database.js +0 -649
  420. package/dist/service/control-ui-query-service.d.ts +0 -221
  421. package/dist/service/control-ui-query-service.js +0 -543
  422. package/dist/service/empathy-observer-manager.d.ts +0 -88
  423. package/dist/service/empathy-observer-manager.js +0 -414
  424. package/dist/service/evolution-query-service.d.ts +0 -155
  425. package/dist/service/evolution-query-service.js +0 -258
  426. package/dist/service/evolution-worker.d.ts +0 -101
  427. package/dist/service/evolution-worker.js +0 -975
  428. package/dist/service/health-query-service.d.ts +0 -170
  429. package/dist/service/health-query-service.js +0 -662
  430. package/dist/service/nocturnal-runtime.d.ts +0 -183
  431. package/dist/service/nocturnal-service.d.ts +0 -163
  432. package/dist/service/nocturnal-service.js +0 -787
  433. package/dist/service/nocturnal-target-selector.d.ts +0 -145
  434. package/dist/service/nocturnal-target-selector.js +0 -315
  435. package/dist/service/phase3-input-filter.d.ts +0 -73
  436. package/dist/service/phase3-input-filter.js +0 -172
  437. package/dist/service/runtime-summary-service.d.ts +0 -122
  438. package/dist/service/runtime-summary-service.js +0 -485
  439. package/dist/service/subagent-workflow/empathy-observer-workflow-manager.d.ts +0 -48
  440. package/dist/service/subagent-workflow/index.d.ts +0 -4
  441. package/dist/service/subagent-workflow/index.js +0 -3
  442. package/dist/service/subagent-workflow/runtime-direct-driver.d.ts +0 -77
  443. package/dist/service/subagent-workflow/runtime-direct-driver.js +0 -75
  444. package/dist/service/subagent-workflow/types.js +0 -11
  445. package/dist/service/subagent-workflow/workflow-store.d.ts +0 -26
  446. package/dist/service/subagent-workflow/workflow-store.js +0 -165
  447. package/dist/service/trajectory-service.d.ts +0 -2
  448. package/dist/service/trajectory-service.js +0 -15
  449. package/dist/tools/critique-prompt.d.ts +0 -14
  450. package/dist/tools/deep-reflect.d.ts +0 -39
  451. package/dist/tools/deep-reflect.js +0 -350
  452. package/dist/tools/model-index.d.ts +0 -9
  453. package/dist/types/event-types.d.ts +0 -306
  454. package/dist/types/event-types.js +0 -106
  455. package/dist/types/hygiene-types.d.ts +0 -20
  456. package/dist/types/hygiene-types.js +0 -12
  457. package/dist/types/runtime-summary.d.ts +0 -47
  458. package/dist/types/runtime-summary.js +0 -1
  459. package/dist/types.d.ts +0 -50
  460. package/dist/types.js +0 -22
  461. package/dist/utils/file-lock.d.ts +0 -71
  462. package/dist/utils/file-lock.js +0 -309
  463. package/dist/utils/glob-match.d.ts +0 -28
  464. package/dist/utils/hashing.d.ts +0 -9
  465. package/dist/utils/io.d.ts +0 -6
  466. package/dist/utils/io.js +0 -106
  467. package/dist/utils/nlp.d.ts +0 -9
  468. package/dist/utils/plugin-logger.d.ts +0 -39
  469. package/dist/utils/subagent-probe.d.ts +0 -34
  470. package/dist/utils/subagent-probe.js +0 -81
@@ -0,0 +1,562 @@
1
+ /**
2
+ * Evolution Engine V2.0 - 单元测试
3
+ */
4
+
5
+ import { describe, it, test, expect, beforeEach, afterEach } from 'vitest';
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import * as os from 'os';
9
+ import {
10
+ EvolutionEngine,
11
+ disposeAllEvolutionEngines,
12
+ disposeEvolutionEngine,
13
+ getEvolutionEngine,
14
+ } from '../../src/core/evolution-engine.js';
15
+ import {
16
+ EvolutionTier,
17
+ TIER_DEFINITIONS,
18
+ TASK_DIFFICULTY_CONFIG,
19
+ getTierByPoints,
20
+ EvolutionEvent,
21
+ EvolutionScorecard,
22
+ TaskDifficulty,
23
+ } from '../../src/core/evolution-types.js';
24
+
25
+ // ===== 测试工具 =====
26
+
27
+ function createTempWorkspace(): string {
28
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ep-test-'));
29
+ // EvolutionEngine 使用 .state 目录(STATE_DIR)
30
+ const stateDir = path.join(tmpDir, '.state');
31
+ fs.mkdirSync(stateDir, { recursive: true });
32
+ return tmpDir;
33
+ }
34
+
35
+ function cleanupWorkspace(dir: string): void {
36
+ try {
37
+ fs.rmSync(dir, { recursive: true, force: true });
38
+ } catch {}
39
+ }
40
+
41
+ // ===== 测试套件 =====
42
+
43
+ describe('EvolutionEngine', () => {
44
+ let workspace: string;
45
+ let engine: EvolutionEngine;
46
+
47
+ beforeEach(() => {
48
+ workspace = createTempWorkspace();
49
+ engine = new EvolutionEngine(workspace);
50
+ });
51
+
52
+ afterEach(() => {
53
+ disposeAllEvolutionEngines();
54
+ cleanupWorkspace(workspace);
55
+ });
56
+
57
+ // ===== 等级系统测试 =====
58
+
59
+ describe('Tier System', () => {
60
+ test('should start at Seed tier with 0 points', () => {
61
+ expect(engine.getTier()).toBe(EvolutionTier.Seed);
62
+ expect(engine.getPoints()).toBe(0);
63
+ });
64
+
65
+ test('should promote to Sprout at 50 points', () => {
66
+ // 50 points / 3 base = ~17 normal successes
67
+ for (let i = 0; i < 17; i++) {
68
+ engine.recordSuccess('write', { difficulty: 'normal' });
69
+ }
70
+ expect(engine.getTier()).toBeGreaterThanOrEqual(EvolutionTier.Sprout);
71
+ });
72
+
73
+ test('should promote to Sapling at 200 points', () => {
74
+ // 200 points / 8 base = 25 hard successes
75
+ for (let i = 0; i < 26; i++) {
76
+ engine.recordSuccess('write', { difficulty: 'hard' });
77
+ }
78
+ expect(engine.getTier()).toBeGreaterThanOrEqual(EvolutionTier.Sapling);
79
+ });
80
+
81
+ test('getTierByPoints returns correct tier', () => {
82
+ expect(getTierByPoints(0)).toBe(EvolutionTier.Seed);
83
+ expect(getTierByPoints(49)).toBe(EvolutionTier.Seed);
84
+ expect(getTierByPoints(50)).toBe(EvolutionTier.Sprout);
85
+ expect(getTierByPoints(199)).toBe(EvolutionTier.Sprout);
86
+ expect(getTierByPoints(200)).toBe(EvolutionTier.Sapling);
87
+ expect(getTierByPoints(499)).toBe(EvolutionTier.Sapling);
88
+ expect(getTierByPoints(500)).toBe(EvolutionTier.Tree);
89
+ expect(getTierByPoints(999)).toBe(EvolutionTier.Tree);
90
+ expect(getTierByPoints(1000)).toBe(EvolutionTier.Forest);
91
+ });
92
+
93
+ test('TIER_DEFINITIONS has 5 tiers', () => {
94
+ expect(TIER_DEFINITIONS).toHaveLength(5);
95
+ });
96
+ });
97
+
98
+ // ===== 积分计算测试 =====
99
+
100
+ describe('Points Calculation', () => {
101
+ test('should award base points for normal success', () => {
102
+ const result = engine.recordSuccess('write', { difficulty: 'normal' });
103
+ expect(result.pointsAwarded).toBe(TASK_DIFFICULTY_CONFIG.normal.basePoints);
104
+ });
105
+
106
+ test('should award more points for hard tasks', () => {
107
+ const normalResult = engine.recordSuccess('write', { difficulty: 'normal' });
108
+
109
+ // Reset for hard test
110
+ workspace = createTempWorkspace();
111
+ engine = new EvolutionEngine(workspace);
112
+ const hardResult = engine.recordSuccess('write', { difficulty: 'hard' });
113
+
114
+ expect(hardResult.pointsAwarded).toBeGreaterThan(normalResult.pointsAwarded);
115
+ });
116
+
117
+ test('should not award points for exploratory tools', () => {
118
+ const result = engine.recordSuccess('read');
119
+ expect(result.pointsAwarded).toBe(0);
120
+ });
121
+
122
+ test('failure should award 0 points', () => {
123
+ const result = engine.recordFailure('write');
124
+ expect(result.pointsAwarded).toBe(0);
125
+ });
126
+ });
127
+
128
+ // ===== 双倍奖励测试 =====
129
+
130
+ describe('Double Reward', () => {
131
+ test('should give double reward after failure then success', () => {
132
+ // 先失败
133
+ engine.recordFailure('write', { filePath: 'test.ts' });
134
+
135
+ // 再成功(同类任务)
136
+ const result = engine.recordSuccess('write', { filePath: 'test.ts', difficulty: 'normal' });
137
+
138
+ expect(result.isDoubleReward).toBe(true);
139
+ expect(result.pointsAwarded).toBe(TASK_DIFFICULTY_CONFIG.normal.basePoints * 2);
140
+ });
141
+
142
+ test('should not give double reward without prior failure', () => {
143
+ const result = engine.recordSuccess('write', { difficulty: 'normal' });
144
+ expect(result.isDoubleReward).toBe(false);
145
+ });
146
+
147
+ test('should respect cooldown for double reward', () => {
148
+ // 第一次失败→成功(触发双倍)
149
+ engine.recordFailure('write', { filePath: 'test1.ts' });
150
+ const first = engine.recordSuccess('write', { filePath: 'test1.ts', difficulty: 'normal' });
151
+ expect(first.isDoubleReward).toBe(true);
152
+
153
+ // 第二次失败→成功(冷却中,不双倍)
154
+ engine.recordFailure('write', { filePath: 'test2.ts' });
155
+ const second = engine.recordSuccess('write', { filePath: 'test2.ts', difficulty: 'normal' });
156
+ expect(second.isDoubleReward).toBe(false);
157
+ });
158
+ });
159
+
160
+ // ===== 难度衰减测试 =====
161
+
162
+ describe('Difficulty Penalty', () => {
163
+ test('should apply penalty for trivial tasks at high tier', () => {
164
+ // 直接设置高积分来模拟高等级
165
+ for (let i = 0; i < 63; i++) {
166
+ engine.recordSuccess('write', { difficulty: 'hard' });
167
+ }
168
+
169
+ // 此时应该是 Tree 级别
170
+ const tier = engine.getTier();
171
+ if (tier >= EvolutionTier.Tree) {
172
+ const result = engine.recordSuccess('write', { difficulty: 'trivial' });
173
+ // trivial 基础分1分,Tree级衰减后应该是 0.1 → 最少1分
174
+ expect(result.pointsAwarded).toBeLessThanOrEqual(TASK_DIFFICULTY_CONFIG.trivial.basePoints);
175
+ }
176
+ });
177
+ });
178
+
179
+ // ===== Gate 检查测试 =====
180
+
181
+ describe('Gate Integration', () => {
182
+ test('Seed tier should limit to 150 lines', () => {
183
+ const decision = engine.beforeToolCall({
184
+ toolName: 'write',
185
+ content: Array(151).fill('line').join('\n'),
186
+ });
187
+ expect(decision.allowed).toBe(false);
188
+ expect(decision.reason).toContain('150');
189
+ });
190
+
191
+ test('Seed tier should allow within limit', () => {
192
+ const decision = engine.beforeToolCall({
193
+ toolName: 'write',
194
+ content: Array(100).fill('line').join('\n'),
195
+ });
196
+ expect(decision.allowed).toBe(true);
197
+ });
198
+
199
+ test('Seed tier should block risk path', () => {
200
+ const decision = engine.beforeToolCall({
201
+ toolName: 'write',
202
+ filePath: 'src/core/trust-engine.ts',
203
+ isRiskPath: true,
204
+ lineCount: 10,
205
+ });
206
+ expect(decision.allowed).toBe(false);
207
+ });
208
+
209
+ test('Seed tier should allow subagent spawn', () => {
210
+ const decision = engine.beforeToolCall({
211
+ toolName: 'sessions_spawn',
212
+ });
213
+ expect(decision.allowed).toBe(true);
214
+ });
215
+
216
+ test('Forest tier should allow everything', () => {
217
+ // 直接设置为 Forest
218
+ for (let i = 0; i < 125; i++) {
219
+ engine.recordSuccess('write', { difficulty: 'hard' });
220
+ }
221
+
222
+ expect(engine.getTier()).toBe(EvolutionTier.Forest);
223
+
224
+ const decision = engine.beforeToolCall({
225
+ toolName: 'write',
226
+ content: Array(10000).fill('line').join('\n'),
227
+ isRiskPath: true,
228
+ });
229
+ expect(decision.allowed).toBe(true);
230
+ });
231
+ });
232
+
233
+ // ===== 持久化测试 =====
234
+
235
+ describe('Persistence', () => {
236
+ test('should save and load scorecard', () => {
237
+ engine.recordSuccess('write', { difficulty: 'hard' });
238
+ engine.recordSuccess('write', { difficulty: 'hard' });
239
+
240
+ const pointsBefore = engine.getPoints();
241
+
242
+ // 创建新实例(模拟重启)
243
+ const engine2 = new EvolutionEngine(workspace);
244
+ expect(engine2.getPoints()).toBe(pointsBefore);
245
+ });
246
+
247
+ test('should persist failure hashes across restart', () => {
248
+ engine.recordFailure('write', { filePath: 'test.ts' });
249
+
250
+ // 重启
251
+ const engine2 = new EvolutionEngine(workspace);
252
+ const result = engine2.recordSuccess('write', { filePath: 'test.ts', difficulty: 'normal' });
253
+
254
+ expect(result.isDoubleReward).toBe(true);
255
+ });
256
+ });
257
+
258
+ // ===== 统计测试 =====
259
+
260
+ describe('Stats', () => {
261
+ test('should track success/failure counts', () => {
262
+ engine.recordSuccess('write', { difficulty: 'normal' });
263
+ engine.recordSuccess('write', { difficulty: 'normal' });
264
+ engine.recordFailure('write');
265
+
266
+ const stats = engine.getStats();
267
+ expect(stats.totalSuccesses).toBe(2);
268
+ expect(stats.totalFailures).toBe(1);
269
+ });
270
+
271
+ test('should track consecutive streaks', () => {
272
+ engine.recordSuccess('write');
273
+ engine.recordSuccess('write');
274
+ engine.recordSuccess('write');
275
+
276
+ const stats = engine.getStats();
277
+ expect(stats.consecutiveSuccesses).toBe(3);
278
+ expect(stats.consecutiveFailures).toBe(0);
279
+ });
280
+
281
+ test('should break streak on failure', () => {
282
+ engine.recordSuccess('write');
283
+ engine.recordSuccess('write');
284
+ engine.recordFailure('write');
285
+
286
+ const stats = engine.getStats();
287
+ expect(stats.consecutiveSuccesses).toBe(0);
288
+ expect(stats.consecutiveFailures).toBe(1);
289
+ });
290
+ });
291
+
292
+ // ===== 状态摘要测试 =====
293
+
294
+ describe('Status Summary', () => {
295
+ test('should return correct status summary', () => {
296
+ const summary = engine.getStatusSummary();
297
+ expect(summary.tier).toBe(EvolutionTier.Seed);
298
+ expect(summary.tierName).toBe('Seed');
299
+ expect(summary.totalPoints).toBe(0);
300
+ expect(summary.nextTier).toBeDefined();
301
+ expect(summary.nextTier!.name).toBe('Sprout');
302
+ });
303
+
304
+ test('Forest should have no next tier', () => {
305
+ for (let i = 0; i < 125; i++) {
306
+ engine.recordSuccess('write', { difficulty: 'hard' });
307
+ }
308
+
309
+ const summary = engine.getStatusSummary();
310
+ expect(summary.nextTier).toBeNull();
311
+ });
312
+ });
313
+
314
+ // ===== P0 修复验证:多 Workspace 隔离 =====
315
+
316
+ describe('Multi-Workspace Isolation (P0 fix)', () => {
317
+ test('getEvolutionEngine should return different instances for different workspaces', () => {
318
+ const workspace1 = createTempWorkspace();
319
+ const workspace2 = createTempWorkspace();
320
+
321
+ const engine1 = getEvolutionEngine(workspace1);
322
+ const engine2 = getEvolutionEngine(workspace2);
323
+
324
+ // 不同 workspace 应该有不同的引擎实例
325
+ expect(engine1).not.toBe(engine2);
326
+
327
+ // 各自独立计分
328
+ engine1.recordSuccess('write', { difficulty: 'hard' });
329
+ expect(engine1.getPoints()).toBe(TASK_DIFFICULTY_CONFIG.hard.basePoints);
330
+ expect(engine2.getPoints()).toBe(0);
331
+
332
+ cleanupWorkspace(workspace1);
333
+ cleanupWorkspace(workspace2);
334
+ });
335
+
336
+ test('getEvolutionEngine should return same instance for same workspace', () => {
337
+ const ws = createTempWorkspace();
338
+ const e1 = getEvolutionEngine(ws);
339
+ const e2 = getEvolutionEngine(ws);
340
+ expect(e1).toBe(e2);
341
+ disposeEvolutionEngine(ws);
342
+ cleanupWorkspace(ws);
343
+ });
344
+
345
+ test('disposeEvolutionEngine should remove cached instance', () => {
346
+ const ws = createTempWorkspace();
347
+ const e1 = getEvolutionEngine(ws);
348
+ disposeEvolutionEngine(ws);
349
+ const e2 = getEvolutionEngine(ws);
350
+ expect(e2).not.toBe(e1);
351
+ disposeEvolutionEngine(ws);
352
+ cleanupWorkspace(ws);
353
+ });
354
+ });
355
+
356
+ // ===== P0 修复验证:并发写入 =====
357
+
358
+ describe('Concurrent Write Safety (P0 fix)', () => {
359
+ test('should handle rapid sequential writes without corruption', () => {
360
+ const iterations = 50;
361
+ for (let i = 0; i < iterations; i++) {
362
+ engine.recordSuccess('write', { difficulty: 'normal' });
363
+ }
364
+
365
+ // 验证数据完整性
366
+ expect(engine.getPoints()).toBe(iterations * TASK_DIFFICULTY_CONFIG.normal.basePoints);
367
+ expect(engine.getStats().totalSuccesses).toBe(iterations);
368
+ });
369
+
370
+ test('should persist correctly after rapid writes', () => {
371
+ const iterations = 30;
372
+ for (let i = 0; i < iterations; i++) {
373
+ engine.recordSuccess('write', { difficulty: 'hard' });
374
+ }
375
+
376
+ const expectedPoints = engine.getPoints();
377
+
378
+ // 重新加载验证持久化
379
+ const engine2 = new EvolutionEngine(workspace);
380
+ expect(engine2.getPoints()).toBe(expectedPoints);
381
+ });
382
+ });
383
+
384
+ // ===== P0 修复验证:锁竞态条件 =====
385
+
386
+ describe('Lock Race Condition Fixes', () => {
387
+ test('should handle concurrent engine instances safely', () => {
388
+ // 测试多个引擎实例(共享同一文件)的安全性
389
+ // 每个实例有独立的内存状态,但文件是共享的
390
+
391
+ const engine1 = new EvolutionEngine(workspace);
392
+ const engine2 = new EvolutionEngine(workspace);
393
+
394
+ // 两个实例交替写入
395
+ engine1.recordSuccess('write', { difficulty: 'normal' });
396
+ engine2.recordSuccess('write', { difficulty: 'normal' });
397
+ engine1.recordSuccess('write', { difficulty: 'normal' });
398
+ engine2.recordSuccess('write', { difficulty: 'normal' });
399
+
400
+ // 重新加载验证最终状态
401
+ const engine3 = new EvolutionEngine(workspace);
402
+ // 由于内存状态独立,最终积分取决于最后一次成功保存的实例
403
+ // 这里主要验证没有数据损坏
404
+ expect(() => engine3.getPoints()).not.toThrow();
405
+ });
406
+
407
+ test('should not corrupt data under high contention', () => {
408
+ // 快速连续写入,测试文件锁的保护
409
+ const iterations = 50;
410
+ for (let i = 0; i < iterations; i++) {
411
+ engine.recordSuccess('write', { difficulty: 'normal' });
412
+ }
413
+
414
+ // 验证数据完整性(没有损坏)
415
+ const stateDir = path.join(workspace, '.state');
416
+ const storagePath = path.join(stateDir, 'evolution-scorecard.json');
417
+ const content = fs.readFileSync(storagePath, 'utf8');
418
+ const data = JSON.parse(content); // 不应该抛出异常
419
+
420
+ expect(data.totalPoints).toBe(iterations * TASK_DIFFICULTY_CONFIG.normal.basePoints);
421
+ });
422
+
423
+ test('should handle lock timeout gracefully', () => {
424
+ // 创建一个持有锁的"假进程"
425
+ const stateDir = path.join(workspace, '.state');
426
+ const storagePath = path.join(stateDir, 'evolution-scorecard.json');
427
+ const lockPath = `${storagePath}.lock`;
428
+
429
+ // 模拟锁被死进程持有
430
+ const deadPid = 99999999;
431
+ fs.writeFileSync(lockPath, String(deadPid), 'utf8');
432
+
433
+ // 尝试写入应该成功(死进程锁会被清理)
434
+ const result = engine.recordSuccess('write', { difficulty: 'normal' });
435
+ expect(result.pointsAwarded).toBeGreaterThan(0);
436
+ });
437
+ });
438
+
439
+ // ===== P0 修复验证:数据不丢失 =====
440
+
441
+ describe('No Data Loss on Lock Failure', () => {
442
+ test('should not silently drop data when lock fails', () => {
443
+ // 记录初始状态
444
+ const initialPoints = engine.getPoints();
445
+
446
+ // 连续快速操作
447
+ const operations = 100;
448
+ for (let i = 0; i < operations; i++) {
449
+ engine.recordSuccess('write', { difficulty: 'trivial' });
450
+ }
451
+
452
+ // 所有操作都应该被记录(无丢失)
453
+ const expectedPoints = initialPoints + operations * TASK_DIFFICULTY_CONFIG.trivial.basePoints;
454
+ expect(engine.getPoints()).toBe(expectedPoints);
455
+ });
456
+
457
+ test('should preserve all failure records for double reward', () => {
458
+ // 记录多次失败
459
+ for (let i = 0; i < 5; i++) {
460
+ engine.recordFailure('write', { filePath: `test-${i}.ts` });
461
+ }
462
+
463
+ // 重新加载
464
+ const engine2 = new EvolutionEngine(workspace);
465
+
466
+ // 验证失败记录被保留
467
+ const result = engine2.recordSuccess('write', {
468
+ filePath: 'test-0.ts',
469
+ difficulty: 'normal'
470
+ });
471
+
472
+ expect(result.isDoubleReward).toBe(true);
473
+ });
474
+
475
+ test('retry queue should eventually save data', async () => {
476
+ // 这个测试验证正常情况下数据能被持久化
477
+ // 重试队列仅在锁获取失败时触发
478
+
479
+ // 记录一些数据
480
+ engine.recordSuccess('write', { difficulty: 'hard' });
481
+ const pointsBefore = engine.getPoints();
482
+
483
+ // 等待可能的异步操作完成
484
+ await new Promise(resolve => setTimeout(resolve, 100));
485
+
486
+ // 重新加载验证
487
+ const engine2 = new EvolutionEngine(workspace);
488
+ expect(engine2.getPoints()).toBe(pointsBefore);
489
+ });
490
+ });
491
+
492
+ // ===== 原子写入验证 =====
493
+
494
+ describe('Atomic Write Operations', () => {
495
+ test('should write to temp file first, then rename', () => {
496
+ const stateDir = path.join(workspace, '.state');
497
+ const tempFiles = fs.readdirSync(stateDir).filter(f => f.includes('.tmp.'));
498
+
499
+ // 不应该有残留的临时文件
500
+ expect(tempFiles.length).toBe(0);
501
+
502
+ // 执行写入
503
+ engine.recordSuccess('write', { difficulty: 'normal' });
504
+
505
+ // 仍然不应该有残留的临时文件
506
+ const tempFilesAfter = fs.readdirSync(stateDir).filter(f => f.includes('.tmp.'));
507
+ expect(tempFilesAfter.length).toBe(0);
508
+ });
509
+
510
+ test('should have valid JSON after concurrent writes', () => {
511
+ // 快速写入
512
+ for (let i = 0; i < 50; i++) {
513
+ engine.recordSuccess('write', { difficulty: 'normal' });
514
+ }
515
+
516
+ // 直接读取文件验证 JSON 有效性
517
+ const stateDir = path.join(workspace, '.state');
518
+ const storagePath = path.join(stateDir, 'evolution-scorecard.json');
519
+
520
+ const content = fs.readFileSync(storagePath, 'utf8');
521
+ const data = JSON.parse(content); // 不应该抛出异常
522
+
523
+ expect(data.totalPoints).toBe(50 * TASK_DIFFICULTY_CONFIG.normal.basePoints);
524
+ });
525
+ });
526
+
527
+ // ===== PID 存活检测测试 =====
528
+
529
+ describe('PID Liveness Detection', () => {
530
+ test('should detect current process as alive', () => {
531
+ // 当前进程应该总是存活的
532
+ expect(() => process.kill(process.pid, 0)).not.toThrow();
533
+ });
534
+
535
+ test('should clean up dead process lock and save data', () => {
536
+ const stateDir = path.join(workspace, '.state');
537
+ const storagePath = path.join(stateDir, 'evolution-scorecard.json');
538
+ const lockPath = `${storagePath}.lock`;
539
+
540
+ // 创建一个"死进程"的锁
541
+ // 使用一个非常大的 PID 号(如 99999999),这个进程几乎肯定不存在
542
+ const deadPid = 99999999;
543
+ fs.writeFileSync(lockPath, String(deadPid), 'utf8');
544
+
545
+ // 验证锁文件存在
546
+ expect(fs.existsSync(lockPath)).toBe(true);
547
+
548
+ // 下一次写入应该能获取锁(因为持有者进程已死亡)并成功保存
549
+ const result = engine.recordSuccess('write', { difficulty: 'normal' });
550
+ expect(result.pointsAwarded).toBeGreaterThan(0);
551
+
552
+ // 验证内存中的积分正确
553
+ expect(engine.getPoints()).toBe(result.pointsAwarded);
554
+
555
+ // 验证锁被释放(文件不存在)
556
+ expect(fs.existsSync(lockPath)).toBe(false);
557
+
558
+ // 验证数据文件存在
559
+ expect(fs.existsSync(storagePath)).toBe(true);
560
+ });
561
+ });
562
+ });