sqlew 3.5.3 → 3.6.1
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 +247 -1772
- package/README.md +70 -304
- package/assets/config.example.toml +106 -0
- 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.map +1 -1
- package/dist/config/loader.js +4 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/types.d.ts +11 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/database.d.ts +56 -121
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +266 -414
- package/dist/database.js.map +1 -1
- package/dist/index.js +329 -245
- 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/index.d.ts +25 -12
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +147 -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/knex/20251027000000_add_agent_reuse_system.d.ts +14 -0
- package/dist/migrations/knex/20251027000000_add_agent_reuse_system.d.ts.map +1 -0
- package/dist/migrations/knex/20251027000000_add_agent_reuse_system.js +34 -0
- package/dist/migrations/knex/20251027000000_add_agent_reuse_system.js.map +1 -0
- package/dist/migrations/knex/20251027010000_add_task_constraint_to_decision_context.d.ts +4 -0
- package/dist/migrations/knex/20251027010000_add_task_constraint_to_decision_context.d.ts.map +1 -0
- package/dist/migrations/knex/20251027010000_add_task_constraint_to_decision_context.js +24 -0
- package/dist/migrations/knex/20251027010000_add_task_constraint_to_decision_context.js.map +1 -0
- package/dist/migrations/knex/20251027020000_update_agent_reusability.d.ts +16 -0
- package/dist/migrations/knex/20251027020000_update_agent_reusability.d.ts.map +1 -0
- package/dist/migrations/knex/20251027020000_update_agent_reusability.js +27 -0
- package/dist/migrations/knex/20251027020000_update_agent_reusability.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/agent-reuse.test.d.ts +6 -0
- package/dist/tests/agent-reuse.test.d.ts.map +1 -0
- package/dist/tests/agent-reuse.test.js +242 -0
- package/dist/tests/agent-reuse.test.js.map +1 -0
- package/dist/tests/all-features.test.d.ts +7 -0
- package/dist/tests/all-features.test.d.ts.map +1 -0
- package/dist/tests/all-features.test.js +514 -0
- package/dist/tests/all-features.test.js.map +1 -0
- package/dist/tests/git-aware-completion.test.js +89 -70
- package/dist/tests/git-aware-completion.test.js.map +1 -1
- 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.js +92 -78
- package/dist/tests/tasks.auto-pruning-decision-link.test.js.map +1 -1
- package/dist/tests/tasks.auto-pruning-partial.test.js +106 -95
- package/dist/tests/tasks.auto-pruning-partial.test.js.map +1 -1
- package/dist/tests/tasks.auto-pruning-persistence.test.js +115 -97
- package/dist/tests/tasks.auto-pruning-persistence.test.js.map +1 -1
- package/dist/tests/tasks.auto-pruning-safety.test.js +124 -103
- package/dist/tests/tasks.auto-pruning-safety.test.js.map +1 -1
- 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.js +116 -104
- package/dist/tests/tasks.link-file-backward-compat.test.js.map +1 -1
- package/dist/tests/tasks.watch-files-action.test.js +122 -101
- package/dist/tests/tasks.watch-files-action.test.js.map +1 -1
- package/dist/tests/tasks.watch-files-parameter.test.js +105 -94
- package/dist/tests/tasks.watch-files-parameter.test.js.map +1 -1
- package/dist/tests/two-step-git-completion.test.js +176 -133
- package/dist/tests/two-step-git-completion.test.js.map +1 -1
- package/dist/tests/vcs-staging.test.js +1 -1
- package/dist/tests/vcs-staging.test.js.map +1 -1
- package/dist/tools/config.d.ts +9 -6
- package/dist/tools/config.d.ts.map +1 -1
- package/dist/tools/config.js +16 -14
- package/dist/tools/config.js.map +1 -1
- package/dist/tools/constraints.d.ts +10 -7
- package/dist/tools/constraints.d.ts.map +1 -1
- package/dist/tools/constraints.js +73 -51
- package/dist/tools/constraints.js.map +1 -1
- package/dist/tools/context.d.ts +36 -33
- package/dist/tools/context.d.ts.map +1 -1
- package/dist/tools/context.js +441 -340
- package/dist/tools/context.js.map +1 -1
- package/dist/tools/files.d.ts +12 -9
- package/dist/tools/files.d.ts.map +1 -1
- package/dist/tools/files.js +173 -95
- 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 +14 -11
- package/dist/tools/messaging.d.ts.map +1 -1
- package/dist/tools/messaging.js +239 -133
- package/dist/tools/messaging.js.map +1 -1
- package/dist/tools/tasks.d.ts +18 -16
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +519 -442
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/utils.d.ts +14 -11
- package/dist/tools/utils.d.ts.map +1 -1
- package/dist/tools/utils.js +90 -122
- package/dist/tools/utils.js.map +1 -1
- package/dist/types.d.ts +1 -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 +24 -14
- package/dist/utils/cleanup.d.ts.map +1 -1
- package/dist/utils/cleanup.js +37 -27
- package/dist/utils/cleanup.js.map +1 -1
- package/dist/utils/debug-logger.d.ts +99 -0
- package/dist/utils/debug-logger.d.ts.map +1 -0
- package/dist/utils/debug-logger.js +267 -0
- package/dist/utils/debug-logger.js.map +1 -0
- package/dist/utils/error-handler.d.ts +28 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +121 -0
- package/dist/utils/error-handler.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/param-parser.d.ts +23 -0
- package/dist/utils/param-parser.d.ts.map +1 -0
- package/dist/utils/param-parser.js +52 -0
- package/dist/utils/param-parser.js.map +1 -0
- package/dist/utils/retention.d.ts +17 -7
- package/dist/utils/retention.d.ts.map +1 -1
- package/dist/utils/retention.js +31 -12
- package/dist/utils/retention.js.map +1 -1
- package/dist/utils/task-stale-detection.d.ts +15 -13
- package/dist/utils/task-stale-detection.d.ts.map +1 -1
- package/dist/utils/task-stale-detection.js +100 -302
- 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/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.map +1 -1
- package/dist/watcher/file-watcher.js +25 -11
- package/dist/watcher/file-watcher.js.map +1 -1
- package/docs/BEST_PRACTICES.md +56 -448
- package/docs/MIGRATION_v3.6.0.md +170 -0
- package/docs/SHARED_CONCEPTS.md +63 -208
- package/docs/TASK_OVERVIEW.md +2 -2
- package/docs/TOOL_SELECTION.md +41 -248
- package/package.json +17 -4
|
@@ -9,25 +9,24 @@
|
|
|
9
9
|
* - Expected: Error thrown, task status unchanged, transaction rolled back
|
|
10
10
|
*/
|
|
11
11
|
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
12
|
-
import assert from 'node:assert/strict';
|
|
13
|
-
import
|
|
14
|
-
import { initializeSchema } from '../schema.js';
|
|
15
|
-
import { runAllMigrations } from '../migrations/index.js';
|
|
12
|
+
import * as assert from 'node:assert/strict';
|
|
13
|
+
import { initializeDatabase, closeDatabase } from '../database.js';
|
|
16
14
|
import { detectAndTransitionToReview } from '../utils/task-stale-detection.js';
|
|
17
15
|
describe('Auto-pruning: Safety check when all files pruned', () => {
|
|
18
16
|
let db;
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
db =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
beforeEach(async () => {
|
|
18
|
+
db = await initializeDatabase({
|
|
19
|
+
databaseType: 'sqlite',
|
|
20
|
+
connection: { filename: ':memory:' }
|
|
21
|
+
});
|
|
24
22
|
});
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
|
|
23
|
+
afterEach(async () => {
|
|
24
|
+
await closeDatabase();
|
|
27
25
|
});
|
|
28
26
|
it('should block transition when all watched files are non-existent', async () => {
|
|
27
|
+
const knex = db.getKnex();
|
|
29
28
|
// 1. Create test task in 'in_progress' status
|
|
30
|
-
const taskId = createTestTask(db);
|
|
29
|
+
const taskId = await createTestTask(db);
|
|
31
30
|
// 2. Add 3 non-existent files to watch list
|
|
32
31
|
// Using paths that will never exist in the test environment
|
|
33
32
|
const nonExistentFiles = [
|
|
@@ -35,27 +34,25 @@ describe('Auto-pruning: Safety check when all files pruned', () => {
|
|
|
35
34
|
'/tmp/never-created-file-2.ts',
|
|
36
35
|
'/tmp/never-created-file-3.ts'
|
|
37
36
|
];
|
|
38
|
-
addWatchedFiles(db, taskId, nonExistentFiles);
|
|
37
|
+
await addWatchedFiles(db, taskId, nonExistentFiles);
|
|
39
38
|
// 3. Make task appear "stale" by backdating its updated_ts
|
|
40
39
|
// Set updated_ts to 10 minutes ago (older than default 3-minute idle threshold)
|
|
41
40
|
const tenMinutesAgo = Math.floor(Date.now() / 1000) - (10 * 60);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
WHERE id = ?
|
|
46
|
-
`).run(tenMinutesAgo, taskId);
|
|
41
|
+
await knex('t_tasks')
|
|
42
|
+
.where({ id: taskId })
|
|
43
|
+
.update({ updated_ts: tenMinutesAgo });
|
|
47
44
|
// 4. Verify task is in 'in_progress' before attempt
|
|
48
|
-
const beforeStatus =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
`).get(taskId);
|
|
45
|
+
const beforeStatus = await knex('t_tasks as t')
|
|
46
|
+
.join('m_task_statuses as s', 't.status_id', 's.id')
|
|
47
|
+
.where('t.id', taskId)
|
|
48
|
+
.select('s.name')
|
|
49
|
+
.first();
|
|
54
50
|
assert.strictEqual(beforeStatus.name, 'in_progress', 'Task should start in in_progress');
|
|
55
51
|
// 5. Verify watch list has all 3 files before attempt
|
|
56
|
-
const beforeWatchCount =
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
const beforeWatchCount = await knex('t_task_file_links')
|
|
53
|
+
.where({ task_id: taskId })
|
|
54
|
+
.count('* as count')
|
|
55
|
+
.first();
|
|
59
56
|
assert.strictEqual(beforeWatchCount.count, 3, 'Watch list should have 3 files before pruning attempt');
|
|
60
57
|
// 6. Attempt transition - should NOT throw at top level
|
|
61
58
|
// The error should be caught internally and logged
|
|
@@ -64,27 +61,29 @@ describe('Auto-pruning: Safety check when all files pruned', () => {
|
|
|
64
61
|
// 7. Verify zero tasks were transitioned
|
|
65
62
|
assert.strictEqual(transitioned, 0, 'No tasks should have been transitioned');
|
|
66
63
|
// 8. Verify task status unchanged (remains in in_progress)
|
|
67
|
-
const afterStatus =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
`).get(taskId);
|
|
64
|
+
const afterStatus = await knex('t_tasks as t')
|
|
65
|
+
.join('m_task_statuses as s', 't.status_id', 's.id')
|
|
66
|
+
.where('t.id', taskId)
|
|
67
|
+
.select('s.name')
|
|
68
|
+
.first();
|
|
73
69
|
assert.strictEqual(afterStatus.name, 'in_progress', 'Task should remain in in_progress after safety check');
|
|
74
70
|
// 9. Verify NO audit records created (transaction rollback)
|
|
75
|
-
const prunedCount =
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
const prunedCount = await knex('t_task_pruned_files')
|
|
72
|
+
.where({ task_id: taskId })
|
|
73
|
+
.count('* as count')
|
|
74
|
+
.first();
|
|
78
75
|
assert.strictEqual(prunedCount.count, 0, 'Should have no pruned file records due to rollback');
|
|
79
76
|
// 10. Verify watch list is NOT empty (transaction rolled back)
|
|
80
|
-
const afterWatchCount =
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
const afterWatchCount = await knex('t_task_file_links')
|
|
78
|
+
.where({ task_id: taskId })
|
|
79
|
+
.count('* as count')
|
|
80
|
+
.first();
|
|
83
81
|
assert.strictEqual(afterWatchCount.count, 3, 'Watch list should still have all 3 files after rollback');
|
|
84
82
|
});
|
|
85
83
|
it('should prune SOME non-existent files and continue (partial prune)', async () => {
|
|
84
|
+
const knex = db.getKnex();
|
|
86
85
|
// Create task
|
|
87
|
-
const taskId = createTestTask(db);
|
|
86
|
+
const taskId = await createTestTask(db);
|
|
88
87
|
// Add mix of existent and non-existent files
|
|
89
88
|
// Use package.json as a file that definitely exists in the project root
|
|
90
89
|
const mixedFiles = [
|
|
@@ -92,60 +91,58 @@ describe('Auto-pruning: Safety check when all files pruned', () => {
|
|
|
92
91
|
'/tmp/never-created-file-1.ts', // does not exist
|
|
93
92
|
'/tmp/never-created-file-2.ts' // does not exist
|
|
94
93
|
];
|
|
95
|
-
addWatchedFiles(db, taskId, mixedFiles);
|
|
94
|
+
await addWatchedFiles(db, taskId, mixedFiles);
|
|
96
95
|
// Make task appear stale
|
|
97
96
|
const tenMinutesAgo = Math.floor(Date.now() / 1000) - (10 * 60);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
WHERE id = ?
|
|
102
|
-
`).run(tenMinutesAgo, taskId);
|
|
97
|
+
await knex('t_tasks')
|
|
98
|
+
.where({ id: taskId })
|
|
99
|
+
.update({ updated_ts: tenMinutesAgo });
|
|
103
100
|
// Verify initial watch count
|
|
104
|
-
const beforeWatchCount =
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
const beforeWatchCount = await knex('t_task_file_links')
|
|
102
|
+
.where({ task_id: taskId })
|
|
103
|
+
.count('* as count')
|
|
104
|
+
.first();
|
|
107
105
|
assert.strictEqual(beforeWatchCount.count, 3, 'Watch list should start with 3 files');
|
|
108
106
|
// Attempt transition - should proceed with partial pruning
|
|
109
107
|
await detectAndTransitionToReview(db);
|
|
110
108
|
// Verify some files were pruned
|
|
111
|
-
const prunedCount =
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
const prunedCount = await knex('t_task_pruned_files')
|
|
110
|
+
.where({ task_id: taskId })
|
|
111
|
+
.count('* as count')
|
|
112
|
+
.first();
|
|
114
113
|
assert.strictEqual(prunedCount.count, 2, 'Should have 2 pruned file records (the non-existent ones)');
|
|
115
114
|
// Verify watch list now has only 1 file (the existing one)
|
|
116
|
-
const afterWatchCount =
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
const afterWatchCount = await knex('t_task_file_links')
|
|
116
|
+
.where({ task_id: taskId })
|
|
117
|
+
.count('* as count')
|
|
118
|
+
.first();
|
|
119
119
|
assert.strictEqual(afterWatchCount.count, 1, 'Watch list should have 1 remaining file after partial prune');
|
|
120
120
|
// Verify remaining file is package.json
|
|
121
|
-
const remainingFile =
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
`).get(taskId);
|
|
121
|
+
const remainingFile = await knex('t_task_file_links as tfl')
|
|
122
|
+
.join('m_files as f', 'tfl.file_id', 'f.id')
|
|
123
|
+
.where('tfl.task_id', taskId)
|
|
124
|
+
.select('f.path')
|
|
125
|
+
.first();
|
|
127
126
|
assert.strictEqual(remainingFile.path, 'package.json', 'Remaining file should be package.json');
|
|
128
127
|
});
|
|
129
128
|
it('should handle task with no watched files gracefully', async () => {
|
|
129
|
+
const knex = db.getKnex();
|
|
130
130
|
// Create task without any watched files
|
|
131
|
-
const taskId = createTestTask(db);
|
|
131
|
+
const taskId = await createTestTask(db);
|
|
132
132
|
// Make task appear stale
|
|
133
133
|
const tenMinutesAgo = Math.floor(Date.now() / 1000) - (10 * 60);
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
WHERE id = ?
|
|
138
|
-
`).run(tenMinutesAgo, taskId);
|
|
134
|
+
await knex('t_tasks')
|
|
135
|
+
.where({ id: taskId })
|
|
136
|
+
.update({ updated_ts: tenMinutesAgo });
|
|
139
137
|
// Attempt transition - should skip this task
|
|
140
138
|
const transitioned = await detectAndTransitionToReview(db);
|
|
141
139
|
assert.strictEqual(transitioned, 0, 'Should not transition task with no watched files');
|
|
142
140
|
// Verify task status unchanged
|
|
143
|
-
const status =
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
`).get(taskId);
|
|
141
|
+
const status = await knex('t_tasks as t')
|
|
142
|
+
.join('m_task_statuses as s', 't.status_id', 's.id')
|
|
143
|
+
.where('t.id', taskId)
|
|
144
|
+
.select('s.name')
|
|
145
|
+
.first();
|
|
149
146
|
assert.strictEqual(status.name, 'in_progress', 'Task should remain in in_progress');
|
|
150
147
|
});
|
|
151
148
|
console.log('\n✅ All auto-pruning safety check tests passed!\n');
|
|
@@ -153,44 +150,68 @@ describe('Auto-pruning: Safety check when all files pruned', () => {
|
|
|
153
150
|
/**
|
|
154
151
|
* Helper: Create a test task in 'in_progress' status
|
|
155
152
|
*/
|
|
156
|
-
function createTestTask(db) {
|
|
153
|
+
async function createTestTask(db) {
|
|
154
|
+
const knex = db.getKnex();
|
|
157
155
|
// Create test agent
|
|
158
|
-
const agentId =
|
|
159
|
-
|
|
160
|
-
|
|
156
|
+
const [agentId] = await knex('m_agents')
|
|
157
|
+
.insert({ name: 'test-agent' })
|
|
158
|
+
.onConflict('name')
|
|
159
|
+
.ignore()
|
|
160
|
+
.returning('id');
|
|
161
|
+
// If insert was ignored, get the existing agent
|
|
162
|
+
let actualAgentId;
|
|
163
|
+
if (agentId) {
|
|
164
|
+
actualAgentId = agentId.id || agentId;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
const agent = await knex('m_agents')
|
|
168
|
+
.where({ name: 'test-agent' })
|
|
169
|
+
.select('id')
|
|
170
|
+
.first();
|
|
171
|
+
actualAgentId = agent.id;
|
|
172
|
+
}
|
|
161
173
|
// Get 'in_progress' status ID
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
174
|
+
const statusRow = await knex('m_task_statuses')
|
|
175
|
+
.where({ name: 'in_progress' })
|
|
176
|
+
.select('id')
|
|
177
|
+
.first();
|
|
165
178
|
// Create task with updated_ts set to now (will be backdated in tests)
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return taskId.id;
|
|
179
|
+
const currentTs = Math.floor(Date.now() / 1000);
|
|
180
|
+
const [taskId] = await knex('t_tasks')
|
|
181
|
+
.insert({
|
|
182
|
+
title: 'Test task for auto-pruning',
|
|
183
|
+
status_id: statusRow.id,
|
|
184
|
+
priority: 2,
|
|
185
|
+
assigned_agent_id: actualAgentId,
|
|
186
|
+
created_by_agent_id: actualAgentId,
|
|
187
|
+
created_ts: currentTs,
|
|
188
|
+
updated_ts: currentTs
|
|
189
|
+
})
|
|
190
|
+
.returning('id');
|
|
191
|
+
return taskId.id || taskId;
|
|
180
192
|
}
|
|
181
193
|
/**
|
|
182
194
|
* Helper: Add watched files to a task
|
|
183
195
|
*/
|
|
184
|
-
function addWatchedFiles(db, taskId, filePaths) {
|
|
185
|
-
const
|
|
186
|
-
INSERT OR IGNORE INTO m_files (path) VALUES (?) RETURNING id
|
|
187
|
-
`);
|
|
188
|
-
const linkFile = db.prepare(`
|
|
189
|
-
INSERT INTO t_task_file_links (task_id, file_id) VALUES (?, ?)
|
|
190
|
-
`);
|
|
196
|
+
async function addWatchedFiles(db, taskId, filePaths) {
|
|
197
|
+
const knex = db.getKnex();
|
|
191
198
|
for (const filePath of filePaths) {
|
|
192
|
-
|
|
193
|
-
|
|
199
|
+
// Insert file (ignore if exists)
|
|
200
|
+
await knex('m_files')
|
|
201
|
+
.insert({ path: filePath })
|
|
202
|
+
.onConflict('path')
|
|
203
|
+
.ignore();
|
|
204
|
+
// Get file ID
|
|
205
|
+
const fileRow = await knex('m_files')
|
|
206
|
+
.where({ path: filePath })
|
|
207
|
+
.select('id')
|
|
208
|
+
.first();
|
|
209
|
+
// Link file to task
|
|
210
|
+
await knex('t_task_file_links')
|
|
211
|
+
.insert({
|
|
212
|
+
task_id: taskId,
|
|
213
|
+
file_id: fileRow.id
|
|
214
|
+
});
|
|
194
215
|
}
|
|
195
216
|
}
|
|
196
217
|
//# sourceMappingURL=tasks.auto-pruning-safety.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks.auto-pruning-safety.test.js","sourceRoot":"","sources":["../../src/tests/tasks.auto-pruning-safety.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,MAAM,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"tasks.auto-pruning-safety.test.js","sourceRoot":"","sources":["../../src/tests/tasks.auto-pruning-safety.test.ts"],"names":[],"mappings":"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"}
|