@sanqianx/project-knowledge 5.0.23 → 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 -1346
  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 +70 -67
  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
@@ -1,118 +1,118 @@
1
- 'use strict';
2
- const assert = require('node:assert/strict');
3
- const http = require('node:http');
4
- const { resolveModuleUrl } = require('../lib/module-port-resolver');
5
- const { ModuleBridge } = require('../lib/module-bridge');
6
-
7
- const countingProbe = outcome => {
8
- const seen = [];
9
- return {
10
- probe: async url => { seen.push(url); return outcome; },
11
- get seen() { return seen; },
12
- get calls() { return seen.length; },
13
- };
14
- };
15
-
16
- const countingPortFree = isFree => {
17
- const seen = [];
18
- return {
19
- portFree: async port => { seen.push(port); return isFree(port); },
20
- get seen() { return seen; },
21
- get calls() { return seen.length; },
22
- };
23
- };
24
-
25
- (async () => {
26
- // A: healthy module on the preferred port is reused without any port scan.
27
- {
28
- const probe = countingProbe('module');
29
- const portFree = countingPortFree(() => false);
30
- const resolved = await resolveModuleUrl({ kind: 'terminal', preferredUrl: 'http://127.0.0.1:5760', explicit: false, portFree: portFree.portFree, probe: probe.probe });
31
- assert.equal(resolved.source, 'reused');
32
- assert.equal(resolved.url, 'http://127.0.0.1:5760');
33
- assert.equal(resolved.port, 5760);
34
- assert.deepEqual(probe.seen, ['http://127.0.0.1:5760']);
35
- assert.equal(portFree.calls, 0, 'reuse must never invoke portFree');
36
- }
37
- // B: foreign occupant on the preferred port moves the module to the next free port.
38
- {
39
- const probe = countingProbe('foreign');
40
- const portFree = countingPortFree(port => port === 5761);
41
- const resolved = await resolveModuleUrl({ kind: 'terminal', preferredUrl: 'http://127.0.0.1:5760', explicit: false, portFree: portFree.portFree, probe: probe.probe });
42
- assert.equal(resolved.source, 'dynamic');
43
- assert.equal(resolved.url, 'http://127.0.0.1:5761');
44
- assert.equal(resolved.port, 5761);
45
- assert.equal(resolved.offset, 1);
46
- assert.deepEqual(portFree.seen, [5760, 5761]);
47
- }
48
- // C: unreachable preferred port skips three busy ports before picking the fourth.
49
- {
50
- const probe = countingProbe('unreachable');
51
- const portFree = countingPortFree(port => port === 8790);
52
- const resolved = await resolveModuleUrl({ kind: 'vector-hub', preferredUrl: 'http://127.0.0.1:8787', explicit: false, portFree: portFree.portFree, probe: probe.probe });
53
- assert.equal(resolved.source, 'dynamic');
54
- assert.equal(resolved.url, 'http://127.0.0.1:8790');
55
- assert.equal(resolved.port, 8790);
56
- assert.equal(resolved.offset, 3);
57
- assert.deepEqual(portFree.seen, [8787, 8788, 8789, 8790]);
58
- }
59
- // D: exhausted scan range fails loudly with kind and port span in the message.
60
- {
61
- const probe = countingProbe('unreachable');
62
- const portFree = countingPortFree(() => false);
63
- await assert.rejects(
64
- () => resolveModuleUrl({ kind: 'event-bridge', preferredUrl: 'http://127.0.0.1:8790', explicit: false, portFree: portFree.portFree, probe: probe.probe }),
65
- error => {
66
- assert.equal(error.code, 'NO_FREE_MODULE_PORT');
67
- assert.ok(error.message.includes('event-bridge'), `message must name the module kind: ${error.message}`);
68
- assert.ok(error.message.includes('8790'), `message must name the first scanned port: ${error.message}`);
69
- assert.ok(error.message.includes('8809'), `message must name the last scanned port: ${error.message}`);
70
- return true;
71
- },
72
- );
73
- assert.equal(portFree.calls, 20, 'default scanRange must probe 20 consecutive ports before failing');
74
- assert.deepEqual(portFree.seen, Array.from({ length: 20 }, (_, index) => 8790 + index));
75
- }
76
- // E: an explicit external URL short-circuits before any probe or port scan.
77
- {
78
- const probe = countingProbe('module');
79
- const portFree = countingPortFree(() => true);
80
- const resolved = await resolveModuleUrl({ kind: 'knowledge-engine', preferredUrl: 'http://192.168.1.5:5790', explicit: true, portFree: portFree.portFree, probe: probe.probe });
81
- assert.equal(resolved.source, 'external');
82
- assert.equal(resolved.url, 'http://192.168.1.5:5790');
83
- assert.equal(probe.calls, 0, 'explicit external URL must never be probed');
84
- assert.equal(portFree.calls, 0, 'explicit external URL must never trigger a port scan');
85
- }
86
- // F: a preferred URL without an explicit port is rejected.
87
- {
88
- const probe = countingProbe('module');
89
- const portFree = countingPortFree(() => true);
90
- await assert.rejects(
91
- () => resolveModuleUrl({ kind: 'terminal', preferredUrl: 'http://127.0.0.1', explicit: false, portFree: portFree.portFree, probe: probe.probe }),
92
- error => { assert.equal(error.code, 'INVALID_MODULE_URL'); return true; },
93
- );
94
- }
95
- // G (integration): an HTTP service squatting on the preferred port with
96
- // 404 responses — exactly what happens when the shell's own fallback range
97
- // 5757..5776 lands on the terminal default 5760 — must not be misread as a
98
- // module and must not crash-loop: the bridge moves to the next free port.
99
- {
100
- const squatter = http.createServer((req, res) => { res.writeHead(404, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'not found' })); });
101
- await new Promise(resolve => squatter.listen(0, '127.0.0.1', resolve));
102
- const squatterPort = squatter.address().port;
103
- const bridge = new ModuleBridge();
104
- // Isolate the terminal leg: everything else is explicit/external so the
105
- // resolution loop only probes the squatter port for the terminal kind.
106
- bridge.terminalUrl = `http://127.0.0.1:${squatterPort}`;
107
- bridge.explicitModuleUrls = { terminal: false, vectorHub: true, eventBridge: true, engine: true };
108
- try {
109
- await bridge._resolveManagedUrls();
110
- assert.equal(bridge.moduleUrlSources.terminal, 'dynamic', '404 squatter must force a dynamic move, never reuse');
111
- assert.equal(bridge.terminalUrl, `http://127.0.0.1:${squatterPort + 1}`, 'module moves to the port right after the squatter');
112
- } finally {
113
- squatter.closeAllConnections?.();
114
- await new Promise(resolve => squatter.close(resolve));
115
- }
116
- }
117
- console.log('module dynamic port test PASS');
118
- })().catch(error => { console.error(error); process.exitCode = 1; });
1
+ 'use strict';
2
+ const assert = require('node:assert/strict');
3
+ const http = require('node:http');
4
+ const { resolveModuleUrl } = require('../lib/module-port-resolver');
5
+ const { ModuleBridge } = require('../lib/module-bridge');
6
+
7
+ const countingProbe = outcome => {
8
+ const seen = [];
9
+ return {
10
+ probe: async url => { seen.push(url); return outcome; },
11
+ get seen() { return seen; },
12
+ get calls() { return seen.length; },
13
+ };
14
+ };
15
+
16
+ const countingPortFree = isFree => {
17
+ const seen = [];
18
+ return {
19
+ portFree: async port => { seen.push(port); return isFree(port); },
20
+ get seen() { return seen; },
21
+ get calls() { return seen.length; },
22
+ };
23
+ };
24
+
25
+ (async () => {
26
+ // A: healthy module on the preferred port is reused without any port scan.
27
+ {
28
+ const probe = countingProbe('module');
29
+ const portFree = countingPortFree(() => false);
30
+ const resolved = await resolveModuleUrl({ kind: 'terminal', preferredUrl: 'http://127.0.0.1:5760', explicit: false, portFree: portFree.portFree, probe: probe.probe });
31
+ assert.equal(resolved.source, 'reused');
32
+ assert.equal(resolved.url, 'http://127.0.0.1:5760');
33
+ assert.equal(resolved.port, 5760);
34
+ assert.deepEqual(probe.seen, ['http://127.0.0.1:5760']);
35
+ assert.equal(portFree.calls, 0, 'reuse must never invoke portFree');
36
+ }
37
+ // B: foreign occupant on the preferred port moves the module to the next free port.
38
+ {
39
+ const probe = countingProbe('foreign');
40
+ const portFree = countingPortFree(port => port === 5761);
41
+ const resolved = await resolveModuleUrl({ kind: 'terminal', preferredUrl: 'http://127.0.0.1:5760', explicit: false, portFree: portFree.portFree, probe: probe.probe });
42
+ assert.equal(resolved.source, 'dynamic');
43
+ assert.equal(resolved.url, 'http://127.0.0.1:5761');
44
+ assert.equal(resolved.port, 5761);
45
+ assert.equal(resolved.offset, 1);
46
+ assert.deepEqual(portFree.seen, [5760, 5761]);
47
+ }
48
+ // C: unreachable preferred port skips three busy ports before picking the fourth.
49
+ {
50
+ const probe = countingProbe('unreachable');
51
+ const portFree = countingPortFree(port => port === 8790);
52
+ const resolved = await resolveModuleUrl({ kind: 'vector-hub', preferredUrl: 'http://127.0.0.1:8787', explicit: false, portFree: portFree.portFree, probe: probe.probe });
53
+ assert.equal(resolved.source, 'dynamic');
54
+ assert.equal(resolved.url, 'http://127.0.0.1:8790');
55
+ assert.equal(resolved.port, 8790);
56
+ assert.equal(resolved.offset, 3);
57
+ assert.deepEqual(portFree.seen, [8787, 8788, 8789, 8790]);
58
+ }
59
+ // D: exhausted scan range fails loudly with kind and port span in the message.
60
+ {
61
+ const probe = countingProbe('unreachable');
62
+ const portFree = countingPortFree(() => false);
63
+ await assert.rejects(
64
+ () => resolveModuleUrl({ kind: 'event-bridge', preferredUrl: 'http://127.0.0.1:8790', explicit: false, portFree: portFree.portFree, probe: probe.probe }),
65
+ error => {
66
+ assert.equal(error.code, 'NO_FREE_MODULE_PORT');
67
+ assert.ok(error.message.includes('event-bridge'), `message must name the module kind: ${error.message}`);
68
+ assert.ok(error.message.includes('8790'), `message must name the first scanned port: ${error.message}`);
69
+ assert.ok(error.message.includes('8809'), `message must name the last scanned port: ${error.message}`);
70
+ return true;
71
+ },
72
+ );
73
+ assert.equal(portFree.calls, 20, 'default scanRange must probe 20 consecutive ports before failing');
74
+ assert.deepEqual(portFree.seen, Array.from({ length: 20 }, (_, index) => 8790 + index));
75
+ }
76
+ // E: an explicit external URL short-circuits before any probe or port scan.
77
+ {
78
+ const probe = countingProbe('module');
79
+ const portFree = countingPortFree(() => true);
80
+ const resolved = await resolveModuleUrl({ kind: 'knowledge-engine', preferredUrl: 'http://192.168.1.5:5790', explicit: true, portFree: portFree.portFree, probe: probe.probe });
81
+ assert.equal(resolved.source, 'external');
82
+ assert.equal(resolved.url, 'http://192.168.1.5:5790');
83
+ assert.equal(probe.calls, 0, 'explicit external URL must never be probed');
84
+ assert.equal(portFree.calls, 0, 'explicit external URL must never trigger a port scan');
85
+ }
86
+ // F: a preferred URL without an explicit port is rejected.
87
+ {
88
+ const probe = countingProbe('module');
89
+ const portFree = countingPortFree(() => true);
90
+ await assert.rejects(
91
+ () => resolveModuleUrl({ kind: 'terminal', preferredUrl: 'http://127.0.0.1', explicit: false, portFree: portFree.portFree, probe: probe.probe }),
92
+ error => { assert.equal(error.code, 'INVALID_MODULE_URL'); return true; },
93
+ );
94
+ }
95
+ // G (integration): an HTTP service squatting on the preferred port with
96
+ // 404 responses — exactly what happens when the shell's own fallback range
97
+ // 5757..5776 lands on the terminal default 5760 — must not be misread as a
98
+ // module and must not crash-loop: the bridge moves to the next free port.
99
+ {
100
+ const squatter = http.createServer((req, res) => { res.writeHead(404, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'not found' })); });
101
+ await new Promise(resolve => squatter.listen(0, '127.0.0.1', resolve));
102
+ const squatterPort = squatter.address().port;
103
+ const bridge = new ModuleBridge();
104
+ // Isolate the terminal leg: everything else is explicit/external so the
105
+ // resolution loop only probes the squatter port for the terminal kind.
106
+ bridge.terminalUrl = `http://127.0.0.1:${squatterPort}`;
107
+ bridge.explicitModuleUrls = { terminal: false, vectorHub: true, eventBridge: true, engine: true };
108
+ try {
109
+ await bridge._resolveManagedUrls();
110
+ assert.equal(bridge.moduleUrlSources.terminal, 'dynamic', '404 squatter must force a dynamic move, never reuse');
111
+ assert.equal(bridge.terminalUrl, `http://127.0.0.1:${squatterPort + 1}`, 'module moves to the port right after the squatter');
112
+ } finally {
113
+ squatter.closeAllConnections?.();
114
+ await new Promise(resolve => squatter.close(resolve));
115
+ }
116
+ }
117
+ console.log('module dynamic port test PASS');
118
+ })().catch(error => { console.error(error); process.exitCode = 1; });
@@ -1,33 +1,33 @@
1
- 'use strict';
2
- const assert = require('node:assert/strict');
3
- const http = require('node:http');
4
- const { ModuleBridge } = require('../lib/module-bridge');
5
- (async () => {
6
- const upstream = http.createServer((req, res) => {
7
- const timer = setTimeout(() => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"ok":true}'); }, 75);
8
- res.on('close', () => clearTimeout(timer));
9
- });
10
- await new Promise(resolve => upstream.listen(0, '127.0.0.1', resolve));
11
- const bridge = new ModuleBridge({ vectorHubUrl: `http://127.0.0.1:${upstream.address().port}` });
12
- const timer = global.setTimeout;
13
- const budgets = [];
14
- // Scale only the two product deadlines, preserving real HTTP cancellation.
15
- global.setTimeout = (fn, ms, ...args) => {
16
- if (ms === 10000 || ms === 120000) { budgets.push(ms); return timer(fn, ms === 10000 ? 25 : 500, ...args); }
17
- return timer(fn, ms, ...args);
18
- };
19
- const server = http.createServer((req, res) => bridge.proxy(req, res, `http://127.0.0.1:${upstream.address().port}${req.url}`));
20
- await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
21
- try {
22
- const base = `http://127.0.0.1:${server.address().port}`;
23
- const indexed = await fetch(`${base}/api/sync`, { method: 'POST', body: '{}' });
24
- assert.equal(indexed.status, 200, 'a real embedding pass must use the engine indexing budget rather than the interactive deadline');
25
- assert.equal(budgets[0], 120000);
26
- const health = await fetch(`${base}/api/health`);
27
- assert.equal(health.status, 502, 'ordinary reads keep their bounded interactive deadline');
28
- console.log('module-index-proxy-test PASS');
29
- } finally {
30
- global.setTimeout = timer;
31
- for (const s of [server, upstream]) { s.closeAllConnections(); await new Promise(resolve => s.close(resolve)); }
32
- }
33
- })().catch(error => { console.error(error); process.exitCode = 1; });
1
+ 'use strict';
2
+ const assert = require('node:assert/strict');
3
+ const http = require('node:http');
4
+ const { ModuleBridge } = require('../lib/module-bridge');
5
+ (async () => {
6
+ const upstream = http.createServer((req, res) => {
7
+ const timer = setTimeout(() => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"ok":true}'); }, 75);
8
+ res.on('close', () => clearTimeout(timer));
9
+ });
10
+ await new Promise(resolve => upstream.listen(0, '127.0.0.1', resolve));
11
+ const bridge = new ModuleBridge({ vectorHubUrl: `http://127.0.0.1:${upstream.address().port}` });
12
+ const timer = global.setTimeout;
13
+ const budgets = [];
14
+ // Scale only the two product deadlines, preserving real HTTP cancellation.
15
+ global.setTimeout = (fn, ms, ...args) => {
16
+ if (ms === 10000 || ms === 120000) { budgets.push(ms); return timer(fn, ms === 10000 ? 25 : 500, ...args); }
17
+ return timer(fn, ms, ...args);
18
+ };
19
+ const server = http.createServer((req, res) => bridge.proxy(req, res, `http://127.0.0.1:${upstream.address().port}${req.url}`));
20
+ await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
21
+ try {
22
+ const base = `http://127.0.0.1:${server.address().port}`;
23
+ const indexed = await fetch(`${base}/api/sync`, { method: 'POST', body: '{}' });
24
+ assert.equal(indexed.status, 200, 'a real embedding pass must use the engine indexing budget rather than the interactive deadline');
25
+ assert.equal(budgets[0], 120000);
26
+ const health = await fetch(`${base}/api/health`);
27
+ assert.equal(health.status, 502, 'ordinary reads keep their bounded interactive deadline');
28
+ console.log('module-index-proxy-test PASS');
29
+ } finally {
30
+ global.setTimeout = timer;
31
+ for (const s of [server, upstream]) { s.closeAllConnections(); await new Promise(resolve => s.close(resolve)); }
32
+ }
33
+ })().catch(error => { console.error(error); process.exitCode = 1; });
@@ -1,44 +1,44 @@
1
- 'use strict';
2
- const assert = require('node:assert/strict');
3
- const http = require('node:http');
4
- const { ModuleBridge } = require('../lib/module-bridge');
5
- (async () => {
6
- let profile = { apiKey: 'controlled-model-key', mainModel: 'durable-default' };
7
- let settings = { provider: 'openai', apiKey: 'controlled-vector-key', model: 'embedding-model' };
8
- let appliedModel, appliedVector; const hits = [];
9
- const migrationId = `embedding-${'a'.repeat(64)}`;
10
- let legacy = { provider: 'minimax', apiKey: 'controlled-legacy-key', model: 'embo-01' };
11
- const service = http.createServer((req, res) => {
12
- assert.equal(req.headers.authorization, 'Bearer runtime-test');
13
- assert.equal(req.headers.origin, undefined);
14
- let input = ''; req.on('data', c => { input += c; });
15
- req.on('end', () => {
16
- hits.push(req.url); const body = JSON.parse(input || '{}');
17
- let result = { ok: true }; let status = 200;
18
- if (req.url.endsWith('/internal/maintenance-config')) { result = profile; if (!profile) status = 409; }
19
- else if (req.url === '/api/internal/embedding-config') result = { settings: legacy, migrationId };
20
- else if (req.url.endsWith('/internal/import-embedding')) { assert.equal(body.settings.apiKey, 'controlled-legacy-key'); }
21
- else if (req.url === '/api/internal/retire-embedding') { assert.equal(body.migrationId, migrationId); legacy = null; }
22
- else if (req.url.endsWith('/v1/internal/embedding-config')) { result = settings; if (!settings) status = 409; }
23
- else if (req.url === '/api/internal/runtime-config') appliedVector = body.settings;
24
- else if (req.url === '/api/runtime-config') appliedModel = body.profile;
25
- res.writeHead(status, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(result || {}));
26
- });
27
- });
28
- await new Promise(resolve => service.listen(0, '127.0.0.1', resolve));
29
- const url = `http://127.0.0.1:${service.address().port}`;
30
- const bridge = new ModuleBridge({ terminalUrl: url, engineUrl: url, vectorHubUrl: url, runtimeToken: 'runtime-test' });
31
- try {
32
- const status = await bridge.syncEngineConfiguration();
33
- assert.equal(status.model, true); assert.equal(status.embedding, true);
34
- assert.equal(appliedModel.mainModel, 'durable-default'); assert.equal(appliedVector.model, 'embedding-model');
35
- assert.ok(!JSON.stringify(status).includes('key'));
36
- assert.ok(!hits.some(route => /import-embedding|retire-embedding/.test(route)), 'fresh product must not import old credentials');
37
- assert.ok(!hits.includes('/api/internal/embedding-config'));
38
- profile = null; settings = null;
39
- const revoked = await bridge.syncEngineConfiguration();
40
- assert.equal(revoked.model, false); assert.equal(revoked.embedding, false);
41
- assert.equal(appliedModel, null); assert.equal(appliedVector, null);
42
- console.log('module-model-configuration-test PASS');
43
- } finally { service.closeAllConnections(); await new Promise(resolve => service.close(resolve)); }
44
- })().catch(error => { console.error(error); process.exitCode = 1; });
1
+ 'use strict';
2
+ const assert = require('node:assert/strict');
3
+ const http = require('node:http');
4
+ const { ModuleBridge } = require('../lib/module-bridge');
5
+ (async () => {
6
+ let profile = { apiKey: 'controlled-model-key', mainModel: 'durable-default' };
7
+ let settings = { provider: 'openai', apiKey: 'controlled-vector-key', model: 'embedding-model' };
8
+ let appliedModel, appliedVector; const hits = [];
9
+ const migrationId = `embedding-${'a'.repeat(64)}`;
10
+ let legacy = { provider: 'minimax', apiKey: 'controlled-legacy-key', model: 'embo-01' };
11
+ const service = http.createServer((req, res) => {
12
+ assert.equal(req.headers.authorization, 'Bearer runtime-test');
13
+ assert.equal(req.headers.origin, undefined);
14
+ let input = ''; req.on('data', c => { input += c; });
15
+ req.on('end', () => {
16
+ hits.push(req.url); const body = JSON.parse(input || '{}');
17
+ let result = { ok: true }; let status = 200;
18
+ if (req.url.endsWith('/internal/maintenance-config')) { result = profile; if (!profile) status = 409; }
19
+ else if (req.url === '/api/internal/embedding-config') result = { settings: legacy, migrationId };
20
+ else if (req.url.endsWith('/internal/import-embedding')) { assert.equal(body.settings.apiKey, 'controlled-legacy-key'); }
21
+ else if (req.url === '/api/internal/retire-embedding') { assert.equal(body.migrationId, migrationId); legacy = null; }
22
+ else if (req.url.endsWith('/v1/internal/embedding-config')) { result = settings; if (!settings) status = 409; }
23
+ else if (req.url === '/api/internal/runtime-config') appliedVector = body.settings;
24
+ else if (req.url === '/api/runtime-config') appliedModel = body.profile;
25
+ res.writeHead(status, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(result || {}));
26
+ });
27
+ });
28
+ await new Promise(resolve => service.listen(0, '127.0.0.1', resolve));
29
+ const url = `http://127.0.0.1:${service.address().port}`;
30
+ const bridge = new ModuleBridge({ terminalUrl: url, engineUrl: url, vectorHubUrl: url, runtimeToken: 'runtime-test' });
31
+ try {
32
+ const status = await bridge.syncEngineConfiguration();
33
+ assert.equal(status.model, true); assert.equal(status.embedding, true);
34
+ assert.equal(appliedModel.mainModel, 'durable-default'); assert.equal(appliedVector.model, 'embedding-model');
35
+ assert.ok(!JSON.stringify(status).includes('key'));
36
+ assert.ok(!hits.some(route => /import-embedding|retire-embedding/.test(route)), 'fresh product must not import old credentials');
37
+ assert.ok(!hits.includes('/api/internal/embedding-config'));
38
+ profile = null; settings = null;
39
+ const revoked = await bridge.syncEngineConfiguration();
40
+ assert.equal(revoked.model, false); assert.equal(revoked.embedding, false);
41
+ assert.equal(appliedModel, null); assert.equal(appliedVector, null);
42
+ console.log('module-model-configuration-test PASS');
43
+ } finally { service.closeAllConnections(); await new Promise(resolve => service.close(resolve)); }
44
+ })().catch(error => { console.error(error); process.exitCode = 1; });
@@ -1,35 +1,35 @@
1
- 'use strict';
2
- const fs = require('node:fs');
3
- const os = require('node:os');
4
- const path = require('node:path');
5
- const assert = require('node:assert/strict');
6
- const { ModuleBridge } = require('../lib/module-bridge');
7
- (async () => {
8
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'kb-supervisor-lifecycle-'));
9
- const fixture = path.join(root, '中文 module.js'), result = path.join(root, 'stopped.json');
10
- fs.writeFileSync(fixture, "const fs=require('fs');process.on('message',m=>{if(m.type==='kb:shutdown'){fs.writeFileSync(process.argv[2],JSON.stringify({arg:process.argv[3],stopped:true}));process.exit(0);}});process.send({ready:true});");
11
- const bridge = new ModuleBridge();
12
- bridge._spawnSupervised({ name: 'fixture', command: `node ${JSON.stringify(fixture)} ${JSON.stringify(result)} ${JSON.stringify('中文 argument with spaces')} ` });
13
- const child = bridge.supervised[0];
14
- await new Promise((resolve, reject) => { child.once('message', resolve); child.once('error', reject); });
15
- await bridge.stopSupervised();
16
- assert.equal(child.exitCode, 0, 'IPC shutdown must finish before the shell releases its process');
17
- assert.deepEqual(JSON.parse(fs.readFileSync(result)), { arg: '中文 argument with spaces', stopped: true });
18
- const missing = new ModuleBridge();
19
- missing._spawnSupervised({ name: 'missing', command: 'kb-definitely-missing-executable' });
20
- await new Promise(resolve => setTimeout(resolve, 100));
21
- assert.equal(missing.supervised.length, 0, 'failed process start must not crash or leave a false running module');
22
- await missing.stopSupervised();
23
- const { Logger, LogRepository } = require('../lib/structured-logger');
24
- const { StorageLayout } = require('../lib/storage-layout');
25
- const layout = new StorageLayout({ dataDir: path.join(root, 'data') }); const logger = new Logger({ layout });
26
- const diagnosticFixture = path.join(root, 'diagnostic.js');
27
- fs.writeFileSync(diagnosticFixture, "process.on('message',m=>{if(m.type==='kb:shutdown')process.exit(0)});process.send({type:'kb:diagnostic',record:{level:'error',event:'knowledge.maintenance.failed',message:'维护失败',projectId:'project-diagnostic',commitSha:'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',phase:'validating',error:{code:'ANALYSIS_EMPTY_DOCUMENT',message:'知识文档正文为空'}}});");
28
- const supervised = new ModuleBridge({ logger }); supervised._spawnSupervised({ name: 'knowledge-engine', command: `node ${JSON.stringify(diagnosticFixture)}` });
29
- await new Promise((resolve, reject) => { supervised.supervised[0].once('message', resolve); supervised.supervised[0].once('error', reject); });
30
- await logger.flush();
31
- const records = new LogRepository({ layout }).query({ commitSha: 'a'.repeat(40) }).entries;
32
- assert(records.some(record => record.event === 'knowledge.maintenance.failed' && record.error.message === '知识文档正文为空' && record.phase === 'validating'));
33
- await supervised.stopSupervised(); await logger.close();
34
- console.log('module process lifecycle test PASS');
35
- })().catch(error => { console.error(error); process.exitCode = 1; });
1
+ 'use strict';
2
+ const fs = require('node:fs');
3
+ const os = require('node:os');
4
+ const path = require('node:path');
5
+ const assert = require('node:assert/strict');
6
+ const { ModuleBridge } = require('../lib/module-bridge');
7
+ (async () => {
8
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'kb-supervisor-lifecycle-'));
9
+ const fixture = path.join(root, '中文 module.js'), result = path.join(root, 'stopped.json');
10
+ fs.writeFileSync(fixture, "const fs=require('fs');process.on('message',m=>{if(m.type==='kb:shutdown'){fs.writeFileSync(process.argv[2],JSON.stringify({arg:process.argv[3],stopped:true}));process.exit(0);}});process.send({ready:true});");
11
+ const bridge = new ModuleBridge();
12
+ bridge._spawnSupervised({ name: 'fixture', command: `node ${JSON.stringify(fixture)} ${JSON.stringify(result)} ${JSON.stringify('中文 argument with spaces')} ` });
13
+ const child = bridge.supervised[0];
14
+ await new Promise((resolve, reject) => { child.once('message', resolve); child.once('error', reject); });
15
+ await bridge.stopSupervised();
16
+ assert.equal(child.exitCode, 0, 'IPC shutdown must finish before the shell releases its process');
17
+ assert.deepEqual(JSON.parse(fs.readFileSync(result)), { arg: '中文 argument with spaces', stopped: true });
18
+ const missing = new ModuleBridge();
19
+ missing._spawnSupervised({ name: 'missing', command: 'kb-definitely-missing-executable' });
20
+ await new Promise(resolve => setTimeout(resolve, 100));
21
+ assert.equal(missing.supervised.length, 0, 'failed process start must not crash or leave a false running module');
22
+ await missing.stopSupervised();
23
+ const { Logger, LogRepository } = require('../lib/structured-logger');
24
+ const { StorageLayout } = require('../lib/storage-layout');
25
+ const layout = new StorageLayout({ dataDir: path.join(root, 'data') }); const logger = new Logger({ layout });
26
+ const diagnosticFixture = path.join(root, 'diagnostic.js');
27
+ fs.writeFileSync(diagnosticFixture, "process.on('message',m=>{if(m.type==='kb:shutdown')process.exit(0)});process.send({type:'kb:diagnostic',record:{level:'error',event:'knowledge.maintenance.failed',message:'维护失败',projectId:'project-diagnostic',commitSha:'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',phase:'validating',error:{code:'ANALYSIS_EMPTY_DOCUMENT',message:'知识文档正文为空'}}});");
28
+ const supervised = new ModuleBridge({ logger }); supervised._spawnSupervised({ name: 'knowledge-engine', command: `node ${JSON.stringify(diagnosticFixture)}` });
29
+ await new Promise((resolve, reject) => { supervised.supervised[0].once('message', resolve); supervised.supervised[0].once('error', reject); });
30
+ await logger.flush();
31
+ const records = new LogRepository({ layout }).query({ commitSha: 'a'.repeat(40) }).entries;
32
+ assert(records.some(record => record.event === 'knowledge.maintenance.failed' && record.error.message === '知识文档正文为空' && record.phase === 'validating'));
33
+ await supervised.stopSupervised(); await logger.close();
34
+ console.log('module process lifecycle test PASS');
35
+ })().catch(error => { console.error(error); process.exitCode = 1; });
@@ -1,34 +1,34 @@
1
- 'use strict';
2
- const assert = require('node:assert/strict');
3
- const http = require('node:http');
4
- const { ModuleBridge } = require('../lib/module-bridge');
5
-
6
- (async () => {
7
- let disconnected = false; let cursor;
8
- const upstream = http.createServer((req, res) => {
9
- cursor = req.headers['last-event-id'];
10
- res.writeHead(200, { 'Content-Type': 'text/event-stream' });
11
- res.write('id: 8\nevent: delta\ndata: {"text":"first"}\n\n');
12
- const timer = setInterval(() => res.write(': live\n\n'), 100);
13
- res.on('close', () => { clearInterval(timer); disconnected = true; });
14
- });
15
- await new Promise(resolve => upstream.listen(0, '127.0.0.1', resolve));
16
- const bridge = new ModuleBridge();
17
- const shell = http.createServer((req, res) => bridge.proxy(req, res, `http://127.0.0.1:${upstream.address().port}/events`));
18
- await new Promise(resolve => shell.listen(0, '127.0.0.1', resolve));
19
- const abort = new AbortController();
20
- try {
21
- const response = await fetch(`http://127.0.0.1:${shell.address().port}/events`, { headers: { 'Last-Event-ID': '7' }, signal: abort.signal });
22
- const reader = response.body.getReader();
23
- const first = await Promise.race([reader.read(), new Promise((_, reject) => setTimeout(() => reject(new Error('SSE was buffered')), 1500))]);
24
- assert.match(Buffer.from(first.value).toString(), /first/);
25
- assert.equal(cursor, '7');
26
- abort.abort();
27
- for (let i = 0; i < 40 && !disconnected; i++) await new Promise(resolve => setTimeout(resolve, 25));
28
- assert.equal(disconnected, true, 'browser disconnect releases upstream');
29
- console.log('module-stream-proxy-test PASS');
30
- } finally {
31
- abort.abort();
32
- for (const server of [shell, upstream]) { server.closeAllConnections(); await new Promise(resolve => server.close(resolve)); }
33
- }
34
- })().catch(error => { console.error(error); process.exitCode = 1; });
1
+ 'use strict';
2
+ const assert = require('node:assert/strict');
3
+ const http = require('node:http');
4
+ const { ModuleBridge } = require('../lib/module-bridge');
5
+
6
+ (async () => {
7
+ let disconnected = false; let cursor;
8
+ const upstream = http.createServer((req, res) => {
9
+ cursor = req.headers['last-event-id'];
10
+ res.writeHead(200, { 'Content-Type': 'text/event-stream' });
11
+ res.write('id: 8\nevent: delta\ndata: {"text":"first"}\n\n');
12
+ const timer = setInterval(() => res.write(': live\n\n'), 100);
13
+ res.on('close', () => { clearInterval(timer); disconnected = true; });
14
+ });
15
+ await new Promise(resolve => upstream.listen(0, '127.0.0.1', resolve));
16
+ const bridge = new ModuleBridge();
17
+ const shell = http.createServer((req, res) => bridge.proxy(req, res, `http://127.0.0.1:${upstream.address().port}/events`));
18
+ await new Promise(resolve => shell.listen(0, '127.0.0.1', resolve));
19
+ const abort = new AbortController();
20
+ try {
21
+ const response = await fetch(`http://127.0.0.1:${shell.address().port}/events`, { headers: { 'Last-Event-ID': '7' }, signal: abort.signal });
22
+ const reader = response.body.getReader();
23
+ const first = await Promise.race([reader.read(), new Promise((_, reject) => setTimeout(() => reject(new Error('SSE was buffered')), 1500))]);
24
+ assert.match(Buffer.from(first.value).toString(), /first/);
25
+ assert.equal(cursor, '7');
26
+ abort.abort();
27
+ for (let i = 0; i < 40 && !disconnected; i++) await new Promise(resolve => setTimeout(resolve, 25));
28
+ assert.equal(disconnected, true, 'browser disconnect releases upstream');
29
+ console.log('module-stream-proxy-test PASS');
30
+ } finally {
31
+ abort.abort();
32
+ for (const server of [shell, upstream]) { server.closeAllConnections(); await new Promise(resolve => server.close(resolve)); }
33
+ }
34
+ })().catch(error => { console.error(error); process.exitCode = 1; });