@sanqianx/project-knowledge 5.0.23 → 5.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (401) hide show
  1. package/.agents/plugins/marketplace.json +20 -20
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/CHANGELOG.md +1361 -1346
  4. package/LICENSE +201 -201
  5. package/NOTICE +5 -5
  6. package/README.md +349 -349
  7. package/_modules/knowledge-engine/package.json +1 -1
  8. package/_modules/knowledge-engine/src/coordinator.js +48 -3
  9. package/_modules/knowledge-engine/src/runtime/automation-config.js +140 -140
  10. package/_modules/knowledge-engine/src/runtime/commit-conversation-binder.js +238 -238
  11. package/_modules/knowledge-engine/src/runtime/commit-processing-ledger.js +26 -26
  12. package/_modules/knowledge-engine/src/runtime/commit-prompt.js +193 -193
  13. package/_modules/knowledge-engine/src/runtime/commit-reconciler.js +394 -394
  14. package/_modules/knowledge-engine/src/runtime/contracts.js +282 -282
  15. package/_modules/knowledge-engine/src/runtime/conversation-store.js +389 -389
  16. package/_modules/knowledge-engine/src/runtime/evidence-bundle.js +228 -228
  17. package/_modules/knowledge-engine/src/runtime/git-runner.js +62 -62
  18. package/_modules/knowledge-engine/src/runtime/knowledge-promotion.js +505 -505
  19. package/_modules/knowledge-engine/src/runtime/knowledge-retrieval-service.js +400 -400
  20. package/_modules/knowledge-engine/src/runtime/markdown-knowledge-indexer.js +171 -171
  21. package/_modules/knowledge-engine/src/runtime/scanner.js +298 -298
  22. package/_modules/knowledge-engine/ui/app.js +23 -2
  23. package/_site/README.md +30 -30
  24. package/_site/_test/agent-capture-mcp-ui-test.js +68 -68
  25. package/_site/_test/agent-capture-ui-test.js +101 -101
  26. package/_site/_test/ai-profile-resolver-test.js +137 -137
  27. package/_site/_test/ai-profile-test.js +75 -75
  28. package/_site/_test/ai-vendor-presets-test.js +91 -91
  29. package/_site/_test/automatic-context-test.js +70 -70
  30. package/_site/_test/automation-queue-test.js +14 -14
  31. package/_site/_test/automation-ui-test.js +40 -40
  32. package/_site/_test/background-task-registry-test.js +43 -43
  33. package/_site/_test/baseline-schema-test.js +91 -91
  34. package/_site/_test/bin-cli-test.js +230 -230
  35. package/_site/_test/bridge-adapter-test.js +95 -95
  36. package/_site/_test/bridge-consumer-service-test.js +310 -310
  37. package/_site/_test/candidate-bin-content-test.js +35 -35
  38. package/_site/_test/candidate-product-assets-test.js +13 -13
  39. package/_site/_test/candidate-release-contract-test.js +14 -14
  40. package/_site/_test/capture-hook-dedup-test.js +158 -158
  41. package/_site/_test/cdp-browser-failure-test.js +103 -103
  42. package/_site/_test/chat-claudecodeui-match-test.js +92 -92
  43. package/_site/_test/claude-executable-discovery-test.js +90 -90
  44. package/_site/_test/claude-session-lifecycle-sweep-test.js +252 -252
  45. package/_site/_test/claude-workbench-test.js +174 -174
  46. package/_site/_test/cli-instance-management-test.js +62 -62
  47. package/_site/_test/client-capture-restart-e2e-test.js +189 -189
  48. package/_site/_test/codex-conversation-projection-test.js +60 -60
  49. package/_site/_test/codex-marketplace-scoped-path-test.js +186 -186
  50. package/_site/_test/codex-notify-capture-e2e-test.js +101 -101
  51. package/_site/_test/codex-notify-fanout-test.js +141 -134
  52. package/_site/_test/codex-notify-upgrade-test.js +253 -253
  53. package/_site/_test/commit-boundary-freeze-test.js +147 -147
  54. package/_site/_test/commit-conversation-binding-test.js +99 -99
  55. package/_site/_test/commit-evidence-test.js +110 -110
  56. package/_site/_test/configuration-generation-test.js +22 -22
  57. package/_site/_test/context-pack-test.js +200 -200
  58. package/_site/_test/conversation-api-test.js +119 -119
  59. package/_site/_test/conversation-origin-test.js +15 -15
  60. package/_site/_test/conversation-store-test.js +138 -138
  61. package/_site/_test/cross-repo-isolation-e2e-test.js +187 -187
  62. package/_site/_test/desktop-browser-compat-test.js +28 -28
  63. package/_site/_test/desktop-hook-runtime-regression-test.js +204 -204
  64. package/_site/_test/embedding-config-test.js +32 -32
  65. package/_site/_test/explicit-commit-processor-test.js +37 -37
  66. package/_site/_test/fixtures/fake-browser-exit.js +10 -10
  67. package/_site/_test/fixtures/fake-browser-hang.js +10 -10
  68. package/_site/_test/fixtures/integration-busy-worker.cjs +6 -6
  69. package/_site/_test/fixtures/make-git-repos.js +92 -92
  70. package/_site/_test/fixtures/retrieval-gold-queries.json +32 -32
  71. package/_site/_test/folder-picker-output-test.js +19 -19
  72. package/_site/_test/fresh-hook-reimport-test.js +53 -53
  73. package/_site/_test/fresh-product-data-test.js +56 -56
  74. package/_site/_test/full-integration-e2e-test.js +167 -167
  75. package/_site/_test/git-path-compatibility-test.js +80 -80
  76. package/_site/_test/git-validation-test.js +81 -81
  77. package/_site/_test/glm-ui-refresh-review-test.js +313 -404
  78. package/_site/_test/harness-isolation-test.js +138 -0
  79. package/_site/_test/helpers/cdp-browser.js +383 -0
  80. package/_site/_test/helpers/cdp-network-capture.js +66 -0
  81. package/_site/_test/helpers/find-chrome.js +34 -0
  82. package/_site/_test/helpers/free-port.js +8 -0
  83. package/_site/_test/helpers/logging-ui-fixture.js +131 -0
  84. package/_site/_test/helpers/module-fixture.js +282 -0
  85. package/_site/_test/helpers/parallel-engine-advanced-engine-child.js +45 -0
  86. package/_site/_test/helpers/parallel-engine-advanced-fault-writer.js +171 -0
  87. package/_site/_test/helpers/parallel-engine-advanced-harness.js +245 -0
  88. package/_site/_test/helpers/parallel-engine-advanced-standin-analyzer.js +80 -0
  89. package/_site/_test/helpers/parallel-engine-advanced-ui-host.js +177 -0
  90. package/_site/_test/helpers/parallel-engine-final-harness.js +314 -0
  91. package/_site/_test/helpers/parallel-engine-final-standin-analyzer.js +159 -0
  92. package/_site/_test/helpers/parallel-knowledge-fixture.js +255 -0
  93. package/_site/_test/helpers/parallel-logging-acceptance-fixture.js +111 -0
  94. package/_site/_test/helpers/parallel-logging-acceptance-proxy.js +106 -0
  95. package/_site/_test/helpers/parallel-logging-fix-r2-proxy.js +205 -0
  96. package/_site/_test/helpers/parallel-logging-integration-5025-env.js +432 -0
  97. package/_site/_test/helpers/parallel-memory-analyzer.js +81 -0
  98. package/_site/_test/helpers/parallel-memory-event-bridge.js +128 -0
  99. package/_site/_test/helpers/parallel-memory-shell.js +470 -0
  100. package/_site/_test/helpers/parallel-nav-isolation-env.js +389 -0
  101. package/_site/_test/helpers/parallel-nav-module-ui.js +186 -0
  102. package/_site/_test/helpers/parallel-nav-proxy.js +148 -0
  103. package/_site/_test/helpers/parallel-nav-shell.js +361 -0
  104. package/_site/_test/helpers/parallel-qa-engine-endpoint-guard.js +206 -0
  105. package/_site/_test/helpers/parallel-qa-engine-endpoint-isolate.js +257 -0
  106. package/_site/_test/helpers/parallel-retrieval-followup-corpus.js +293 -0
  107. package/_site/_test/helpers/parallel-retrieval-followup-next-session.js +70 -0
  108. package/_site/_test/helpers/parallel-retrieval-followup-r2-shell.js +737 -0
  109. package/_site/_test/helpers/parallel-retrieval-followup-r2-wb-host.js +82 -0
  110. package/_site/_test/helpers/parallel-retrieval-followup-shell.js +279 -0
  111. package/_site/_test/helpers/parallel-workbench-fixture.js +371 -0
  112. package/_site/_test/helpers/parallel-workbench-host.js +80 -0
  113. package/_site/_test/helpers/parallel-workbench-integration-5025-fixture.js +408 -0
  114. package/_site/_test/helpers/parallel-workbench-integration-5025-harness.js +593 -0
  115. package/_site/_test/helpers/parallel-workbench-integration-5025-host.js +70 -0
  116. package/_site/_test/helpers/parallel-workbench-integration-5025-launcher.js +240 -0
  117. package/_site/_test/helpers/parallel-workbench-integration-5025-runtime-harness.js +630 -0
  118. package/_site/_test/helpers/parallel-workbench-source-map.js +196 -0
  119. package/_site/_test/helpers/spawn-server.js +106 -0
  120. package/_site/_test/helpers/version-visibility-fixture.js +251 -0
  121. package/_site/_test/hook-runtime-endpoint-test.js +88 -88
  122. package/_site/_test/hook-status-repair-api-test.js +152 -152
  123. package/_site/_test/hook-trigger-test.js +85 -85
  124. package/_site/_test/hook-worktree-test.js +42 -42
  125. package/_site/_test/import-preflight-api-test.js +234 -234
  126. package/_site/_test/index-builder-test.js +41 -41
  127. package/_site/_test/index-error-display-contract-test.js +10 -10
  128. package/_site/_test/index-writer-concurrency-test.js +135 -135
  129. package/_site/_test/integration-adapters-test.js +262 -262
  130. package/_site/_test/integration-auto-repair-test.js +113 -113
  131. package/_site/_test/integration-capture-setup-test.js +118 -118
  132. package/_site/_test/integration-intent-test.js +81 -81
  133. package/_site/_test/integration-runtime-binding-a2-test.js +566 -566
  134. package/_site/_test/integration-runtime-binding-a3-test.js +227 -227
  135. package/_site/_test/integration-runtime-binding-test.js +473 -473
  136. package/_site/_test/integration-status-scan-test.js +29 -29
  137. package/_site/_test/integration-surface-coverage-test.js +164 -164
  138. package/_site/_test/kb-framework-test.js +57 -57
  139. package/_site/_test/kbpath-follow-test.js +63 -63
  140. package/_site/_test/knowledge-db-test.js +144 -144
  141. package/_site/_test/knowledge-engine-client-test.js +120 -109
  142. package/_site/_test/knowledge-language-control-test.js +170 -170
  143. package/_site/_test/knowledge-maintenance-test.js +40 -40
  144. package/_site/_test/knowledge-promotion-recovery-test.js +260 -260
  145. package/_site/_test/knowledge-query-test.js +54 -54
  146. package/_site/_test/knowledge-retrieval-service-test.js +77 -77
  147. package/_site/_test/knowledge-scopes-test.js +37 -37
  148. package/_site/_test/knowledge-storage-location-test.js +28 -28
  149. package/_site/_test/knowledge-storage-startup-test.js +52 -52
  150. package/_site/_test/knowledge-store-logs-supervision-test.js +89 -89
  151. package/_site/_test/launcher-readiness-test.js +80 -80
  152. package/_site/_test/legacy-claude-session-alias-test.js +106 -106
  153. package/_site/_test/legacy-routes-removed-test.js +47 -47
  154. package/_site/_test/legacy-workbench-exclusion-test.js +92 -92
  155. package/_site/_test/live-gateway-test.js +48 -48
  156. package/_site/_test/local-marketplace-test.js +16 -16
  157. package/_site/_test/log-redaction-test.js +58 -58
  158. package/_site/_test/logging-api-test.js +89 -89
  159. package/_site/_test/logging-sse-no-gap-test.js +88 -88
  160. package/_site/_test/logging-ui-test.js +107 -107
  161. package/_site/_test/markdown-delta-overlay-test.js +85 -85
  162. package/_site/_test/markdown-maintenance-api-test.js +75 -75
  163. package/_site/_test/markdown-maintenance-test.js +11 -11
  164. package/_site/_test/mcp-server-test.js +149 -149
  165. package/_site/_test/model-context-windows-test.js +89 -89
  166. package/_site/_test/module-agent-start-proxy-test.js +65 -65
  167. package/_site/_test/module-artifact-integrity-test.js +27 -27
  168. package/_site/_test/module-boundary-test.js +30 -30
  169. package/_site/_test/module-bridge-eventbridge-test.js +202 -202
  170. package/_site/_test/module-dynamic-port-test.js +118 -118
  171. package/_site/_test/module-index-proxy-test.js +33 -33
  172. package/_site/_test/module-model-configuration-test.js +44 -44
  173. package/_site/_test/module-process-lifecycle-test.js +35 -35
  174. package/_site/_test/module-stream-proxy-test.js +34 -34
  175. package/_site/_test/module-terminal-restart-test.js +63 -63
  176. package/_site/_test/module-wiring-unbind-race-test.js +59 -59
  177. package/_site/_test/native-context-integrations-test.js +86 -86
  178. package/_site/_test/non-release-ci-test.js +34 -34
  179. package/_site/_test/offline-boundary-isolation-test.js +32 -32
  180. package/_site/_test/orphaned-claim-recovery-test.js +80 -80
  181. package/_site/_test/package-boundary-test.js +43 -43
  182. package/_site/_test/package-startup-test.js +56 -56
  183. package/_site/_test/packaged-ui-smoke-test.js +88 -88
  184. package/_site/_test/parallel-ci-r9-posix-socket-budget-test.js +156 -0
  185. package/_site/_test/parallel-engine-advanced-eng005-test.js +136 -0
  186. package/_site/_test/parallel-engine-advanced-eng006-test.js +171 -0
  187. package/_site/_test/parallel-engine-advanced-eng007-reconcile-test.js +231 -0
  188. package/_site/_test/parallel-engine-advanced-eng009-test.js +208 -0
  189. package/_site/_test/parallel-engine-advanced-eng010-test.js +213 -0
  190. package/_site/_test/parallel-engine-advanced-eng011-ui-probe.js +459 -0
  191. package/_site/_test/parallel-engine-final-eng002-test.js +255 -0
  192. package/_site/_test/parallel-engine-final-eng007-test.js +269 -0
  193. package/_site/_test/parallel-engine-final-eng011-test.js +197 -0
  194. package/_site/_test/parallel-engine-final-eng012-test.js +354 -0
  195. package/_site/_test/parallel-knowledge-client-error-code-test.js +184 -0
  196. package/_site/_test/parallel-knowledge-engine-test.js +353 -0
  197. package/_site/_test/parallel-knowledge-retrieval-test.js +292 -0
  198. package/_site/_test/parallel-knowledge-vector-test.js +168 -0
  199. package/_site/_test/parallel-linux-ci-r7-log007-day-test.js +110 -0
  200. package/_site/_test/parallel-logging-acceptance-log003-test.js +224 -0
  201. package/_site/_test/parallel-logging-acceptance-log004-test.js +231 -0
  202. package/_site/_test/parallel-logging-acceptance-log005-test.js +208 -0
  203. package/_site/_test/parallel-logging-acceptance-log006-test.js +214 -0
  204. package/_site/_test/parallel-logging-acceptance-log007-test.js +223 -0
  205. package/_site/_test/parallel-logging-acceptance-log008-test.js +180 -0
  206. package/_site/_test/parallel-logging-fix-r2-crash-probe.js +271 -0
  207. package/_site/_test/parallel-logging-fix-r2-gap-test.js +294 -0
  208. package/_site/_test/parallel-logging-fix-r2-normalhook-test.js +330 -0
  209. package/_site/_test/parallel-logging-integration-5025-portability-test.js +554 -0
  210. package/_site/_test/parallel-memory-candidate-test.js +301 -0
  211. package/_site/_test/parallel-memory-manual-test.js +197 -0
  212. package/_site/_test/parallel-memory-scope-test.js +228 -0
  213. package/_site/_test/parallel-memory-source-test.js +227 -0
  214. package/_site/_test/parallel-memory-sync-test.js +238 -0
  215. package/_site/_test/parallel-memory-view-r8-reload-gate-test.js +123 -0
  216. package/_site/_test/parallel-nav-failure-test.js +119 -0
  217. package/_site/_test/parallel-nav-isolation-test.js +308 -0
  218. package/_site/_test/parallel-nav-isolation-vector-path-test.js +90 -0
  219. package/_site/_test/parallel-nav-offline-test.js +272 -0
  220. package/_site/_test/parallel-nav-operability-test.js +257 -0
  221. package/_site/_test/parallel-nav-switch-test.js +247 -0
  222. package/_site/_test/parallel-nav-theme-test.js +130 -0
  223. package/_site/_test/parallel-nav-viewport-test.js +310 -0
  224. package/_site/_test/parallel-qa-engine-endpoint-guard-test.js +273 -0
  225. package/_site/_test/parallel-retrieval-followup-citation-test.js +219 -0
  226. package/_site/_test/parallel-retrieval-followup-corpus-test.js +287 -0
  227. package/_site/_test/parallel-workbench-independent-host.js +262 -0
  228. package/_site/_test/parallel-workbench-integration-5025-abort-probe.js +340 -0
  229. package/_site/_test/parallel-workbench-integration-5025-drafts-probe.js +588 -0
  230. package/_site/_test/parallel-workbench-integration-5025-env-check.js +317 -0
  231. package/_site/_test/parallel-workbench-integration-5025-model-probe.js +342 -0
  232. package/_site/_test/parallel-workbench-integration-5025-ordering-probe.js +326 -0
  233. package/_site/_test/parallel-workbench-model-probe.js +336 -0
  234. package/_site/_test/parallel-workbench-offline-test.js +169 -0
  235. package/_site/_test/parallel-workbench-provenance-trace.js +134 -0
  236. package/_site/_test/parallel-workbench-source-match.js +206 -0
  237. package/_site/_test/parallel-workbench-standalone-turn.js +349 -0
  238. package/_site/_test/path-consistency-test.js +151 -151
  239. package/_site/_test/pending-sweep-test.js +9 -9
  240. package/_site/_test/post-commit-automation-test.js +87 -87
  241. package/_site/_test/pr-consumer-contract-test.js +55 -55
  242. package/_site/_test/product-brand-contract-test.js +25 -25
  243. package/_site/_test/product-diagnostics-ui-test.js +93 -93
  244. package/_site/_test/product-empty-state-test.js +148 -0
  245. package/_site/_test/product-import-ui-test.js +219 -104
  246. package/_site/_test/product-navigation-test.js +152 -0
  247. package/_site/_test/product-progress-status-test.js +84 -84
  248. package/_site/_test/project-delete-recovery-test.js +64 -64
  249. package/_site/_test/project-domain-create-test.js +91 -0
  250. package/_site/_test/project-domain-scope-retrieval-test.js +214 -0
  251. package/_site/_test/project-git-init-confirm-test.js +115 -0
  252. package/_site/_test/project-goal-editor-test.js +144 -144
  253. package/_site/_test/project-import-duplicate-alias-test.js +134 -0
  254. package/_site/_test/project-import-unicode-restart-test.js +140 -0
  255. package/_site/_test/project-lifecycle-transaction-test.js +106 -106
  256. package/_site/_test/project-module-partial-recovery-test.js +222 -0
  257. package/_site/_test/project-remove-running-guard-test.js +79 -79
  258. package/_site/_test/project-store-test.js +90 -90
  259. package/_site/_test/project-unbind-late-read-ui-test.js +250 -0
  260. package/_site/_test/project-unbind-writer-guard-test.js +231 -0
  261. package/_site/_test/prompt-settings-test.js +115 -115
  262. package/_site/_test/protected-architecture-gate-test.js +122 -122
  263. package/_site/_test/refactor-characterization-test.js +36 -36
  264. package/_site/_test/registry-events-test.js +38 -38
  265. package/_site/_test/release-version-sync-test.js +115 -115
  266. package/_site/_test/requirement-binding-test.js +113 -113
  267. package/_site/_test/requirement-recorder-test.js +173 -173
  268. package/_site/_test/run-all-tests.js +173 -161
  269. package/_site/_test/runtime-endpoint-test.js +64 -64
  270. package/_site/_test/scanner-test.js +83 -83
  271. package/_site/_test/server-security-test.js +96 -96
  272. package/_site/_test/sessions-stream-test.js +93 -93
  273. package/_site/_test/shared-contracts-test.js +58 -58
  274. package/_site/_test/shared-scope-root-binding-test.js +74 -67
  275. package/_site/_test/simple-import-test.js +98 -98
  276. package/_site/_test/startup-analysis-disabled-test.js +16 -16
  277. package/_site/_test/storage-foundation-test.js +78 -78
  278. package/_site/_test/structured-logger-test.js +101 -101
  279. package/_site/_test/t07b-cln-005-coverage-test.js +212 -0
  280. package/_site/_test/team-knowledge-store-sparse-checkout-test.js +196 -196
  281. package/_site/_test/team-knowledge-store-test.js +132 -132
  282. package/_site/_test/test-server-cleanup-test.js +35 -35
  283. package/_site/_test/test-server-module-isolation-test.js +37 -37
  284. package/_site/_test/tracking-start-test.js +144 -144
  285. package/_site/_test/vector-storage-root-test.js +75 -75
  286. package/_site/_test/version-visibility-browser-probe.js +249 -0
  287. package/_site/_test/version-visibility-test.js +92 -0
  288. package/_site/_test/workbench-context-receipts-test.js +22 -22
  289. package/_site/_test/workbench-permission-test.js +117 -117
  290. package/_site/_test/zcode-capture-integration-test.js +112 -112
  291. package/_site/lib/ai-profile-resolver.js +78 -78
  292. package/_site/lib/ai-vendor-presets.js +83 -83
  293. package/_site/lib/ai-workspace.js +104 -104
  294. package/_site/lib/atomic-file.js +204 -204
  295. package/_site/lib/automation-config.js +140 -140
  296. package/_site/lib/bridge-adapter.js +260 -260
  297. package/_site/lib/bridge-consumer-service.js +402 -402
  298. package/_site/lib/capture-hook-config.js +108 -108
  299. package/_site/lib/claude-cli-runner.js +1599 -1599
  300. package/_site/lib/cli-instances.js +43 -43
  301. package/_site/lib/codex-context-status.js +17 -17
  302. package/_site/lib/codex-notify-config.js +193 -193
  303. package/_site/lib/commit-conversation-binder.js +247 -247
  304. package/_site/lib/commit-processing-ledger.js +27 -27
  305. package/_site/lib/commit-prompt.js +202 -202
  306. package/_site/lib/commit-reconciler.js +444 -444
  307. package/_site/lib/context-pack-builder.js +299 -299
  308. package/_site/lib/contracts.js +291 -291
  309. package/_site/lib/conversation-exclusions.js +204 -204
  310. package/_site/lib/conversation-query-service.js +161 -161
  311. package/_site/lib/conversation-store.js +387 -387
  312. package/_site/lib/data-dir.js +13 -13
  313. package/_site/lib/embedding-service.js +85 -85
  314. package/_site/lib/engine-connection.js +93 -93
  315. package/_site/lib/engine-knowledge-client.js +76 -72
  316. package/_site/lib/evidence-bundle.js +228 -228
  317. package/_site/lib/folder-picker-output.js +24 -24
  318. package/_site/lib/git-path.js +14 -14
  319. package/_site/lib/git-runner.js +62 -62
  320. package/_site/lib/github-team-store.js +1175 -1175
  321. package/_site/lib/hook-manager.js +203 -203
  322. package/_site/lib/index-builder.js +157 -157
  323. package/_site/lib/index-service.js +173 -173
  324. package/_site/lib/integration-auto-repair.js +77 -77
  325. package/_site/lib/integration-installer.js +1240 -1240
  326. package/_site/lib/integration-intent.js +88 -88
  327. package/_site/lib/integration-status-scan.js +99 -99
  328. package/_site/lib/integration-status-worker.js +14 -14
  329. package/_site/lib/kb-framework.js +191 -191
  330. package/_site/lib/kb-validator.js +124 -124
  331. package/_site/lib/knowledge-db.js +363 -363
  332. package/_site/lib/knowledge-promotion.js +435 -435
  333. package/_site/lib/knowledge-retrieval-service.js +401 -401
  334. package/_site/lib/knowledge-schema.js +121 -121
  335. package/_site/lib/knowledge-tool-runtime.js +366 -366
  336. package/_site/lib/live-gateway.js +78 -78
  337. package/_site/lib/llm-client.js +173 -173
  338. package/_site/lib/markdown-knowledge-indexer.js +230 -230
  339. package/_site/lib/model-context-windows.js +82 -82
  340. package/_site/lib/module-bridge.js +874 -874
  341. package/_site/lib/module-port-resolver.js +57 -57
  342. package/_site/lib/post-commit-automation.js +141 -141
  343. package/_site/lib/product-data.js +35 -35
  344. package/_site/lib/project-lifecycle-service.js +554 -554
  345. package/_site/lib/project-registry-store.js +129 -129
  346. package/_site/lib/project-store.js +268 -268
  347. package/_site/lib/prompt-registry.js +148 -148
  348. package/_site/lib/public-version-info.js +37 -0
  349. package/_site/lib/registry-events.js +16 -16
  350. package/_site/lib/requirement-adapters.js +10 -10
  351. package/_site/lib/requirement-binder.js +112 -112
  352. package/_site/lib/requirement-recorder.js +278 -278
  353. package/_site/lib/runtime-control.js +89 -89
  354. package/_site/lib/runtime-endpoint.js +160 -160
  355. package/_site/lib/scanner.js +298 -298
  356. package/_site/lib/server-app.js +1672 -1664
  357. package/_site/lib/settings-store.js +153 -153
  358. package/_site/lib/storage-layout.js +166 -166
  359. package/_site/lib/structured-logger.js +574 -574
  360. package/_site/lib/zcode-context-integration.js +60 -60
  361. package/_site/scripts/codex-notify-fanout.cjs +95 -95
  362. package/_site/scripts/folder-picker.ps1 +156 -156
  363. package/_site/scripts/hook-trigger.js +158 -158
  364. package/_site/scripts/install-module-candidates.js +69 -69
  365. package/_site/scripts/pack-module-candidates.js +89 -89
  366. package/_site/scripts/sync-product-content.js +28 -28
  367. package/_site/scripts/sync-release-version.js +164 -164
  368. package/_site/scripts/vendor-modules.js +49 -49
  369. package/_site/scripts/verify-module-runtime.js +50 -50
  370. package/_site/scripts/verify-product-runtime.js +36 -36
  371. package/_site/scripts/verify-retrieval-gold.js +83 -83
  372. package/_site/server.js +15 -15
  373. package/_site/start.bat +26 -26
  374. package/_site/stop.bat +11 -11
  375. package/bin/project-knowledge-integrations.js +254 -254
  376. package/bin/project-knowledge-kb.js +67 -67
  377. package/bin/project-knowledge-mcp.js +201 -201
  378. package/bin/project-knowledge.js +269 -170
  379. package/claude-prompts.json +21 -21
  380. package/docs/README.zh-CN.md +207 -205
  381. package/docs/assets/architecture.svg +181 -181
  382. package/docs/assets/logo.svg +49 -49
  383. package/docs/fresh-v5-start.md +44 -44
  384. package/docs/leader-glm-workbench-playbook.md +122 -122
  385. package/docs/project-registry-schema.md +33 -33
  386. package/docs/release-5.0.16-acceptance.md +176 -176
  387. package/docs/release-5.0.17-acceptance.md +117 -117
  388. package/docs/release-5.0.19-acceptance.md +39 -39
  389. package/docs/team-knowledge-mode-a-plan.md +73 -73
  390. package/docs/testing-strategy.md +33 -33
  391. package/module-runtime-manifest.json +70 -67
  392. package/package.json +113 -110
  393. package/plugins/project-knowledge/.claude-plugin/plugin.json +1 -1
  394. package/plugins/project-knowledge/.codex-plugin/plugin.json +1 -1
  395. package/plugins/project-knowledge/.mcp.json +1 -1
  396. package/templates/change.md +30 -30
  397. package/templates/project-readme.md +52 -52
  398. package/ui/index.html +3 -2
  399. package/ui/version-info.css +44 -0
  400. package/ui/version-info.js +24 -0
  401. package/vendor-manifest.json +55 -55
@@ -1,101 +1,101 @@
1
- const assert = require('assert');
2
- const fs = require('fs');
3
- const os = require('os');
4
- const path = require('path');
5
- const { StorageLayout } = require('../lib/storage-layout');
6
- const { Logger, LogRepository, localDay } = require('../lib/structured-logger');
7
-
8
- (async () => {
9
- const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pk-logger-v3-'));
10
- const layout = new StorageLayout({ dataDir });
11
- const config = { levels: ['trace', 'debug', 'info', 'warn', 'error', 'fatal'] };
12
- let stderr = '';
13
- const logger = new Logger({
14
- layout,
15
- settingsProvider: () => config,
16
- secrets: ['known-secret-value'],
17
- stderr: { write(value) { stderr += String(value); } },
18
- });
19
- const published = [];
20
- logger.subscribe(record => published.push(record));
21
- logger.subscribe(() => { throw new Error('subscriber failure must be isolated'); });
22
- const child = logger.child({ component: 'commit-reconciler', projectId: 'project-a', operationId: 'op-1', runId: 'run-1', commitSha: 'abc' });
23
- const cause = new Error('cause known-secret-value');
24
- cause.code = 'ECAUSE';
25
- const failure = new Error('Bearer top-secret-token');
26
- failure.code = 'ETEST';
27
- failure.cause = cause;
28
- for (const level of ['trace', 'debug', 'info', 'warn', 'error', 'fatal']) {
29
- await child[level](`test.${level}`, `${level} message`, {
30
- phase: 'test',
31
- error: level === 'error' ? failure : null,
32
- context: { apiKey: 'known-secret-value', nested: { authorization: 'Bearer nested-token', safe: 'kept' } },
33
- });
34
- }
35
- await logger.close();
36
-
37
- const projectDirectory = layout.getLogPath('project', 'project-a');
38
- const files = fs.readdirSync(projectDirectory).filter(file => file.endsWith('.jsonl'));
39
- assert.deepStrictEqual(files, [`${localDay()}.jsonl`], 'one project/day must use exactly one file');
40
- assert(!files.some(file => /\.\d{3}\.jsonl$/.test(file)), 'v13 writer must never create size segments');
41
- const allText = fs.readFileSync(path.join(projectDirectory, files[0]), 'utf8');
42
- assert(!allText.includes('known-secret-value'));
43
- assert(!allText.includes('top-secret-token'));
44
- assert(!allText.includes('nested-token'));
45
- assert(allText.includes('[REDACTED]'));
46
- assert.strictEqual(published.length, 6, 'each durable append must publish exactly once');
47
- assert.deepStrictEqual(published.map(record => record.level), ['trace', 'debug', 'info', 'warn', 'error', 'fatal']);
48
- for (const line of allText.trim().split(/\r?\n/)) {
49
- const record = JSON.parse(line);
50
- assert.strictEqual(record.schema, 'log/v2');
51
- assert.strictEqual(record.projectId, 'project-a');
52
- assert.strictEqual(record.operationId, 'op-1');
53
- assert(record.id && record.ts && record.event);
54
- }
55
-
56
- await logger.info('system.completed', 'System record', { component: 'server', operationId: 'op-system' });
57
- await logger.close();
58
- assert(fs.existsSync(path.join(layout.getLogPath('system'), `${localDay()}.jsonl`)), 'unscoped logs belong to system/day');
59
-
60
- const repository = new LogRepository({ layout, secrets: ['known-secret-value'] });
61
- const first = repository.query({ pageSize: 2, projectId: 'project-a' });
62
- assert.strictEqual(first.entries.length, 2);
63
- assert(first.nextCursor);
64
- const second = repository.query({ pageSize: 2, projectId: 'project-a', cursor: first.nextCursor });
65
- assert.strictEqual(second.entries.length, 2);
66
- assert.notStrictEqual(first.entries[0].id, second.entries[0].id);
67
- assert.throws(
68
- () => repository.query({ pageSize: 3, projectId: 'project-a', cursor: first.nextCursor }),
69
- error => error.code === 'LOG_CURSOR_EXPIRED',
70
- );
71
-
72
- const exportPath = path.join(dataDir, 'exports', 'diagnostics.jsonl');
73
- const exported = repository.exportToFile(exportPath, { projectId: 'project-a' });
74
- assert.strictEqual(exported.count, 6);
75
- assert(!fs.readFileSync(exportPath, 'utf8').includes('known-secret-value'));
76
- assert.strictEqual(stderr, '');
77
- assert.strictEqual(typeof repository.cleanup, 'undefined', 'production log cleanup API must not exist');
78
-
79
- const blocker = path.join(dataDir, 'not-a-directory');
80
- fs.writeFileSync(blocker, 'blocker');
81
- const failingLayout = {
82
- getDataDir() { return dataDir; },
83
- getLogPath() { return path.join(blocker, 'logs'); },
84
- };
85
- const failing = new Logger({
86
- layout: failingLayout,
87
- settingsProvider: () => config,
88
- secrets: ['known-secret-value'],
89
- stderr: { write(value) { stderr += String(value); } },
90
- });
91
- const failingChild = failing.child({ component: 'failure-test' });
92
- await failingChild.error('logger.failure.test', 'known-secret-value', { error: new Error('known-secret-value') });
93
- assert.strictEqual(failing.getHealth().status, 'degraded', 'parent and child must share logger health');
94
- assert.strictEqual(failingChild.getHealth().status, 'degraded');
95
- assert(stderr.includes('logger fallback'));
96
- assert(!stderr.includes('known-secret-value'));
97
- console.log('structured-logger-test PASS');
98
- })().catch(error => {
99
- console.error(error.stack || error.message);
100
- process.exitCode = 1;
101
- });
1
+ const assert = require('assert');
2
+ const fs = require('fs');
3
+ const os = require('os');
4
+ const path = require('path');
5
+ const { StorageLayout } = require('../lib/storage-layout');
6
+ const { Logger, LogRepository, localDay } = require('../lib/structured-logger');
7
+
8
+ (async () => {
9
+ const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pk-logger-v3-'));
10
+ const layout = new StorageLayout({ dataDir });
11
+ const config = { levels: ['trace', 'debug', 'info', 'warn', 'error', 'fatal'] };
12
+ let stderr = '';
13
+ const logger = new Logger({
14
+ layout,
15
+ settingsProvider: () => config,
16
+ secrets: ['known-secret-value'],
17
+ stderr: { write(value) { stderr += String(value); } },
18
+ });
19
+ const published = [];
20
+ logger.subscribe(record => published.push(record));
21
+ logger.subscribe(() => { throw new Error('subscriber failure must be isolated'); });
22
+ const child = logger.child({ component: 'commit-reconciler', projectId: 'project-a', operationId: 'op-1', runId: 'run-1', commitSha: 'abc' });
23
+ const cause = new Error('cause known-secret-value');
24
+ cause.code = 'ECAUSE';
25
+ const failure = new Error('Bearer top-secret-token');
26
+ failure.code = 'ETEST';
27
+ failure.cause = cause;
28
+ for (const level of ['trace', 'debug', 'info', 'warn', 'error', 'fatal']) {
29
+ await child[level](`test.${level}`, `${level} message`, {
30
+ phase: 'test',
31
+ error: level === 'error' ? failure : null,
32
+ context: { apiKey: 'known-secret-value', nested: { authorization: 'Bearer nested-token', safe: 'kept' } },
33
+ });
34
+ }
35
+ await logger.close();
36
+
37
+ const projectDirectory = layout.getLogPath('project', 'project-a');
38
+ const files = fs.readdirSync(projectDirectory).filter(file => file.endsWith('.jsonl'));
39
+ assert.deepStrictEqual(files, [`${localDay()}.jsonl`], 'one project/day must use exactly one file');
40
+ assert(!files.some(file => /\.\d{3}\.jsonl$/.test(file)), 'v13 writer must never create size segments');
41
+ const allText = fs.readFileSync(path.join(projectDirectory, files[0]), 'utf8');
42
+ assert(!allText.includes('known-secret-value'));
43
+ assert(!allText.includes('top-secret-token'));
44
+ assert(!allText.includes('nested-token'));
45
+ assert(allText.includes('[REDACTED]'));
46
+ assert.strictEqual(published.length, 6, 'each durable append must publish exactly once');
47
+ assert.deepStrictEqual(published.map(record => record.level), ['trace', 'debug', 'info', 'warn', 'error', 'fatal']);
48
+ for (const line of allText.trim().split(/\r?\n/)) {
49
+ const record = JSON.parse(line);
50
+ assert.strictEqual(record.schema, 'log/v2');
51
+ assert.strictEqual(record.projectId, 'project-a');
52
+ assert.strictEqual(record.operationId, 'op-1');
53
+ assert(record.id && record.ts && record.event);
54
+ }
55
+
56
+ await logger.info('system.completed', 'System record', { component: 'server', operationId: 'op-system' });
57
+ await logger.close();
58
+ assert(fs.existsSync(path.join(layout.getLogPath('system'), `${localDay()}.jsonl`)), 'unscoped logs belong to system/day');
59
+
60
+ const repository = new LogRepository({ layout, secrets: ['known-secret-value'] });
61
+ const first = repository.query({ pageSize: 2, projectId: 'project-a' });
62
+ assert.strictEqual(first.entries.length, 2);
63
+ assert(first.nextCursor);
64
+ const second = repository.query({ pageSize: 2, projectId: 'project-a', cursor: first.nextCursor });
65
+ assert.strictEqual(second.entries.length, 2);
66
+ assert.notStrictEqual(first.entries[0].id, second.entries[0].id);
67
+ assert.throws(
68
+ () => repository.query({ pageSize: 3, projectId: 'project-a', cursor: first.nextCursor }),
69
+ error => error.code === 'LOG_CURSOR_EXPIRED',
70
+ );
71
+
72
+ const exportPath = path.join(dataDir, 'exports', 'diagnostics.jsonl');
73
+ const exported = repository.exportToFile(exportPath, { projectId: 'project-a' });
74
+ assert.strictEqual(exported.count, 6);
75
+ assert(!fs.readFileSync(exportPath, 'utf8').includes('known-secret-value'));
76
+ assert.strictEqual(stderr, '');
77
+ assert.strictEqual(typeof repository.cleanup, 'undefined', 'production log cleanup API must not exist');
78
+
79
+ const blocker = path.join(dataDir, 'not-a-directory');
80
+ fs.writeFileSync(blocker, 'blocker');
81
+ const failingLayout = {
82
+ getDataDir() { return dataDir; },
83
+ getLogPath() { return path.join(blocker, 'logs'); },
84
+ };
85
+ const failing = new Logger({
86
+ layout: failingLayout,
87
+ settingsProvider: () => config,
88
+ secrets: ['known-secret-value'],
89
+ stderr: { write(value) { stderr += String(value); } },
90
+ });
91
+ const failingChild = failing.child({ component: 'failure-test' });
92
+ await failingChild.error('logger.failure.test', 'known-secret-value', { error: new Error('known-secret-value') });
93
+ assert.strictEqual(failing.getHealth().status, 'degraded', 'parent and child must share logger health');
94
+ assert.strictEqual(failingChild.getHealth().status, 'degraded');
95
+ assert(stderr.includes('logger fallback'));
96
+ assert(!stderr.includes('known-secret-value'));
97
+ console.log('structured-logger-test PASS');
98
+ })().catch(error => {
99
+ console.error(error.stack || error.message);
100
+ process.exitCode = 1;
101
+ });
@@ -0,0 +1,212 @@
1
+ // _site/_test/t07b-cln-005-coverage-test.js
2
+ //
3
+ // T07B ledger coverage for spec CLN-005 "活跃数据保留"
4
+ // (qa-autopilot/config/test-cases.json).
5
+ //
6
+ // steps : "ACTIVE/FAILED/RETAIN与旧PASSED目录混合。"
7
+ // expected : "仅PASSED且到期进入清单;首失败/检查点/基线永不自动删。"
8
+ //
9
+ // The behaviour under test is the real cleanup planner of the QA control
10
+ // package (qa-autopilot/lib/safety.cjs -> cleanupPlan / applyCleanup) together
11
+ // with the real checkpoint store (qa-autopilot/lib/state.cjs -> Store). The
12
+ // fixture is an isolated QA root that mixes every run status, so the plan is
13
+ // checked against the spec itself and not against a hand-written expectation.
14
+ //
15
+ // Every assertion message starts with "QA-SPEC-CLN-005" so the controller can
16
+ // confirm on its own that this expectation is guarded.
17
+
18
+ 'use strict';
19
+
20
+ const assert = require('node:assert/strict');
21
+ const fs = require('node:fs');
22
+ const os = require('node:os');
23
+ const path = require('node:path');
24
+
25
+ const CONTROL_ROOT = path.resolve(__dirname, '..', '..', 'qa-autopilot');
26
+ const SAFETY_LIB = path.join(CONTROL_ROOT, 'lib', 'safety.cjs');
27
+ const STATE_LIB = path.join(CONTROL_ROOT, 'lib', 'state.cjs');
28
+
29
+ if (!fs.existsSync(SAFETY_LIB) || !fs.existsSync(STATE_LIB)) {
30
+ console.error('t07b-cln-005-coverage-test FAILED: QA control library is missing at ' + CONTROL_ROOT);
31
+ process.exit(1);
32
+ }
33
+
34
+ const { cleanupPlan, applyCleanup, ownedRun, setRunStatus, readJSON, atomicJSON, hash } = require(SAFETY_LIB);
35
+ const { Store } = require(STATE_LIB);
36
+
37
+ const EPOCH = new Date(0).toISOString();
38
+ const RETENTION_HOURS = 1;
39
+ const FIRST_FAILURE_LOG = 'first failure stdout (redacted)\n';
40
+ const FIRST_FAILURE_SHOT = Buffer.from('89504e470d0a1a0a0000000d49484452', 'hex');
41
+
42
+ function writeFile(file, content) {
43
+ fs.mkdirSync(path.dirname(file), { recursive: true });
44
+ fs.writeFileSync(file, content);
45
+ }
46
+
47
+ // Creates a real owned run directory through the control library, then pins the
48
+ // finished timestamp so "expired" and "not expired" are decided by the fixture
49
+ // and not by wall-clock luck.
50
+ function ownedRunWithStatus(qa, id, status, finishedAt) {
51
+ const dir = ownedRun(qa, id);
52
+ setRunStatus(dir, status);
53
+ const marker = path.join(dir, '.qa-owner.json');
54
+ const state = readJSON(marker);
55
+ state.finishedAt = finishedAt;
56
+ atomicJSON(marker, state);
57
+ return dir;
58
+ }
59
+
60
+ function readBytes(file) {
61
+ return fs.readFileSync(file);
62
+ }
63
+
64
+ const qa = fs.mkdtempSync(path.join(os.tmpdir(), 'qa-cln005-'));
65
+ try {
66
+ const runsRoot = path.join(qa, '.runtime', 'runs');
67
+
68
+ // --- mixed run fixture: only one of these may ever reach the cleanup list ---
69
+ const expired = ownedRunWithStatus(qa, 'expired-passed', 'PASSED', EPOCH);
70
+ writeFile(path.join(expired, 'temp.txt'), 'expired run payload');
71
+ writeFile(path.join(expired, 'logs', 'stdout.log'), 'expired run log');
72
+
73
+ const fresh = ownedRunWithStatus(qa, 'fresh-passed', 'PASSED', new Date().toISOString());
74
+ writeFile(path.join(fresh, 'temp.txt'), 'fresh run payload');
75
+
76
+ // An ACTIVE run is protected by its status alone, even when it looks ancient.
77
+ const active = ownedRunWithStatus(qa, 'active-run', 'ACTIVE', EPOCH);
78
+ writeFile(path.join(active, 'temp.txt'), 'active run payload');
79
+
80
+ const failed = ownedRunWithStatus(qa, 'failed-run', 'FAILED', EPOCH);
81
+ writeFile(path.join(failed, 'first-failure', 'stdout.log'), FIRST_FAILURE_LOG);
82
+ writeFile(path.join(failed, 'first-failure', 'screenshot.png'), FIRST_FAILURE_SHOT);
83
+
84
+ const retained = ownedRunWithStatus(qa, 'retained-run', 'RETAIN', EPOCH);
85
+ writeFile(path.join(retained, 'evidence.json'), '{"retained":true}');
86
+
87
+ // A PASSED run without a usable finishedAt has no proven expiry.
88
+ const brokenFinished = ownedRunWithStatus(qa, 'broken-finished-run', 'PASSED', 'not-a-date');
89
+ writeFile(path.join(brokenFinished, 'temp.txt'), 'broken finished payload');
90
+
91
+ // Runs this controller does not own: no marker, a foreign id, a foreign root.
92
+ const unowned = path.join(runsRoot, 'unowned-run');
93
+ writeFile(path.join(unowned, 'data.txt'), 'unowned payload');
94
+
95
+ const foreignId = path.join(runsRoot, 'foreign-id-run');
96
+ writeFile(path.join(foreignId, 'data.txt'), 'foreign id payload');
97
+ atomicJSON(path.join(foreignId, '.qa-owner.json'), {
98
+ schema: 1, id: 'another-id', root: fs.realpathSync(runsRoot), createdAt: EPOCH, status: 'PASSED', finishedAt: EPOCH,
99
+ });
100
+
101
+ const foreignRoot = path.join(runsRoot, 'foreign-root-run');
102
+ writeFile(path.join(foreignRoot, 'data.txt'), 'foreign root payload');
103
+ atomicJSON(path.join(foreignRoot, '.qa-owner.json'), {
104
+ schema: 1, id: 'foreign-root-run', root: path.join(qa, 'elsewhere'), createdAt: EPOCH, status: 'PASSED', finishedAt: EPOCH,
105
+ });
106
+
107
+ // --- checkpoint, baseline and work clone live outside the run area ---
108
+ const store = new Store(path.join(qa, 'state'));
109
+ const checkpoint = store.transition('BASELINE_VERIFYING');
110
+ const checkpointFile = path.join(qa, 'state', 'checkpoint.json');
111
+ const journalFile = path.join(qa, 'state', 'journal', '00000001.json');
112
+
113
+ const baselineRecord = {
114
+ baseSha: 'b'.repeat(40), tag: 'qa-baseline-20261020', branch: 'qa/test-20261020', status: 'REMOTE_BASELINE_CONFIRMED',
115
+ };
116
+ const baselineFile = path.join(qa, 'state', 'baseline.json');
117
+ atomicJSON(baselineFile, baselineRecord);
118
+
119
+ const workspaceFile = path.join(qa, '.runtime', 'workspaces', 'repair', 'src', 'app.js');
120
+ writeFile(workspaceFile, 'console.log("work clone");\n');
121
+
122
+ // --- dry run ---
123
+ const plan = cleanupPlan(qa, RETENTION_HOURS);
124
+ const planFile = path.join(qa, 'state', 'cleanup-plan.json');
125
+ atomicJSON(planFile, { olderThanHours: RETENTION_HOURS, plan, planHash: hash(JSON.stringify(plan)) });
126
+
127
+ // Only the expired, owned, PASSED run may enter the list.
128
+ assert.deepEqual(
129
+ plan.map(item => item.id),
130
+ ['expired-passed'],
131
+ 'QA-SPEC-CLN-005 仅PASSED且到期进入清单:混合目录中只有已到期的自有PASSED运行进入清单',
132
+ );
133
+ assert.equal(plan[0].id, 'expired-passed', 'QA-SPEC-CLN-005 仅PASSED且到期进入清单:进入清单的运行必须是已到期的PASSED运行');
134
+
135
+ const plannedFiles = plan.flatMap(item => item.entries.map(entry => entry.relative));
136
+ assert.ok(
137
+ plannedFiles.includes(path.join('expired-passed', 'temp.txt')),
138
+ 'QA-SPEC-CLN-005 仅PASSED且到期进入清单:清单逐文件列出到期运行的内容',
139
+ );
140
+ assert.ok(
141
+ plannedFiles.includes(path.join('expired-passed', 'logs', 'stdout.log')),
142
+ 'QA-SPEC-CLN-005 仅PASSED且到期进入清单:清单逐文件列出到期运行的子目录内容',
143
+ );
144
+ assert.ok(
145
+ plan[0].entries.every(entry => /^[0-9a-f]{64}$/.test(entry.sha256)),
146
+ 'QA-SPEC-CLN-005 仅PASSED且到期进入清单:每个被列入的文件都带可核对的哈希',
147
+ );
148
+
149
+ // Every other run status and every foreign directory stays out of the list.
150
+ for (const id of ['fresh-passed', 'active-run', 'failed-run', 'retained-run', 'broken-finished-run', 'unowned-run', 'foreign-id-run', 'foreign-root-run']) {
151
+ assert.ok(
152
+ !plannedFiles.some(relative => relative.startsWith(id + path.sep)),
153
+ 'QA-SPEC-CLN-005 仅PASSED且到期进入清单:' + id + ' 不得进入清理清单',
154
+ );
155
+ }
156
+
157
+ // The retention floor keeps a just finished run out of reach.
158
+ assert.throws(
159
+ () => cleanupPlan(qa, 0),
160
+ { code: 'RETENTION' },
161
+ 'QA-SPEC-CLN-005 仅PASSED且到期进入清单:保留期低于一小时时拒绝出清单',
162
+ );
163
+
164
+ // --- apply the reviewed plan ---
165
+ const deleted = applyCleanup(qa, { olderThanHours: RETENTION_HOURS, planHash: hash(JSON.stringify(plan)) });
166
+ assert.deepEqual(
167
+ deleted,
168
+ ['expired-passed'],
169
+ 'QA-SPEC-CLN-005 仅PASSED且到期进入清单:执行时只删除清单里的到期PASSED运行',
170
+ );
171
+ assert.equal(fs.existsSync(expired), false, 'QA-SPEC-CLN-005 仅PASSED且到期进入清单:到期PASSED运行被真正删除');
172
+ assert.equal(fs.existsSync(path.join(expired, 'temp.txt')), false, 'QA-SPEC-CLN-005 仅PASSED且到期进入清单:到期运行的文件被逐个删除');
173
+
174
+ // Active / failed / retained / fresh runs and their payloads stay untouched.
175
+ assert.equal(fs.existsSync(active), true, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:ACTIVE运行目录被保留');
176
+ assert.equal(fs.readFileSync(path.join(active, 'temp.txt'), 'utf8'), 'active run payload', 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:ACTIVE运行内容被保留');
177
+
178
+ assert.equal(fs.existsSync(failed), true, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:FAILED运行目录被保留');
179
+ assert.equal(fs.readFileSync(path.join(failed, 'first-failure', 'stdout.log'), 'utf8'), FIRST_FAILURE_LOG, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:首失败日志被保留');
180
+ assert.ok(readBytes(path.join(failed, 'first-failure', 'screenshot.png')).equals(FIRST_FAILURE_SHOT), 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:首失败截图被保留');
181
+
182
+ assert.equal(fs.existsSync(retained), true, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:RETAIN运行目录被保留');
183
+ assert.equal(fs.readFileSync(path.join(retained, 'evidence.json'), 'utf8'), '{"retained":true}', 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:RETAIN运行证据被保留');
184
+
185
+ assert.equal(fs.existsSync(fresh), true, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:未到期的PASSED运行被保留');
186
+ assert.equal(fs.readFileSync(path.join(fresh, 'temp.txt'), 'utf8'), 'fresh run payload', 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:未到期运行内容被保留');
187
+
188
+ for (const id of ['unowned-run', 'foreign-id-run', 'foreign-root-run', 'broken-finished-run']) {
189
+ assert.equal(fs.existsSync(path.join(runsRoot, id)), true, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:非自有运行目录 ' + id + ' 被保留');
190
+ }
191
+ assert.equal(fs.readFileSync(path.join(unowned, 'data.txt'), 'utf8'), 'unowned payload', 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:无归属标记的目录内容被保留');
192
+
193
+ // Checkpoint, baseline and the work clone are outside the cleanup scope.
194
+ assert.equal(fs.existsSync(checkpointFile), true, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:检查点文件被保留');
195
+ assert.deepEqual(readJSON(checkpointFile), checkpoint, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:检查点内容未被改动');
196
+ assert.equal(fs.existsSync(journalFile), true, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:检查点日志被保留');
197
+ assert.equal(fs.existsSync(baselineFile), true, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:基线记录被保留');
198
+ assert.deepEqual(readJSON(baselineFile), baselineRecord, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:基线记录内容未被改动');
199
+ assert.equal(fs.existsSync(workspaceFile), true, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:工作clone不在清理范围');
200
+ assert.equal(fs.existsSync(planFile), true, 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:已审计的清理计划记录被保留');
201
+
202
+ // A survivor never silently turns into a deletion candidate.
203
+ assert.deepEqual(
204
+ cleanupPlan(qa, RETENTION_HOURS),
205
+ [],
206
+ 'QA-SPEC-CLN-005 首失败/检查点/基线永不自动删:清理后重新出清单仍为空,保留数据不会自动变成可删数据',
207
+ );
208
+
209
+ console.log('t07b-cln-005-coverage-test PASS (QA-SPEC-CLN-005: only expired owned PASSED runs are listed and deleted; first failure, checkpoint and baseline are never auto-deleted)');
210
+ } finally {
211
+ fs.rmSync(qa, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
212
+ }