claude-memory-layer 1.0.31 → 1.0.32
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/README.md +9 -2
- package/dist/cli/index.js +1 -1
- package/package.json +11 -2
- package/scripts/postinstall-embedding-backend.cjs +16 -12
- package/AGENTS.md +0 -71
- package/CLAUDE.md +0 -30
- package/HANDOFF.md +0 -92
- package/Memo.txt +0 -558
- package/benchmarks/replay/anonymized-real-sessions.json +0 -48
- package/config/kpi-thresholds.json +0 -7
- package/context.md +0 -636
- package/docs/ARCHITECTURE_COMPARISON_AND_RECOMMENDATIONS.md +0 -627
- package/docs/HERMES_MEMORY_INGESTION_ANALYSIS.md +0 -440
- package/docs/MCP_MEMORY_SERVICE_COMPARATIVE_REVIEW.md +0 -271
- package/docs/MEMORY_USEFULNESS_AUDIT.md +0 -371
- package/docs/MEMORY_USEFULNESS_AUDIT_RAW.json +0 -80
- package/docs/MEMSEARCH_PROJECT_STRUCTURE_ANALYSIS.md +0 -333
- package/docs/MEMU_ADOPTION.md +0 -40
- package/docs/OPERATIONS.md +0 -18
- package/docs/PRODUCT_VALIDATION_MATRIX.md +0 -82
- package/docs/PROJECT_STRUCTURE_ANALYSIS.md +0 -421
- package/docs/REFACTORING_MILESTONES_AND_ISSUES.md +0 -501
- package/docs/REFACTORING_PLAN_THIN_CORE.md +0 -414
- package/docs/REFERENCE_PROJECT_ANALYSES.md +0 -25
- package/docs/SUPERLOCALMEMORY_PROJECT_STRUCTURE_ANALYSIS.md +0 -452
- package/docs/TARGET_ARCHITECTURE_AND_FOLDER_STRUCTURE.md +0 -446
- package/docs/architecture/comparison-index.md +0 -47
- package/docs/reports/codex-real-data-validation-20260505T040447Z.md +0 -46
- package/plan.md +0 -1642
- package/scripts/build.ts +0 -159
- package/scripts/bump-patch-version.sh +0 -18
- package/scripts/delete-unknown-projects.js +0 -154
- package/scripts/fix-sync-gap.js +0 -32
- package/scripts/generate-session-qrels.ts +0 -126
- package/scripts/heartbeat-memory-orchestrator.sh +0 -28
- package/scripts/replay-retrieval-benchmark.ts +0 -69
- package/scripts/report-sync-gap.js +0 -26
- package/scripts/review-queue-auto-resolve.js +0 -21
- package/scripts/sync-gap-auto-heal.sh +0 -17
- package/spec.md +0 -624
- package/specs/20260207-dashboard-upgrade/context.md +0 -38
- package/specs/20260207-dashboard-upgrade/spec.md +0 -96
- package/specs/citations-system/context.md +0 -243
- package/specs/citations-system/plan.md +0 -495
- package/specs/citations-system/spec.md +0 -371
- package/specs/endless-mode/context.md +0 -305
- package/specs/endless-mode/plan.md +0 -620
- package/specs/endless-mode/spec.md +0 -455
- package/specs/entity-edge-model/context.md +0 -401
- package/specs/entity-edge-model/plan.md +0 -459
- package/specs/entity-edge-model/spec.md +0 -391
- package/specs/evidence-aligner-v2/context.md +0 -401
- package/specs/evidence-aligner-v2/plan.md +0 -303
- package/specs/evidence-aligner-v2/spec.md +0 -312
- package/specs/mcp-desktop-integration/context.md +0 -278
- package/specs/mcp-desktop-integration/plan.md +0 -550
- package/specs/mcp-desktop-integration/spec.md +0 -494
- package/specs/memory-utilization-improvements/context.md +0 -145
- package/specs/memory-utilization-improvements/plan.md +0 -361
- package/specs/memory-utilization-improvements/spec.md +0 -361
- package/specs/post-tool-use-hook/context.md +0 -319
- package/specs/post-tool-use-hook/plan.md +0 -469
- package/specs/post-tool-use-hook/spec.md +0 -364
- package/specs/private-tags/context.md +0 -288
- package/specs/private-tags/plan.md +0 -412
- package/specs/private-tags/spec.md +0 -345
- package/specs/progressive-disclosure/context.md +0 -346
- package/specs/progressive-disclosure/plan.md +0 -663
- package/specs/progressive-disclosure/spec.md +0 -415
- package/specs/selective-tool-observation/context.md +0 -100
- package/specs/selective-tool-observation/plan.md +0 -158
- package/specs/selective-tool-observation/spec.md +0 -127
- package/specs/task-entity-system/context.md +0 -297
- package/specs/task-entity-system/plan.md +0 -301
- package/specs/task-entity-system/spec.md +0 -314
- package/specs/thin-core-refactor/context.md +0 -275
- package/specs/thin-core-refactor/plan.md +0 -536
- package/specs/thin-core-refactor/spec.md +0 -465
- package/specs/vector-outbox-v2/context.md +0 -470
- package/specs/vector-outbox-v2/plan.md +0 -562
- package/specs/vector-outbox-v2/spec.md +0 -466
- package/specs/web-viewer-ui/context.md +0 -384
- package/specs/web-viewer-ui/plan.md +0 -797
- package/specs/web-viewer-ui/spec.md +0 -516
- package/src/adapters/claude/capture/index.ts +0 -3
- package/src/adapters/claude/context/index.ts +0 -3
- package/src/adapters/claude/hooks/index.ts +0 -21
- package/src/adapters/claude/hooks/post-tool-use.ts +0 -239
- package/src/adapters/claude/hooks/prompt-injection-policy.ts +0 -104
- package/src/adapters/claude/hooks/semantic-daemon-client.ts +0 -209
- package/src/adapters/claude/hooks/semantic-daemon.ts +0 -283
- package/src/adapters/claude/hooks/session-end.ts +0 -59
- package/src/adapters/claude/hooks/session-start.ts +0 -73
- package/src/adapters/claude/hooks/stop.ts +0 -128
- package/src/adapters/claude/hooks/user-prompt-submit.ts +0 -361
- package/src/adapters/claude/index.ts +0 -4
- package/src/adapters/claude/transcript/index.ts +0 -4
- package/src/adapters/claude/transcript/transcript-reader.ts +0 -57
- package/src/adapters/claude/transcript/turn-reconstructor.ts +0 -65
- package/src/apps/cli/claude-settings-hooks.ts +0 -138
- package/src/apps/cli/codex-import-runner.ts +0 -125
- package/src/apps/cli/codex-validation-output.ts +0 -95
- package/src/apps/cli/hermes-import-runner.ts +0 -130
- package/src/apps/cli/hermes-validation-output.ts +0 -91
- package/src/apps/cli/index.ts +0 -1735
- package/src/apps/cli/mcp-install.ts +0 -106
- package/src/apps/cli/retrieval-disclosure-output.ts +0 -196
- package/src/apps/dashboard/assets/js/bootstrap.js +0 -244
- package/src/apps/dashboard/assets/js/chat.js +0 -373
- package/src/apps/dashboard/assets/js/disclosure.js +0 -232
- package/src/apps/dashboard/assets/js/modals.js +0 -298
- package/src/apps/dashboard/assets/js/overview.js +0 -655
- package/src/apps/dashboard/assets/js/state.js +0 -72
- package/src/apps/dashboard/assets/js/views.js +0 -468
- package/src/apps/dashboard/index.html +0 -543
- package/src/apps/dashboard/index.ts +0 -3
- package/src/apps/dashboard/style.css +0 -1750
- package/src/apps/index.ts +0 -5
- package/src/apps/server/api/chat.ts +0 -244
- package/src/apps/server/api/citations.ts +0 -105
- package/src/apps/server/api/events.ts +0 -137
- package/src/apps/server/api/health.ts +0 -53
- package/src/apps/server/api/index.ts +0 -26
- package/src/apps/server/api/projects.ts +0 -74
- package/src/apps/server/api/search.ts +0 -184
- package/src/apps/server/api/sessions.ts +0 -115
- package/src/apps/server/api/stats.ts +0 -723
- package/src/apps/server/api/turns.ts +0 -143
- package/src/apps/server/api/utils.ts +0 -65
- package/src/apps/server/index.ts +0 -111
- package/src/cli/index.ts +0 -3
- package/src/cli/retrieval-disclosure-output.ts +0 -2
- package/src/compat/index.ts +0 -5
- package/src/core/canonical-key.ts +0 -186
- package/src/core/citation-generator.ts +0 -63
- package/src/core/consolidated-store.ts +0 -356
- package/src/core/consolidation-worker.ts +0 -493
- package/src/core/context-formatter.ts +0 -276
- package/src/core/continuity-manager.ts +0 -341
- package/src/core/db-wrapper.ts +0 -64
- package/src/core/derive/fact-deriver.ts +0 -170
- package/src/core/derive/index.ts +0 -2
- package/src/core/derive/summary-deriver.ts +0 -76
- package/src/core/edge-repo.ts +0 -333
- package/src/core/embedder.ts +0 -4
- package/src/core/engine/embedding-maintenance-service.ts +0 -187
- package/src/core/engine/endless-memory-services.ts +0 -4
- package/src/core/engine/index.ts +0 -19
- package/src/core/engine/memory-engine-services.ts +0 -170
- package/src/core/engine/memory-ingest-service.ts +0 -317
- package/src/core/engine/memory-query-service.ts +0 -173
- package/src/core/engine/memory-runtime-service.ts +0 -162
- package/src/core/engine/memory-service-composition.ts +0 -231
- package/src/core/engine/retrieval-analytics-service.ts +0 -181
- package/src/core/engine/retrieval-disclosure-service.ts +0 -420
- package/src/core/engine/retrieval-orchestrator.ts +0 -377
- package/src/core/engine/retrieval-services.ts +0 -176
- package/src/core/engine/shared-memory-services.ts +0 -4
- package/src/core/entity-repo.ts +0 -349
- package/src/core/event-store.ts +0 -779
- package/src/core/evidence-aligner.ts +0 -635
- package/src/core/external-market-context.ts +0 -582
- package/src/core/graduation-worker.ts +0 -171
- package/src/core/graduation.ts +0 -377
- package/src/core/index.ts +0 -64
- package/src/core/ingest-interceptor.ts +0 -80
- package/src/core/markdown-mirror.ts +0 -70
- package/src/core/matcher.ts +0 -208
- package/src/core/md-mirror.ts +0 -92
- package/src/core/metadata-extractor.ts +0 -203
- package/src/core/model/memory-fact.ts +0 -30
- package/src/core/model/memory-rule.ts +0 -14
- package/src/core/model/memory-summary.ts +0 -21
- package/src/core/model/raw-event.ts +0 -28
- package/src/core/model/retrieval-result.ts +0 -35
- package/src/core/mongo-sync-config.ts +0 -165
- package/src/core/mongo-sync-worker.ts +0 -381
- package/src/core/privacy/filter.ts +0 -190
- package/src/core/privacy/index.ts +0 -20
- package/src/core/privacy/tag-parser.ts +0 -145
- package/src/core/product-validation-matrix.ts +0 -314
- package/src/core/progressive-retriever.ts +0 -414
- package/src/core/registry/project-path.ts +0 -54
- package/src/core/registry/session-registry.ts +0 -69
- package/src/core/replay-evaluator.ts +0 -625
- package/src/core/retrieval-benchmark.ts +0 -117
- package/src/core/retrieval-quality.ts +0 -109
- package/src/core/retriever.ts +0 -800
- package/src/core/session-qrels.ts +0 -360
- package/src/core/shared-event-store.ts +0 -114
- package/src/core/shared-promoter.ts +0 -249
- package/src/core/shared-store.ts +0 -289
- package/src/core/shared-vector-store.ts +0 -203
- package/src/core/sqlite-event-store.ts +0 -1846
- package/src/core/sqlite-wrapper.ts +0 -116
- package/src/core/sync-worker.ts +0 -228
- package/src/core/tag-taxonomy.ts +0 -51
- package/src/core/task/blocker-resolver.ts +0 -333
- package/src/core/task/index.ts +0 -9
- package/src/core/task/task-matcher.ts +0 -240
- package/src/core/task/task-projector.ts +0 -358
- package/src/core/task/task-resolver.ts +0 -421
- package/src/core/turn-state.ts +0 -207
- package/src/core/types.ts +0 -952
- package/src/core/vector-outbox.ts +0 -299
- package/src/core/vector-store.ts +0 -231
- package/src/core/vector-worker.ts +0 -521
- package/src/core/working-set-store.ts +0 -257
- package/src/extensions/endless-memory/endless-memory-services.ts +0 -350
- package/src/extensions/endless-memory/index.ts +0 -1
- package/src/extensions/index.ts +0 -5
- package/src/extensions/mcp/handlers.ts +0 -960
- package/src/extensions/mcp/index.ts +0 -48
- package/src/extensions/mcp/tools.ts +0 -252
- package/src/extensions/shared-memory/index.ts +0 -1
- package/src/extensions/shared-memory/shared-memory-services.ts +0 -211
- package/src/extensions/vector/embedder.ts +0 -234
- package/src/extensions/vector/index.ts +0 -1
- package/src/hooks/post-tool-use.ts +0 -9
- package/src/hooks/semantic-daemon-client.ts +0 -1
- package/src/hooks/semantic-daemon.ts +0 -11
- package/src/hooks/session-end.ts +0 -9
- package/src/hooks/session-start.ts +0 -9
- package/src/hooks/stop.ts +0 -9
- package/src/hooks/user-prompt-submit.ts +0 -9
- package/src/index.ts +0 -13
- package/src/mcp/handlers.ts +0 -2
- package/src/mcp/index.ts +0 -4
- package/src/mcp/tools.ts +0 -2
- package/src/server/api/chat.ts +0 -2
- package/src/server/api/citations.ts +0 -2
- package/src/server/api/events.ts +0 -2
- package/src/server/api/health.ts +0 -2
- package/src/server/api/index.ts +0 -2
- package/src/server/api/projects.ts +0 -2
- package/src/server/api/search.ts +0 -2
- package/src/server/api/sessions.ts +0 -2
- package/src/server/api/stats.ts +0 -2
- package/src/server/api/turns.ts +0 -2
- package/src/server/api/utils.ts +0 -2
- package/src/server/index.ts +0 -2
- package/src/services/bootstrap-organizer.ts +0 -463
- package/src/services/codex-session-history-importer.ts +0 -966
- package/src/services/hermes-session-history-importer.ts +0 -733
- package/src/services/memory-service-config.ts +0 -36
- package/src/services/memory-service-registry.ts +0 -150
- package/src/services/memory-service.ts +0 -688
- package/src/services/session-history-importer.ts +0 -629
- package/tests/README.md +0 -23
- package/tests/adapters/claude/claude-semantic-daemon-adapter.test.ts +0 -54
- package/tests/adapters/claude/claude-transcript-reconstructor.test.ts +0 -98
- package/tests/adapters/claude-hook-prompt-injection-policy.test.ts +0 -99
- package/tests/apps/app-layer-boundary.test.ts +0 -48
- package/tests/apps/claude-settings-hooks.test.ts +0 -107
- package/tests/apps/cli-disclosure-output.test.ts +0 -212
- package/tests/apps/codex-import-runner.test.ts +0 -99
- package/tests/apps/codex-validation-output.test.ts +0 -100
- package/tests/apps/hermes-import-runner.test.ts +0 -99
- package/tests/apps/mcp-install-command.test.ts +0 -59
- package/tests/apps/package-build-entrypoints.test.ts +0 -30
- package/tests/apps/postinstall-embedding-backend.test.ts +0 -185
- package/tests/apps/search-api-disclosure.test.ts +0 -162
- package/tests/apps/stats-api-lightweight.test.ts +0 -67
- package/tests/apps/ui-disclosure-output.test.ts +0 -140
- package/tests/core/bootstrap-organizer.test.ts +0 -111
- package/tests/core/canonical-key.test.ts +0 -101
- package/tests/core/codex-session-history-importer-validation.test.ts +0 -185
- package/tests/core/consolidation-worker.test.ts +0 -75
- package/tests/core/embedding-maintenance-service.test.ts +0 -282
- package/tests/core/evidence-aligner.test.ts +0 -152
- package/tests/core/external-market-context.test.ts +0 -209
- package/tests/core/fact-deriver.test.ts +0 -79
- package/tests/core/hermes-session-history-importer-validation.test.ts +0 -609
- package/tests/core/ingest-interceptor.test.ts +0 -38
- package/tests/core/markdown-mirror.test.ts +0 -85
- package/tests/core/matcher.test.ts +0 -112
- package/tests/core/md-mirror.test.ts +0 -50
- package/tests/core/memory-engine-services.test.ts +0 -240
- package/tests/core/memory-ingest-service.test.ts +0 -296
- package/tests/core/memory-query-service.test.ts +0 -129
- package/tests/core/memory-runtime-service.test.ts +0 -201
- package/tests/core/memory-service-composition.test.ts +0 -192
- package/tests/core/memory-service-config.test.ts +0 -41
- package/tests/core/memory-service-facade.test.ts +0 -30
- package/tests/core/memory-service-registry.test.ts +0 -206
- package/tests/core/product-validation-matrix.test.ts +0 -61
- package/tests/core/project-registry.test.ts +0 -78
- package/tests/core/replay-evaluator.test.ts +0 -181
- package/tests/core/retrieval-analytics-service.test.ts +0 -210
- package/tests/core/retrieval-benchmark.test.ts +0 -93
- package/tests/core/retrieval-disclosure-service.test.ts +0 -264
- package/tests/core/retrieval-orchestrator.test.ts +0 -403
- package/tests/core/retrieval-quality.test.ts +0 -31
- package/tests/core/retrieval-services.test.ts +0 -185
- package/tests/core/retriever-fallback-chain.test.ts +0 -223
- package/tests/core/retriever-strategy-scope.test.ts +0 -164
- package/tests/core/retriever.memu-adoption.test.ts +0 -122
- package/tests/core/session-history-importer-filter.test.ts +0 -78
- package/tests/core/session-qrels.test.ts +0 -250
- package/tests/core/sqlite-event-store-replication.test.ts +0 -127
- package/tests/core/summary-deriver.test.ts +0 -66
- package/tests/extensions/embedder-warning-suppression.test.ts +0 -84
- package/tests/extensions/endless-memory-extension-boundary.test.ts +0 -17
- package/tests/extensions/endless-memory-services.test.ts +0 -325
- package/tests/extensions/mcp-context-tools.test.ts +0 -905
- package/tests/extensions/mcp-extension-boundary.test.ts +0 -21
- package/tests/extensions/mcp-package-build.test.ts +0 -22
- package/tests/extensions/mcp-project-aware-tools.test.ts +0 -102
- package/tests/extensions/shared-memory-extension-boundary.test.ts +0 -24
- package/tests/extensions/shared-memory-services.test.ts +0 -309
- package/tests/extensions/vector-extension-boundary.test.ts +0 -21
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -15
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
createMemoryServiceComposition,
|
|
5
|
-
type MemoryServiceCompositionFactories
|
|
6
|
-
} from '../../src/core/engine/memory-service-composition.js';
|
|
7
|
-
import type { SharedStoreConfig, ToolObservationPayload } from '../../src/core/types.js';
|
|
8
|
-
|
|
9
|
-
const sharedStoreConfig: SharedStoreConfig = {
|
|
10
|
-
enabled: true,
|
|
11
|
-
autoPromote: true,
|
|
12
|
-
searchShared: true,
|
|
13
|
-
minConfidenceForPromotion: 0.8,
|
|
14
|
-
sharedStoragePath: '~/shared-memory'
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
describe('createMemoryServiceComposition', () => {
|
|
18
|
-
it('wires engine, endless, shared, runtime, and embedding maintenance services for MemoryService', async () => {
|
|
19
|
-
const initialize = vi.fn(async () => undefined);
|
|
20
|
-
let projectHash: string | null = 'project-hash-1';
|
|
21
|
-
let projectPath: string | null = '/repo/project';
|
|
22
|
-
|
|
23
|
-
const sqliteStore = {
|
|
24
|
-
clearEmbeddingOutbox: vi.fn(async () => undefined),
|
|
25
|
-
getEventsPage: vi.fn(async () => [{ id: 'event-1', content: 'event content' }]),
|
|
26
|
-
enqueueForEmbedding: vi.fn(async () => undefined)
|
|
27
|
-
};
|
|
28
|
-
const vectorStore = { name: 'vector-store' };
|
|
29
|
-
const embedder = { getModelName: vi.fn(() => 'test-embedding-model') };
|
|
30
|
-
const retriever = { setSharedStores: vi.fn() };
|
|
31
|
-
const graduation = { name: 'graduation' };
|
|
32
|
-
const ingestService = { name: 'ingest' };
|
|
33
|
-
const queryService = { name: 'query' };
|
|
34
|
-
const retrievalOrchestrator = { name: 'retrieval-orchestrator' };
|
|
35
|
-
const retrievalDisclosureService = { name: 'retrieval-disclosure' };
|
|
36
|
-
const retrievalAnalyticsService = { name: 'retrieval-analytics' };
|
|
37
|
-
const endlessMemoryServices = { name: 'endless-memory' };
|
|
38
|
-
const sharedMemoryServices = {
|
|
39
|
-
isEnabled: vi.fn(() => true),
|
|
40
|
-
getEntryForDisclosure: vi.fn(async (entryId: string) => ({ id: entryId }))
|
|
41
|
-
};
|
|
42
|
-
const runtimeService = { getVectorWorker: vi.fn(() => ({ name: 'vector-worker' })) };
|
|
43
|
-
const embeddingMaintenanceService = { getEmbeddingModelName: vi.fn(() => 'maintenance-model') };
|
|
44
|
-
|
|
45
|
-
const factories: MemoryServiceCompositionFactories = {
|
|
46
|
-
expandPath: vi.fn((targetPath: string) => targetPath.replace('~', '/home/test')),
|
|
47
|
-
createToolObservationEmbedding: vi.fn((toolName: string) => `embedding:${toolName}`),
|
|
48
|
-
createMemoryEngineServices: vi.fn(() => ({
|
|
49
|
-
storagePath: '/expanded/storage',
|
|
50
|
-
sqliteStore,
|
|
51
|
-
vectorStore,
|
|
52
|
-
embedder,
|
|
53
|
-
matcher: { name: 'matcher' },
|
|
54
|
-
retriever,
|
|
55
|
-
retrievalOrchestrator,
|
|
56
|
-
retrievalDisclosureService,
|
|
57
|
-
retrievalAnalyticsService,
|
|
58
|
-
graduation,
|
|
59
|
-
mdMirror: { name: 'md-mirror' },
|
|
60
|
-
ingestService,
|
|
61
|
-
queryService
|
|
62
|
-
}) as any),
|
|
63
|
-
createEndlessMemoryServices: vi.fn(() => endlessMemoryServices as any),
|
|
64
|
-
createSharedMemoryServices: vi.fn(() => sharedMemoryServices as any),
|
|
65
|
-
createMemoryRuntimeService: vi.fn(() => runtimeService as any),
|
|
66
|
-
createEmbeddingMaintenanceService: vi.fn(() => embeddingMaintenanceService as any)
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const composition = createMemoryServiceComposition({
|
|
70
|
-
config: {
|
|
71
|
-
storagePath: '~/memory-store',
|
|
72
|
-
embeddingModel: 'explicit-model',
|
|
73
|
-
readOnly: true,
|
|
74
|
-
lightweightMode: true,
|
|
75
|
-
embeddingOnly: true,
|
|
76
|
-
projectHash,
|
|
77
|
-
projectPath,
|
|
78
|
-
sharedStoreConfig
|
|
79
|
-
},
|
|
80
|
-
defaultSharedStoragePath: '/default/shared',
|
|
81
|
-
initialize,
|
|
82
|
-
getProjectHash: () => projectHash,
|
|
83
|
-
getProjectPath: () => projectPath,
|
|
84
|
-
factories
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
expect(factories.expandPath).toHaveBeenCalledWith('~/memory-store');
|
|
88
|
-
expect(factories.createMemoryEngineServices).toHaveBeenCalledWith(expect.objectContaining({
|
|
89
|
-
storagePath: '/home/test/memory-store',
|
|
90
|
-
readOnly: true,
|
|
91
|
-
embeddingModel: 'explicit-model',
|
|
92
|
-
cwd: '/repo/project',
|
|
93
|
-
initialize,
|
|
94
|
-
getProjectHash: expect.any(Function),
|
|
95
|
-
getProjectPath: expect.any(Function),
|
|
96
|
-
hasSharedStore: expect.any(Function),
|
|
97
|
-
sharedStore: expect.objectContaining({ get: expect.any(Function) }),
|
|
98
|
-
createToolObservationEmbedding: expect.any(Function)
|
|
99
|
-
}));
|
|
100
|
-
|
|
101
|
-
const engineOptions = vi.mocked(factories.createMemoryEngineServices).mock.calls[0][0];
|
|
102
|
-
expect(engineOptions.createToolObservationEmbedding({
|
|
103
|
-
toolName: 'Read',
|
|
104
|
-
metadata: { path: 'README.md' },
|
|
105
|
-
success: true
|
|
106
|
-
} as ToolObservationPayload)).toBe('embedding:Read');
|
|
107
|
-
expect(factories.createToolObservationEmbedding).toHaveBeenCalledWith(
|
|
108
|
-
'Read',
|
|
109
|
-
{ path: 'README.md' },
|
|
110
|
-
true
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
expect(factories.createEndlessMemoryServices).toHaveBeenCalledWith({
|
|
114
|
-
eventStore: sqliteStore,
|
|
115
|
-
configStore: sqliteStore,
|
|
116
|
-
initialize
|
|
117
|
-
});
|
|
118
|
-
expect(factories.createSharedMemoryServices).toHaveBeenCalledWith({
|
|
119
|
-
config: sharedStoreConfig,
|
|
120
|
-
defaultSharedStoragePath: '/default/shared',
|
|
121
|
-
readOnly: true,
|
|
122
|
-
expandPath: expect.any(Function),
|
|
123
|
-
embedder,
|
|
124
|
-
retriever
|
|
125
|
-
});
|
|
126
|
-
expect(factories.createMemoryRuntimeService).toHaveBeenCalledWith(expect.objectContaining({
|
|
127
|
-
sqliteStore,
|
|
128
|
-
eventStore: sqliteStore,
|
|
129
|
-
vectorStore,
|
|
130
|
-
embedder,
|
|
131
|
-
retriever,
|
|
132
|
-
graduation,
|
|
133
|
-
endlessMemoryServices,
|
|
134
|
-
sharedMemoryServices,
|
|
135
|
-
readOnly: true,
|
|
136
|
-
lightweightMode: true,
|
|
137
|
-
embeddingOnly: true
|
|
138
|
-
}));
|
|
139
|
-
expect(factories.createEmbeddingMaintenanceService).toHaveBeenCalledWith(expect.objectContaining({
|
|
140
|
-
storagePath: '/home/test/memory-store',
|
|
141
|
-
initialize,
|
|
142
|
-
getEmbeddingModelName: expect.any(Function),
|
|
143
|
-
vectorStore,
|
|
144
|
-
eventStore: expect.objectContaining({
|
|
145
|
-
clearEmbeddingOutbox: expect.any(Function),
|
|
146
|
-
getEventsPage: expect.any(Function),
|
|
147
|
-
enqueueForEmbedding: expect.any(Function)
|
|
148
|
-
}),
|
|
149
|
-
getVectorWorker: expect.any(Function)
|
|
150
|
-
}));
|
|
151
|
-
|
|
152
|
-
const embeddingOptions = vi.mocked(factories.createEmbeddingMaintenanceService).mock.calls[0][0];
|
|
153
|
-
expect(embeddingOptions.getEmbeddingModelName()).toBe('test-embedding-model');
|
|
154
|
-
expect(embeddingOptions.getVectorWorker()).toEqual({ name: 'vector-worker' });
|
|
155
|
-
await embeddingOptions.eventStore.clearEmbeddingOutbox();
|
|
156
|
-
await expect(embeddingOptions.eventStore.getEventsPage(10, 0)).resolves.toEqual([
|
|
157
|
-
{ id: 'event-1', content: 'event content' }
|
|
158
|
-
]);
|
|
159
|
-
await embeddingOptions.eventStore.enqueueForEmbedding('event-1', 'event content');
|
|
160
|
-
expect(sqliteStore.clearEmbeddingOutbox).toHaveBeenCalled();
|
|
161
|
-
expect(sqliteStore.getEventsPage).toHaveBeenCalledWith(10, 0);
|
|
162
|
-
expect(sqliteStore.enqueueForEmbedding).toHaveBeenCalledWith('event-1', 'event content');
|
|
163
|
-
|
|
164
|
-
expect(await engineOptions.sharedStore?.get('shared-1')).toEqual({ id: 'shared-1' });
|
|
165
|
-
expect(engineOptions.hasSharedStore()).toBe(true);
|
|
166
|
-
projectHash = 'project-hash-2';
|
|
167
|
-
projectPath = '/repo/other';
|
|
168
|
-
expect(engineOptions.getProjectHash()).toBe('project-hash-2');
|
|
169
|
-
expect(engineOptions.getProjectPath?.()).toBe('/repo/other');
|
|
170
|
-
|
|
171
|
-
expect(composition).toMatchObject({
|
|
172
|
-
storagePath: '/home/test/memory-store',
|
|
173
|
-
readOnly: true,
|
|
174
|
-
lightweightMode: true,
|
|
175
|
-
embeddingOnly: true,
|
|
176
|
-
sqliteStore,
|
|
177
|
-
vectorStore,
|
|
178
|
-
embedder,
|
|
179
|
-
retriever,
|
|
180
|
-
retrievalOrchestrator,
|
|
181
|
-
retrievalDisclosureService,
|
|
182
|
-
retrievalAnalyticsService,
|
|
183
|
-
graduation,
|
|
184
|
-
ingestService,
|
|
185
|
-
queryService,
|
|
186
|
-
endlessMemoryServices,
|
|
187
|
-
sharedMemoryServices,
|
|
188
|
-
runtimeService,
|
|
189
|
-
embeddingMaintenanceService
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
DEFAULT_ENABLED_SHARED_STORE_CONFIG as CONFIG_DEFAULT_ENABLED_SHARED_STORE_CONFIG,
|
|
5
|
-
DISABLED_SHARED_STORE_CONFIG as CONFIG_DISABLED_SHARED_STORE_CONFIG,
|
|
6
|
-
DEFAULT_SHARED_STORAGE_PATH as CONFIG_DEFAULT_SHARED_STORAGE_PATH
|
|
7
|
-
} from '../../src/services/memory-service-config.js';
|
|
8
|
-
import {
|
|
9
|
-
DEFAULT_ENABLED_SHARED_STORE_CONFIG as FACADE_DEFAULT_ENABLED_SHARED_STORE_CONFIG,
|
|
10
|
-
DISABLED_SHARED_STORE_CONFIG as FACADE_DISABLED_SHARED_STORE_CONFIG
|
|
11
|
-
} from '../../src/services/memory-service.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* MemoryService should stay a thin compatibility facade. Shared defaults are
|
|
15
|
-
* owned by memory-service-config so registries can import them without pulling
|
|
16
|
-
* in the MemoryService class and creating a service-locator cycle.
|
|
17
|
-
*/
|
|
18
|
-
describe('memory-service-config', () => {
|
|
19
|
-
it('owns disabled shared-store defaults while memory-service preserves the public export', () => {
|
|
20
|
-
expect(CONFIG_DISABLED_SHARED_STORE_CONFIG).toMatchObject({
|
|
21
|
-
enabled: false,
|
|
22
|
-
autoPromote: false,
|
|
23
|
-
searchShared: false,
|
|
24
|
-
minConfidenceForPromotion: 0.8
|
|
25
|
-
});
|
|
26
|
-
expect(CONFIG_DISABLED_SHARED_STORE_CONFIG.sharedStoragePath).toContain('.claude-code');
|
|
27
|
-
expect(CONFIG_DISABLED_SHARED_STORE_CONFIG.sharedStoragePath).toContain('shared');
|
|
28
|
-
expect(FACADE_DISABLED_SHARED_STORE_CONFIG).toBe(CONFIG_DISABLED_SHARED_STORE_CONFIG);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('owns enabled shared-store defaults while memory-service preserves the public export', () => {
|
|
32
|
-
expect(CONFIG_DEFAULT_ENABLED_SHARED_STORE_CONFIG).toEqual({
|
|
33
|
-
enabled: true,
|
|
34
|
-
autoPromote: true,
|
|
35
|
-
searchShared: true,
|
|
36
|
-
minConfidenceForPromotion: 0.8,
|
|
37
|
-
sharedStoragePath: CONFIG_DEFAULT_SHARED_STORAGE_PATH
|
|
38
|
-
});
|
|
39
|
-
expect(FACADE_DEFAULT_ENABLED_SHARED_STORE_CONFIG).toBe(CONFIG_DEFAULT_ENABLED_SHARED_STORE_CONFIG);
|
|
40
|
-
});
|
|
41
|
-
});
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { mkdtemp } from 'fs/promises';
|
|
2
|
-
import * as os from 'os';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
|
|
5
|
-
import { describe, expect, it } from 'vitest';
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
DISABLED_SHARED_STORE_CONFIG,
|
|
9
|
-
MemoryService
|
|
10
|
-
} from '../../src/services/memory-service.js';
|
|
11
|
-
|
|
12
|
-
describe('MemoryService facade delegation', () => {
|
|
13
|
-
it('reads the embedding model name through the embedding maintenance facade', async () => {
|
|
14
|
-
const storagePath = await mkdtemp(path.join(os.tmpdir(), 'memory-service-facade-'));
|
|
15
|
-
const service = new MemoryService({
|
|
16
|
-
storagePath,
|
|
17
|
-
sharedStoreConfig: DISABLED_SHARED_STORE_CONFIG
|
|
18
|
-
});
|
|
19
|
-
const serviceInternals = service as unknown as {
|
|
20
|
-
embedder: { getModelName(): string };
|
|
21
|
-
embeddingMaintenanceService: { getEmbeddingModelName(): string };
|
|
22
|
-
};
|
|
23
|
-
serviceInternals.embedder = { getModelName: () => 'direct-embedder-model' };
|
|
24
|
-
serviceInternals.embeddingMaintenanceService = {
|
|
25
|
-
getEmbeddingModelName: () => 'maintenance-facade-model'
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
expect(service.getEmbeddingModelName()).toBe('maintenance-facade-model');
|
|
29
|
-
});
|
|
30
|
-
});
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
|
|
4
|
-
import { createMemoryServiceRegistry } from '../../src/services/memory-service-registry.js';
|
|
5
|
-
import type { SharedStoreConfig } from '../../src/core/types.js';
|
|
6
|
-
|
|
7
|
-
interface FakeService {
|
|
8
|
-
config: Record<string, unknown>;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const disabledSharedStoreConfig: SharedStoreConfig = {
|
|
12
|
-
enabled: false,
|
|
13
|
-
autoPromote: false,
|
|
14
|
-
searchShared: false,
|
|
15
|
-
minConfidenceForPromotion: 0.8,
|
|
16
|
-
sharedStoragePath: '/home/test/.claude-code/memory/shared'
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
function createRegistry(sessionProject?: { projectHash: string; projectPath: string }) {
|
|
20
|
-
const createdConfigs: Array<Record<string, unknown>> = [];
|
|
21
|
-
const registry = createMemoryServiceRegistry<FakeService>({
|
|
22
|
-
createService: (config) => {
|
|
23
|
-
createdConfigs.push(config as unknown as Record<string, unknown>);
|
|
24
|
-
return { config: config as unknown as Record<string, unknown> };
|
|
25
|
-
},
|
|
26
|
-
hashProjectPath: (projectPath) => `hash:${projectPath}`,
|
|
27
|
-
getProjectStoragePath: (projectPath) => `/storage/${projectPath}`,
|
|
28
|
-
getSessionProject: (sessionId) => sessionId === 'known-session' ? sessionProject ?? null : null,
|
|
29
|
-
homedir: () => '/home/test',
|
|
30
|
-
disabledSharedStoreConfig
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
return { registry, createdConfigs };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
describe('createMemoryServiceRegistry', () => {
|
|
37
|
-
it('stays independent from the MemoryService facade to avoid service-locator cycles', () => {
|
|
38
|
-
const source = readFileSync('src/services/memory-service-registry.ts', 'utf8');
|
|
39
|
-
|
|
40
|
-
expect(source).not.toContain("from './memory-service.js'");
|
|
41
|
-
expect(source).not.toContain('from "./memory-service.js"');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('caches the default writable service with global storage and disabled shared store', () => {
|
|
45
|
-
const { registry, createdConfigs } = createRegistry();
|
|
46
|
-
|
|
47
|
-
const first = registry.getDefaultMemoryService();
|
|
48
|
-
const second = registry.getDefaultMemoryService();
|
|
49
|
-
|
|
50
|
-
expect(first).toBe(second);
|
|
51
|
-
expect(createdConfigs).toHaveLength(1);
|
|
52
|
-
expect(first.config).toMatchObject({
|
|
53
|
-
storagePath: '~/.claude-code/memory',
|
|
54
|
-
analyticsEnabled: false,
|
|
55
|
-
sharedStoreConfig: disabledSharedStoreConfig
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('creates fresh read-only services to avoid holding locks', () => {
|
|
60
|
-
const { registry, createdConfigs } = createRegistry();
|
|
61
|
-
|
|
62
|
-
const first = registry.getReadOnlyMemoryService();
|
|
63
|
-
const second = registry.getReadOnlyMemoryService();
|
|
64
|
-
|
|
65
|
-
expect(first).not.toBe(second);
|
|
66
|
-
expect(createdConfigs).toHaveLength(2);
|
|
67
|
-
expect(first.config).toMatchObject({
|
|
68
|
-
storagePath: '~/.claude-code/memory',
|
|
69
|
-
readOnly: true,
|
|
70
|
-
analyticsEnabled: false,
|
|
71
|
-
sharedStoreConfig: disabledSharedStoreConfig
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('caches project services by project hash and preserves project scope config', () => {
|
|
76
|
-
const { registry, createdConfigs } = createRegistry();
|
|
77
|
-
|
|
78
|
-
const first = registry.getMemoryServiceForProject('/workspace/app');
|
|
79
|
-
const second = registry.getMemoryServiceForProject('/workspace/app');
|
|
80
|
-
|
|
81
|
-
expect(first).toBe(second);
|
|
82
|
-
expect(createdConfigs).toHaveLength(1);
|
|
83
|
-
expect(first.config).toMatchObject({
|
|
84
|
-
storagePath: '/storage//workspace/app',
|
|
85
|
-
projectHash: 'hash:/workspace/app',
|
|
86
|
-
projectPath: '/workspace/app',
|
|
87
|
-
analyticsEnabled: false,
|
|
88
|
-
sharedStoreConfig: disabledSharedStoreConfig
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('preserves the first shared store config for cached project services', () => {
|
|
93
|
-
const { registry, createdConfigs } = createRegistry();
|
|
94
|
-
const firstSharedConfig: SharedStoreConfig = {
|
|
95
|
-
...disabledSharedStoreConfig,
|
|
96
|
-
enabled: true,
|
|
97
|
-
searchShared: true,
|
|
98
|
-
sharedStoragePath: '/shared/first'
|
|
99
|
-
};
|
|
100
|
-
const laterSharedConfig: SharedStoreConfig = {
|
|
101
|
-
...disabledSharedStoreConfig,
|
|
102
|
-
enabled: true,
|
|
103
|
-
autoPromote: true,
|
|
104
|
-
sharedStoragePath: '/shared/later'
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const first = registry.getMemoryServiceForProject('/workspace/app', firstSharedConfig);
|
|
108
|
-
const second = registry.getMemoryServiceForProject('/workspace/app', laterSharedConfig);
|
|
109
|
-
|
|
110
|
-
expect(second).toBe(first);
|
|
111
|
-
expect(createdConfigs).toHaveLength(1);
|
|
112
|
-
expect(first.config.sharedStoreConfig).toBe(firstSharedConfig);
|
|
113
|
-
expect(first.config.sharedStoreConfig).not.toBe(laterSharedConfig);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('resolves session services from the session registry and falls back to global service', () => {
|
|
117
|
-
const { registry } = createRegistry({
|
|
118
|
-
projectHash: 'registered-hash',
|
|
119
|
-
projectPath: '/workspace/registered'
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
const projectService = registry.getMemoryServiceForSession('known-session');
|
|
123
|
-
const directService = registry.getMemoryServiceForProject('/workspace/registered');
|
|
124
|
-
const fallbackService = registry.getMemoryServiceForSession('unknown-session');
|
|
125
|
-
|
|
126
|
-
expect(projectService).toBe(directService);
|
|
127
|
-
expect(fallbackService).toBe(registry.getDefaultMemoryService());
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('keeps registry methods safe when callers destructure a custom registry', () => {
|
|
131
|
-
const { registry } = createRegistry({
|
|
132
|
-
projectHash: 'registered-hash',
|
|
133
|
-
projectPath: '/workspace/registered'
|
|
134
|
-
});
|
|
135
|
-
const {
|
|
136
|
-
getDefaultMemoryService,
|
|
137
|
-
getMemoryServiceForProject,
|
|
138
|
-
getMemoryServiceForSession
|
|
139
|
-
} = registry;
|
|
140
|
-
|
|
141
|
-
const projectService = getMemoryServiceForSession('known-session');
|
|
142
|
-
const directService = getMemoryServiceForProject('/workspace/registered');
|
|
143
|
-
const fallbackService = getMemoryServiceForSession('unknown-session');
|
|
144
|
-
|
|
145
|
-
expect(projectService).toBe(directService);
|
|
146
|
-
expect(fallbackService).toBe(getDefaultMemoryService());
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('caches lightweight services separately for project and global sessions', () => {
|
|
150
|
-
const { registry } = createRegistry({
|
|
151
|
-
projectHash: 'registered-hash',
|
|
152
|
-
projectPath: '/workspace/registered'
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
const projectService = registry.getLightweightMemoryService('known-session');
|
|
156
|
-
const sameProjectService = registry.getLightweightMemoryService('known-session');
|
|
157
|
-
const globalService = registry.getLightweightMemoryService('unknown-session');
|
|
158
|
-
|
|
159
|
-
expect(projectService).toBe(sameProjectService);
|
|
160
|
-
expect(projectService).not.toBe(globalService);
|
|
161
|
-
expect(projectService.config).toMatchObject({
|
|
162
|
-
storagePath: '/storage//workspace/registered',
|
|
163
|
-
projectHash: 'registered-hash',
|
|
164
|
-
projectPath: '/workspace/registered',
|
|
165
|
-
lightweightMode: true,
|
|
166
|
-
analyticsEnabled: false,
|
|
167
|
-
sharedStoreConfig: disabledSharedStoreConfig
|
|
168
|
-
});
|
|
169
|
-
expect(globalService.config).toMatchObject({
|
|
170
|
-
storagePath: '/home/test/.claude-code/memory',
|
|
171
|
-
lightweightMode: true,
|
|
172
|
-
analyticsEnabled: false,
|
|
173
|
-
sharedStoreConfig: disabledSharedStoreConfig
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('caches lightweight project services for CLI read paths without reusing the full project service', () => {
|
|
178
|
-
const { registry, createdConfigs } = createRegistry();
|
|
179
|
-
|
|
180
|
-
const fullProjectService = registry.getMemoryServiceForProject('/workspace/app');
|
|
181
|
-
const lightweightProjectService = registry.getLightweightMemoryServiceForProject('/workspace/app');
|
|
182
|
-
const sameLightweightProjectService = registry.getLightweightMemoryServiceForProject('/workspace/app');
|
|
183
|
-
|
|
184
|
-
expect(lightweightProjectService).toBe(sameLightweightProjectService);
|
|
185
|
-
expect(lightweightProjectService).not.toBe(fullProjectService);
|
|
186
|
-
expect(createdConfigs).toHaveLength(2);
|
|
187
|
-
expect(lightweightProjectService.config).toMatchObject({
|
|
188
|
-
storagePath: '/storage//workspace/app',
|
|
189
|
-
projectHash: 'hash:/workspace/app',
|
|
190
|
-
projectPath: '/workspace/app',
|
|
191
|
-
lightweightMode: true,
|
|
192
|
-
analyticsEnabled: false,
|
|
193
|
-
sharedStoreConfig: disabledSharedStoreConfig
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it('creates uncached services through the explicit factory facade', () => {
|
|
198
|
-
const { registry } = createRegistry();
|
|
199
|
-
|
|
200
|
-
const first = registry.createMemoryService({ storagePath: '/tmp/a' });
|
|
201
|
-
const second = registry.createMemoryService({ storagePath: '/tmp/a' });
|
|
202
|
-
|
|
203
|
-
expect(first).not.toBe(second);
|
|
204
|
-
expect(first.config).toMatchObject({ storagePath: '/tmp/a' });
|
|
205
|
-
});
|
|
206
|
-
});
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
getProductValidationMatrixSummary,
|
|
5
|
-
productValidationMatrix,
|
|
6
|
-
renderProductValidationMatrixMarkdown
|
|
7
|
-
} from '../../src/core/product-validation-matrix.js';
|
|
8
|
-
|
|
9
|
-
const requiredSurfaces = [
|
|
10
|
-
'claude.adapter.import',
|
|
11
|
-
'claude.adapter.search',
|
|
12
|
-
'claude.adapter.disclosure',
|
|
13
|
-
'codex.adapter.scan',
|
|
14
|
-
'codex.adapter.import',
|
|
15
|
-
'codex.adapter.replay',
|
|
16
|
-
'hermes.adapter.scan',
|
|
17
|
-
'hermes.adapter.import',
|
|
18
|
-
'hermes.adapter.replay',
|
|
19
|
-
'mcp.context.pack',
|
|
20
|
-
'mcp.project.timeline',
|
|
21
|
-
'mcp.source.ref',
|
|
22
|
-
'cli.api.reporting',
|
|
23
|
-
'safety.dryRun'
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
describe('product validation matrix', () => {
|
|
27
|
-
it('covers the product-level validation surfaces with requirements and evidence', () => {
|
|
28
|
-
const surfaceIds = new Set(productValidationMatrix.map((surface) => surface.id));
|
|
29
|
-
|
|
30
|
-
for (const id of requiredSurfaces) {
|
|
31
|
-
expect(surfaceIds.has(id), `missing surface ${id}`).toBe(true);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
for (const surface of productValidationMatrix) {
|
|
35
|
-
expect(surface.title).toBeTruthy();
|
|
36
|
-
expect(surface.requirements.length, `${surface.id} requirements`).toBeGreaterThan(0);
|
|
37
|
-
expect(surface.evidence.length, `${surface.id} evidence`).toBeGreaterThan(0);
|
|
38
|
-
expect(['ready', 'covered', 'partial', 'planned']).toContain(surface.status);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('summarizes and renders a stable reporting-friendly matrix', () => {
|
|
43
|
-
const summary = getProductValidationMatrixSummary(productValidationMatrix);
|
|
44
|
-
expect(summary.totalSurfaces).toBeGreaterThanOrEqual(requiredSurfaces.length);
|
|
45
|
-
expect(summary.surfacesByArea.codex).toBeGreaterThanOrEqual(3);
|
|
46
|
-
expect(summary.surfacesByArea.hermes).toBeGreaterThanOrEqual(3);
|
|
47
|
-
expect(summary.surfacesByArea.mcp).toBeGreaterThanOrEqual(3);
|
|
48
|
-
expect(summary.surfacesByArea.claude).toBeGreaterThanOrEqual(3);
|
|
49
|
-
expect(summary.evidenceCount).toBeGreaterThanOrEqual(requiredSurfaces.length);
|
|
50
|
-
|
|
51
|
-
const markdown = renderProductValidationMatrixMarkdown(productValidationMatrix);
|
|
52
|
-
expect(markdown).toContain('# Product Validation Matrix');
|
|
53
|
-
expect(markdown).toContain('Codex adapter replay');
|
|
54
|
-
expect(markdown).toContain('Hermes adapter replay');
|
|
55
|
-
expect(markdown).toContain('MCP context pack');
|
|
56
|
-
expect(markdown).toContain('MCP source reference');
|
|
57
|
-
expect(markdown).toContain('Safety / dry-run');
|
|
58
|
-
expect(markdown).toContain('tests/core/codex-session-history-importer-validation.test.ts');
|
|
59
|
-
expect(markdown).toContain('tests/core/hermes-session-history-importer-validation.test.ts');
|
|
60
|
-
});
|
|
61
|
-
});
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import * as fs from 'node:fs/promises';
|
|
3
|
-
import * as os from 'node:os';
|
|
4
|
-
import * as path from 'node:path';
|
|
5
|
-
import {
|
|
6
|
-
getProjectStoragePath,
|
|
7
|
-
hashProjectPath,
|
|
8
|
-
normalizeProjectPath,
|
|
9
|
-
resolveProjectStoragePath
|
|
10
|
-
} from '../../src/core/registry/project-path.js';
|
|
11
|
-
|
|
12
|
-
describe('project-path registry utilities', () => {
|
|
13
|
-
it('normalizes paths and generates stable hashes', async () => {
|
|
14
|
-
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'cml-project-path-'));
|
|
15
|
-
const projectDir = path.join(root, 'project');
|
|
16
|
-
await fs.mkdir(projectDir, { recursive: true });
|
|
17
|
-
|
|
18
|
-
const hashA = hashProjectPath(projectDir);
|
|
19
|
-
const hashB = hashProjectPath(projectDir + '/');
|
|
20
|
-
|
|
21
|
-
const normalized = normalizeProjectPath(projectDir + '/');
|
|
22
|
-
|
|
23
|
-
expect(normalized.endsWith('/project')).toBe(true);
|
|
24
|
-
expect(hashA).toBe(hashB);
|
|
25
|
-
expect(hashA).toMatch(/^[a-f0-9]{8}$/);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('resolves storage paths for both project paths and explicit hashes', async () => {
|
|
29
|
-
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'cml-storage-path-'));
|
|
30
|
-
const projectDir = path.join(root, 'project');
|
|
31
|
-
await fs.mkdir(projectDir, { recursive: true });
|
|
32
|
-
|
|
33
|
-
const projectHash = hashProjectPath(projectDir);
|
|
34
|
-
const storageFromPath = getProjectStoragePath(projectDir);
|
|
35
|
-
const storageFromResolverPath = resolveProjectStoragePath(projectDir);
|
|
36
|
-
const storageFromResolverHash = resolveProjectStoragePath(projectHash);
|
|
37
|
-
|
|
38
|
-
expect(storageFromPath).toBe(storageFromResolverPath);
|
|
39
|
-
expect(storageFromResolverHash).toContain(path.join('.claude-code', 'memory', 'projects', projectHash));
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
describe('session registry utilities', () => {
|
|
44
|
-
afterEach(() => {
|
|
45
|
-
vi.resetModules();
|
|
46
|
-
vi.doUnmock('os');
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('registers and loads project mapping from the isolated home directory', async () => {
|
|
50
|
-
const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), 'cml-home-'));
|
|
51
|
-
const projectDir = path.join(tempHome, 'workspace', 'project');
|
|
52
|
-
await fs.mkdir(projectDir, { recursive: true });
|
|
53
|
-
|
|
54
|
-
vi.doMock('os', async () => {
|
|
55
|
-
const actual = await vi.importActual<typeof import('os')>('os');
|
|
56
|
-
return {
|
|
57
|
-
...actual,
|
|
58
|
-
homedir: () => tempHome
|
|
59
|
-
};
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
const registryModule = await import('../../src/core/registry/session-registry.js');
|
|
63
|
-
|
|
64
|
-
registryModule.registerSession('session-123', projectDir);
|
|
65
|
-
const projectInfo = registryModule.getSessionProject('session-123');
|
|
66
|
-
|
|
67
|
-
expect(projectInfo).not.toBeNull();
|
|
68
|
-
expect(projectInfo?.projectPath.endsWith('/workspace/project')).toBe(true);
|
|
69
|
-
expect(projectInfo?.projectHash).toBe(hashProjectPath(projectDir));
|
|
70
|
-
|
|
71
|
-
const registryPath = path.join(tempHome, '.claude-code', 'memory', 'session-registry.json');
|
|
72
|
-
const saved = JSON.parse(await fs.readFile(registryPath, 'utf8')) as {
|
|
73
|
-
sessions: Record<string, { projectPath: string }>;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
expect(saved.sessions['session-123']?.projectPath.endsWith('/workspace/project')).toBe(true);
|
|
77
|
-
});
|
|
78
|
-
});
|