@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,170 +1,269 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
- const path = require('node:path');
4
- const fs = require('node:fs');
5
- const net = require('node:net');
6
- const { spawn, spawnSync, exec } = require('node:child_process');
7
- const { resolveDataDirPath } = require('../_site/lib/data-dir');
8
- const endpoint = require('../_site/lib/runtime-endpoint');
9
- const instances = require('../_site/lib/cli-instances');
10
- const pkg = require('../package.json');
11
-
12
- function help() {
13
- console.log(`project-knowledge ${pkg.version}
14
-
15
- Usage:
16
- project-knowledge [start] Start in background and open the UI
17
- project-knowledge --fg Start in foreground
18
- project-knowledge stop Stop this data directory and its owned modules
19
- project-knowledge status Show this data directory's instance
20
- project-knowledge status --all List controllable local knowledge instances
21
- project-knowledge stop --port 5804
22
- Stop the verified instance on this port
23
- project-knowledge install|update|uninstall|integrations
24
- Manage coding-agent integrations
25
-
26
- Options:
27
- -p, --port <port> Port (default: 5757, startup auto-fallback +19)
28
- --data <dir> Select data directory (default: ~/.project-knowledge-v5)
29
- --host <host> Bind host (default: 127.0.0.1)
30
- --no-open Do not open browser
31
- --fg Run in foreground
32
- -v, --version Print version
33
- -h, --help Show help
34
-
35
- Commands are case-insensitive. Unknown commands never start a service.`);
36
- }
37
- function parse(args) {
38
- const commands = new Set(['start', 'stop', 'status', 'install', 'update', 'uninstall', 'integrations']);
39
- let command = 'start';
40
- if (args[0] && !args[0].startsWith('-')) {
41
- command = args.shift().toLowerCase();
42
- if (!commands.has(command)) throw new Error(`Unknown command: ${command}. Run project-knowledge --help.`);
43
- }
44
- if (['install', 'update', 'uninstall', 'integrations'].includes(command)) return { command, forwarded: args };
45
- const options = { command, port: Number(process.env.KB_SITE_PORT || 5757), host: '127.0.0.1', open: true };
46
- for (let i = 0; i < args.length; i++) {
47
- const arg = args[i];
48
- if (arg === '--help' || arg === '-h') options.help = true;
49
- else if (arg === '--version' || arg === '-v') options.version = true;
50
- else if (['--port', '-p', '--host', '--data'].includes(arg)) {
51
- const value = args[++i];
52
- if (!value || value.startsWith('-')) throw new Error(`Missing value for ${arg}.`);
53
- if (arg === '--port' || arg === '-p') { options.port = Number(value); options.portExplicit = true; }
54
- else if (arg === '--data') options.dataDir = value;
55
- else options.host = value;
56
- } else if (arg === '--no-open') options.open = false;
57
- else if (arg === '--fg') options.foreground = true;
58
- else if (arg === '--all') options.all = true;
59
- else throw new Error(`${arg.startsWith('-') ? 'Unknown option' : 'Unexpected argument'}: ${arg}.`);
60
- }
61
- if (!Number.isInteger(options.port) || options.port < 1 || options.port > 65535) throw new Error('Port must be an integer from 1 to 65535.');
62
- if (options.all && (command !== 'status' || options.portExplicit)) throw new Error('--all is only supported by status, without --port.');
63
- if (command !== 'start' && (options.foreground || !options.open || options.host !== '127.0.0.1')) throw new Error('Startup options cannot be used with stop/status.');
64
- return options;
65
- }
66
- function openBrowser(url) {
67
- const command = process.platform === 'win32' ? `start "" "${url}"` : process.platform === 'darwin' ? `open "${url}"` : `xdg-open "${url}"`;
68
- exec(command, () => {});
69
- }
70
- function notify(message) { if (process.connected) process.send(message, () => {}); }
71
- function waitForStartup(child, log) {
72
- return new Promise((resolve, reject) => {
73
- const finish = (error, value) => {
74
- clearTimeout(timer); child.removeAllListeners('message'); child.removeAllListeners('exit');
75
- if (child.connected) child.disconnect();
76
- if (error) reject(error); else resolve(value);
77
- };
78
- const timer = setTimeout(() => finish(new Error(`启动尚未完成,请运行 project-knowledge status 并查看 ${log}`)), 45000);
79
- child.on('message', message => {
80
- if (message?.type === 'kb:launcher-ready') finish(null, message);
81
- else if (message?.type === 'kb:launcher-failed') finish(new Error(message.message));
82
- });
83
- child.once('error', error => finish(error));
84
- child.once('exit', code => finish(new Error(`后台进程在启动完成前退出(${code}),请查看 ${log}`)));
85
- });
86
- }
87
- function portFree(port, host) {
88
- return new Promise(resolve => {
89
- const tester = net.createServer();
90
- let done = false;
91
- const timer = setTimeout(() => finish(false), 3000);
92
- function finish(free) {
93
- if (done) return; done = true; clearTimeout(timer); tester.close(() => resolve(free));
94
- }
95
- tester.once('error', () => finish(false)); tester.once('listening', () => finish(true)); tester.listen(port, host);
96
- });
97
- }
98
- async function freePort(port, host) {
99
- for (let offset = 0; offset < 20 && port + offset <= 65535; offset++) if (await portFree(port + offset, host)) return port + offset;
100
- throw new Error(`No free port found near ${port}.`);
101
- }
102
- function show(info) { console.log(`project-knowledge is ${info.status === 'stopping' ? 'stopping' : 'running'} (PID ${info.pid}) at ${instances.url(info)} [${info.version}]\nData dir: ${info.dataDir}`); }
103
-
104
- async function main() {
105
- const options = parse(process.argv.slice(2));
106
- if (options.help) { help(); return; }
107
- if (options.version) { console.log(pkg.version); return; }
108
- if (options.forwarded) {
109
- const args = options.command === 'integrations' ? (options.forwarded.length ? options.forwarded : ['status']) : [options.command, ...options.forwarded];
110
- const result = spawnSync(process.execPath, [path.join(__dirname, 'project-knowledge-integrations.js'), ...args], { stdio: 'inherit', windowsHide: true });
111
- process.exitCode = result.status ?? 1; return;
112
- }
113
- const dataDir = resolveDataDirPath({ dataDir: options.dataDir });
114
- process.env.KB_DATA_DIR = dataDir;
115
- if (options.all) {
116
- const found = await instances.all();
117
- if (!found.length) console.log('No controllable project-knowledge instances found.');
118
- for (const info of found) show(info);
119
- return;
120
- }
121
- const existing = options.command !== 'start' && options.portExplicit ? await instances.atPort(options.port) : await instances.current(dataDir);
122
- const unverified = !existing && endpoint.readLiveEndpoint(dataDir, { removeStale: false });
123
- if (unverified) throw new Error(`数据目录已有实例记录(PID ${unverified.pid},端口 ${unverified.port}),但控制通道不可用。请先确认该实例,不会重复启动、误停止或报告已停止。`);
124
- if (existing && options.dataDir && options.command !== 'start' && path.resolve(existing.dataDir).toLowerCase() !== dataDir.toLowerCase()) throw new Error('指定端口不属于指定数据目录,已拒绝控制。');
125
- if (options.command === 'status') {
126
- if (existing) show(existing);
127
- else console.log(`project-knowledge is not running for ${dataDir}.\nUse "project-knowledge status --all" to inspect other data directories.`);
128
- return;
129
- }
130
- if (options.command === 'stop') {
131
- if (!existing) { console.log(`No background process found for ${dataDir}.`); return; }
132
- await instances.stop(existing);
133
- console.log(`project-knowledge stopped (PID ${existing.pid}) at ${instances.url(existing)}.\nData dir: ${existing.dataDir}`);
134
- return;
135
- }
136
- if (existing) {
137
- if (existing.status === 'stopping') throw new Error('实例正在停止,请稍后再启动。');
138
- const url = instances.url(existing); console.log(`Already running (PID ${existing.pid}) at ${url}\nData dir: ${existing.dataDir}`);
139
- notify({ type: 'kb:launcher-ready', url }); if (options.open) openBrowser(url); return;
140
- }
141
- // A live claim with no control channel is starting, legacy, or unverified.
142
- // Never trust a reused/shared PID as proof or kill it to make room.
143
- if (!options.foreground) {
144
- fs.mkdirSync(dataDir, { recursive: true });
145
- const log = path.join(dataDir, 'launcher.log'), fd = fs.openSync(log, 'a');
146
- const child = spawn(process.execPath, [...process.argv.slice(1), '--fg'], { detached: true, stdio: ['ignore', fd, fd, 'ipc'], windowsHide: true });
147
- fs.closeSync(fd); child.unref();
148
- console.log(`project-knowledge starting in background\nDiagnostics: ${log}`);
149
- const ready = await waitForStartup(child, log);
150
- console.log(`project-knowledge is ready at ${ready.url}\nUse "project-knowledge status" to check, "project-knowledge stop" to stop.`);
151
- return;
152
- }
153
- const port = options.portExplicit ? options.port : await freePort(options.port, options.host);
154
- process.env.KB_SITE_HOST = options.host; process.env.KB_SITE_PORT = String(port);
155
- console.log(`project-knowledge ${pkg.version}\nData dir: ${dataDir}`);
156
- if (port !== options.port) console.log(`(Port ${options.port} was busy, using ${port} instead)`);
157
- const { startServer, installProcessHandlers } = require('../_site/lib/server-app');
158
- const promise = startServer(); installProcessHandlers(promise);
159
- const instance = await promise;
160
- if (process.platform === 'win32') process.once('SIGBREAK', () => instance.stop('SIGBREAK'));
161
- const url = instances.url({ host: options.host, port });
162
- console.log(`Listening at ${url}`); notify({ type: 'kb:launcher-ready', url });
163
- if (options.open) setTimeout(() => openBrowser(url), 500);
164
- }
165
- main().catch(error => {
166
- const control = ['stop', 'status'].includes(process.argv[2]?.toLowerCase());
167
- console.error(process.argv.includes('--fg') ? `[project-knowledge] startup failed: ${error.message}` : `${control ? '控制失败' : '启动失败'}:${error.message}`);
168
- notify({ type: 'kb:launcher-failed', message: error.message });
169
- process.exitCode = 1;
170
- });
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ const path = require('node:path');
4
+ const fs = require('node:fs');
5
+ const net = require('node:net');
6
+ const { spawn, spawnSync, exec } = require('node:child_process');
7
+ const { resolveDataDirPath } = require('../_site/lib/data-dir');
8
+ const endpoint = require('../_site/lib/runtime-endpoint');
9
+ const instances = require('../_site/lib/cli-instances');
10
+ const pkg = require('../package.json');
11
+
12
+ function help() {
13
+ console.log(`project-knowledge ${pkg.version}
14
+
15
+ Usage:
16
+ project-knowledge [start] Start in background and open the UI
17
+ project-knowledge --fg Start in foreground
18
+ project-knowledge stop Stop this data directory and its owned modules
19
+ project-knowledge status Show this data directory's instance
20
+ project-knowledge status --all List controllable local knowledge instances
21
+ project-knowledge stop --port 5804
22
+ Stop the verified instance on this port
23
+ project-knowledge install|update|uninstall|integrations
24
+ Manage coding-agent integrations
25
+
26
+ Options:
27
+ -p, --port <port> Port (default: 5757, startup auto-fallback +19)
28
+ --data <dir> Select data directory (default: ~/.project-knowledge-v5)
29
+ --host <host> Bind host (default: 127.0.0.1)
30
+ --no-open Do not open browser
31
+ --fg Run in foreground
32
+ -v, --version Print version
33
+ -h, --help Show help
34
+
35
+ Commands are case-insensitive. Unknown commands never start a service.`);
36
+ }
37
+ function parse(args) {
38
+ const commands = new Set(['start', 'stop', 'status', 'install', 'update', 'uninstall', 'integrations']);
39
+ let command = 'start';
40
+ if (args[0] && !args[0].startsWith('-')) {
41
+ command = args.shift().toLowerCase();
42
+ if (!commands.has(command)) throw new Error(`Unknown command: ${command}. Run project-knowledge --help.`);
43
+ }
44
+ if (['install', 'update', 'uninstall', 'integrations'].includes(command)) return { command, forwarded: args };
45
+ const options = { command, port: Number(process.env.KB_SITE_PORT || 5757), host: '127.0.0.1', open: true };
46
+ for (let i = 0; i < args.length; i++) {
47
+ const arg = args[i];
48
+ if (arg === '--help' || arg === '-h') options.help = true;
49
+ else if (arg === '--version' || arg === '-v') options.version = true;
50
+ else if (['--port', '-p', '--host', '--data'].includes(arg)) {
51
+ const value = args[++i];
52
+ if (!value || value.startsWith('-')) throw new Error(`Missing value for ${arg}.`);
53
+ if (arg === '--port' || arg === '-p') { options.port = Number(value); options.portExplicit = true; }
54
+ else if (arg === '--data') options.dataDir = value;
55
+ else options.host = value;
56
+ } else if (arg === '--no-open') options.open = false;
57
+ else if (arg === '--fg') options.foreground = true;
58
+ else if (arg === '--all') options.all = true;
59
+ else throw new Error(`${arg.startsWith('-') ? 'Unknown option' : 'Unexpected argument'}: ${arg}.`);
60
+ }
61
+ if (!Number.isInteger(options.port) || options.port < 1 || options.port > 65535) throw new Error('Port must be an integer from 1 to 65535.');
62
+ if (options.all && (command !== 'status' || options.portExplicit)) throw new Error('--all is only supported by status, without --port.');
63
+ if (command !== 'start' && (options.foreground || !options.open || options.host !== '127.0.0.1')) throw new Error('Startup options cannot be used with stop/status.');
64
+ return options;
65
+ }
66
+ function openBrowser(url) {
67
+ const command = process.platform === 'win32' ? `start "" "${url}"` : process.platform === 'darwin' ? `open "${url}"` : `xdg-open "${url}"`;
68
+ exec(command, () => {});
69
+ }
70
+ function notify(message) { if (process.connected) process.send(message, () => {}); }
71
+ // Patience knobs must never produce NaN/Infinity budgets (a NaN comparison
72
+ // is always false, which silently disables the deadline and loops forever).
73
+ // Invalid or missing values fall back; absurd values clamp to one hour.
74
+ function parsePatienceMs(raw, fallbackMs) {
75
+ const value = Number(raw);
76
+ if (!Number.isFinite(value) || value <= 0) return fallbackMs;
77
+ return Math.min(value, 3600000);
78
+ }
79
+ function waitForStartup(child, log, options = {}) {
80
+ return new Promise((resolve, reject) => {
81
+ const initialBudgetMs = options.initialBudgetMs ?? 45000;
82
+ const progressIntervalMs = options.progressIntervalMs ?? 15000;
83
+ const patienceMs = options.patienceMs !== undefined
84
+ ? parsePatienceMs(options.patienceMs, 300000)
85
+ : parsePatienceMs(process.env.KB_LAUNCHER_STARTUP_PATIENCE_MS, 300000);
86
+ const startedAt = Date.now();
87
+ let timer = null;
88
+ const finish = (error, value) => {
89
+ clearTimeout(timer); child.removeAllListeners('message'); child.removeAllListeners('exit');
90
+ if (child.connected) child.disconnect();
91
+ if (error) reject(error); else resolve(value);
92
+ };
93
+ // R10: a slow init is STARTING, not a failure. The old fixed 45s budget
94
+ // reported 启动失败 while the detached backend kept initializing and
95
+ // opened the browser minutes later. Keep waiting (with progress lines)
96
+ // while the child lives; only a child exit or a real launcher-failed
97
+ // message is definitive. The patience cap stays an honest give-up-waiting
98
+ // report that explicitly does not claim the backend failed; R12: the
99
+ // schedule honors a patience deadline BELOW the first checkpoint (the cap
100
+ // fires at min(checkpoint, patience)) and the cap error is TYPED so the
101
+ // CLI reports it as still-starting instead of 启动失败.
102
+ const onBudget = () => {
103
+ const elapsed = Date.now() - startedAt;
104
+ if (child.exitCode !== null) return;
105
+ if (elapsed >= patienceMs) {
106
+ finish(Object.assign(new Error(`启动仍在进行:后台进程存活但 ${Math.round(elapsed / 1000)}s 内未就绪(未判定失败)。请运行 project-knowledge status 并查看 ${log}`), { code: 'KB_STARTUP_STILL_STARTING' }));
107
+ return;
108
+ }
109
+ console.log(`仍在启动(已等待 ${Math.round(elapsed / 1000)}s,进程存活)…诊断: ${log}`);
110
+ timer = setTimeout(onBudget, Math.max(50, Math.min(progressIntervalMs, patienceMs - elapsed)));
111
+ };
112
+ timer = setTimeout(onBudget, Math.max(50, Math.min(initialBudgetMs, patienceMs)));
113
+ child.on('message', message => {
114
+ if (message?.type === 'kb:launcher-ready') finish(null, message);
115
+ else if (message?.type === 'kb:launcher-failed') finish(new Error(message.message));
116
+ });
117
+ child.once('error', error => finish(error));
118
+ child.once('exit', code => finish(new Error(`后台进程在启动完成前退出(${code}),请查看 ${log}`)));
119
+ });
120
+ }
121
+ function portFree(port, host) {
122
+ return new Promise(resolve => {
123
+ const tester = net.createServer();
124
+ let done = false;
125
+ const timer = setTimeout(() => finish(false), 3000);
126
+ function finish(free) {
127
+ if (done) return; done = true; clearTimeout(timer); tester.close(() => resolve(free));
128
+ }
129
+ tester.once('error', () => finish(false)); tester.once('listening', () => finish(true)); tester.listen(port, host);
130
+ });
131
+ }
132
+ async function freePort(port, host) {
133
+ for (let offset = 0; offset < 20 && port + offset <= 65535; offset++) if (await portFree(port + offset, host)) return port + offset;
134
+ throw new Error(`No free port found near ${port}.`);
135
+ }
136
+ function show(info) { console.log(`project-knowledge is ${info.status === 'stopping' ? 'stopping' : 'running'} (PID ${info.pid}) at ${instances.url(info)} [${info.version}]\nData dir: ${info.dataDir}`); }
137
+ function isRetryableProbeError(error) {
138
+ if (!error) return false;
139
+ if (['ETIMEDOUT', 'ECONNRESET', 'EAGAIN'].includes(error.code)) return true;
140
+ if (error.code) return false;
141
+ return /超时|断开连接/.test(String(error.message || ''));
142
+ }
143
+ // R10: `start` must not report 启动失败 while an existing instance is alive
144
+ // but its control channel is stalled (large-data busy windows exceed the
145
+ // short probe budget, and a timeout error carries no code). Retry while the
146
+ // endpoint PID lives; a dead record falls through to a normal spawn.
147
+ async function resolveExistingForStart(dataDir) {
148
+ const patienceMs = parsePatienceMs(process.env.KB_LAUNCHER_CONNECT_PATIENCE_MS, 300000);
149
+ const startedAt = Date.now();
150
+ while (true) {
151
+ let current = null;
152
+ let answered = false; // the probe definitively reported "no control channel"
153
+ try { current = await instances.current(dataDir); answered = true; }
154
+ catch (error) { if (!isRetryableProbeError(error)) throw error; }
155
+ if (current) return { instance: current };
156
+ const live = endpoint.readLiveEndpoint(dataDir, { removeStale: false });
157
+ if (!live || !endpoint.isProcessAlive(live.pid)) return { instance: null };
158
+ // R13: the live writer ALWAYS stamps startedAt (writeEndpoint/claimEndpoint
159
+ // default it). A live PID behind an unstamped record while the probe
160
+ // answered a definitive refusal (ENOENT/ECONNREFUSED/EPIPE, not a busy
161
+ // timeout) is a legacy or hand-written claim, not a busy window: refuse
162
+ // fast like stop/status instead of trusting the unverified PID through the
163
+ // whole patience budget. A stalled-but-present channel (retryable timeout)
164
+ // keeps the honest retry below.
165
+ if (answered && !live.startedAt) return { unverified: live };
166
+ if (Date.now() - startedAt >= patienceMs) return { busy: live };
167
+ await new Promise(resolve => setTimeout(resolve, 500));
168
+ }
169
+ }
170
+
171
+ async function main() {
172
+ const options = parse(process.argv.slice(2));
173
+ if (options.help) { help(); return; }
174
+ if (options.version) { console.log(pkg.version); return; }
175
+ if (options.forwarded) {
176
+ const args = options.command === 'integrations' ? (options.forwarded.length ? options.forwarded : ['status']) : [options.command, ...options.forwarded];
177
+ const result = spawnSync(process.execPath, [path.join(__dirname, 'project-knowledge-integrations.js'), ...args], { stdio: 'inherit', windowsHide: true });
178
+ process.exitCode = result.status ?? 1; return;
179
+ }
180
+ const dataDir = resolveDataDirPath({ dataDir: options.dataDir });
181
+ process.env.KB_DATA_DIR = dataDir;
182
+ if (options.all) {
183
+ const found = await instances.all();
184
+ if (!found.length) console.log('No controllable project-knowledge instances found.');
185
+ for (const info of found) show(info);
186
+ return;
187
+ }
188
+ let existing;
189
+ if (options.command === 'start') {
190
+ // R10: live-but-busy instance → honest retry, never 启动失败 and never a
191
+ // second spawn. stop/status keep their strict refusal semantics below.
192
+ const resolved = await resolveExistingForStart(dataDir);
193
+ if (resolved.unverified) {
194
+ const info = resolved.unverified;
195
+ throw new Error(`数据目录已有实例记录(PID ${info.pid},端口 ${info.port}),但该记录缺少 startedAt 启动标识且控制通道无响应(未验证的遗留记录)。已拒绝启动:不会重复启动、误停止或报告已停止。`);
196
+ }
197
+ if (resolved.busy) {
198
+ const info = resolved.busy;
199
+ console.log(`现有实例(PID ${info.pid},端口 ${info.port})正在启动或繁忙,控制通道暂未响应(未判定失败,未重复启动)。` +
200
+ `\n可稍后重试,或直接访问 ${instances.url(info)}`);
201
+ return;
202
+ }
203
+ existing = resolved.instance;
204
+ } else {
205
+ existing = options.portExplicit ? await instances.atPort(options.port) : await instances.current(dataDir);
206
+ const unverified = !existing && endpoint.readLiveEndpoint(dataDir, { removeStale: false });
207
+ if (unverified) throw new Error(`数据目录已有实例记录(PID ${unverified.pid},端口 ${unverified.port}),但控制通道不可用。请先确认该实例,不会重复启动、误停止或报告已停止。`);
208
+ }
209
+ if (existing && options.dataDir && options.command !== 'start' && path.resolve(existing.dataDir).toLowerCase() !== dataDir.toLowerCase()) throw new Error('指定端口不属于指定数据目录,已拒绝控制。');
210
+ if (options.command === 'status') {
211
+ if (existing) show(existing);
212
+ else console.log(`project-knowledge is not running for ${dataDir}.\nUse "project-knowledge status --all" to inspect other data directories.`);
213
+ return;
214
+ }
215
+ if (options.command === 'stop') {
216
+ if (!existing) { console.log(`No background process found for ${dataDir}.`); return; }
217
+ await instances.stop(existing);
218
+ console.log(`project-knowledge stopped (PID ${existing.pid}) at ${instances.url(existing)}.\nData dir: ${existing.dataDir}`);
219
+ return;
220
+ }
221
+ if (existing) {
222
+ if (existing.status === 'stopping') throw new Error('实例正在停止,请稍后再启动。');
223
+ const url = instances.url(existing); console.log(`Already running (PID ${existing.pid}) at ${url}\nData dir: ${existing.dataDir}`);
224
+ notify({ type: 'kb:launcher-ready', url }); if (options.open) openBrowser(url); return;
225
+ }
226
+ // A live claim with no control channel is starting, legacy, or unverified.
227
+ // Never trust a reused/shared PID as proof or kill it to make room.
228
+ if (!options.foreground) {
229
+ fs.mkdirSync(dataDir, { recursive: true });
230
+ const log = path.join(dataDir, 'launcher.log'), fd = fs.openSync(log, 'a');
231
+ const child = spawn(process.execPath, [...process.argv.slice(1), '--fg'], { detached: true, stdio: ['ignore', fd, fd, 'ipc'], windowsHide: true });
232
+ fs.closeSync(fd); child.unref();
233
+ console.log(`project-knowledge starting in background\nDiagnostics: ${log}`);
234
+ const ready = await waitForStartup(child, log).catch(error => {
235
+ // R12: the patience cap while the child lives is an honest
236
+ // still-starting report, never 启动失败 — the backend keeps booting.
237
+ if (error && error.code === 'KB_STARTUP_STILL_STARTING') {
238
+ console.log(`${error.message}\n后台进程将继续初始化(未重复启动,未判定失败)。`);
239
+ return null;
240
+ }
241
+ throw error;
242
+ });
243
+ if (!ready) return;
244
+ console.log(`project-knowledge is ready at ${ready.url}\nUse "project-knowledge status" to check, "project-knowledge stop" to stop.`);
245
+ return;
246
+ }
247
+ const port = options.portExplicit ? options.port : await freePort(options.port, options.host);
248
+ process.env.KB_SITE_HOST = options.host; process.env.KB_SITE_PORT = String(port);
249
+ console.log(`project-knowledge ${pkg.version}\nData dir: ${dataDir}`);
250
+ if (port !== options.port) console.log(`(Port ${options.port} was busy, using ${port} instead)`);
251
+ const { startServer, installProcessHandlers } = require('../_site/lib/server-app');
252
+ const promise = startServer(); installProcessHandlers(promise);
253
+ const instance = await promise;
254
+ if (process.platform === 'win32') process.once('SIGBREAK', () => instance.stop('SIGBREAK'));
255
+ const url = instances.url({ host: options.host, port });
256
+ console.log(`Listening at ${url}`); notify({ type: 'kb:launcher-ready', url });
257
+ if (options.open) setTimeout(() => openBrowser(url), 500);
258
+ }
259
+ // R12: the module doubles as the CLI entry AND a testable unit surface;
260
+ // require() must never run the CLI.
261
+ module.exports = { waitForStartup, parsePatienceMs };
262
+ if (require.main === module) {
263
+ main().catch(error => {
264
+ const control = ['stop', 'status'].includes(process.argv[2]?.toLowerCase());
265
+ console.error(process.argv.includes('--fg') ? `[project-knowledge] startup failed: ${error.message}` : `${control ? '控制失败' : '启动失败'}:${error.message}`);
266
+ notify({ type: 'kb:launcher-failed', message: error.message });
267
+ process.exitCode = 1;
268
+ });
269
+ }
@@ -1,21 +1,21 @@
1
- {
2
- "schema": "claude-prompts/v1",
3
- "prompts": {
4
- "initial-analysis": {
5
- "description": "Initial project analysis. Claude runs from the KB workspace and reads the source project via PROJECT_PATH.",
6
- "model": "sonnet",
7
- "permissionMode": "bypassPermissions",
8
- "allowedTools": ["Read", "Grep", "Glob"],
9
- "systemPrompt": "You are an expert project analyst building a knowledge base. The current working directory is the knowledge-base workspace, not the source project. Read source code from PROJECT_PATH and treat KB_PATH as the write target for knowledge-base drafts and updates. Output STRICT JSON only: no prose and no markdown fences. The JSON must match this shape:\n\n{\n \"goalDraft\": {\n \"oneLine\": \"one-sentence description of what this project is\",\n \"positioning\": \"paragraph describing the project's role and core value\",\n \"coreValue\": [\"bullet points of core value to developers / teams\"],\n \"painPoints\": [{\"pain\": \"...\", \"legacyApproach\": \"...\", \"projectApproach\": \"...\"}]\n },\n \"analysisDraft\": {\n \"framework\": \"primary framework / language / stack\",\n \"modules\": [{\"name\": \"...\", \"responsibility\": \"...\", \"keyFiles\": [\"path/to/file\"]}],\n \"architecture\": \"paragraph describing the architecture and data flow\",\n \"evidence\": [{\"claim\": \"...\", \"file\": \"path:line\"}]\n },\n \"features\": [{\"slug\": \"kebab-case-slug\", \"name\": \"...\", \"summary\": \"...\"}]\n}\n\nUse the Read, Grep, and Glob tools to investigate PROJECT_PATH. Cite real source file paths in evidence. Do not invent modules that do not exist. Do not modify the source project unless the user explicitly asks for source changes.",
10
- "userPrompt": "Analyze the source project at PROJECT_PATH. The current working directory is KB_PATH.\n\nProject context:\n- Slug: {{SLUG}}\n- Source project path: {{PROJECT_PATH}}\n- Knowledge-base path: {{KB_PATH}}\n- Primary language: {{PRIMARY_LANGUAGE}}\n- Knowledge language: {{KNOWLEDGE_LANGUAGE}}\n\nTasks:\n1. Identify the framework, main tech stack, and language distribution.\n2. List the core modules / top-level directories and their responsibilities.\n3. Describe the architecture and data flow at a high level.\n4. Identify 3-6 user-facing features.\n5. Capture 4-8 evidence-backed claims with file:line citations.\n\nWrite the knowledge-base content in {{KNOWLEDGE_LANGUAGE}} where natural, but keep code identifiers, file paths, and JSON keys in English.\n\nReturn ONLY the JSON object described in the system prompt."
11
- },
12
- "commit-analysis": {
13
- "description": "Batch analysis of one or more commits. Claude runs from the KB workspace and reads the source project via PROJECT_PATH.",
14
- "model": "sonnet",
15
- "permissionMode": "bypassPermissions",
16
- "allowedTools": ["Read", "Grep", "Glob", "Bash"],
17
- "systemPrompt": "You are a commit analyst building a knowledge base. The current working directory is the knowledge-base workspace, not the source project. Read source code from PROJECT_PATH and treat KB_PATH as the write target for knowledge-base drafts and updates. For each commit provided, output a structured change description. STRICT JSON only: no prose.\n\nOutput shape:\n{\n \"changes\": [\n {\n \"hash\": \"<full-or-short-hash>\",\n \"subject\": \"<original commit subject>\",\n \"type\": \"feat|fix|refactor|docs|test|chore|infra\",\n \"classification\": \"feature|bugfix|infrastructure|documentation|test\",\n \"summary\": \"one-paragraph description of what changed and why\",\n \"files\": [\"paths/touched\"],\n \"evidence\": [{\"claim\": \"...\", \"file\": \"path:line\"}]\n }\n ]\n}\n\nUse git commands against PROJECT_PATH and Read for inspecting changed files. Cite real source file paths. Do not modify the source project unless the user explicitly asks for source changes.",
18
- "userPrompt": "Analyze the following commits in the source project at PROJECT_PATH. The current working directory is KB_PATH.\n\nProject: {{SLUG}} ({{PROJECT_PATH}})\nKnowledge-base path: {{KB_PATH}}\nCommit range: {{COMMIT_RANGE}}\nCommits to analyze:\n{{COMMIT_HASHES}}\n\nFor each commit, produce one entry in the changes array. Use git commands against {{PROJECT_PATH}} and Read for inspecting changed source files. Summarize in {{KNOWLEDGE_LANGUAGE}}; keep identifiers and paths in English.\n\nReturn ONLY the JSON object."
19
- }
20
- }
21
- }
1
+ {
2
+ "schema": "claude-prompts/v1",
3
+ "prompts": {
4
+ "initial-analysis": {
5
+ "description": "Initial project analysis. Claude runs from the KB workspace and reads the source project via PROJECT_PATH.",
6
+ "model": "sonnet",
7
+ "permissionMode": "bypassPermissions",
8
+ "allowedTools": ["Read", "Grep", "Glob"],
9
+ "systemPrompt": "You are an expert project analyst building a knowledge base. The current working directory is the knowledge-base workspace, not the source project. Read source code from PROJECT_PATH and treat KB_PATH as the write target for knowledge-base drafts and updates. Output STRICT JSON only: no prose and no markdown fences. The JSON must match this shape:\n\n{\n \"goalDraft\": {\n \"oneLine\": \"one-sentence description of what this project is\",\n \"positioning\": \"paragraph describing the project's role and core value\",\n \"coreValue\": [\"bullet points of core value to developers / teams\"],\n \"painPoints\": [{\"pain\": \"...\", \"legacyApproach\": \"...\", \"projectApproach\": \"...\"}]\n },\n \"analysisDraft\": {\n \"framework\": \"primary framework / language / stack\",\n \"modules\": [{\"name\": \"...\", \"responsibility\": \"...\", \"keyFiles\": [\"path/to/file\"]}],\n \"architecture\": \"paragraph describing the architecture and data flow\",\n \"evidence\": [{\"claim\": \"...\", \"file\": \"path:line\"}]\n },\n \"features\": [{\"slug\": \"kebab-case-slug\", \"name\": \"...\", \"summary\": \"...\"}]\n}\n\nUse the Read, Grep, and Glob tools to investigate PROJECT_PATH. Cite real source file paths in evidence. Do not invent modules that do not exist. Do not modify the source project unless the user explicitly asks for source changes.",
10
+ "userPrompt": "Analyze the source project at PROJECT_PATH. The current working directory is KB_PATH.\n\nProject context:\n- Slug: {{SLUG}}\n- Source project path: {{PROJECT_PATH}}\n- Knowledge-base path: {{KB_PATH}}\n- Primary language: {{PRIMARY_LANGUAGE}}\n- Knowledge language: {{KNOWLEDGE_LANGUAGE}}\n\nTasks:\n1. Identify the framework, main tech stack, and language distribution.\n2. List the core modules / top-level directories and their responsibilities.\n3. Describe the architecture and data flow at a high level.\n4. Identify 3-6 user-facing features.\n5. Capture 4-8 evidence-backed claims with file:line citations.\n\nWrite the knowledge-base content in {{KNOWLEDGE_LANGUAGE}} where natural, but keep code identifiers, file paths, and JSON keys in English.\n\nReturn ONLY the JSON object described in the system prompt."
11
+ },
12
+ "commit-analysis": {
13
+ "description": "Batch analysis of one or more commits. Claude runs from the KB workspace and reads the source project via PROJECT_PATH.",
14
+ "model": "sonnet",
15
+ "permissionMode": "bypassPermissions",
16
+ "allowedTools": ["Read", "Grep", "Glob", "Bash"],
17
+ "systemPrompt": "You are a commit analyst building a knowledge base. The current working directory is the knowledge-base workspace, not the source project. Read source code from PROJECT_PATH and treat KB_PATH as the write target for knowledge-base drafts and updates. For each commit provided, output a structured change description. STRICT JSON only: no prose.\n\nOutput shape:\n{\n \"changes\": [\n {\n \"hash\": \"<full-or-short-hash>\",\n \"subject\": \"<original commit subject>\",\n \"type\": \"feat|fix|refactor|docs|test|chore|infra\",\n \"classification\": \"feature|bugfix|infrastructure|documentation|test\",\n \"summary\": \"one-paragraph description of what changed and why\",\n \"files\": [\"paths/touched\"],\n \"evidence\": [{\"claim\": \"...\", \"file\": \"path:line\"}]\n }\n ]\n}\n\nUse git commands against PROJECT_PATH and Read for inspecting changed files. Cite real source file paths. Do not modify the source project unless the user explicitly asks for source changes.",
18
+ "userPrompt": "Analyze the following commits in the source project at PROJECT_PATH. The current working directory is KB_PATH.\n\nProject: {{SLUG}} ({{PROJECT_PATH}})\nKnowledge-base path: {{KB_PATH}}\nCommit range: {{COMMIT_RANGE}}\nCommits to analyze:\n{{COMMIT_HASHES}}\n\nFor each commit, produce one entry in the changes array. Use git commands against {{PROJECT_PATH}} and Read for inspecting changed source files. Summarize in {{KNOWLEDGE_LANGUAGE}}; keep identifiers and paths in English.\n\nReturn ONLY the JSON object."
19
+ }
20
+ }
21
+ }