sqlew 3.2.5 → 3.6.0
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/CHANGELOG.md +288 -1011
- package/README.md +80 -263
- package/assets/config.example.toml +97 -0
- package/assets/schema.sql +6 -1
- package/dist/adapters/index.d.ts +11 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +21 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/mysql-adapter.d.ts +31 -0
- package/dist/adapters/mysql-adapter.d.ts.map +1 -0
- package/dist/adapters/mysql-adapter.js +63 -0
- package/dist/adapters/mysql-adapter.js.map +1 -0
- package/dist/adapters/postgresql-adapter.d.ts +31 -0
- package/dist/adapters/postgresql-adapter.d.ts.map +1 -0
- package/dist/adapters/postgresql-adapter.js +63 -0
- package/dist/adapters/postgresql-adapter.js.map +1 -0
- package/dist/adapters/sqlite-adapter.d.ts +37 -0
- package/dist/adapters/sqlite-adapter.d.ts.map +1 -0
- package/dist/adapters/sqlite-adapter.js +129 -0
- package/dist/adapters/sqlite-adapter.js.map +1 -0
- package/dist/adapters/types.d.ts +33 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/cli.js +55 -54
- package/dist/cli.js.map +1 -1
- package/dist/config/example-generator.d.ts +11 -0
- package/dist/config/example-generator.d.ts.map +1 -0
- package/dist/config/example-generator.js +48 -0
- package/dist/config/example-generator.js.map +1 -0
- package/dist/config/loader.d.ts +46 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +155 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +86 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +28 -0
- package/dist/config/types.js.map +1 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +10 -0
- package/dist/constants.js.map +1 -1
- package/dist/database.d.ts +44 -122
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +145 -349
- package/dist/database.js.map +1 -1
- package/dist/index.js +223 -175
- package/dist/index.js.map +1 -1
- package/dist/knexfile.d.ts +6 -0
- package/dist/knexfile.d.ts.map +1 -0
- package/dist/knexfile.js +85 -0
- package/dist/knexfile.js.map +1 -0
- package/dist/migrations/add-help-system-tables.d.ts +35 -0
- package/dist/migrations/add-help-system-tables.d.ts.map +1 -0
- package/dist/migrations/add-help-system-tables.js +206 -0
- package/dist/migrations/add-help-system-tables.js.map +1 -0
- package/dist/migrations/add-token-tracking.d.ts +28 -0
- package/dist/migrations/add-token-tracking.d.ts.map +1 -0
- package/dist/migrations/add-token-tracking.js +108 -0
- package/dist/migrations/add-token-tracking.js.map +1 -0
- package/dist/migrations/add-v3.5.0-pruned-files.d.ts +26 -0
- package/dist/migrations/add-v3.5.0-pruned-files.d.ts.map +1 -0
- package/dist/migrations/add-v3.5.0-pruned-files.js +107 -0
- package/dist/migrations/add-v3.5.0-pruned-files.js.map +1 -0
- package/dist/migrations/index.d.ts +26 -12
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +162 -20
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/knex/20251025020452_create_master_tables.d.ts +4 -0
- package/dist/migrations/knex/20251025020452_create_master_tables.d.ts.map +1 -0
- package/dist/migrations/knex/20251025020452_create_master_tables.js +65 -0
- package/dist/migrations/knex/20251025020452_create_master_tables.js.map +1 -0
- package/dist/migrations/knex/20251025021152_create_transaction_tables.d.ts +4 -0
- package/dist/migrations/knex/20251025021152_create_transaction_tables.d.ts.map +1 -0
- package/dist/migrations/knex/20251025021152_create_transaction_tables.js +235 -0
- package/dist/migrations/knex/20251025021152_create_transaction_tables.js.map +1 -0
- package/dist/migrations/knex/20251025021351_create_indexes.d.ts +4 -0
- package/dist/migrations/knex/20251025021351_create_indexes.d.ts.map +1 -0
- package/dist/migrations/knex/20251025021351_create_indexes.js +62 -0
- package/dist/migrations/knex/20251025021351_create_indexes.js.map +1 -0
- package/dist/migrations/knex/20251025021416_seed_master_data.d.ts +4 -0
- package/dist/migrations/knex/20251025021416_seed_master_data.d.ts.map +1 -0
- package/dist/migrations/knex/20251025021416_seed_master_data.js +58 -0
- package/dist/migrations/knex/20251025021416_seed_master_data.js.map +1 -0
- package/dist/migrations/knex/20251025070349_create_views.d.ts +4 -0
- package/dist/migrations/knex/20251025070349_create_views.d.ts.map +1 -0
- package/dist/migrations/knex/20251025070349_create_views.js +143 -0
- package/dist/migrations/knex/20251025070349_create_views.js.map +1 -0
- package/dist/migrations/knex/20251025081221_add_link_type_to_task_decision_links.d.ts +4 -0
- package/dist/migrations/knex/20251025081221_add_link_type_to_task_decision_links.d.ts.map +1 -0
- package/dist/migrations/knex/20251025081221_add_link_type_to_task_decision_links.js +15 -0
- package/dist/migrations/knex/20251025081221_add_link_type_to_task_decision_links.js.map +1 -0
- package/dist/migrations/knex/20251025082220_fix_task_dependencies_columns.d.ts +8 -0
- package/dist/migrations/knex/20251025082220_fix_task_dependencies_columns.d.ts.map +1 -0
- package/dist/migrations/knex/20251025082220_fix_task_dependencies_columns.js +12 -0
- package/dist/migrations/knex/20251025082220_fix_task_dependencies_columns.js.map +1 -0
- package/dist/migrations/knex/20251025090000_create_help_system_tables.d.ts +19 -0
- package/dist/migrations/knex/20251025090000_create_help_system_tables.d.ts.map +1 -0
- package/dist/migrations/knex/20251025090000_create_help_system_tables.js +115 -0
- package/dist/migrations/knex/20251025090000_create_help_system_tables.js.map +1 -0
- package/dist/migrations/knex/20251025090100_seed_help_categories_and_use_cases.d.ts +13 -0
- package/dist/migrations/knex/20251025090100_seed_help_categories_and_use_cases.d.ts.map +1 -0
- package/dist/migrations/knex/20251025090100_seed_help_categories_and_use_cases.js +377 -0
- package/dist/migrations/knex/20251025090100_seed_help_categories_and_use_cases.js.map +1 -0
- package/dist/migrations/knex/20251025100000_seed_help_metadata.d.ts +15 -0
- package/dist/migrations/knex/20251025100000_seed_help_metadata.d.ts.map +1 -0
- package/dist/migrations/knex/20251025100000_seed_help_metadata.js +253 -0
- package/dist/migrations/knex/20251025100000_seed_help_metadata.js.map +1 -0
- package/dist/migrations/knex/20251025100100_seed_remaining_use_cases.d.ts +16 -0
- package/dist/migrations/knex/20251025100100_seed_remaining_use_cases.d.ts.map +1 -0
- package/dist/migrations/knex/20251025100100_seed_remaining_use_cases.js +276 -0
- package/dist/migrations/knex/20251025100100_seed_remaining_use_cases.js.map +1 -0
- package/dist/migrations/knex/20251025120000_add_cascade_to_task_dependencies.d.ts +8 -0
- package/dist/migrations/knex/20251025120000_add_cascade_to_task_dependencies.d.ts.map +1 -0
- package/dist/migrations/knex/20251025120000_add_cascade_to_task_dependencies.js +64 -0
- package/dist/migrations/knex/20251025120000_add_cascade_to_task_dependencies.js.map +1 -0
- package/dist/migrations/seed-help-data.d.ts +48 -0
- package/dist/migrations/seed-help-data.d.ts.map +1 -0
- package/dist/migrations/seed-help-data.js +1466 -0
- package/dist/migrations/seed-help-data.js.map +1 -0
- package/dist/migrations/seed-tool-metadata.d.ts +24 -0
- package/dist/migrations/seed-tool-metadata.d.ts.map +1 -0
- package/dist/migrations/seed-tool-metadata.js +392 -0
- package/dist/migrations/seed-tool-metadata.js.map +1 -0
- package/dist/migrations/v3.6.0-help-system-refactor.d.ts +46 -0
- package/dist/migrations/v3.6.0-help-system-refactor.d.ts.map +1 -0
- package/dist/migrations/v3.6.0-help-system-refactor.js +223 -0
- package/dist/migrations/v3.6.0-help-system-refactor.js.map +1 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +2 -0
- package/dist/schema.js.map +1 -1
- package/dist/tests/git-aware-completion.test.d.ts +6 -0
- package/dist/tests/git-aware-completion.test.d.ts.map +1 -0
- package/dist/tests/git-aware-completion.test.js +160 -0
- package/dist/tests/git-aware-completion.test.js.map +1 -0
- package/dist/tests/help-system.test.d.ts +23 -0
- package/dist/tests/help-system.test.d.ts.map +1 -0
- package/dist/tests/help-system.test.js +374 -0
- package/dist/tests/help-system.test.js.map +1 -0
- package/dist/tests/tasks.auto-pruning-decision-link.test.d.ts +6 -0
- package/dist/tests/tasks.auto-pruning-decision-link.test.d.ts.map +1 -0
- package/dist/tests/tasks.auto-pruning-decision-link.test.js +264 -0
- package/dist/tests/tasks.auto-pruning-decision-link.test.js.map +1 -0
- package/dist/tests/tasks.auto-pruning-partial.test.d.ts +6 -0
- package/dist/tests/tasks.auto-pruning-partial.test.d.ts.map +1 -0
- package/dist/tests/tasks.auto-pruning-partial.test.js +285 -0
- package/dist/tests/tasks.auto-pruning-partial.test.js.map +1 -0
- package/dist/tests/tasks.auto-pruning-persistence.test.d.ts +6 -0
- package/dist/tests/tasks.auto-pruning-persistence.test.d.ts.map +1 -0
- package/dist/tests/tasks.auto-pruning-persistence.test.js +250 -0
- package/dist/tests/tasks.auto-pruning-persistence.test.js.map +1 -0
- package/dist/tests/tasks.auto-pruning-safety.test.d.ts +12 -0
- package/dist/tests/tasks.auto-pruning-safety.test.d.ts.map +1 -0
- package/dist/tests/tasks.auto-pruning-safety.test.js +217 -0
- package/dist/tests/tasks.auto-pruning-safety.test.js.map +1 -0
- package/dist/tests/tasks.dependencies.test.js +338 -307
- package/dist/tests/tasks.dependencies.test.js.map +1 -1
- package/dist/tests/tasks.link-file-backward-compat.test.d.ts +6 -0
- package/dist/tests/tasks.link-file-backward-compat.test.d.ts.map +1 -0
- package/dist/tests/tasks.link-file-backward-compat.test.js +247 -0
- package/dist/tests/tasks.link-file-backward-compat.test.js.map +1 -0
- package/dist/tests/tasks.watch-files-action.test.d.ts +6 -0
- package/dist/tests/tasks.watch-files-action.test.d.ts.map +1 -0
- package/dist/tests/tasks.watch-files-action.test.js +372 -0
- package/dist/tests/tasks.watch-files-action.test.js.map +1 -0
- package/dist/tests/tasks.watch-files-parameter.test.d.ts +6 -0
- package/dist/tests/tasks.watch-files-parameter.test.d.ts.map +1 -0
- package/dist/tests/tasks.watch-files-parameter.test.js +260 -0
- package/dist/tests/tasks.watch-files-parameter.test.js.map +1 -0
- package/dist/tests/two-step-git-completion.test.d.ts +6 -0
- package/dist/tests/two-step-git-completion.test.d.ts.map +1 -0
- package/dist/tests/two-step-git-completion.test.js +326 -0
- package/dist/tests/two-step-git-completion.test.js.map +1 -0
- package/dist/tests/vcs-staging.test.d.ts +6 -0
- package/dist/tests/vcs-staging.test.d.ts.map +1 -0
- package/dist/tests/vcs-staging.test.js +137 -0
- package/dist/tests/vcs-staging.test.js.map +1 -0
- package/dist/tools/config.d.ts +9 -4
- package/dist/tools/config.d.ts.map +1 -1
- package/dist/tools/config.js +16 -12
- package/dist/tools/config.js.map +1 -1
- package/dist/tools/constraints.d.ts +9 -3
- package/dist/tools/constraints.d.ts.map +1 -1
- package/dist/tools/constraints.js +66 -45
- package/dist/tools/constraints.js.map +1 -1
- package/dist/tools/context.d.ts +35 -16
- package/dist/tools/context.d.ts.map +1 -1
- package/dist/tools/context.js +374 -314
- package/dist/tools/context.js.map +1 -1
- package/dist/tools/files.d.ts +11 -4
- package/dist/tools/files.d.ts.map +1 -1
- package/dist/tools/files.js +173 -91
- package/dist/tools/files.js.map +1 -1
- package/dist/tools/help-queries.d.ts +130 -0
- package/dist/tools/help-queries.d.ts.map +1 -0
- package/dist/tools/help-queries.js +393 -0
- package/dist/tools/help-queries.js.map +1 -0
- package/dist/tools/messaging.d.ts +13 -6
- package/dist/tools/messaging.d.ts.map +1 -1
- package/dist/tools/messaging.js +217 -129
- package/dist/tools/messaging.js.map +1 -1
- package/dist/tools/tasks.d.ts +42 -12
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +809 -347
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/utils.d.ts +13 -5
- package/dist/tools/utils.d.ts.map +1 -1
- package/dist/tools/utils.js +92 -115
- package/dist/tools/utils.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/activity-logging.d.ts +114 -0
- package/dist/utils/activity-logging.d.ts.map +1 -0
- package/dist/utils/activity-logging.js +162 -0
- package/dist/utils/activity-logging.js.map +1 -0
- package/dist/utils/batch.d.ts +2 -2
- package/dist/utils/batch.d.ts.map +1 -1
- package/dist/utils/batch.js +8 -8
- package/dist/utils/batch.js.map +1 -1
- package/dist/utils/cleanup.d.ts +21 -13
- package/dist/utils/cleanup.d.ts.map +1 -1
- package/dist/utils/cleanup.js +31 -24
- package/dist/utils/cleanup.js.map +1 -1
- package/dist/utils/debug-logger.d.ts +44 -0
- package/dist/utils/debug-logger.d.ts.map +1 -0
- package/dist/utils/debug-logger.js +116 -0
- package/dist/utils/debug-logger.js.map +1 -0
- package/dist/utils/file-pruning.d.ts +69 -0
- package/dist/utils/file-pruning.d.ts.map +1 -0
- package/dist/utils/file-pruning.js +185 -0
- package/dist/utils/file-pruning.js.map +1 -0
- package/dist/utils/help-tracking.d.ts +55 -0
- package/dist/utils/help-tracking.d.ts.map +1 -0
- package/dist/utils/help-tracking.js +88 -0
- package/dist/utils/help-tracking.js.map +1 -0
- package/dist/utils/quality-checks.d.ts +60 -0
- package/dist/utils/quality-checks.d.ts.map +1 -0
- package/dist/utils/quality-checks.js +228 -0
- package/dist/utils/quality-checks.js.map +1 -0
- package/dist/utils/retention.d.ts +13 -5
- package/dist/utils/retention.d.ts.map +1 -1
- package/dist/utils/retention.js +20 -8
- package/dist/utils/retention.js.map +1 -1
- package/dist/utils/task-stale-detection.d.ts +77 -7
- package/dist/utils/task-stale-detection.d.ts.map +1 -1
- package/dist/utils/task-stale-detection.js +309 -34
- package/dist/utils/task-stale-detection.js.map +1 -1
- package/dist/utils/token-estimation.d.ts +72 -0
- package/dist/utils/token-estimation.d.ts.map +1 -0
- package/dist/utils/token-estimation.js +71 -0
- package/dist/utils/token-estimation.js.map +1 -0
- package/dist/utils/token-logging.d.ts +48 -0
- package/dist/utils/token-logging.d.ts.map +1 -0
- package/dist/utils/token-logging.js +112 -0
- package/dist/utils/token-logging.js.map +1 -0
- package/dist/utils/vcs-adapter.d.ts +68 -0
- package/dist/utils/vcs-adapter.d.ts.map +1 -0
- package/dist/utils/vcs-adapter.js +187 -0
- package/dist/utils/vcs-adapter.js.map +1 -0
- package/dist/utils/view-queries.d.ts +34 -0
- package/dist/utils/view-queries.d.ts.map +1 -0
- package/dist/utils/view-queries.js +192 -0
- package/dist/utils/view-queries.js.map +1 -0
- package/dist/watcher/file-watcher.d.ts +54 -4
- package/dist/watcher/file-watcher.d.ts.map +1 -1
- package/dist/watcher/file-watcher.js +329 -33
- package/dist/watcher/file-watcher.js.map +1 -1
- package/dist/watcher/gitignore-parser.d.ts +70 -0
- package/dist/watcher/gitignore-parser.d.ts.map +1 -0
- package/dist/watcher/gitignore-parser.js +191 -0
- package/dist/watcher/gitignore-parser.js.map +1 -0
- package/dist/watcher/index.d.ts +1 -0
- package/dist/watcher/index.d.ts.map +1 -1
- package/dist/watcher/index.js +1 -0
- package/dist/watcher/index.js.map +1 -1
- package/docs/AI_AGENT_GUIDE.md +1 -1
- package/docs/ARCHITECTURE.md +12 -0
- package/docs/AUTO_FILE_TRACKING.md +486 -82
- package/docs/BEST_PRACTICES.md +56 -448
- package/docs/CONFIGURATION.md +908 -0
- package/docs/GIT_AWARE_AUTO_COMPLETE.md +645 -0
- package/docs/MIGRATION_v3.3.md +602 -0
- package/docs/MIGRATION_v3.6.0.md +170 -0
- package/docs/SHARED_CONCEPTS.md +65 -209
- package/docs/TASK_ACTIONS.md +12 -0
- package/docs/TASK_OVERVIEW.md +125 -24
- package/docs/TASK_PRUNING.md +589 -0
- package/docs/TASK_SYSTEM.md +83 -13
- package/docs/TOOL_REFERENCE.md +94 -6
- package/docs/TOOL_SELECTION.md +41 -248
- package/package.json +21 -7
package/dist/database.js
CHANGED
|
@@ -1,163 +1,67 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Database connection and initialization module
|
|
3
|
-
* Handles
|
|
3
|
+
* Handles database setup with Knex.js and DatabaseAdapter pattern
|
|
4
4
|
*/
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import { DEFAULT_DB_PATH, DB_BUSY_TIMEOUT } from './constants.js';
|
|
10
|
-
import { performAutoCleanup } from './utils/cleanup.js';
|
|
11
|
-
import { runAllMigrations, needsAnyMigrations } from './migrations/index.js';
|
|
12
|
-
let dbInstance = null;
|
|
5
|
+
import knexConfig from './knexfile.js';
|
|
6
|
+
import { createDatabaseAdapter } from './adapters/index.js';
|
|
7
|
+
// Global adapter instance
|
|
8
|
+
let adapterInstance = null;
|
|
13
9
|
/**
|
|
14
|
-
* Initialize database
|
|
15
|
-
* Creates database file and folder if they don't exist
|
|
16
|
-
* Initializes schema on first run
|
|
17
|
-
*
|
|
18
|
-
* @param dbPath - Optional database path (defaults to .sqlew/sqlew.db)
|
|
19
|
-
* @returns SQLite database instance
|
|
10
|
+
* Initialize database with adapter pattern
|
|
20
11
|
*/
|
|
21
|
-
export function initializeDatabase(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return dbInstance;
|
|
25
|
-
}
|
|
26
|
-
try {
|
|
27
|
-
// Use provided path or default
|
|
28
|
-
const finalPath = dbPath || DEFAULT_DB_PATH;
|
|
29
|
-
// Convert to absolute path if relative
|
|
30
|
-
const absolutePath = isAbsolute(finalPath)
|
|
31
|
-
? finalPath
|
|
32
|
-
: resolve(process.cwd(), finalPath);
|
|
33
|
-
// Create directory if it doesn't exist
|
|
34
|
-
const dbDir = dirname(absolutePath);
|
|
35
|
-
if (!existsSync(dbDir)) {
|
|
36
|
-
mkdirSync(dbDir, { recursive: true });
|
|
37
|
-
console.log(`✓ Created database directory: ${dbDir}`);
|
|
38
|
-
}
|
|
39
|
-
// Open database connection
|
|
40
|
-
const db = new Database(absolutePath, {
|
|
41
|
-
verbose: process.env.DEBUG_SQL ? console.log : undefined,
|
|
42
|
-
});
|
|
43
|
-
// Configure database
|
|
44
|
-
db.pragma('journal_mode = WAL'); // Write-Ahead Logging for better concurrency
|
|
45
|
-
db.pragma('foreign_keys = ON'); // Enforce foreign key constraints
|
|
46
|
-
db.pragma('synchronous = NORMAL'); // Balance between safety and performance
|
|
47
|
-
db.pragma(`busy_timeout = ${DB_BUSY_TIMEOUT}`); // Set busy timeout
|
|
48
|
-
console.log(`✓ Connected to database: ${absolutePath}`);
|
|
49
|
-
// Check if database has existing schema
|
|
50
|
-
const schemaExists = isSchemaInitialized(db);
|
|
51
|
-
if (schemaExists) {
|
|
52
|
-
// Run all pending migrations using orchestrator
|
|
53
|
-
// This handles upgrades from any version (v1.0.0, v1.1.x, v2.0.0, v2.1.x) to latest
|
|
54
|
-
if (needsAnyMigrations(db)) {
|
|
55
|
-
const migrationResults = runAllMigrations(db);
|
|
56
|
-
// Check if any migration failed
|
|
57
|
-
const failed = migrationResults.find(r => !r.success);
|
|
58
|
-
if (failed) {
|
|
59
|
-
console.error('\n❌ ERROR: Migration failed!');
|
|
60
|
-
console.error(failed.message);
|
|
61
|
-
db.close();
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
// After table prefix migration, run schema initialization to create views/triggers
|
|
65
|
-
// (tables already exist, CREATE TABLE IF NOT EXISTS will skip them)
|
|
66
|
-
const hadPrefixMigration = migrationResults.some(r => r.message.toLowerCase().includes('table prefix') ||
|
|
67
|
-
r.message.toLowerCase().includes('prefix'));
|
|
68
|
-
if (hadPrefixMigration) {
|
|
69
|
-
console.log('\n→ Creating views and triggers for new schema...');
|
|
70
|
-
initializeSchema(db);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// Validate existing schema integrity (after migrations)
|
|
74
|
-
console.log('→ Validating existing database schema...');
|
|
75
|
-
const validation = verifySchemaIntegrity(db);
|
|
76
|
-
if (!validation.valid) {
|
|
77
|
-
// Schema is invalid - display error and exit
|
|
78
|
-
console.error('\n❌ ERROR: Database schema validation failed!');
|
|
79
|
-
console.error('\nThe existing database file has an incompatible schema.');
|
|
80
|
-
console.error(`Database location: ${absolutePath}`);
|
|
81
|
-
if (validation.missing.length > 0) {
|
|
82
|
-
console.error('\n📋 Missing components:');
|
|
83
|
-
validation.missing.forEach(item => console.error(` - ${item}`));
|
|
84
|
-
}
|
|
85
|
-
if (validation.errors.length > 0) {
|
|
86
|
-
console.error('\n⚠️ Validation errors:');
|
|
87
|
-
validation.errors.forEach(error => console.error(` - ${error}`));
|
|
88
|
-
}
|
|
89
|
-
console.error('\n💡 Possible solutions:');
|
|
90
|
-
console.error(' 1. Backup and delete the existing database file to start fresh');
|
|
91
|
-
console.error(' 2. Use a different database path with --db-path option');
|
|
92
|
-
console.error(' 3. Restore from a backup if available\n');
|
|
93
|
-
// Close database and exit
|
|
94
|
-
db.close();
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
console.log('✓ Database schema validation passed');
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
// Initialize new schema
|
|
101
|
-
console.log('→ Initializing database schema...');
|
|
102
|
-
initializeSchema(db);
|
|
103
|
-
}
|
|
104
|
-
// Store instance
|
|
105
|
-
dbInstance = db;
|
|
106
|
-
// Perform initial cleanup
|
|
107
|
-
try {
|
|
108
|
-
const cleanupResult = performAutoCleanup(db);
|
|
109
|
-
if (cleanupResult.messagesDeleted > 0 || cleanupResult.fileChangesDeleted > 0) {
|
|
110
|
-
console.log(`✓ Cleanup: ${cleanupResult.messagesDeleted} messages, ${cleanupResult.fileChangesDeleted} file changes deleted`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
console.warn('⚠️ Initial cleanup failed:', error instanceof Error ? error.message : String(error));
|
|
115
|
-
}
|
|
116
|
-
return db;
|
|
117
|
-
}
|
|
118
|
-
catch (error) {
|
|
119
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
120
|
-
throw new Error(`Failed to initialize database: ${message}`);
|
|
12
|
+
export async function initializeDatabase(config) {
|
|
13
|
+
if (adapterInstance) {
|
|
14
|
+
return adapterInstance;
|
|
121
15
|
}
|
|
16
|
+
const dbType = config?.databaseType || 'sqlite';
|
|
17
|
+
const adapter = createDatabaseAdapter(dbType);
|
|
18
|
+
// Determine if running from compiled code (dist/) or source (src/)
|
|
19
|
+
const isCompiledCode = import.meta.url.includes('/dist/');
|
|
20
|
+
const environment = isCompiledCode ? 'production' : 'development';
|
|
21
|
+
// Use config from knexfile or provided config
|
|
22
|
+
const baseConfig = knexConfig[environment] || knexConfig.development;
|
|
23
|
+
const knexConnConfig = config?.connection
|
|
24
|
+
? { ...baseConfig, connection: config.connection }
|
|
25
|
+
: baseConfig;
|
|
26
|
+
await adapter.connect(knexConnConfig);
|
|
27
|
+
// Run migrations if needed
|
|
28
|
+
const knex = adapter.getKnex();
|
|
29
|
+
await knex.migrate.latest();
|
|
30
|
+
console.log(`✓ Database initialized with Knex adapter (${environment})`);
|
|
31
|
+
adapterInstance = adapter;
|
|
32
|
+
return adapter;
|
|
122
33
|
}
|
|
123
34
|
/**
|
|
124
|
-
*
|
|
35
|
+
* Get current database adapter
|
|
125
36
|
*/
|
|
126
|
-
export function
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
dbInstance = null;
|
|
130
|
-
console.log('✓ Database connection closed');
|
|
37
|
+
export function getAdapter() {
|
|
38
|
+
if (!adapterInstance) {
|
|
39
|
+
throw new Error('Database not initialized. Call initializeDatabase() first.');
|
|
131
40
|
}
|
|
41
|
+
return adapterInstance;
|
|
132
42
|
}
|
|
133
43
|
/**
|
|
134
|
-
*
|
|
135
|
-
* Throws error if not initialized
|
|
136
|
-
*
|
|
137
|
-
* @returns Current database instance
|
|
44
|
+
* Close database connection
|
|
138
45
|
*/
|
|
139
|
-
export function
|
|
140
|
-
if (
|
|
141
|
-
|
|
46
|
+
export async function closeDatabase() {
|
|
47
|
+
if (adapterInstance) {
|
|
48
|
+
await adapterInstance.disconnect();
|
|
49
|
+
adapterInstance = null;
|
|
50
|
+
console.log('✓ Database connection closed');
|
|
142
51
|
}
|
|
143
|
-
return dbInstance;
|
|
144
52
|
}
|
|
145
53
|
// ============================================================================
|
|
146
|
-
// Helper Functions for Master Table Management
|
|
54
|
+
// Helper Functions for Master Table Management (Async)
|
|
147
55
|
// ============================================================================
|
|
148
56
|
/**
|
|
149
57
|
* Get or create agent by name
|
|
150
|
-
* Uses INSERT OR IGNORE for idempotent operation
|
|
151
|
-
*
|
|
152
|
-
* @param db - Database instance
|
|
153
|
-
* @param name - Agent name
|
|
154
|
-
* @returns Agent ID
|
|
155
58
|
*/
|
|
156
|
-
export function getOrCreateAgent(
|
|
157
|
-
|
|
158
|
-
|
|
59
|
+
export async function getOrCreateAgent(adapter, name, trx) {
|
|
60
|
+
const knex = trx || adapter.getKnex();
|
|
61
|
+
// Try to insert (will be ignored if exists)
|
|
62
|
+
await knex('m_agents').insert({ name }).onConflict('name').ignore();
|
|
159
63
|
// Get the ID
|
|
160
|
-
const result =
|
|
64
|
+
const result = await knex('m_agents').where({ name }).first('id');
|
|
161
65
|
if (!result) {
|
|
162
66
|
throw new Error(`Failed to get or create agent: ${name}`);
|
|
163
67
|
}
|
|
@@ -165,14 +69,11 @@ export function getOrCreateAgent(db, name) {
|
|
|
165
69
|
}
|
|
166
70
|
/**
|
|
167
71
|
* Get or create context key by name
|
|
168
|
-
*
|
|
169
|
-
* @param db - Database instance
|
|
170
|
-
* @param key - Context key name
|
|
171
|
-
* @returns Context key ID
|
|
172
72
|
*/
|
|
173
|
-
export function getOrCreateContextKey(
|
|
174
|
-
|
|
175
|
-
|
|
73
|
+
export async function getOrCreateContextKey(adapter, key, trx) {
|
|
74
|
+
const knex = trx || adapter.getKnex();
|
|
75
|
+
await knex('m_context_keys').insert({ key }).onConflict('key').ignore();
|
|
76
|
+
const result = await knex('m_context_keys').where({ key }).first('id');
|
|
176
77
|
if (!result) {
|
|
177
78
|
throw new Error(`Failed to get or create context key: ${key}`);
|
|
178
79
|
}
|
|
@@ -180,14 +81,11 @@ export function getOrCreateContextKey(db, key) {
|
|
|
180
81
|
}
|
|
181
82
|
/**
|
|
182
83
|
* Get or create file by path
|
|
183
|
-
*
|
|
184
|
-
* @param db - Database instance
|
|
185
|
-
* @param path - File path
|
|
186
|
-
* @returns File ID
|
|
187
84
|
*/
|
|
188
|
-
export function getOrCreateFile(
|
|
189
|
-
|
|
190
|
-
|
|
85
|
+
export async function getOrCreateFile(adapter, path, trx) {
|
|
86
|
+
const knex = trx || adapter.getKnex();
|
|
87
|
+
await knex('m_files').insert({ path }).onConflict('path').ignore();
|
|
88
|
+
const result = await knex('m_files').where({ path }).first('id');
|
|
191
89
|
if (!result) {
|
|
192
90
|
throw new Error(`Failed to get or create file: ${path}`);
|
|
193
91
|
}
|
|
@@ -195,14 +93,11 @@ export function getOrCreateFile(db, path) {
|
|
|
195
93
|
}
|
|
196
94
|
/**
|
|
197
95
|
* Get or create tag by name
|
|
198
|
-
*
|
|
199
|
-
* @param db - Database instance
|
|
200
|
-
* @param name - Tag name
|
|
201
|
-
* @returns Tag ID
|
|
202
96
|
*/
|
|
203
|
-
export function getOrCreateTag(
|
|
204
|
-
|
|
205
|
-
|
|
97
|
+
export async function getOrCreateTag(adapter, name, trx) {
|
|
98
|
+
const knex = trx || adapter.getKnex();
|
|
99
|
+
await knex('m_tags').insert({ name }).onConflict('name').ignore();
|
|
100
|
+
const result = await knex('m_tags').where({ name }).first('id');
|
|
206
101
|
if (!result) {
|
|
207
102
|
throw new Error(`Failed to get or create tag: ${name}`);
|
|
208
103
|
}
|
|
@@ -210,14 +105,11 @@ export function getOrCreateTag(db, name) {
|
|
|
210
105
|
}
|
|
211
106
|
/**
|
|
212
107
|
* Get or create scope by name
|
|
213
|
-
*
|
|
214
|
-
* @param db - Database instance
|
|
215
|
-
* @param name - Scope name
|
|
216
|
-
* @returns Scope ID
|
|
217
108
|
*/
|
|
218
|
-
export function getOrCreateScope(
|
|
219
|
-
|
|
220
|
-
|
|
109
|
+
export async function getOrCreateScope(adapter, name, trx) {
|
|
110
|
+
const knex = trx || adapter.getKnex();
|
|
111
|
+
await knex('m_scopes').insert({ name }).onConflict('name').ignore();
|
|
112
|
+
const result = await knex('m_scopes').where({ name }).first('id');
|
|
221
113
|
if (!result) {
|
|
222
114
|
throw new Error(`Failed to get or create scope: ${name}`);
|
|
223
115
|
}
|
|
@@ -225,17 +117,11 @@ export function getOrCreateScope(db, name) {
|
|
|
225
117
|
}
|
|
226
118
|
/**
|
|
227
119
|
* Get or create category ID
|
|
228
|
-
* Uses INSERT to create if doesn't exist
|
|
229
|
-
*
|
|
230
|
-
* @param db - Database instance
|
|
231
|
-
* @param category - Category name
|
|
232
|
-
* @returns Category ID
|
|
233
120
|
*/
|
|
234
|
-
export function getOrCreateCategoryId(
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const result = db.prepare('SELECT id FROM m_constraint_categories WHERE name = ?').get(category);
|
|
121
|
+
export async function getOrCreateCategoryId(adapter, category, trx) {
|
|
122
|
+
const knex = trx || adapter.getKnex();
|
|
123
|
+
await knex('m_constraint_categories').insert({ name: category }).onConflict('name').ignore();
|
|
124
|
+
const result = await knex('m_constraint_categories').where({ name: category }).first('id');
|
|
239
125
|
if (!result) {
|
|
240
126
|
throw new Error(`Failed to get or create category: ${category}`);
|
|
241
127
|
}
|
|
@@ -243,77 +129,56 @@ export function getOrCreateCategoryId(db, category) {
|
|
|
243
129
|
}
|
|
244
130
|
/**
|
|
245
131
|
* Get layer ID by name
|
|
246
|
-
* Does not auto-create (layers are predefined)
|
|
247
|
-
*
|
|
248
|
-
* @param db - Database instance
|
|
249
|
-
* @param name - Layer name
|
|
250
|
-
* @returns Layer ID or null if not found
|
|
251
132
|
*/
|
|
252
|
-
export function getLayerId(
|
|
253
|
-
const
|
|
133
|
+
export async function getLayerId(adapter, name, trx) {
|
|
134
|
+
const knex = trx || adapter.getKnex();
|
|
135
|
+
const result = await knex('m_layers').where({ name }).first('id');
|
|
254
136
|
return result ? result.id : null;
|
|
255
137
|
}
|
|
256
138
|
/**
|
|
257
139
|
* Get constraint category ID by name
|
|
258
|
-
* Does not auto-create (categories are predefined)
|
|
259
|
-
*
|
|
260
|
-
* @param db - Database instance
|
|
261
|
-
* @param name - Category name
|
|
262
|
-
* @returns Category ID or null if not found
|
|
263
140
|
*/
|
|
264
|
-
export function getCategoryId(
|
|
265
|
-
const
|
|
141
|
+
export async function getCategoryId(adapter, name, trx) {
|
|
142
|
+
const knex = trx || adapter.getKnex();
|
|
143
|
+
const result = await knex('m_constraint_categories').where({ name }).first('id');
|
|
266
144
|
return result ? result.id : null;
|
|
267
145
|
}
|
|
268
146
|
// ============================================================================
|
|
269
|
-
// Configuration Management
|
|
147
|
+
// Configuration Management (Async)
|
|
270
148
|
// ============================================================================
|
|
271
149
|
/**
|
|
272
150
|
* Get configuration value from m_config table
|
|
273
|
-
*
|
|
274
|
-
* @param db - Database instance
|
|
275
|
-
* @param key - Config key
|
|
276
|
-
* @returns Config value as string or null if not found
|
|
277
151
|
*/
|
|
278
|
-
export function getConfigValue(
|
|
279
|
-
const
|
|
152
|
+
export async function getConfigValue(adapter, key) {
|
|
153
|
+
const knex = adapter.getKnex();
|
|
154
|
+
const result = await knex('m_config').where({ key }).first('value');
|
|
280
155
|
return result ? result.value : null;
|
|
281
156
|
}
|
|
282
157
|
/**
|
|
283
158
|
* Set configuration value in m_config table
|
|
284
|
-
*
|
|
285
|
-
* @param db - Database instance
|
|
286
|
-
* @param key - Config key
|
|
287
|
-
* @param value - Config value (will be converted to string)
|
|
288
159
|
*/
|
|
289
|
-
export function setConfigValue(
|
|
160
|
+
export async function setConfigValue(adapter, key, value) {
|
|
161
|
+
const knex = adapter.getKnex();
|
|
290
162
|
const stringValue = String(value);
|
|
291
|
-
|
|
163
|
+
await knex('m_config')
|
|
164
|
+
.insert({ key, value: stringValue })
|
|
165
|
+
.onConflict('key')
|
|
166
|
+
.merge({ value: stringValue });
|
|
292
167
|
}
|
|
293
168
|
/**
|
|
294
169
|
* Get configuration value as boolean
|
|
295
|
-
*
|
|
296
|
-
* @param db - Database instance
|
|
297
|
-
* @param key - Config key
|
|
298
|
-
* @param defaultValue - Default value if key not found
|
|
299
|
-
* @returns Boolean value
|
|
300
170
|
*/
|
|
301
|
-
export function getConfigBool(
|
|
302
|
-
const value = getConfigValue(
|
|
171
|
+
export async function getConfigBool(adapter, key, defaultValue = false) {
|
|
172
|
+
const value = await getConfigValue(adapter, key);
|
|
303
173
|
if (value === null)
|
|
304
174
|
return defaultValue;
|
|
305
175
|
return value === '1' || value.toLowerCase() === 'true';
|
|
306
176
|
}
|
|
307
177
|
/**
|
|
308
178
|
* Get configuration value as integer
|
|
309
|
-
*
|
|
310
|
-
* @param db - Database instance
|
|
311
|
-
* @param key - Config key
|
|
312
|
-
* @param defaultValue - Default value if key not found
|
|
313
|
-
* @returns Integer value
|
|
314
179
|
*/
|
|
315
|
-
export function getConfigInt(
|
|
316
|
-
const value = getConfigValue(
|
|
180
|
+
export async function getConfigInt(adapter, key, defaultValue = 0) {
|
|
181
|
+
const value = await getConfigValue(adapter, key);
|
|
317
182
|
if (value === null)
|
|
318
183
|
return defaultValue;
|
|
319
184
|
const parsed = parseInt(value, 10);
|
|
@@ -321,12 +186,10 @@ export function getConfigInt(db, key, defaultValue = 0) {
|
|
|
321
186
|
}
|
|
322
187
|
/**
|
|
323
188
|
* Get all configuration as an object
|
|
324
|
-
*
|
|
325
|
-
* @param db - Database instance
|
|
326
|
-
* @returns Object with all m_config key-value pairs
|
|
327
189
|
*/
|
|
328
|
-
export function getAllConfig(
|
|
329
|
-
const
|
|
190
|
+
export async function getAllConfig(adapter) {
|
|
191
|
+
const knex = adapter.getKnex();
|
|
192
|
+
const rows = await knex('m_config').select('key', 'value');
|
|
330
193
|
const config = {};
|
|
331
194
|
for (const row of rows) {
|
|
332
195
|
config[row.key] = row.value;
|
|
@@ -334,35 +197,10 @@ export function getAllConfig(db) {
|
|
|
334
197
|
return config;
|
|
335
198
|
}
|
|
336
199
|
// ============================================================================
|
|
337
|
-
//
|
|
338
|
-
// ============================================================================
|
|
339
|
-
/**
|
|
340
|
-
* Execute a function within a transaction
|
|
341
|
-
* Automatically handles commit/rollback
|
|
342
|
-
*
|
|
343
|
-
* @param db - Database instance
|
|
344
|
-
* @param fn - Function to execute in transaction
|
|
345
|
-
* @returns Result from function
|
|
346
|
-
*/
|
|
347
|
-
export function transaction(db, fn) {
|
|
348
|
-
db.exec('BEGIN TRANSACTION');
|
|
349
|
-
try {
|
|
350
|
-
const result = fn();
|
|
351
|
-
db.exec('COMMIT');
|
|
352
|
-
return result;
|
|
353
|
-
}
|
|
354
|
-
catch (error) {
|
|
355
|
-
db.exec('ROLLBACK');
|
|
356
|
-
throw error;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
// ============================================================================
|
|
360
|
-
// Decision Context Management (v3.2.2)
|
|
200
|
+
// Decision Context Management (Async - v3.2.2)
|
|
361
201
|
// ============================================================================
|
|
362
202
|
/**
|
|
363
203
|
* Validate JSON structure for alternatives array
|
|
364
|
-
* @param alternatives - JSON string or null
|
|
365
|
-
* @throws Error if JSON is invalid or not an array
|
|
366
204
|
*/
|
|
367
205
|
function validateAlternativesJson(alternatives) {
|
|
368
206
|
if (alternatives === null || alternatives === undefined)
|
|
@@ -382,8 +220,6 @@ function validateAlternativesJson(alternatives) {
|
|
|
382
220
|
}
|
|
383
221
|
/**
|
|
384
222
|
* Validate JSON structure for tradeoffs object
|
|
385
|
-
* @param tradeoffs - JSON string or null
|
|
386
|
-
* @throws Error if JSON is invalid or doesn't have pros/cons structure
|
|
387
223
|
*/
|
|
388
224
|
function validateTradeoffsJson(tradeoffs) {
|
|
389
225
|
if (tradeoffs === null || tradeoffs === undefined)
|
|
@@ -393,7 +229,6 @@ function validateTradeoffsJson(tradeoffs) {
|
|
|
393
229
|
if (typeof parsed !== 'object' || parsed === null) {
|
|
394
230
|
throw new Error('tradeoffs must be a JSON object');
|
|
395
231
|
}
|
|
396
|
-
// Optional: Check for pros/cons keys if provided
|
|
397
232
|
if (parsed.pros !== undefined && !Array.isArray(parsed.pros)) {
|
|
398
233
|
throw new Error('tradeoffs.pros must be an array');
|
|
399
234
|
}
|
|
@@ -410,85 +245,54 @@ function validateTradeoffsJson(tradeoffs) {
|
|
|
410
245
|
}
|
|
411
246
|
/**
|
|
412
247
|
* Add decision context to a decision
|
|
413
|
-
*
|
|
414
|
-
* @param db - Database instance
|
|
415
|
-
* @param decisionKey - Decision key to attach context to
|
|
416
|
-
* @param rationale - Rationale for the decision (required)
|
|
417
|
-
* @param alternatives - JSON array of alternatives considered (optional)
|
|
418
|
-
* @param tradeoffs - JSON object with pros/cons (optional)
|
|
419
|
-
* @param decidedBy - Agent name who decided (optional)
|
|
420
|
-
* @param relatedTaskId - Related task ID (optional)
|
|
421
|
-
* @param relatedConstraintId - Related constraint ID (optional)
|
|
422
|
-
* @returns Context ID
|
|
423
248
|
*/
|
|
424
|
-
export function addDecisionContext(
|
|
249
|
+
export async function addDecisionContext(adapter, decisionKey, rationale, alternatives = null, tradeoffs = null, decidedBy = null, relatedTaskId = null, relatedConstraintId = null) {
|
|
425
250
|
// Validate JSON inputs
|
|
426
251
|
validateAlternativesJson(alternatives);
|
|
427
252
|
validateTradeoffsJson(tradeoffs);
|
|
253
|
+
const knex = adapter.getKnex();
|
|
428
254
|
// Get decision key ID
|
|
429
|
-
const keyId = getOrCreateContextKey(
|
|
255
|
+
const keyId = await getOrCreateContextKey(adapter, decisionKey);
|
|
430
256
|
// Get agent ID if provided
|
|
431
257
|
let agentId = null;
|
|
432
258
|
if (decidedBy) {
|
|
433
|
-
agentId = getOrCreateAgent(
|
|
259
|
+
agentId = await getOrCreateAgent(adapter, decidedBy);
|
|
434
260
|
}
|
|
435
261
|
// Insert context
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
)
|
|
446
|
-
|
|
447
|
-
return result.lastInsertRowid;
|
|
262
|
+
const [id] = await knex('t_decision_context').insert({
|
|
263
|
+
decision_key_id: keyId,
|
|
264
|
+
rationale,
|
|
265
|
+
alternatives_considered: alternatives,
|
|
266
|
+
tradeoffs,
|
|
267
|
+
decided_by_agent_id: agentId,
|
|
268
|
+
related_task_id: relatedTaskId,
|
|
269
|
+
related_constraint_id: relatedConstraintId,
|
|
270
|
+
decision_date: Math.floor(Date.now() / 1000),
|
|
271
|
+
});
|
|
272
|
+
return id;
|
|
448
273
|
}
|
|
449
274
|
/**
|
|
450
275
|
* Get decision with context
|
|
451
|
-
*
|
|
452
|
-
* @param db - Database instance
|
|
453
|
-
* @param decisionKey - Decision key
|
|
454
|
-
* @returns Decision with context or null if not found
|
|
455
276
|
*/
|
|
456
|
-
export function getDecisionWithContext(
|
|
277
|
+
export async function getDecisionWithContext(adapter, decisionKey) {
|
|
278
|
+
const knex = adapter.getKnex();
|
|
457
279
|
// First get the decision
|
|
458
|
-
const decision =
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
a.name as decided_by,
|
|
466
|
-
datetime(d.ts, 'unixepoch') as updated
|
|
467
|
-
FROM t_decisions d
|
|
468
|
-
JOIN m_context_keys k ON d.key_id = k.id
|
|
469
|
-
LEFT JOIN m_layers l ON d.layer_id = l.id
|
|
470
|
-
LEFT JOIN m_agents a ON d.agent_id = a.id
|
|
471
|
-
WHERE k.key = ?
|
|
472
|
-
`).get(decisionKey);
|
|
280
|
+
const decision = await knex('t_decisions as d')
|
|
281
|
+
.join('m_context_keys as k', 'd.key_id', 'k.id')
|
|
282
|
+
.leftJoin('m_layers as l', 'd.layer_id', 'l.id')
|
|
283
|
+
.leftJoin('m_agents as a', 'd.agent_id', 'a.id')
|
|
284
|
+
.where('k.key', decisionKey)
|
|
285
|
+
.select('k.key', 'd.value', 'd.version', knex.raw(`CASE d.status WHEN 1 THEN 'active' WHEN 2 THEN 'deprecated' ELSE 'draft' END as status`), 'l.name as layer', 'a.name as decided_by', knex.raw(`datetime(d.ts, 'unixepoch') as updated`))
|
|
286
|
+
.first();
|
|
473
287
|
if (!decision)
|
|
474
288
|
return null;
|
|
475
289
|
// Get all contexts for this decision
|
|
476
|
-
const contexts =
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
a.name as decided_by,
|
|
483
|
-
datetime(dc.decision_date, 'unixepoch') as decision_date,
|
|
484
|
-
dc.related_task_id,
|
|
485
|
-
dc.related_constraint_id
|
|
486
|
-
FROM t_decision_context dc
|
|
487
|
-
JOIN m_context_keys k ON dc.decision_key_id = k.id
|
|
488
|
-
LEFT JOIN m_agents a ON dc.decided_by_agent_id = a.id
|
|
489
|
-
WHERE k.key = ?
|
|
490
|
-
ORDER BY dc.decision_date DESC
|
|
491
|
-
`).all(decisionKey);
|
|
290
|
+
const contexts = await knex('t_decision_context as dc')
|
|
291
|
+
.join('m_context_keys as k', 'dc.decision_key_id', 'k.id')
|
|
292
|
+
.leftJoin('m_agents as a', 'dc.decided_by_agent_id', 'a.id')
|
|
293
|
+
.where('k.key', decisionKey)
|
|
294
|
+
.select('dc.id', 'dc.rationale', 'dc.alternatives_considered', 'dc.tradeoffs', 'a.name as decided_by', knex.raw(`datetime(dc.decision_date, 'unixepoch') as decision_date`), 'dc.related_task_id', 'dc.related_constraint_id')
|
|
295
|
+
.orderBy('dc.decision_date', 'desc');
|
|
492
296
|
return {
|
|
493
297
|
...decision,
|
|
494
298
|
context: contexts,
|
|
@@ -496,54 +300,46 @@ export function getDecisionWithContext(db, decisionKey) {
|
|
|
496
300
|
}
|
|
497
301
|
/**
|
|
498
302
|
* List decision contexts with optional filters
|
|
499
|
-
*
|
|
500
|
-
* @param db - Database instance
|
|
501
|
-
* @param filters - Optional filters
|
|
502
|
-
* @returns Array of decision contexts
|
|
503
303
|
*/
|
|
504
|
-
export function listDecisionContexts(
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
dc.alternatives_considered,
|
|
511
|
-
dc.tradeoffs,
|
|
512
|
-
a.name as decided_by,
|
|
513
|
-
datetime(dc.decision_date, 'unixepoch') as decision_date,
|
|
514
|
-
dc.related_task_id,
|
|
515
|
-
dc.related_constraint_id
|
|
516
|
-
FROM t_decision_context dc
|
|
517
|
-
JOIN m_context_keys k ON dc.decision_key_id = k.id
|
|
518
|
-
LEFT JOIN m_agents a ON dc.decided_by_agent_id = a.id
|
|
519
|
-
WHERE 1=1
|
|
520
|
-
`;
|
|
521
|
-
const params = [];
|
|
304
|
+
export async function listDecisionContexts(adapter, filters) {
|
|
305
|
+
const knex = adapter.getKnex();
|
|
306
|
+
let query = knex('t_decision_context as dc')
|
|
307
|
+
.join('m_context_keys as k', 'dc.decision_key_id', 'k.id')
|
|
308
|
+
.leftJoin('m_agents as a', 'dc.decided_by_agent_id', 'a.id')
|
|
309
|
+
.select('dc.id', 'k.key as decision_key', 'dc.rationale', 'dc.alternatives_considered', 'dc.tradeoffs', 'a.name as decided_by', knex.raw(`datetime(dc.decision_date, 'unixepoch') as decision_date`), 'dc.related_task_id', 'dc.related_constraint_id');
|
|
522
310
|
if (filters?.decisionKey) {
|
|
523
|
-
query
|
|
524
|
-
params.push(filters.decisionKey);
|
|
311
|
+
query = query.where('k.key', filters.decisionKey);
|
|
525
312
|
}
|
|
526
313
|
if (filters?.relatedTaskId !== undefined) {
|
|
527
|
-
query
|
|
528
|
-
params.push(filters.relatedTaskId);
|
|
314
|
+
query = query.where('dc.related_task_id', filters.relatedTaskId);
|
|
529
315
|
}
|
|
530
316
|
if (filters?.relatedConstraintId !== undefined) {
|
|
531
|
-
query
|
|
532
|
-
params.push(filters.relatedConstraintId);
|
|
317
|
+
query = query.where('dc.related_constraint_id', filters.relatedConstraintId);
|
|
533
318
|
}
|
|
534
319
|
if (filters?.decidedBy) {
|
|
535
|
-
query
|
|
536
|
-
params.push(filters.decidedBy);
|
|
320
|
+
query = query.where('a.name', filters.decidedBy);
|
|
537
321
|
}
|
|
538
|
-
query
|
|
322
|
+
query = query.orderBy('dc.decision_date', 'desc');
|
|
539
323
|
if (filters?.limit) {
|
|
540
|
-
query
|
|
541
|
-
params.push(filters.limit);
|
|
324
|
+
query = query.limit(filters.limit);
|
|
542
325
|
}
|
|
543
326
|
if (filters?.offset) {
|
|
544
|
-
query
|
|
545
|
-
params.push(filters.offset);
|
|
327
|
+
query = query.offset(filters.offset);
|
|
546
328
|
}
|
|
547
|
-
return
|
|
329
|
+
return await query;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Backwards compatibility alias for getAdapter
|
|
333
|
+
*/
|
|
334
|
+
export function getDatabase() {
|
|
335
|
+
return getAdapter();
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Execute a function within a database transaction
|
|
339
|
+
*/
|
|
340
|
+
export async function transaction(callback) {
|
|
341
|
+
const adapter = getAdapter();
|
|
342
|
+
const knex = adapter.getKnex();
|
|
343
|
+
return await knex.transaction(callback);
|
|
548
344
|
}
|
|
549
345
|
//# sourceMappingURL=database.js.map
|