@skillsmith/core 0.4.14 → 0.4.16
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 +2 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/analysis/DependencyMerger.d.ts +39 -0
- package/dist/src/analysis/DependencyMerger.d.ts.map +1 -0
- package/dist/src/analysis/DependencyMerger.js +191 -0
- package/dist/src/analysis/DependencyMerger.js.map +1 -0
- package/dist/src/analysis/DependencyMerger.test.d.ts +2 -0
- package/dist/src/analysis/DependencyMerger.test.d.ts.map +1 -0
- package/dist/src/analysis/DependencyMerger.test.js +258 -0
- package/dist/src/analysis/DependencyMerger.test.js.map +1 -0
- package/dist/src/analysis/McpReferenceExtractor.d.ts +42 -0
- package/dist/src/analysis/McpReferenceExtractor.d.ts.map +1 -0
- package/dist/src/analysis/McpReferenceExtractor.js +92 -0
- package/dist/src/analysis/McpReferenceExtractor.js.map +1 -0
- package/dist/src/analysis/McpReferenceExtractor.test.d.ts +2 -0
- package/dist/src/analysis/McpReferenceExtractor.test.d.ts.map +1 -0
- package/dist/src/analysis/McpReferenceExtractor.test.js +262 -0
- package/dist/src/analysis/McpReferenceExtractor.test.js.map +1 -0
- package/dist/src/api/client.d.ts +1 -0
- package/dist/src/api/client.d.ts.map +1 -1
- package/dist/src/api/client.health.d.ts +26 -0
- package/dist/src/api/client.health.d.ts.map +1 -0
- package/dist/src/api/client.health.js +74 -0
- package/dist/src/api/client.health.js.map +1 -0
- package/dist/src/api/client.js +3 -51
- package/dist/src/api/client.js.map +1 -1
- package/dist/src/api/schemas.d.ts +4 -4
- package/dist/src/db/createDatabase.d.ts +9 -1
- package/dist/src/db/createDatabase.d.ts.map +1 -1
- package/dist/src/db/createDatabase.js +9 -1
- package/dist/src/db/createDatabase.js.map +1 -1
- package/dist/src/db/drivers/sqljsDriver.d.ts.map +1 -1
- package/dist/src/db/drivers/sqljsDriver.js +7 -8
- package/dist/src/db/drivers/sqljsDriver.js.map +1 -1
- package/dist/src/db/migrations/v10-dependencies.d.ts +18 -0
- package/dist/src/db/migrations/v10-dependencies.d.ts.map +1 -0
- package/dist/src/db/migrations/v10-dependencies.js +50 -0
- package/dist/src/db/migrations/v10-dependencies.js.map +1 -0
- package/dist/src/db/migrations/v2-phase5-columns.d.ts +7 -0
- package/dist/src/db/migrations/v2-phase5-columns.d.ts.map +1 -0
- package/dist/src/db/migrations/v2-phase5-columns.js +16 -0
- package/dist/src/db/migrations/v2-phase5-columns.js.map +1 -0
- package/dist/src/db/migrations/v3-sync-tables.d.ts +6 -0
- package/dist/src/db/migrations/v3-sync-tables.d.ts.map +1 -0
- package/dist/src/db/migrations/v3-sync-tables.js +41 -0
- package/dist/src/db/migrations/v3-sync-tables.js.map +1 -0
- package/dist/src/db/migrations/v4-security-columns.d.ts +7 -0
- package/dist/src/db/migrations/v4-security-columns.d.ts.map +1 -0
- package/dist/src/db/migrations/v4-security-columns.js +17 -0
- package/dist/src/db/migrations/v4-security-columns.js.map +1 -0
- package/dist/src/db/migrations/v5b-change-type.d.ts +19 -0
- package/dist/src/db/migrations/v5b-change-type.d.ts.map +1 -0
- package/dist/src/db/migrations/v5b-change-type.js +22 -0
- package/dist/src/db/migrations/v5b-change-type.js.map +1 -0
- package/dist/src/db/migrations/v6-advisories.d.ts +32 -0
- package/dist/src/db/migrations/v6-advisories.d.ts.map +1 -0
- package/dist/src/db/migrations/v6-advisories.js +53 -0
- package/dist/src/db/migrations/v6-advisories.js.map +1 -0
- package/dist/src/db/migrations/v7-compatibility.d.ts +21 -0
- package/dist/src/db/migrations/v7-compatibility.d.ts.map +1 -0
- package/dist/src/db/migrations/v7-compatibility.js +23 -0
- package/dist/src/db/migrations/v7-compatibility.js.map +1 -0
- package/dist/src/db/migrations/v8-co-installs.d.ts +21 -0
- package/dist/src/db/migrations/v8-co-installs.d.ts.map +1 -0
- package/dist/src/db/migrations/v8-co-installs.js +33 -0
- package/dist/src/db/migrations/v8-co-installs.js.map +1 -0
- package/dist/src/db/schema.d.ts +5 -16
- package/dist/src/db/schema.d.ts.map +1 -1
- package/dist/src/db/schema.js +50 -79
- package/dist/src/db/schema.js.map +1 -1
- package/dist/src/exports/repositories.d.ts +6 -0
- package/dist/src/exports/repositories.d.ts.map +1 -1
- package/dist/src/exports/repositories.js +21 -0
- package/dist/src/exports/repositories.js.map +1 -1
- package/dist/src/exports/services.d.ts +2 -0
- package/dist/src/exports/services.d.ts.map +1 -1
- package/dist/src/exports/services.js +5 -0
- package/dist/src/exports/services.js.map +1 -1
- package/dist/src/exports/types.d.ts +2 -1
- package/dist/src/exports/types.d.ts.map +1 -1
- package/dist/src/exports/types.js.map +1 -1
- package/dist/src/indexer/GitHubIndexer.d.ts +3 -1
- package/dist/src/indexer/GitHubIndexer.d.ts.map +1 -1
- package/dist/src/indexer/GitHubIndexer.js.map +1 -1
- package/dist/src/indexer/SkillParser.d.ts +22 -9
- package/dist/src/indexer/SkillParser.d.ts.map +1 -1
- package/dist/src/indexer/SkillParser.js +17 -10
- package/dist/src/indexer/SkillParser.js.map +1 -1
- package/dist/src/learning/PatternStore.d.ts +0 -2
- package/dist/src/learning/PatternStore.d.ts.map +1 -1
- package/dist/src/learning/PatternStore.helpers.d.ts +19 -1
- package/dist/src/learning/PatternStore.helpers.d.ts.map +1 -1
- package/dist/src/learning/PatternStore.helpers.js +51 -0
- package/dist/src/learning/PatternStore.helpers.js.map +1 -1
- package/dist/src/learning/PatternStore.js +5 -37
- package/dist/src/learning/PatternStore.js.map +1 -1
- package/dist/src/repositories/AdvisoryRepository.d.ts +80 -0
- package/dist/src/repositories/AdvisoryRepository.d.ts.map +1 -0
- package/dist/src/repositories/AdvisoryRepository.js +128 -0
- package/dist/src/repositories/AdvisoryRepository.js.map +1 -0
- package/dist/src/repositories/AdvisoryRepository.test.d.ts +6 -0
- package/dist/src/repositories/AdvisoryRepository.test.d.ts.map +1 -0
- package/dist/src/repositories/AdvisoryRepository.test.js +149 -0
- package/dist/src/repositories/AdvisoryRepository.test.js.map +1 -0
- package/dist/src/repositories/CoInstallRepository.d.ts +68 -0
- package/dist/src/repositories/CoInstallRepository.d.ts.map +1 -0
- package/dist/src/repositories/CoInstallRepository.js +122 -0
- package/dist/src/repositories/CoInstallRepository.js.map +1 -0
- package/dist/src/repositories/IndexerRepository.d.ts.map +1 -1
- package/dist/src/repositories/IndexerRepository.js +5 -1
- package/dist/src/repositories/IndexerRepository.js.map +1 -1
- package/dist/src/repositories/SkillDependencyRepository.d.ts +73 -0
- package/dist/src/repositories/SkillDependencyRepository.d.ts.map +1 -0
- package/dist/src/repositories/SkillDependencyRepository.js +199 -0
- package/dist/src/repositories/SkillDependencyRepository.js.map +1 -0
- package/dist/src/repositories/SkillRepository.d.ts.map +1 -1
- package/dist/src/repositories/SkillRepository.js +16 -5
- package/dist/src/repositories/SkillRepository.js.map +1 -1
- package/dist/src/scripts/validation/types.d.ts +2 -2
- package/dist/src/services/SearchService.helpers.d.ts.map +1 -1
- package/dist/src/services/SearchService.helpers.js +4 -0
- package/dist/src/services/SearchService.helpers.js.map +1 -1
- package/dist/src/services/SearchService.types.d.ts +1 -0
- package/dist/src/services/SearchService.types.d.ts.map +1 -1
- package/dist/src/services/TaskRunner.d.ts +5 -81
- package/dist/src/services/TaskRunner.d.ts.map +1 -1
- package/dist/src/services/TaskRunner.js +7 -68
- package/dist/src/services/TaskRunner.js.map +1 -1
- package/dist/src/services/TaskRunner.process.d.ts +33 -0
- package/dist/src/services/TaskRunner.process.d.ts.map +1 -0
- package/dist/src/services/TaskRunner.process.js +70 -0
- package/dist/src/services/TaskRunner.process.js.map +1 -0
- package/dist/src/services/TaskRunner.types.d.ts +76 -0
- package/dist/src/services/TaskRunner.types.d.ts.map +1 -0
- package/dist/src/services/TaskRunner.types.js +22 -0
- package/dist/src/services/TaskRunner.types.js.map +1 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.d.ts +13 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.d.ts.map +1 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.js +91 -0
- package/dist/src/services/__tests__/TaskRunner.process.test.js.map +1 -0
- package/dist/src/services/quarantine/QuarantineService.d.ts +3 -24
- package/dist/src/services/quarantine/QuarantineService.d.ts.map +1 -1
- package/dist/src/services/quarantine/QuarantineService.js +8 -205
- package/dist/src/services/quarantine/QuarantineService.js.map +1 -1
- package/dist/src/services/quarantine/QuarantineService.multiapproval.d.ts +57 -0
- package/dist/src/services/quarantine/QuarantineService.multiapproval.d.ts.map +1 -0
- package/dist/src/services/quarantine/QuarantineService.multiapproval.js +211 -0
- package/dist/src/services/quarantine/QuarantineService.multiapproval.js.map +1 -0
- package/dist/src/session/SessionManager.d.ts +2 -33
- package/dist/src/session/SessionManager.d.ts.map +1 -1
- package/dist/src/session/SessionManager.js +14 -238
- package/dist/src/session/SessionManager.js.map +1 -1
- package/dist/src/session/SessionManager.memory.d.ts +67 -0
- package/dist/src/session/SessionManager.memory.d.ts.map +1 -0
- package/dist/src/session/SessionManager.memory.js +262 -0
- package/dist/src/session/SessionManager.memory.js.map +1 -0
- package/dist/src/sources/SourceIndexer.d.ts +3 -1
- package/dist/src/sources/SourceIndexer.d.ts.map +1 -1
- package/dist/src/sources/SourceIndexer.js.map +1 -1
- package/dist/src/sync/SyncEngine.d.ts +13 -1
- package/dist/src/sync/SyncEngine.d.ts.map +1 -1
- package/dist/src/sync/SyncEngine.js +50 -1
- package/dist/src/sync/SyncEngine.js.map +1 -1
- package/dist/src/testing/MultiLLMProvider.d.ts +5 -6
- package/dist/src/testing/MultiLLMProvider.d.ts.map +1 -1
- package/dist/src/testing/MultiLLMProvider.js +18 -130
- package/dist/src/testing/MultiLLMProvider.js.map +1 -1
- package/dist/src/testing/MultiLLMProvider.metrics.d.ts +33 -0
- package/dist/src/testing/MultiLLMProvider.metrics.d.ts.map +1 -0
- package/dist/src/testing/MultiLLMProvider.metrics.js +87 -0
- package/dist/src/testing/MultiLLMProvider.metrics.js.map +1 -0
- package/dist/src/testing/MultiLLMProvider.selection.d.ts +77 -0
- package/dist/src/testing/MultiLLMProvider.selection.d.ts.map +1 -0
- package/dist/src/testing/MultiLLMProvider.selection.js +151 -0
- package/dist/src/testing/MultiLLMProvider.selection.js.map +1 -0
- package/dist/src/types/dependencies.d.ts +85 -0
- package/dist/src/types/dependencies.d.ts.map +1 -0
- package/dist/src/types/dependencies.js +11 -0
- package/dist/src/types/dependencies.js.map +1 -0
- package/dist/src/types/skill.d.ts +13 -0
- package/dist/src/types/skill.d.ts.map +1 -1
- package/dist/src/types/skill.js.map +1 -1
- package/dist/src/types.d.ts +32 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/versioning/change-classifier.d.ts +38 -0
- package/dist/src/versioning/change-classifier.d.ts.map +1 -0
- package/dist/src/versioning/change-classifier.js +187 -0
- package/dist/src/versioning/change-classifier.js.map +1 -0
- package/dist/src/versioning/change-classifier.test.d.ts +6 -0
- package/dist/src/versioning/change-classifier.test.d.ts.map +1 -0
- package/dist/src/versioning/change-classifier.test.js +275 -0
- package/dist/src/versioning/change-classifier.test.js.map +1 -0
- package/dist/src/versioning/update-risk.d.ts +50 -0
- package/dist/src/versioning/update-risk.d.ts.map +1 -0
- package/dist/src/versioning/update-risk.js +80 -0
- package/dist/src/versioning/update-risk.js.map +1 -0
- package/dist/src/versioning/update-risk.test.d.ts +6 -0
- package/dist/src/versioning/update-risk.test.d.ts.map +1 -0
- package/dist/src/versioning/update-risk.test.js +200 -0
- package/dist/src/versioning/update-risk.test.js.map +1 -0
- package/dist/tests/AuditLogger.edge-cases.test.d.ts +10 -0
- package/dist/tests/AuditLogger.edge-cases.test.d.ts.map +1 -0
- package/dist/tests/AuditLogger.edge-cases.test.js +183 -0
- package/dist/tests/AuditLogger.edge-cases.test.js.map +1 -0
- package/dist/tests/CacheManager.test.d.ts +9 -0
- package/dist/tests/CacheManager.test.d.ts.map +1 -0
- package/dist/tests/CacheManager.test.js +163 -0
- package/dist/tests/CacheManager.test.js.map +1 -0
- package/dist/tests/DailyIndexPipeline.test.js +3 -3
- package/dist/tests/DailyIndexPipeline.test.js.map +1 -1
- package/dist/tests/GitHubIndexer.edge-cases.test.d.ts +10 -0
- package/dist/tests/GitHubIndexer.edge-cases.test.d.ts.map +1 -0
- package/dist/tests/GitHubIndexer.edge-cases.test.js +255 -0
- package/dist/tests/GitHubIndexer.edge-cases.test.js.map +1 -0
- package/dist/tests/GitHubIndexer.test.js +4 -2
- package/dist/tests/GitHubIndexer.test.js.map +1 -1
- package/dist/tests/SearchService.test.js +71 -0
- package/dist/tests/SearchService.test.js.map +1 -1
- package/dist/tests/SkillVersionRepository.test.d.ts +0 -11
- package/dist/tests/SkillVersionRepository.test.d.ts.map +1 -1
- package/dist/tests/SkillVersionRepository.test.js +131 -194
- package/dist/tests/SkillVersionRepository.test.js.map +1 -1
- package/dist/tests/api/client.health.test.d.ts +15 -0
- package/dist/tests/api/client.health.test.d.ts.map +1 -0
- package/dist/tests/api/client.health.test.js +111 -0
- package/dist/tests/api/client.health.test.js.map +1 -0
- package/dist/tests/db/betterSqlite3Driver.test.d.ts +8 -0
- package/dist/tests/db/betterSqlite3Driver.test.d.ts.map +1 -0
- package/dist/tests/db/betterSqlite3Driver.test.js +88 -0
- package/dist/tests/db/betterSqlite3Driver.test.js.map +1 -0
- package/dist/tests/db/database-abstraction.test.js +12 -0
- package/dist/tests/db/database-abstraction.test.js.map +1 -1
- package/dist/tests/db/schema-migrations.test.d.ts +10 -0
- package/dist/tests/db/schema-migrations.test.d.ts.map +1 -0
- package/dist/tests/db/schema-migrations.test.js +134 -0
- package/dist/tests/db/schema-migrations.test.js.map +1 -0
- package/dist/tests/db/sqljsDriver.test.d.ts +9 -0
- package/dist/tests/db/sqljsDriver.test.d.ts.map +1 -0
- package/dist/tests/db/sqljsDriver.test.js +75 -0
- package/dist/tests/db/sqljsDriver.test.js.map +1 -0
- package/dist/tests/edge-cases/EdgeCases.test.js +4 -1
- package/dist/tests/edge-cases/EdgeCases.test.js.map +1 -1
- package/dist/tests/helpers/database.d.ts +32 -0
- package/dist/tests/helpers/database.d.ts.map +1 -0
- package/dist/tests/helpers/database.js +54 -0
- package/dist/tests/helpers/database.js.map +1 -0
- package/dist/tests/learning/PatternStore.helpers.test.d.ts +17 -0
- package/dist/tests/learning/PatternStore.helpers.test.d.ts.map +1 -0
- package/dist/tests/learning/PatternStore.helpers.test.js +301 -0
- package/dist/tests/learning/PatternStore.helpers.test.js.map +1 -0
- package/dist/tests/repositories/CoInstallRepository.test.d.ts +9 -0
- package/dist/tests/repositories/CoInstallRepository.test.d.ts.map +1 -0
- package/dist/tests/repositories/CoInstallRepository.test.js +126 -0
- package/dist/tests/repositories/CoInstallRepository.test.js.map +1 -0
- package/dist/tests/repositories/SkillDependencyRepository.test.d.ts +10 -0
- package/dist/tests/repositories/SkillDependencyRepository.test.d.ts.map +1 -0
- package/dist/tests/repositories/SkillDependencyRepository.test.js +336 -0
- package/dist/tests/repositories/SkillDependencyRepository.test.js.map +1 -0
- package/dist/tests/routing/LanguageRouter.test.d.ts +9 -0
- package/dist/tests/routing/LanguageRouter.test.d.ts.map +1 -0
- package/dist/tests/routing/LanguageRouter.test.js +150 -0
- package/dist/tests/routing/LanguageRouter.test.js.map +1 -0
- package/dist/tests/session/SessionManager.memory.test.d.ts +11 -0
- package/dist/tests/session/SessionManager.memory.test.d.ts.map +1 -0
- package/dist/tests/session/SessionManager.memory.test.js +219 -0
- package/dist/tests/session/SessionManager.memory.test.js.map +1 -0
- package/dist/tests/sources.test.js +1 -1
- package/dist/tests/sources.test.js.map +1 -1
- package/dist/tests/sync/SyncEngine.test.js +32 -18
- package/dist/tests/sync/SyncEngine.test.js.map +1 -1
- package/dist/tests/testing/MultiLLMProvider.metrics.test.d.ts +13 -0
- package/dist/tests/testing/MultiLLMProvider.metrics.test.d.ts.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.metrics.test.js +149 -0
- package/dist/tests/testing/MultiLLMProvider.metrics.test.js.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.d.ts +15 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.d.ts.map +1 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.js +249 -0
- package/dist/tests/testing/MultiLLMProvider.selection.test.js.map +1 -0
- package/dist/tests/unit/migrations/v10-dependencies.test.d.ts +6 -0
- package/dist/tests/unit/migrations/v10-dependencies.test.d.ts.map +1 -0
- package/dist/tests/unit/migrations/v10-dependencies.test.js +166 -0
- package/dist/tests/unit/migrations/v10-dependencies.test.js.map +1 -0
- package/dist/tests/unit/quarantine-query-builder.test.d.ts +10 -0
- package/dist/tests/unit/quarantine-query-builder.test.d.ts.map +1 -0
- package/dist/tests/unit/quarantine-query-builder.test.js +157 -0
- package/dist/tests/unit/quarantine-query-builder.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Test database helpers — prevents "no such table" for migrated tables
|
|
3
|
+
* @see SMI-2749
|
|
4
|
+
*
|
|
5
|
+
* Use createTestDatabase() instead of createDatabase(':memory:') whenever tests
|
|
6
|
+
* need tables that only exist in migration files (e.g. skill_versions).
|
|
7
|
+
*
|
|
8
|
+
* WHY THIS EXISTS:
|
|
9
|
+
* createDatabase(':memory:') calls initializeSchema(), which records SCHEMA_VERSION=5
|
|
10
|
+
* directly in schema_version WITHOUT running the intermediate migration SQLs.
|
|
11
|
+
* runMigrations() then sees version=5 and skips all migrations — a no-op.
|
|
12
|
+
* Tables defined only in migration SQL (not in SCHEMA_SQL) are never created.
|
|
13
|
+
* Example: skill_versions is in MIGRATION_V5_SQL, not SCHEMA_SQL.
|
|
14
|
+
*
|
|
15
|
+
* createTestDatabase() iterates MIGRATIONS directly (no version gate) so every
|
|
16
|
+
* migration's SQL runs unconditionally. New migrations added to MIGRATIONS are
|
|
17
|
+
* automatically included — no change required here.
|
|
18
|
+
*/
|
|
19
|
+
import { createDatabase, MIGRATIONS } from '../../src/db/schema.js';
|
|
20
|
+
// Re-exported for test convenience — tests only need to import from this module
|
|
21
|
+
export { closeDatabase } from '../../src/db/schema.js';
|
|
22
|
+
/**
|
|
23
|
+
* Create an in-memory SQLite database with ALL schema + migrations applied.
|
|
24
|
+
*
|
|
25
|
+
* Safe to use for any test that needs migrated tables (e.g. skill_versions,
|
|
26
|
+
* sync_config, sync_history). Forward-compatible: new migrations added to
|
|
27
|
+
* MIGRATIONS are included automatically.
|
|
28
|
+
*
|
|
29
|
+
* @returns Database with full schema + all migrations applied
|
|
30
|
+
*/
|
|
31
|
+
export function createTestDatabase() {
|
|
32
|
+
// createDatabase() calls initializeSchema() — runs SCHEMA_SQL (handling FTS5 triggers
|
|
33
|
+
// and multi-statement SQL correctly) and stamps SCHEMA_VERSION in schema_version.
|
|
34
|
+
const db = createDatabase();
|
|
35
|
+
// Run all migrations unconditionally (no version gate) so tables that only exist in
|
|
36
|
+
// migration SQL (not SCHEMA_SQL) are created. db.exec() handles multi-statement SQL
|
|
37
|
+
// natively — no semicolon split needed.
|
|
38
|
+
//
|
|
39
|
+
// "duplicate column" errors are caught: some migration SQL adds columns that are
|
|
40
|
+
// already included in the canonical SCHEMA_SQL. Those errors are expected and safe.
|
|
41
|
+
for (const migration of MIGRATIONS) {
|
|
42
|
+
try {
|
|
43
|
+
db.exec(migration.sql);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
47
|
+
if (!msg.includes('duplicate column'))
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
db.prepare('INSERT OR REPLACE INTO schema_version (version) VALUES (?)').run(migration.version);
|
|
51
|
+
}
|
|
52
|
+
return db;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../../tests/helpers/database.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAGnE,gFAAgF;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAGtD;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB;IAChC,sFAAsF;IACtF,kFAAkF;IAClF,MAAM,EAAE,GAAG,cAAc,EAAE,CAAA;IAE3B,oFAAoF;IACpF,oFAAoF;IACpF,wCAAwC;IACxC,EAAE;IACF,iFAAiF;IACjF,oFAAoF;IACpF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAClE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC;gBAAE,MAAM,KAAK,CAAA;QACpD,CAAC;QACD,EAAE,CAAC,OAAO,CAAC,4DAA4D,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IACjG,CAAC;IAED,OAAO,EAAE,CAAA;AACX,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-2754: PatternStore Helper Functions Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests covering pure math functions, FisherInformationMatrix,
|
|
5
|
+
* and DB-touching helpers extracted to PatternStore.helpers.ts.
|
|
6
|
+
*
|
|
7
|
+
* Categories:
|
|
8
|
+
* - FisherInformationMatrix: construct, update, accumulate, decay,
|
|
9
|
+
* serialize/deserialize round-trip, reset, invalid buffer size
|
|
10
|
+
* - contextToText: empty, partial, full context
|
|
11
|
+
* - computeGradient, cosineSimilarity, importanceWeightedSimilarity (zero-norm edge)
|
|
12
|
+
* - calculatePatternImportance: positive and negative reward
|
|
13
|
+
* - shouldConsolidate: too recent, no patterns, ratio threshold, near max patterns
|
|
14
|
+
* - computeAverageEmbedding: empty table → zero vector, populated → average
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=PatternStore.helpers.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PatternStore.helpers.test.d.ts","sourceRoot":"","sources":["../../../tests/learning/PatternStore.helpers.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-2754: PatternStore Helper Functions Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests covering pure math functions, FisherInformationMatrix,
|
|
5
|
+
* and DB-touching helpers extracted to PatternStore.helpers.ts.
|
|
6
|
+
*
|
|
7
|
+
* Categories:
|
|
8
|
+
* - FisherInformationMatrix: construct, update, accumulate, decay,
|
|
9
|
+
* serialize/deserialize round-trip, reset, invalid buffer size
|
|
10
|
+
* - contextToText: empty, partial, full context
|
|
11
|
+
* - computeGradient, cosineSimilarity, importanceWeightedSimilarity (zero-norm edge)
|
|
12
|
+
* - calculatePatternImportance: positive and negative reward
|
|
13
|
+
* - shouldConsolidate: too recent, no patterns, ratio threshold, near max patterns
|
|
14
|
+
* - computeAverageEmbedding: empty table → zero vector, populated → average
|
|
15
|
+
*/
|
|
16
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
17
|
+
import { FisherInformationMatrix, contextToText, computeGradient, cosineSimilarity, importanceWeightedSimilarity, calculatePatternImportance, shouldConsolidate, computeAverageEmbedding, PATTERN_STORE_SCHEMA, } from '../../src/learning/PatternStore.helpers.js';
|
|
18
|
+
import { createDatabase } from '../../src/db/createDatabase.js';
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// FisherInformationMatrix
|
|
21
|
+
// ============================================================================
|
|
22
|
+
describe('FisherInformationMatrix', () => {
|
|
23
|
+
it('constructs with zero importance vector', () => {
|
|
24
|
+
const fim = new FisherInformationMatrix(4);
|
|
25
|
+
expect(fim.getImportanceVector()).toEqual(new Float32Array(4));
|
|
26
|
+
expect(fim.getUpdateCount()).toBe(0);
|
|
27
|
+
expect(fim.getAverageImportance()).toBe(0);
|
|
28
|
+
});
|
|
29
|
+
it('updates importance from a gradient', () => {
|
|
30
|
+
const fim = new FisherInformationMatrix(3);
|
|
31
|
+
const gradient = new Float32Array([1.0, 2.0, 0.0]);
|
|
32
|
+
fim.update(gradient);
|
|
33
|
+
expect(fim.getUpdateCount()).toBe(1);
|
|
34
|
+
// importance = runningSum / updateCount = [1, 4, 0] / 1
|
|
35
|
+
expect(fim.getImportance(0)).toBeCloseTo(1.0);
|
|
36
|
+
expect(fim.getImportance(1)).toBeCloseTo(4.0);
|
|
37
|
+
expect(fim.getImportance(2)).toBeCloseTo(0.0);
|
|
38
|
+
});
|
|
39
|
+
it('accumulates importance over multiple updates', () => {
|
|
40
|
+
const fim = new FisherInformationMatrix(2);
|
|
41
|
+
fim.update(new Float32Array([2.0, 0.0]));
|
|
42
|
+
fim.update(new Float32Array([2.0, 0.0]));
|
|
43
|
+
// runningSum = [4+4, 0] = [8, 0]; importance = [8/2, 0/2] = [4, 0]
|
|
44
|
+
expect(fim.getImportance(0)).toBeCloseTo(4.0);
|
|
45
|
+
expect(fim.getUpdateCount()).toBe(2);
|
|
46
|
+
});
|
|
47
|
+
it('decays importance by decayFactor', () => {
|
|
48
|
+
const fim = new FisherInformationMatrix(2);
|
|
49
|
+
fim.update(new Float32Array([2.0, 4.0]));
|
|
50
|
+
// After update: runningSum=[4, 16], importance=[4, 16]
|
|
51
|
+
fim.decay(0.5);
|
|
52
|
+
// runningSum=[2, 8]; importance = [2, 8] / max(1, 1) = [2, 8]
|
|
53
|
+
expect(fim.getImportance(0)).toBeCloseTo(2.0);
|
|
54
|
+
expect(fim.getImportance(1)).toBeCloseTo(8.0);
|
|
55
|
+
});
|
|
56
|
+
it('serialize and deserialize round-trip preserves values', () => {
|
|
57
|
+
const fim = new FisherInformationMatrix(3);
|
|
58
|
+
fim.update(new Float32Array([1.0, 2.0, 3.0]));
|
|
59
|
+
fim.update(new Float32Array([0.5, 1.0, 1.5]));
|
|
60
|
+
const buffer = fim.serialize();
|
|
61
|
+
const fim2 = new FisherInformationMatrix(3);
|
|
62
|
+
fim2.deserialize(buffer);
|
|
63
|
+
expect(fim2.getUpdateCount()).toBe(2);
|
|
64
|
+
// Values should match within float32 precision
|
|
65
|
+
for (let i = 0; i < 3; i++) {
|
|
66
|
+
expect(fim2.getImportance(i)).toBeCloseTo(fim.getImportance(i), 4);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
it('reset clears all values to zero', () => {
|
|
70
|
+
const fim = new FisherInformationMatrix(3);
|
|
71
|
+
fim.update(new Float32Array([1.0, 2.0, 3.0]));
|
|
72
|
+
fim.reset();
|
|
73
|
+
expect(fim.getUpdateCount()).toBe(0);
|
|
74
|
+
expect(fim.getAverageImportance()).toBe(0);
|
|
75
|
+
expect(fim.getImportance(0)).toBe(0);
|
|
76
|
+
});
|
|
77
|
+
it('throws when deserializing buffer that is too small', () => {
|
|
78
|
+
const fim = new FisherInformationMatrix(4);
|
|
79
|
+
const tooSmall = Buffer.alloc(4); // way smaller than needed
|
|
80
|
+
expect(() => fim.deserialize(tooSmall)).toThrow(/Invalid Fisher matrix buffer/);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// contextToText
|
|
85
|
+
// ============================================================================
|
|
86
|
+
describe('contextToText', () => {
|
|
87
|
+
it('returns "empty context" for an empty context object', () => {
|
|
88
|
+
const ctx = { installedSkills: [] };
|
|
89
|
+
expect(contextToText(ctx)).toBe('empty context');
|
|
90
|
+
});
|
|
91
|
+
it('returns partial text when only some fields are set', () => {
|
|
92
|
+
const ctx = {
|
|
93
|
+
installedSkills: ['anthropic/commit'],
|
|
94
|
+
timeOfDay: 'morning',
|
|
95
|
+
};
|
|
96
|
+
const text = contextToText(ctx);
|
|
97
|
+
expect(text).toContain('installed: anthropic/commit');
|
|
98
|
+
expect(text).toContain('time: morning');
|
|
99
|
+
expect(text).not.toContain('frameworks');
|
|
100
|
+
});
|
|
101
|
+
it('returns all fields when all are set', () => {
|
|
102
|
+
const ctx = {
|
|
103
|
+
installedSkills: ['anthropic/commit', 'community/jest'],
|
|
104
|
+
frameworks: ['react', 'typescript'],
|
|
105
|
+
keywords: ['testing'],
|
|
106
|
+
timeOfDay: 'afternoon',
|
|
107
|
+
dayType: 'weekday',
|
|
108
|
+
};
|
|
109
|
+
const text = contextToText(ctx);
|
|
110
|
+
expect(text).toContain('installed: anthropic/commit, community/jest');
|
|
111
|
+
expect(text).toContain('frameworks: react, typescript');
|
|
112
|
+
expect(text).toContain('keywords: testing');
|
|
113
|
+
expect(text).toContain('time: afternoon');
|
|
114
|
+
expect(text).toContain('day: weekday');
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
// ============================================================================
|
|
118
|
+
// computeGradient
|
|
119
|
+
// ============================================================================
|
|
120
|
+
describe('computeGradient', () => {
|
|
121
|
+
it('computes element-wise difference a - b', () => {
|
|
122
|
+
const a = new Float32Array([3.0, 1.0, 2.0]);
|
|
123
|
+
const b = new Float32Array([1.0, 2.0, 1.0]);
|
|
124
|
+
const gradient = computeGradient(a, b);
|
|
125
|
+
expect(gradient[0]).toBeCloseTo(2.0);
|
|
126
|
+
expect(gradient[1]).toBeCloseTo(-1.0);
|
|
127
|
+
expect(gradient[2]).toBeCloseTo(1.0);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
// ============================================================================
|
|
131
|
+
// cosineSimilarity
|
|
132
|
+
// ============================================================================
|
|
133
|
+
describe('cosineSimilarity', () => {
|
|
134
|
+
it('returns 1.0 for identical non-zero vectors', () => {
|
|
135
|
+
const a = new Float32Array([1.0, 0.0, 0.0]);
|
|
136
|
+
expect(cosineSimilarity(a, a)).toBeCloseTo(1.0);
|
|
137
|
+
});
|
|
138
|
+
it('returns 0 for orthogonal vectors', () => {
|
|
139
|
+
const a = new Float32Array([1.0, 0.0]);
|
|
140
|
+
const b = new Float32Array([0.0, 1.0]);
|
|
141
|
+
expect(cosineSimilarity(a, b)).toBeCloseTo(0.0);
|
|
142
|
+
});
|
|
143
|
+
it('returns 0 when either vector is all zeros (zero-norm edge case)', () => {
|
|
144
|
+
const zero = new Float32Array([0.0, 0.0]);
|
|
145
|
+
const a = new Float32Array([1.0, 2.0]);
|
|
146
|
+
expect(cosineSimilarity(zero, a)).toBe(0);
|
|
147
|
+
expect(cosineSimilarity(a, zero)).toBe(0);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
// ============================================================================
|
|
151
|
+
// importanceWeightedSimilarity
|
|
152
|
+
// ============================================================================
|
|
153
|
+
describe('importanceWeightedSimilarity', () => {
|
|
154
|
+
it('computes weighted similarity between two identical vectors', () => {
|
|
155
|
+
const a = new Float32Array([1.0, 0.0]);
|
|
156
|
+
const importance = new Float32Array([1.0, 0.0]);
|
|
157
|
+
const result = importanceWeightedSimilarity(a, a, importance);
|
|
158
|
+
expect(result).toBeCloseTo(1.0);
|
|
159
|
+
});
|
|
160
|
+
it('returns 0 when the weighted norms are zero (zero-norm edge case)', () => {
|
|
161
|
+
const zero = new Float32Array([0.0, 0.0]);
|
|
162
|
+
const importance = new Float32Array([1.0, 1.0]);
|
|
163
|
+
const result = importanceWeightedSimilarity(zero, zero, importance);
|
|
164
|
+
expect(result).toBe(0);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// calculatePatternImportance
|
|
169
|
+
// ============================================================================
|
|
170
|
+
function makeStoredPattern(reward) {
|
|
171
|
+
return {
|
|
172
|
+
id: 'test-id',
|
|
173
|
+
context: { installedSkills: [] },
|
|
174
|
+
skill: {
|
|
175
|
+
skillId: 'community/test',
|
|
176
|
+
category: 'testing',
|
|
177
|
+
trustTier: 'community',
|
|
178
|
+
keywords: [],
|
|
179
|
+
qualityScore: 80,
|
|
180
|
+
installCount: 100,
|
|
181
|
+
},
|
|
182
|
+
originalScore: 0.8,
|
|
183
|
+
source: 'recommend',
|
|
184
|
+
contextEmbedding: new Float32Array([0.1, 0.2]),
|
|
185
|
+
outcome: { type: reward >= 0 ? 'accept' : 'dismiss', reward },
|
|
186
|
+
importance: 0.5,
|
|
187
|
+
accessCount: 3,
|
|
188
|
+
createdAt: new Date(),
|
|
189
|
+
lastAccessedAt: new Date(),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
describe('calculatePatternImportance', () => {
|
|
193
|
+
it('gives higher importance for positive reward (1.5x multiplier)', () => {
|
|
194
|
+
const pattern = makeStoredPattern(1.0);
|
|
195
|
+
const outcome = { type: 'accept', reward: 1.0 };
|
|
196
|
+
const importance = calculatePatternImportance(pattern, outcome);
|
|
197
|
+
// baseImportance = 1.0 * 1.5 = 1.5, times other factors
|
|
198
|
+
expect(importance).toBeGreaterThan(0);
|
|
199
|
+
});
|
|
200
|
+
it('gives lower importance for negative reward (no 1.5x multiplier)', () => {
|
|
201
|
+
const positivePattern = makeStoredPattern(1.0);
|
|
202
|
+
const negativePattern = makeStoredPattern(-0.5);
|
|
203
|
+
const positiveOutcome = { type: 'accept', reward: 1.0 };
|
|
204
|
+
const negativeOutcome = { type: 'dismiss', reward: -0.5 };
|
|
205
|
+
const importancePos = calculatePatternImportance(positivePattern, positiveOutcome);
|
|
206
|
+
const importanceNeg = calculatePatternImportance(negativePattern, negativeOutcome);
|
|
207
|
+
// positive reward has 1.5x boost, so its importance should be higher
|
|
208
|
+
expect(importancePos).toBeGreaterThan(importanceNeg);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
// ============================================================================
|
|
212
|
+
// shouldConsolidate
|
|
213
|
+
// ============================================================================
|
|
214
|
+
function makeConsolidationState(overrides = {}) {
|
|
215
|
+
return {
|
|
216
|
+
totalPatterns: 100,
|
|
217
|
+
patternsSinceLastConsolidation: 5,
|
|
218
|
+
lastConsolidation: null,
|
|
219
|
+
...overrides,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
const ewcConfig = {
|
|
223
|
+
lambda: 5.0,
|
|
224
|
+
fisherDecay: 0.95,
|
|
225
|
+
importanceThreshold: 0.01,
|
|
226
|
+
fisherSampleSize: 100,
|
|
227
|
+
consolidationThreshold: 0.1,
|
|
228
|
+
maxPatterns: 1000,
|
|
229
|
+
};
|
|
230
|
+
describe('shouldConsolidate', () => {
|
|
231
|
+
it('returns false when last consolidation was less than 1 hour ago', () => {
|
|
232
|
+
const state = makeConsolidationState({
|
|
233
|
+
lastConsolidation: new Date(Date.now() - 30 * 60 * 1000), // 30 min ago
|
|
234
|
+
totalPatterns: 200,
|
|
235
|
+
patternsSinceLastConsolidation: 50,
|
|
236
|
+
});
|
|
237
|
+
expect(shouldConsolidate(state, ewcConfig)).toBe(false);
|
|
238
|
+
});
|
|
239
|
+
it('returns false when totalPatterns is 0', () => {
|
|
240
|
+
const state = makeConsolidationState({ totalPatterns: 0, patternsSinceLastConsolidation: 0 });
|
|
241
|
+
expect(shouldConsolidate(state, ewcConfig)).toBe(false);
|
|
242
|
+
});
|
|
243
|
+
it('returns true when newPatternsRatio exceeds consolidationThreshold', () => {
|
|
244
|
+
// 20/100 = 0.2 > 0.1 threshold
|
|
245
|
+
const state = makeConsolidationState({
|
|
246
|
+
totalPatterns: 100,
|
|
247
|
+
patternsSinceLastConsolidation: 20,
|
|
248
|
+
lastConsolidation: new Date(Date.now() - 2 * 60 * 60 * 1000), // 2 hours ago
|
|
249
|
+
});
|
|
250
|
+
expect(shouldConsolidate(state, ewcConfig)).toBe(true);
|
|
251
|
+
});
|
|
252
|
+
it('returns true when totalPatterns > 90% of maxPatterns', () => {
|
|
253
|
+
const state = makeConsolidationState({
|
|
254
|
+
totalPatterns: 950, // > 1000 * 0.9 = 900
|
|
255
|
+
patternsSinceLastConsolidation: 5, // ratio = 5/950 < 0.1
|
|
256
|
+
lastConsolidation: new Date(Date.now() - 2 * 60 * 60 * 1000),
|
|
257
|
+
});
|
|
258
|
+
expect(shouldConsolidate(state, ewcConfig)).toBe(true);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
// ============================================================================
|
|
262
|
+
// computeAverageEmbedding (requires in-memory SQLite)
|
|
263
|
+
// ============================================================================
|
|
264
|
+
describe('computeAverageEmbedding', () => {
|
|
265
|
+
let db;
|
|
266
|
+
beforeEach(() => {
|
|
267
|
+
db = createDatabase(':memory:');
|
|
268
|
+
db.exec(PATTERN_STORE_SCHEMA);
|
|
269
|
+
});
|
|
270
|
+
afterEach(() => {
|
|
271
|
+
db.close();
|
|
272
|
+
});
|
|
273
|
+
it('returns zero vector when the patterns table is empty', async () => {
|
|
274
|
+
const result = await computeAverageEmbedding(db, 100, 4);
|
|
275
|
+
expect(result).toEqual(new Float32Array(4));
|
|
276
|
+
});
|
|
277
|
+
it('returns the average of all stored embeddings', async () => {
|
|
278
|
+
const dims = 4;
|
|
279
|
+
// Store two embeddings: [1,2,3,4] and [3,4,5,6]
|
|
280
|
+
// Expected average: [2,3,4,5]
|
|
281
|
+
const emb1 = new Float32Array([1, 2, 3, 4]);
|
|
282
|
+
const emb2 = new Float32Array([3, 4, 5, 6]);
|
|
283
|
+
const buf1 = Buffer.from(emb1.buffer);
|
|
284
|
+
const buf2 = Buffer.from(emb2.buffer);
|
|
285
|
+
const insertStmt = db.prepare(`
|
|
286
|
+
INSERT INTO patterns (
|
|
287
|
+
pattern_id, context_embedding, skill_id, skill_features, context_data,
|
|
288
|
+
outcome_type, outcome_reward, importance, original_score, source,
|
|
289
|
+
access_count, created_at, last_accessed_at
|
|
290
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, unixepoch(), unixepoch())
|
|
291
|
+
`);
|
|
292
|
+
insertStmt.run('p1', buf1, 'skill1', '{}', '{}', 'accept', 1.0, 0.5, 0.8, 'recommend', 0);
|
|
293
|
+
insertStmt.run('p2', buf2, 'skill2', '{}', '{}', 'accept', 1.0, 0.5, 0.8, 'recommend', 0);
|
|
294
|
+
const result = await computeAverageEmbedding(db, 100, dims);
|
|
295
|
+
expect(result[0]).toBeCloseTo(2.0);
|
|
296
|
+
expect(result[1]).toBeCloseTo(3.0);
|
|
297
|
+
expect(result[2]).toBeCloseTo(4.0);
|
|
298
|
+
expect(result[3]).toBeCloseTo(5.0);
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
//# sourceMappingURL=PatternStore.helpers.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PatternStore.helpers.test.js","sourceRoot":"","sources":["../../../tests/learning/PatternStore.helpers.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for CoInstallRepository (SMI-2761)
|
|
3
|
+
* @module @skillsmith/core/tests/repositories/CoInstallRepository
|
|
4
|
+
*
|
|
5
|
+
* Tests co-install recording, upsert symmetry, and min-count threshold.
|
|
6
|
+
* Uses createTestDatabase() which runs all migrations including v8.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=CoInstallRepository.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoInstallRepository.test.d.ts","sourceRoot":"","sources":["../../../tests/repositories/CoInstallRepository.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for CoInstallRepository (SMI-2761)
|
|
3
|
+
* @module @skillsmith/core/tests/repositories/CoInstallRepository
|
|
4
|
+
*
|
|
5
|
+
* Tests co-install recording, upsert symmetry, and min-count threshold.
|
|
6
|
+
* Uses createTestDatabase() which runs all migrations including v8.
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
9
|
+
import { createTestDatabase, closeDatabase } from '../helpers/database.js';
|
|
10
|
+
import { CoInstallRepository } from '../../src/repositories/CoInstallRepository.js';
|
|
11
|
+
let db;
|
|
12
|
+
let repo;
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
db = createTestDatabase();
|
|
15
|
+
repo = new CoInstallRepository(db);
|
|
16
|
+
// Insert fixture skills so JOIN works in getTopCoInstalls
|
|
17
|
+
db.exec(`
|
|
18
|
+
INSERT INTO skills (id, name, author, description)
|
|
19
|
+
VALUES
|
|
20
|
+
('skill-a', 'skill-a', 'test', 'Skill A description'),
|
|
21
|
+
('skill-b', 'skill-b', 'test', 'Skill B description'),
|
|
22
|
+
('skill-c', 'skill-c', 'test', 'Skill C description');
|
|
23
|
+
`);
|
|
24
|
+
});
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
closeDatabase(db);
|
|
27
|
+
});
|
|
28
|
+
describe('CoInstallRepository', () => {
|
|
29
|
+
describe('getTopCoInstalls — empty table', () => {
|
|
30
|
+
it('returns empty array when no co-installs recorded', () => {
|
|
31
|
+
const results = repo.getTopCoInstalls('skill-a');
|
|
32
|
+
expect(results).toEqual([]);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe('recordCoInstall — upsert symmetry', () => {
|
|
36
|
+
it('creates (A,B) and (B,A) rows on first call', () => {
|
|
37
|
+
repo.recordCoInstall('skill-a', 'skill-b');
|
|
38
|
+
const forA = repo.getTopCoInstalls('skill-a', 10, 1);
|
|
39
|
+
const forB = repo.getTopCoInstalls('skill-b', 10, 1);
|
|
40
|
+
expect(forA.map((r) => r.skillId)).toContain('skill-b');
|
|
41
|
+
expect(forB.map((r) => r.skillId)).toContain('skill-a');
|
|
42
|
+
});
|
|
43
|
+
it('increments install_count on repeated calls', () => {
|
|
44
|
+
repo.recordCoInstall('skill-a', 'skill-b');
|
|
45
|
+
repo.recordCoInstall('skill-a', 'skill-b');
|
|
46
|
+
repo.recordCoInstall('skill-a', 'skill-b');
|
|
47
|
+
const results = repo.getTopCoInstalls('skill-a', 10, 1);
|
|
48
|
+
const entry = results.find((r) => r.skillId === 'skill-b');
|
|
49
|
+
expect(entry?.installCount).toBe(3);
|
|
50
|
+
});
|
|
51
|
+
it('is idempotent for self-pairs (no-op)', () => {
|
|
52
|
+
// Should not throw, simply return
|
|
53
|
+
expect(() => repo.recordCoInstall('skill-a', 'skill-a')).not.toThrow();
|
|
54
|
+
const results = repo.getTopCoInstalls('skill-a', 10, 1);
|
|
55
|
+
expect(results).toEqual([]);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe('recordSessionCoInstalls', () => {
|
|
59
|
+
it('records all pairs in a session', () => {
|
|
60
|
+
repo.recordSessionCoInstalls(['skill-a', 'skill-b', 'skill-c']);
|
|
61
|
+
const forA = repo.getTopCoInstalls('skill-a', 10, 1);
|
|
62
|
+
const ids = forA.map((r) => r.skillId);
|
|
63
|
+
expect(ids).toContain('skill-b');
|
|
64
|
+
expect(ids).toContain('skill-c');
|
|
65
|
+
});
|
|
66
|
+
it('is a no-op for fewer than 2 skills', () => {
|
|
67
|
+
expect(() => repo.recordSessionCoInstalls([])).not.toThrow();
|
|
68
|
+
expect(() => repo.recordSessionCoInstalls(['skill-a'])).not.toThrow();
|
|
69
|
+
expect(repo.getTopCoInstalls('skill-a', 10, 1)).toEqual([]);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
describe('getTopCoInstalls — min-count boundary', () => {
|
|
73
|
+
it('excludes entries below minCount (4 → excluded at default threshold 5)', () => {
|
|
74
|
+
// Record 4 co-installs
|
|
75
|
+
for (let i = 0; i < 4; i++) {
|
|
76
|
+
repo.recordCoInstall('skill-a', 'skill-b');
|
|
77
|
+
}
|
|
78
|
+
const results = repo.getTopCoInstalls('skill-a'); // default minCount=5
|
|
79
|
+
expect(results.find((r) => r.skillId === 'skill-b')).toBeUndefined();
|
|
80
|
+
});
|
|
81
|
+
it('includes entries at exactly minCount (5 → included at default threshold 5)', () => {
|
|
82
|
+
// Record exactly 5 co-installs
|
|
83
|
+
for (let i = 0; i < 5; i++) {
|
|
84
|
+
repo.recordCoInstall('skill-a', 'skill-b');
|
|
85
|
+
}
|
|
86
|
+
const results = repo.getTopCoInstalls('skill-a'); // default minCount=5
|
|
87
|
+
expect(results.find((r) => r.skillId === 'skill-b')).toBeDefined();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
describe('getTopCoInstalls — result shape', () => {
|
|
91
|
+
it('returns skills with name/description/author from skills table', () => {
|
|
92
|
+
for (let i = 0; i < 5; i++) {
|
|
93
|
+
repo.recordCoInstall('skill-a', 'skill-b');
|
|
94
|
+
}
|
|
95
|
+
const results = repo.getTopCoInstalls('skill-a');
|
|
96
|
+
expect(results).toHaveLength(1);
|
|
97
|
+
expect(results[0]).toMatchObject({
|
|
98
|
+
skillId: 'skill-b',
|
|
99
|
+
name: 'skill-b',
|
|
100
|
+
description: 'Skill B description',
|
|
101
|
+
author: 'test',
|
|
102
|
+
installCount: 5,
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
it('respects the limit parameter', () => {
|
|
106
|
+
for (let i = 0; i < 5; i++) {
|
|
107
|
+
repo.recordCoInstall('skill-a', 'skill-b');
|
|
108
|
+
repo.recordCoInstall('skill-a', 'skill-c');
|
|
109
|
+
}
|
|
110
|
+
const results = repo.getTopCoInstalls('skill-a', 1); // limit=1
|
|
111
|
+
expect(results).toHaveLength(1);
|
|
112
|
+
});
|
|
113
|
+
it('orders results by install_count descending', () => {
|
|
114
|
+
for (let i = 0; i < 10; i++)
|
|
115
|
+
repo.recordCoInstall('skill-a', 'skill-b');
|
|
116
|
+
for (let i = 0; i < 5; i++)
|
|
117
|
+
repo.recordCoInstall('skill-a', 'skill-c');
|
|
118
|
+
const results = repo.getTopCoInstalls('skill-a', 10, 1);
|
|
119
|
+
expect(results[0].skillId).toBe('skill-b');
|
|
120
|
+
expect(results[0].installCount).toBe(10);
|
|
121
|
+
expect(results[1].skillId).toBe('skill-c');
|
|
122
|
+
expect(results[1].installCount).toBe(5);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=CoInstallRepository.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoInstallRepository.test.js","sourceRoot":"","sources":["../../../tests/repositories/CoInstallRepository.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for SkillDependencyRepository (SMI-3143)
|
|
3
|
+
* @module @skillsmith/core/tests/repositories/SkillDependencyRepository
|
|
4
|
+
*
|
|
5
|
+
* Tests CRUD operations, upsert idempotency, source filtering,
|
|
6
|
+
* reverse lookup, and graceful missing-table handling.
|
|
7
|
+
* Uses createTestDatabase() which runs all migrations including v10.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=SkillDependencyRepository.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkillDependencyRepository.test.d.ts","sourceRoot":"","sources":["../../../tests/repositories/SkillDependencyRepository.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|