@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.
- 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 +66 -63
- 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
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
const assert = require('assert');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const os = require('os');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { spawnServer } = require('./helpers/spawn-server');
|
|
6
|
-
|
|
7
|
-
const ROOT = path.resolve(__dirname, '..', '..');
|
|
8
|
-
const PORT = 7833;
|
|
9
|
-
const BASE = `http://127.0.0.1:${PORT}`;
|
|
10
|
-
const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pkb-routes-v2-'));
|
|
11
|
-
|
|
12
|
-
async function waitForServer() {
|
|
13
|
-
for (let attempt = 0; attempt < 100; attempt += 1) {
|
|
14
|
-
try { if ((await fetch(`${BASE}/api/health`)).ok) return; } catch {}
|
|
15
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
16
|
-
}
|
|
17
|
-
throw new Error('server did not start');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
(async () => {
|
|
21
|
-
const source = `${fs.readFileSync(path.join(ROOT, '_site', 'server.js'), 'utf8')}\n${fs.readFileSync(path.join(ROOT, '_site', 'lib', 'server-app.js'), 'utf8')}`;
|
|
22
|
-
for (const removedSymbol of ['automation/simulate', 'automation/init', 'hook-install', 'hook-uninstall', 'dispatchProjectInit', 'DEFAULT_INIT_PROMPT_TEMPLATE', 'renderProjectInitPrompt', '/api/raw']) {
|
|
23
|
-
assert(!source.includes(removedSymbol), `removed production symbol remains: ${removedSymbol}`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const spawned = spawnServer({ root: ROOT, port: PORT, dataDir, tag: 'routes-v2', extraEnv: { KB_SKIP_MIGRATION: '1' } });
|
|
27
|
-
try {
|
|
28
|
-
await waitForServer();
|
|
29
|
-
const routes = [
|
|
30
|
-
['PUT', '/api/projects'],
|
|
31
|
-
['POST', '/api/projects/project-example/init'],
|
|
32
|
-
['POST', '/api/projects/project-example/automation/simulate'],
|
|
33
|
-
['POST', '/api/projects/project-example/automation/init'],
|
|
34
|
-
['GET', '/api/projects/project-example/hook-status'],
|
|
35
|
-
['POST', '/api/projects/project-example/hook-install'],
|
|
36
|
-
['POST', '/api/projects/project-example/hook-uninstall'],
|
|
37
|
-
['GET', '/api/raw?path=README.md'],
|
|
38
|
-
];
|
|
39
|
-
for (const [method, pathname] of routes) {
|
|
40
|
-
const response = await fetch(`${BASE}${pathname}`, { method });
|
|
41
|
-
assert.strictEqual(response.status, 404, `${method} ${pathname} should be removed`);
|
|
42
|
-
}
|
|
43
|
-
console.log('legacy-routes-removed-test PASS');
|
|
44
|
-
} finally {
|
|
45
|
-
await spawned.cleanup();
|
|
46
|
-
}
|
|
47
|
-
})().catch(error => { console.error(error); process.exitCode = 1; });
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { spawnServer } = require('./helpers/spawn-server');
|
|
6
|
+
|
|
7
|
+
const ROOT = path.resolve(__dirname, '..', '..');
|
|
8
|
+
const PORT = 7833;
|
|
9
|
+
const BASE = `http://127.0.0.1:${PORT}`;
|
|
10
|
+
const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pkb-routes-v2-'));
|
|
11
|
+
|
|
12
|
+
async function waitForServer() {
|
|
13
|
+
for (let attempt = 0; attempt < 100; attempt += 1) {
|
|
14
|
+
try { if ((await fetch(`${BASE}/api/health`)).ok) return; } catch {}
|
|
15
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
16
|
+
}
|
|
17
|
+
throw new Error('server did not start');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
(async () => {
|
|
21
|
+
const source = `${fs.readFileSync(path.join(ROOT, '_site', 'server.js'), 'utf8')}\n${fs.readFileSync(path.join(ROOT, '_site', 'lib', 'server-app.js'), 'utf8')}`;
|
|
22
|
+
for (const removedSymbol of ['automation/simulate', 'automation/init', 'hook-install', 'hook-uninstall', 'dispatchProjectInit', 'DEFAULT_INIT_PROMPT_TEMPLATE', 'renderProjectInitPrompt', '/api/raw']) {
|
|
23
|
+
assert(!source.includes(removedSymbol), `removed production symbol remains: ${removedSymbol}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const spawned = spawnServer({ root: ROOT, port: PORT, dataDir, tag: 'routes-v2', extraEnv: { KB_SKIP_MIGRATION: '1' } });
|
|
27
|
+
try {
|
|
28
|
+
await waitForServer();
|
|
29
|
+
const routes = [
|
|
30
|
+
['PUT', '/api/projects'],
|
|
31
|
+
['POST', '/api/projects/project-example/init'],
|
|
32
|
+
['POST', '/api/projects/project-example/automation/simulate'],
|
|
33
|
+
['POST', '/api/projects/project-example/automation/init'],
|
|
34
|
+
['GET', '/api/projects/project-example/hook-status'],
|
|
35
|
+
['POST', '/api/projects/project-example/hook-install'],
|
|
36
|
+
['POST', '/api/projects/project-example/hook-uninstall'],
|
|
37
|
+
['GET', '/api/raw?path=README.md'],
|
|
38
|
+
];
|
|
39
|
+
for (const [method, pathname] of routes) {
|
|
40
|
+
const response = await fetch(`${BASE}${pathname}`, { method });
|
|
41
|
+
assert.strictEqual(response.status, 404, `${method} ${pathname} should be removed`);
|
|
42
|
+
}
|
|
43
|
+
console.log('legacy-routes-removed-test PASS');
|
|
44
|
+
} finally {
|
|
45
|
+
await spawned.cleanup();
|
|
46
|
+
}
|
|
47
|
+
})().catch(error => { console.error(error); process.exitCode = 1; });
|
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
// Run: node _site/_test/legacy-workbench-exclusion-test.js
|
|
2
|
-
//
|
|
3
|
-
// T17 / GATE LEGACY-001: old embedded Workbench pairs are excluded from
|
|
4
|
-
// Development Conversation presentation and new commit binding; genuine
|
|
5
|
-
// explicit MCP requirements survive; immutable snapshots and JSONL lines are
|
|
6
|
-
// never rewritten.
|
|
7
|
-
|
|
8
|
-
const assert = require('assert');
|
|
9
|
-
const fs = require('fs');
|
|
10
|
-
const os = require('os');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const { StorageLayout } = require('../lib/storage-layout');
|
|
13
|
-
const { ProjectStore } = require('../lib/project-store');
|
|
14
|
-
const { ConversationStore } = require('../lib/conversation-store');
|
|
15
|
-
const { CommitConversationBinder } = require('../lib/commit-conversation-binder');
|
|
16
|
-
const { computeConversationExclusions, readDevelopmentEvents } = require('../lib/conversation-exclusions');
|
|
17
|
-
|
|
18
|
-
const temp = fs.mkdtempSync(path.join(os.tmpdir(), `kb-legacy-exclusion-${process.pid}-`));
|
|
19
|
-
const layout = new StorageLayout({ dataDir: path.join(temp, 'data') });
|
|
20
|
-
const projects = new ProjectStore({ layout });
|
|
21
|
-
const store = new ConversationStore({ layout, projectStore: projects, logger: null });
|
|
22
|
-
const projectId = 'project-legacy';
|
|
23
|
-
|
|
24
|
-
const repoIdentity = { commonDir: path.join(temp, 'repo', '.git') };
|
|
25
|
-
|
|
26
|
-
async function append(input) {
|
|
27
|
-
await store.appendEvent(projectId, {
|
|
28
|
-
source: 'claude-code',
|
|
29
|
-
sessionId: 'legacy-session',
|
|
30
|
-
projectPath: path.join(temp, 'repo'),
|
|
31
|
-
repoIdentity,
|
|
32
|
-
branch: 'main',
|
|
33
|
-
capturedAt: '2026-08-01T00:00:00.000Z',
|
|
34
|
-
...input,
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
(async () => {
|
|
39
|
-
await projects.create(projectId, {
|
|
40
|
-
displayName: 'Legacy', storageName: 'legacy',
|
|
41
|
-
repoPath: path.join(temp, 'repo'), knowledgePath: path.join(temp, 'knowledge'),
|
|
42
|
-
repoIdentity,
|
|
43
|
-
}, { conversationBaselineCursor: 0 });
|
|
44
|
-
|
|
45
|
-
// Old embedded Workbench pair (explicit-REQ1 + embedded-assistant-REQ1).
|
|
46
|
-
await append({ eventId: 'explicit-REQ1', sequence: 1, eventType: 'user_prompt', role: 'user', content: 'Workbench prompt', turnId: 'turn-embed-1', identityConfidence: 'high' });
|
|
47
|
-
await append({ eventId: 'embedded-assistant-REQ1', sequence: 2, eventType: 'assistant_response', role: 'assistant', content: 'Workbench reply', turnId: 'turn-embed-1', rawEventType: 'embedded-claude-result', identityConfidence: 'high' });
|
|
48
|
-
// Genuine explicit MCP requirement NOT paired with an embedded assistant.
|
|
49
|
-
await append({ eventId: 'explicit-REQ2', sequence: 3, eventType: 'user_prompt', role: 'user', content: 'Genuine MCP requirement', turnId: 'turn-explicit-2', identityConfidence: 'explicit', explicitCommitSha: 'f'.repeat(40) });
|
|
50
|
-
// Modern bridge-projected event.
|
|
51
|
-
await append({ eventId: 'evt-bridge-1', sequence: 4, eventType: 'user_prompt', role: 'user', content: 'Modern bridge event', turnId: 'turn-bridge', identityConfidence: 'exact' });
|
|
52
|
-
|
|
53
|
-
const eventsRaw = store.readEvents(projectId);
|
|
54
|
-
assert.strictEqual(eventsRaw.length, 4, 'raw JSONL lines are never deleted');
|
|
55
|
-
|
|
56
|
-
const manifest = computeConversationExclusions(projectId, eventsRaw);
|
|
57
|
-
assert.deepStrictEqual(manifest.excludedEventIds, ['embedded-assistant-REQ1', 'explicit-REQ1'], 'only the embedded pair is excluded');
|
|
58
|
-
|
|
59
|
-
const development = readDevelopmentEvents(store, projectId);
|
|
60
|
-
assert.deepStrictEqual(development.map(event => event.eventId), ['explicit-REQ2', 'evt-bridge-1'], 'genuine explicit + bridge events survive');
|
|
61
|
-
assert.strictEqual(development.some(event => event.content === 'Workbench prompt'), false);
|
|
62
|
-
assert.strictEqual(development.some(event => event.content === 'Workbench reply'), false);
|
|
63
|
-
|
|
64
|
-
// Manifest persisted for audit; JSONL untouched.
|
|
65
|
-
const manifestFile = path.join(layout.getProjectMetadataDir(projectId), 'conversation-exclusions.json');
|
|
66
|
-
assert.ok(fs.existsSync(manifestFile), 'exclusion manifest is persisted');
|
|
67
|
-
assert.strictEqual(JSON.parse(fs.readFileSync(manifestFile, 'utf8')).schema, 'conversation-exclusions/v1');
|
|
68
|
-
assert.strictEqual(store.readEvents(projectId).length, 4, 'raw store still holds every historical line');
|
|
69
|
-
|
|
70
|
-
// New commit binding excludes the legacy pair.
|
|
71
|
-
const binder = new CommitConversationBinder({ layout, projectStore: projects, conversationStore: store });
|
|
72
|
-
const commitSha = 'a'.repeat(40);
|
|
73
|
-
store.writeBoundary(projectId, {
|
|
74
|
-
repoIdentity, commitSha, parentShas: [], branch: 'main', committedAt: '2026-08-02T00:00:00.000Z',
|
|
75
|
-
bridgeCursorAtCommit: 10, journalSequence: 10, openTurnIdsAtCommit: [], operationId: 'op-legacy',
|
|
76
|
-
});
|
|
77
|
-
const snapshot = await binder.bind({ projectId, commitSha });
|
|
78
|
-
assert.ok(!JSON.stringify(snapshot).includes('Workbench prompt'), 'legacy embedded pair never binds to a new commit');
|
|
79
|
-
assert.ok(!JSON.stringify(snapshot).includes('embedded-claude-result'));
|
|
80
|
-
|
|
81
|
-
// An old frozen snapshot written before the migration stays byte-identical.
|
|
82
|
-
const frozenPath = layout.getProjectCommitConversationPath(projectId, commitSha);
|
|
83
|
-
const before = fs.readFileSync(frozenPath, 'utf8');
|
|
84
|
-
const rebound = await binder.bind({ projectId, commitSha });
|
|
85
|
-
assert.strictEqual(rebound.snapshotHash, snapshot.snapshotHash, 'immutable snapshot untouched by exclusion');
|
|
86
|
-
assert.strictEqual(fs.readFileSync(frozenPath, 'utf8'), before);
|
|
87
|
-
|
|
88
|
-
console.log('legacy-workbench-exclusion-test PASS');
|
|
89
|
-
})().catch(error => {
|
|
90
|
-
console.error(error.stack || error.message);
|
|
91
|
-
process.exitCode = 1;
|
|
92
|
-
});
|
|
1
|
+
// Run: node _site/_test/legacy-workbench-exclusion-test.js
|
|
2
|
+
//
|
|
3
|
+
// T17 / GATE LEGACY-001: old embedded Workbench pairs are excluded from
|
|
4
|
+
// Development Conversation presentation and new commit binding; genuine
|
|
5
|
+
// explicit MCP requirements survive; immutable snapshots and JSONL lines are
|
|
6
|
+
// never rewritten.
|
|
7
|
+
|
|
8
|
+
const assert = require('assert');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const { StorageLayout } = require('../lib/storage-layout');
|
|
13
|
+
const { ProjectStore } = require('../lib/project-store');
|
|
14
|
+
const { ConversationStore } = require('../lib/conversation-store');
|
|
15
|
+
const { CommitConversationBinder } = require('../lib/commit-conversation-binder');
|
|
16
|
+
const { computeConversationExclusions, readDevelopmentEvents } = require('../lib/conversation-exclusions');
|
|
17
|
+
|
|
18
|
+
const temp = fs.mkdtempSync(path.join(os.tmpdir(), `kb-legacy-exclusion-${process.pid}-`));
|
|
19
|
+
const layout = new StorageLayout({ dataDir: path.join(temp, 'data') });
|
|
20
|
+
const projects = new ProjectStore({ layout });
|
|
21
|
+
const store = new ConversationStore({ layout, projectStore: projects, logger: null });
|
|
22
|
+
const projectId = 'project-legacy';
|
|
23
|
+
|
|
24
|
+
const repoIdentity = { commonDir: path.join(temp, 'repo', '.git') };
|
|
25
|
+
|
|
26
|
+
async function append(input) {
|
|
27
|
+
await store.appendEvent(projectId, {
|
|
28
|
+
source: 'claude-code',
|
|
29
|
+
sessionId: 'legacy-session',
|
|
30
|
+
projectPath: path.join(temp, 'repo'),
|
|
31
|
+
repoIdentity,
|
|
32
|
+
branch: 'main',
|
|
33
|
+
capturedAt: '2026-08-01T00:00:00.000Z',
|
|
34
|
+
...input,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
(async () => {
|
|
39
|
+
await projects.create(projectId, {
|
|
40
|
+
displayName: 'Legacy', storageName: 'legacy',
|
|
41
|
+
repoPath: path.join(temp, 'repo'), knowledgePath: path.join(temp, 'knowledge'),
|
|
42
|
+
repoIdentity,
|
|
43
|
+
}, { conversationBaselineCursor: 0 });
|
|
44
|
+
|
|
45
|
+
// Old embedded Workbench pair (explicit-REQ1 + embedded-assistant-REQ1).
|
|
46
|
+
await append({ eventId: 'explicit-REQ1', sequence: 1, eventType: 'user_prompt', role: 'user', content: 'Workbench prompt', turnId: 'turn-embed-1', identityConfidence: 'high' });
|
|
47
|
+
await append({ eventId: 'embedded-assistant-REQ1', sequence: 2, eventType: 'assistant_response', role: 'assistant', content: 'Workbench reply', turnId: 'turn-embed-1', rawEventType: 'embedded-claude-result', identityConfidence: 'high' });
|
|
48
|
+
// Genuine explicit MCP requirement NOT paired with an embedded assistant.
|
|
49
|
+
await append({ eventId: 'explicit-REQ2', sequence: 3, eventType: 'user_prompt', role: 'user', content: 'Genuine MCP requirement', turnId: 'turn-explicit-2', identityConfidence: 'explicit', explicitCommitSha: 'f'.repeat(40) });
|
|
50
|
+
// Modern bridge-projected event.
|
|
51
|
+
await append({ eventId: 'evt-bridge-1', sequence: 4, eventType: 'user_prompt', role: 'user', content: 'Modern bridge event', turnId: 'turn-bridge', identityConfidence: 'exact' });
|
|
52
|
+
|
|
53
|
+
const eventsRaw = store.readEvents(projectId);
|
|
54
|
+
assert.strictEqual(eventsRaw.length, 4, 'raw JSONL lines are never deleted');
|
|
55
|
+
|
|
56
|
+
const manifest = computeConversationExclusions(projectId, eventsRaw);
|
|
57
|
+
assert.deepStrictEqual(manifest.excludedEventIds, ['embedded-assistant-REQ1', 'explicit-REQ1'], 'only the embedded pair is excluded');
|
|
58
|
+
|
|
59
|
+
const development = readDevelopmentEvents(store, projectId);
|
|
60
|
+
assert.deepStrictEqual(development.map(event => event.eventId), ['explicit-REQ2', 'evt-bridge-1'], 'genuine explicit + bridge events survive');
|
|
61
|
+
assert.strictEqual(development.some(event => event.content === 'Workbench prompt'), false);
|
|
62
|
+
assert.strictEqual(development.some(event => event.content === 'Workbench reply'), false);
|
|
63
|
+
|
|
64
|
+
// Manifest persisted for audit; JSONL untouched.
|
|
65
|
+
const manifestFile = path.join(layout.getProjectMetadataDir(projectId), 'conversation-exclusions.json');
|
|
66
|
+
assert.ok(fs.existsSync(manifestFile), 'exclusion manifest is persisted');
|
|
67
|
+
assert.strictEqual(JSON.parse(fs.readFileSync(manifestFile, 'utf8')).schema, 'conversation-exclusions/v1');
|
|
68
|
+
assert.strictEqual(store.readEvents(projectId).length, 4, 'raw store still holds every historical line');
|
|
69
|
+
|
|
70
|
+
// New commit binding excludes the legacy pair.
|
|
71
|
+
const binder = new CommitConversationBinder({ layout, projectStore: projects, conversationStore: store });
|
|
72
|
+
const commitSha = 'a'.repeat(40);
|
|
73
|
+
store.writeBoundary(projectId, {
|
|
74
|
+
repoIdentity, commitSha, parentShas: [], branch: 'main', committedAt: '2026-08-02T00:00:00.000Z',
|
|
75
|
+
bridgeCursorAtCommit: 10, journalSequence: 10, openTurnIdsAtCommit: [], operationId: 'op-legacy',
|
|
76
|
+
});
|
|
77
|
+
const snapshot = await binder.bind({ projectId, commitSha });
|
|
78
|
+
assert.ok(!JSON.stringify(snapshot).includes('Workbench prompt'), 'legacy embedded pair never binds to a new commit');
|
|
79
|
+
assert.ok(!JSON.stringify(snapshot).includes('embedded-claude-result'));
|
|
80
|
+
|
|
81
|
+
// An old frozen snapshot written before the migration stays byte-identical.
|
|
82
|
+
const frozenPath = layout.getProjectCommitConversationPath(projectId, commitSha);
|
|
83
|
+
const before = fs.readFileSync(frozenPath, 'utf8');
|
|
84
|
+
const rebound = await binder.bind({ projectId, commitSha });
|
|
85
|
+
assert.strictEqual(rebound.snapshotHash, snapshot.snapshotHash, 'immutable snapshot untouched by exclusion');
|
|
86
|
+
assert.strictEqual(fs.readFileSync(frozenPath, 'utf8'), before);
|
|
87
|
+
|
|
88
|
+
console.log('legacy-workbench-exclusion-test PASS');
|
|
89
|
+
})().catch(error => {
|
|
90
|
+
console.error(error.stack || error.message);
|
|
91
|
+
process.exitCode = 1;
|
|
92
|
+
});
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const assert = require('node:assert/strict');
|
|
3
|
-
const http = require('node:http');
|
|
4
|
-
const { once } = require('node:events');
|
|
5
|
-
const { WebSocket } = require('ws');
|
|
6
|
-
const { attachLiveGateway } = require('../lib/live-gateway');
|
|
7
|
-
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
8
|
-
(async () => {
|
|
9
|
-
let active = 0, total = 0;
|
|
10
|
-
const upstream = http.createServer((req, res) => {
|
|
11
|
-
active++; total++;
|
|
12
|
-
res.writeHead(200, { 'Content-Type': 'text/event-stream' });
|
|
13
|
-
res.write('id: 17\r\nevent: snapshot\r\ndata: {"ok":true}\r');
|
|
14
|
-
setTimeout(() => { if (!res.destroyed) res.write('\n\r\n'); }, 5);
|
|
15
|
-
req.on('close', () => { active--; });
|
|
16
|
-
});
|
|
17
|
-
await new Promise(resolve => upstream.listen(0, '127.0.0.1', resolve));
|
|
18
|
-
const origin = `http://127.0.0.1:${upstream.address().port}`;
|
|
19
|
-
const server = http.createServer();
|
|
20
|
-
const runtime = { moduleBridge: { engineUrl: origin, engineCompatible: true, _terminalApi: route => origin + route } };
|
|
21
|
-
const gateway = attachLiveGateway(server, runtime);
|
|
22
|
-
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
|
|
23
|
-
const base = `http://127.0.0.1:${server.address().port}`, clients = [];
|
|
24
|
-
try {
|
|
25
|
-
for (let i = 0; i < 8; i++) {
|
|
26
|
-
const ws = new WebSocket(base.replace('http:', 'ws:') + '/api/live', { origin: base }); clients.push(ws);
|
|
27
|
-
await once(ws, 'open');
|
|
28
|
-
const messages = []; ws.on('message', b => messages.push(JSON.parse(String(b))));
|
|
29
|
-
ws.send(JSON.stringify({ type: 'subscribe', id: 'engine', route: '/api/engine/progress?summary=1' }));
|
|
30
|
-
for (let n = 0; n < 100 && !messages.some(m => m.type === 'event'); n++) await wait(5);
|
|
31
|
-
const event = messages.find(m => m.type === 'event'); assert.equal(event.event, 'snapshot'); assert.equal(event.cursor, '17'); assert.deepEqual(JSON.parse(event.data), { ok: true });
|
|
32
|
-
ws.send(JSON.stringify({ type: 'subscribe', id: 'invalid', route: 'http://attacker.invalid/private' }));
|
|
33
|
-
for (let n = 0; n < 100 && !messages.some(m => m.id === 'invalid'); n++) await wait(5);
|
|
34
|
-
assert.equal(messages.find(m => m.id === 'invalid').code, 'INVALID_SUBSCRIPTION');
|
|
35
|
-
}
|
|
36
|
-
assert.equal(active, 8); assert.equal(total, 8, 'invalid URLs never fetch an upstream');
|
|
37
|
-
const last = clients.at(-1);
|
|
38
|
-
last.send(JSON.stringify({ type: 'unsubscribe', id: 'engine' }));
|
|
39
|
-
for (let n = 0; n < 100 && active !== 7; n++) await wait(5);
|
|
40
|
-
assert.equal(active, 7, 'unsubscribing releases the upstream');
|
|
41
|
-
const rejected = new WebSocket(base.replace('http:', 'ws:') + '/api/live', { origin: 'http://evil.invalid' });
|
|
42
|
-
await new Promise(resolve => { rejected.on('error', resolve); rejected.on('open', () => { throw new Error('cross-origin upgrade was accepted'); }); });
|
|
43
|
-
gateway.close();
|
|
44
|
-
for (let n = 0; n < 100 && active; n++) await wait(5);
|
|
45
|
-
assert.equal(active, 0);
|
|
46
|
-
console.log('live-gateway-test PASS (8 real sockets, CRLF frames, bounded allowlist, unsubscribe and shutdown release)');
|
|
47
|
-
} finally { for (const ws of clients) ws.terminate(); gateway.close(); upstream.closeAllConnections(); await Promise.all([new Promise(r => server.close(r)), new Promise(r => upstream.close(r))]); }
|
|
48
|
-
})().catch(error => { console.error(error); process.exitCode = 1; });
|
|
1
|
+
'use strict';
|
|
2
|
+
const assert = require('node:assert/strict');
|
|
3
|
+
const http = require('node:http');
|
|
4
|
+
const { once } = require('node:events');
|
|
5
|
+
const { WebSocket } = require('ws');
|
|
6
|
+
const { attachLiveGateway } = require('../lib/live-gateway');
|
|
7
|
+
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
8
|
+
(async () => {
|
|
9
|
+
let active = 0, total = 0;
|
|
10
|
+
const upstream = http.createServer((req, res) => {
|
|
11
|
+
active++; total++;
|
|
12
|
+
res.writeHead(200, { 'Content-Type': 'text/event-stream' });
|
|
13
|
+
res.write('id: 17\r\nevent: snapshot\r\ndata: {"ok":true}\r');
|
|
14
|
+
setTimeout(() => { if (!res.destroyed) res.write('\n\r\n'); }, 5);
|
|
15
|
+
req.on('close', () => { active--; });
|
|
16
|
+
});
|
|
17
|
+
await new Promise(resolve => upstream.listen(0, '127.0.0.1', resolve));
|
|
18
|
+
const origin = `http://127.0.0.1:${upstream.address().port}`;
|
|
19
|
+
const server = http.createServer();
|
|
20
|
+
const runtime = { moduleBridge: { engineUrl: origin, engineCompatible: true, _terminalApi: route => origin + route } };
|
|
21
|
+
const gateway = attachLiveGateway(server, runtime);
|
|
22
|
+
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
|
|
23
|
+
const base = `http://127.0.0.1:${server.address().port}`, clients = [];
|
|
24
|
+
try {
|
|
25
|
+
for (let i = 0; i < 8; i++) {
|
|
26
|
+
const ws = new WebSocket(base.replace('http:', 'ws:') + '/api/live', { origin: base }); clients.push(ws);
|
|
27
|
+
await once(ws, 'open');
|
|
28
|
+
const messages = []; ws.on('message', b => messages.push(JSON.parse(String(b))));
|
|
29
|
+
ws.send(JSON.stringify({ type: 'subscribe', id: 'engine', route: '/api/engine/progress?summary=1' }));
|
|
30
|
+
for (let n = 0; n < 100 && !messages.some(m => m.type === 'event'); n++) await wait(5);
|
|
31
|
+
const event = messages.find(m => m.type === 'event'); assert.equal(event.event, 'snapshot'); assert.equal(event.cursor, '17'); assert.deepEqual(JSON.parse(event.data), { ok: true });
|
|
32
|
+
ws.send(JSON.stringify({ type: 'subscribe', id: 'invalid', route: 'http://attacker.invalid/private' }));
|
|
33
|
+
for (let n = 0; n < 100 && !messages.some(m => m.id === 'invalid'); n++) await wait(5);
|
|
34
|
+
assert.equal(messages.find(m => m.id === 'invalid').code, 'INVALID_SUBSCRIPTION');
|
|
35
|
+
}
|
|
36
|
+
assert.equal(active, 8); assert.equal(total, 8, 'invalid URLs never fetch an upstream');
|
|
37
|
+
const last = clients.at(-1);
|
|
38
|
+
last.send(JSON.stringify({ type: 'unsubscribe', id: 'engine' }));
|
|
39
|
+
for (let n = 0; n < 100 && active !== 7; n++) await wait(5);
|
|
40
|
+
assert.equal(active, 7, 'unsubscribing releases the upstream');
|
|
41
|
+
const rejected = new WebSocket(base.replace('http:', 'ws:') + '/api/live', { origin: 'http://evil.invalid' });
|
|
42
|
+
await new Promise(resolve => { rejected.on('error', resolve); rejected.on('open', () => { throw new Error('cross-origin upgrade was accepted'); }); });
|
|
43
|
+
gateway.close();
|
|
44
|
+
for (let n = 0; n < 100 && active; n++) await wait(5);
|
|
45
|
+
assert.equal(active, 0);
|
|
46
|
+
console.log('live-gateway-test PASS (8 real sockets, CRLF frames, bounded allowlist, unsubscribe and shutdown release)');
|
|
47
|
+
} finally { for (const ws of clients) ws.terminate(); gateway.close(); upstream.closeAllConnections(); await Promise.all([new Promise(r => server.close(r)), new Promise(r => upstream.close(r))]); }
|
|
48
|
+
})().catch(error => { console.error(error); process.exitCode = 1; });
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const assert = require('node:assert/strict');
|
|
3
|
-
const path = require('node:path');
|
|
4
|
-
const { IntegrationManager } = require('../lib/integration-installer');
|
|
5
|
-
const commands = [];
|
|
6
|
-
const root = path.resolve(__dirname, '../..');
|
|
7
|
-
const manager = new IntegrationManager({ rootDir: root, commandResolver: name => name, runner: (cmd, args) => {
|
|
8
|
-
commands.push(args);
|
|
9
|
-
return { status: 0, stdout: '[]', stderr: '' };
|
|
10
|
-
} });
|
|
11
|
-
manager.ensureClaudeMarketplace();
|
|
12
|
-
assert.equal(commands.find(args => args.slice(0, 3).join(' ') === 'plugin marketplace add')[3], root, 'Claude installs from the downloaded npm package, not GitHub');
|
|
13
|
-
const custom = new IntegrationManager({ marketplaceSource: 'https://example.invalid/explicit.git', commandResolver: name => name, runner: (cmd, args) => ({ status: 0, stdout: '[]' }), dryRun: true });
|
|
14
|
-
custom.ensureClaudeMarketplace();
|
|
15
|
-
assert.equal(custom.planned[0].args[3], 'https://example.invalid/explicit.git');
|
|
16
|
-
console.log('Local marketplace and explicit-source override passed.');
|
|
1
|
+
'use strict';
|
|
2
|
+
const assert = require('node:assert/strict');
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const { IntegrationManager } = require('../lib/integration-installer');
|
|
5
|
+
const commands = [];
|
|
6
|
+
const root = path.resolve(__dirname, '../..');
|
|
7
|
+
const manager = new IntegrationManager({ rootDir: root, commandResolver: name => name, runner: (cmd, args) => {
|
|
8
|
+
commands.push(args);
|
|
9
|
+
return { status: 0, stdout: '[]', stderr: '' };
|
|
10
|
+
} });
|
|
11
|
+
manager.ensureClaudeMarketplace();
|
|
12
|
+
assert.equal(commands.find(args => args.slice(0, 3).join(' ') === 'plugin marketplace add')[3], root, 'Claude installs from the downloaded npm package, not GitHub');
|
|
13
|
+
const custom = new IntegrationManager({ marketplaceSource: 'https://example.invalid/explicit.git', commandResolver: name => name, runner: (cmd, args) => ({ status: 0, stdout: '[]' }), dryRun: true });
|
|
14
|
+
custom.ensureClaudeMarketplace();
|
|
15
|
+
assert.equal(custom.planned[0].args[3], 'https://example.invalid/explicit.git');
|
|
16
|
+
console.log('Local marketplace and explicit-source override passed.');
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
const assert = require('assert');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const os = require('os');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { StorageLayout } = require('../lib/storage-layout');
|
|
6
|
-
const { Logger, LogRepository, redactValue, serializeError } = require('../lib/structured-logger');
|
|
7
|
-
|
|
8
|
-
(async () => {
|
|
9
|
-
const secret = 'sk-secret-123456';
|
|
10
|
-
const value = redactValue({
|
|
11
|
-
apiKey: secret,
|
|
12
|
-
headers: { authorization: 'Bearer ' + secret },
|
|
13
|
-
url: 'https://user:' + secret + '@example.invalid/path?token=' + secret,
|
|
14
|
-
nested: [{ clientSecret: secret }, { safe: 'visible' }],
|
|
15
|
-
}, { secrets: [secret] });
|
|
16
|
-
const text = JSON.stringify(value);
|
|
17
|
-
assert(!text.includes(secret));
|
|
18
|
-
assert(text.includes('visible'));
|
|
19
|
-
|
|
20
|
-
const cause = Object.assign(new Error('cause ' + secret), { code: 'ECAUSE' });
|
|
21
|
-
const error = Object.assign(new Error('Bearer ' + secret), { code: 'ETEST', cause });
|
|
22
|
-
const serialized = JSON.stringify(serializeError(error, { secrets: [secret] }));
|
|
23
|
-
assert(!serialized.includes(secret));
|
|
24
|
-
assert(serialized.includes('ETEST'));
|
|
25
|
-
assert(serialized.includes('ECAUSE'));
|
|
26
|
-
|
|
27
|
-
const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pk-dynamic-redaction-'));
|
|
28
|
-
try {
|
|
29
|
-
const layout = new StorageLayout({ dataDir });
|
|
30
|
-
let currentSecret = 'dynamic-secret-one';
|
|
31
|
-
const settings = { levels: ['info', 'error'], retentionDays: 365, maxTotalSizeMB: 10 };
|
|
32
|
-
const secretsProvider = () => [currentSecret];
|
|
33
|
-
const logger = new Logger({ layout, settingsProvider: () => settings, secretsProvider });
|
|
34
|
-
await logger.info('secret.first', 'first ' + currentSecret, { context: { echoed: currentSecret } });
|
|
35
|
-
currentSecret = 'dynamic-secret-two';
|
|
36
|
-
await logger.error('secret.second', 'second ' + currentSecret, { error: new Error('failure ' + currentSecret) });
|
|
37
|
-
await logger.close();
|
|
38
|
-
|
|
39
|
-
const repository = new LogRepository({ layout, settingsProvider: () => settings, secretsProvider });
|
|
40
|
-
const page = repository.query({ from: '2000-01-01', to: '2999-12-31' });
|
|
41
|
-
const queried = JSON.stringify(page);
|
|
42
|
-
assert(!queried.includes(currentSecret), 'current configured secret must be redacted during query');
|
|
43
|
-
assert(!queried.includes('dynamic-secret-one'), 'write-time configured secret must be redacted before persistence');
|
|
44
|
-
|
|
45
|
-
const exportPath = path.join(dataDir, 'export.jsonl');
|
|
46
|
-
repository.exportToFile(exportPath, { from: '2000-01-01', to: '2999-12-31' });
|
|
47
|
-
const exported = fs.readFileSync(exportPath, 'utf8');
|
|
48
|
-
assert(!exported.includes('dynamic-secret-one'));
|
|
49
|
-
assert(!exported.includes('dynamic-secret-two'));
|
|
50
|
-
} finally {
|
|
51
|
-
fs.rmSync(dataDir, { recursive: true, force: true });
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
console.log('log-redaction-test PASS');
|
|
55
|
-
})().catch(error => {
|
|
56
|
-
console.error(error.stack || error.message);
|
|
57
|
-
process.exitCode = 1;
|
|
58
|
-
});
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { StorageLayout } = require('../lib/storage-layout');
|
|
6
|
+
const { Logger, LogRepository, redactValue, serializeError } = require('../lib/structured-logger');
|
|
7
|
+
|
|
8
|
+
(async () => {
|
|
9
|
+
const secret = 'sk-secret-123456';
|
|
10
|
+
const value = redactValue({
|
|
11
|
+
apiKey: secret,
|
|
12
|
+
headers: { authorization: 'Bearer ' + secret },
|
|
13
|
+
url: 'https://user:' + secret + '@example.invalid/path?token=' + secret,
|
|
14
|
+
nested: [{ clientSecret: secret }, { safe: 'visible' }],
|
|
15
|
+
}, { secrets: [secret] });
|
|
16
|
+
const text = JSON.stringify(value);
|
|
17
|
+
assert(!text.includes(secret));
|
|
18
|
+
assert(text.includes('visible'));
|
|
19
|
+
|
|
20
|
+
const cause = Object.assign(new Error('cause ' + secret), { code: 'ECAUSE' });
|
|
21
|
+
const error = Object.assign(new Error('Bearer ' + secret), { code: 'ETEST', cause });
|
|
22
|
+
const serialized = JSON.stringify(serializeError(error, { secrets: [secret] }));
|
|
23
|
+
assert(!serialized.includes(secret));
|
|
24
|
+
assert(serialized.includes('ETEST'));
|
|
25
|
+
assert(serialized.includes('ECAUSE'));
|
|
26
|
+
|
|
27
|
+
const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pk-dynamic-redaction-'));
|
|
28
|
+
try {
|
|
29
|
+
const layout = new StorageLayout({ dataDir });
|
|
30
|
+
let currentSecret = 'dynamic-secret-one';
|
|
31
|
+
const settings = { levels: ['info', 'error'], retentionDays: 365, maxTotalSizeMB: 10 };
|
|
32
|
+
const secretsProvider = () => [currentSecret];
|
|
33
|
+
const logger = new Logger({ layout, settingsProvider: () => settings, secretsProvider });
|
|
34
|
+
await logger.info('secret.first', 'first ' + currentSecret, { context: { echoed: currentSecret } });
|
|
35
|
+
currentSecret = 'dynamic-secret-two';
|
|
36
|
+
await logger.error('secret.second', 'second ' + currentSecret, { error: new Error('failure ' + currentSecret) });
|
|
37
|
+
await logger.close();
|
|
38
|
+
|
|
39
|
+
const repository = new LogRepository({ layout, settingsProvider: () => settings, secretsProvider });
|
|
40
|
+
const page = repository.query({ from: '2000-01-01', to: '2999-12-31' });
|
|
41
|
+
const queried = JSON.stringify(page);
|
|
42
|
+
assert(!queried.includes(currentSecret), 'current configured secret must be redacted during query');
|
|
43
|
+
assert(!queried.includes('dynamic-secret-one'), 'write-time configured secret must be redacted before persistence');
|
|
44
|
+
|
|
45
|
+
const exportPath = path.join(dataDir, 'export.jsonl');
|
|
46
|
+
repository.exportToFile(exportPath, { from: '2000-01-01', to: '2999-12-31' });
|
|
47
|
+
const exported = fs.readFileSync(exportPath, 'utf8');
|
|
48
|
+
assert(!exported.includes('dynamic-secret-one'));
|
|
49
|
+
assert(!exported.includes('dynamic-secret-two'));
|
|
50
|
+
} finally {
|
|
51
|
+
fs.rmSync(dataDir, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
console.log('log-redaction-test PASS');
|
|
55
|
+
})().catch(error => {
|
|
56
|
+
console.error(error.stack || error.message);
|
|
57
|
+
process.exitCode = 1;
|
|
58
|
+
});
|