@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,158 +1,158 @@
|
|
|
1
|
-
const http = require('http');
|
|
2
|
-
const crypto = require('crypto');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { execFileSync } = require('child_process');
|
|
6
|
-
const { getDataDir } = require('../lib/data-dir');
|
|
7
|
-
const { readLiveEndpoint } = require('../lib/runtime-endpoint');
|
|
8
|
-
const { StorageLayout } = require('../lib/storage-layout');
|
|
9
|
-
const { Logger } = require('../lib/structured-logger');
|
|
10
|
-
const { BridgeAdapter } = require('../lib/bridge-adapter');
|
|
11
|
-
const { resolveGitPath } = require('../lib/git-path');
|
|
12
|
-
|
|
13
|
-
let bridgeIdentityModule = null;
|
|
14
|
-
try {
|
|
15
|
-
const bridgePackage = require('@sanqianx/ai-coding-event-bridge-console/src/bridge');
|
|
16
|
-
if (bridgePackage && typeof bridgePackage.buildRepoIdentityV1 === 'function') bridgeIdentityModule = bridgePackage;
|
|
17
|
-
} catch (_) {
|
|
18
|
-
bridgeIdentityModule = null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const args = process.argv.slice(2);
|
|
22
|
-
function arg(name, fallback = '') {
|
|
23
|
-
const index = args.indexOf(name);
|
|
24
|
-
return index >= 0 ? (args[index + 1] || fallback) : fallback;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const projectId = arg('--project-id', '');
|
|
28
|
-
const repoRoot = arg('--repo-root', arg('--repo', ''));
|
|
29
|
-
const fallbackHost = arg('--host', '127.0.0.1');
|
|
30
|
-
const fallbackPort = Number(arg('--port', process.env.KB_SITE_PORT || '5757'));
|
|
31
|
-
const dataDir = path.resolve(arg('--data-dir', getDataDir()));
|
|
32
|
-
const layout = new StorageLayout({ dataDir });
|
|
33
|
-
const logger = new Logger({
|
|
34
|
-
layout,
|
|
35
|
-
settingsProvider: () => ({ levels: ['trace', 'debug', 'info', 'warn', 'error', 'fatal'] }),
|
|
36
|
-
context: { component: 'git-hook', projectId },
|
|
37
|
-
});
|
|
38
|
-
const bridge = new BridgeAdapter({ dataDir, modulePath: arg('--bridge-module', ''), bridgeHomeDir: arg('--bridge-home', '') });
|
|
39
|
-
if (bridge.module && typeof bridge.module.buildRepoIdentityV1 === 'function') bridgeIdentityModule = bridge.module;
|
|
40
|
-
const timeoutMs = 2000;
|
|
41
|
-
|
|
42
|
-
function git(gitArgs, fallback = '') {
|
|
43
|
-
if (!repoRoot) return fallback;
|
|
44
|
-
try {
|
|
45
|
-
return execFileSync('git', ['-C', repoRoot, ...gitArgs], {
|
|
46
|
-
encoding: 'utf8', windowsHide: true, timeout: timeoutMs,
|
|
47
|
-
stdio: ['ignore', 'pipe', 'ignore'], env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
48
|
-
}).trim();
|
|
49
|
-
} catch { return fallback; }
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function target() {
|
|
53
|
-
const endpoint = readLiveEndpoint(dataDir);
|
|
54
|
-
return endpoint ? { host: endpoint.host, port: endpoint.port } : { host: fallbackHost, port: fallbackPort };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function post(body) {
|
|
58
|
-
return new Promise((resolve, reject) => {
|
|
59
|
-
const payload = JSON.stringify(body);
|
|
60
|
-
const endpoint = target();
|
|
61
|
-
const request = http.request({
|
|
62
|
-
host: endpoint.host,
|
|
63
|
-
port: endpoint.port,
|
|
64
|
-
method: 'POST',
|
|
65
|
-
path: '/api/hooks/post-commit',
|
|
66
|
-
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) },
|
|
67
|
-
timeout: timeoutMs,
|
|
68
|
-
}, response => {
|
|
69
|
-
response.resume();
|
|
70
|
-
response.on('end', () => resolve(response.statusCode || 0));
|
|
71
|
-
});
|
|
72
|
-
request.on('error', reject);
|
|
73
|
-
request.on('timeout', () => request.destroy(new Error('hook notification timeout')));
|
|
74
|
-
request.end(payload);
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
(async () => {
|
|
79
|
-
try {
|
|
80
|
-
if (!projectId || !repoRoot) {
|
|
81
|
-
await logger.warn('hook.notification.skipped', 'Hook payload is missing project identity or repository root.', { phase: 'validate' });
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const payload = {
|
|
85
|
-
schema: 'hook-event/v2',
|
|
86
|
-
projectId,
|
|
87
|
-
repoRoot,
|
|
88
|
-
head: git(['rev-parse', 'HEAD']),
|
|
89
|
-
branch: git(['branch', '--show-current']),
|
|
90
|
-
};
|
|
91
|
-
const operationId = arg('--operation-id', `op-${crypto.randomUUID()}`);
|
|
92
|
-
// Canonical repo-identity/v1 from the authoritative Git working tree.
|
|
93
|
-
// The old { commonDir }-only shape must never reach the Bridge again.
|
|
94
|
-
let repoIdentity = null;
|
|
95
|
-
if (bridgeIdentityModule) {
|
|
96
|
-
const toplevel = git(['rev-parse', '--show-toplevel']);
|
|
97
|
-
if (toplevel) {
|
|
98
|
-
let workspaceRoot = path.resolve(toplevel);
|
|
99
|
-
try { workspaceRoot = fs.realpathSync.native(workspaceRoot) || workspaceRoot; } catch { workspaceRoot = path.resolve(toplevel); }
|
|
100
|
-
const commonDir = git(['rev-parse', '--git-common-dir']);
|
|
101
|
-
const remoteRaw = git(['config', '--get', 'remote.origin.url']);
|
|
102
|
-
repoIdentity = bridgeIdentityModule.buildRepoIdentityV1({
|
|
103
|
-
workspaceRoot,
|
|
104
|
-
commonDir: commonDir ? resolveGitPath(repoRoot, commonDir) : null,
|
|
105
|
-
remote: remoteRaw ? bridgeIdentityModule.normalizeGitUrl(remoteRaw) : null,
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
const boundaryResult = await bridge.appendCommitBoundary({
|
|
110
|
-
projectId,
|
|
111
|
-
repoIdentity,
|
|
112
|
-
commitSha: payload.head,
|
|
113
|
-
parentShas: git(['show', '-s', '--format=%P', 'HEAD']).split(/\s+/).filter(Boolean),
|
|
114
|
-
branch: payload.branch || null,
|
|
115
|
-
committedAt: git(['show', '-s', '--format=%cI', 'HEAD']) || new Date().toISOString(),
|
|
116
|
-
operationId,
|
|
117
|
-
});
|
|
118
|
-
payload.operationId = operationId;
|
|
119
|
-
payload.boundary = boundaryResult;
|
|
120
|
-
if (boundaryResult.status === 'captured') {
|
|
121
|
-
await logger.debug('hook.boundary.captured', 'Commit conversation boundary was durably captured.', {
|
|
122
|
-
operationId,
|
|
123
|
-
phase: 'boundary',
|
|
124
|
-
commitSha: payload.head,
|
|
125
|
-
context: {
|
|
126
|
-
bridgeCursorAtCommit: boundaryResult.boundary.bridgeCursorAtCommit,
|
|
127
|
-
openTurnCount: boundaryResult.boundary.openTurnIdsAtCommit.length,
|
|
128
|
-
},
|
|
129
|
-
});
|
|
130
|
-
} else {
|
|
131
|
-
await logger.warn('hook.boundary.unavailable', 'Commit conversation boundary could not be captured.', {
|
|
132
|
-
operationId,
|
|
133
|
-
phase: 'boundary',
|
|
134
|
-
commitSha: payload.head,
|
|
135
|
-
context: { gapId: boundaryResult.gap && boundaryResult.gap.gapId, reason: boundaryResult.gap && boundaryResult.gap.reason },
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
try {
|
|
139
|
-
const status = await post(payload);
|
|
140
|
-
if (status < 200 || status >= 300) {
|
|
141
|
-
await logger.warn('hook.notification.failed', 'Knowledge service rejected the Hook notification.', { phase: 'notify', context: { status } });
|
|
142
|
-
} else {
|
|
143
|
-
await logger.debug('hook.notification.completed', 'Hook notification delivered.', { phase: 'notify' });
|
|
144
|
-
}
|
|
145
|
-
} catch (error) {
|
|
146
|
-
await logger.warn('hook.notification.degraded', 'Knowledge service is unavailable; this commit was not submitted for knowledge analysis.', { phase: 'notify', error });
|
|
147
|
-
}
|
|
148
|
-
} catch (error) {
|
|
149
|
-
await logger.error('hook.script.failed', 'Hook trigger failed.', { phase: 'runtime', error });
|
|
150
|
-
} finally {
|
|
151
|
-
await logger.close();
|
|
152
|
-
}
|
|
153
|
-
})().then(() => process.exit(0), async error => {
|
|
154
|
-
try { await logger.error('hook.script.failed', 'Hook trigger failed unexpectedly.', { error }); await logger.close(); } catch {
|
|
155
|
-
// Hook execution must always exit zero even when logging is unavailable.
|
|
156
|
-
}
|
|
157
|
-
process.exit(0);
|
|
158
|
-
});
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { execFileSync } = require('child_process');
|
|
6
|
+
const { getDataDir } = require('../lib/data-dir');
|
|
7
|
+
const { readLiveEndpoint } = require('../lib/runtime-endpoint');
|
|
8
|
+
const { StorageLayout } = require('../lib/storage-layout');
|
|
9
|
+
const { Logger } = require('../lib/structured-logger');
|
|
10
|
+
const { BridgeAdapter } = require('../lib/bridge-adapter');
|
|
11
|
+
const { resolveGitPath } = require('../lib/git-path');
|
|
12
|
+
|
|
13
|
+
let bridgeIdentityModule = null;
|
|
14
|
+
try {
|
|
15
|
+
const bridgePackage = require('@sanqianx/ai-coding-event-bridge-console/src/bridge');
|
|
16
|
+
if (bridgePackage && typeof bridgePackage.buildRepoIdentityV1 === 'function') bridgeIdentityModule = bridgePackage;
|
|
17
|
+
} catch (_) {
|
|
18
|
+
bridgeIdentityModule = null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const args = process.argv.slice(2);
|
|
22
|
+
function arg(name, fallback = '') {
|
|
23
|
+
const index = args.indexOf(name);
|
|
24
|
+
return index >= 0 ? (args[index + 1] || fallback) : fallback;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const projectId = arg('--project-id', '');
|
|
28
|
+
const repoRoot = arg('--repo-root', arg('--repo', ''));
|
|
29
|
+
const fallbackHost = arg('--host', '127.0.0.1');
|
|
30
|
+
const fallbackPort = Number(arg('--port', process.env.KB_SITE_PORT || '5757'));
|
|
31
|
+
const dataDir = path.resolve(arg('--data-dir', getDataDir()));
|
|
32
|
+
const layout = new StorageLayout({ dataDir });
|
|
33
|
+
const logger = new Logger({
|
|
34
|
+
layout,
|
|
35
|
+
settingsProvider: () => ({ levels: ['trace', 'debug', 'info', 'warn', 'error', 'fatal'] }),
|
|
36
|
+
context: { component: 'git-hook', projectId },
|
|
37
|
+
});
|
|
38
|
+
const bridge = new BridgeAdapter({ dataDir, modulePath: arg('--bridge-module', ''), bridgeHomeDir: arg('--bridge-home', '') });
|
|
39
|
+
if (bridge.module && typeof bridge.module.buildRepoIdentityV1 === 'function') bridgeIdentityModule = bridge.module;
|
|
40
|
+
const timeoutMs = 2000;
|
|
41
|
+
|
|
42
|
+
function git(gitArgs, fallback = '') {
|
|
43
|
+
if (!repoRoot) return fallback;
|
|
44
|
+
try {
|
|
45
|
+
return execFileSync('git', ['-C', repoRoot, ...gitArgs], {
|
|
46
|
+
encoding: 'utf8', windowsHide: true, timeout: timeoutMs,
|
|
47
|
+
stdio: ['ignore', 'pipe', 'ignore'], env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
48
|
+
}).trim();
|
|
49
|
+
} catch { return fallback; }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function target() {
|
|
53
|
+
const endpoint = readLiveEndpoint(dataDir);
|
|
54
|
+
return endpoint ? { host: endpoint.host, port: endpoint.port } : { host: fallbackHost, port: fallbackPort };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function post(body) {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
const payload = JSON.stringify(body);
|
|
60
|
+
const endpoint = target();
|
|
61
|
+
const request = http.request({
|
|
62
|
+
host: endpoint.host,
|
|
63
|
+
port: endpoint.port,
|
|
64
|
+
method: 'POST',
|
|
65
|
+
path: '/api/hooks/post-commit',
|
|
66
|
+
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) },
|
|
67
|
+
timeout: timeoutMs,
|
|
68
|
+
}, response => {
|
|
69
|
+
response.resume();
|
|
70
|
+
response.on('end', () => resolve(response.statusCode || 0));
|
|
71
|
+
});
|
|
72
|
+
request.on('error', reject);
|
|
73
|
+
request.on('timeout', () => request.destroy(new Error('hook notification timeout')));
|
|
74
|
+
request.end(payload);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
(async () => {
|
|
79
|
+
try {
|
|
80
|
+
if (!projectId || !repoRoot) {
|
|
81
|
+
await logger.warn('hook.notification.skipped', 'Hook payload is missing project identity or repository root.', { phase: 'validate' });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const payload = {
|
|
85
|
+
schema: 'hook-event/v2',
|
|
86
|
+
projectId,
|
|
87
|
+
repoRoot,
|
|
88
|
+
head: git(['rev-parse', 'HEAD']),
|
|
89
|
+
branch: git(['branch', '--show-current']),
|
|
90
|
+
};
|
|
91
|
+
const operationId = arg('--operation-id', `op-${crypto.randomUUID()}`);
|
|
92
|
+
// Canonical repo-identity/v1 from the authoritative Git working tree.
|
|
93
|
+
// The old { commonDir }-only shape must never reach the Bridge again.
|
|
94
|
+
let repoIdentity = null;
|
|
95
|
+
if (bridgeIdentityModule) {
|
|
96
|
+
const toplevel = git(['rev-parse', '--show-toplevel']);
|
|
97
|
+
if (toplevel) {
|
|
98
|
+
let workspaceRoot = path.resolve(toplevel);
|
|
99
|
+
try { workspaceRoot = fs.realpathSync.native(workspaceRoot) || workspaceRoot; } catch { workspaceRoot = path.resolve(toplevel); }
|
|
100
|
+
const commonDir = git(['rev-parse', '--git-common-dir']);
|
|
101
|
+
const remoteRaw = git(['config', '--get', 'remote.origin.url']);
|
|
102
|
+
repoIdentity = bridgeIdentityModule.buildRepoIdentityV1({
|
|
103
|
+
workspaceRoot,
|
|
104
|
+
commonDir: commonDir ? resolveGitPath(repoRoot, commonDir) : null,
|
|
105
|
+
remote: remoteRaw ? bridgeIdentityModule.normalizeGitUrl(remoteRaw) : null,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const boundaryResult = await bridge.appendCommitBoundary({
|
|
110
|
+
projectId,
|
|
111
|
+
repoIdentity,
|
|
112
|
+
commitSha: payload.head,
|
|
113
|
+
parentShas: git(['show', '-s', '--format=%P', 'HEAD']).split(/\s+/).filter(Boolean),
|
|
114
|
+
branch: payload.branch || null,
|
|
115
|
+
committedAt: git(['show', '-s', '--format=%cI', 'HEAD']) || new Date().toISOString(),
|
|
116
|
+
operationId,
|
|
117
|
+
});
|
|
118
|
+
payload.operationId = operationId;
|
|
119
|
+
payload.boundary = boundaryResult;
|
|
120
|
+
if (boundaryResult.status === 'captured') {
|
|
121
|
+
await logger.debug('hook.boundary.captured', 'Commit conversation boundary was durably captured.', {
|
|
122
|
+
operationId,
|
|
123
|
+
phase: 'boundary',
|
|
124
|
+
commitSha: payload.head,
|
|
125
|
+
context: {
|
|
126
|
+
bridgeCursorAtCommit: boundaryResult.boundary.bridgeCursorAtCommit,
|
|
127
|
+
openTurnCount: boundaryResult.boundary.openTurnIdsAtCommit.length,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
} else {
|
|
131
|
+
await logger.warn('hook.boundary.unavailable', 'Commit conversation boundary could not be captured.', {
|
|
132
|
+
operationId,
|
|
133
|
+
phase: 'boundary',
|
|
134
|
+
commitSha: payload.head,
|
|
135
|
+
context: { gapId: boundaryResult.gap && boundaryResult.gap.gapId, reason: boundaryResult.gap && boundaryResult.gap.reason },
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const status = await post(payload);
|
|
140
|
+
if (status < 200 || status >= 300) {
|
|
141
|
+
await logger.warn('hook.notification.failed', 'Knowledge service rejected the Hook notification.', { phase: 'notify', context: { status } });
|
|
142
|
+
} else {
|
|
143
|
+
await logger.debug('hook.notification.completed', 'Hook notification delivered.', { phase: 'notify' });
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
await logger.warn('hook.notification.degraded', 'Knowledge service is unavailable; this commit was not submitted for knowledge analysis.', { phase: 'notify', error });
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
await logger.error('hook.script.failed', 'Hook trigger failed.', { phase: 'runtime', error });
|
|
150
|
+
} finally {
|
|
151
|
+
await logger.close();
|
|
152
|
+
}
|
|
153
|
+
})().then(() => process.exit(0), async error => {
|
|
154
|
+
try { await logger.error('hook.script.failed', 'Hook trigger failed unexpectedly.', { error }); await logger.close(); } catch {
|
|
155
|
+
// Hook execution must always exit zero even when logging is unavailable.
|
|
156
|
+
}
|
|
157
|
+
process.exit(0);
|
|
158
|
+
});
|
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
const fs = require('node:fs');
|
|
3
|
-
const os = require('node:os');
|
|
4
|
-
const path = require('node:path');
|
|
5
|
-
const crypto = require('node:crypto');
|
|
6
|
-
const { createRequire } = require('node:module');
|
|
7
|
-
const { spawnSync } = require('node:child_process');
|
|
8
|
-
const AtomicFile = require('../lib/atomic-file');
|
|
9
|
-
const { verifyInstalled, safeRelative } = require('./pack-module-candidates');
|
|
10
|
-
const root = path.resolve(__dirname, '../..');
|
|
11
|
-
const npmCli = process.env.npm_execpath || path.join(path.dirname(process.execPath), 'node_modules/npm/bin/npm-cli.js');
|
|
12
|
-
function run(args, cwd) {
|
|
13
|
-
const result = spawnSync(process.execPath, [npmCli, ...args], { cwd, windowsHide: true, encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
|
|
14
|
-
if (result.status !== 0) throw new Error(`npm ${args[0]} failed (${result.status})`);
|
|
15
|
-
return result.stdout;
|
|
16
|
-
}
|
|
17
|
-
function contentAddressedArtifact(packedCore) {
|
|
18
|
-
const sha256 = crypto.createHash('sha256').update(fs.readFileSync(packedCore)).digest('hex');
|
|
19
|
-
const file = packedCore.replace(/\.tgz$/, `-${sha256}.tgz`);
|
|
20
|
-
if (file === packedCore) throw new Error('Candidate must be a tarball');
|
|
21
|
-
fs.copyFileSync(packedCore, file);
|
|
22
|
-
return { file, sha256 };
|
|
23
|
-
}
|
|
24
|
-
function main() {
|
|
25
|
-
const manifestFile = path.resolve(process.argv[2]);
|
|
26
|
-
const manifest = JSON.parse(fs.readFileSync(manifestFile));
|
|
27
|
-
if (manifest.schema !== 'project-knowledge/module-candidates/v1') throw new Error('Invalid candidate manifest');
|
|
28
|
-
const artifactRoot = path.dirname(manifestFile);
|
|
29
|
-
const dependencies = {};
|
|
30
|
-
for (const module of Object.values(manifest.modules)) {
|
|
31
|
-
if (!safeRelative(module.tarball) || !module.tarball.endsWith('.tgz')) throw new Error('Unsafe artifact path');
|
|
32
|
-
const file = path.join(artifactRoot, module.tarball);
|
|
33
|
-
if (fs.lstatSync(file).isSymbolicLink() || crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex') !== module.sha256) throw new Error('Module artifact drift');
|
|
34
|
-
dependencies[module.installName] = `file:${file}`;
|
|
35
|
-
}
|
|
36
|
-
const candidate = JSON.parse(run(['pack', '--ignore-scripts', '--json', '--pack-destination', artifactRoot], root))[0];
|
|
37
|
-
const packedCore = path.join(artifactRoot, candidate.filename);
|
|
38
|
-
// Same-version local tarballs are cached by npm. Address each candidate by
|
|
39
|
-
// content so an update cannot silently keep an older runtime or UI.
|
|
40
|
-
const { sha256: shellSha256, file: shellArtifact } = contentAddressedArtifact(packedCore);
|
|
41
|
-
dependencies['@sanqianx/project-knowledge'] = `file:${shellArtifact}`;
|
|
42
|
-
const updateAt = process.argv.indexOf('--update');
|
|
43
|
-
const installedRoot = updateAt < 0 ? fs.mkdtempSync(path.join(os.tmpdir(), 'kb-installed-product-')) : path.resolve(process.argv[updateAt + 1]);
|
|
44
|
-
if (path.dirname(installedRoot) !== path.resolve(os.tmpdir()) || !path.basename(installedRoot).startsWith('kb-installed-product-') || fs.lstatSync(installedRoot).isSymbolicLink()) throw new Error('Only this task’s isolated installation can be updated');
|
|
45
|
-
if (updateAt >= 0 && JSON.parse(fs.readFileSync(path.join(installedRoot, 'installation-acceptance.json'))).installedRoot !== installedRoot) throw new Error('Installed fixture identity mismatch');
|
|
46
|
-
AtomicFile.writeJsonAtomic(path.join(installedRoot, 'package.json'), { name: 'kb-local-acceptance', version: '0.0.0', private: true, dependencies });
|
|
47
|
-
process.stdout.write(`Installing isolated product at ${installedRoot}\n`);
|
|
48
|
-
run(['install', '--omit=dev', '--ignore-scripts', '--no-audit', '--no-fund'], installedRoot);
|
|
49
|
-
verifyInstalled(manifest, installedRoot);
|
|
50
|
-
const core = path.join(installedRoot, 'node_modules/@sanqianx/project-knowledge');
|
|
51
|
-
const resolver = createRequire(path.join(core, 'package.json'));
|
|
52
|
-
for (const module of Object.values(manifest.modules)) {
|
|
53
|
-
const actual = resolver.resolve(`${module.installName}/package.json`);
|
|
54
|
-
if (actual !== path.join(installedRoot, 'node_modules', module.installName, 'package.json')) throw new Error(`A nested stale module shadows the tested candidate: ${module.installName}`);
|
|
55
|
-
}
|
|
56
|
-
const verify = spawnSync(process.execPath, [path.join(core, '_site/scripts/verify-module-runtime.js'), '--working-tree'], { cwd: installedRoot, windowsHide: true, encoding: 'utf8' });
|
|
57
|
-
if (verify.status !== 0) throw new Error('Packaged engine integrity failed');
|
|
58
|
-
require('./verify-product-runtime').verifyProductRuntime(core);
|
|
59
|
-
for (const relative of ['vendor-manifest.json', 'module-runtime-manifest.json']) {
|
|
60
|
-
if (!fs.readFileSync(path.join(core, relative)).equals(fs.readFileSync(path.join(root, relative)))) throw new Error(`Installed candidate is stale: ${relative}`);
|
|
61
|
-
}
|
|
62
|
-
const report = { schema: 'project-knowledge/installed-candidates/v1', mode: 'local npm candidate installation, not remote release', installedRoot, core, artifactManifest: manifestFile, shellVersion: candidate.version, shellSha256, shellArtifact, modules: Object.fromEntries(Object.entries(manifest.modules).map(([key, module]) => [key, { version: module.version, sha256: module.sha256 }])), integrityPassed: true, testedAt: new Date().toISOString() };
|
|
63
|
-
AtomicFile.writeJsonAtomic(path.join(installedRoot, 'installation-acceptance.json'), report);
|
|
64
|
-
process.stdout.write(`INSTALLED_PRODUCT ${path.join(installedRoot, 'installation-acceptance.json')}\n`);
|
|
65
|
-
}
|
|
66
|
-
if (require.main === module) {
|
|
67
|
-
try { main(); } catch (error) { process.stderr.write(`${error.message}\n`); process.exitCode = 1; }
|
|
68
|
-
}
|
|
69
|
-
module.exports = { contentAddressedArtifact };
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('node:fs');
|
|
3
|
+
const os = require('node:os');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const crypto = require('node:crypto');
|
|
6
|
+
const { createRequire } = require('node:module');
|
|
7
|
+
const { spawnSync } = require('node:child_process');
|
|
8
|
+
const AtomicFile = require('../lib/atomic-file');
|
|
9
|
+
const { verifyInstalled, safeRelative } = require('./pack-module-candidates');
|
|
10
|
+
const root = path.resolve(__dirname, '../..');
|
|
11
|
+
const npmCli = process.env.npm_execpath || path.join(path.dirname(process.execPath), 'node_modules/npm/bin/npm-cli.js');
|
|
12
|
+
function run(args, cwd) {
|
|
13
|
+
const result = spawnSync(process.execPath, [npmCli, ...args], { cwd, windowsHide: true, encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
|
|
14
|
+
if (result.status !== 0) throw new Error(`npm ${args[0]} failed (${result.status})`);
|
|
15
|
+
return result.stdout;
|
|
16
|
+
}
|
|
17
|
+
function contentAddressedArtifact(packedCore) {
|
|
18
|
+
const sha256 = crypto.createHash('sha256').update(fs.readFileSync(packedCore)).digest('hex');
|
|
19
|
+
const file = packedCore.replace(/\.tgz$/, `-${sha256}.tgz`);
|
|
20
|
+
if (file === packedCore) throw new Error('Candidate must be a tarball');
|
|
21
|
+
fs.copyFileSync(packedCore, file);
|
|
22
|
+
return { file, sha256 };
|
|
23
|
+
}
|
|
24
|
+
function main() {
|
|
25
|
+
const manifestFile = path.resolve(process.argv[2]);
|
|
26
|
+
const manifest = JSON.parse(fs.readFileSync(manifestFile));
|
|
27
|
+
if (manifest.schema !== 'project-knowledge/module-candidates/v1') throw new Error('Invalid candidate manifest');
|
|
28
|
+
const artifactRoot = path.dirname(manifestFile);
|
|
29
|
+
const dependencies = {};
|
|
30
|
+
for (const module of Object.values(manifest.modules)) {
|
|
31
|
+
if (!safeRelative(module.tarball) || !module.tarball.endsWith('.tgz')) throw new Error('Unsafe artifact path');
|
|
32
|
+
const file = path.join(artifactRoot, module.tarball);
|
|
33
|
+
if (fs.lstatSync(file).isSymbolicLink() || crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex') !== module.sha256) throw new Error('Module artifact drift');
|
|
34
|
+
dependencies[module.installName] = `file:${file}`;
|
|
35
|
+
}
|
|
36
|
+
const candidate = JSON.parse(run(['pack', '--ignore-scripts', '--json', '--pack-destination', artifactRoot], root))[0];
|
|
37
|
+
const packedCore = path.join(artifactRoot, candidate.filename);
|
|
38
|
+
// Same-version local tarballs are cached by npm. Address each candidate by
|
|
39
|
+
// content so an update cannot silently keep an older runtime or UI.
|
|
40
|
+
const { sha256: shellSha256, file: shellArtifact } = contentAddressedArtifact(packedCore);
|
|
41
|
+
dependencies['@sanqianx/project-knowledge'] = `file:${shellArtifact}`;
|
|
42
|
+
const updateAt = process.argv.indexOf('--update');
|
|
43
|
+
const installedRoot = updateAt < 0 ? fs.mkdtempSync(path.join(os.tmpdir(), 'kb-installed-product-')) : path.resolve(process.argv[updateAt + 1]);
|
|
44
|
+
if (path.dirname(installedRoot) !== path.resolve(os.tmpdir()) || !path.basename(installedRoot).startsWith('kb-installed-product-') || fs.lstatSync(installedRoot).isSymbolicLink()) throw new Error('Only this task’s isolated installation can be updated');
|
|
45
|
+
if (updateAt >= 0 && JSON.parse(fs.readFileSync(path.join(installedRoot, 'installation-acceptance.json'))).installedRoot !== installedRoot) throw new Error('Installed fixture identity mismatch');
|
|
46
|
+
AtomicFile.writeJsonAtomic(path.join(installedRoot, 'package.json'), { name: 'kb-local-acceptance', version: '0.0.0', private: true, dependencies });
|
|
47
|
+
process.stdout.write(`Installing isolated product at ${installedRoot}\n`);
|
|
48
|
+
run(['install', '--omit=dev', '--ignore-scripts', '--no-audit', '--no-fund'], installedRoot);
|
|
49
|
+
verifyInstalled(manifest, installedRoot);
|
|
50
|
+
const core = path.join(installedRoot, 'node_modules/@sanqianx/project-knowledge');
|
|
51
|
+
const resolver = createRequire(path.join(core, 'package.json'));
|
|
52
|
+
for (const module of Object.values(manifest.modules)) {
|
|
53
|
+
const actual = resolver.resolve(`${module.installName}/package.json`);
|
|
54
|
+
if (actual !== path.join(installedRoot, 'node_modules', module.installName, 'package.json')) throw new Error(`A nested stale module shadows the tested candidate: ${module.installName}`);
|
|
55
|
+
}
|
|
56
|
+
const verify = spawnSync(process.execPath, [path.join(core, '_site/scripts/verify-module-runtime.js'), '--working-tree'], { cwd: installedRoot, windowsHide: true, encoding: 'utf8' });
|
|
57
|
+
if (verify.status !== 0) throw new Error('Packaged engine integrity failed');
|
|
58
|
+
require('./verify-product-runtime').verifyProductRuntime(core);
|
|
59
|
+
for (const relative of ['vendor-manifest.json', 'module-runtime-manifest.json']) {
|
|
60
|
+
if (!fs.readFileSync(path.join(core, relative)).equals(fs.readFileSync(path.join(root, relative)))) throw new Error(`Installed candidate is stale: ${relative}`);
|
|
61
|
+
}
|
|
62
|
+
const report = { schema: 'project-knowledge/installed-candidates/v1', mode: 'local npm candidate installation, not remote release', installedRoot, core, artifactManifest: manifestFile, shellVersion: candidate.version, shellSha256, shellArtifact, modules: Object.fromEntries(Object.entries(manifest.modules).map(([key, module]) => [key, { version: module.version, sha256: module.sha256 }])), integrityPassed: true, testedAt: new Date().toISOString() };
|
|
63
|
+
AtomicFile.writeJsonAtomic(path.join(installedRoot, 'installation-acceptance.json'), report);
|
|
64
|
+
process.stdout.write(`INSTALLED_PRODUCT ${path.join(installedRoot, 'installation-acceptance.json')}\n`);
|
|
65
|
+
}
|
|
66
|
+
if (require.main === module) {
|
|
67
|
+
try { main(); } catch (error) { process.stderr.write(`${error.message}\n`); process.exitCode = 1; }
|
|
68
|
+
}
|
|
69
|
+
module.exports = { contentAddressedArtifact };
|