@sanqianx/project-knowledge 5.0.24 → 5.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (401) hide show
  1. package/.agents/plugins/marketplace.json +20 -20
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/CHANGELOG.md +1361 -1353
  4. package/LICENSE +201 -201
  5. package/NOTICE +5 -5
  6. package/README.md +349 -349
  7. package/_modules/knowledge-engine/package.json +1 -1
  8. package/_modules/knowledge-engine/src/coordinator.js +48 -3
  9. package/_modules/knowledge-engine/src/runtime/automation-config.js +140 -140
  10. package/_modules/knowledge-engine/src/runtime/commit-conversation-binder.js +238 -238
  11. package/_modules/knowledge-engine/src/runtime/commit-processing-ledger.js +26 -26
  12. package/_modules/knowledge-engine/src/runtime/commit-prompt.js +193 -193
  13. package/_modules/knowledge-engine/src/runtime/commit-reconciler.js +394 -394
  14. package/_modules/knowledge-engine/src/runtime/contracts.js +282 -282
  15. package/_modules/knowledge-engine/src/runtime/conversation-store.js +389 -389
  16. package/_modules/knowledge-engine/src/runtime/evidence-bundle.js +228 -228
  17. package/_modules/knowledge-engine/src/runtime/git-runner.js +62 -62
  18. package/_modules/knowledge-engine/src/runtime/knowledge-promotion.js +505 -505
  19. package/_modules/knowledge-engine/src/runtime/knowledge-retrieval-service.js +400 -400
  20. package/_modules/knowledge-engine/src/runtime/markdown-knowledge-indexer.js +171 -171
  21. package/_modules/knowledge-engine/src/runtime/scanner.js +298 -298
  22. package/_modules/knowledge-engine/ui/app.js +23 -2
  23. package/_site/README.md +30 -30
  24. package/_site/_test/agent-capture-mcp-ui-test.js +68 -68
  25. package/_site/_test/agent-capture-ui-test.js +101 -101
  26. package/_site/_test/ai-profile-resolver-test.js +137 -137
  27. package/_site/_test/ai-profile-test.js +75 -75
  28. package/_site/_test/ai-vendor-presets-test.js +91 -91
  29. package/_site/_test/automatic-context-test.js +70 -70
  30. package/_site/_test/automation-queue-test.js +14 -14
  31. package/_site/_test/automation-ui-test.js +40 -40
  32. package/_site/_test/background-task-registry-test.js +43 -43
  33. package/_site/_test/baseline-schema-test.js +91 -91
  34. package/_site/_test/bin-cli-test.js +230 -230
  35. package/_site/_test/bridge-adapter-test.js +95 -95
  36. package/_site/_test/bridge-consumer-service-test.js +310 -310
  37. package/_site/_test/candidate-bin-content-test.js +35 -35
  38. package/_site/_test/candidate-product-assets-test.js +13 -13
  39. package/_site/_test/candidate-release-contract-test.js +14 -14
  40. package/_site/_test/capture-hook-dedup-test.js +158 -158
  41. package/_site/_test/cdp-browser-failure-test.js +103 -103
  42. package/_site/_test/chat-claudecodeui-match-test.js +92 -92
  43. package/_site/_test/claude-executable-discovery-test.js +90 -90
  44. package/_site/_test/claude-session-lifecycle-sweep-test.js +252 -252
  45. package/_site/_test/claude-workbench-test.js +174 -174
  46. package/_site/_test/cli-instance-management-test.js +62 -62
  47. package/_site/_test/client-capture-restart-e2e-test.js +189 -189
  48. package/_site/_test/codex-conversation-projection-test.js +60 -60
  49. package/_site/_test/codex-marketplace-scoped-path-test.js +186 -186
  50. package/_site/_test/codex-notify-capture-e2e-test.js +101 -101
  51. package/_site/_test/codex-notify-fanout-test.js +141 -134
  52. package/_site/_test/codex-notify-upgrade-test.js +253 -253
  53. package/_site/_test/commit-boundary-freeze-test.js +147 -147
  54. package/_site/_test/commit-conversation-binding-test.js +99 -99
  55. package/_site/_test/commit-evidence-test.js +110 -110
  56. package/_site/_test/configuration-generation-test.js +22 -22
  57. package/_site/_test/context-pack-test.js +200 -200
  58. package/_site/_test/conversation-api-test.js +119 -119
  59. package/_site/_test/conversation-origin-test.js +15 -15
  60. package/_site/_test/conversation-store-test.js +138 -138
  61. package/_site/_test/cross-repo-isolation-e2e-test.js +187 -187
  62. package/_site/_test/desktop-browser-compat-test.js +28 -28
  63. package/_site/_test/desktop-hook-runtime-regression-test.js +204 -204
  64. package/_site/_test/embedding-config-test.js +32 -32
  65. package/_site/_test/explicit-commit-processor-test.js +37 -37
  66. package/_site/_test/fixtures/fake-browser-exit.js +10 -10
  67. package/_site/_test/fixtures/fake-browser-hang.js +10 -10
  68. package/_site/_test/fixtures/integration-busy-worker.cjs +6 -6
  69. package/_site/_test/fixtures/make-git-repos.js +92 -92
  70. package/_site/_test/fixtures/retrieval-gold-queries.json +32 -32
  71. package/_site/_test/folder-picker-output-test.js +19 -19
  72. package/_site/_test/fresh-hook-reimport-test.js +53 -53
  73. package/_site/_test/fresh-product-data-test.js +56 -56
  74. package/_site/_test/full-integration-e2e-test.js +167 -167
  75. package/_site/_test/git-path-compatibility-test.js +80 -80
  76. package/_site/_test/git-validation-test.js +81 -81
  77. package/_site/_test/glm-ui-refresh-review-test.js +313 -404
  78. package/_site/_test/harness-isolation-test.js +138 -0
  79. package/_site/_test/helpers/cdp-browser.js +383 -0
  80. package/_site/_test/helpers/cdp-network-capture.js +66 -0
  81. package/_site/_test/helpers/find-chrome.js +34 -0
  82. package/_site/_test/helpers/free-port.js +8 -0
  83. package/_site/_test/helpers/logging-ui-fixture.js +131 -0
  84. package/_site/_test/helpers/module-fixture.js +282 -0
  85. package/_site/_test/helpers/parallel-engine-advanced-engine-child.js +45 -0
  86. package/_site/_test/helpers/parallel-engine-advanced-fault-writer.js +171 -0
  87. package/_site/_test/helpers/parallel-engine-advanced-harness.js +245 -0
  88. package/_site/_test/helpers/parallel-engine-advanced-standin-analyzer.js +80 -0
  89. package/_site/_test/helpers/parallel-engine-advanced-ui-host.js +177 -0
  90. package/_site/_test/helpers/parallel-engine-final-harness.js +314 -0
  91. package/_site/_test/helpers/parallel-engine-final-standin-analyzer.js +159 -0
  92. package/_site/_test/helpers/parallel-knowledge-fixture.js +255 -0
  93. package/_site/_test/helpers/parallel-logging-acceptance-fixture.js +111 -0
  94. package/_site/_test/helpers/parallel-logging-acceptance-proxy.js +106 -0
  95. package/_site/_test/helpers/parallel-logging-fix-r2-proxy.js +205 -0
  96. package/_site/_test/helpers/parallel-logging-integration-5025-env.js +432 -0
  97. package/_site/_test/helpers/parallel-memory-analyzer.js +81 -0
  98. package/_site/_test/helpers/parallel-memory-event-bridge.js +128 -0
  99. package/_site/_test/helpers/parallel-memory-shell.js +470 -0
  100. package/_site/_test/helpers/parallel-nav-isolation-env.js +389 -0
  101. package/_site/_test/helpers/parallel-nav-module-ui.js +186 -0
  102. package/_site/_test/helpers/parallel-nav-proxy.js +148 -0
  103. package/_site/_test/helpers/parallel-nav-shell.js +361 -0
  104. package/_site/_test/helpers/parallel-qa-engine-endpoint-guard.js +206 -0
  105. package/_site/_test/helpers/parallel-qa-engine-endpoint-isolate.js +257 -0
  106. package/_site/_test/helpers/parallel-retrieval-followup-corpus.js +293 -0
  107. package/_site/_test/helpers/parallel-retrieval-followup-next-session.js +70 -0
  108. package/_site/_test/helpers/parallel-retrieval-followup-r2-shell.js +737 -0
  109. package/_site/_test/helpers/parallel-retrieval-followup-r2-wb-host.js +82 -0
  110. package/_site/_test/helpers/parallel-retrieval-followup-shell.js +279 -0
  111. package/_site/_test/helpers/parallel-workbench-fixture.js +371 -0
  112. package/_site/_test/helpers/parallel-workbench-host.js +80 -0
  113. package/_site/_test/helpers/parallel-workbench-integration-5025-fixture.js +408 -0
  114. package/_site/_test/helpers/parallel-workbench-integration-5025-harness.js +593 -0
  115. package/_site/_test/helpers/parallel-workbench-integration-5025-host.js +70 -0
  116. package/_site/_test/helpers/parallel-workbench-integration-5025-launcher.js +240 -0
  117. package/_site/_test/helpers/parallel-workbench-integration-5025-runtime-harness.js +630 -0
  118. package/_site/_test/helpers/parallel-workbench-source-map.js +196 -0
  119. package/_site/_test/helpers/spawn-server.js +106 -0
  120. package/_site/_test/helpers/version-visibility-fixture.js +251 -0
  121. package/_site/_test/hook-runtime-endpoint-test.js +88 -88
  122. package/_site/_test/hook-status-repair-api-test.js +152 -152
  123. package/_site/_test/hook-trigger-test.js +85 -85
  124. package/_site/_test/hook-worktree-test.js +42 -42
  125. package/_site/_test/import-preflight-api-test.js +234 -234
  126. package/_site/_test/index-builder-test.js +41 -41
  127. package/_site/_test/index-error-display-contract-test.js +10 -10
  128. package/_site/_test/index-writer-concurrency-test.js +135 -135
  129. package/_site/_test/integration-adapters-test.js +262 -262
  130. package/_site/_test/integration-auto-repair-test.js +113 -113
  131. package/_site/_test/integration-capture-setup-test.js +118 -118
  132. package/_site/_test/integration-intent-test.js +81 -81
  133. package/_site/_test/integration-runtime-binding-a2-test.js +566 -566
  134. package/_site/_test/integration-runtime-binding-a3-test.js +227 -227
  135. package/_site/_test/integration-runtime-binding-test.js +473 -473
  136. package/_site/_test/integration-status-scan-test.js +29 -29
  137. package/_site/_test/integration-surface-coverage-test.js +164 -164
  138. package/_site/_test/kb-framework-test.js +57 -57
  139. package/_site/_test/kbpath-follow-test.js +63 -63
  140. package/_site/_test/knowledge-db-test.js +144 -144
  141. package/_site/_test/knowledge-engine-client-test.js +120 -109
  142. package/_site/_test/knowledge-language-control-test.js +170 -170
  143. package/_site/_test/knowledge-maintenance-test.js +40 -40
  144. package/_site/_test/knowledge-promotion-recovery-test.js +260 -260
  145. package/_site/_test/knowledge-query-test.js +54 -54
  146. package/_site/_test/knowledge-retrieval-service-test.js +77 -77
  147. package/_site/_test/knowledge-scopes-test.js +37 -37
  148. package/_site/_test/knowledge-storage-location-test.js +28 -28
  149. package/_site/_test/knowledge-storage-startup-test.js +52 -52
  150. package/_site/_test/knowledge-store-logs-supervision-test.js +89 -89
  151. package/_site/_test/launcher-readiness-test.js +80 -80
  152. package/_site/_test/legacy-claude-session-alias-test.js +106 -106
  153. package/_site/_test/legacy-routes-removed-test.js +47 -47
  154. package/_site/_test/legacy-workbench-exclusion-test.js +92 -92
  155. package/_site/_test/live-gateway-test.js +48 -48
  156. package/_site/_test/local-marketplace-test.js +16 -16
  157. package/_site/_test/log-redaction-test.js +58 -58
  158. package/_site/_test/logging-api-test.js +89 -89
  159. package/_site/_test/logging-sse-no-gap-test.js +88 -88
  160. package/_site/_test/logging-ui-test.js +107 -107
  161. package/_site/_test/markdown-delta-overlay-test.js +85 -85
  162. package/_site/_test/markdown-maintenance-api-test.js +75 -75
  163. package/_site/_test/markdown-maintenance-test.js +11 -11
  164. package/_site/_test/mcp-server-test.js +149 -149
  165. package/_site/_test/model-context-windows-test.js +89 -89
  166. package/_site/_test/module-agent-start-proxy-test.js +65 -65
  167. package/_site/_test/module-artifact-integrity-test.js +27 -27
  168. package/_site/_test/module-boundary-test.js +30 -30
  169. package/_site/_test/module-bridge-eventbridge-test.js +202 -202
  170. package/_site/_test/module-dynamic-port-test.js +118 -118
  171. package/_site/_test/module-index-proxy-test.js +33 -33
  172. package/_site/_test/module-model-configuration-test.js +44 -44
  173. package/_site/_test/module-process-lifecycle-test.js +35 -35
  174. package/_site/_test/module-stream-proxy-test.js +34 -34
  175. package/_site/_test/module-terminal-restart-test.js +63 -63
  176. package/_site/_test/module-wiring-unbind-race-test.js +59 -59
  177. package/_site/_test/native-context-integrations-test.js +86 -86
  178. package/_site/_test/non-release-ci-test.js +34 -34
  179. package/_site/_test/offline-boundary-isolation-test.js +32 -32
  180. package/_site/_test/orphaned-claim-recovery-test.js +80 -80
  181. package/_site/_test/package-boundary-test.js +43 -43
  182. package/_site/_test/package-startup-test.js +56 -56
  183. package/_site/_test/packaged-ui-smoke-test.js +88 -88
  184. package/_site/_test/parallel-ci-r9-posix-socket-budget-test.js +156 -0
  185. package/_site/_test/parallel-engine-advanced-eng005-test.js +136 -0
  186. package/_site/_test/parallel-engine-advanced-eng006-test.js +171 -0
  187. package/_site/_test/parallel-engine-advanced-eng007-reconcile-test.js +231 -0
  188. package/_site/_test/parallel-engine-advanced-eng009-test.js +208 -0
  189. package/_site/_test/parallel-engine-advanced-eng010-test.js +213 -0
  190. package/_site/_test/parallel-engine-advanced-eng011-ui-probe.js +459 -0
  191. package/_site/_test/parallel-engine-final-eng002-test.js +255 -0
  192. package/_site/_test/parallel-engine-final-eng007-test.js +269 -0
  193. package/_site/_test/parallel-engine-final-eng011-test.js +197 -0
  194. package/_site/_test/parallel-engine-final-eng012-test.js +354 -0
  195. package/_site/_test/parallel-knowledge-client-error-code-test.js +184 -0
  196. package/_site/_test/parallel-knowledge-engine-test.js +353 -0
  197. package/_site/_test/parallel-knowledge-retrieval-test.js +292 -0
  198. package/_site/_test/parallel-knowledge-vector-test.js +168 -0
  199. package/_site/_test/parallel-linux-ci-r7-log007-day-test.js +110 -0
  200. package/_site/_test/parallel-logging-acceptance-log003-test.js +224 -0
  201. package/_site/_test/parallel-logging-acceptance-log004-test.js +231 -0
  202. package/_site/_test/parallel-logging-acceptance-log005-test.js +208 -0
  203. package/_site/_test/parallel-logging-acceptance-log006-test.js +214 -0
  204. package/_site/_test/parallel-logging-acceptance-log007-test.js +223 -0
  205. package/_site/_test/parallel-logging-acceptance-log008-test.js +180 -0
  206. package/_site/_test/parallel-logging-fix-r2-crash-probe.js +271 -0
  207. package/_site/_test/parallel-logging-fix-r2-gap-test.js +294 -0
  208. package/_site/_test/parallel-logging-fix-r2-normalhook-test.js +330 -0
  209. package/_site/_test/parallel-logging-integration-5025-portability-test.js +554 -0
  210. package/_site/_test/parallel-memory-candidate-test.js +301 -0
  211. package/_site/_test/parallel-memory-manual-test.js +197 -0
  212. package/_site/_test/parallel-memory-scope-test.js +228 -0
  213. package/_site/_test/parallel-memory-source-test.js +227 -0
  214. package/_site/_test/parallel-memory-sync-test.js +238 -0
  215. package/_site/_test/parallel-memory-view-r8-reload-gate-test.js +123 -0
  216. package/_site/_test/parallel-nav-failure-test.js +119 -0
  217. package/_site/_test/parallel-nav-isolation-test.js +308 -0
  218. package/_site/_test/parallel-nav-isolation-vector-path-test.js +90 -0
  219. package/_site/_test/parallel-nav-offline-test.js +272 -0
  220. package/_site/_test/parallel-nav-operability-test.js +257 -0
  221. package/_site/_test/parallel-nav-switch-test.js +247 -0
  222. package/_site/_test/parallel-nav-theme-test.js +130 -0
  223. package/_site/_test/parallel-nav-viewport-test.js +310 -0
  224. package/_site/_test/parallel-qa-engine-endpoint-guard-test.js +273 -0
  225. package/_site/_test/parallel-retrieval-followup-citation-test.js +219 -0
  226. package/_site/_test/parallel-retrieval-followup-corpus-test.js +287 -0
  227. package/_site/_test/parallel-workbench-independent-host.js +262 -0
  228. package/_site/_test/parallel-workbench-integration-5025-abort-probe.js +340 -0
  229. package/_site/_test/parallel-workbench-integration-5025-drafts-probe.js +588 -0
  230. package/_site/_test/parallel-workbench-integration-5025-env-check.js +317 -0
  231. package/_site/_test/parallel-workbench-integration-5025-model-probe.js +342 -0
  232. package/_site/_test/parallel-workbench-integration-5025-ordering-probe.js +326 -0
  233. package/_site/_test/parallel-workbench-model-probe.js +336 -0
  234. package/_site/_test/parallel-workbench-offline-test.js +169 -0
  235. package/_site/_test/parallel-workbench-provenance-trace.js +134 -0
  236. package/_site/_test/parallel-workbench-source-match.js +206 -0
  237. package/_site/_test/parallel-workbench-standalone-turn.js +349 -0
  238. package/_site/_test/path-consistency-test.js +151 -151
  239. package/_site/_test/pending-sweep-test.js +9 -9
  240. package/_site/_test/post-commit-automation-test.js +87 -87
  241. package/_site/_test/pr-consumer-contract-test.js +55 -55
  242. package/_site/_test/product-brand-contract-test.js +25 -25
  243. package/_site/_test/product-diagnostics-ui-test.js +93 -93
  244. package/_site/_test/product-empty-state-test.js +148 -0
  245. package/_site/_test/product-import-ui-test.js +219 -104
  246. package/_site/_test/product-navigation-test.js +152 -0
  247. package/_site/_test/product-progress-status-test.js +84 -84
  248. package/_site/_test/project-delete-recovery-test.js +64 -64
  249. package/_site/_test/project-domain-create-test.js +91 -0
  250. package/_site/_test/project-domain-scope-retrieval-test.js +214 -0
  251. package/_site/_test/project-git-init-confirm-test.js +115 -0
  252. package/_site/_test/project-goal-editor-test.js +144 -144
  253. package/_site/_test/project-import-duplicate-alias-test.js +134 -0
  254. package/_site/_test/project-import-unicode-restart-test.js +140 -0
  255. package/_site/_test/project-lifecycle-transaction-test.js +106 -106
  256. package/_site/_test/project-module-partial-recovery-test.js +222 -0
  257. package/_site/_test/project-remove-running-guard-test.js +79 -79
  258. package/_site/_test/project-store-test.js +90 -90
  259. package/_site/_test/project-unbind-late-read-ui-test.js +250 -0
  260. package/_site/_test/project-unbind-writer-guard-test.js +231 -0
  261. package/_site/_test/prompt-settings-test.js +115 -115
  262. package/_site/_test/protected-architecture-gate-test.js +122 -122
  263. package/_site/_test/refactor-characterization-test.js +36 -36
  264. package/_site/_test/registry-events-test.js +38 -38
  265. package/_site/_test/release-version-sync-test.js +115 -115
  266. package/_site/_test/requirement-binding-test.js +113 -113
  267. package/_site/_test/requirement-recorder-test.js +173 -173
  268. package/_site/_test/run-all-tests.js +173 -161
  269. package/_site/_test/runtime-endpoint-test.js +64 -64
  270. package/_site/_test/scanner-test.js +83 -83
  271. package/_site/_test/server-security-test.js +96 -96
  272. package/_site/_test/sessions-stream-test.js +93 -93
  273. package/_site/_test/shared-contracts-test.js +58 -58
  274. package/_site/_test/shared-scope-root-binding-test.js +74 -67
  275. package/_site/_test/simple-import-test.js +98 -98
  276. package/_site/_test/startup-analysis-disabled-test.js +16 -16
  277. package/_site/_test/storage-foundation-test.js +78 -78
  278. package/_site/_test/structured-logger-test.js +101 -101
  279. package/_site/_test/t07b-cln-005-coverage-test.js +212 -0
  280. package/_site/_test/team-knowledge-store-sparse-checkout-test.js +196 -196
  281. package/_site/_test/team-knowledge-store-test.js +132 -132
  282. package/_site/_test/test-server-cleanup-test.js +35 -35
  283. package/_site/_test/test-server-module-isolation-test.js +37 -37
  284. package/_site/_test/tracking-start-test.js +144 -144
  285. package/_site/_test/vector-storage-root-test.js +75 -75
  286. package/_site/_test/version-visibility-browser-probe.js +249 -0
  287. package/_site/_test/version-visibility-test.js +92 -0
  288. package/_site/_test/workbench-context-receipts-test.js +22 -22
  289. package/_site/_test/workbench-permission-test.js +117 -117
  290. package/_site/_test/zcode-capture-integration-test.js +112 -112
  291. package/_site/lib/ai-profile-resolver.js +78 -78
  292. package/_site/lib/ai-vendor-presets.js +83 -83
  293. package/_site/lib/ai-workspace.js +104 -104
  294. package/_site/lib/atomic-file.js +204 -204
  295. package/_site/lib/automation-config.js +140 -140
  296. package/_site/lib/bridge-adapter.js +260 -260
  297. package/_site/lib/bridge-consumer-service.js +402 -402
  298. package/_site/lib/capture-hook-config.js +108 -108
  299. package/_site/lib/claude-cli-runner.js +1599 -1599
  300. package/_site/lib/cli-instances.js +43 -43
  301. package/_site/lib/codex-context-status.js +17 -17
  302. package/_site/lib/codex-notify-config.js +193 -193
  303. package/_site/lib/commit-conversation-binder.js +247 -247
  304. package/_site/lib/commit-processing-ledger.js +27 -27
  305. package/_site/lib/commit-prompt.js +202 -202
  306. package/_site/lib/commit-reconciler.js +444 -444
  307. package/_site/lib/context-pack-builder.js +299 -299
  308. package/_site/lib/contracts.js +291 -291
  309. package/_site/lib/conversation-exclusions.js +204 -204
  310. package/_site/lib/conversation-query-service.js +161 -161
  311. package/_site/lib/conversation-store.js +387 -387
  312. package/_site/lib/data-dir.js +13 -13
  313. package/_site/lib/embedding-service.js +85 -85
  314. package/_site/lib/engine-connection.js +93 -93
  315. package/_site/lib/engine-knowledge-client.js +76 -72
  316. package/_site/lib/evidence-bundle.js +228 -228
  317. package/_site/lib/folder-picker-output.js +24 -24
  318. package/_site/lib/git-path.js +14 -14
  319. package/_site/lib/git-runner.js +62 -62
  320. package/_site/lib/github-team-store.js +1175 -1175
  321. package/_site/lib/hook-manager.js +203 -203
  322. package/_site/lib/index-builder.js +157 -157
  323. package/_site/lib/index-service.js +173 -173
  324. package/_site/lib/integration-auto-repair.js +77 -77
  325. package/_site/lib/integration-installer.js +1240 -1240
  326. package/_site/lib/integration-intent.js +88 -88
  327. package/_site/lib/integration-status-scan.js +99 -99
  328. package/_site/lib/integration-status-worker.js +14 -14
  329. package/_site/lib/kb-framework.js +191 -191
  330. package/_site/lib/kb-validator.js +124 -124
  331. package/_site/lib/knowledge-db.js +363 -363
  332. package/_site/lib/knowledge-promotion.js +435 -435
  333. package/_site/lib/knowledge-retrieval-service.js +401 -401
  334. package/_site/lib/knowledge-schema.js +121 -121
  335. package/_site/lib/knowledge-tool-runtime.js +366 -366
  336. package/_site/lib/live-gateway.js +78 -78
  337. package/_site/lib/llm-client.js +173 -173
  338. package/_site/lib/markdown-knowledge-indexer.js +230 -230
  339. package/_site/lib/model-context-windows.js +82 -82
  340. package/_site/lib/module-bridge.js +874 -874
  341. package/_site/lib/module-port-resolver.js +57 -57
  342. package/_site/lib/post-commit-automation.js +141 -141
  343. package/_site/lib/product-data.js +35 -35
  344. package/_site/lib/project-lifecycle-service.js +554 -554
  345. package/_site/lib/project-registry-store.js +129 -129
  346. package/_site/lib/project-store.js +268 -268
  347. package/_site/lib/prompt-registry.js +148 -148
  348. package/_site/lib/public-version-info.js +37 -0
  349. package/_site/lib/registry-events.js +16 -16
  350. package/_site/lib/requirement-adapters.js +10 -10
  351. package/_site/lib/requirement-binder.js +112 -112
  352. package/_site/lib/requirement-recorder.js +278 -278
  353. package/_site/lib/runtime-control.js +89 -89
  354. package/_site/lib/runtime-endpoint.js +160 -160
  355. package/_site/lib/scanner.js +298 -298
  356. package/_site/lib/server-app.js +1672 -1664
  357. package/_site/lib/settings-store.js +153 -153
  358. package/_site/lib/storage-layout.js +166 -166
  359. package/_site/lib/structured-logger.js +574 -574
  360. package/_site/lib/zcode-context-integration.js +60 -60
  361. package/_site/scripts/codex-notify-fanout.cjs +95 -95
  362. package/_site/scripts/folder-picker.ps1 +156 -156
  363. package/_site/scripts/hook-trigger.js +158 -158
  364. package/_site/scripts/install-module-candidates.js +69 -69
  365. package/_site/scripts/pack-module-candidates.js +89 -89
  366. package/_site/scripts/sync-product-content.js +28 -28
  367. package/_site/scripts/sync-release-version.js +164 -164
  368. package/_site/scripts/vendor-modules.js +49 -49
  369. package/_site/scripts/verify-module-runtime.js +50 -50
  370. package/_site/scripts/verify-product-runtime.js +36 -36
  371. package/_site/scripts/verify-retrieval-gold.js +83 -83
  372. package/_site/server.js +15 -15
  373. package/_site/start.bat +26 -26
  374. package/_site/stop.bat +11 -11
  375. package/bin/project-knowledge-integrations.js +254 -254
  376. package/bin/project-knowledge-kb.js +67 -67
  377. package/bin/project-knowledge-mcp.js +201 -201
  378. package/bin/project-knowledge.js +269 -170
  379. package/claude-prompts.json +21 -21
  380. package/docs/README.zh-CN.md +207 -205
  381. package/docs/assets/architecture.svg +181 -181
  382. package/docs/assets/logo.svg +49 -49
  383. package/docs/fresh-v5-start.md +44 -44
  384. package/docs/leader-glm-workbench-playbook.md +122 -122
  385. package/docs/project-registry-schema.md +33 -33
  386. package/docs/release-5.0.16-acceptance.md +176 -176
  387. package/docs/release-5.0.17-acceptance.md +117 -117
  388. package/docs/release-5.0.19-acceptance.md +39 -39
  389. package/docs/team-knowledge-mode-a-plan.md +73 -73
  390. package/docs/testing-strategy.md +33 -33
  391. package/module-runtime-manifest.json +66 -63
  392. package/package.json +113 -110
  393. package/plugins/project-knowledge/.claude-plugin/plugin.json +1 -1
  394. package/plugins/project-knowledge/.codex-plugin/plugin.json +1 -1
  395. package/plugins/project-knowledge/.mcp.json +1 -1
  396. package/templates/change.md +30 -30
  397. package/templates/project-readme.md +52 -52
  398. package/ui/index.html +3 -2
  399. package/ui/version-info.css +44 -0
  400. package/ui/version-info.js +24 -0
  401. package/vendor-manifest.json +55 -55
@@ -0,0 +1,247 @@
1
+ 'use strict';
2
+ // NAV-005 — 项目快速切换。
3
+ //
4
+ // Switching projects quickly must show one project at a time, a late answer
5
+ // must not paint another project over the current one, and the project that
6
+ // reaches the embedded module must be the current one.
7
+ //
8
+ // The regression drives the real product UI in a real browser against an
9
+ // isolated instance (own port, own data dir, own knowledge dir, own Bridge
10
+ // journal, own browser profile). The project switch is a real pointer click
11
+ // on the real project row. The late answer is a real held HTTP response in a
12
+ // proxy in front of the product: the shell really receives it, late. The
13
+ // knowledge snapshot is real engine state — the vendored knowledge engine is
14
+ // started for this case and the runs are written into its store.
15
+ //
16
+ // The embedded module UI is a test double that speaks the real kb:*
17
+ // protocol; it records the kb:select-project the shell really posted, so the
18
+ // project -> module mapping under test is the shell's own mapping.
19
+ //
20
+ // Screenshots are written to PK_TEST_EVIDENCE_DIR when the batch sets it, so
21
+ // this tracked file stays free of machine-specific paths.
22
+
23
+ const path = require('node:path');
24
+ const assert = require('node:assert/strict');
25
+
26
+ const { startHarness, makeRepo } = require('./helpers/parallel-nav-shell');
27
+
28
+ const EVIDENCE = process.env.PK_TEST_EVIDENCE_DIR ? path.resolve(process.env.PK_TEST_EVIDENCE_DIR) : null;
29
+
30
+ const SNAPSHOT = '/api/engine/snapshot';
31
+
32
+ /**
33
+ * Ask the shell to read the registry again and wait until a new matching
34
+ * read really left the browser.
35
+ *
36
+ * The case owns this loop instead of the shared helper because the held
37
+ * read lives inside the shell's three second read timeout: every hundred
38
+ * milliseconds of polling is a hundred milliseconds less of the budget the
39
+ * late answer has to arrive in.
40
+ */
41
+ async function refreshUntil(harness, match, timeoutMs = 20000) {
42
+ const before = harness.productProxy.requests.filter(match).length;
43
+ const deadline = Date.now() + timeoutMs;
44
+ while (Date.now() < deadline) {
45
+ await harness.requestRegistryRefresh();
46
+ await harness.wait(50);
47
+ const now = harness.productProxy.requests.filter(match).length;
48
+ if (now > before) return now;
49
+ }
50
+ throw new Error('the shell did not make the expected read');
51
+ }
52
+
53
+ /**
54
+ * Record every read the page really made and how it ended.
55
+ *
56
+ * The late answer of the previous project is only evidence if it really
57
+ * reached the product's promise chain: a read that the shell abandons after
58
+ * its three second timeout never reaches the guard, so the case would pass
59
+ * without a late answer ever arriving. The hook therefore records the state
60
+ * of every read, and the case waits for the late answer to be consumed.
61
+ */
62
+ const FETCH_HOOK = `(() => {
63
+ window.__fetches = [];
64
+ const nativeFetch = window.fetch;
65
+ window.fetch = function (input) {
66
+ const url = typeof input === 'string' ? input : (input && input.url) || '';
67
+ const entry = { url: String(url), state: 'pending', at: Date.now() };
68
+ window.__fetches.push(entry);
69
+ const args = arguments;
70
+ return nativeFetch.apply(this, args).then(response => {
71
+ entry.state = 'responded';
72
+ entry.status = response.status;
73
+ const originalJson = response.json.bind(response);
74
+ response.json = () => originalJson().then(data => {
75
+ entry.state = 'consumed';
76
+ entry.endedAt = Date.now();
77
+ return data;
78
+ }, error => {
79
+ entry.state = 'failed';
80
+ entry.endedAt = Date.now();
81
+ throw error;
82
+ });
83
+ return response;
84
+ }, error => {
85
+ entry.state = 'aborted';
86
+ entry.endedAt = Date.now();
87
+ throw error;
88
+ });
89
+ };
90
+ })()`;
91
+
92
+ /** The reads of the given project the page really made. */
93
+ const projectReads = (harness, projectId, skip = 0) => harness.run(`(window.__fetches || []).filter(entry => entry.url.includes('/api/engine/snapshot') && entry.url.includes(${JSON.stringify(`projectId=${projectId}`)})).slice(${skip})`);
94
+
95
+ async function main() {
96
+ const harness = await startHarness({ tag: 'nav005', evidenceDir: EVIDENCE || undefined });
97
+ try {
98
+ // The hook is installed before the case starts, so every read of the
99
+ // case is recorded.
100
+ await harness.run(FETCH_HOOK);
101
+ const repoA = makeRepo(harness.fixture, 'nav005-a');
102
+ const repoB = makeRepo(harness.fixture, 'nav005-b');
103
+ const projectA = await harness.importProject(repoA, 'NAV005 甲');
104
+ const projectB = await harness.importProject(repoB, 'NAV005 乙');
105
+
106
+ // Real engine state: one run per project, on the real baseline commit.
107
+ harness.engine.store.addRun({ projectId: projectA.projectId, commitSha: repoA.headCommit, trigger: 'manual' });
108
+ harness.engine.store.addRun({ projectId: projectB.projectId, commitSha: repoB.headCommit, trigger: 'manual' });
109
+ const shortA = repoA.headCommit.slice(0, 8);
110
+ const shortB = repoB.headCommit.slice(0, 8);
111
+
112
+ await harness.requestRegistryRefresh();
113
+ await harness.waitFor(
114
+ () => harness.run(`document.getElementById('homeContent').textContent.includes(${JSON.stringify(shortA)})`),
115
+ 'the current project shows its own run',
116
+ 20000,
117
+ );
118
+
119
+ const homeText = () => harness.run("document.getElementById('homeContent').textContent");
120
+ const currentProject = () => harness.run("document.getElementById('projectSelect').value");
121
+
122
+ // The terminal frame is opened once so the project mapping the shell
123
+ // really posts is observable.
124
+ await harness.run("document.querySelector('[data-view=\"work\"]').click()");
125
+ await harness.waitFor(
126
+ async () => {
127
+ const messages = await harness.frameMessages('workFrame');
128
+ return Array.isArray(messages) && messages.some(message => message.type === 'kb:select-project');
129
+ },
130
+ 'the terminal frame receives kb:select-project',
131
+ 20000,
132
+ );
133
+ await harness.run("document.querySelector('[data-view=\"home\"]').click()");
134
+ await harness.waitFor(() => harness.run("document.getElementById('view-home').classList.contains('active')"), 'the home view');
135
+
136
+ assert.equal(await currentProject(), projectA.projectId, 'the first project is the current one');
137
+
138
+ // How many reads of the first project the page already made: the held
139
+ // read is the next one, and the late answer is the one after it.
140
+ const readsBeforeHold = (await projectReads(harness, projectA.projectId)).length;
141
+
142
+ // A registry refresh reads the snapshot of the current project; that read
143
+ // is held so it can be released after the switch.
144
+ harness.productProxy.hold(entry => entry.method === 'GET' && entry.path.startsWith(SNAPSHOT) && entry.path.includes(`projectId=${projectA.projectId}`), { once: true });
145
+ await refreshUntil(harness, entry => entry.path.startsWith(SNAPSHOT) && entry.path.includes(`projectId=${projectA.projectId}`));
146
+ await harness.waitFor(
147
+ () => harness.productProxy.heldCount() > 0,
148
+ 'the snapshot read of the current project is held',
149
+ 20000,
150
+ );
151
+
152
+ // The switch to the other project is a real pointer click on the row.
153
+ await harness.nativeClick(`#homeContent [data-select-project="${projectB.projectId}"]`);
154
+ await harness.waitFor(async () => (await currentProject()) === projectB.projectId, 'the second project becomes the current one');
155
+ await harness.waitFor(
156
+ () => harness.run(`document.getElementById('homeContent').textContent.includes(${JSON.stringify(shortB)})`),
157
+ 'the second project shows its own run',
158
+ 20000,
159
+ );
160
+
161
+ // NAV-005 expected 1: only the current project is shown.
162
+ let text = await homeText();
163
+ assert.ok(text.includes(shortB), 'the current project run is shown');
164
+ assert.equal(text.includes(shortA), false, 'the other project run is not shown while the second project is current');
165
+
166
+ // NAV-005 expected 2: the late answer of the previous project must not
167
+ // paint over the current project.
168
+ //
169
+ // The snapshot reads are broken from here on, so that no automatic
170
+ // refresh can repair the page and hide a late answer that was wrongly
171
+ // applied. Without the shell's epoch and project guard the late snapshot
172
+ // of the other project would replace the current one, and the home would
173
+ // lose the run of the current project.
174
+ harness.productProxy.fail(entry => entry.method === 'GET' && entry.path.startsWith(SNAPSHOT), 503, '注入的快照读取故障');
175
+ const released = harness.productProxy.releaseHeld();
176
+ assert.ok(released >= 1, 'the held snapshot read is really delivered late');
177
+
178
+ // The late answer must really have reached the page: a read the shell
179
+ // abandons after its three second timeout never reaches the guard, and
180
+ // the case would prove nothing about a late answer that never arrived.
181
+ const lateRead = await harness.waitFor(
182
+ async () => {
183
+ const reads = await projectReads(harness, projectA.projectId, readsBeforeHold);
184
+ const last = reads[reads.length - 1];
185
+ if (!last || last.state === 'pending' || last.state === 'responded') return null;
186
+ return last;
187
+ },
188
+ 'the late answer really reached the page',
189
+ 20000,
190
+ );
191
+ assert.equal(lateRead.state, 'consumed', `the late answer was really consumed by the page: ${JSON.stringify(lateRead)}`);
192
+ // Two frames: the page really painted the outcome of the late answer.
193
+ await harness.run('new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve(true))))');
194
+
195
+ // The fault must really bite a real read. The shell reads the snapshot
196
+ // again on its own schedule, but the case does not wait for that: it
197
+ // asks the shell to read the registry again and waits until the proxy
198
+ // really saw a failed snapshot read. Without a failed read the case
199
+ // could not claim that no successful refresh was able to mask the late
200
+ // answer.
201
+ const failedReads = await refreshUntil(harness, entry => entry.path.startsWith(SNAPSHOT) && entry.status === 503);
202
+ assert.ok(failedReads >= 1, `the snapshot read really failed while the late answer was delivered: ${failedReads}`);
203
+
204
+ text = await homeText();
205
+ assert.equal(await currentProject(), projectB.projectId, 'the current project did not change because of the late answer');
206
+ assert.ok(text.includes(shortB), 'the current project run is still shown after the late answer');
207
+ assert.equal(text.includes(shortA), false, 'the late answer of the other project did not overwrite the current project');
208
+ const failedSnapshotReads = harness.productProxy.requests.filter(entry => entry.path.startsWith(SNAPSHOT) && entry.status === 503).length;
209
+ assert.ok(failedSnapshotReads >= 1, `the snapshot reads really failed while the late answer was delivered, so no refresh could mask it: ${failedSnapshotReads} failed reads`);
210
+ harness.productProxy.clearFaults();
211
+
212
+ // The switch back is a real pointer click as well.
213
+ await harness.nativeClick(`#homeContent [data-select-project="${projectA.projectId}"]`);
214
+ await harness.waitFor(async () => (await currentProject()) === projectA.projectId, 'the first project becomes the current one again');
215
+ await harness.waitFor(
216
+ () => harness.run(`document.getElementById('homeContent').textContent.includes(${JSON.stringify(shortA)})`),
217
+ 'the first project shows its own run again',
218
+ 20000,
219
+ );
220
+ text = await homeText();
221
+ assert.equal(text.includes(shortB), false, 'the other project run is not shown after switching back');
222
+ await harness.browser.screenshot(path.join(harness.evidence, 'nav005-switch-back.png'));
223
+
224
+ // NAV-005 expected 3: the project that reaches the embedded module is the
225
+ // current one, and the mapping is the one the product registered.
226
+ const mappings = (await harness.frameMessages('workFrame')).filter(message => message.type === 'kb:select-project');
227
+ const last = mappings[mappings.length - 1];
228
+ assert.ok(last, 'the terminal frame really received kb:select-project');
229
+ assert.equal(last.projectId, projectA.projectId, 'the newest kb:select-project carries the current project');
230
+ assert.equal(last.project, projectA.project.state.modules.terminal.projectId, 'the newest kb:select-project carries the module project the product registered for it');
231
+ const forB = mappings.find(message => message.projectId === projectB.projectId);
232
+ assert.ok(forB, 'the terminal frame really received the mapping of the other project');
233
+ assert.equal(forB.project, projectB.project.state.modules.terminal.projectId, 'the mapping of the other project is the module project the product registered for it');
234
+ const requestIds = mappings.map(message => message.requestId);
235
+ assert.ok(requestIds.every(requestId => /^\d+:terminal$/.test(String(requestId))), `every mapping carries the shell request id: ${JSON.stringify(requestIds)}`);
236
+ assert.notEqual(forB.requestId, last.requestId, 'the switch to the other project used a new request id');
237
+ assert.ok(mappings.every(message => message.projectId === projectA.projectId || message.projectId === projectB.projectId), 'no mapping carries a project that was never current');
238
+
239
+ assert.equal(harness.browser.exceptions.length, 0, `no uncaught product JavaScript exceptions: ${JSON.stringify(harness.browser.exceptions)}`);
240
+
241
+ console.log('parallel-nav-switch-test PASS (one project at a time, the late answer does not cross projects, the module mapping follows the current project)');
242
+ } finally {
243
+ await harness.cleanup();
244
+ }
245
+ }
246
+
247
+ main().catch(error => { console.error(error.stack || error.message); process.exitCode = 1; });
@@ -0,0 +1,130 @@
1
+ 'use strict';
2
+ // NAV-002 — 主题同步。
3
+ //
4
+ // The shell owns the product theme: switching it must persist, every embedded
5
+ // module that is already ready must be told about the new theme, and the
6
+ // switch must not rebuild the module task.
7
+ //
8
+ // The regression drives the real product UI in a real browser against an
9
+ // isolated instance (own port, own data dir, own knowledge dir, own Bridge
10
+ // journal, own browser profile, own vendored knowledge engine). The embedded
11
+ // module UI is a test double that speaks the real kb:* protocol: it announces
12
+ // kb:ready, records every kb:* message the shell really posted, and counts
13
+ // how often its document was really served — a rebuilt task is a served
14
+ // document. The substituted part is the module's own UI, not the shell.
15
+ //
16
+ // Screenshots are written to PK_TEST_EVIDENCE_DIR when the batch sets it, so
17
+ // this tracked file stays free of machine-specific paths.
18
+
19
+ const path = require('node:path');
20
+ const assert = require('node:assert/strict');
21
+
22
+ const { startHarness, makeRepo } = require('./helpers/parallel-nav-shell');
23
+
24
+ const EVIDENCE = process.env.PK_TEST_EVIDENCE_DIR ? path.resolve(process.env.PK_TEST_EVIDENCE_DIR) : null;
25
+
26
+ const FRAMES = [
27
+ { key: 'terminal', id: 'workFrame', view: 'work' },
28
+ { key: 'vectorHub', id: 'vectorFrame', view: 'search' },
29
+ { key: 'eventBridge', id: 'bridgeFrame', view: 'activity' },
30
+ ];
31
+
32
+ async function main() {
33
+ const harness = await startHarness({ tag: 'nav002', evidenceDir: EVIDENCE || undefined });
34
+ try {
35
+ const repo = makeRepo(harness.fixture, 'nav002-project');
36
+ await harness.importProject(repo, 'NAV002 项目');
37
+
38
+ // The shell boots on its own registry read.
39
+ await harness.waitFor(
40
+ () => harness.run("document.getElementById('homeContent').textContent.trim().length > 0"),
41
+ 'the shell reads the registry',
42
+ 20000,
43
+ );
44
+ await harness.requestRegistryRefresh();
45
+ await harness.waitFor(
46
+ () => harness.run("document.getElementById('homeContent').textContent.includes('NAV002 项目')"),
47
+ 'the imported project is listed',
48
+ 20000,
49
+ );
50
+
51
+ const shellTheme = () => harness.run("document.documentElement.dataset.theme");
52
+ const storedTheme = () => harness.run("localStorage.getItem('kb.theme')");
53
+
54
+ // NAV-002 expected 1: the theme persists.
55
+ assert.equal(await shellTheme(), 'light', 'the shell starts in the light theme');
56
+ assert.equal(await storedTheme(), null, 'no theme is stored before the first switch');
57
+ await harness.nativeClick('#themeToggle');
58
+ await harness.waitFor(async () => (await shellTheme()) === 'dark', 'the shell switches to the dark theme');
59
+ assert.equal(await storedTheme(), 'dark', 'the dark theme is persisted');
60
+ await harness.browser.screenshot(path.join(harness.evidence, 'nav002-theme-dark.png'));
61
+
62
+ // NAV-002 expected 2: a ready frame receives kb:theme.
63
+ // The three embedded modules are opened one after another; each frame has
64
+ // to be ready (the shell only talks to a frame that announced itself).
65
+ for (const frame of FRAMES) {
66
+ await harness.run(`document.querySelector('[data-view="${frame.view}"]').click()`);
67
+ if (frame.key === 'eventBridge') {
68
+ await harness.run("document.querySelector('[data-activity-tab=\"sessions\"]').click()");
69
+ }
70
+ await harness.waitFor(
71
+ async () => {
72
+ const messages = await harness.frameMessages(frame.id);
73
+ return Array.isArray(messages) && messages.some(message => message.type === 'kb:theme');
74
+ },
75
+ `the ${frame.key} frame announces itself and receives kb:theme`,
76
+ 20000,
77
+ );
78
+ const before = await harness.frameMessages(frame.id);
79
+ const themesBefore = before.filter(message => message.type === 'kb:theme').map(message => message.theme);
80
+ const currentTheme = await shellTheme();
81
+ assert.ok(themesBefore.includes(currentTheme), `the ${frame.key} frame is told the current theme when it becomes ready: ${JSON.stringify(themesBefore)} (shell theme ${currentTheme})`);
82
+
83
+ // Switch the theme while this frame is ready and connected.
84
+ const themeBeforeSwitch = await shellTheme();
85
+ const expected = themeBeforeSwitch === 'dark' ? 'light' : 'dark';
86
+ await harness.nativeClick('#themeToggle');
87
+ await harness.waitFor(async () => {
88
+ const messages = await harness.frameMessages(frame.id);
89
+ return Array.isArray(messages) && messages.some(message => message.type === 'kb:theme' && message.theme === expected);
90
+ }, `the ${frame.key} frame receives the new kb:theme`, 10000);
91
+ const after = (await harness.frameMessages(frame.id)).filter(message => message.type === 'kb:theme').map(message => message.theme);
92
+ assert.equal(after[after.length - 1], expected, `the ${frame.key} frame's newest kb:theme is the new theme: ${JSON.stringify(after)}`);
93
+ }
94
+
95
+ // NAV-002 expected 3: a theme switch never rebuilds the module task.
96
+ const loadsBefore = harness.modulePageLoads();
97
+ await harness.nativeClick('#themeToggle');
98
+ await harness.waitFor(async () => (await storedTheme()) === (await shellTheme()), 'the switched theme is persisted');
99
+ await harness.wait(500);
100
+ assert.equal(harness.modulePageLoads(), loadsBefore, 'a theme switch does not reload an embedded module document');
101
+ const registrations = harness.moduleUi.state.requests.filter(entry => entry.method === 'POST' && entry.path === '/api/claude-workbench/v1/projects').length;
102
+ await harness.nativeClick('#themeToggle');
103
+ await harness.wait(500);
104
+ assert.equal(
105
+ harness.moduleUi.state.requests.filter(entry => entry.method === 'POST' && entry.path === '/api/claude-workbench/v1/projects').length,
106
+ registrations,
107
+ 'a theme switch does not re-register the project with the module',
108
+ );
109
+
110
+ // The persisted theme survives a real reload of the product page.
111
+ const themeBeforeReload = await shellTheme();
112
+ await harness.browser.send('Page.reload');
113
+ await harness.waitFor(
114
+ async () => (await harness.run("document.documentElement.dataset.theme")) === themeBeforeReload && (await harness.run("document.readyState")) === 'complete',
115
+ 'the reloaded shell restores the persisted theme',
116
+ 20000,
117
+ );
118
+ assert.equal(await shellTheme(), themeBeforeReload, 'the theme is restored from localStorage after a reload');
119
+ assert.equal(await storedTheme(), themeBeforeReload, 'the persisted theme is unchanged by the reload');
120
+ await harness.browser.screenshot(path.join(harness.evidence, 'nav002-theme-after-reload.png'));
121
+
122
+ assert.equal(harness.browser.exceptions.length, 0, `no uncaught product JavaScript exceptions: ${JSON.stringify(harness.browser.exceptions)}`);
123
+
124
+ console.log('parallel-nav-theme-test PASS (theme persisted, ready frames receive kb:theme, no module task rebuilt)');
125
+ } finally {
126
+ await harness.cleanup();
127
+ }
128
+ }
129
+
130
+ main().catch(error => { console.error(error.stack || error.message); process.exitCode = 1; });