@sanqianx/project-knowledge 5.0.24 → 5.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/plugins/marketplace.json +20 -20
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +1361 -1353
- package/LICENSE +201 -201
- package/NOTICE +5 -5
- package/README.md +349 -349
- package/_modules/knowledge-engine/package.json +1 -1
- package/_modules/knowledge-engine/src/coordinator.js +48 -3
- package/_modules/knowledge-engine/src/runtime/automation-config.js +140 -140
- package/_modules/knowledge-engine/src/runtime/commit-conversation-binder.js +238 -238
- package/_modules/knowledge-engine/src/runtime/commit-processing-ledger.js +26 -26
- package/_modules/knowledge-engine/src/runtime/commit-prompt.js +193 -193
- package/_modules/knowledge-engine/src/runtime/commit-reconciler.js +394 -394
- package/_modules/knowledge-engine/src/runtime/contracts.js +282 -282
- package/_modules/knowledge-engine/src/runtime/conversation-store.js +389 -389
- package/_modules/knowledge-engine/src/runtime/evidence-bundle.js +228 -228
- package/_modules/knowledge-engine/src/runtime/git-runner.js +62 -62
- package/_modules/knowledge-engine/src/runtime/knowledge-promotion.js +505 -505
- package/_modules/knowledge-engine/src/runtime/knowledge-retrieval-service.js +400 -400
- package/_modules/knowledge-engine/src/runtime/markdown-knowledge-indexer.js +171 -171
- package/_modules/knowledge-engine/src/runtime/scanner.js +298 -298
- package/_modules/knowledge-engine/ui/app.js +23 -2
- package/_site/README.md +30 -30
- package/_site/_test/agent-capture-mcp-ui-test.js +68 -68
- package/_site/_test/agent-capture-ui-test.js +101 -101
- package/_site/_test/ai-profile-resolver-test.js +137 -137
- package/_site/_test/ai-profile-test.js +75 -75
- package/_site/_test/ai-vendor-presets-test.js +91 -91
- package/_site/_test/automatic-context-test.js +70 -70
- package/_site/_test/automation-queue-test.js +14 -14
- package/_site/_test/automation-ui-test.js +40 -40
- package/_site/_test/background-task-registry-test.js +43 -43
- package/_site/_test/baseline-schema-test.js +91 -91
- package/_site/_test/bin-cli-test.js +230 -230
- package/_site/_test/bridge-adapter-test.js +95 -95
- package/_site/_test/bridge-consumer-service-test.js +310 -310
- package/_site/_test/candidate-bin-content-test.js +35 -35
- package/_site/_test/candidate-product-assets-test.js +13 -13
- package/_site/_test/candidate-release-contract-test.js +14 -14
- package/_site/_test/capture-hook-dedup-test.js +158 -158
- package/_site/_test/cdp-browser-failure-test.js +103 -103
- package/_site/_test/chat-claudecodeui-match-test.js +92 -92
- package/_site/_test/claude-executable-discovery-test.js +90 -90
- package/_site/_test/claude-session-lifecycle-sweep-test.js +252 -252
- package/_site/_test/claude-workbench-test.js +174 -174
- package/_site/_test/cli-instance-management-test.js +62 -62
- package/_site/_test/client-capture-restart-e2e-test.js +189 -189
- package/_site/_test/codex-conversation-projection-test.js +60 -60
- package/_site/_test/codex-marketplace-scoped-path-test.js +186 -186
- package/_site/_test/codex-notify-capture-e2e-test.js +101 -101
- package/_site/_test/codex-notify-fanout-test.js +141 -134
- package/_site/_test/codex-notify-upgrade-test.js +253 -253
- package/_site/_test/commit-boundary-freeze-test.js +147 -147
- package/_site/_test/commit-conversation-binding-test.js +99 -99
- package/_site/_test/commit-evidence-test.js +110 -110
- package/_site/_test/configuration-generation-test.js +22 -22
- package/_site/_test/context-pack-test.js +200 -200
- package/_site/_test/conversation-api-test.js +119 -119
- package/_site/_test/conversation-origin-test.js +15 -15
- package/_site/_test/conversation-store-test.js +138 -138
- package/_site/_test/cross-repo-isolation-e2e-test.js +187 -187
- package/_site/_test/desktop-browser-compat-test.js +28 -28
- package/_site/_test/desktop-hook-runtime-regression-test.js +204 -204
- package/_site/_test/embedding-config-test.js +32 -32
- package/_site/_test/explicit-commit-processor-test.js +37 -37
- package/_site/_test/fixtures/fake-browser-exit.js +10 -10
- package/_site/_test/fixtures/fake-browser-hang.js +10 -10
- package/_site/_test/fixtures/integration-busy-worker.cjs +6 -6
- package/_site/_test/fixtures/make-git-repos.js +92 -92
- package/_site/_test/fixtures/retrieval-gold-queries.json +32 -32
- package/_site/_test/folder-picker-output-test.js +19 -19
- package/_site/_test/fresh-hook-reimport-test.js +53 -53
- package/_site/_test/fresh-product-data-test.js +56 -56
- package/_site/_test/full-integration-e2e-test.js +167 -167
- package/_site/_test/git-path-compatibility-test.js +80 -80
- package/_site/_test/git-validation-test.js +81 -81
- package/_site/_test/glm-ui-refresh-review-test.js +313 -404
- package/_site/_test/harness-isolation-test.js +138 -0
- package/_site/_test/helpers/cdp-browser.js +383 -0
- package/_site/_test/helpers/cdp-network-capture.js +66 -0
- package/_site/_test/helpers/find-chrome.js +34 -0
- package/_site/_test/helpers/free-port.js +8 -0
- package/_site/_test/helpers/logging-ui-fixture.js +131 -0
- package/_site/_test/helpers/module-fixture.js +282 -0
- package/_site/_test/helpers/parallel-engine-advanced-engine-child.js +45 -0
- package/_site/_test/helpers/parallel-engine-advanced-fault-writer.js +171 -0
- package/_site/_test/helpers/parallel-engine-advanced-harness.js +245 -0
- package/_site/_test/helpers/parallel-engine-advanced-standin-analyzer.js +80 -0
- package/_site/_test/helpers/parallel-engine-advanced-ui-host.js +177 -0
- package/_site/_test/helpers/parallel-engine-final-harness.js +314 -0
- package/_site/_test/helpers/parallel-engine-final-standin-analyzer.js +159 -0
- package/_site/_test/helpers/parallel-knowledge-fixture.js +255 -0
- package/_site/_test/helpers/parallel-logging-acceptance-fixture.js +111 -0
- package/_site/_test/helpers/parallel-logging-acceptance-proxy.js +106 -0
- package/_site/_test/helpers/parallel-logging-fix-r2-proxy.js +205 -0
- package/_site/_test/helpers/parallel-logging-integration-5025-env.js +432 -0
- package/_site/_test/helpers/parallel-memory-analyzer.js +81 -0
- package/_site/_test/helpers/parallel-memory-event-bridge.js +128 -0
- package/_site/_test/helpers/parallel-memory-shell.js +470 -0
- package/_site/_test/helpers/parallel-nav-isolation-env.js +389 -0
- package/_site/_test/helpers/parallel-nav-module-ui.js +186 -0
- package/_site/_test/helpers/parallel-nav-proxy.js +148 -0
- package/_site/_test/helpers/parallel-nav-shell.js +361 -0
- package/_site/_test/helpers/parallel-qa-engine-endpoint-guard.js +206 -0
- package/_site/_test/helpers/parallel-qa-engine-endpoint-isolate.js +257 -0
- package/_site/_test/helpers/parallel-retrieval-followup-corpus.js +293 -0
- package/_site/_test/helpers/parallel-retrieval-followup-next-session.js +70 -0
- package/_site/_test/helpers/parallel-retrieval-followup-r2-shell.js +737 -0
- package/_site/_test/helpers/parallel-retrieval-followup-r2-wb-host.js +82 -0
- package/_site/_test/helpers/parallel-retrieval-followup-shell.js +279 -0
- package/_site/_test/helpers/parallel-workbench-fixture.js +371 -0
- package/_site/_test/helpers/parallel-workbench-host.js +80 -0
- package/_site/_test/helpers/parallel-workbench-integration-5025-fixture.js +408 -0
- package/_site/_test/helpers/parallel-workbench-integration-5025-harness.js +593 -0
- package/_site/_test/helpers/parallel-workbench-integration-5025-host.js +70 -0
- package/_site/_test/helpers/parallel-workbench-integration-5025-launcher.js +240 -0
- package/_site/_test/helpers/parallel-workbench-integration-5025-runtime-harness.js +630 -0
- package/_site/_test/helpers/parallel-workbench-source-map.js +196 -0
- package/_site/_test/helpers/spawn-server.js +106 -0
- package/_site/_test/helpers/version-visibility-fixture.js +251 -0
- package/_site/_test/hook-runtime-endpoint-test.js +88 -88
- package/_site/_test/hook-status-repair-api-test.js +152 -152
- package/_site/_test/hook-trigger-test.js +85 -85
- package/_site/_test/hook-worktree-test.js +42 -42
- package/_site/_test/import-preflight-api-test.js +234 -234
- package/_site/_test/index-builder-test.js +41 -41
- package/_site/_test/index-error-display-contract-test.js +10 -10
- package/_site/_test/index-writer-concurrency-test.js +135 -135
- package/_site/_test/integration-adapters-test.js +262 -262
- package/_site/_test/integration-auto-repair-test.js +113 -113
- package/_site/_test/integration-capture-setup-test.js +118 -118
- package/_site/_test/integration-intent-test.js +81 -81
- package/_site/_test/integration-runtime-binding-a2-test.js +566 -566
- package/_site/_test/integration-runtime-binding-a3-test.js +227 -227
- package/_site/_test/integration-runtime-binding-test.js +473 -473
- package/_site/_test/integration-status-scan-test.js +29 -29
- package/_site/_test/integration-surface-coverage-test.js +164 -164
- package/_site/_test/kb-framework-test.js +57 -57
- package/_site/_test/kbpath-follow-test.js +63 -63
- package/_site/_test/knowledge-db-test.js +144 -144
- package/_site/_test/knowledge-engine-client-test.js +120 -109
- package/_site/_test/knowledge-language-control-test.js +170 -170
- package/_site/_test/knowledge-maintenance-test.js +40 -40
- package/_site/_test/knowledge-promotion-recovery-test.js +260 -260
- package/_site/_test/knowledge-query-test.js +54 -54
- package/_site/_test/knowledge-retrieval-service-test.js +77 -77
- package/_site/_test/knowledge-scopes-test.js +37 -37
- package/_site/_test/knowledge-storage-location-test.js +28 -28
- package/_site/_test/knowledge-storage-startup-test.js +52 -52
- package/_site/_test/knowledge-store-logs-supervision-test.js +89 -89
- package/_site/_test/launcher-readiness-test.js +80 -80
- package/_site/_test/legacy-claude-session-alias-test.js +106 -106
- package/_site/_test/legacy-routes-removed-test.js +47 -47
- package/_site/_test/legacy-workbench-exclusion-test.js +92 -92
- package/_site/_test/live-gateway-test.js +48 -48
- package/_site/_test/local-marketplace-test.js +16 -16
- package/_site/_test/log-redaction-test.js +58 -58
- package/_site/_test/logging-api-test.js +89 -89
- package/_site/_test/logging-sse-no-gap-test.js +88 -88
- package/_site/_test/logging-ui-test.js +107 -107
- package/_site/_test/markdown-delta-overlay-test.js +85 -85
- package/_site/_test/markdown-maintenance-api-test.js +75 -75
- package/_site/_test/markdown-maintenance-test.js +11 -11
- package/_site/_test/mcp-server-test.js +149 -149
- package/_site/_test/model-context-windows-test.js +89 -89
- package/_site/_test/module-agent-start-proxy-test.js +65 -65
- package/_site/_test/module-artifact-integrity-test.js +27 -27
- package/_site/_test/module-boundary-test.js +30 -30
- package/_site/_test/module-bridge-eventbridge-test.js +202 -202
- package/_site/_test/module-dynamic-port-test.js +118 -118
- package/_site/_test/module-index-proxy-test.js +33 -33
- package/_site/_test/module-model-configuration-test.js +44 -44
- package/_site/_test/module-process-lifecycle-test.js +35 -35
- package/_site/_test/module-stream-proxy-test.js +34 -34
- package/_site/_test/module-terminal-restart-test.js +63 -63
- package/_site/_test/module-wiring-unbind-race-test.js +59 -59
- package/_site/_test/native-context-integrations-test.js +86 -86
- package/_site/_test/non-release-ci-test.js +34 -34
- package/_site/_test/offline-boundary-isolation-test.js +32 -32
- package/_site/_test/orphaned-claim-recovery-test.js +80 -80
- package/_site/_test/package-boundary-test.js +43 -43
- package/_site/_test/package-startup-test.js +56 -56
- package/_site/_test/packaged-ui-smoke-test.js +88 -88
- package/_site/_test/parallel-ci-r9-posix-socket-budget-test.js +156 -0
- package/_site/_test/parallel-engine-advanced-eng005-test.js +136 -0
- package/_site/_test/parallel-engine-advanced-eng006-test.js +171 -0
- package/_site/_test/parallel-engine-advanced-eng007-reconcile-test.js +231 -0
- package/_site/_test/parallel-engine-advanced-eng009-test.js +208 -0
- package/_site/_test/parallel-engine-advanced-eng010-test.js +213 -0
- package/_site/_test/parallel-engine-advanced-eng011-ui-probe.js +459 -0
- package/_site/_test/parallel-engine-final-eng002-test.js +255 -0
- package/_site/_test/parallel-engine-final-eng007-test.js +269 -0
- package/_site/_test/parallel-engine-final-eng011-test.js +197 -0
- package/_site/_test/parallel-engine-final-eng012-test.js +354 -0
- package/_site/_test/parallel-knowledge-client-error-code-test.js +184 -0
- package/_site/_test/parallel-knowledge-engine-test.js +353 -0
- package/_site/_test/parallel-knowledge-retrieval-test.js +292 -0
- package/_site/_test/parallel-knowledge-vector-test.js +168 -0
- package/_site/_test/parallel-linux-ci-r7-log007-day-test.js +110 -0
- package/_site/_test/parallel-logging-acceptance-log003-test.js +224 -0
- package/_site/_test/parallel-logging-acceptance-log004-test.js +231 -0
- package/_site/_test/parallel-logging-acceptance-log005-test.js +208 -0
- package/_site/_test/parallel-logging-acceptance-log006-test.js +214 -0
- package/_site/_test/parallel-logging-acceptance-log007-test.js +223 -0
- package/_site/_test/parallel-logging-acceptance-log008-test.js +180 -0
- package/_site/_test/parallel-logging-fix-r2-crash-probe.js +271 -0
- package/_site/_test/parallel-logging-fix-r2-gap-test.js +294 -0
- package/_site/_test/parallel-logging-fix-r2-normalhook-test.js +330 -0
- package/_site/_test/parallel-logging-integration-5025-portability-test.js +554 -0
- package/_site/_test/parallel-memory-candidate-test.js +301 -0
- package/_site/_test/parallel-memory-manual-test.js +197 -0
- package/_site/_test/parallel-memory-scope-test.js +228 -0
- package/_site/_test/parallel-memory-source-test.js +227 -0
- package/_site/_test/parallel-memory-sync-test.js +238 -0
- package/_site/_test/parallel-memory-view-r8-reload-gate-test.js +123 -0
- package/_site/_test/parallel-nav-failure-test.js +119 -0
- package/_site/_test/parallel-nav-isolation-test.js +308 -0
- package/_site/_test/parallel-nav-isolation-vector-path-test.js +90 -0
- package/_site/_test/parallel-nav-offline-test.js +272 -0
- package/_site/_test/parallel-nav-operability-test.js +257 -0
- package/_site/_test/parallel-nav-switch-test.js +247 -0
- package/_site/_test/parallel-nav-theme-test.js +130 -0
- package/_site/_test/parallel-nav-viewport-test.js +310 -0
- package/_site/_test/parallel-qa-engine-endpoint-guard-test.js +273 -0
- package/_site/_test/parallel-retrieval-followup-citation-test.js +219 -0
- package/_site/_test/parallel-retrieval-followup-corpus-test.js +287 -0
- package/_site/_test/parallel-workbench-independent-host.js +262 -0
- package/_site/_test/parallel-workbench-integration-5025-abort-probe.js +340 -0
- package/_site/_test/parallel-workbench-integration-5025-drafts-probe.js +588 -0
- package/_site/_test/parallel-workbench-integration-5025-env-check.js +317 -0
- package/_site/_test/parallel-workbench-integration-5025-model-probe.js +342 -0
- package/_site/_test/parallel-workbench-integration-5025-ordering-probe.js +326 -0
- package/_site/_test/parallel-workbench-model-probe.js +336 -0
- package/_site/_test/parallel-workbench-offline-test.js +169 -0
- package/_site/_test/parallel-workbench-provenance-trace.js +134 -0
- package/_site/_test/parallel-workbench-source-match.js +206 -0
- package/_site/_test/parallel-workbench-standalone-turn.js +349 -0
- package/_site/_test/path-consistency-test.js +151 -151
- package/_site/_test/pending-sweep-test.js +9 -9
- package/_site/_test/post-commit-automation-test.js +87 -87
- package/_site/_test/pr-consumer-contract-test.js +55 -55
- package/_site/_test/product-brand-contract-test.js +25 -25
- package/_site/_test/product-diagnostics-ui-test.js +93 -93
- package/_site/_test/product-empty-state-test.js +148 -0
- package/_site/_test/product-import-ui-test.js +219 -104
- package/_site/_test/product-navigation-test.js +152 -0
- package/_site/_test/product-progress-status-test.js +84 -84
- package/_site/_test/project-delete-recovery-test.js +64 -64
- package/_site/_test/project-domain-create-test.js +91 -0
- package/_site/_test/project-domain-scope-retrieval-test.js +214 -0
- package/_site/_test/project-git-init-confirm-test.js +115 -0
- package/_site/_test/project-goal-editor-test.js +144 -144
- package/_site/_test/project-import-duplicate-alias-test.js +134 -0
- package/_site/_test/project-import-unicode-restart-test.js +140 -0
- package/_site/_test/project-lifecycle-transaction-test.js +106 -106
- package/_site/_test/project-module-partial-recovery-test.js +222 -0
- package/_site/_test/project-remove-running-guard-test.js +79 -79
- package/_site/_test/project-store-test.js +90 -90
- package/_site/_test/project-unbind-late-read-ui-test.js +250 -0
- package/_site/_test/project-unbind-writer-guard-test.js +231 -0
- package/_site/_test/prompt-settings-test.js +115 -115
- package/_site/_test/protected-architecture-gate-test.js +122 -122
- package/_site/_test/refactor-characterization-test.js +36 -36
- package/_site/_test/registry-events-test.js +38 -38
- package/_site/_test/release-version-sync-test.js +115 -115
- package/_site/_test/requirement-binding-test.js +113 -113
- package/_site/_test/requirement-recorder-test.js +173 -173
- package/_site/_test/run-all-tests.js +173 -161
- package/_site/_test/runtime-endpoint-test.js +64 -64
- package/_site/_test/scanner-test.js +83 -83
- package/_site/_test/server-security-test.js +96 -96
- package/_site/_test/sessions-stream-test.js +93 -93
- package/_site/_test/shared-contracts-test.js +58 -58
- package/_site/_test/shared-scope-root-binding-test.js +74 -67
- package/_site/_test/simple-import-test.js +98 -98
- package/_site/_test/startup-analysis-disabled-test.js +16 -16
- package/_site/_test/storage-foundation-test.js +78 -78
- package/_site/_test/structured-logger-test.js +101 -101
- package/_site/_test/t07b-cln-005-coverage-test.js +212 -0
- package/_site/_test/team-knowledge-store-sparse-checkout-test.js +196 -196
- package/_site/_test/team-knowledge-store-test.js +132 -132
- package/_site/_test/test-server-cleanup-test.js +35 -35
- package/_site/_test/test-server-module-isolation-test.js +37 -37
- package/_site/_test/tracking-start-test.js +144 -144
- package/_site/_test/vector-storage-root-test.js +75 -75
- package/_site/_test/version-visibility-browser-probe.js +249 -0
- package/_site/_test/version-visibility-test.js +92 -0
- package/_site/_test/workbench-context-receipts-test.js +22 -22
- package/_site/_test/workbench-permission-test.js +117 -117
- package/_site/_test/zcode-capture-integration-test.js +112 -112
- package/_site/lib/ai-profile-resolver.js +78 -78
- package/_site/lib/ai-vendor-presets.js +83 -83
- package/_site/lib/ai-workspace.js +104 -104
- package/_site/lib/atomic-file.js +204 -204
- package/_site/lib/automation-config.js +140 -140
- package/_site/lib/bridge-adapter.js +260 -260
- package/_site/lib/bridge-consumer-service.js +402 -402
- package/_site/lib/capture-hook-config.js +108 -108
- package/_site/lib/claude-cli-runner.js +1599 -1599
- package/_site/lib/cli-instances.js +43 -43
- package/_site/lib/codex-context-status.js +17 -17
- package/_site/lib/codex-notify-config.js +193 -193
- package/_site/lib/commit-conversation-binder.js +247 -247
- package/_site/lib/commit-processing-ledger.js +27 -27
- package/_site/lib/commit-prompt.js +202 -202
- package/_site/lib/commit-reconciler.js +444 -444
- package/_site/lib/context-pack-builder.js +299 -299
- package/_site/lib/contracts.js +291 -291
- package/_site/lib/conversation-exclusions.js +204 -204
- package/_site/lib/conversation-query-service.js +161 -161
- package/_site/lib/conversation-store.js +387 -387
- package/_site/lib/data-dir.js +13 -13
- package/_site/lib/embedding-service.js +85 -85
- package/_site/lib/engine-connection.js +93 -93
- package/_site/lib/engine-knowledge-client.js +76 -72
- package/_site/lib/evidence-bundle.js +228 -228
- package/_site/lib/folder-picker-output.js +24 -24
- package/_site/lib/git-path.js +14 -14
- package/_site/lib/git-runner.js +62 -62
- package/_site/lib/github-team-store.js +1175 -1175
- package/_site/lib/hook-manager.js +203 -203
- package/_site/lib/index-builder.js +157 -157
- package/_site/lib/index-service.js +173 -173
- package/_site/lib/integration-auto-repair.js +77 -77
- package/_site/lib/integration-installer.js +1240 -1240
- package/_site/lib/integration-intent.js +88 -88
- package/_site/lib/integration-status-scan.js +99 -99
- package/_site/lib/integration-status-worker.js +14 -14
- package/_site/lib/kb-framework.js +191 -191
- package/_site/lib/kb-validator.js +124 -124
- package/_site/lib/knowledge-db.js +363 -363
- package/_site/lib/knowledge-promotion.js +435 -435
- package/_site/lib/knowledge-retrieval-service.js +401 -401
- package/_site/lib/knowledge-schema.js +121 -121
- package/_site/lib/knowledge-tool-runtime.js +366 -366
- package/_site/lib/live-gateway.js +78 -78
- package/_site/lib/llm-client.js +173 -173
- package/_site/lib/markdown-knowledge-indexer.js +230 -230
- package/_site/lib/model-context-windows.js +82 -82
- package/_site/lib/module-bridge.js +874 -874
- package/_site/lib/module-port-resolver.js +57 -57
- package/_site/lib/post-commit-automation.js +141 -141
- package/_site/lib/product-data.js +35 -35
- package/_site/lib/project-lifecycle-service.js +554 -554
- package/_site/lib/project-registry-store.js +129 -129
- package/_site/lib/project-store.js +268 -268
- package/_site/lib/prompt-registry.js +148 -148
- package/_site/lib/public-version-info.js +37 -0
- package/_site/lib/registry-events.js +16 -16
- package/_site/lib/requirement-adapters.js +10 -10
- package/_site/lib/requirement-binder.js +112 -112
- package/_site/lib/requirement-recorder.js +278 -278
- package/_site/lib/runtime-control.js +89 -89
- package/_site/lib/runtime-endpoint.js +160 -160
- package/_site/lib/scanner.js +298 -298
- package/_site/lib/server-app.js +1672 -1664
- package/_site/lib/settings-store.js +153 -153
- package/_site/lib/storage-layout.js +166 -166
- package/_site/lib/structured-logger.js +574 -574
- package/_site/lib/zcode-context-integration.js +60 -60
- package/_site/scripts/codex-notify-fanout.cjs +95 -95
- package/_site/scripts/folder-picker.ps1 +156 -156
- package/_site/scripts/hook-trigger.js +158 -158
- package/_site/scripts/install-module-candidates.js +69 -69
- package/_site/scripts/pack-module-candidates.js +89 -89
- package/_site/scripts/sync-product-content.js +28 -28
- package/_site/scripts/sync-release-version.js +164 -164
- package/_site/scripts/vendor-modules.js +49 -49
- package/_site/scripts/verify-module-runtime.js +50 -50
- package/_site/scripts/verify-product-runtime.js +36 -36
- package/_site/scripts/verify-retrieval-gold.js +83 -83
- package/_site/server.js +15 -15
- package/_site/start.bat +26 -26
- package/_site/stop.bat +11 -11
- package/bin/project-knowledge-integrations.js +254 -254
- package/bin/project-knowledge-kb.js +67 -67
- package/bin/project-knowledge-mcp.js +201 -201
- package/bin/project-knowledge.js +269 -170
- package/claude-prompts.json +21 -21
- package/docs/README.zh-CN.md +207 -205
- package/docs/assets/architecture.svg +181 -181
- package/docs/assets/logo.svg +49 -49
- package/docs/fresh-v5-start.md +44 -44
- package/docs/leader-glm-workbench-playbook.md +122 -122
- package/docs/project-registry-schema.md +33 -33
- package/docs/release-5.0.16-acceptance.md +176 -176
- package/docs/release-5.0.17-acceptance.md +117 -117
- package/docs/release-5.0.19-acceptance.md +39 -39
- package/docs/team-knowledge-mode-a-plan.md +73 -73
- package/docs/testing-strategy.md +33 -33
- package/module-runtime-manifest.json +68 -65
- package/package.json +113 -110
- package/plugins/project-knowledge/.claude-plugin/plugin.json +1 -1
- package/plugins/project-knowledge/.codex-plugin/plugin.json +1 -1
- package/plugins/project-knowledge/.mcp.json +1 -1
- package/templates/change.md +30 -30
- package/templates/project-readme.md +52 -52
- package/ui/index.html +3 -2
- package/ui/version-info.css +44 -0
- package/ui/version-info.js +24 -0
- package/vendor-manifest.json +55 -55
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// _site/_test/helpers/parallel-qa-engine-endpoint-guard.js — P-QA-ENGINE-ENDPOINT-FIX-R5
|
|
3
|
+
//
|
|
4
|
+
// Fail-closed endpoint discipline for every engine construction in this lane.
|
|
5
|
+
// The engine coordinator ignores env for its vector/bridge legs (hardcoded
|
|
6
|
+
// LIVE fallbacks 127.0.0.1:8787/8790), so tests must pass explicit OWN urls —
|
|
7
|
+
// these helpers refuse anything else instead of silently defaulting live:
|
|
8
|
+
//
|
|
9
|
+
// assertOwnedEndpoint(url, {role}) throws PK_ENGINE_ENDPOINT_REFUSED for
|
|
10
|
+
// missing/non-http/non-loopback/port-0/
|
|
11
|
+
// protected-port URLs; accepts ONLY
|
|
12
|
+
// http on loopback with an explicit
|
|
13
|
+
// non-protected port.
|
|
14
|
+
// guardedCreateEngineServer(options) requires a safe options.vectorUrl AND
|
|
15
|
+
// (safe options.bridgeUrl OR an
|
|
16
|
+
// options.bridge double); only then
|
|
17
|
+
// lazily requires the product server.
|
|
18
|
+
// Refusals never load product code.
|
|
19
|
+
// installEgressGuard() patches global.fetch: protected ports
|
|
20
|
+
// and non-loopback hosts throw
|
|
21
|
+
// PK_PROTECTED_EGRESS_BLOCKED BEFORE
|
|
22
|
+
// any I/O (no socket is opened); every
|
|
23
|
+
// allowed call is recorded and passed
|
|
24
|
+
// through. Covers requestIndex
|
|
25
|
+
// (default-param fetch), retrieval
|
|
26
|
+
// recallIndex, coordinator health and
|
|
27
|
+
// ModuleBridge._fetch, which all read
|
|
28
|
+
// global fetch at call time.
|
|
29
|
+
// createEngineVectorStandin() minimal OWN vector contract server
|
|
30
|
+
// (ephemeral loopback port): POST
|
|
31
|
+
// /api/import, POST /api/sync, GET
|
|
32
|
+
// /api/projects, GET /api/search.
|
|
33
|
+
// /api/search answers 503 so retrieval
|
|
34
|
+
// degrades to lexical — this stand-in
|
|
35
|
+
// proves request routing and contract
|
|
36
|
+
// parity, NOT real vector quality.
|
|
37
|
+
// createEngineBridgeDouble() in-process bridge test double with
|
|
38
|
+
// the full drain surface; never opens
|
|
39
|
+
// a socket.
|
|
40
|
+
const http = require('node:http');
|
|
41
|
+
const path = require('node:path');
|
|
42
|
+
const { PROTECTED_PORTS } = require('./parallel-qa-engine-endpoint-isolate');
|
|
43
|
+
|
|
44
|
+
const REFUSAL_CODE = 'PK_ENGINE_ENDPOINT_REFUSED';
|
|
45
|
+
const EGRESS_BLOCK_CODE = 'PK_PROTECTED_EGRESS_BLOCKED';
|
|
46
|
+
const ENGINE_SERVER_MODULE = path.resolve(__dirname, '..', '..', '..', '_modules', 'knowledge-engine', 'src', 'server.js');
|
|
47
|
+
|
|
48
|
+
function refusal(message, extra = {}) {
|
|
49
|
+
return Object.assign(new Error(message), { code: REFUSAL_CODE, ...extra });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function assertOwnedEndpoint(value, { role = 'endpoint' } = {}) {
|
|
53
|
+
if (typeof value !== 'string' || !value.trim()) throw refusal(`${role}: 缺少显式 URL,拒绝回落 LIVE 默认端口。`, { role });
|
|
54
|
+
let url;
|
|
55
|
+
try { url = new URL(value); } catch { throw refusal(`${role}: URL 无法解析(${value})。`, { role }); }
|
|
56
|
+
if (url.protocol !== 'http:') throw refusal(`${role}: 只允许 http://(收到 ${url.protocol}//)。`, { role });
|
|
57
|
+
if (!['127.0.0.1', 'localhost', '[::1]'].includes(url.hostname)) throw refusal(`${role}: 只允许回环地址(收到 ${url.hostname})。`, { role });
|
|
58
|
+
const port = Number(url.port);
|
|
59
|
+
if (!url.port || !Number.isInteger(port) || port <= 0) throw refusal(`${role}: 必须显式指定非零端口(收到 ${value})。`, { role });
|
|
60
|
+
if (PROTECTED_PORTS.has(port)) throw refusal(`${role}: 端口 ${port} 属于保护模块端口(${[...PROTECTED_PORTS].join('/')}),拒绝 LIVE 默认接触。`, { role, port });
|
|
61
|
+
return url;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function assertBridgeOption(options) {
|
|
65
|
+
if (options.bridge !== undefined) {
|
|
66
|
+
if (!options.bridge || typeof options.bridge !== 'object' || Array.isArray(options.bridge)) throw refusal('bridge 替身必须是对象。');
|
|
67
|
+
return options.bridge;
|
|
68
|
+
}
|
|
69
|
+
assertOwnedEndpoint(options.bridgeUrl, { role: 'bridgeUrl' });
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function guardedCreateEngineServer(options = {}) {
|
|
74
|
+
assertOwnedEndpoint(options.vectorUrl, { role: 'vectorUrl' });
|
|
75
|
+
assertBridgeOption(options);
|
|
76
|
+
const { createEngineServer } = require(ENGINE_SERVER_MODULE);
|
|
77
|
+
return createEngineServer(options);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function installEgressGuard() {
|
|
81
|
+
const original = global.fetch;
|
|
82
|
+
if (typeof original !== 'function') throw new Error('global.fetch 不可用,无法安装出口守卫。');
|
|
83
|
+
const blocked = [];
|
|
84
|
+
const requests = [];
|
|
85
|
+
function judge(url) {
|
|
86
|
+
let port;
|
|
87
|
+
if (url.port === '') port = url.protocol === 'https:' ? 443 : url.protocol === 'http:' ? 80 : NaN;
|
|
88
|
+
else port = Number(url.port);
|
|
89
|
+
if (Number.isInteger(port) && PROTECTED_PORTS.has(port)) return `protected-port:${port}`;
|
|
90
|
+
// URL.hostname keeps IPv6 literals in bracketed form — this list must
|
|
91
|
+
// match assertOwnedEndpoint's exactly ('[::1]', never bare '::1', which
|
|
92
|
+
// no URL.hostname ever yields).
|
|
93
|
+
if (!['127.0.0.1', 'localhost', '[::1]'].includes(url.hostname)) return `non-loopback-host:${url.hostname}`;
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const guard = async (input, init) => {
|
|
97
|
+
let href = null, method = null;
|
|
98
|
+
try {
|
|
99
|
+
const url = input instanceof URL ? new URL(input.href) : new URL(typeof input === 'string' ? input : input?.url);
|
|
100
|
+
href = url.href;
|
|
101
|
+
method = (init?.method) || (typeof input === 'object' && input?.method) || 'GET';
|
|
102
|
+
const reason = judge(url);
|
|
103
|
+
if (reason) {
|
|
104
|
+
const error = Object.assign(new Error(`出口守卫:${reason} — ${href}(已阻止,未建立任何连接)`), { code: EGRESS_BLOCK_CODE, target: href, reason });
|
|
105
|
+
blocked.push({ href, method, reason, at: Date.now() });
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
requests.push({ href, method, at: Date.now() });
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (error && error.code === EGRESS_BLOCK_CODE) throw error;
|
|
111
|
+
const record = { href: String(input), method: 'UNKNOWN', reason: 'unparseable-target', at: Date.now() };
|
|
112
|
+
blocked.push(record);
|
|
113
|
+
throw Object.assign(new Error(`出口守卫:无法解析目标,按拒绝处理 — ${record.href}`), { code: EGRESS_BLOCK_CODE, target: record.href, reason: 'unparseable-target' });
|
|
114
|
+
}
|
|
115
|
+
return original(input, init);
|
|
116
|
+
};
|
|
117
|
+
global.fetch = guard;
|
|
118
|
+
return {
|
|
119
|
+
blocked,
|
|
120
|
+
requests,
|
|
121
|
+
uninstall() { if (global.fetch === guard) global.fetch = original; },
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function respondJson(res, status, payload) {
|
|
126
|
+
const body = JSON.stringify(payload);
|
|
127
|
+
res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8', 'Content-Length': Buffer.byteLength(body) });
|
|
128
|
+
res.end(body);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function createEngineVectorStandin({ label = 'r5-vector-standin' } = {}) {
|
|
132
|
+
const records = [];
|
|
133
|
+
const projects = new Map();
|
|
134
|
+
const server = http.createServer((req, res) => {
|
|
135
|
+
const chunks = [];
|
|
136
|
+
req.on('data', chunk => chunks.push(chunk));
|
|
137
|
+
req.on('end', () => {
|
|
138
|
+
let body = null;
|
|
139
|
+
try { const text = Buffer.concat(chunks).toString('utf8'); if (text) body = JSON.parse(text); } catch { body = null; }
|
|
140
|
+
records.push({ method: req.method, path: req.url, body, at: Date.now() });
|
|
141
|
+
const route = (req.url || '').split('?')[0];
|
|
142
|
+
if (req.method === 'POST' && route === '/api/import') {
|
|
143
|
+
const name = String(body?.projectName || '(missing-projectName)');
|
|
144
|
+
const sourceDir = String(body?.sourceDir || '');
|
|
145
|
+
projects.set(name, { name, hasIndex: true, sourceDir });
|
|
146
|
+
respondJson(res, 200, { ok: true, project: { name, hasIndex: true, sourceDir } });
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (req.method === 'POST' && route === '/api/sync') {
|
|
150
|
+
const name = String(body?.project || '(missing-project)');
|
|
151
|
+
const sourceDir = String(body?.sourceDir || '');
|
|
152
|
+
projects.set(name, { name, hasIndex: true, sourceDir });
|
|
153
|
+
respondJson(res, 200, { ok: true });
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (req.method === 'GET' && route === '/api/projects') {
|
|
157
|
+
respondJson(res, 200, { projects: [...projects.values()] });
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (req.method === 'GET' && route === '/api/search') {
|
|
161
|
+
// Stand-in deliberately reports unavailable: retrieval must degrade to
|
|
162
|
+
// lexical. This fixture proves request routing and contract parity —
|
|
163
|
+
// it must never be cited as real vector retrieval quality.
|
|
164
|
+
respondJson(res, 503, { ok: false, error: { code: 'VECTOR_UNAVAILABLE_STANDIN', message: `${label}: 替身不提供向量检索质量` } });
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
respondJson(res, 404, { ok: false, error: { code: 'NOT_FOUND', message: `${label}: 未实现该向量契约路由` } });
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
const listening = new Promise((resolve, reject) => {
|
|
171
|
+
server.once('error', reject);
|
|
172
|
+
server.listen(0, '127.0.0.1', () => resolve(server.address().port));
|
|
173
|
+
});
|
|
174
|
+
const standin = {
|
|
175
|
+
label,
|
|
176
|
+
records,
|
|
177
|
+
projects,
|
|
178
|
+
url: null,
|
|
179
|
+
async close() { await listening.catch(() => {}); await new Promise(resolve => server.close(resolve)); },
|
|
180
|
+
};
|
|
181
|
+
standin.ready = listening.then(port => { standin.url = `http://127.0.0.1:${port}`; return standin.url; });
|
|
182
|
+
return standin;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function createEngineBridgeDouble() {
|
|
186
|
+
return {
|
|
187
|
+
double: 'r5-bridge-double',
|
|
188
|
+
calls: [],
|
|
189
|
+
async registerConsumer(consumer, options) { this.calls.push({ op: 'registerConsumer', consumer }); return { ok: true }; },
|
|
190
|
+
async listJournals() { this.calls.push({ op: 'listJournals' }); return []; },
|
|
191
|
+
async readEvents(query) { this.calls.push({ op: 'readEvents', query }); return []; },
|
|
192
|
+
async ackConsumerCursor(consumer, through, options) { this.calls.push({ op: 'ackConsumerCursor', consumer, through }); return { ok: true }; },
|
|
193
|
+
async close() { this.calls.push({ op: 'close' }); },
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
module.exports = {
|
|
198
|
+
REFUSAL_CODE,
|
|
199
|
+
EGRESS_BLOCK_CODE,
|
|
200
|
+
PROTECTED_PORTS,
|
|
201
|
+
assertOwnedEndpoint,
|
|
202
|
+
guardedCreateEngineServer,
|
|
203
|
+
installEgressGuard,
|
|
204
|
+
createEngineVectorStandin,
|
|
205
|
+
createEngineBridgeDouble,
|
|
206
|
+
};
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// _site/_test/helpers/parallel-qa-engine-endpoint-isolate.js — P-QA-ENGINE-ENDPOINT-FIX-R5
|
|
3
|
+
//
|
|
4
|
+
// Driver/child environment isolation for the engine-endpoint lane. Applied as
|
|
5
|
+
// the FIRST action of a test's main phase, BEFORE any product module is
|
|
6
|
+
// required: this process's environment is wiped and rebuilt from an explicit
|
|
7
|
+
// case-insensitive SYSTEM whitelist (provider keys, NODE_OPTIONS, proxy URLs
|
|
8
|
+
// and CLI injection vars are dropped by construction), then the complete
|
|
9
|
+
// isolation map below points every product surface at one per-run layout:
|
|
10
|
+
// HOME/USERPROFILE/HOMEDRIVE/HOMEPATH, CODEX_HOME, CLAUDE_CONFIG_DIR,
|
|
11
|
+
// APPDATA, LOCALAPPDATA, TEMP/TMP/TMPDIR, PSModuleAnalysisCachePath,
|
|
12
|
+
// KB_DATA_DIR, KB_KNOWLEDGE_DATA_DIR, AI_CODING_EVENT_BRIDGE_HOME,
|
|
13
|
+
// AGENT_TERMINAL_DATA_DIR, CLAUDE_AI_WORKBENCH_DATA_DIR,
|
|
14
|
+
// KB_MODULES_AUTOSTART='0', and dead-zero module URLs so no ambient module
|
|
15
|
+
// address survives. Every env-pointed directory is MATERIALIZED and
|
|
16
|
+
// statSync-verified before the map is applied (not string-only checks).
|
|
17
|
+
//
|
|
18
|
+
// Chrome (when the lane needs a browser) is captured with the REAL
|
|
19
|
+
// environment BEFORE the wipe and carried through as KB_CHROME_PATH — the
|
|
20
|
+
// find-chrome helper honours it first, so post-isolation lookups cannot fall
|
|
21
|
+
// back to a wiped machine path. An empty default-shaped Chrome "User Data"
|
|
22
|
+
// scaffold is pre-created under the isolated home (Chrome >= 136 gate).
|
|
23
|
+
//
|
|
24
|
+
// Lane overrides (own fixture URLs, lane markers) are applied AFTER the
|
|
25
|
+
// cleanup through childEnv(extra) / the values this module returns — never
|
|
26
|
+
// merged before the wipe.
|
|
27
|
+
//
|
|
28
|
+
// P-QA-ENGINE-ENDPOINT-REVIEW-R6 corrections, all in one place:
|
|
29
|
+
// * PSModuleAnalysisCachePath is a cache FILE PowerShell writes itself —
|
|
30
|
+
// only its PARENT is materialized and the target is asserted to never be
|
|
31
|
+
// a directory (R5 mkdir'd every layout value and turned it into one);
|
|
32
|
+
// * the dead module URLs use port 1, not port 0: :0 is an invalid address
|
|
33
|
+
// a ModulePortResolver may treat as "unset" and fall back LIVE, while :1
|
|
34
|
+
// (tcpmux) is a valid, near-certainly-dead explicit port;
|
|
35
|
+
// * POSIX uses short root/temp/data components and enforces a worst-case
|
|
36
|
+
// socket byte budget (Chrome SingletonSocket under the isolated temp +
|
|
37
|
+
// the runtime-control domain socket under the data dir; sun_path is 108
|
|
38
|
+
// bytes including NUL, budgeted in UTF-8 BYTES). The budget is asserted
|
|
39
|
+
// on the worst-case mkdtemp result BEFORE any filesystem write, and the
|
|
40
|
+
// full lane tag lives in owner.json inside the root so short names cost
|
|
41
|
+
// no post-mortem ownership. Windows keeps the descriptive R5 names.
|
|
42
|
+
|
|
43
|
+
const fs = require('node:fs');
|
|
44
|
+
const os = require('node:os');
|
|
45
|
+
const path = require('node:path');
|
|
46
|
+
|
|
47
|
+
const REPO_ROOT = path.resolve(__dirname, '..', '..', '..');
|
|
48
|
+
const PROTECTED_PORTS = new Set([5757, 5760, 5789, 5790, 8787, 8790]);
|
|
49
|
+
|
|
50
|
+
// Captured at module load, before any isolation rebuilds the environment.
|
|
51
|
+
const LIVE_HOME = process.env.USERPROFILE || process.env.HOME || os.homedir();
|
|
52
|
+
const IS_POSIX = process.platform !== 'win32';
|
|
53
|
+
|
|
54
|
+
// POSIX socket budget (mirrors the R9 Nav helper constants — physical limits,
|
|
55
|
+
// not tunables): sun_path is 108 bytes including the NUL terminator, so 107
|
|
56
|
+
// chars is the hard ceiling, and Chrome's SingletonSocket suffix rand is
|
|
57
|
+
// observed at ~6 chars but budgeted at 12.
|
|
58
|
+
const POSIX_SOCKET_CHAR_LIMIT = 107;
|
|
59
|
+
const CHROME_RAND_MAX_CHARS = 12;
|
|
60
|
+
const POSIX_TEMP_NAME = 't';
|
|
61
|
+
const POSIX_DATA_NAME = 'data';
|
|
62
|
+
|
|
63
|
+
/** Worst-case POSIX socket paths this layout must be able to host. */
|
|
64
|
+
function worstCaseSocketPaths(root) {
|
|
65
|
+
const base = String(root).replaceAll('\\', '/').replace(/\/+$/, '');
|
|
66
|
+
return {
|
|
67
|
+
chromeSingletonSocket: `${base}/${POSIX_TEMP_NAME}/com.google.Chrome.${'x'.repeat(CHROME_RAND_MAX_CHARS)}/SingletonSocket`,
|
|
68
|
+
productRuntimeControlSock: `${base}/${POSIX_DATA_NAME}/runtime-control.sock`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function socketBudgetVerdict(root, limit = POSIX_SOCKET_CHAR_LIMIT) {
|
|
73
|
+
const paths = worstCaseSocketPaths(root);
|
|
74
|
+
const chromeSocketBytes = Buffer.byteLength(paths.chromeSingletonSocket, 'utf8');
|
|
75
|
+
const controlSocketBytes = Buffer.byteLength(paths.productRuntimeControlSock, 'utf8');
|
|
76
|
+
return { ok: chromeSocketBytes <= limit && controlSocketBytes <= limit, limit, chromeSocketBytes, controlSocketBytes, paths };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Fail fast — with the computed path in the message — when the budget cannot hold. */
|
|
80
|
+
function assertSocketBudget(root, what) {
|
|
81
|
+
const verdict = socketBudgetVerdict(root);
|
|
82
|
+
if (!verdict.ok) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`POSIX socket path budget exceeded for ${what}: worst-case Chrome SingletonSocket is ${verdict.chromeSocketBytes} UTF-8 bytes, limit is ${verdict.limit} — ${verdict.paths.chromeSingletonSocket}`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
return verdict;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const SYSTEM_ENV_WHITELIST = [
|
|
91
|
+
'SystemRoot', 'SystemDrive', 'windir', 'ComSpec', 'PATHEXT',
|
|
92
|
+
'PROCESSOR_ARCHITECTURE', 'PROCESSOR_ARCHITECTURE_W6432', 'PROCESSOR_IDENTIFIER',
|
|
93
|
+
'PROCESSOR_LEVEL', 'PROCESSOR_REVISION', 'NUMBER_OF_PROCESSORS',
|
|
94
|
+
'PROGRAMFILES', 'PROGRAMFILES(X86)', 'PROGRAMW6432',
|
|
95
|
+
'PATH', 'TEMP', 'TMP', 'TMPDIR',
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
const PRESERVED_VARS = ['PK_TEST_TEMP_ROOT'];
|
|
99
|
+
|
|
100
|
+
function isInside(candidate, parent) {
|
|
101
|
+
const relative = path.relative(parent, candidate);
|
|
102
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function systemBaseEnv(source = process.env) {
|
|
106
|
+
const allow = new Set(SYSTEM_ENV_WHITELIST.map(name => name.toLowerCase()));
|
|
107
|
+
const base = {};
|
|
108
|
+
for (const [key, value] of Object.entries(source)) {
|
|
109
|
+
if (value !== undefined && allow.has(key.toLowerCase())) base[key] = value;
|
|
110
|
+
}
|
|
111
|
+
return base;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function resolveTempRoot() {
|
|
115
|
+
const candidates = [process.env.PK_TEST_TEMP_ROOT, process.env.TEMP, process.env.TMP, process.env.TMPDIR];
|
|
116
|
+
const chosen = candidates.find(value => value && String(value).trim());
|
|
117
|
+
const root = path.resolve(chosen ? String(chosen).trim() : os.tmpdir());
|
|
118
|
+
if (isInside(root, REPO_ROOT)) throw new Error(`refusing to use a temp root inside the repository: ${root}`);
|
|
119
|
+
return root;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let applied = null;
|
|
123
|
+
|
|
124
|
+
function applyDriverIsolation({ prefix = 'pk-qa-engine-endpoint', captureChrome = false } = {}) {
|
|
125
|
+
if (applied) throw new Error('applyDriverIsolation must run exactly once per process');
|
|
126
|
+
// Discovery with the REAL environment, strictly before the wipe.
|
|
127
|
+
let chrome = null;
|
|
128
|
+
if (captureChrome) {
|
|
129
|
+
const { findChromeDetailed } = require('./find-chrome');
|
|
130
|
+
const detailed = findChromeDetailed();
|
|
131
|
+
chrome = detailed && detailed.path ? detailed.path : null;
|
|
132
|
+
}
|
|
133
|
+
const tempRoot = resolveTempRoot();
|
|
134
|
+
// POSIX shortens the mkdtemp prefix to 'pkq': every byte of the root is
|
|
135
|
+
// spent by every socket beneath it. The suffix adds exactly 6 ASCII chars,
|
|
136
|
+
// so the worst-case root is knowable BEFORE any filesystem write — a
|
|
137
|
+
// configured temp that cannot host the budget is refused up front.
|
|
138
|
+
const shortPrefix = IS_POSIX ? 'pkq' : `${prefix}-`;
|
|
139
|
+
const mkdtempPrefix = path.join(tempRoot, shortPrefix);
|
|
140
|
+
if (IS_POSIX) assertSocketBudget(`${mkdtempPrefix}xxxxxx`, `configured temp root ${tempRoot} + prefix ${shortPrefix} (checked before any filesystem write)`);
|
|
141
|
+
const root = fs.mkdtempSync(mkdtempPrefix);
|
|
142
|
+
if (isInside(root, REPO_ROOT)) throw new Error(`refusing to create an isolation layout inside the repository: ${root}`);
|
|
143
|
+
if (IS_POSIX) {
|
|
144
|
+
try {
|
|
145
|
+
assertSocketBudget(root, 'created isolation root');
|
|
146
|
+
} catch (error) {
|
|
147
|
+
try { fs.rmSync(root, { recursive: true, force: true }); } catch { /* best effort */ }
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const layout = {
|
|
152
|
+
root,
|
|
153
|
+
home: path.join(root, 'home'),
|
|
154
|
+
appData: path.join(root, 'appdata'),
|
|
155
|
+
localAppData: path.join(root, 'localappdata'),
|
|
156
|
+
// POSIX 't'/'data': three fewer bytes on every Chrome socket path and a
|
|
157
|
+
// short runtime-control socket root; Windows keeps the descriptive names.
|
|
158
|
+
temp: path.join(root, IS_POSIX ? POSIX_TEMP_NAME : 'temp'),
|
|
159
|
+
codexHome: path.join(root, 'codex-home'),
|
|
160
|
+
claudeConfigDir: path.join(root, 'claude-config'),
|
|
161
|
+
bridgeHome: path.join(root, 'bridge-home'),
|
|
162
|
+
dataDir: path.join(root, IS_POSIX ? POSIX_DATA_NAME : 'workbench-data'),
|
|
163
|
+
knowledgeDataDir: path.join(root, IS_POSIX ? 'kb' : 'knowledge-data'),
|
|
164
|
+
};
|
|
165
|
+
for (const dir of Object.values(layout)) fs.mkdirSync(dir, { recursive: true });
|
|
166
|
+
for (const dir of Object.values(layout)) {
|
|
167
|
+
if (!fs.statSync(dir).isDirectory()) throw new Error(`isolation directory does not really exist on disk: ${dir}`);
|
|
168
|
+
}
|
|
169
|
+
// PSModuleAnalysisCachePath is a cache FILE PowerShell writes itself: only
|
|
170
|
+
// the parent is materialized, and the target must never be a directory.
|
|
171
|
+
layout.psModuleCacheParent = path.join(root, IS_POSIX ? 'pm' : 'ps-module-analysis-cache');
|
|
172
|
+
layout.psModuleCache = path.join(layout.psModuleCacheParent, IS_POSIX ? 'm.bin' : 'AnalysisCache.bin');
|
|
173
|
+
fs.mkdirSync(layout.psModuleCacheParent, { recursive: true });
|
|
174
|
+
if (!fs.statSync(layout.psModuleCacheParent).isDirectory()) throw new Error(`PS cache parent does not really exist on disk: ${layout.psModuleCacheParent}`);
|
|
175
|
+
if (fs.existsSync(layout.psModuleCache) && fs.statSync(layout.psModuleCache).isDirectory()) {
|
|
176
|
+
throw new Error(`PSModuleAnalysisCachePath target must be a file path, never a directory: ${layout.psModuleCache}`);
|
|
177
|
+
}
|
|
178
|
+
// Short POSIX component names must cost no post-mortem ownership: the full
|
|
179
|
+
// lane tag, pid and creation time stay on disk inside the root.
|
|
180
|
+
const owner = {
|
|
181
|
+
schema: 'qa-autopilot/engine-endpoint-isolation-owner/v1',
|
|
182
|
+
tag: prefix,
|
|
183
|
+
platform: process.platform,
|
|
184
|
+
pid: process.pid,
|
|
185
|
+
createdAt: new Date().toISOString(),
|
|
186
|
+
tempRoot,
|
|
187
|
+
};
|
|
188
|
+
fs.writeFileSync(path.join(root, 'owner.json'), JSON.stringify(owner, null, 2) + '\n', 'utf8');
|
|
189
|
+
// Chrome >= 136 refuses --remote-debugging-port unless it can resolve its
|
|
190
|
+
// DEFAULT user data dir under the home it sees. Empty default-shaped
|
|
191
|
+
// scaffold, entirely inside the isolated root.
|
|
192
|
+
fs.mkdirSync(path.join(layout.home, 'AppData', 'Local', 'Google', 'Chrome', 'User Data'), { recursive: true });
|
|
193
|
+
fs.mkdirSync(path.join(layout.home, 'AppData', 'Roaming'), { recursive: true });
|
|
194
|
+
|
|
195
|
+
const parsed = path.parse(layout.home);
|
|
196
|
+
const envMap = {
|
|
197
|
+
HOME: layout.home,
|
|
198
|
+
USERPROFILE: layout.home,
|
|
199
|
+
HOMEDRIVE: parsed.root,
|
|
200
|
+
HOMEPATH: parsed.root === path.sep ? layout.home.slice(1) : layout.home.slice(parsed.root.length),
|
|
201
|
+
CODEX_HOME: layout.codexHome,
|
|
202
|
+
CLAUDE_CONFIG_DIR: layout.claudeConfigDir,
|
|
203
|
+
APPDATA: layout.appData,
|
|
204
|
+
LOCALAPPDATA: layout.localAppData,
|
|
205
|
+
TEMP: layout.temp,
|
|
206
|
+
TMP: layout.temp,
|
|
207
|
+
TMPDIR: layout.temp,
|
|
208
|
+
PSModuleAnalysisCachePath: layout.psModuleCache,
|
|
209
|
+
KB_DATA_DIR: layout.dataDir,
|
|
210
|
+
KB_KNOWLEDGE_DATA_DIR: layout.knowledgeDataDir,
|
|
211
|
+
AI_CODING_EVENT_BRIDGE_HOME: layout.bridgeHome,
|
|
212
|
+
AGENT_TERMINAL_DATA_DIR: layout.dataDir,
|
|
213
|
+
CLAUDE_AI_WORKBENCH_DATA_DIR: layout.dataDir,
|
|
214
|
+
KB_MODULES_AUTOSTART: '0',
|
|
215
|
+
// Valid-but-dead explicit ports (R6): :0 is an invalid address a port
|
|
216
|
+
// resolver may treat as unset and fall back LIVE; :1 never runs these
|
|
217
|
+
// modules and remains a well-formed URL. Caller-owned actual URLs passed
|
|
218
|
+
// to childEnv() still win.
|
|
219
|
+
KB_TERMINAL_URL: 'http://127.0.0.1:1',
|
|
220
|
+
KB_VECTORHUB_URL: 'http://127.0.0.1:1',
|
|
221
|
+
KB_EVENTBRIDGE_URL: 'http://127.0.0.1:1',
|
|
222
|
+
KB_KNOWLEDGE_ENGINE_URL: 'http://127.0.0.1:1',
|
|
223
|
+
};
|
|
224
|
+
const preserved = systemBaseEnv(process.env);
|
|
225
|
+
for (const key of PRESERVED_VARS) {
|
|
226
|
+
if (process.env[key] !== undefined) preserved[key] = process.env[key];
|
|
227
|
+
}
|
|
228
|
+
for (const key of Object.keys(process.env)) delete process.env[key];
|
|
229
|
+
Object.assign(process.env, preserved, envMap);
|
|
230
|
+
if (chrome) process.env.KB_CHROME_PATH = chrome;
|
|
231
|
+
applied = { layout, envMap, chrome, tempRoot, owner };
|
|
232
|
+
return applied;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// The environment an own child (product server, git helper) may inherit from
|
|
236
|
+
// an already-isolated driver: the whitelisted+isolated env plus the caller's
|
|
237
|
+
// EXPLICIT lane values, which win.
|
|
238
|
+
function childEnv(extra = {}) {
|
|
239
|
+
if (!applied) throw new Error('applyDriverIsolation must run before childEnv');
|
|
240
|
+
return { ...systemBaseEnv(process.env), ...applied.envMap, ...extra };
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
module.exports = {
|
|
244
|
+
PROTECTED_PORTS,
|
|
245
|
+
SYSTEM_ENV_WHITELIST,
|
|
246
|
+
applyDriverIsolation,
|
|
247
|
+
childEnv,
|
|
248
|
+
systemBaseEnv,
|
|
249
|
+
isInside,
|
|
250
|
+
LIVE_HOME,
|
|
251
|
+
IS_POSIX,
|
|
252
|
+
POSIX_SOCKET_CHAR_LIMIT,
|
|
253
|
+
CHROME_RAND_MAX_CHARS,
|
|
254
|
+
worstCaseSocketPaths,
|
|
255
|
+
socketBudgetVerdict,
|
|
256
|
+
assertSocketBudget,
|
|
257
|
+
};
|