@sanqianx/project-knowledge 5.0.24 → 5.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (401) hide show
  1. package/.agents/plugins/marketplace.json +20 -20
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/CHANGELOG.md +1361 -1353
  4. package/LICENSE +201 -201
  5. package/NOTICE +5 -5
  6. package/README.md +349 -349
  7. package/_modules/knowledge-engine/package.json +1 -1
  8. package/_modules/knowledge-engine/src/coordinator.js +48 -3
  9. package/_modules/knowledge-engine/src/runtime/automation-config.js +140 -140
  10. package/_modules/knowledge-engine/src/runtime/commit-conversation-binder.js +238 -238
  11. package/_modules/knowledge-engine/src/runtime/commit-processing-ledger.js +26 -26
  12. package/_modules/knowledge-engine/src/runtime/commit-prompt.js +193 -193
  13. package/_modules/knowledge-engine/src/runtime/commit-reconciler.js +394 -394
  14. package/_modules/knowledge-engine/src/runtime/contracts.js +282 -282
  15. package/_modules/knowledge-engine/src/runtime/conversation-store.js +389 -389
  16. package/_modules/knowledge-engine/src/runtime/evidence-bundle.js +228 -228
  17. package/_modules/knowledge-engine/src/runtime/git-runner.js +62 -62
  18. package/_modules/knowledge-engine/src/runtime/knowledge-promotion.js +505 -505
  19. package/_modules/knowledge-engine/src/runtime/knowledge-retrieval-service.js +400 -400
  20. package/_modules/knowledge-engine/src/runtime/markdown-knowledge-indexer.js +171 -171
  21. package/_modules/knowledge-engine/src/runtime/scanner.js +298 -298
  22. package/_modules/knowledge-engine/ui/app.js +23 -2
  23. package/_site/README.md +30 -30
  24. package/_site/_test/agent-capture-mcp-ui-test.js +68 -68
  25. package/_site/_test/agent-capture-ui-test.js +101 -101
  26. package/_site/_test/ai-profile-resolver-test.js +137 -137
  27. package/_site/_test/ai-profile-test.js +75 -75
  28. package/_site/_test/ai-vendor-presets-test.js +91 -91
  29. package/_site/_test/automatic-context-test.js +70 -70
  30. package/_site/_test/automation-queue-test.js +14 -14
  31. package/_site/_test/automation-ui-test.js +40 -40
  32. package/_site/_test/background-task-registry-test.js +43 -43
  33. package/_site/_test/baseline-schema-test.js +91 -91
  34. package/_site/_test/bin-cli-test.js +230 -230
  35. package/_site/_test/bridge-adapter-test.js +95 -95
  36. package/_site/_test/bridge-consumer-service-test.js +310 -310
  37. package/_site/_test/candidate-bin-content-test.js +35 -35
  38. package/_site/_test/candidate-product-assets-test.js +13 -13
  39. package/_site/_test/candidate-release-contract-test.js +14 -14
  40. package/_site/_test/capture-hook-dedup-test.js +158 -158
  41. package/_site/_test/cdp-browser-failure-test.js +103 -103
  42. package/_site/_test/chat-claudecodeui-match-test.js +92 -92
  43. package/_site/_test/claude-executable-discovery-test.js +90 -90
  44. package/_site/_test/claude-session-lifecycle-sweep-test.js +252 -252
  45. package/_site/_test/claude-workbench-test.js +174 -174
  46. package/_site/_test/cli-instance-management-test.js +62 -62
  47. package/_site/_test/client-capture-restart-e2e-test.js +189 -189
  48. package/_site/_test/codex-conversation-projection-test.js +60 -60
  49. package/_site/_test/codex-marketplace-scoped-path-test.js +186 -186
  50. package/_site/_test/codex-notify-capture-e2e-test.js +101 -101
  51. package/_site/_test/codex-notify-fanout-test.js +141 -134
  52. package/_site/_test/codex-notify-upgrade-test.js +253 -253
  53. package/_site/_test/commit-boundary-freeze-test.js +147 -147
  54. package/_site/_test/commit-conversation-binding-test.js +99 -99
  55. package/_site/_test/commit-evidence-test.js +110 -110
  56. package/_site/_test/configuration-generation-test.js +22 -22
  57. package/_site/_test/context-pack-test.js +200 -200
  58. package/_site/_test/conversation-api-test.js +119 -119
  59. package/_site/_test/conversation-origin-test.js +15 -15
  60. package/_site/_test/conversation-store-test.js +138 -138
  61. package/_site/_test/cross-repo-isolation-e2e-test.js +187 -187
  62. package/_site/_test/desktop-browser-compat-test.js +28 -28
  63. package/_site/_test/desktop-hook-runtime-regression-test.js +204 -204
  64. package/_site/_test/embedding-config-test.js +32 -32
  65. package/_site/_test/explicit-commit-processor-test.js +37 -37
  66. package/_site/_test/fixtures/fake-browser-exit.js +10 -10
  67. package/_site/_test/fixtures/fake-browser-hang.js +10 -10
  68. package/_site/_test/fixtures/integration-busy-worker.cjs +6 -6
  69. package/_site/_test/fixtures/make-git-repos.js +92 -92
  70. package/_site/_test/fixtures/retrieval-gold-queries.json +32 -32
  71. package/_site/_test/folder-picker-output-test.js +19 -19
  72. package/_site/_test/fresh-hook-reimport-test.js +53 -53
  73. package/_site/_test/fresh-product-data-test.js +56 -56
  74. package/_site/_test/full-integration-e2e-test.js +167 -167
  75. package/_site/_test/git-path-compatibility-test.js +80 -80
  76. package/_site/_test/git-validation-test.js +81 -81
  77. package/_site/_test/glm-ui-refresh-review-test.js +313 -404
  78. package/_site/_test/harness-isolation-test.js +138 -0
  79. package/_site/_test/helpers/cdp-browser.js +383 -0
  80. package/_site/_test/helpers/cdp-network-capture.js +66 -0
  81. package/_site/_test/helpers/find-chrome.js +34 -0
  82. package/_site/_test/helpers/free-port.js +8 -0
  83. package/_site/_test/helpers/logging-ui-fixture.js +131 -0
  84. package/_site/_test/helpers/module-fixture.js +282 -0
  85. package/_site/_test/helpers/parallel-engine-advanced-engine-child.js +45 -0
  86. package/_site/_test/helpers/parallel-engine-advanced-fault-writer.js +171 -0
  87. package/_site/_test/helpers/parallel-engine-advanced-harness.js +245 -0
  88. package/_site/_test/helpers/parallel-engine-advanced-standin-analyzer.js +80 -0
  89. package/_site/_test/helpers/parallel-engine-advanced-ui-host.js +177 -0
  90. package/_site/_test/helpers/parallel-engine-final-harness.js +314 -0
  91. package/_site/_test/helpers/parallel-engine-final-standin-analyzer.js +159 -0
  92. package/_site/_test/helpers/parallel-knowledge-fixture.js +255 -0
  93. package/_site/_test/helpers/parallel-logging-acceptance-fixture.js +111 -0
  94. package/_site/_test/helpers/parallel-logging-acceptance-proxy.js +106 -0
  95. package/_site/_test/helpers/parallel-logging-fix-r2-proxy.js +205 -0
  96. package/_site/_test/helpers/parallel-logging-integration-5025-env.js +432 -0
  97. package/_site/_test/helpers/parallel-memory-analyzer.js +81 -0
  98. package/_site/_test/helpers/parallel-memory-event-bridge.js +128 -0
  99. package/_site/_test/helpers/parallel-memory-shell.js +470 -0
  100. package/_site/_test/helpers/parallel-nav-isolation-env.js +389 -0
  101. package/_site/_test/helpers/parallel-nav-module-ui.js +186 -0
  102. package/_site/_test/helpers/parallel-nav-proxy.js +148 -0
  103. package/_site/_test/helpers/parallel-nav-shell.js +361 -0
  104. package/_site/_test/helpers/parallel-qa-engine-endpoint-guard.js +206 -0
  105. package/_site/_test/helpers/parallel-qa-engine-endpoint-isolate.js +257 -0
  106. package/_site/_test/helpers/parallel-retrieval-followup-corpus.js +293 -0
  107. package/_site/_test/helpers/parallel-retrieval-followup-next-session.js +70 -0
  108. package/_site/_test/helpers/parallel-retrieval-followup-r2-shell.js +737 -0
  109. package/_site/_test/helpers/parallel-retrieval-followup-r2-wb-host.js +82 -0
  110. package/_site/_test/helpers/parallel-retrieval-followup-shell.js +279 -0
  111. package/_site/_test/helpers/parallel-workbench-fixture.js +371 -0
  112. package/_site/_test/helpers/parallel-workbench-host.js +80 -0
  113. package/_site/_test/helpers/parallel-workbench-integration-5025-fixture.js +408 -0
  114. package/_site/_test/helpers/parallel-workbench-integration-5025-harness.js +593 -0
  115. package/_site/_test/helpers/parallel-workbench-integration-5025-host.js +70 -0
  116. package/_site/_test/helpers/parallel-workbench-integration-5025-launcher.js +240 -0
  117. package/_site/_test/helpers/parallel-workbench-integration-5025-runtime-harness.js +630 -0
  118. package/_site/_test/helpers/parallel-workbench-source-map.js +196 -0
  119. package/_site/_test/helpers/spawn-server.js +106 -0
  120. package/_site/_test/helpers/version-visibility-fixture.js +251 -0
  121. package/_site/_test/hook-runtime-endpoint-test.js +88 -88
  122. package/_site/_test/hook-status-repair-api-test.js +152 -152
  123. package/_site/_test/hook-trigger-test.js +85 -85
  124. package/_site/_test/hook-worktree-test.js +42 -42
  125. package/_site/_test/import-preflight-api-test.js +234 -234
  126. package/_site/_test/index-builder-test.js +41 -41
  127. package/_site/_test/index-error-display-contract-test.js +10 -10
  128. package/_site/_test/index-writer-concurrency-test.js +135 -135
  129. package/_site/_test/integration-adapters-test.js +262 -262
  130. package/_site/_test/integration-auto-repair-test.js +113 -113
  131. package/_site/_test/integration-capture-setup-test.js +118 -118
  132. package/_site/_test/integration-intent-test.js +81 -81
  133. package/_site/_test/integration-runtime-binding-a2-test.js +566 -566
  134. package/_site/_test/integration-runtime-binding-a3-test.js +227 -227
  135. package/_site/_test/integration-runtime-binding-test.js +473 -473
  136. package/_site/_test/integration-status-scan-test.js +29 -29
  137. package/_site/_test/integration-surface-coverage-test.js +164 -164
  138. package/_site/_test/kb-framework-test.js +57 -57
  139. package/_site/_test/kbpath-follow-test.js +63 -63
  140. package/_site/_test/knowledge-db-test.js +144 -144
  141. package/_site/_test/knowledge-engine-client-test.js +120 -109
  142. package/_site/_test/knowledge-language-control-test.js +170 -170
  143. package/_site/_test/knowledge-maintenance-test.js +40 -40
  144. package/_site/_test/knowledge-promotion-recovery-test.js +260 -260
  145. package/_site/_test/knowledge-query-test.js +54 -54
  146. package/_site/_test/knowledge-retrieval-service-test.js +77 -77
  147. package/_site/_test/knowledge-scopes-test.js +37 -37
  148. package/_site/_test/knowledge-storage-location-test.js +28 -28
  149. package/_site/_test/knowledge-storage-startup-test.js +52 -52
  150. package/_site/_test/knowledge-store-logs-supervision-test.js +89 -89
  151. package/_site/_test/launcher-readiness-test.js +80 -80
  152. package/_site/_test/legacy-claude-session-alias-test.js +106 -106
  153. package/_site/_test/legacy-routes-removed-test.js +47 -47
  154. package/_site/_test/legacy-workbench-exclusion-test.js +92 -92
  155. package/_site/_test/live-gateway-test.js +48 -48
  156. package/_site/_test/local-marketplace-test.js +16 -16
  157. package/_site/_test/log-redaction-test.js +58 -58
  158. package/_site/_test/logging-api-test.js +89 -89
  159. package/_site/_test/logging-sse-no-gap-test.js +88 -88
  160. package/_site/_test/logging-ui-test.js +107 -107
  161. package/_site/_test/markdown-delta-overlay-test.js +85 -85
  162. package/_site/_test/markdown-maintenance-api-test.js +75 -75
  163. package/_site/_test/markdown-maintenance-test.js +11 -11
  164. package/_site/_test/mcp-server-test.js +149 -149
  165. package/_site/_test/model-context-windows-test.js +89 -89
  166. package/_site/_test/module-agent-start-proxy-test.js +65 -65
  167. package/_site/_test/module-artifact-integrity-test.js +27 -27
  168. package/_site/_test/module-boundary-test.js +30 -30
  169. package/_site/_test/module-bridge-eventbridge-test.js +202 -202
  170. package/_site/_test/module-dynamic-port-test.js +118 -118
  171. package/_site/_test/module-index-proxy-test.js +33 -33
  172. package/_site/_test/module-model-configuration-test.js +44 -44
  173. package/_site/_test/module-process-lifecycle-test.js +35 -35
  174. package/_site/_test/module-stream-proxy-test.js +34 -34
  175. package/_site/_test/module-terminal-restart-test.js +63 -63
  176. package/_site/_test/module-wiring-unbind-race-test.js +59 -59
  177. package/_site/_test/native-context-integrations-test.js +86 -86
  178. package/_site/_test/non-release-ci-test.js +34 -34
  179. package/_site/_test/offline-boundary-isolation-test.js +32 -32
  180. package/_site/_test/orphaned-claim-recovery-test.js +80 -80
  181. package/_site/_test/package-boundary-test.js +43 -43
  182. package/_site/_test/package-startup-test.js +56 -56
  183. package/_site/_test/packaged-ui-smoke-test.js +88 -88
  184. package/_site/_test/parallel-ci-r9-posix-socket-budget-test.js +156 -0
  185. package/_site/_test/parallel-engine-advanced-eng005-test.js +136 -0
  186. package/_site/_test/parallel-engine-advanced-eng006-test.js +171 -0
  187. package/_site/_test/parallel-engine-advanced-eng007-reconcile-test.js +231 -0
  188. package/_site/_test/parallel-engine-advanced-eng009-test.js +208 -0
  189. package/_site/_test/parallel-engine-advanced-eng010-test.js +213 -0
  190. package/_site/_test/parallel-engine-advanced-eng011-ui-probe.js +459 -0
  191. package/_site/_test/parallel-engine-final-eng002-test.js +255 -0
  192. package/_site/_test/parallel-engine-final-eng007-test.js +269 -0
  193. package/_site/_test/parallel-engine-final-eng011-test.js +197 -0
  194. package/_site/_test/parallel-engine-final-eng012-test.js +354 -0
  195. package/_site/_test/parallel-knowledge-client-error-code-test.js +184 -0
  196. package/_site/_test/parallel-knowledge-engine-test.js +353 -0
  197. package/_site/_test/parallel-knowledge-retrieval-test.js +292 -0
  198. package/_site/_test/parallel-knowledge-vector-test.js +168 -0
  199. package/_site/_test/parallel-linux-ci-r7-log007-day-test.js +110 -0
  200. package/_site/_test/parallel-logging-acceptance-log003-test.js +224 -0
  201. package/_site/_test/parallel-logging-acceptance-log004-test.js +231 -0
  202. package/_site/_test/parallel-logging-acceptance-log005-test.js +208 -0
  203. package/_site/_test/parallel-logging-acceptance-log006-test.js +214 -0
  204. package/_site/_test/parallel-logging-acceptance-log007-test.js +223 -0
  205. package/_site/_test/parallel-logging-acceptance-log008-test.js +180 -0
  206. package/_site/_test/parallel-logging-fix-r2-crash-probe.js +271 -0
  207. package/_site/_test/parallel-logging-fix-r2-gap-test.js +294 -0
  208. package/_site/_test/parallel-logging-fix-r2-normalhook-test.js +330 -0
  209. package/_site/_test/parallel-logging-integration-5025-portability-test.js +554 -0
  210. package/_site/_test/parallel-memory-candidate-test.js +301 -0
  211. package/_site/_test/parallel-memory-manual-test.js +197 -0
  212. package/_site/_test/parallel-memory-scope-test.js +228 -0
  213. package/_site/_test/parallel-memory-source-test.js +227 -0
  214. package/_site/_test/parallel-memory-sync-test.js +238 -0
  215. package/_site/_test/parallel-memory-view-r8-reload-gate-test.js +123 -0
  216. package/_site/_test/parallel-nav-failure-test.js +119 -0
  217. package/_site/_test/parallel-nav-isolation-test.js +308 -0
  218. package/_site/_test/parallel-nav-isolation-vector-path-test.js +90 -0
  219. package/_site/_test/parallel-nav-offline-test.js +272 -0
  220. package/_site/_test/parallel-nav-operability-test.js +257 -0
  221. package/_site/_test/parallel-nav-switch-test.js +247 -0
  222. package/_site/_test/parallel-nav-theme-test.js +130 -0
  223. package/_site/_test/parallel-nav-viewport-test.js +310 -0
  224. package/_site/_test/parallel-qa-engine-endpoint-guard-test.js +273 -0
  225. package/_site/_test/parallel-retrieval-followup-citation-test.js +219 -0
  226. package/_site/_test/parallel-retrieval-followup-corpus-test.js +287 -0
  227. package/_site/_test/parallel-workbench-independent-host.js +262 -0
  228. package/_site/_test/parallel-workbench-integration-5025-abort-probe.js +340 -0
  229. package/_site/_test/parallel-workbench-integration-5025-drafts-probe.js +588 -0
  230. package/_site/_test/parallel-workbench-integration-5025-env-check.js +317 -0
  231. package/_site/_test/parallel-workbench-integration-5025-model-probe.js +342 -0
  232. package/_site/_test/parallel-workbench-integration-5025-ordering-probe.js +326 -0
  233. package/_site/_test/parallel-workbench-model-probe.js +336 -0
  234. package/_site/_test/parallel-workbench-offline-test.js +169 -0
  235. package/_site/_test/parallel-workbench-provenance-trace.js +134 -0
  236. package/_site/_test/parallel-workbench-source-match.js +206 -0
  237. package/_site/_test/parallel-workbench-standalone-turn.js +349 -0
  238. package/_site/_test/path-consistency-test.js +151 -151
  239. package/_site/_test/pending-sweep-test.js +9 -9
  240. package/_site/_test/post-commit-automation-test.js +87 -87
  241. package/_site/_test/pr-consumer-contract-test.js +55 -55
  242. package/_site/_test/product-brand-contract-test.js +25 -25
  243. package/_site/_test/product-diagnostics-ui-test.js +93 -93
  244. package/_site/_test/product-empty-state-test.js +148 -0
  245. package/_site/_test/product-import-ui-test.js +219 -104
  246. package/_site/_test/product-navigation-test.js +152 -0
  247. package/_site/_test/product-progress-status-test.js +84 -84
  248. package/_site/_test/project-delete-recovery-test.js +64 -64
  249. package/_site/_test/project-domain-create-test.js +91 -0
  250. package/_site/_test/project-domain-scope-retrieval-test.js +214 -0
  251. package/_site/_test/project-git-init-confirm-test.js +115 -0
  252. package/_site/_test/project-goal-editor-test.js +144 -144
  253. package/_site/_test/project-import-duplicate-alias-test.js +134 -0
  254. package/_site/_test/project-import-unicode-restart-test.js +140 -0
  255. package/_site/_test/project-lifecycle-transaction-test.js +106 -106
  256. package/_site/_test/project-module-partial-recovery-test.js +222 -0
  257. package/_site/_test/project-remove-running-guard-test.js +79 -79
  258. package/_site/_test/project-store-test.js +90 -90
  259. package/_site/_test/project-unbind-late-read-ui-test.js +250 -0
  260. package/_site/_test/project-unbind-writer-guard-test.js +231 -0
  261. package/_site/_test/prompt-settings-test.js +115 -115
  262. package/_site/_test/protected-architecture-gate-test.js +122 -122
  263. package/_site/_test/refactor-characterization-test.js +36 -36
  264. package/_site/_test/registry-events-test.js +38 -38
  265. package/_site/_test/release-version-sync-test.js +115 -115
  266. package/_site/_test/requirement-binding-test.js +113 -113
  267. package/_site/_test/requirement-recorder-test.js +173 -173
  268. package/_site/_test/run-all-tests.js +173 -161
  269. package/_site/_test/runtime-endpoint-test.js +64 -64
  270. package/_site/_test/scanner-test.js +83 -83
  271. package/_site/_test/server-security-test.js +96 -96
  272. package/_site/_test/sessions-stream-test.js +93 -93
  273. package/_site/_test/shared-contracts-test.js +58 -58
  274. package/_site/_test/shared-scope-root-binding-test.js +74 -67
  275. package/_site/_test/simple-import-test.js +98 -98
  276. package/_site/_test/startup-analysis-disabled-test.js +16 -16
  277. package/_site/_test/storage-foundation-test.js +78 -78
  278. package/_site/_test/structured-logger-test.js +101 -101
  279. package/_site/_test/t07b-cln-005-coverage-test.js +212 -0
  280. package/_site/_test/team-knowledge-store-sparse-checkout-test.js +196 -196
  281. package/_site/_test/team-knowledge-store-test.js +132 -132
  282. package/_site/_test/test-server-cleanup-test.js +35 -35
  283. package/_site/_test/test-server-module-isolation-test.js +37 -37
  284. package/_site/_test/tracking-start-test.js +144 -144
  285. package/_site/_test/vector-storage-root-test.js +75 -75
  286. package/_site/_test/version-visibility-browser-probe.js +249 -0
  287. package/_site/_test/version-visibility-test.js +92 -0
  288. package/_site/_test/workbench-context-receipts-test.js +22 -22
  289. package/_site/_test/workbench-permission-test.js +117 -117
  290. package/_site/_test/zcode-capture-integration-test.js +112 -112
  291. package/_site/lib/ai-profile-resolver.js +78 -78
  292. package/_site/lib/ai-vendor-presets.js +83 -83
  293. package/_site/lib/ai-workspace.js +104 -104
  294. package/_site/lib/atomic-file.js +204 -204
  295. package/_site/lib/automation-config.js +140 -140
  296. package/_site/lib/bridge-adapter.js +260 -260
  297. package/_site/lib/bridge-consumer-service.js +402 -402
  298. package/_site/lib/capture-hook-config.js +108 -108
  299. package/_site/lib/claude-cli-runner.js +1599 -1599
  300. package/_site/lib/cli-instances.js +43 -43
  301. package/_site/lib/codex-context-status.js +17 -17
  302. package/_site/lib/codex-notify-config.js +193 -193
  303. package/_site/lib/commit-conversation-binder.js +247 -247
  304. package/_site/lib/commit-processing-ledger.js +27 -27
  305. package/_site/lib/commit-prompt.js +202 -202
  306. package/_site/lib/commit-reconciler.js +444 -444
  307. package/_site/lib/context-pack-builder.js +299 -299
  308. package/_site/lib/contracts.js +291 -291
  309. package/_site/lib/conversation-exclusions.js +204 -204
  310. package/_site/lib/conversation-query-service.js +161 -161
  311. package/_site/lib/conversation-store.js +387 -387
  312. package/_site/lib/data-dir.js +13 -13
  313. package/_site/lib/embedding-service.js +85 -85
  314. package/_site/lib/engine-connection.js +93 -93
  315. package/_site/lib/engine-knowledge-client.js +76 -72
  316. package/_site/lib/evidence-bundle.js +228 -228
  317. package/_site/lib/folder-picker-output.js +24 -24
  318. package/_site/lib/git-path.js +14 -14
  319. package/_site/lib/git-runner.js +62 -62
  320. package/_site/lib/github-team-store.js +1175 -1175
  321. package/_site/lib/hook-manager.js +203 -203
  322. package/_site/lib/index-builder.js +157 -157
  323. package/_site/lib/index-service.js +173 -173
  324. package/_site/lib/integration-auto-repair.js +77 -77
  325. package/_site/lib/integration-installer.js +1240 -1240
  326. package/_site/lib/integration-intent.js +88 -88
  327. package/_site/lib/integration-status-scan.js +99 -99
  328. package/_site/lib/integration-status-worker.js +14 -14
  329. package/_site/lib/kb-framework.js +191 -191
  330. package/_site/lib/kb-validator.js +124 -124
  331. package/_site/lib/knowledge-db.js +363 -363
  332. package/_site/lib/knowledge-promotion.js +435 -435
  333. package/_site/lib/knowledge-retrieval-service.js +401 -401
  334. package/_site/lib/knowledge-schema.js +121 -121
  335. package/_site/lib/knowledge-tool-runtime.js +366 -366
  336. package/_site/lib/live-gateway.js +78 -78
  337. package/_site/lib/llm-client.js +173 -173
  338. package/_site/lib/markdown-knowledge-indexer.js +230 -230
  339. package/_site/lib/model-context-windows.js +82 -82
  340. package/_site/lib/module-bridge.js +874 -874
  341. package/_site/lib/module-port-resolver.js +57 -57
  342. package/_site/lib/post-commit-automation.js +141 -141
  343. package/_site/lib/product-data.js +35 -35
  344. package/_site/lib/project-lifecycle-service.js +554 -554
  345. package/_site/lib/project-registry-store.js +129 -129
  346. package/_site/lib/project-store.js +268 -268
  347. package/_site/lib/prompt-registry.js +148 -148
  348. package/_site/lib/public-version-info.js +37 -0
  349. package/_site/lib/registry-events.js +16 -16
  350. package/_site/lib/requirement-adapters.js +10 -10
  351. package/_site/lib/requirement-binder.js +112 -112
  352. package/_site/lib/requirement-recorder.js +278 -278
  353. package/_site/lib/runtime-control.js +89 -89
  354. package/_site/lib/runtime-endpoint.js +160 -160
  355. package/_site/lib/scanner.js +298 -298
  356. package/_site/lib/server-app.js +1672 -1664
  357. package/_site/lib/settings-store.js +153 -153
  358. package/_site/lib/storage-layout.js +166 -166
  359. package/_site/lib/structured-logger.js +574 -574
  360. package/_site/lib/zcode-context-integration.js +60 -60
  361. package/_site/scripts/codex-notify-fanout.cjs +95 -95
  362. package/_site/scripts/folder-picker.ps1 +156 -156
  363. package/_site/scripts/hook-trigger.js +158 -158
  364. package/_site/scripts/install-module-candidates.js +69 -69
  365. package/_site/scripts/pack-module-candidates.js +89 -89
  366. package/_site/scripts/sync-product-content.js +28 -28
  367. package/_site/scripts/sync-release-version.js +164 -164
  368. package/_site/scripts/vendor-modules.js +49 -49
  369. package/_site/scripts/verify-module-runtime.js +50 -50
  370. package/_site/scripts/verify-product-runtime.js +36 -36
  371. package/_site/scripts/verify-retrieval-gold.js +83 -83
  372. package/_site/server.js +15 -15
  373. package/_site/start.bat +26 -26
  374. package/_site/stop.bat +11 -11
  375. package/bin/project-knowledge-integrations.js +254 -254
  376. package/bin/project-knowledge-kb.js +67 -67
  377. package/bin/project-knowledge-mcp.js +201 -201
  378. package/bin/project-knowledge.js +269 -170
  379. package/claude-prompts.json +21 -21
  380. package/docs/README.zh-CN.md +207 -205
  381. package/docs/assets/architecture.svg +181 -181
  382. package/docs/assets/logo.svg +49 -49
  383. package/docs/fresh-v5-start.md +44 -44
  384. package/docs/leader-glm-workbench-playbook.md +122 -122
  385. package/docs/project-registry-schema.md +33 -33
  386. package/docs/release-5.0.16-acceptance.md +176 -176
  387. package/docs/release-5.0.17-acceptance.md +117 -117
  388. package/docs/release-5.0.19-acceptance.md +39 -39
  389. package/docs/team-knowledge-mode-a-plan.md +73 -73
  390. package/docs/testing-strategy.md +33 -33
  391. package/module-runtime-manifest.json +66 -63
  392. package/package.json +113 -110
  393. package/plugins/project-knowledge/.claude-plugin/plugin.json +1 -1
  394. package/plugins/project-knowledge/.codex-plugin/plugin.json +1 -1
  395. package/plugins/project-knowledge/.mcp.json +1 -1
  396. package/templates/change.md +30 -30
  397. package/templates/project-readme.md +52 -52
  398. package/ui/index.html +3 -2
  399. package/ui/version-info.css +44 -0
  400. package/ui/version-info.js +24 -0
  401. package/vendor-manifest.json +55 -55
@@ -0,0 +1,245 @@
1
+ 'use strict';
2
+
3
+ // P-ENG-ADVANCED lane-exclusive harness (parallel-20261023 batch).
4
+ //
5
+ // Drives the VENDORED knowledge-engine (_modules/knowledge-engine, byte-identical
6
+ // to source e5573bb at batch time) inside real child processes with full
7
+ // isolation: ephemeral loopback ports, lane-owned data dirs under
8
+ // PK_TEST_TEMP_ROOT (or the OS temp dir), isolated HOME/TEMP, and a
9
+ // scrubbed child environment (no KB_*/KNOWLEDGE_*/ANTHROPIC_*/CLAUDE* leakage,
10
+ // no env -u dependency). The analyzer is a DECLARATIVE STAND-IN: it writes real
11
+ // staged Markdown + manifest bytes through the engine's real promotion path but
12
+ // does NOT cover real model output. The vector endpoint is a loopback HTTP
13
+ // double: engine-side index behavior is real, vector-hub itself is not covered.
14
+
15
+ const { spawn, execFileSync } = require('node:child_process');
16
+ const fs = require('node:fs');
17
+ const http = require('node:http');
18
+ const os = require('node:os');
19
+ const path = require('node:path');
20
+
21
+ const REPO_ROOT = path.resolve(__dirname, '..', '..', '..');
22
+ const VENDORED_ENGINE_SERVER = path.join(REPO_ROOT, '_modules', 'knowledge-engine', 'src', 'server.js');
23
+ const ENGINE_CHILD = path.join(__dirname, 'parallel-engine-advanced-engine-child.js');
24
+
25
+ // Temp root: PK_TEST_TEMP_ROOT or the OS temp dir; never inside the repository.
26
+ const TEMP_ROOT = (() => {
27
+ const base = path.resolve(process.env.PK_TEST_TEMP_ROOT || path.join(os.tmpdir(), 'project-knowledge-engine-test', 'parallel-engine-advanced'));
28
+ if (base === REPO_ROOT || base.startsWith(REPO_ROOT + path.sep)) {
29
+ throw new Error(`temp root must live outside the repository (got ${base})`);
30
+ }
31
+ return base;
32
+ })();
33
+
34
+ function ensureTempRoot() {
35
+ fs.mkdirSync(TEMP_ROOT, { recursive: true });
36
+ return TEMP_ROOT;
37
+ }
38
+
39
+ function makeLaneDir(label) {
40
+ ensureTempRoot();
41
+ const dir = fs.mkdtempSync(path.join(TEMP_ROOT, `${label}-`));
42
+ return dir;
43
+ }
44
+
45
+ function isolatedEnv(extra = {}) {
46
+ const home = extra.ISOLATED_HOME || path.join(ensureTempRoot(), 'isolated-home');
47
+ fs.mkdirSync(home, { recursive: true });
48
+ const env = { ...process.env };
49
+ for (const name of Object.keys(env)) {
50
+ if (/^(KB_|KNOWLEDGE_|ANTHROPIC_|CLAUDE|OPENAI_|CODEX|MINIMAX|GLM|PK_TEST_)/i.test(name)) delete env[name];
51
+ }
52
+ const tmp = path.join(ensureTempRoot(), 'tmp');
53
+ fs.mkdirSync(tmp, { recursive: true });
54
+ env.HOME = home;
55
+ env.USERPROFILE = home;
56
+ env.APPDATA = path.join(home, 'AppData', 'Roaming');
57
+ env.LOCALAPPDATA = path.join(home, 'AppData', 'Local');
58
+ env.TEMP = tmp;
59
+ env.TMP = tmp;
60
+ env.TMPDIR = tmp;
61
+ env.GIT_CONFIG_NOSYSTEM = '1';
62
+ env.GIT_CONFIG_GLOBAL = path.join(home, 'does-not-exist.gitconfig');
63
+ return { ...env, ...Object.fromEntries(Object.entries(extra).filter(([k]) => k !== 'ISOLATED_HOME')) };
64
+ }
65
+
66
+ function git(repoPath, args, env) {
67
+ return execFileSync('git', args, { cwd: repoPath, windowsHide: true, encoding: 'utf8', env }).trim();
68
+ }
69
+
70
+ // Real fixture git repository with a baseline plus one labeled commit per entry.
71
+ // Mirrors the canonical fixture shape from the engine suite (test/engine.test.js
72
+ // project()) so scanner.collectEvidence sees the same repo shape it supports.
73
+ function buildFixtureRepo(root, name, commits) {
74
+ const env = isolatedEnv();
75
+ const repoPath = path.join(root, `repo-${name}`);
76
+ fs.mkdirSync(repoPath, { recursive: true });
77
+ git(repoPath, ['init', '-q'], env);
78
+ git(repoPath, ['config', 'user.email', 'eng-advanced@test.invalid'], env);
79
+ git(repoPath, ['config', 'user.name', 'P-ENG-ADVANCED'], env);
80
+ fs.writeFileSync(path.join(repoPath, 'README.md'), `# ${name}\n\nInitial fixture repository.\n`);
81
+ git(repoPath, ['add', '.'], env);
82
+ git(repoPath, ['commit', '-qm', 'baseline'], env);
83
+ const baseline = git(repoPath, ['rev-parse', 'HEAD'], env);
84
+ const shas = {};
85
+ for (const label of commits) {
86
+ fs.writeFileSync(path.join(repoPath, `${label}.txt`), `change ${name} ${label}\n` + 'x'.repeat(64) + '\n');
87
+ git(repoPath, ['add', '.'], env);
88
+ git(repoPath, ['commit', '-qm', `feature ${label}`], env);
89
+ shas[label] = git(repoPath, ['rev-parse', 'HEAD'], env);
90
+ }
91
+ return { repoPath, baseline, shas };
92
+ }
93
+
94
+ async function waitUntil(fn, timeoutMs, describe) {
95
+ const started = Date.now();
96
+ for (;;) {
97
+ const value = await fn();
98
+ if (value) return value;
99
+ if (Date.now() - started > timeoutMs) throw new Error(`waitUntil timed out after ${timeoutMs}ms: ${describe}`);
100
+ await new Promise(resolve => setTimeout(resolve, 25));
101
+ }
102
+ }
103
+
104
+ async function callJson(base, route, body, init = {}) {
105
+ const response = await fetch(`${base}${route}`, {
106
+ ...init,
107
+ method: body === undefined && !init.method ? 'GET' : init.method || 'POST',
108
+ headers: { 'Content-Type': 'application/json', ...(init.headers || {}) },
109
+ body: body === undefined && (!init.method || init.method === 'GET') ? undefined : JSON.stringify(body),
110
+ });
111
+ let payload = null;
112
+ try { payload = await response.json(); } catch { payload = null; }
113
+ return { status: response.status, body: payload };
114
+ }
115
+
116
+ // Loopback vector-service double. Engine-side requestIndex behavior is fully
117
+ // real; this double only stands in for vector-hub's HTTP contract.
118
+ async function startVectorDouble() {
119
+ const requests = [];
120
+ let mode = { kind: 'ok' };
121
+ const server = http.createServer((req, res) => {
122
+ let raw = '';
123
+ req.on('data', chunk => { raw += chunk; });
124
+ req.on('end', () => {
125
+ let body = null;
126
+ try { body = raw ? JSON.parse(raw) : null; } catch { body = null; }
127
+ requests.push({ at: new Date().toISOString(), url: req.url, body });
128
+ if (mode.kind === 'ok') {
129
+ res.writeHead(200, { 'Content-Type': 'application/json' });
130
+ res.end(JSON.stringify({ ok: true }));
131
+ } else {
132
+ res.writeHead(mode.httpStatus || 503, { 'Content-Type': 'application/json' });
133
+ res.end(JSON.stringify({ ok: false, error: { code: mode.code || 'EMBEDDING_UNAVAILABLE', message: mode.message || 'vector double scripted failure' } }));
134
+ }
135
+ });
136
+ });
137
+ await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
138
+ return {
139
+ url: `http://127.0.0.1:${server.address().port}`,
140
+ requests,
141
+ setMode(next) { mode = next; },
142
+ async close() { server.closeAllConnections(); await new Promise(resolve => server.close(resolve)); },
143
+ };
144
+ }
145
+
146
+ // Real engine child process running the vendored server module with the
147
+ // declarative stand-in analyzer. Returns { base, proc, dataDir, killHard, stop }.
148
+ async function startEngineChild({ label, dataDir, vectorUrl, planFile, eventsFile, concurrency }) {
149
+ fs.mkdirSync(dataDir, { recursive: true });
150
+ const proc = spawn(process.execPath, [ENGINE_CHILD], {
151
+ windowsHide: true,
152
+ stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
153
+ env: isolatedEnv({
154
+ ENGADV_DATA_DIR: dataDir,
155
+ ENGADV_VECTOR_URL: vectorUrl,
156
+ ENGADV_PLAN_FILE: planFile,
157
+ ENGADV_EVENTS_FILE: eventsFile,
158
+ ...(concurrency !== undefined ? { ENGADV_CONCURRENCY: String(concurrency) } : {}),
159
+ }),
160
+ });
161
+ let stderr = '';
162
+ proc.stderr.on('data', chunk => { stderr += chunk; });
163
+ const base = await new Promise((resolve, reject) => {
164
+ let out = '';
165
+ const timer = setTimeout(() => reject(new Error(`engine child not ready; stderr: ${stderr}`)), 30000);
166
+ proc.stdout.on('data', chunk => {
167
+ out += chunk;
168
+ const match = out.match(/^ENGADV-READY (\{.*\})\n/m);
169
+ if (match) {
170
+ clearTimeout(timer);
171
+ resolve(JSON.parse(match[1]).base);
172
+ }
173
+ });
174
+ proc.on('exit', code => { clearTimeout(timer); reject(new Error(`engine child exited early (${code}); stderr: ${stderr}`)); });
175
+ });
176
+ async function killHard() {
177
+ if (proc.exitCode !== null || proc.signalCode !== null) return proc.exitCode;
178
+ // A HARD crash must not run the engine's graceful shutdown. On POSIX the
179
+ // default signal of kill() is SIGTERM, and the engine child traps SIGTERM
180
+ // to close the server gracefully - which releases the single-writer lock
181
+ // file, so the residual-lock state under test would never exist (root CI
182
+ // 39927630516 failed on Linux with ENOENT on engine-runtime.lock). SIGKILL
183
+ // cannot be trapped, so the process dies with the lock still on disk; on
184
+ // Windows Node maps SIGKILL to TerminateProcess, which is what kill()
185
+ // already did there.
186
+ proc.kill('SIGKILL');
187
+ return await new Promise(resolve => {
188
+ if (proc.exitCode !== null || proc.signalCode !== null) return resolve(proc.exitCode);
189
+ proc.on('exit', code => resolve(code));
190
+ });
191
+ }
192
+ async function stop() {
193
+ if (proc.exitCode !== null) return;
194
+ proc.send({ type: 'kb:shutdown' });
195
+ await new Promise(resolve => {
196
+ const timer = setTimeout(() => { try { proc.kill(); } catch {} resolve(); }, 15000);
197
+ proc.on('exit', () => { clearTimeout(timer); resolve(); });
198
+ });
199
+ }
200
+ return { base, proc, dataDir, killHard, stop, stderr: () => stderr };
201
+ }
202
+
203
+ function readEventsFile(eventsFile) {
204
+ if (!fs.existsSync(eventsFile)) return [];
205
+ return fs.readFileSync(eventsFile, 'utf8').split('\n').filter(Boolean).map(line => JSON.parse(line));
206
+ }
207
+
208
+ function writePlan(planFile, plan) {
209
+ fs.mkdirSync(path.dirname(planFile), { recursive: true });
210
+ fs.writeFileSync(planFile, JSON.stringify(plan, null, 1));
211
+ }
212
+
213
+ function listFilesRecursive(root) {
214
+ const out = [];
215
+ if (!fs.existsSync(root)) return out;
216
+ for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
217
+ const absolute = path.join(root, entry.name);
218
+ if (entry.isDirectory()) out.push(...listFilesRecursive(absolute).map(sub => `${entry.name}/${sub}`));
219
+ else out.push(entry.name);
220
+ }
221
+ return out.sort();
222
+ }
223
+
224
+ function saveEvidence(laneDir, name, value) {
225
+ fs.mkdirSync(laneDir, { recursive: true });
226
+ fs.writeFileSync(path.join(laneDir, name), JSON.stringify(value, null, 2));
227
+ }
228
+
229
+ module.exports = {
230
+ REPO_ROOT,
231
+ VENDORED_ENGINE_SERVER,
232
+ TEMP_ROOT,
233
+ makeLaneDir,
234
+ isolatedEnv,
235
+ git,
236
+ buildFixtureRepo,
237
+ waitUntil,
238
+ callJson,
239
+ startVectorDouble,
240
+ startEngineChild,
241
+ readEventsFile,
242
+ writePlan,
243
+ listFilesRecursive,
244
+ saveEvidence,
245
+ };
@@ -0,0 +1,80 @@
1
+ 'use strict';
2
+
3
+ // P-ENG-ADVANCED declarative stand-in analyzer.
4
+ //
5
+ // HONEST SCOPE LABEL: this analyzer produces real staged Markdown bytes and a
6
+ // valid knowledge-staging-manifest through the engine's REAL promotion path,
7
+ // but it does NOT cover real model output, real prompt adherence, or the
8
+ // headless Claude Agent SDK worker. Every case that relies on it is evidence
9
+ // about engine scheduling/promotion/indexing machinery, never about model
10
+ // quality. The debug simulateFailure flag is handled by the engine itself
11
+ // BEFORE this analyzer runs (DEBUG_SIMULATED_FAILURE).
12
+ //
13
+ // Plan file shape (JSON, read per claim):
14
+ // {
15
+ // "default": { "delayMs": 300, "markdownHeader": "..." },
16
+ // "rules": [{ "projectId": "...", "commitSha": "...", "delayMs": 5000 }]
17
+ // }
18
+ // Behavior: sleep delayMs (timing control), then write
19
+ // changes/<sha12>.md plus the manifest with the frozen claim evidence refs.
20
+ // Every start/finish appends a JSONL record to the events file for
21
+ // cross-process invocation-count and overlap evidence.
22
+
23
+ const fs = require('node:fs');
24
+ const path = require('node:path');
25
+ const crypto = require('node:crypto');
26
+ const AtomicFile = require('../../../_modules/knowledge-engine/src/runtime/atomic-file.js');
27
+
28
+ function hashBuffer(value) {
29
+ return `sha256:${crypto.createHash('sha256').update(value).digest('hex')}`;
30
+ }
31
+
32
+ function appendEvent(eventsFile, record) {
33
+ if (!eventsFile) return;
34
+ fs.mkdirSync(path.dirname(eventsFile), { recursive: true });
35
+ fs.appendFileSync(eventsFile, `${JSON.stringify({ ...record, at: new Date().toISOString(), pid: process.pid })}\n`);
36
+ }
37
+
38
+ function readPlan(planFile) {
39
+ if (!planFile || !fs.existsSync(planFile)) return { default: {} };
40
+ try { return JSON.parse(fs.readFileSync(planFile, 'utf8')); } catch { return { default: {} }; }
41
+ }
42
+
43
+ function createStandinAnalyzer({ planFile, eventsFile } = {}) {
44
+ return {
45
+ sourceReadMode: 'isolated-frozen-evidence',
46
+ async runClaim(input) {
47
+ const plan = readPlan(planFile);
48
+ const rule = (plan.rules || []).find(r => (!r.projectId || r.projectId === input.projectId) && (!r.commitSha || r.commitSha === input.claim.commitSha)) || {};
49
+ const effective = { ...(plan.default || {}), ...rule };
50
+ appendEvent(eventsFile, { kind: 'start', projectId: input.projectId, commitSha: input.claim.commitSha, runId: input.claim.runId, delayMs: effective.delayMs || 0 });
51
+ if (effective.delayMs) await new Promise(resolve => setTimeout(resolve, effective.delayMs));
52
+ const relative = `changes/${input.claim.commitSha.slice(0, 12)}.md`;
53
+ const content = `${effective.markdownHeader || '# Verified maintenance'} ${input.projectId}\n\nCommit ${input.claim.commitSha} implements a fixture change.\n\n- Project: ${input.projectId}\n- Staged by: declarative stand-in analyzer (no real model output)\n`;
54
+ AtomicFile.writeFileAtomic(path.join(input.stagingPath, 'files', relative), content);
55
+ const refs = [
56
+ `commit:${input.claim.commitSha}`,
57
+ input.claim.patchHash && `patch:${input.claim.patchHash}`,
58
+ input.claim.conversationSnapshotHash && `conversation:${input.claim.conversationSnapshotHash}`,
59
+ input.claim.retrievalManifestHash && `retrieval:${input.claim.retrievalManifestHash}`,
60
+ ].filter(Boolean);
61
+ AtomicFile.writeJsonAtomic(input.manifestPath, {
62
+ schema: 'knowledge-staging-manifest/v1',
63
+ projectId: input.projectId,
64
+ runId: input.claim.runId,
65
+ commitSha: input.claim.commitSha,
66
+ operations: [{
67
+ path: relative,
68
+ operation: 'create',
69
+ sha256: hashBuffer(content),
70
+ reason: 'Frozen Git evidence from fixture commit',
71
+ evidenceReferences: refs,
72
+ }],
73
+ });
74
+ appendEvent(eventsFile, { kind: 'finish', projectId: input.projectId, commitSha: input.claim.commitSha, runId: input.claim.runId });
75
+ return { ok: true };
76
+ },
77
+ };
78
+ }
79
+
80
+ module.exports = { createStandinAnalyzer };
@@ -0,0 +1,177 @@
1
+ 'use strict';
2
+
3
+ // P-ENGINE-REVIEW-R2/R3 lane-exclusive candidate host for the knowledge-engine UI.
4
+ //
5
+ // Purpose: let a REAL browser load the REAL product UI bytes from a directory
6
+ // the caller chooses (the vendored copy = as shipped, or the module source
7
+ // tree = candidate fix), while /api/* is reverse-proxied to the REAL vendored
8
+ // engine - mirroring the product shell wiring where the UI is embedded
9
+ // same-origin behind the shell proxy. The engine refuses cross-origin
10
+ // requests (src/server.js FORBIDDEN_ORIGIN), so the browser origin and the
11
+ // API origin must be this one host.
12
+ //
13
+ // Harness-only fault injection (never touches the engine or the UI bytes):
14
+ // * retryDelayMs - hold retry POST responses so a second native click can
15
+ // land while the first intent is still in flight.
16
+ // * dropRetry - forward the retry POST upstream, let the engine really
17
+ // execute it, then destroy the browser socket without
18
+ // any response bytes (lost response -> the product
19
+ // client faces an UNKNOWN result).
20
+ // * rejectRetryStatus - answer the retry POST with an explicit error status
21
+ // (e.g. 409) WITHOUT forwarding it (the API clearly
22
+ // refused the intent).
23
+ // * holdRetryForward - accept the retry POST but do NOT forward it yet, so
24
+ // the engine still reports the run as failed and every
25
+ // detail re-render rebuilds a retry button for the SAME
26
+ // in-flight intent (the re-render counter-proof).
27
+ // releaseHeldRetries() forwards the parked requests.
28
+
29
+ const crypto = require('node:crypto');
30
+ const fs = require('node:fs');
31
+ const http = require('node:http');
32
+ const path = require('node:path');
33
+
34
+ const STATIC_FILES = new Map([
35
+ ['/', ['index.html', 'text/html; charset=utf-8']],
36
+ ['/index.html', ['index.html', 'text/html; charset=utf-8']],
37
+ ['/app.js', ['app.js', 'text/javascript; charset=utf-8']],
38
+ ['/app.css', ['app.css', 'text/css; charset=utf-8']],
39
+ ]);
40
+
41
+ function fileSha(file) {
42
+ return crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex');
43
+ }
44
+
45
+ function startUiHost({ uiDir, engineBase, retryDelayMs = 0, dropRetry = false, rejectRetryStatus = 0, holdRetryForward = false }) {
46
+ const settings = { retryDelayMs, dropRetry, rejectRetryStatus, holdRetryForward };
47
+ const state = {
48
+ proxiedApiRequests: 0,
49
+ receivedRetryPosts: 0,
50
+ forwardedRetryPosts: 0,
51
+ rejectedRetryResponses: 0,
52
+ heldRetryPosts: 0,
53
+ droppedRetryResponses: 0,
54
+ };
55
+ const held = [];
56
+
57
+ const forward = ({ url, method, headers, body }, res, isRetryPost) => {
58
+ const target = new URL(url.pathname + url.search, engineBase);
59
+ const outHeaders = { ...headers, host: target.host };
60
+ delete outHeaders.origin;
61
+ delete outHeaders.connection;
62
+ delete outHeaders['proxy-connection'];
63
+ delete outHeaders['content-length'];
64
+ if (body.length) outHeaders['content-length'] = String(body.length);
65
+ if (isRetryPost) state.forwardedRetryPosts += 1;
66
+ const upstream = http.request(target, { method, headers: outHeaders }, up => {
67
+ const responseChunks = [];
68
+ up.on('data', chunk => responseChunks.push(chunk));
69
+ up.on('end', () => {
70
+ const payload = Buffer.concat(responseChunks);
71
+ if (isRetryPost && settings.dropRetry) {
72
+ // The engine has fully executed the retry. Start the response (so
73
+ // the browser cannot transparently retry the request on a fresh
74
+ // keep-alive connection) and then destroy the socket mid-flight -
75
+ // the product client faces a truncated answer, i.e. an UNKNOWN
76
+ // result it must reconcile by querying, never by re-dispatching.
77
+ state.droppedRetryResponses += 1;
78
+ const out = { ...up.headers };
79
+ delete out['content-length'];
80
+ delete out['transfer-encoding'];
81
+ delete out.connection;
82
+ res.writeHead(up.statusCode, out);
83
+ res.flushHeaders();
84
+ setTimeout(() => res.destroy(), 30);
85
+ return;
86
+ }
87
+ const reply = () => {
88
+ const out = { ...up.headers };
89
+ delete out['content-length'];
90
+ delete out['transfer-encoding'];
91
+ delete out.connection;
92
+ if (payload.length) out['content-length'] = String(payload.length);
93
+ res.writeHead(up.statusCode, out);
94
+ res.end(payload);
95
+ };
96
+ if (isRetryPost && settings.retryDelayMs > 0) setTimeout(reply, settings.retryDelayMs);
97
+ else reply();
98
+ });
99
+ });
100
+ upstream.on('error', () => res.destroy());
101
+ upstream.end(body);
102
+ };
103
+
104
+ const server = http.createServer((req, res) => {
105
+ const url = new URL(req.url, 'http://127.0.0.1');
106
+ const staticEntry = req.method === 'GET' ? STATIC_FILES.get(url.pathname) : null;
107
+ if (staticEntry) {
108
+ res.writeHead(200, { 'Content-Type': staticEntry[1], 'Cache-Control': 'no-store' });
109
+ res.end(fs.readFileSync(path.join(uiDir, staticEntry[0])));
110
+ return;
111
+ }
112
+ if (!url.pathname.startsWith('/api/')) {
113
+ res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
114
+ res.end('not found');
115
+ return;
116
+ }
117
+ state.proxiedApiRequests += 1;
118
+ const chunks = [];
119
+ req.on('data', chunk => chunks.push(chunk));
120
+ req.on('end', () => {
121
+ const body = Buffer.concat(chunks);
122
+ const headers = { ...req.headers };
123
+ // The shell proxy terminates the browser origin; the engine would refuse
124
+ // any mismatched Origin header (FORBIDDEN_ORIGIN).
125
+ delete headers.origin;
126
+ delete headers.connection;
127
+ delete headers['proxy-connection'];
128
+ delete headers['content-length'];
129
+ const isRetryPost = req.method === 'POST' && /\/api\/runs\/[^/]+\/retry$/.test(url.pathname);
130
+ if (isRetryPost) state.receivedRetryPosts += 1;
131
+
132
+ if (isRetryPost && settings.rejectRetryStatus) {
133
+ state.rejectedRetryResponses += 1;
134
+ res.writeHead(settings.rejectRetryStatus, { 'Content-Type': 'application/json; charset=utf-8' });
135
+ res.end(JSON.stringify({ ok: false, error: 'RUN_NOT_RETRYABLE', message: `ui-host injected explicit refusal (HTTP ${settings.rejectRetryStatus})` }));
136
+ return;
137
+ }
138
+ if (isRetryPost && settings.holdRetryForward) {
139
+ state.heldRetryPosts += 1;
140
+ held.push({ url, method: req.method, headers, body, res });
141
+ return;
142
+ }
143
+ forward({ url, method: req.method, headers, body }, res, isRetryPost);
144
+ });
145
+ });
146
+
147
+ return {
148
+ state,
149
+ uiDir,
150
+ uiHashes: {
151
+ 'index.html': fileSha(path.join(uiDir, 'index.html')),
152
+ 'app.js': fileSha(path.join(uiDir, 'app.js')),
153
+ 'app.css': fileSha(path.join(uiDir, 'app.css')),
154
+ },
155
+ configure(next) { Object.assign(settings, next); },
156
+ // Forward every parked retry POST and answer it (the held intent finally
157
+ // reaches the engine).
158
+ releaseHeldRetries() {
159
+ const parked = held.splice(0, held.length);
160
+ for (const request of parked) {
161
+ const isRetryPost = request.method === 'POST' && /\/api\/runs\/[^/]+\/retry$/.test(request.url.pathname);
162
+ forward(request, request.res, isRetryPost);
163
+ }
164
+ return parked.length;
165
+ },
166
+ async listen() {
167
+ await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
168
+ return `http://127.0.0.1:${server.address().port}`;
169
+ },
170
+ async close() {
171
+ server.closeAllConnections();
172
+ await new Promise(resolve => server.close(resolve));
173
+ },
174
+ };
175
+ }
176
+
177
+ module.exports = { startUiHost };