@sanqianx/project-knowledge 5.0.24 → 5.0.26

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 +68 -65
  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,554 @@
1
+ 'use strict';
2
+ // P-QA-LOG-INTEGRATION-5025 portability gate (canonical tracked regression
3
+ // entry for the logging acceptance / logging-safety lane).
4
+ //
5
+ // This entry does NOT re-run the acceptance drivers. It proves the
6
+ // PORTABILITY contract that lets those drivers enter the canonical
7
+ // cross-platform `npm test`:
8
+ //
9
+ // 1. No machine-specific absolute path survives in any lane file
10
+ // (comments excluded; string literals are executable and are scanned).
11
+ // 2. The isolation helper installs a complete, own environment before any
12
+ // product module loads: temp root OUTSIDE the source repository, own
13
+ // HOME/USERPROFILE/CODEX_HOME/CLAUDE_CONFIG_DIR/APPDATA/LOCALAPPDATA/
14
+ // TEMP/TMP/TMPDIR, own dual KB data roots, own Bridge / agent-terminal /
15
+ // workbench roots. The developer's real configuration is never used.
16
+ // 3. Every require() target of every lane entry resolves to a file that is
17
+ // either git-tracked or explicitly declared in this lane's manifest, so
18
+ // a clean checkout of tracked source can execute the entries (no
19
+ // dependency on untracked fixtures or local drive letters).
20
+ // 4. The run-all / manual-QA classification matches the runner's own rule
21
+ // (read from run-all-tests.js), and the frozen R1 exploration probes are
22
+ // not submitted as canonical entries.
23
+ // 5. No lane entry performs a real model/provider call; the entries that
24
+ // need an analyzer use the labelled offline stand-in.
25
+ // 6. The default evidence directories are inside a gitignored tree.
26
+ // 7. (P-LOGGING-ISOLATION-R2) The driver environment itself is sanitized:
27
+ // a poisoned environment proves that ambient provider keys, proxies,
28
+ // NODE_OPTIONS, module endpoints and CLI-injected configuration do not
29
+ // survive the install, that the entry's explicit lane values do, that a
30
+ // grandchild process inherits the same clean base, and that the real
31
+ // browser executable is still resolvable after HOME/LOCALAPPDATA moved.
32
+ // 8. (P-LOGGING-PS-BROWSER-R3) The remaining isolation details are proven
33
+ // as well: PSModuleAnalysisCachePath is a FILE path whose parent
34
+ // directory exists (structural contract asserted on EVERY platform;
35
+ // the own-PowerShell-child proof runs on Windows only); the
36
+ // browser default profile Chrome derives from USERPROFILE is scaffolded
37
+ // inside the owned home (never the developer's real profile); and the
38
+ // lane tree is really removed when the entry releases it.
39
+ //
40
+ // Strict mode: set PK_LOGGING_GATE_STRICT_TRACKED=1 to additionally require
41
+ // every manifest file to be committed to Git (the commit step belongs to the
42
+ // Leader, not to this lane).
43
+
44
+ const fs = require('node:fs');
45
+ const os = require('node:os');
46
+ const path = require('node:path');
47
+ const { spawnSync } = require('node:child_process');
48
+
49
+ const {
50
+ installLoggingTestEnv, resolveEvidenceDir, isInsideRepo,
51
+ DEAD_MODULE_URL, MODULE_URL_KEYS, MODULE_FLAG_KEYS, MODULE_COMMAND_KEYS,
52
+ } = require('./helpers/parallel-logging-integration-5025-env');
53
+
54
+ const ROOT = path.resolve(__dirname, '../..');
55
+ const ARTIFACTS = resolveEvidenceDir(path.resolve(ROOT, 'qa-autopilot/artifacts/parallel-20261023/logging-integration-5025/evidence/portability'));
56
+
57
+ // Every file this lane owns and hands to the Leader for the canonical commit.
58
+ const LANE_MANIFEST = [
59
+ '_site/_test/parallel-logging-acceptance-log003-test.js',
60
+ '_site/_test/parallel-logging-acceptance-log004-test.js',
61
+ '_site/_test/parallel-logging-acceptance-log005-test.js',
62
+ '_site/_test/parallel-logging-acceptance-log006-test.js',
63
+ '_site/_test/parallel-logging-acceptance-log007-test.js',
64
+ '_site/_test/parallel-logging-acceptance-log008-test.js',
65
+ '_site/_test/parallel-logging-fix-r2-normalhook-test.js',
66
+ '_site/_test/parallel-logging-fix-r2-gap-test.js',
67
+ '_site/_test/helpers/parallel-logging-acceptance-fixture.js',
68
+ '_site/_test/helpers/parallel-logging-acceptance-proxy.js',
69
+ '_site/_test/helpers/parallel-logging-fix-r2-proxy.js',
70
+ '_site/_test/helpers/parallel-logging-integration-5025-env.js',
71
+ '_site/_test/parallel-logging-integration-5025-portability-test.js',
72
+ ];
73
+
74
+ // The R1 exploration probes: frozen history, never canonical entries.
75
+ const FROZEN_EXPLORATION = [
76
+ '_site/_test/parallel-logging-acceptance-log003-probe.js',
77
+ '_site/_test/parallel-logging-acceptance-log004-probe.js',
78
+ ];
79
+
80
+ // Manual-QA-only entry (not matched by the runner glob; needs --expect).
81
+ const MANUAL_ONLY = '_site/_test/parallel-logging-fix-r2-crash-probe.js';
82
+ LANE_MANIFEST.push(MANUAL_ONLY);
83
+
84
+ const SCAN_FILES = Array.from(new Set(LANE_MANIFEST));
85
+
86
+ const AUTOMATIC_ENTRIES = LANE_MANIFEST.filter(file => file.endsWith('-test.js') && file.includes('/parallel-logging-'));
87
+
88
+ const REQUIRED_ENV_KEYS = [
89
+ 'HOME',
90
+ 'USERPROFILE',
91
+ 'CODEX_HOME',
92
+ 'CLAUDE_CONFIG_DIR',
93
+ 'APPDATA',
94
+ 'LOCALAPPDATA',
95
+ 'TEMP',
96
+ 'TMP',
97
+ 'TMPDIR',
98
+ 'PSModuleAnalysisCachePath',
99
+ 'KB_DATA_DIR',
100
+ 'KB_KNOWLEDGE_DATA_DIR',
101
+ 'AI_CODING_EVENT_BRIDGE_HOME',
102
+ 'AGENT_TERMINAL_DATA_DIR',
103
+ 'CLAUDE_AI_WORKBENCH_DATA_DIR',
104
+ ];
105
+
106
+ // P-LOGGING-ISOLATION-R2: the poisoned environment. Every value here is
107
+ // fabricated - the sentinel never reads a real key and never contacts a real
108
+ // host. The point is to prove what the install REMOVES and what it KEEPS.
109
+ const POISON_ENV = {
110
+ MINIMAX_API_KEY: 'poison-fabricated-key',
111
+ ANTHROPIC_API_KEY: 'poison-fabricated-key',
112
+ OPENAI_API_KEY: 'poison-fabricated-key',
113
+ KB_SITE_AUTH_TOKEN: 'poison-fabricated-token',
114
+ KB_WORKBENCH_RUNTIME_TOKEN: 'poison-fabricated-token',
115
+ HTTP_PROXY: 'http://poison-user:poison-password@proxy.invalid:1',
116
+ HTTPS_PROXY: 'http://poison-user:poison-password@proxy.invalid:1',
117
+ ALL_PROXY: 'http://poison-user:poison-password@proxy.invalid:1',
118
+ NODE_OPTIONS: '--require poison-never-loaded.js',
119
+ ANTHROPIC_BASE_URL: 'http://poison.invalid:1/',
120
+ KB_TERMINAL_URL: 'http://poison.invalid:1/',
121
+ KB_VECTORHUB_URL: 'http://poison.invalid:1/',
122
+ KB_KNOWLEDGE_ENGINE_URL: 'http://poison.invalid:1/',
123
+ KB_EVENTBRIDGE_URL: 'http://poison.invalid:1/',
124
+ KB_MODULES_AUTOSTART: '1',
125
+ KB_MODULES_REGISTER: '1',
126
+ KB_TERMINAL_COMMAND: 'poison-never-executed',
127
+ GIT_CONFIG_GLOBAL: 'poison-git-config',
128
+ GIT_DIR: 'poison-git-dir',
129
+ KB_AUTOMATION_FAKE_CLAUDE: 'ambient-fake-marker',
130
+ };
131
+
132
+ // The lane paths that must be redirected away from any ambient value.
133
+ // LOCALAPPDATA is deliberately NOT poisoned: the helper resolves the real
134
+ // browser executable from it BEFORE any path moves, so poisoning it here
135
+ // would hide the per-user Chrome install. Its redirection is proven by the
136
+ // lane-root containment check below.
137
+ const POISON_PATH_KEYS = [
138
+ 'HOME', 'USERPROFILE', 'APPDATA', 'TEMP', 'TMP', 'TMPDIR',
139
+ 'PSModuleAnalysisCachePath', 'CODEX_HOME', 'CLAUDE_CONFIG_DIR',
140
+ 'KB_DATA_DIR', 'KB_KNOWLEDGE_DATA_DIR', 'AI_CODING_EVENT_BRIDGE_HOME',
141
+ 'AGENT_TERMINAL_DATA_DIR', 'CLAUDE_AI_WORKBENCH_DATA_DIR',
142
+ ];
143
+
144
+ // The explicit lane values the entry owns. They are applied AFTER the
145
+ // sanitization and must survive it.
146
+ const LANE_OVERRIDES = {
147
+ KB_AUTOMATION_FAKE_CLAUDE: '1',
148
+ KB_EMBEDDING_FAKE: '1',
149
+ };
150
+
151
+ const stripComments = source => source
152
+ .replace(/\/\*[\s\S]*?\*\//g, ' ')
153
+ .replace(/(^|[^:])\/\/[^\n]*/g, '$1');
154
+
155
+ const git = args => {
156
+ const res = spawnSync('git', ['-C', ROOT, ...args], { encoding: 'utf8' });
157
+ if (res.status !== 0) throw new Error(`git ${args.join(' ')} failed: ${res.stderr || res.stdout}`);
158
+ return res.stdout.trim();
159
+ };
160
+
161
+ const isTracked = file => {
162
+ const res = spawnSync('git', ['-C', ROOT, 'ls-files', '--error-unmatch', '--', file], { encoding: 'utf8' });
163
+ return res.status === 0;
164
+ };
165
+
166
+ const isIgnored = file => {
167
+ const res = spawnSync('git', ['-C', ROOT, 'check-ignore', '-q', '--', file]);
168
+ return res.status === 0;
169
+ };
170
+
171
+ function requiresOf(file) {
172
+ const source = fs.readFileSync(path.join(ROOT, file), 'utf8');
173
+ const targets = [];
174
+ const pattern = /require\(\s*'([^']+)'\s*\)/g;
175
+ let match;
176
+ while ((match = pattern.exec(source)) !== null) {
177
+ const target = match[1];
178
+ if (target.startsWith('node:')) continue;
179
+ targets.push(target);
180
+ }
181
+ return targets;
182
+ }
183
+
184
+ function main() {
185
+ fs.mkdirSync(ARTIFACTS, { recursive: true });
186
+ const evidence = { caseId: 'P-QA-LOG-INTEGRATION-5025-portability', startedAt: new Date().toISOString(), checks: {} };
187
+ const failures = [];
188
+
189
+ git(['rev-parse', '--is-inside-work-tree']);
190
+
191
+ // 1. No machine-specific absolute path in any lane file.
192
+ const absolutePathHits = [];
193
+ // Built from parts so this gate's own source does not contain the needle.
194
+ const OLD_TEMP_BASE_NAME = ['.project-knowledge', 'test-temp'].join('-');
195
+ for (const file of SCAN_FILES) {
196
+ const code = stripComments(fs.readFileSync(path.join(ROOT, file), 'utf8'));
197
+ // A drive letter only counts when it starts a path, not inside a URL
198
+ // scheme such as "http://".
199
+ const matches = code.match(/(?<![A-Za-z0-9_])[A-Za-z]:[\\/][^\s'"`)]*/g) || [];
200
+ const oldTempBase = code.includes(OLD_TEMP_BASE_NAME) ? [OLD_TEMP_BASE_NAME] : [];
201
+ if (matches.length || oldTempBase.length) absolutePathHits.push({ file, matches, oldTempBase });
202
+ }
203
+ evidence.checks.noMachineSpecificPath = { scannedFiles: SCAN_FILES.length, hits: absolutePathHits };
204
+ if (absolutePathHits.length) failures.push(`machine-specific absolute path in: ${absolutePathHits.map(hit => hit.file).join(', ')}`);
205
+
206
+ // 1b. Every manifest file exists.
207
+ const missingManifest = SCAN_FILES.filter(file => !fs.existsSync(path.join(ROOT, file)));
208
+ evidence.checks.manifestExists = { missing: missingManifest };
209
+ if (missingManifest.length) failures.push(`manifest files missing: ${missingManifest.join(', ')}`);
210
+
211
+ // 2. Isolation contract of the helper, proven against a POISONED ambient
212
+ // environment (P-LOGGING-ISOLATION-R2). Redirecting a few directories is
213
+ // not isolation: the driver's own environment still reached every child
214
+ // process. The poison below is fabricated - no real key is read.
215
+ const realHome = process.env.USERPROFILE || process.env.HOME;
216
+ const ambientLocalAppData = process.env.LOCALAPPDATA;
217
+ // The poison/temp base must be OUTSIDE the repository: on the Windows CI
218
+ // job os.tmpdir() is the in-workspace .tmp directory, and a tool root built
219
+ // from it is exactly the in-repo temp shape the helper must refuse. The
220
+ // runner-provided PK_TEST_TEMP_ROOT (runner.temp) is the documented
221
+ // outside-repo root; a normal dev machine's tmpdir is outside as well.
222
+ const ambientTmp = (() => {
223
+ const candidates = [process.env.PK_TEST_TEMP_ROOT, os.tmpdir()];
224
+ for (const candidate of candidates) {
225
+ if (candidate && path.isAbsolute(path.resolve(candidate)) && !isInsideRepo(path.resolve(candidate))) {
226
+ return path.resolve(candidate);
227
+ }
228
+ }
229
+ return path.resolve(ROOT, '..');
230
+ })();
231
+ const poisonPaths = {};
232
+ for (const key of POISON_PATH_KEYS) {
233
+ poisonPaths[key] = path.join(ambientTmp, `poison-${key.toLowerCase()}`);
234
+ process.env[key] = poisonPaths[key];
235
+ }
236
+ for (const [key, value] of Object.entries(POISON_ENV)) process.env[key] = value;
237
+ // A tool-controlled knob: it must survive the sanitization and be honored.
238
+ const toolTempRoot = path.join(ambientTmp, 'pk-logging-gate-poison-temp');
239
+ process.env.PK_TEST_TEMP_ROOT = toolTempRoot;
240
+
241
+ // The browser that is resolvable BEFORE the install: after HOME/LOCALAPPDATA
242
+ // move it must still be reachable, otherwise the entries would fall back to
243
+ // the developer's real browser profile.
244
+ let preInstallChrome = null;
245
+ try { preInstallChrome = require('./helpers/find-chrome').findChromeDetailed(); } catch {}
246
+
247
+ const lane = installLoggingTestEnv({
248
+ caseId: 'P-QA-LOG-INTEGRATION-5025-portability',
249
+ prefix: 'logport',
250
+ extraEnv: LANE_OVERRIDES,
251
+ });
252
+ const installed = {};
253
+ for (const key of REQUIRED_ENV_KEYS) installed[key] = process.env[key];
254
+ const envProblems = [];
255
+ for (const key of REQUIRED_ENV_KEYS) {
256
+ const value = installed[key];
257
+ if (!value || !path.isAbsolute(value)) envProblems.push(`${key} is not an absolute path: ${value}`);
258
+ else if (!value.startsWith(lane.laneTmp)) envProblems.push(`${key} escapes the lane temp root: ${value}`);
259
+ }
260
+ if (isInsideRepo(lane.tempRoot)) envProblems.push(`temp root is inside the repository: ${lane.tempRoot}`);
261
+ if (installed.HOME === realHome) envProblems.push('HOME still points at the developer profile');
262
+ const evidenceDir = resolveEvidenceDir(path.join(ROOT, 'qa-autopilot/artifacts/parallel-20261023/logging-integration-5025/evidence/portability'), { PK_TEST_EVIDENCE_ROOT: path.join(lane.laneTmp, 'evidence-root') });
263
+ if (evidenceDir !== path.join(lane.laneTmp, 'evidence-root', 'portability')) envProblems.push(`PK_TEST_EVIDENCE_ROOT override not honoured: ${evidenceDir}`);
264
+ evidence.checks.isolation = {
265
+ tempRoot: lane.tempRoot,
266
+ tempRootOutsideRepo: !isInsideRepo(lane.tempRoot),
267
+ laneTmp: lane.laneTmp,
268
+ installedEnvKeys: installed,
269
+ isolatedEnvKeys: lane.isolatedEnvKeys,
270
+ evidenceOverride: evidenceDir,
271
+ problems: envProblems,
272
+ };
273
+ if (envProblems.length) failures.push(`isolation contract violated: ${envProblems.join('; ')}`);
274
+
275
+ // 2b. Poisoned-environment sentinel: what the install removes, what it
276
+ // keeps, what a grandchild inherits, and what the browser resolves to.
277
+ const sentinelProblems = [];
278
+ const sentinel = { poison: {}, removed: [], overrides: {}, child: null, chrome: {} };
279
+ const laneOwnedKeys = new Set([...MODULE_URL_KEYS, ...MODULE_FLAG_KEYS, ...MODULE_COMMAND_KEYS]);
280
+
281
+ for (const [key, value] of Object.entries(POISON_ENV)) {
282
+ sentinel.poison[key] = value;
283
+ const current = process.env[key];
284
+ if (laneOwnedKeys.has(key)) {
285
+ // Module endpoints / switches are reset to the lane's own values.
286
+ if (current === value) sentinelProblems.push(`${key} kept the poisoned ambient value`);
287
+ sentinel.overrides[key] = current;
288
+ continue;
289
+ }
290
+ if (LANE_OVERRIDES[key]) continue;
291
+ if (current !== undefined) sentinelProblems.push(`${key} survived the sanitization: ${current}`);
292
+ else sentinel.removed.push(key);
293
+ }
294
+ for (const [key, value] of Object.entries(LANE_OVERRIDES)) {
295
+ if (process.env[key] !== value) sentinelProblems.push(`${key} did not keep the explicit lane value ${value}: ${process.env[key]}`);
296
+ else sentinel.overrides[key] = value;
297
+ }
298
+ for (const key of POISON_PATH_KEYS) {
299
+ const value = process.env[key];
300
+ if (value === poisonPaths[key]) sentinelProblems.push(`${key} kept the poisoned path`);
301
+ if (!value || !path.isAbsolute(value)) sentinelProblems.push(`${key} is not an absolute path after the install: ${value}`);
302
+ else if (!value.startsWith(lane.laneTmp)) sentinelProblems.push(`${key} escapes the lane temp root: ${value}`);
303
+ }
304
+ if (process.env.PK_TEST_TEMP_ROOT !== toolTempRoot) sentinelProblems.push('PK_TEST_TEMP_ROOT did not survive the sanitization');
305
+ if (path.resolve(lane.tempRoot) !== path.resolve(toolTempRoot)) sentinelProblems.push(`the tool-controlled temp root was not honored: ${lane.tempRoot}`);
306
+
307
+ // A grandchild process must inherit the same clean base.
308
+ const childKeys = ['PATH', 'HOME', 'KB_DATA_DIR', 'KB_MODULES_AUTOSTART', 'KB_TERMINAL_URL', ...Object.keys(POISON_ENV)];
309
+ const probe = spawnSync(process.execPath, ['-e', `const keys=${JSON.stringify(childKeys)};const out={};for(const k of keys)out[k]=process.env[k]===undefined?null:process.env[k];process.stdout.write(JSON.stringify(out));`], { env: process.env, encoding: 'utf8' });
310
+ if (probe.status !== 0) {
311
+ sentinelProblems.push(`the grandchild environment probe failed: ${probe.stderr}`);
312
+ } else {
313
+ const childEnv = JSON.parse(probe.stdout);
314
+ for (const [key, value] of Object.entries(POISON_ENV)) {
315
+ if (laneOwnedKeys.has(key) || LANE_OVERRIDES[key]) continue;
316
+ if (childEnv[key] !== null) sentinelProblems.push(`the grandchild inherited ${key}`);
317
+ }
318
+ if (!childEnv.PATH) sentinelProblems.push('the grandchild lost PATH');
319
+ else if (childEnv.PATH !== process.env.PATH) sentinelProblems.push('the grandchild PATH differs from the sanitized base');
320
+ if (childEnv.HOME !== lane.dirs.home) sentinelProblems.push(`the grandchild HOME is not the lane home: ${childEnv.HOME}`);
321
+ if (childEnv.KB_MODULES_AUTOSTART !== '0') sentinelProblems.push('the grandchild did not inherit the lane module switch');
322
+ if (childEnv.KB_TERMINAL_URL !== DEAD_MODULE_URL) sentinelProblems.push(`the grandchild module endpoint is not the lane dead address: ${childEnv.KB_TERMINAL_URL}`);
323
+ sentinel.child = {
324
+ status: probe.status,
325
+ // Only key names and verdicts - the machine's own environment values are
326
+ // never written into the evidence.
327
+ inheritedNullKeys: Object.entries(childEnv).filter(([, value]) => value === null).map(([key]) => key),
328
+ pathPresent: Boolean(childEnv.PATH),
329
+ pathMatchesSanitizedBase: childEnv.PATH === process.env.PATH,
330
+ homeIsLaneHome: childEnv.HOME === lane.dirs.home,
331
+ moduleSwitch: childEnv.KB_MODULES_AUTOSTART,
332
+ moduleUrlIsLaneDeadAddress: childEnv.KB_TERMINAL_URL === DEAD_MODULE_URL,
333
+ };
334
+ }
335
+
336
+ // The real browser must still be resolvable after HOME/LOCALAPPDATA moved,
337
+ // and it must not be the developer's real profile.
338
+ const chromeProblems = [];
339
+ let resolvedChrome = null;
340
+ try {
341
+ resolvedChrome = require('./helpers/find-chrome').findChromeDetailed();
342
+ } catch (error) {
343
+ chromeProblems.push(`find-chrome failed after the install: ${error.code || error.message}`);
344
+ }
345
+ if (lane.chromePath) {
346
+ if (!resolvedChrome || resolvedChrome.path !== lane.chromePath) chromeProblems.push('the captured browser executable differs from the resolved one');
347
+ if (process.env.KB_CHROME_PATH !== lane.chromePath) chromeProblems.push('KB_CHROME_PATH does not carry the captured browser executable');
348
+ if (!resolvedChrome || resolvedChrome.source !== 'env') chromeProblems.push(`the browser was not resolved through the captured KB_CHROME_PATH: ${resolvedChrome && resolvedChrome.source}`);
349
+ if (!fs.existsSync(lane.chromePath)) chromeProblems.push('the captured browser executable does not exist');
350
+ }
351
+ if (preInstallChrome) {
352
+ if (!lane.chromePath) chromeProblems.push('the browser executable that was resolvable before the install was lost');
353
+ else if (lane.chromePath !== preInstallChrome.path) chromeProblems.push('the captured browser executable differs from the pre-install resolution');
354
+ }
355
+ for (const dir of lane.chromeProfileDirs) {
356
+ if (!dir.startsWith(lane.laneTmp)) chromeProblems.push(`the browser profile directory is outside the lane tree: ${dir}`);
357
+ }
358
+ // Chrome >= 136 also derives its default profile from
359
+ // <USERPROFILE>\AppData\Local\Google\Chrome\User Data, independently of
360
+ // LOCALAPPDATA. That derived directory must exist inside the owned home -
361
+ // and the developer's real default profile must never be part of it.
362
+ if (process.platform === 'win32') {
363
+ const ownedDerivedProfile = path.join(lane.dirs.home, 'AppData', 'Local', 'Google', 'Chrome', 'User Data');
364
+ if (!fs.existsSync(ownedDerivedProfile)) chromeProblems.push('the USERPROFILE-derived browser default profile directory is missing under the owned home');
365
+ if (!lane.chromeProfileDirs.includes(ownedDerivedProfile)) chromeProblems.push('the USERPROFILE-derived browser default profile directory is not scaffolded');
366
+ if (!ownedDerivedProfile.startsWith(lane.laneTmp)) chromeProblems.push('the USERPROFILE-derived browser default profile directory escapes the lane tree');
367
+ const realProfiles = [
368
+ ambientLocalAppData && path.join(ambientLocalAppData, 'Google', 'Chrome', 'User Data'),
369
+ realHome && path.join(realHome, 'AppData', 'Local', 'Google', 'Chrome', 'User Data'),
370
+ ].filter(Boolean);
371
+ for (const realProfile of realProfiles) {
372
+ if (lane.chromeProfileDirs.includes(realProfile)) chromeProblems.push('the developer default browser profile is part of the scaffold');
373
+ }
374
+ }
375
+ if (process.env.LOCALAPPDATA === ambientLocalAppData) chromeProblems.push('LOCALAPPDATA still points at the ambient directory');
376
+
377
+ // The PowerShell module analysis cache must be a FILE path whose parent
378
+ // directory exists; a directory target is wrong. The helper installs the
379
+ // same isolated cache FILE inside the owned parent on EVERY platform, so the
380
+ // structural contract (absolute owned parent, file-shaped target, never the
381
+ // poisoned ambient value) is asserted platform-independently; only the
382
+ // powershell.exe child probe is Windows-specific.
383
+ const psProblems = [];
384
+ const psCache = installed.PSModuleAnalysisCachePath;
385
+ const psCacheParent = path.dirname(psCache);
386
+ let psProbe = null;
387
+ if (!psCache || !path.isAbsolute(psCache)) psProblems.push(`the PowerShell cache path is not absolute: ${psCache}`);
388
+ else {
389
+ if (!fs.existsSync(psCacheParent) || !fs.statSync(psCacheParent).isDirectory()) {
390
+ psProblems.push(`the PowerShell cache parent directory is missing: ${psCacheParent}`);
391
+ }
392
+ if (fs.existsSync(psCache) && fs.statSync(psCache).isDirectory()) {
393
+ psProblems.push('the PowerShell cache path is a directory, not a file path');
394
+ }
395
+ if (!psCache.startsWith(lane.laneTmp)) psProblems.push('the PowerShell cache path is outside the lane tree');
396
+ if (psCache === poisonPaths.PSModuleAnalysisCachePath) psProblems.push('the PowerShell cache path kept the poisoned ambient value');
397
+ }
398
+ if (process.platform === 'win32') {
399
+ // The child prints one status word only - no environment values.
400
+ psProbe = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command',
401
+ "$ErrorActionPreference='Stop'; Get-Module -ListAvailable | Out-Null; Write-Output 'PS-CACHE-OK'"], {
402
+ env: { ...process.env, PSModuleAnalysisCachePath: psCache },
403
+ encoding: 'utf8',
404
+ timeout: 120000,
405
+ windowsHide: true,
406
+ });
407
+ if (psProbe.error) psProblems.push(`the PowerShell child could not be started: ${psProbe.error.code || psProbe.error.message}`);
408
+ else if (psProbe.status !== 0) psProblems.push(`the PowerShell child failed with the lane cache path (exit ${psProbe.status})`);
409
+ else if (!String(psProbe.stdout || '').includes('PS-CACHE-OK')) psProblems.push('the PowerShell child did not complete with the lane cache path');
410
+ if (psProbe.status === 0 && fs.existsSync(psCache) && fs.statSync(psCache).isDirectory()) {
411
+ psProblems.push('PowerShell created a directory at the cache file path');
412
+ }
413
+ }
414
+ sentinel.powerShell = {
415
+ parentExists: fs.existsSync(psCacheParent),
416
+ cachePathIsFile: !fs.existsSync(psCache) || !fs.statSync(psCache).isDirectory(),
417
+ childExitCode: psProbe ? psProbe.status : null,
418
+ childCompleted: psProbe ? String(psProbe.stdout || '').includes('PS-CACHE-OK') : null,
419
+ problems: psProblems,
420
+ };
421
+ sentinelProblems.push(...psProblems);
422
+ sentinel.chrome = {
423
+ captured: lane.chromePath,
424
+ resolved: resolvedChrome,
425
+ preInstall: preInstallChrome,
426
+ profileDirs: lane.chromeProfileDirs,
427
+ problems: chromeProblems,
428
+ skipped: !lane.chromePath && !preInstallChrome,
429
+ };
430
+ sentinelProblems.push(...chromeProblems);
431
+
432
+ // Own-process cleanup: the lane tree must be gone once the entry releases
433
+ // it, and the probe child must have exited.
434
+ lane.cleanup();
435
+ const laneTreeRemoved = !fs.existsSync(lane.laneTmp);
436
+ if (!laneTreeRemoved) sentinelProblems.push('the lane temp tree survived the cleanup');
437
+ sentinel.cleanup = {
438
+ laneTreeRemoved,
439
+ probeChildExited: probe.status !== null || Boolean(probe.error),
440
+ powerShellChildExited: psProbe ? (psProbe.status !== null || Boolean(psProbe.error)) : null,
441
+ };
442
+ if (!sentinel.cleanup.probeChildExited) sentinelProblems.push('the grandchild probe process did not exit');
443
+ if (psProbe && !sentinel.cleanup.powerShellChildExited) sentinelProblems.push('the PowerShell probe process did not exit');
444
+
445
+ evidence.checks.poisonedEnvSentinel = { ...sentinel, problems: sentinelProblems };
446
+ if (sentinelProblems.length) failures.push(`poisoned environment sentinel failed: ${sentinelProblems.join('; ')}`);
447
+
448
+ try { fs.rmdirSync(toolTempRoot); } catch {}
449
+
450
+ // 3. Dependency contract: every require target is tracked or declared.
451
+ const dependencyProblems = [];
452
+ const dependencyRows = [];
453
+ for (const file of SCAN_FILES) {
454
+ for (const target of requiresOf(file)) {
455
+ const base = path.resolve(path.dirname(path.join(ROOT, file)), target);
456
+ const candidates = [base, `${base}.js`, `${base}.json`, path.join(base, 'index.js')];
457
+ const hit = candidates.find(candidate => fs.existsSync(candidate));
458
+ const relative = path.relative(ROOT, hit || base).split(path.sep).join('/');
459
+ const exists = Boolean(hit);
460
+ const tracked = exists && isTracked(relative);
461
+ const declared = LANE_MANIFEST.includes(relative);
462
+ dependencyRows.push({ file, target, resolved: relative, exists, tracked, declared });
463
+ if (!exists) dependencyProblems.push(`${file} requires missing ${relative}`);
464
+ else if (!tracked && !declared) dependencyProblems.push(`${file} requires untracked, undeclared ${relative}`);
465
+ }
466
+ }
467
+ evidence.checks.dependencies = { rows: dependencyRows, problems: dependencyProblems };
468
+ if (dependencyProblems.length) failures.push(`dependency contract violated: ${dependencyProblems.join('; ')}`);
469
+
470
+ // 4. Classification: automatic vs manual-QA-only, per the runner's own rule.
471
+ const runnerSource = fs.readFileSync(path.join(ROOT, '_site', '_test', 'run-all-tests.js'), 'utf8');
472
+ const runnerUsesTestSuffix = runnerSource.includes("endsWith('-test.js')");
473
+ const classificationProblems = [];
474
+ if (!runnerUsesTestSuffix) classificationProblems.push('run-all-tests.js no longer selects *-test.js; classification must be re-derived');
475
+ for (const file of AUTOMATIC_ENTRIES) {
476
+ if (!file.endsWith('-test.js')) classificationProblems.push(`${file} is declared automatic but is not selected by the runner`);
477
+ }
478
+ if (MANUAL_ONLY.endsWith('-test.js')) classificationProblems.push(`${MANUAL_ONLY} must not match the automatic runner glob`);
479
+ const manualSource = fs.readFileSync(path.join(ROOT, MANUAL_ONLY), 'utf8');
480
+ const manualNeedsExpect = manualSource.includes('--expect');
481
+ if (!manualNeedsExpect) classificationProblems.push(`${MANUAL_ONLY} no longer requires an explicit --expect argument`);
482
+ for (const file of FROZEN_EXPLORATION) {
483
+ if (LANE_MANIFEST.includes(file)) classificationProblems.push(`${file} is frozen exploration history and must not be canonical`);
484
+ if (file.endsWith('-test.js')) classificationProblems.push(`${file} would be picked up by the automatic runner`);
485
+ }
486
+ evidence.checks.classification = {
487
+ runnerUsesTestSuffix,
488
+ automaticEntries: AUTOMATIC_ENTRIES,
489
+ manualOnly: MANUAL_ONLY,
490
+ manualRequiresExpectArgument: manualNeedsExpect,
491
+ frozenExploration: FROZEN_EXPLORATION,
492
+ problems: classificationProblems,
493
+ };
494
+ if (classificationProblems.length) failures.push(`classification contract violated: ${classificationProblems.join('; ')}`);
495
+
496
+ // 5. No real model/provider call in the lane entries.
497
+ const providerProblems = [];
498
+ const providerPattern = /api\.anthropic\.com|api\.openai\.com|api\.minimax|generativelanguage\.googleapis|sk-[A-Za-z0-9]{16,}/;
499
+ for (const file of SCAN_FILES) {
500
+ const code = stripComments(fs.readFileSync(path.join(ROOT, file), 'utf8'));
501
+ if (providerPattern.test(code)) providerProblems.push(`${file} references a provider endpoint or key`);
502
+ }
503
+ const standInUsers = AUTOMATIC_ENTRIES.concat([MANUAL_ONLY]).filter(file => fs.readFileSync(path.join(ROOT, file), 'utf8').includes('KB_AUTOMATION_FAKE_CLAUDE=1'));
504
+ evidence.checks.noRealModelCall = { providerProblems, standInUsers, standInCount: standInUsers.length };
505
+ if (providerProblems.length) failures.push(`provider reference found: ${providerProblems.join('; ')}`);
506
+ if (standInUsers.length === 0) failures.push('no entry declares the labelled offline analyzer stand-in');
507
+
508
+ // 6. Default evidence roots live inside the gitignored artifact tree.
509
+ const evidenceProblems = [];
510
+ const defaultEvidenceDirs = AUTOMATIC_ENTRIES.map(file => {
511
+ const code = fs.readFileSync(path.join(ROOT, file), 'utf8');
512
+ const match = /qa-autopilot\/artifacts\/[^'"]+/.exec(code);
513
+ return match ? match[0] : null;
514
+ }).filter(Boolean);
515
+ for (const dir of defaultEvidenceDirs) {
516
+ if (!isIgnored(dir)) evidenceProblems.push(`${dir} is not gitignored`);
517
+ }
518
+ evidence.checks.evidenceRoots = { defaultEvidenceDirs, problems: evidenceProblems };
519
+ if (evidenceProblems.length) failures.push(`evidence root not ignored: ${evidenceProblems.join('; ')}`);
520
+
521
+ // Manifest state for the Leader's commit step.
522
+ const manifestState = LANE_MANIFEST.map(file => ({ file, tracked: isTracked(file) }));
523
+ const pendingCommit = manifestState.filter(row => !row.tracked).map(row => row.file);
524
+ const strict = process.env.PK_LOGGING_GATE_STRICT_TRACKED === '1';
525
+ evidence.manifest = { files: manifestState, pendingCommit, strictMode: strict };
526
+ if (strict && pendingCommit.length) failures.push(`strict mode: manifest files not committed yet: ${pendingCommit.join(', ')}`);
527
+
528
+ evidence.verdict = failures.length
529
+ ? { status: 'FAIL', failures }
530
+ : { status: 'PASS', pendingCommit };
531
+ evidence.finishedAt = new Date().toISOString();
532
+ fs.writeFileSync(path.join(ARTIFACTS, 'portability-evidence.json'), JSON.stringify(evidence, null, 2) + '\n');
533
+
534
+ if (failures.length) {
535
+ console.error(`P-QA-LOG-INTEGRATION-5025 portability FAIL: ${failures.join(' | ')}`);
536
+ process.exitCode = 1;
537
+ return;
538
+ }
539
+ console.log(`P-QA-LOG-INTEGRATION-5025 portability PASS${pendingCommit.length ? ` (pending commit: ${pendingCommit.length} lane files)` : ''}`);
540
+ process.exitCode = 0;
541
+ }
542
+
543
+ try {
544
+ main();
545
+ } catch (error) {
546
+ // Fail closed: an unusable environment must never degrade into a PASS.
547
+ fs.mkdirSync(ARTIFACTS, { recursive: true });
548
+ fs.writeFileSync(path.join(ARTIFACTS, 'portability-evidence.json'), JSON.stringify({
549
+ caseId: 'P-QA-LOG-INTEGRATION-5025-portability',
550
+ verdict: { status: 'FAIL', failures: [String((error && error.stack) || error)] },
551
+ }, null, 2) + '\n');
552
+ console.error(`P-QA-LOG-INTEGRATION-5025 portability FAIL: ${error && error.message}`);
553
+ process.exitCode = 1;
554
+ }