@sanqianx/project-knowledge 5.0.24 → 5.0.25

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 (401) hide show
  1. package/.agents/plugins/marketplace.json +20 -20
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/CHANGELOG.md +1361 -1353
  4. package/LICENSE +201 -201
  5. package/NOTICE +5 -5
  6. package/README.md +349 -349
  7. package/_modules/knowledge-engine/package.json +1 -1
  8. package/_modules/knowledge-engine/src/coordinator.js +48 -3
  9. package/_modules/knowledge-engine/src/runtime/automation-config.js +140 -140
  10. package/_modules/knowledge-engine/src/runtime/commit-conversation-binder.js +238 -238
  11. package/_modules/knowledge-engine/src/runtime/commit-processing-ledger.js +26 -26
  12. package/_modules/knowledge-engine/src/runtime/commit-prompt.js +193 -193
  13. package/_modules/knowledge-engine/src/runtime/commit-reconciler.js +394 -394
  14. package/_modules/knowledge-engine/src/runtime/contracts.js +282 -282
  15. package/_modules/knowledge-engine/src/runtime/conversation-store.js +389 -389
  16. package/_modules/knowledge-engine/src/runtime/evidence-bundle.js +228 -228
  17. package/_modules/knowledge-engine/src/runtime/git-runner.js +62 -62
  18. package/_modules/knowledge-engine/src/runtime/knowledge-promotion.js +505 -505
  19. package/_modules/knowledge-engine/src/runtime/knowledge-retrieval-service.js +400 -400
  20. package/_modules/knowledge-engine/src/runtime/markdown-knowledge-indexer.js +171 -171
  21. package/_modules/knowledge-engine/src/runtime/scanner.js +298 -298
  22. package/_modules/knowledge-engine/ui/app.js +23 -2
  23. package/_site/README.md +30 -30
  24. package/_site/_test/agent-capture-mcp-ui-test.js +68 -68
  25. package/_site/_test/agent-capture-ui-test.js +101 -101
  26. package/_site/_test/ai-profile-resolver-test.js +137 -137
  27. package/_site/_test/ai-profile-test.js +75 -75
  28. package/_site/_test/ai-vendor-presets-test.js +91 -91
  29. package/_site/_test/automatic-context-test.js +70 -70
  30. package/_site/_test/automation-queue-test.js +14 -14
  31. package/_site/_test/automation-ui-test.js +40 -40
  32. package/_site/_test/background-task-registry-test.js +43 -43
  33. package/_site/_test/baseline-schema-test.js +91 -91
  34. package/_site/_test/bin-cli-test.js +230 -230
  35. package/_site/_test/bridge-adapter-test.js +95 -95
  36. package/_site/_test/bridge-consumer-service-test.js +310 -310
  37. package/_site/_test/candidate-bin-content-test.js +35 -35
  38. package/_site/_test/candidate-product-assets-test.js +13 -13
  39. package/_site/_test/candidate-release-contract-test.js +14 -14
  40. package/_site/_test/capture-hook-dedup-test.js +158 -158
  41. package/_site/_test/cdp-browser-failure-test.js +103 -103
  42. package/_site/_test/chat-claudecodeui-match-test.js +92 -92
  43. package/_site/_test/claude-executable-discovery-test.js +90 -90
  44. package/_site/_test/claude-session-lifecycle-sweep-test.js +252 -252
  45. package/_site/_test/claude-workbench-test.js +174 -174
  46. package/_site/_test/cli-instance-management-test.js +62 -62
  47. package/_site/_test/client-capture-restart-e2e-test.js +189 -189
  48. package/_site/_test/codex-conversation-projection-test.js +60 -60
  49. package/_site/_test/codex-marketplace-scoped-path-test.js +186 -186
  50. package/_site/_test/codex-notify-capture-e2e-test.js +101 -101
  51. package/_site/_test/codex-notify-fanout-test.js +141 -134
  52. package/_site/_test/codex-notify-upgrade-test.js +253 -253
  53. package/_site/_test/commit-boundary-freeze-test.js +147 -147
  54. package/_site/_test/commit-conversation-binding-test.js +99 -99
  55. package/_site/_test/commit-evidence-test.js +110 -110
  56. package/_site/_test/configuration-generation-test.js +22 -22
  57. package/_site/_test/context-pack-test.js +200 -200
  58. package/_site/_test/conversation-api-test.js +119 -119
  59. package/_site/_test/conversation-origin-test.js +15 -15
  60. package/_site/_test/conversation-store-test.js +138 -138
  61. package/_site/_test/cross-repo-isolation-e2e-test.js +187 -187
  62. package/_site/_test/desktop-browser-compat-test.js +28 -28
  63. package/_site/_test/desktop-hook-runtime-regression-test.js +204 -204
  64. package/_site/_test/embedding-config-test.js +32 -32
  65. package/_site/_test/explicit-commit-processor-test.js +37 -37
  66. package/_site/_test/fixtures/fake-browser-exit.js +10 -10
  67. package/_site/_test/fixtures/fake-browser-hang.js +10 -10
  68. package/_site/_test/fixtures/integration-busy-worker.cjs +6 -6
  69. package/_site/_test/fixtures/make-git-repos.js +92 -92
  70. package/_site/_test/fixtures/retrieval-gold-queries.json +32 -32
  71. package/_site/_test/folder-picker-output-test.js +19 -19
  72. package/_site/_test/fresh-hook-reimport-test.js +53 -53
  73. package/_site/_test/fresh-product-data-test.js +56 -56
  74. package/_site/_test/full-integration-e2e-test.js +167 -167
  75. package/_site/_test/git-path-compatibility-test.js +80 -80
  76. package/_site/_test/git-validation-test.js +81 -81
  77. package/_site/_test/glm-ui-refresh-review-test.js +313 -404
  78. package/_site/_test/harness-isolation-test.js +138 -0
  79. package/_site/_test/helpers/cdp-browser.js +383 -0
  80. package/_site/_test/helpers/cdp-network-capture.js +66 -0
  81. package/_site/_test/helpers/find-chrome.js +34 -0
  82. package/_site/_test/helpers/free-port.js +8 -0
  83. package/_site/_test/helpers/logging-ui-fixture.js +131 -0
  84. package/_site/_test/helpers/module-fixture.js +282 -0
  85. package/_site/_test/helpers/parallel-engine-advanced-engine-child.js +45 -0
  86. package/_site/_test/helpers/parallel-engine-advanced-fault-writer.js +171 -0
  87. package/_site/_test/helpers/parallel-engine-advanced-harness.js +245 -0
  88. package/_site/_test/helpers/parallel-engine-advanced-standin-analyzer.js +80 -0
  89. package/_site/_test/helpers/parallel-engine-advanced-ui-host.js +177 -0
  90. package/_site/_test/helpers/parallel-engine-final-harness.js +314 -0
  91. package/_site/_test/helpers/parallel-engine-final-standin-analyzer.js +159 -0
  92. package/_site/_test/helpers/parallel-knowledge-fixture.js +255 -0
  93. package/_site/_test/helpers/parallel-logging-acceptance-fixture.js +111 -0
  94. package/_site/_test/helpers/parallel-logging-acceptance-proxy.js +106 -0
  95. package/_site/_test/helpers/parallel-logging-fix-r2-proxy.js +205 -0
  96. package/_site/_test/helpers/parallel-logging-integration-5025-env.js +432 -0
  97. package/_site/_test/helpers/parallel-memory-analyzer.js +81 -0
  98. package/_site/_test/helpers/parallel-memory-event-bridge.js +128 -0
  99. package/_site/_test/helpers/parallel-memory-shell.js +470 -0
  100. package/_site/_test/helpers/parallel-nav-isolation-env.js +389 -0
  101. package/_site/_test/helpers/parallel-nav-module-ui.js +186 -0
  102. package/_site/_test/helpers/parallel-nav-proxy.js +148 -0
  103. package/_site/_test/helpers/parallel-nav-shell.js +361 -0
  104. package/_site/_test/helpers/parallel-qa-engine-endpoint-guard.js +206 -0
  105. package/_site/_test/helpers/parallel-qa-engine-endpoint-isolate.js +257 -0
  106. package/_site/_test/helpers/parallel-retrieval-followup-corpus.js +293 -0
  107. package/_site/_test/helpers/parallel-retrieval-followup-next-session.js +70 -0
  108. package/_site/_test/helpers/parallel-retrieval-followup-r2-shell.js +737 -0
  109. package/_site/_test/helpers/parallel-retrieval-followup-r2-wb-host.js +82 -0
  110. package/_site/_test/helpers/parallel-retrieval-followup-shell.js +279 -0
  111. package/_site/_test/helpers/parallel-workbench-fixture.js +371 -0
  112. package/_site/_test/helpers/parallel-workbench-host.js +80 -0
  113. package/_site/_test/helpers/parallel-workbench-integration-5025-fixture.js +408 -0
  114. package/_site/_test/helpers/parallel-workbench-integration-5025-harness.js +593 -0
  115. package/_site/_test/helpers/parallel-workbench-integration-5025-host.js +70 -0
  116. package/_site/_test/helpers/parallel-workbench-integration-5025-launcher.js +240 -0
  117. package/_site/_test/helpers/parallel-workbench-integration-5025-runtime-harness.js +630 -0
  118. package/_site/_test/helpers/parallel-workbench-source-map.js +196 -0
  119. package/_site/_test/helpers/spawn-server.js +106 -0
  120. package/_site/_test/helpers/version-visibility-fixture.js +251 -0
  121. package/_site/_test/hook-runtime-endpoint-test.js +88 -88
  122. package/_site/_test/hook-status-repair-api-test.js +152 -152
  123. package/_site/_test/hook-trigger-test.js +85 -85
  124. package/_site/_test/hook-worktree-test.js +42 -42
  125. package/_site/_test/import-preflight-api-test.js +234 -234
  126. package/_site/_test/index-builder-test.js +41 -41
  127. package/_site/_test/index-error-display-contract-test.js +10 -10
  128. package/_site/_test/index-writer-concurrency-test.js +135 -135
  129. package/_site/_test/integration-adapters-test.js +262 -262
  130. package/_site/_test/integration-auto-repair-test.js +113 -113
  131. package/_site/_test/integration-capture-setup-test.js +118 -118
  132. package/_site/_test/integration-intent-test.js +81 -81
  133. package/_site/_test/integration-runtime-binding-a2-test.js +566 -566
  134. package/_site/_test/integration-runtime-binding-a3-test.js +227 -227
  135. package/_site/_test/integration-runtime-binding-test.js +473 -473
  136. package/_site/_test/integration-status-scan-test.js +29 -29
  137. package/_site/_test/integration-surface-coverage-test.js +164 -164
  138. package/_site/_test/kb-framework-test.js +57 -57
  139. package/_site/_test/kbpath-follow-test.js +63 -63
  140. package/_site/_test/knowledge-db-test.js +144 -144
  141. package/_site/_test/knowledge-engine-client-test.js +120 -109
  142. package/_site/_test/knowledge-language-control-test.js +170 -170
  143. package/_site/_test/knowledge-maintenance-test.js +40 -40
  144. package/_site/_test/knowledge-promotion-recovery-test.js +260 -260
  145. package/_site/_test/knowledge-query-test.js +54 -54
  146. package/_site/_test/knowledge-retrieval-service-test.js +77 -77
  147. package/_site/_test/knowledge-scopes-test.js +37 -37
  148. package/_site/_test/knowledge-storage-location-test.js +28 -28
  149. package/_site/_test/knowledge-storage-startup-test.js +52 -52
  150. package/_site/_test/knowledge-store-logs-supervision-test.js +89 -89
  151. package/_site/_test/launcher-readiness-test.js +80 -80
  152. package/_site/_test/legacy-claude-session-alias-test.js +106 -106
  153. package/_site/_test/legacy-routes-removed-test.js +47 -47
  154. package/_site/_test/legacy-workbench-exclusion-test.js +92 -92
  155. package/_site/_test/live-gateway-test.js +48 -48
  156. package/_site/_test/local-marketplace-test.js +16 -16
  157. package/_site/_test/log-redaction-test.js +58 -58
  158. package/_site/_test/logging-api-test.js +89 -89
  159. package/_site/_test/logging-sse-no-gap-test.js +88 -88
  160. package/_site/_test/logging-ui-test.js +107 -107
  161. package/_site/_test/markdown-delta-overlay-test.js +85 -85
  162. package/_site/_test/markdown-maintenance-api-test.js +75 -75
  163. package/_site/_test/markdown-maintenance-test.js +11 -11
  164. package/_site/_test/mcp-server-test.js +149 -149
  165. package/_site/_test/model-context-windows-test.js +89 -89
  166. package/_site/_test/module-agent-start-proxy-test.js +65 -65
  167. package/_site/_test/module-artifact-integrity-test.js +27 -27
  168. package/_site/_test/module-boundary-test.js +30 -30
  169. package/_site/_test/module-bridge-eventbridge-test.js +202 -202
  170. package/_site/_test/module-dynamic-port-test.js +118 -118
  171. package/_site/_test/module-index-proxy-test.js +33 -33
  172. package/_site/_test/module-model-configuration-test.js +44 -44
  173. package/_site/_test/module-process-lifecycle-test.js +35 -35
  174. package/_site/_test/module-stream-proxy-test.js +34 -34
  175. package/_site/_test/module-terminal-restart-test.js +63 -63
  176. package/_site/_test/module-wiring-unbind-race-test.js +59 -59
  177. package/_site/_test/native-context-integrations-test.js +86 -86
  178. package/_site/_test/non-release-ci-test.js +34 -34
  179. package/_site/_test/offline-boundary-isolation-test.js +32 -32
  180. package/_site/_test/orphaned-claim-recovery-test.js +80 -80
  181. package/_site/_test/package-boundary-test.js +43 -43
  182. package/_site/_test/package-startup-test.js +56 -56
  183. package/_site/_test/packaged-ui-smoke-test.js +88 -88
  184. package/_site/_test/parallel-ci-r9-posix-socket-budget-test.js +156 -0
  185. package/_site/_test/parallel-engine-advanced-eng005-test.js +136 -0
  186. package/_site/_test/parallel-engine-advanced-eng006-test.js +171 -0
  187. package/_site/_test/parallel-engine-advanced-eng007-reconcile-test.js +231 -0
  188. package/_site/_test/parallel-engine-advanced-eng009-test.js +208 -0
  189. package/_site/_test/parallel-engine-advanced-eng010-test.js +213 -0
  190. package/_site/_test/parallel-engine-advanced-eng011-ui-probe.js +459 -0
  191. package/_site/_test/parallel-engine-final-eng002-test.js +255 -0
  192. package/_site/_test/parallel-engine-final-eng007-test.js +269 -0
  193. package/_site/_test/parallel-engine-final-eng011-test.js +197 -0
  194. package/_site/_test/parallel-engine-final-eng012-test.js +354 -0
  195. package/_site/_test/parallel-knowledge-client-error-code-test.js +184 -0
  196. package/_site/_test/parallel-knowledge-engine-test.js +353 -0
  197. package/_site/_test/parallel-knowledge-retrieval-test.js +292 -0
  198. package/_site/_test/parallel-knowledge-vector-test.js +168 -0
  199. package/_site/_test/parallel-linux-ci-r7-log007-day-test.js +110 -0
  200. package/_site/_test/parallel-logging-acceptance-log003-test.js +224 -0
  201. package/_site/_test/parallel-logging-acceptance-log004-test.js +231 -0
  202. package/_site/_test/parallel-logging-acceptance-log005-test.js +208 -0
  203. package/_site/_test/parallel-logging-acceptance-log006-test.js +214 -0
  204. package/_site/_test/parallel-logging-acceptance-log007-test.js +223 -0
  205. package/_site/_test/parallel-logging-acceptance-log008-test.js +180 -0
  206. package/_site/_test/parallel-logging-fix-r2-crash-probe.js +271 -0
  207. package/_site/_test/parallel-logging-fix-r2-gap-test.js +294 -0
  208. package/_site/_test/parallel-logging-fix-r2-normalhook-test.js +330 -0
  209. package/_site/_test/parallel-logging-integration-5025-portability-test.js +554 -0
  210. package/_site/_test/parallel-memory-candidate-test.js +301 -0
  211. package/_site/_test/parallel-memory-manual-test.js +197 -0
  212. package/_site/_test/parallel-memory-scope-test.js +228 -0
  213. package/_site/_test/parallel-memory-source-test.js +227 -0
  214. package/_site/_test/parallel-memory-sync-test.js +238 -0
  215. package/_site/_test/parallel-memory-view-r8-reload-gate-test.js +123 -0
  216. package/_site/_test/parallel-nav-failure-test.js +119 -0
  217. package/_site/_test/parallel-nav-isolation-test.js +308 -0
  218. package/_site/_test/parallel-nav-isolation-vector-path-test.js +90 -0
  219. package/_site/_test/parallel-nav-offline-test.js +272 -0
  220. package/_site/_test/parallel-nav-operability-test.js +257 -0
  221. package/_site/_test/parallel-nav-switch-test.js +247 -0
  222. package/_site/_test/parallel-nav-theme-test.js +130 -0
  223. package/_site/_test/parallel-nav-viewport-test.js +310 -0
  224. package/_site/_test/parallel-qa-engine-endpoint-guard-test.js +273 -0
  225. package/_site/_test/parallel-retrieval-followup-citation-test.js +219 -0
  226. package/_site/_test/parallel-retrieval-followup-corpus-test.js +287 -0
  227. package/_site/_test/parallel-workbench-independent-host.js +262 -0
  228. package/_site/_test/parallel-workbench-integration-5025-abort-probe.js +340 -0
  229. package/_site/_test/parallel-workbench-integration-5025-drafts-probe.js +588 -0
  230. package/_site/_test/parallel-workbench-integration-5025-env-check.js +317 -0
  231. package/_site/_test/parallel-workbench-integration-5025-model-probe.js +342 -0
  232. package/_site/_test/parallel-workbench-integration-5025-ordering-probe.js +326 -0
  233. package/_site/_test/parallel-workbench-model-probe.js +336 -0
  234. package/_site/_test/parallel-workbench-offline-test.js +169 -0
  235. package/_site/_test/parallel-workbench-provenance-trace.js +134 -0
  236. package/_site/_test/parallel-workbench-source-match.js +206 -0
  237. package/_site/_test/parallel-workbench-standalone-turn.js +349 -0
  238. package/_site/_test/path-consistency-test.js +151 -151
  239. package/_site/_test/pending-sweep-test.js +9 -9
  240. package/_site/_test/post-commit-automation-test.js +87 -87
  241. package/_site/_test/pr-consumer-contract-test.js +55 -55
  242. package/_site/_test/product-brand-contract-test.js +25 -25
  243. package/_site/_test/product-diagnostics-ui-test.js +93 -93
  244. package/_site/_test/product-empty-state-test.js +148 -0
  245. package/_site/_test/product-import-ui-test.js +219 -104
  246. package/_site/_test/product-navigation-test.js +152 -0
  247. package/_site/_test/product-progress-status-test.js +84 -84
  248. package/_site/_test/project-delete-recovery-test.js +64 -64
  249. package/_site/_test/project-domain-create-test.js +91 -0
  250. package/_site/_test/project-domain-scope-retrieval-test.js +214 -0
  251. package/_site/_test/project-git-init-confirm-test.js +115 -0
  252. package/_site/_test/project-goal-editor-test.js +144 -144
  253. package/_site/_test/project-import-duplicate-alias-test.js +134 -0
  254. package/_site/_test/project-import-unicode-restart-test.js +140 -0
  255. package/_site/_test/project-lifecycle-transaction-test.js +106 -106
  256. package/_site/_test/project-module-partial-recovery-test.js +222 -0
  257. package/_site/_test/project-remove-running-guard-test.js +79 -79
  258. package/_site/_test/project-store-test.js +90 -90
  259. package/_site/_test/project-unbind-late-read-ui-test.js +250 -0
  260. package/_site/_test/project-unbind-writer-guard-test.js +231 -0
  261. package/_site/_test/prompt-settings-test.js +115 -115
  262. package/_site/_test/protected-architecture-gate-test.js +122 -122
  263. package/_site/_test/refactor-characterization-test.js +36 -36
  264. package/_site/_test/registry-events-test.js +38 -38
  265. package/_site/_test/release-version-sync-test.js +115 -115
  266. package/_site/_test/requirement-binding-test.js +113 -113
  267. package/_site/_test/requirement-recorder-test.js +173 -173
  268. package/_site/_test/run-all-tests.js +173 -161
  269. package/_site/_test/runtime-endpoint-test.js +64 -64
  270. package/_site/_test/scanner-test.js +83 -83
  271. package/_site/_test/server-security-test.js +96 -96
  272. package/_site/_test/sessions-stream-test.js +93 -93
  273. package/_site/_test/shared-contracts-test.js +58 -58
  274. package/_site/_test/shared-scope-root-binding-test.js +74 -67
  275. package/_site/_test/simple-import-test.js +98 -98
  276. package/_site/_test/startup-analysis-disabled-test.js +16 -16
  277. package/_site/_test/storage-foundation-test.js +78 -78
  278. package/_site/_test/structured-logger-test.js +101 -101
  279. package/_site/_test/t07b-cln-005-coverage-test.js +212 -0
  280. package/_site/_test/team-knowledge-store-sparse-checkout-test.js +196 -196
  281. package/_site/_test/team-knowledge-store-test.js +132 -132
  282. package/_site/_test/test-server-cleanup-test.js +35 -35
  283. package/_site/_test/test-server-module-isolation-test.js +37 -37
  284. package/_site/_test/tracking-start-test.js +144 -144
  285. package/_site/_test/vector-storage-root-test.js +75 -75
  286. package/_site/_test/version-visibility-browser-probe.js +249 -0
  287. package/_site/_test/version-visibility-test.js +92 -0
  288. package/_site/_test/workbench-context-receipts-test.js +22 -22
  289. package/_site/_test/workbench-permission-test.js +117 -117
  290. package/_site/_test/zcode-capture-integration-test.js +112 -112
  291. package/_site/lib/ai-profile-resolver.js +78 -78
  292. package/_site/lib/ai-vendor-presets.js +83 -83
  293. package/_site/lib/ai-workspace.js +104 -104
  294. package/_site/lib/atomic-file.js +204 -204
  295. package/_site/lib/automation-config.js +140 -140
  296. package/_site/lib/bridge-adapter.js +260 -260
  297. package/_site/lib/bridge-consumer-service.js +402 -402
  298. package/_site/lib/capture-hook-config.js +108 -108
  299. package/_site/lib/claude-cli-runner.js +1599 -1599
  300. package/_site/lib/cli-instances.js +43 -43
  301. package/_site/lib/codex-context-status.js +17 -17
  302. package/_site/lib/codex-notify-config.js +193 -193
  303. package/_site/lib/commit-conversation-binder.js +247 -247
  304. package/_site/lib/commit-processing-ledger.js +27 -27
  305. package/_site/lib/commit-prompt.js +202 -202
  306. package/_site/lib/commit-reconciler.js +444 -444
  307. package/_site/lib/context-pack-builder.js +299 -299
  308. package/_site/lib/contracts.js +291 -291
  309. package/_site/lib/conversation-exclusions.js +204 -204
  310. package/_site/lib/conversation-query-service.js +161 -161
  311. package/_site/lib/conversation-store.js +387 -387
  312. package/_site/lib/data-dir.js +13 -13
  313. package/_site/lib/embedding-service.js +85 -85
  314. package/_site/lib/engine-connection.js +93 -93
  315. package/_site/lib/engine-knowledge-client.js +76 -72
  316. package/_site/lib/evidence-bundle.js +228 -228
  317. package/_site/lib/folder-picker-output.js +24 -24
  318. package/_site/lib/git-path.js +14 -14
  319. package/_site/lib/git-runner.js +62 -62
  320. package/_site/lib/github-team-store.js +1175 -1175
  321. package/_site/lib/hook-manager.js +203 -203
  322. package/_site/lib/index-builder.js +157 -157
  323. package/_site/lib/index-service.js +173 -173
  324. package/_site/lib/integration-auto-repair.js +77 -77
  325. package/_site/lib/integration-installer.js +1240 -1240
  326. package/_site/lib/integration-intent.js +88 -88
  327. package/_site/lib/integration-status-scan.js +99 -99
  328. package/_site/lib/integration-status-worker.js +14 -14
  329. package/_site/lib/kb-framework.js +191 -191
  330. package/_site/lib/kb-validator.js +124 -124
  331. package/_site/lib/knowledge-db.js +363 -363
  332. package/_site/lib/knowledge-promotion.js +435 -435
  333. package/_site/lib/knowledge-retrieval-service.js +401 -401
  334. package/_site/lib/knowledge-schema.js +121 -121
  335. package/_site/lib/knowledge-tool-runtime.js +366 -366
  336. package/_site/lib/live-gateway.js +78 -78
  337. package/_site/lib/llm-client.js +173 -173
  338. package/_site/lib/markdown-knowledge-indexer.js +230 -230
  339. package/_site/lib/model-context-windows.js +82 -82
  340. package/_site/lib/module-bridge.js +874 -874
  341. package/_site/lib/module-port-resolver.js +57 -57
  342. package/_site/lib/post-commit-automation.js +141 -141
  343. package/_site/lib/product-data.js +35 -35
  344. package/_site/lib/project-lifecycle-service.js +554 -554
  345. package/_site/lib/project-registry-store.js +129 -129
  346. package/_site/lib/project-store.js +268 -268
  347. package/_site/lib/prompt-registry.js +148 -148
  348. package/_site/lib/public-version-info.js +37 -0
  349. package/_site/lib/registry-events.js +16 -16
  350. package/_site/lib/requirement-adapters.js +10 -10
  351. package/_site/lib/requirement-binder.js +112 -112
  352. package/_site/lib/requirement-recorder.js +278 -278
  353. package/_site/lib/runtime-control.js +89 -89
  354. package/_site/lib/runtime-endpoint.js +160 -160
  355. package/_site/lib/scanner.js +298 -298
  356. package/_site/lib/server-app.js +1672 -1664
  357. package/_site/lib/settings-store.js +153 -153
  358. package/_site/lib/storage-layout.js +166 -166
  359. package/_site/lib/structured-logger.js +574 -574
  360. package/_site/lib/zcode-context-integration.js +60 -60
  361. package/_site/scripts/codex-notify-fanout.cjs +95 -95
  362. package/_site/scripts/folder-picker.ps1 +156 -156
  363. package/_site/scripts/hook-trigger.js +158 -158
  364. package/_site/scripts/install-module-candidates.js +69 -69
  365. package/_site/scripts/pack-module-candidates.js +89 -89
  366. package/_site/scripts/sync-product-content.js +28 -28
  367. package/_site/scripts/sync-release-version.js +164 -164
  368. package/_site/scripts/vendor-modules.js +49 -49
  369. package/_site/scripts/verify-module-runtime.js +50 -50
  370. package/_site/scripts/verify-product-runtime.js +36 -36
  371. package/_site/scripts/verify-retrieval-gold.js +83 -83
  372. package/_site/server.js +15 -15
  373. package/_site/start.bat +26 -26
  374. package/_site/stop.bat +11 -11
  375. package/bin/project-knowledge-integrations.js +254 -254
  376. package/bin/project-knowledge-kb.js +67 -67
  377. package/bin/project-knowledge-mcp.js +201 -201
  378. package/bin/project-knowledge.js +269 -170
  379. package/claude-prompts.json +21 -21
  380. package/docs/README.zh-CN.md +207 -205
  381. package/docs/assets/architecture.svg +181 -181
  382. package/docs/assets/logo.svg +49 -49
  383. package/docs/fresh-v5-start.md +44 -44
  384. package/docs/leader-glm-workbench-playbook.md +122 -122
  385. package/docs/project-registry-schema.md +33 -33
  386. package/docs/release-5.0.16-acceptance.md +176 -176
  387. package/docs/release-5.0.17-acceptance.md +117 -117
  388. package/docs/release-5.0.19-acceptance.md +39 -39
  389. package/docs/team-knowledge-mode-a-plan.md +73 -73
  390. package/docs/testing-strategy.md +33 -33
  391. package/module-runtime-manifest.json +66 -63
  392. package/package.json +113 -110
  393. package/plugins/project-knowledge/.claude-plugin/plugin.json +1 -1
  394. package/plugins/project-knowledge/.codex-plugin/plugin.json +1 -1
  395. package/plugins/project-knowledge/.mcp.json +1 -1
  396. package/templates/change.md +30 -30
  397. package/templates/project-readme.md +52 -52
  398. package/ui/index.html +3 -2
  399. package/ui/version-info.css +44 -0
  400. package/ui/version-info.js +24 -0
  401. package/vendor-manifest.json +55 -55
@@ -0,0 +1,470 @@
1
+ 'use strict';
2
+ // _site/_test/helpers/parallel-memory-shell.js
3
+ //
4
+ // Lane harness for the P-MEMORY-01 memory lane.
5
+ //
6
+ // Every case runs against a real, isolated product instance:
7
+ // * its own port, data dir, knowledge root and Bridge journal home (the
8
+ // shared spawn-server helper already isolates those);
9
+ // * the REAL vendored knowledge engine, in-process, with a declared
10
+ // stand-in analyzer (helpers/parallel-memory-analyzer.js) that only
11
+ // replaces the model step;
12
+ // * a pass-through proxy in front of the engine, so the product's own
13
+ // runtime token reaches the engine the way it does in production;
14
+ // * real HTTP module services for terminal / vector-hub / event-bridge;
15
+ // * a real Chrome (CDP) in its own profile.
16
+ //
17
+ // Nothing here reaches the developer's live 5757/5790/8787/8790 endpoints,
18
+ // the real HOME, the real knowledge directories or the real memories.
19
+
20
+ const assert = require('node:assert/strict');
21
+ const crypto = require('node:crypto');
22
+ const fs = require('node:fs');
23
+ const path = require('node:path');
24
+ const { spawnSync } = require('node:child_process');
25
+
26
+ const { spawnServer } = require('../helpers/spawn-server');
27
+ const { findChrome } = require('../helpers/find-chrome');
28
+ const { launchCdpBrowser, waitFor } = require('../helpers/cdp-browser');
29
+ const { attachNetworkCapture } = require('../helpers/cdp-network-capture');
30
+ const { createModuleFixture, createUpstreamProxy } = require('../helpers/module-fixture');
31
+ const freePort = require('../helpers/free-port');
32
+ const { createMemoryStandinAnalyzer } = require('./parallel-memory-analyzer');
33
+ const { createEventBridgeStandin } = require('./parallel-memory-event-bridge');
34
+ const { applyDriverIsolation } = require('./parallel-qa-engine-endpoint-isolate');
35
+ const { guardedCreateEngineServer, createEngineVectorStandin } = require('./parallel-qa-engine-endpoint-guard');
36
+
37
+ const ROOT = path.resolve(__dirname, '../../..');
38
+ const LIVE_PORTS = new Set([5757, 5790, 8787, 8790]);
39
+
40
+ function git(cwd, args) {
41
+ const result = spawnSync('git', ['-C', cwd, ...args], { encoding: 'utf8', windowsHide: true, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
42
+ assert.equal(result.status, 0, `git ${args.join(' ')} failed: ${result.stderr}`);
43
+ return String(result.stdout || '').trim();
44
+ }
45
+
46
+ /** A real Git repository with real commits: the product imports it for real. */
47
+ function makeRepo(root, name, files = { 'README.md': `# ${name}\n` }) {
48
+ const repo = path.join(root, name);
49
+ fs.mkdirSync(repo, { recursive: true });
50
+ git(repo, ['init', '-q', '-b', 'main']);
51
+ git(repo, ['config', 'user.email', 'parallel-memory@local.invalid']);
52
+ git(repo, ['config', 'user.name', 'Parallel Memory Regression']);
53
+ git(repo, ['config', 'commit.gpgsign', 'false']);
54
+ for (const [file, content] of Object.entries(files)) fs.writeFileSync(path.join(repo, file), content, 'utf8');
55
+ git(repo, ['add', '.']);
56
+ git(repo, ['commit', '-qm', 'baseline']);
57
+ return { path: repo, headCommit: git(repo, ['rev-parse', 'HEAD']) };
58
+ }
59
+
60
+ /**
61
+ * A real follow-up commit in an existing repository.
62
+ *
63
+ * The engine registers a project with `trackingStartCommit` set to the commit
64
+ * that was HEAD at import time, and it treats a run for that very commit as
65
+ * already analysed. A maintenance run therefore has to target a commit that
66
+ * was made after the import — exactly the production flow.
67
+ */
68
+ function commitFile(repo, file, content, message = 'follow-up') {
69
+ const full = path.join(repo.path, file);
70
+ fs.mkdirSync(path.dirname(full), { recursive: true });
71
+ fs.writeFileSync(full, content, 'utf8');
72
+ git(repo.path, ['add', '.']);
73
+ git(repo.path, ['commit', '-qm', message]);
74
+ repo.headCommit = git(repo.path, ['rev-parse', 'HEAD']);
75
+ return repo.headCommit;
76
+ }
77
+
78
+ async function startHarness({ tag, evidenceDir, viewport = { width: 1600, height: 900 } } = {}) {
79
+ // Full driver isolation FIRST, before any product module load or fixture
80
+ // directory: the environment is rebuilt from a system whitelist with every
81
+ // product surface pointed at a per-run layout. Chrome is captured from the
82
+ // REAL environment before the wipe and carried through as KB_CHROME_PATH.
83
+ const applied = applyDriverIsolation({ prefix: `pk-qa-memory-${tag}`, captureChrome: true });
84
+ const tempRoot = applied.layout.temp;
85
+
86
+ const fixture = fs.mkdtempSync(path.join(tempRoot, `pk-parallel-memory-${tag}-`));
87
+ const evidence = evidenceDir || path.join(fixture, 'evidence');
88
+ fs.mkdirSync(evidence, { recursive: true });
89
+ const dataDir = path.join(fixture, 'data');
90
+ const knowledgeRoot = path.join(fixture, 'knowledge');
91
+ fs.mkdirSync(knowledgeRoot, { recursive: true });
92
+
93
+ const plan = { document: '', memoryCandidates: [] };
94
+ const engineToken = crypto.randomBytes(24).toString('hex');
95
+ // OWN fixtures exist BEFORE the engine. The coordinator ignores env and its
96
+ // defaults are LIVE 8787/8790, so the engine must be constructed with an
97
+ // explicit OWN vector endpoint (the full-contract stand-in, because run
98
+ // maintenance ends in POST /api/sync which the module fixture lacks) and the
99
+ // lane's own event bridge.
100
+ const engineVector = createEngineVectorStandin({ label: 'memory-shell-engine-vector' });
101
+ await engineVector.ready;
102
+ const terminal = createModuleFixture({ kind: 'terminal', tag: `${tag}-terminal` });
103
+ const vectorHub = createModuleFixture({ kind: 'vectorHub', tag: `${tag}-vectorhub` });
104
+ // The shared event-bridge fixture answers with `bridge-1`, a journal id the
105
+ // engine rejects, so the project never reaches the engine. This lane uses
106
+ // its own stand-in that derives the real `sha256:` workspace id.
107
+ const eventBridge = await createEventBridgeStandin({ tag: `${tag}-eventbridge` });
108
+ await terminal.start();
109
+ await vectorHub.start();
110
+ await eventBridge.start();
111
+
112
+ const engine = guardedCreateEngineServer({
113
+ dataDir: path.join(fixture, 'engine'),
114
+ runtimeToken: engineToken,
115
+ debug: true,
116
+ consume: false,
117
+ analyzer: createMemoryStandinAnalyzer({ plan }),
118
+ vectorUrl: engineVector.url,
119
+ bridgeUrl: eventBridge.url,
120
+ });
121
+ await engine.ready;
122
+ await new Promise(resolve => engine.server.listen(0, '127.0.0.1', resolve));
123
+ const engineUrl = `http://127.0.0.1:${engine.server.address().port}`;
124
+ assert.equal(LIVE_PORTS.has(engine.server.address().port), false, 'the lane engine must never use a live port');
125
+ const engineProxy = createUpstreamProxy({ target: engineUrl, token: engineToken, tag: 'engine' });
126
+ await engineProxy.start();
127
+
128
+ const port = await freePort();
129
+ const base = `http://127.0.0.1:${port}`;
130
+ const server = spawnServer({
131
+ root: ROOT,
132
+ port,
133
+ dataDir,
134
+ tag: `parallel-memory-${tag}`,
135
+ analysisOwner: 'engine',
136
+ extraEnv: {
137
+ KB_MODULES_REGISTER: '1',
138
+ KB_MODULES_AUTOSTART: '0',
139
+ KB_TERMINAL_URL: terminal.url,
140
+ KB_VECTORHUB_URL: vectorHub.url,
141
+ KB_EVENTBRIDGE_URL: eventBridge.url,
142
+ KB_KNOWLEDGE_ENGINE_URL: engineProxy.url,
143
+ },
144
+ });
145
+
146
+ const productApi = async (method, route, body) => {
147
+ const response = await fetch(base + route, {
148
+ method,
149
+ headers: body === undefined ? undefined : { 'Content-Type': 'application/json' },
150
+ body: body === undefined ? undefined : JSON.stringify(body),
151
+ signal: AbortSignal.timeout(20000),
152
+ });
153
+ return { status: response.status, body: await response.json().catch(() => null) };
154
+ };
155
+
156
+ const engineApi = async (method, route, body) => {
157
+ const response = await fetch(engineUrl + route, {
158
+ method,
159
+ headers: {
160
+ 'Content-Type': 'application/json',
161
+ ...(engineToken ? { Authorization: `Bearer ${engineToken}` } : {}),
162
+ },
163
+ body: body === undefined ? undefined : JSON.stringify(body),
164
+ signal: AbortSignal.timeout(20000),
165
+ });
166
+ return { status: response.status, body: await response.json().catch(() => null) };
167
+ };
168
+
169
+ await waitFor(async () => {
170
+ try { return (await productApi('GET', '/api/health')).status === 200; } catch { return false; }
171
+ }, 'the isolated product instance', 30000);
172
+ const settings = await productApi('PATCH', '/api/settings', { knowledge: { rootPath: knowledgeRoot } });
173
+ assert.equal(settings.status, 200, `the isolated instance accepts its own knowledge root: ${JSON.stringify(settings.body)}`);
174
+
175
+ let browser = null;
176
+ let network = null;
177
+ try {
178
+ browser = await launchCdpBrowser({
179
+ chrome: findChrome(),
180
+ profileDir: path.join(fixture, 'browser'),
181
+ url: `${base}/`,
182
+ width: viewport.width,
183
+ height: viewport.height,
184
+ });
185
+ await browser.setViewport(viewport.width, viewport.height);
186
+ await browser.send('Network.enable');
187
+ network = attachNetworkCapture(browser);
188
+ } catch (error) {
189
+ await server.cleanup();
190
+ await engineProxy.close();
191
+ await terminal.close();
192
+ await vectorHub.close();
193
+ await eventBridge.close();
194
+ await engine.close().catch(() => {});
195
+ fs.rmSync(fixture, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
196
+ throw error;
197
+ }
198
+
199
+ const run = expression => browser.evaluate(expression);
200
+ const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
201
+ const reloadLog = [];
202
+
203
+ /** Ask the shell to read the project registry again. */
204
+ const requestRegistryRefresh = () => run("document.dispatchEvent(new Event('visibilitychange'))");
205
+
206
+ /** A real page reload, so "it survives a refresh" is proven by the browser. */
207
+ const reload = async () => {
208
+ // Mark the OUTGOING document first. Page.reload is acknowledged before the
209
+ // navigation commits, and Runtime.evaluate keeps answering in the old
210
+ // context while it stays attached — so a bare readyState gate is satisfied
211
+ // by the outgoing page (CI 40062048045: the nav click right after
212
+ // reload() was dispatched into the commit gap and lost, and the memory
213
+ // view never activated). The marker exists only in the old context, so
214
+ // the gate below can only pass on the FRESH document; the active-view
215
+ // clause additionally proves the product's synchronous boot finished
216
+ // (ui/product.js attaches its click delegation before the boot setView
217
+ // that marks the initial view active).
218
+ const startedAt = Date.now();
219
+ await run('window.__pkShellReloadMark = Date.now(), true');
220
+ await browser.send('Page.reload', {});
221
+ await waitFor(
222
+ () => run("document.readyState === 'complete' && typeof window.__pkShellReloadMark === 'undefined' && document.querySelector('.view.active') !== null"),
223
+ 'the reloaded page is the fresh document and its boot finished',
224
+ 20000,
225
+ );
226
+ reloadLog.push({ at: new Date().toISOString(), freshBootGateMs: Date.now() - startedAt });
227
+ };
228
+
229
+ /**
230
+ * Readiness snapshot for failure diagnostics: what the page really looks
231
+ * like when a navigation assertion is about to fail (small metadata).
232
+ */
233
+ const navigationState = async () => {
234
+ try {
235
+ return await run(`(() => ({
236
+ readyState: document.readyState,
237
+ href: location.href,
238
+ activeView: (document.querySelector('.view.active') || {}).id || null,
239
+ activeNav: document.querySelector('nav [data-view].active') ? document.querySelector('nav [data-view].active').dataset.view : null,
240
+ reloadMark: typeof window.__pkShellReloadMark,
241
+ openDialogs: [...document.querySelectorAll('dialog[open]')].map(dialog => dialog.id),
242
+ toastHidden: document.getElementById('toast') ? document.getElementById('toast').hidden : null,
243
+ toastText: document.getElementById('toast') ? document.getElementById('toast').textContent.trim().slice(0, 80) : null,
244
+ }))()`);
245
+ } catch (error) {
246
+ return { unreachable: String(error && error.message || error) };
247
+ }
248
+ };
249
+
250
+ const pressBackspace = async (count = 1) => {
251
+ for (let index = 0; index < count; index += 1) await pressKey('Backspace', { code: 'Backspace', keyCode: 8 });
252
+ };
253
+
254
+ /** Set a select's value and fire the real change event the shell listens to. */
255
+ const selectOption = async (selector, value) => {
256
+ const changed = await run(`(() => {
257
+ const el = document.querySelector(${JSON.stringify(selector)});
258
+ if (!el) return { missing: true };
259
+ el.value = ${JSON.stringify(value)};
260
+ el.dispatchEvent(new Event('change', { bubbles: true }));
261
+ return { value: el.value };
262
+ })()`);
263
+ assert.ok(changed && !changed.missing, `the select ${selector} must exist`);
264
+ assert.equal(changed.value, value, `the select ${selector} must accept the value ${value}`);
265
+ };
266
+
267
+ /** A native pointer click: the hit test runs first and must resolve to the target. */
268
+ const nativeClick = async selector => {
269
+ const probe = await run(`(() => {
270
+ const el = document.querySelector(${JSON.stringify(selector)});
271
+ if (!el) return { missing: true };
272
+ const rect = el.getBoundingClientRect();
273
+ if (rect.width <= 0 || rect.height <= 0) return { invisible: true };
274
+ const x = rect.left + rect.width / 2;
275
+ const y = rect.top + rect.height / 2;
276
+ const hit = document.elementFromPoint(x, y);
277
+ return { x, y, hitIsTarget: Boolean(hit && (hit === el || el.contains(hit))), label: (el.textContent || '').trim().slice(0, 40) };
278
+ })()`);
279
+ assert.ok(probe && !probe.missing, `the control ${selector} must exist in the page`);
280
+ assert.ok(!probe.invisible, `the control ${selector} must be visible`);
281
+ assert.ok(probe.hitIsTarget, `the control ${selector} must be the hit target; something else is on top`);
282
+ const common = { x: probe.x, y: probe.y, button: 'left', clickCount: 1 };
283
+ await browser.send('Input.dispatchMouseEvent', { type: 'mouseMoved', x: probe.x, y: probe.y, button: 'none', clickCount: 0 });
284
+ await browser.send('Input.dispatchMouseEvent', { type: 'mousePressed', ...common });
285
+ await browser.send('Input.dispatchMouseEvent', { type: 'mouseReleased', ...common });
286
+ return probe;
287
+ };
288
+
289
+ const pressKey = async (key, { code, keyCode, text } = {}) => {
290
+ const base = { key, code: code || key, windowsVirtualKeyCode: keyCode, nativeVirtualKeyCode: keyCode };
291
+ await browser.send('Input.dispatchKeyEvent', { type: text ? 'keyDown' : 'rawKeyDown', ...base, text });
292
+ await browser.send('Input.dispatchKeyEvent', { type: 'keyUp', ...base });
293
+ };
294
+ const pressTab = () => pressKey('Tab', { code: 'Tab', keyCode: 9 });
295
+ const pressEnter = () => pressKey('Enter', { code: 'Enter', keyCode: 13, text: '\r' });
296
+
297
+ /** Type into a focused field with real key events. */
298
+ const typeText = async text => {
299
+ for (const character of String(text)) {
300
+ const upper = character.toUpperCase();
301
+ const isLower = character >= 'a' && character <= 'z';
302
+ const isUpper = character >= 'A' && character <= 'Z';
303
+ const isDigit = character >= '0' && character <= '9';
304
+ const code = isLower ? `Key${upper}` : isUpper ? `Key${character}` : isDigit ? `Digit${character}` : '';
305
+ const keyCode = isLower ? upper.charCodeAt(0) : isUpper || isDigit ? character.charCodeAt(0) : 0;
306
+ const base = { key: character, code, windowsVirtualKeyCode: keyCode, nativeVirtualKeyCode: keyCode };
307
+ await browser.send('Input.dispatchKeyEvent', { type: 'keyDown', ...base, text: character, unmodifiedText: character });
308
+ await browser.send('Input.dispatchKeyEvent', { type: 'keyUp', ...base });
309
+ }
310
+ };
311
+
312
+ /** Import a real project through the real product API. */
313
+ const importProject = async (repo, displayName, { domainId } = {}) => {
314
+ const knowledgePath = path.join(knowledgeRoot, displayName);
315
+ fs.mkdirSync(knowledgePath, { recursive: true });
316
+ const result = await productApi('POST', '/api/projects/import', { localPath: repo.path, knowledgePath, displayName });
317
+ assert.equal(result.status, 201, `the project import must succeed: ${JSON.stringify(result.body)}`);
318
+ const projectId = result.body.projectId;
319
+ if (domainId) {
320
+ const patched = await productApi('PATCH', `/api/projects/${encodeURIComponent(projectId)}`, { domainId });
321
+ assert.equal(patched.status, 200, `the domain binding must succeed: ${JSON.stringify(patched.body)}`);
322
+ }
323
+ return { projectId, project: result.body.project, knowledgePath, modules: result.body.modules };
324
+ };
325
+
326
+ /** Add a real domain to the brain of the isolated instance. */
327
+ const addDomain = async name => {
328
+ const result = await productApi('POST', '/api/domains', { name });
329
+ assert.equal(result.status, 201, `the brain domain must be accepted: ${JSON.stringify(result.body)}`);
330
+ return result.body.domain;
331
+ };
332
+
333
+ /** The knowledge directory the engine uses for the brain scope. */
334
+ const brainScopePath = () => {
335
+ const scope = engine.store.state.sharedScopes.find(entry => entry.kind === 'brain');
336
+ assert.ok(scope, 'the engine must know the brain scope');
337
+ return scope.knowledgePath;
338
+ };
339
+
340
+ /** The knowledge directory the engine uses for one domain scope. */
341
+ const domainScopePath = domainId => {
342
+ const scope = engine.store.state.sharedScopes.find(entry => entry.kind === 'domain' && entry.id === domainId);
343
+ assert.ok(scope, `the engine must know the domain scope ${domainId}`);
344
+ return scope.knowledgePath;
345
+ };
346
+
347
+ /** Every memory the product's own snapshot endpoint serves. */
348
+ const productMemories = async () => {
349
+ const snapshot = await productApi('GET', '/api/engine/snapshot?summary=1&limit=50');
350
+ assert.equal(snapshot.status, 200, `the product snapshot must be readable: ${JSON.stringify(snapshot.body)}`);
351
+ return snapshot.body.memories || [];
352
+ };
353
+
354
+ /** The memories the engine would inject into a task for one project. */
355
+ const injectedMemories = async projectId => {
356
+ const context = await engineApi('POST', '/api/context', { projectId, query: '长期记忆', task: 'memory-lane' });
357
+ assert.equal(context.status, 200, `the engine context must be readable: ${JSON.stringify(context.body)}`);
358
+ return context.body.memories || [];
359
+ };
360
+
361
+ /**
362
+ * A memory candidate that satisfies the engine's own provenance gate: it
363
+ * quotes the real human event, the quote contains the memory text, and it
364
+ * declares why the text is a durable, cross-project owner preference.
365
+ */
366
+ const memoryCandidate = ({ text, event, scopeType = 'global' }) => ({
367
+ text,
368
+ quote: text,
369
+ scopeType,
370
+ sourceEventId: event.eventId,
371
+ sourceHash: event.contentHash,
372
+ eligibility: {
373
+ durable: true,
374
+ crossProject: true,
375
+ reason: '人工明确表达的长期偏好',
376
+ scopeReason: scopeType === 'global' ? '适用于所有领域与项目' : '适用于指定领域',
377
+ },
378
+ });
379
+
380
+ /**
381
+ * Drive the real pipeline to a candidate: a real follow-up commit, a real
382
+ * conversation event bound to it, the stand-in analyzer's manifest and the
383
+ * engine's own promotion and capture.
384
+ */
385
+ const produceCandidate = async ({ repo, projectId, text, scopeType = 'global', inputOrigin = 'human', file = 'src/candidate.js' }) => {
386
+ const head = commitFile(repo, file, `// ${text}\n`, 'candidate commit');
387
+ const event = await ingestUserEvent({
388
+ projectId,
389
+ commitSha: head,
390
+ content: `人工要求:${text}`,
391
+ inputOrigin,
392
+ });
393
+ plan.document = `# 冻结证据\n\n${text}\n`;
394
+ plan.memoryCandidates = [memoryCandidate({ text, event, scopeType })];
395
+ const run = await triggerRun(projectId, head);
396
+ return { run, event, commitSha: head, capture: run.memoryCapture };
397
+ };
398
+
399
+ /**
400
+ * Append a real conversation event to the engine's own conversation store.
401
+ * The engine's own binder freezes it into the commit snapshot, and the
402
+ * engine's own eligibility gate reads its inputOrigin.
403
+ */
404
+ const ingestUserEvent = async ({ projectId, commitSha, content, inputOrigin = 'human', turnId, eventId }) => {
405
+ const id = eventId || `event-${crypto.randomUUID()}`;
406
+ const turn = turnId || `turn-${crypto.randomUUID()}`;
407
+ const result = await engine.coordinator.conversations.appendEvent(projectId, {
408
+ eventId: id,
409
+ sequence: 1,
410
+ source: 'claude-code',
411
+ eventType: 'user_prompt',
412
+ role: 'user',
413
+ inputOrigin,
414
+ content,
415
+ sessionId: `session-${projectId}`,
416
+ turnId: turn,
417
+ capturedAt: new Date().toISOString(),
418
+ identityConfidence: 'exact',
419
+ explicitCommitSha: commitSha,
420
+ });
421
+ return { eventId: id, turnId: turn, contentHash: result.event.contentHash, inputOrigin: result.event.inputOrigin };
422
+ };
423
+
424
+ /** Run the real maintenance pipeline for a commit and wait for the run. */
425
+ const triggerRun = async (projectId, commitSha, timeoutMs = 60000) => {
426
+ const started = await engineApi('POST', '/api/runs', { projectId, commitSha });
427
+ assert.equal(started.status, 200, `the run must be accepted: ${JSON.stringify(started.body)}`);
428
+ const runId = started.body.run.runId;
429
+ const deadline = Date.now() + timeoutMs;
430
+ let last = null;
431
+ while (Date.now() < deadline) {
432
+ const current = await engineApi('GET', `/api/runs/${encodeURIComponent(runId)}`);
433
+ last = current.body && current.body.run;
434
+ if (last && ['succeeded', 'failed'].includes(last.state)) {
435
+ if (last.state === 'failed') throw new Error(`the run failed: ${JSON.stringify(last.error)}`);
436
+ return last;
437
+ }
438
+ if (last && last.promotedAt && last.memoryCapture) return last;
439
+ await wait(150);
440
+ }
441
+ throw new Error(`the run did not finish in time: ${JSON.stringify(last)}`);
442
+ };
443
+
444
+ const cleanup = async () => {
445
+ await browser?.close();
446
+ await server.cleanup();
447
+ await engineProxy.close();
448
+ await terminal.close();
449
+ await vectorHub.close();
450
+ await eventBridge.close();
451
+ await engine.close().catch(() => {});
452
+ await engineVector.close().catch(() => {});
453
+ fs.rmSync(fixture, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
454
+ };
455
+
456
+ return {
457
+ fixture, evidence, dataDir, knowledgeRoot, tempRoot, plan,
458
+ base, server, productApi, engineApi, engine, engineUrl, engineProxy,
459
+ terminal, vectorHub, eventBridge, engineVector,
460
+ browser, run, wait, waitFor, network, reloadLog, navigationState,
461
+ requestRegistryRefresh, reload, pressBackspace, selectOption,
462
+ nativeClick, pressKey, pressTab, pressEnter, typeText,
463
+ importProject, addDomain, ingestUserEvent, triggerRun,
464
+ brainScopePath, domainScopePath, productMemories, injectedMemories,
465
+ memoryCandidate, produceCandidate,
466
+ cleanup,
467
+ };
468
+ }
469
+
470
+ module.exports = { startHarness, makeRepo, commitFile, ROOT };