@jamesaphoenix/tx-core 0.5.8 → 0.5.9
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/dist/services/migration-service.d.ts.map +1 -1
- package/dist/services/migration-service.js +12 -7
- package/dist/services/migration-service.js.map +1 -1
- package/migrations/001_initial.sql +57 -0
- package/migrations/002_learnings.sql +64 -0
- package/migrations/003_file_learnings.sql +19 -0
- package/migrations/004_attempts.sql +18 -0
- package/migrations/005_runs.sql +34 -0
- package/migrations/006_events.sql +33 -0
- package/migrations/007_sync_config.sql +18 -0
- package/migrations/008_learning_anchors.sql +28 -0
- package/migrations/009_learning_edges.sql +43 -0
- package/migrations/010_learning_candidates.sql +30 -0
- package/migrations/011_processed_hashes.sql +35 -0
- package/migrations/012_invalidation.sql +32 -0
- package/migrations/013_content_preview.sql +13 -0
- package/migrations/014_daemon_tracked_projects.sql +20 -0
- package/migrations/015_worker_orchestration.sql +64 -0
- package/migrations/016_tracing_io_paths.sql +13 -0
- package/migrations/017_span_metric_events.sql +47 -0
- package/migrations/018_compaction_learnings.sql +15 -0
- package/migrations/019_tasks_updated_at_index.sql +11 -0
- package/migrations/020_task_id_check.sql +32 -0
- package/migrations/021_agent_outbox.sql +34 -0
- package/migrations/022_docs_as_primitives.sql +66 -0
- package/migrations/023_task_labels.sql +29 -0
- package/migrations/024_task_assignment.sql +27 -0
- package/migrations/025_run_heartbeat_state.sql +21 -0
- package/migrations/026_task_order_composite_indexes.sql +17 -0
- package/migrations/027_runs_events_hot_query_indexes.sql +35 -0
- package/migrations/028_task_group_context.sql +13 -0
- package/package.json +3 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-service.d.ts","sourceRoot":"","sources":["../../src/services/migration-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"migration-service.d.ts","sourceRoot":"","sources":["../../src/services/migration-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAK/C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,SAAS,gBAAgB,EAAE,CAAA;IACvD,QAAQ,CAAC,iBAAiB,EAAE,SAAS,SAAS,EAAE,CAAA;CACjD;AAwED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,SAAS,EAAkC,CAAA;AAE7E;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAAO,MAGnC,CAAA;;IASG;;;OAGG;wBACiB,MAAM,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC;IAEvE;;;;OAIG;kBACW,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAExD;;OAEG;gCACyB,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAEtE;;OAEG;mCAC4B,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,gBAAgB,EAAE,EAAE,aAAa,CAAC;;AA5BlG;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,qBA0BnC;CAAG;AAEN,eAAO,MAAM,oBAAoB,oDAkFhC,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
2
3
|
import { readdir, readFile } from "node:fs/promises";
|
|
3
4
|
import { dirname, join, resolve } from "node:path";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -6,16 +7,20 @@ import { SqliteClient } from "../db.js";
|
|
|
6
7
|
import { DatabaseError } from "../errors.js";
|
|
7
8
|
/**
|
|
8
9
|
* Get the migrations directory path.
|
|
9
|
-
*
|
|
10
|
+
* Checks two locations:
|
|
11
|
+
* 1. Package-local: ../../migrations relative to this file (works for npm installs
|
|
12
|
+
* where migrations/ is copied into the package during build)
|
|
13
|
+
* 2. Monorepo root: ../../../../migrations (works in monorepo development)
|
|
10
14
|
*/
|
|
11
15
|
const getMigrationsDir = () => {
|
|
12
|
-
// When running from source (src/services/migration-service.ts)
|
|
13
|
-
// or from dist (dist/services/migration-service.js),
|
|
14
|
-
// we need to go up to the package root and then into migrations/
|
|
15
16
|
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
//
|
|
17
|
-
const
|
|
18
|
-
|
|
17
|
+
// From src/services/ or dist/services/, up 2 levels = package root
|
|
18
|
+
const packageLocal = resolve(currentDir, "..", "..", "migrations");
|
|
19
|
+
if (existsSync(packageLocal))
|
|
20
|
+
return packageLocal;
|
|
21
|
+
// Fallback: monorepo root (up 4 levels from packages/core/src/services/)
|
|
22
|
+
const monorepoRoot = resolve(currentDir, "..", "..", "..", "..", "migrations");
|
|
23
|
+
return monorepoRoot;
|
|
19
24
|
};
|
|
20
25
|
/**
|
|
21
26
|
* Parse a migration filename to extract version and description.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-service.js","sourceRoot":"","sources":["../../src/services/migration-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AA8B5C
|
|
1
|
+
{"version":3,"file":"migration-service.js","sourceRoot":"","sources":["../../src/services/migration-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
-- Version: 001
|
|
2
|
+
-- Migration: initial
|
|
3
|
+
|
|
4
|
+
-- Core tasks table
|
|
5
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
6
|
+
id TEXT PRIMARY KEY,
|
|
7
|
+
title TEXT NOT NULL,
|
|
8
|
+
description TEXT DEFAULT '',
|
|
9
|
+
status TEXT NOT NULL DEFAULT 'backlog'
|
|
10
|
+
CHECK (status IN (
|
|
11
|
+
'backlog', 'ready', 'planning', 'active',
|
|
12
|
+
'blocked', 'review', 'human_needs_to_review', 'done'
|
|
13
|
+
)),
|
|
14
|
+
parent_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
15
|
+
score INTEGER NOT NULL DEFAULT 0,
|
|
16
|
+
created_at TEXT NOT NULL,
|
|
17
|
+
updated_at TEXT NOT NULL,
|
|
18
|
+
completed_at TEXT,
|
|
19
|
+
metadata TEXT DEFAULT '{}'
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
-- Dependency relationships
|
|
23
|
+
CREATE TABLE IF NOT EXISTS task_dependencies (
|
|
24
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
25
|
+
blocker_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
26
|
+
blocked_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
27
|
+
created_at TEXT NOT NULL,
|
|
28
|
+
UNIQUE(blocker_id, blocked_id),
|
|
29
|
+
CHECK (blocker_id != blocked_id)
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
-- Compaction history
|
|
33
|
+
CREATE TABLE IF NOT EXISTS compaction_log (
|
|
34
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
35
|
+
compacted_at TEXT NOT NULL,
|
|
36
|
+
task_count INTEGER NOT NULL,
|
|
37
|
+
summary TEXT NOT NULL,
|
|
38
|
+
task_ids TEXT NOT NULL,
|
|
39
|
+
learnings_exported_to TEXT
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
-- Schema version tracking
|
|
43
|
+
CREATE TABLE IF NOT EXISTS schema_version (
|
|
44
|
+
version INTEGER PRIMARY KEY,
|
|
45
|
+
applied_at TEXT NOT NULL
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
-- Indexes
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_parent ON tasks(parent_id);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_score ON tasks(score DESC);
|
|
52
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_created ON tasks(created_at);
|
|
53
|
+
CREATE INDEX IF NOT EXISTS idx_deps_blocker ON task_dependencies(blocker_id);
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_deps_blocked ON task_dependencies(blocked_id);
|
|
55
|
+
|
|
56
|
+
-- Record this migration
|
|
57
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (1, datetime('now'));
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
-- Version: 002
|
|
2
|
+
-- Migration: Learnings table with FTS5 for BM25 search
|
|
3
|
+
|
|
4
|
+
-- Learnings table (append-only event log)
|
|
5
|
+
CREATE TABLE IF NOT EXISTS learnings (
|
|
6
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
7
|
+
content TEXT NOT NULL,
|
|
8
|
+
source_type TEXT NOT NULL CHECK (source_type IN ('compaction', 'run', 'manual', 'claude_md')),
|
|
9
|
+
source_ref TEXT,
|
|
10
|
+
created_at TEXT NOT NULL,
|
|
11
|
+
keywords TEXT,
|
|
12
|
+
category TEXT,
|
|
13
|
+
usage_count INTEGER NOT NULL DEFAULT 0,
|
|
14
|
+
last_used_at TEXT,
|
|
15
|
+
outcome_score REAL,
|
|
16
|
+
embedding BLOB
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
-- FTS5 for BM25 keyword search
|
|
20
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS learnings_fts USING fts5(
|
|
21
|
+
content, keywords, category,
|
|
22
|
+
content='learnings', content_rowid='id',
|
|
23
|
+
tokenize='porter unicode61'
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
-- Triggers to sync FTS on insert
|
|
27
|
+
CREATE TRIGGER IF NOT EXISTS learnings_ai AFTER INSERT ON learnings BEGIN
|
|
28
|
+
INSERT INTO learnings_fts(rowid, content, keywords, category)
|
|
29
|
+
VALUES (new.id, new.content, new.keywords, new.category);
|
|
30
|
+
END;
|
|
31
|
+
|
|
32
|
+
-- Triggers to sync FTS on delete
|
|
33
|
+
CREATE TRIGGER IF NOT EXISTS learnings_ad AFTER DELETE ON learnings BEGIN
|
|
34
|
+
INSERT INTO learnings_fts(learnings_fts, rowid, content, keywords, category)
|
|
35
|
+
VALUES ('delete', old.id, old.content, old.keywords, old.category);
|
|
36
|
+
END;
|
|
37
|
+
|
|
38
|
+
-- Triggers to sync FTS on update
|
|
39
|
+
CREATE TRIGGER IF NOT EXISTS learnings_au AFTER UPDATE ON learnings BEGIN
|
|
40
|
+
INSERT INTO learnings_fts(learnings_fts, rowid, content, keywords, category)
|
|
41
|
+
VALUES ('delete', old.id, old.content, old.keywords, old.category);
|
|
42
|
+
INSERT INTO learnings_fts(rowid, content, keywords, category)
|
|
43
|
+
VALUES (new.id, new.content, new.keywords, new.category);
|
|
44
|
+
END;
|
|
45
|
+
|
|
46
|
+
-- Config for retrieval weights
|
|
47
|
+
CREATE TABLE IF NOT EXISTS learnings_config (
|
|
48
|
+
key TEXT PRIMARY KEY,
|
|
49
|
+
value TEXT NOT NULL
|
|
50
|
+
);
|
|
51
|
+
INSERT OR IGNORE INTO learnings_config (key, value) VALUES
|
|
52
|
+
('bm25_weight', '0.4'),
|
|
53
|
+
('vector_weight', '0.4'),
|
|
54
|
+
('recency_weight', '0.2');
|
|
55
|
+
|
|
56
|
+
-- Indexes for common queries
|
|
57
|
+
CREATE INDEX IF NOT EXISTS idx_learnings_created ON learnings(created_at DESC);
|
|
58
|
+
CREATE INDEX IF NOT EXISTS idx_learnings_source_type ON learnings(source_type);
|
|
59
|
+
CREATE INDEX IF NOT EXISTS idx_learnings_usage ON learnings(usage_count DESC);
|
|
60
|
+
CREATE INDEX IF NOT EXISTS idx_learnings_outcome ON learnings(outcome_score DESC);
|
|
61
|
+
CREATE INDEX IF NOT EXISTS idx_learnings_category ON learnings(category);
|
|
62
|
+
|
|
63
|
+
-- Record this migration
|
|
64
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (2, datetime('now'));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- Version: 003
|
|
2
|
+
-- Migration: File learnings table for path-based knowledge
|
|
3
|
+
|
|
4
|
+
-- File learnings table (path-based knowledge storage)
|
|
5
|
+
CREATE TABLE IF NOT EXISTS file_learnings (
|
|
6
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
7
|
+
file_pattern TEXT NOT NULL,
|
|
8
|
+
note TEXT NOT NULL,
|
|
9
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
10
|
+
created_at TEXT NOT NULL
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
-- Index for file pattern lookups
|
|
14
|
+
CREATE INDEX IF NOT EXISTS idx_file_learnings_pattern ON file_learnings(file_pattern);
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_file_learnings_created ON file_learnings(created_at DESC);
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_file_learnings_task ON file_learnings(task_id);
|
|
17
|
+
|
|
18
|
+
-- Record this migration
|
|
19
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (3, datetime('now'));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- Version: 004
|
|
2
|
+
-- Migration: Attempts table for tracking task attempt outcomes
|
|
3
|
+
|
|
4
|
+
-- Attempts table (track failed/succeeded approaches per task)
|
|
5
|
+
CREATE TABLE IF NOT EXISTS attempts (
|
|
6
|
+
id INTEGER PRIMARY KEY,
|
|
7
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
8
|
+
approach TEXT NOT NULL,
|
|
9
|
+
outcome TEXT NOT NULL CHECK (outcome IN ('failed', 'succeeded')),
|
|
10
|
+
reason TEXT,
|
|
11
|
+
created_at TEXT NOT NULL
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
-- Index for task_id lookups
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_attempts_task_id ON attempts(task_id);
|
|
16
|
+
|
|
17
|
+
-- Record this migration
|
|
18
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (4, datetime('now'));
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
-- Version: 005
|
|
2
|
+
-- Migration: Runs table for tracking Claude agent sessions
|
|
3
|
+
|
|
4
|
+
-- Runs table (track each Claude agent session)
|
|
5
|
+
CREATE TABLE IF NOT EXISTS runs (
|
|
6
|
+
id TEXT PRIMARY KEY, -- run-<sha8>
|
|
7
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
8
|
+
agent TEXT NOT NULL, -- tx-implementer, tx-decomposer, etc.
|
|
9
|
+
started_at TEXT NOT NULL,
|
|
10
|
+
ended_at TEXT,
|
|
11
|
+
status TEXT NOT NULL DEFAULT 'running'
|
|
12
|
+
CHECK (status IN ('running', 'completed', 'failed', 'timeout', 'cancelled')),
|
|
13
|
+
exit_code INTEGER,
|
|
14
|
+
pid INTEGER, -- OS process ID
|
|
15
|
+
transcript_path TEXT, -- Path to conversation .jsonl file
|
|
16
|
+
context_injected TEXT, -- Path to context.md that was injected
|
|
17
|
+
summary TEXT, -- LLM-generated summary of what happened
|
|
18
|
+
error_message TEXT, -- If failed, why
|
|
19
|
+
metadata TEXT DEFAULT '{}' -- JSON: git_sha, branch, iteration, etc.
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
-- Link learnings to runs (which run produced this learning?)
|
|
23
|
+
-- Note: learnings table already exists, just adding the column
|
|
24
|
+
ALTER TABLE learnings ADD COLUMN run_id TEXT REFERENCES runs(id) ON DELETE SET NULL;
|
|
25
|
+
|
|
26
|
+
-- Indexes for common queries
|
|
27
|
+
CREATE INDEX IF NOT EXISTS idx_runs_task ON runs(task_id);
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_runs_status ON runs(status);
|
|
29
|
+
CREATE INDEX IF NOT EXISTS idx_runs_started ON runs(started_at DESC);
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_runs_agent ON runs(agent);
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_learnings_run ON learnings(run_id);
|
|
32
|
+
|
|
33
|
+
-- Record this migration
|
|
34
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (5, datetime('now'));
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
-- Version: 006
|
|
2
|
+
-- Migration: Events table for append-only activity tracking
|
|
3
|
+
|
|
4
|
+
-- Events table (append-only log of all activity for replay/analysis)
|
|
5
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
6
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
7
|
+
timestamp TEXT NOT NULL,
|
|
8
|
+
event_type TEXT NOT NULL CHECK (event_type IN (
|
|
9
|
+
'run_started', 'run_completed', 'run_failed',
|
|
10
|
+
'task_created', 'task_updated', 'task_completed',
|
|
11
|
+
'tool_call', 'tool_result',
|
|
12
|
+
'user_message', 'assistant_message',
|
|
13
|
+
'error', 'learning_captured',
|
|
14
|
+
'commit', 'review'
|
|
15
|
+
)),
|
|
16
|
+
run_id TEXT REFERENCES runs(id) ON DELETE SET NULL,
|
|
17
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
18
|
+
agent TEXT,
|
|
19
|
+
tool_name TEXT,
|
|
20
|
+
content TEXT,
|
|
21
|
+
metadata TEXT DEFAULT '{}',
|
|
22
|
+
duration_ms INTEGER
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
-- Indexes for efficient querying
|
|
26
|
+
CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp DESC);
|
|
27
|
+
CREATE INDEX IF NOT EXISTS idx_events_type ON events(event_type);
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_events_run ON events(run_id);
|
|
29
|
+
CREATE INDEX IF NOT EXISTS idx_events_task ON events(task_id);
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_events_agent ON events(agent);
|
|
31
|
+
|
|
32
|
+
-- Record this migration
|
|
33
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (6, datetime('now'));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- Version: 007
|
|
2
|
+
-- Migration: Sync config table for JSONL sync daemon settings
|
|
3
|
+
|
|
4
|
+
-- Sync config table (key-value store for sync settings)
|
|
5
|
+
CREATE TABLE IF NOT EXISTS sync_config (
|
|
6
|
+
key TEXT PRIMARY KEY,
|
|
7
|
+
value TEXT NOT NULL,
|
|
8
|
+
updated_at TEXT NOT NULL
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
-- Default values
|
|
12
|
+
INSERT OR IGNORE INTO sync_config (key, value, updated_at) VALUES
|
|
13
|
+
('auto_sync', 'false', datetime('now')),
|
|
14
|
+
('last_export', '', datetime('now')),
|
|
15
|
+
('last_import', '', datetime('now'));
|
|
16
|
+
|
|
17
|
+
-- Record this migration
|
|
18
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (7, datetime('now'));
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-- Version: 008
|
|
2
|
+
-- Migration: Learning anchors table for file-code associations
|
|
3
|
+
|
|
4
|
+
-- Learning anchors table (file/code associations for learnings)
|
|
5
|
+
CREATE TABLE IF NOT EXISTS learning_anchors (
|
|
6
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
7
|
+
learning_id INTEGER NOT NULL REFERENCES learnings(id) ON DELETE CASCADE,
|
|
8
|
+
anchor_type TEXT NOT NULL CHECK (anchor_type IN ('glob', 'hash', 'symbol', 'line_range')),
|
|
9
|
+
anchor_value TEXT NOT NULL,
|
|
10
|
+
file_path TEXT NOT NULL,
|
|
11
|
+
symbol_fqname TEXT,
|
|
12
|
+
line_start INTEGER,
|
|
13
|
+
line_end INTEGER,
|
|
14
|
+
content_hash TEXT,
|
|
15
|
+
status TEXT NOT NULL DEFAULT 'valid' CHECK (status IN ('valid', 'invalid', 'drifted')),
|
|
16
|
+
verified_at TEXT,
|
|
17
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
-- Indexes for graph traversal and common queries
|
|
21
|
+
CREATE INDEX IF NOT EXISTS idx_learning_anchors_learning_id ON learning_anchors(learning_id);
|
|
22
|
+
CREATE INDEX IF NOT EXISTS idx_learning_anchors_file_path ON learning_anchors(file_path);
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_learning_anchors_status ON learning_anchors(status);
|
|
24
|
+
CREATE INDEX IF NOT EXISTS idx_learning_anchors_anchor_type ON learning_anchors(anchor_type);
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_learning_anchors_symbol ON learning_anchors(symbol_fqname) WHERE symbol_fqname IS NOT NULL;
|
|
26
|
+
|
|
27
|
+
-- Record this migration
|
|
28
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (8, datetime('now'));
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
-- Version: 009
|
|
2
|
+
-- Migration: Learning edges table for graph relationships
|
|
3
|
+
|
|
4
|
+
-- Learning edges table (graph relationships between nodes)
|
|
5
|
+
-- Supports edge types: ANCHORED_TO, DERIVED_FROM, IMPORTS, CO_CHANGES_WITH, SIMILAR_TO, LINKS_TO, USED_IN_RUN, INVALIDATED_BY
|
|
6
|
+
-- Node types: learning, file, task, run
|
|
7
|
+
CREATE TABLE IF NOT EXISTS learning_edges (
|
|
8
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9
|
+
edge_type TEXT NOT NULL CHECK (edge_type IN (
|
|
10
|
+
'ANCHORED_TO',
|
|
11
|
+
'DERIVED_FROM',
|
|
12
|
+
'IMPORTS',
|
|
13
|
+
'CO_CHANGES_WITH',
|
|
14
|
+
'SIMILAR_TO',
|
|
15
|
+
'LINKS_TO',
|
|
16
|
+
'USED_IN_RUN',
|
|
17
|
+
'INVALIDATED_BY'
|
|
18
|
+
)),
|
|
19
|
+
source_type TEXT NOT NULL CHECK (source_type IN ('learning', 'file', 'task', 'run')),
|
|
20
|
+
source_id TEXT NOT NULL,
|
|
21
|
+
target_type TEXT NOT NULL CHECK (target_type IN ('learning', 'file', 'task', 'run')),
|
|
22
|
+
target_id TEXT NOT NULL,
|
|
23
|
+
weight REAL NOT NULL DEFAULT 1.0 CHECK (weight >= 0.0 AND weight <= 1.0),
|
|
24
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
25
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
26
|
+
invalidated_at TEXT
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
-- Indexes for graph traversal
|
|
30
|
+
-- Source-based lookups (outgoing edges)
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_learning_edges_source ON learning_edges(source_type, source_id);
|
|
32
|
+
-- Target-based lookups (incoming edges)
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_learning_edges_target ON learning_edges(target_type, target_id);
|
|
34
|
+
-- Edge type filtering
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_learning_edges_type ON learning_edges(edge_type);
|
|
36
|
+
-- Active edges only (not invalidated) - partial index for efficient traversal
|
|
37
|
+
CREATE INDEX IF NOT EXISTS idx_learning_edges_active ON learning_edges(source_type, source_id) WHERE invalidated_at IS NULL;
|
|
38
|
+
-- Composite index for bidirectional traversal with edge type filtering
|
|
39
|
+
CREATE INDEX IF NOT EXISTS idx_learning_edges_source_type ON learning_edges(source_type, source_id, edge_type) WHERE invalidated_at IS NULL;
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_learning_edges_target_type ON learning_edges(target_type, target_id, edge_type) WHERE invalidated_at IS NULL;
|
|
41
|
+
|
|
42
|
+
-- Record this migration
|
|
43
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (9, datetime('now'));
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
-- Version: 010
|
|
2
|
+
-- Migration: Learning candidates table for telemetry extraction pipeline
|
|
3
|
+
|
|
4
|
+
-- Learning candidates awaiting promotion to learnings table
|
|
5
|
+
-- See PRD-015: JSONL Telemetry Daemon and Knowledge Promotion Pipeline
|
|
6
|
+
CREATE TABLE IF NOT EXISTS learning_candidates (
|
|
7
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
8
|
+
content TEXT NOT NULL,
|
|
9
|
+
confidence TEXT NOT NULL CHECK (confidence IN ('high', 'medium', 'low')),
|
|
10
|
+
category TEXT,
|
|
11
|
+
source_file TEXT NOT NULL,
|
|
12
|
+
source_run_id TEXT,
|
|
13
|
+
source_task_id TEXT,
|
|
14
|
+
extracted_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
15
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'promoted', 'rejected', 'merged')),
|
|
16
|
+
reviewed_at TEXT,
|
|
17
|
+
reviewed_by TEXT, -- 'auto' or user identifier
|
|
18
|
+
promoted_learning_id INTEGER,
|
|
19
|
+
rejection_reason TEXT,
|
|
20
|
+
FOREIGN KEY (promoted_learning_id) REFERENCES learnings(id) ON DELETE SET NULL
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
-- Indexes for efficient queries
|
|
24
|
+
CREATE INDEX IF NOT EXISTS idx_learning_candidates_status ON learning_candidates(status);
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_learning_candidates_confidence ON learning_candidates(confidence);
|
|
26
|
+
CREATE INDEX IF NOT EXISTS idx_learning_candidates_source ON learning_candidates(source_file);
|
|
27
|
+
CREATE INDEX IF NOT EXISTS idx_learning_candidates_extracted ON learning_candidates(extracted_at);
|
|
28
|
+
|
|
29
|
+
-- Record this migration
|
|
30
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (10, datetime('now'));
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
-- Version: 011
|
|
2
|
+
-- Migration: Processed hashes table for JSONL line deduplication
|
|
3
|
+
|
|
4
|
+
-- Track processed JSONL line hashes for deduplication
|
|
5
|
+
-- Each unique line (by content hash) is recorded once to avoid re-processing
|
|
6
|
+
CREATE TABLE IF NOT EXISTS processed_hashes (
|
|
7
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
8
|
+
content_hash TEXT NOT NULL UNIQUE, -- SHA256 of the JSONL line content
|
|
9
|
+
source_file TEXT NOT NULL, -- First file where this line was seen
|
|
10
|
+
source_line INTEGER NOT NULL, -- Line number in source file (1-indexed)
|
|
11
|
+
processed_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
-- Index for fast hash lookups (most common operation)
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_processed_hashes_hash ON processed_hashes(content_hash);
|
|
16
|
+
-- Index for querying by source file
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_processed_hashes_file ON processed_hashes(source_file);
|
|
18
|
+
|
|
19
|
+
-- Track file processing progress for incremental processing
|
|
20
|
+
-- Allows resuming from last position when a file changes
|
|
21
|
+
CREATE TABLE IF NOT EXISTS file_progress (
|
|
22
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
file_path TEXT NOT NULL UNIQUE, -- Absolute path to the JSONL file
|
|
24
|
+
last_line_processed INTEGER DEFAULT 0, -- Last line number processed (1-indexed)
|
|
25
|
+
last_byte_offset INTEGER DEFAULT 0, -- Byte offset for streaming resume
|
|
26
|
+
file_size INTEGER, -- Size at last processing time
|
|
27
|
+
file_checksum TEXT, -- SHA256 of file content at last processing
|
|
28
|
+
last_processed_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
-- Index for file path lookups
|
|
32
|
+
CREATE INDEX IF NOT EXISTS idx_file_progress_path ON file_progress(file_path);
|
|
33
|
+
|
|
34
|
+
-- Record this migration
|
|
35
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (11, datetime('now'));
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
-- Version: 012
|
|
2
|
+
-- Migration: Invalidation tracking and pinned anchors for PRD-017
|
|
3
|
+
|
|
4
|
+
-- Add pinned column to learning_anchors
|
|
5
|
+
ALTER TABLE learning_anchors ADD COLUMN pinned INTEGER NOT NULL DEFAULT 0;
|
|
6
|
+
|
|
7
|
+
-- Invalidation audit log
|
|
8
|
+
CREATE TABLE IF NOT EXISTS invalidation_log (
|
|
9
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
10
|
+
anchor_id INTEGER NOT NULL,
|
|
11
|
+
old_status TEXT NOT NULL,
|
|
12
|
+
new_status TEXT NOT NULL,
|
|
13
|
+
reason TEXT NOT NULL,
|
|
14
|
+
detected_by TEXT NOT NULL CHECK (detected_by IN ('periodic', 'lazy', 'manual', 'agent', 'git_hook')),
|
|
15
|
+
old_content_hash TEXT,
|
|
16
|
+
new_content_hash TEXT,
|
|
17
|
+
similarity_score REAL,
|
|
18
|
+
invalidated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
19
|
+
FOREIGN KEY (anchor_id) REFERENCES learning_anchors(id) ON DELETE CASCADE
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
-- Indexes for invalidation_log
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_invalidation_anchor ON invalidation_log(anchor_id);
|
|
24
|
+
CREATE INDEX IF NOT EXISTS idx_invalidation_time ON invalidation_log(invalidated_at);
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_invalidation_status ON invalidation_log(new_status);
|
|
26
|
+
CREATE INDEX IF NOT EXISTS idx_invalidation_detected_by ON invalidation_log(detected_by);
|
|
27
|
+
|
|
28
|
+
-- Index for pinned anchors
|
|
29
|
+
CREATE INDEX IF NOT EXISTS idx_learning_anchors_pinned ON learning_anchors(pinned) WHERE pinned = 1;
|
|
30
|
+
|
|
31
|
+
-- Record this migration
|
|
32
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (12, datetime('now'));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- Version: 013
|
|
2
|
+
-- Migration: Add content_preview for self-healing comparison (PRD-017)
|
|
3
|
+
|
|
4
|
+
-- Add content_preview column to store original content snippet for Jaccard similarity
|
|
5
|
+
-- Used by self-healing to compare old vs new content when anchors drift
|
|
6
|
+
ALTER TABLE learning_anchors ADD COLUMN content_preview TEXT;
|
|
7
|
+
|
|
8
|
+
-- Index for faster lookups when content_preview is present
|
|
9
|
+
CREATE INDEX IF NOT EXISTS idx_learning_anchors_has_preview
|
|
10
|
+
ON learning_anchors(content_hash) WHERE content_preview IS NOT NULL;
|
|
11
|
+
|
|
12
|
+
-- Record this migration
|
|
13
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (13, datetime('now'));
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- Version: 014
|
|
2
|
+
-- Migration: Daemon tracked projects for opt-in project monitoring (PRD-015)
|
|
3
|
+
|
|
4
|
+
-- Tracked projects for the daemon to watch for JSONL transcript processing
|
|
5
|
+
-- Users explicitly opt-in projects via `tx daemon track <path>`
|
|
6
|
+
CREATE TABLE IF NOT EXISTS daemon_tracked_projects (
|
|
7
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
8
|
+
project_path TEXT NOT NULL UNIQUE,
|
|
9
|
+
project_id TEXT,
|
|
10
|
+
source_type TEXT DEFAULT 'claude' CHECK (source_type IN ('claude', 'cursor', 'windsurf', 'other')),
|
|
11
|
+
added_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
12
|
+
enabled INTEGER NOT NULL DEFAULT 1 CHECK (enabled IN (0, 1))
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
-- Index for efficient enabled project queries
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_daemon_tracked_projects_enabled
|
|
17
|
+
ON daemon_tracked_projects(enabled) WHERE enabled = 1;
|
|
18
|
+
|
|
19
|
+
-- Record this migration
|
|
20
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (14, datetime('now'));
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
-- Version: 015
|
|
2
|
+
-- Migration: Worker orchestration system (PRD-018)
|
|
3
|
+
-- Implements k8s-style worker orchestration with heartbeats, leases, and reconciliation
|
|
4
|
+
|
|
5
|
+
-- Workers table: registered worker processes
|
|
6
|
+
CREATE TABLE IF NOT EXISTS workers (
|
|
7
|
+
id TEXT PRIMARY KEY,
|
|
8
|
+
name TEXT NOT NULL,
|
|
9
|
+
hostname TEXT NOT NULL,
|
|
10
|
+
pid INTEGER NOT NULL,
|
|
11
|
+
status TEXT NOT NULL DEFAULT 'starting'
|
|
12
|
+
CHECK (status IN ('starting', 'idle', 'busy', 'stopping', 'dead')),
|
|
13
|
+
registered_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
14
|
+
last_heartbeat_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
15
|
+
current_task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
16
|
+
capabilities TEXT NOT NULL DEFAULT '[]',
|
|
17
|
+
metadata TEXT NOT NULL DEFAULT '{}'
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
-- Task claims table: lease-based task ownership
|
|
21
|
+
CREATE TABLE IF NOT EXISTS task_claims (
|
|
22
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
24
|
+
worker_id TEXT NOT NULL REFERENCES workers(id) ON DELETE CASCADE,
|
|
25
|
+
claimed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
26
|
+
lease_expires_at TEXT NOT NULL,
|
|
27
|
+
renewed_count INTEGER NOT NULL DEFAULT 0,
|
|
28
|
+
status TEXT NOT NULL DEFAULT 'active'
|
|
29
|
+
CHECK (status IN ('active', 'released', 'expired', 'completed'))
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
-- Orchestrator state table: singleton state for the orchestrator
|
|
33
|
+
-- Uses CHECK constraint to enforce singleton (only id=1 allowed)
|
|
34
|
+
CREATE TABLE IF NOT EXISTS orchestrator_state (
|
|
35
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
36
|
+
status TEXT NOT NULL DEFAULT 'stopped'
|
|
37
|
+
CHECK (status IN ('stopped', 'starting', 'running', 'stopping')),
|
|
38
|
+
pid INTEGER,
|
|
39
|
+
started_at TEXT,
|
|
40
|
+
last_reconcile_at TEXT,
|
|
41
|
+
worker_pool_size INTEGER NOT NULL DEFAULT 1,
|
|
42
|
+
reconcile_interval_seconds INTEGER NOT NULL DEFAULT 60,
|
|
43
|
+
heartbeat_interval_seconds INTEGER NOT NULL DEFAULT 30,
|
|
44
|
+
lease_duration_minutes INTEGER NOT NULL DEFAULT 30,
|
|
45
|
+
metadata TEXT NOT NULL DEFAULT '{}'
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
-- Indexes for workers
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_workers_status ON workers(status);
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_workers_last_heartbeat ON workers(last_heartbeat_at);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_workers_current_task ON workers(current_task_id) WHERE current_task_id IS NOT NULL;
|
|
52
|
+
|
|
53
|
+
-- Indexes for task_claims
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_claims_task_id ON task_claims(task_id);
|
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_claims_worker_id ON task_claims(worker_id);
|
|
56
|
+
CREATE INDEX IF NOT EXISTS idx_claims_status ON task_claims(status);
|
|
57
|
+
CREATE INDEX IF NOT EXISTS idx_claims_expires ON task_claims(lease_expires_at) WHERE status = 'active';
|
|
58
|
+
CREATE INDEX IF NOT EXISTS idx_claims_active_task ON task_claims(task_id, status) WHERE status = 'active';
|
|
59
|
+
|
|
60
|
+
-- Insert initial orchestrator state (singleton row)
|
|
61
|
+
INSERT OR IGNORE INTO orchestrator_state (id, status) VALUES (1, 'stopped');
|
|
62
|
+
|
|
63
|
+
-- Record this migration
|
|
64
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (15, datetime('now'));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- Version: 016
|
|
2
|
+
-- Migration: Add stderr_path and stdout_path to runs table for PRD-019 execution tracing
|
|
3
|
+
|
|
4
|
+
-- Add stderr capture path (optional, orchestrator decides whether to capture)
|
|
5
|
+
ALTER TABLE runs ADD COLUMN stderr_path TEXT;
|
|
6
|
+
|
|
7
|
+
-- Add stdout capture path (optional, orchestrator decides whether to capture)
|
|
8
|
+
ALTER TABLE runs ADD COLUMN stdout_path TEXT;
|
|
9
|
+
|
|
10
|
+
-- Note: transcript_path already exists from migration 005
|
|
11
|
+
|
|
12
|
+
-- Record this migration
|
|
13
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (16, datetime('now'));
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
-- Version: 017
|
|
2
|
+
-- Migration: Add 'span' and 'metric' event types for PRD-019 execution tracing
|
|
3
|
+
|
|
4
|
+
-- SQLite doesn't support ALTER CHECK, so we need to recreate the table
|
|
5
|
+
-- with the updated constraint that includes 'span' and 'metric' event types
|
|
6
|
+
|
|
7
|
+
-- Step 1: Create new events table with updated CHECK constraint
|
|
8
|
+
CREATE TABLE events_new (
|
|
9
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
10
|
+
timestamp TEXT NOT NULL,
|
|
11
|
+
event_type TEXT NOT NULL CHECK (event_type IN (
|
|
12
|
+
'run_started', 'run_completed', 'run_failed',
|
|
13
|
+
'task_created', 'task_updated', 'task_completed',
|
|
14
|
+
'tool_call', 'tool_result',
|
|
15
|
+
'user_message', 'assistant_message',
|
|
16
|
+
'error', 'learning_captured',
|
|
17
|
+
'commit', 'review',
|
|
18
|
+
'span', 'metric'
|
|
19
|
+
)),
|
|
20
|
+
run_id TEXT REFERENCES runs(id) ON DELETE SET NULL,
|
|
21
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
22
|
+
agent TEXT,
|
|
23
|
+
tool_name TEXT,
|
|
24
|
+
content TEXT,
|
|
25
|
+
metadata TEXT DEFAULT '{}',
|
|
26
|
+
duration_ms INTEGER
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
-- Step 2: Copy existing data
|
|
30
|
+
INSERT INTO events_new (id, timestamp, event_type, run_id, task_id, agent, tool_name, content, metadata, duration_ms)
|
|
31
|
+
SELECT id, timestamp, event_type, run_id, task_id, agent, tool_name, content, metadata, duration_ms FROM events;
|
|
32
|
+
|
|
33
|
+
-- Step 3: Drop old table
|
|
34
|
+
DROP TABLE events;
|
|
35
|
+
|
|
36
|
+
-- Step 4: Rename new table
|
|
37
|
+
ALTER TABLE events_new RENAME TO events;
|
|
38
|
+
|
|
39
|
+
-- Step 5: Recreate indexes (dropped with old table)
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp DESC);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_events_type ON events(event_type);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_events_run ON events(run_id);
|
|
43
|
+
CREATE INDEX IF NOT EXISTS idx_events_task ON events(task_id);
|
|
44
|
+
CREATE INDEX IF NOT EXISTS idx_events_agent ON events(agent);
|
|
45
|
+
|
|
46
|
+
-- Record this migration
|
|
47
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (17, datetime('now'));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Version: 018
|
|
2
|
+
-- Migration: Add learnings column to compaction_log for data loss prevention
|
|
3
|
+
--
|
|
4
|
+
-- Fixes CRITICAL bug: learnings were only exported to file, not stored in DB.
|
|
5
|
+
-- If file export failed (disk full, permissions, etc.), learnings were lost
|
|
6
|
+
-- forever because the original tasks were already deleted.
|
|
7
|
+
--
|
|
8
|
+
-- Now learnings are stored in the database as the primary source of truth,
|
|
9
|
+
-- ensuring they're never lost even if file export fails.
|
|
10
|
+
|
|
11
|
+
-- Add learnings column to store actual learning content
|
|
12
|
+
ALTER TABLE compaction_log ADD COLUMN learnings TEXT;
|
|
13
|
+
|
|
14
|
+
-- Record this migration
|
|
15
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (18, datetime('now'));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Version: 019
|
|
2
|
+
-- Migration: Add index on tasks.updated_at for sync dirty detection
|
|
3
|
+
--
|
|
4
|
+
-- The sync status dirty check scans all tasks to find any updated after
|
|
5
|
+
-- the last export. Without an index on updated_at, this is O(n).
|
|
6
|
+
-- With the index, a SQL query can find changed tasks in O(log n).
|
|
7
|
+
|
|
8
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_updated ON tasks(updated_at DESC);
|
|
9
|
+
|
|
10
|
+
-- Record this migration
|
|
11
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (19, datetime('now'));
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
-- Version: 020
|
|
2
|
+
-- Migration: Add database-level task ID format validation
|
|
3
|
+
--
|
|
4
|
+
-- Problem: tasks.id has no format constraint. ID validation (tx-[a-z0-9]{6,})
|
|
5
|
+
-- only exists in the app layer. JSONL import and direct SQL can insert malformed IDs.
|
|
6
|
+
--
|
|
7
|
+
-- Approach: Use BEFORE INSERT/UPDATE triggers instead of CHECK constraint because
|
|
8
|
+
-- SQLite does not support ALTER TABLE ADD CONSTRAINT, and recreating the tasks table
|
|
9
|
+
-- would cascade-delete all data in referencing tables (task_dependencies, attempts,
|
|
10
|
+
-- runs, events, task_claims, workers, file_learnings) when foreign_keys is ON.
|
|
11
|
+
-- Triggers provide identical database-level enforcement without table recreation.
|
|
12
|
+
|
|
13
|
+
-- Validate task ID format on INSERT
|
|
14
|
+
CREATE TRIGGER IF NOT EXISTS validate_task_id_insert
|
|
15
|
+
BEFORE INSERT ON tasks
|
|
16
|
+
FOR EACH ROW
|
|
17
|
+
WHEN NEW.id NOT GLOB 'tx-[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]*'
|
|
18
|
+
BEGIN
|
|
19
|
+
SELECT RAISE(ABORT, 'Task ID must match format: tx-[a-z0-9]{6,}');
|
|
20
|
+
END;
|
|
21
|
+
|
|
22
|
+
-- Validate task ID format on UPDATE (prevents changing id to malformed value)
|
|
23
|
+
CREATE TRIGGER IF NOT EXISTS validate_task_id_update
|
|
24
|
+
BEFORE UPDATE OF id ON tasks
|
|
25
|
+
FOR EACH ROW
|
|
26
|
+
WHEN NEW.id NOT GLOB 'tx-[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]*'
|
|
27
|
+
BEGIN
|
|
28
|
+
SELECT RAISE(ABORT, 'Task ID must match format: tx-[a-z0-9]{6,}');
|
|
29
|
+
END;
|
|
30
|
+
|
|
31
|
+
-- Record this migration
|
|
32
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (20, datetime('now'));
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
-- Migration 021: Agent Outbox Messaging (PRD-024)
|
|
2
|
+
--
|
|
3
|
+
-- Channel-based agent-to-agent messaging primitive.
|
|
4
|
+
-- Two-state lifecycle: pending -> acked
|
|
5
|
+
-- Read-only inbox with cursor-based fan-out.
|
|
6
|
+
|
|
7
|
+
CREATE TABLE IF NOT EXISTS outbox_messages (
|
|
8
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9
|
+
channel TEXT NOT NULL,
|
|
10
|
+
sender TEXT NOT NULL,
|
|
11
|
+
content TEXT NOT NULL,
|
|
12
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
13
|
+
CHECK (status IN ('pending', 'acked')),
|
|
14
|
+
correlation_id TEXT,
|
|
15
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
16
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
17
|
+
created_at TEXT NOT NULL,
|
|
18
|
+
acked_at TEXT,
|
|
19
|
+
expires_at TEXT
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
-- Primary query path: inbox reads by channel + cursor (id > ?)
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_outbox_channel_id ON outbox_messages(channel, id);
|
|
24
|
+
-- Filter by status (pending vs acked)
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_outbox_channel_status ON outbox_messages(channel, status);
|
|
26
|
+
-- Request/reply pattern
|
|
27
|
+
CREATE INDEX IF NOT EXISTS idx_outbox_correlation ON outbox_messages(correlation_id) WHERE correlation_id IS NOT NULL;
|
|
28
|
+
-- Task-scoped messages
|
|
29
|
+
CREATE INDEX IF NOT EXISTS idx_outbox_task_id ON outbox_messages(task_id) WHERE task_id IS NOT NULL;
|
|
30
|
+
-- TTL cleanup
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_outbox_expires ON outbox_messages(expires_at) WHERE expires_at IS NOT NULL;
|
|
32
|
+
|
|
33
|
+
-- Record this migration
|
|
34
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (21, datetime('now'));
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
-- Migration 022: Docs as Primitives (DD-023)
|
|
2
|
+
-- Tables: docs, doc_links, task_doc_links, invariants, invariant_checks
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS docs (
|
|
5
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6
|
+
hash TEXT NOT NULL,
|
|
7
|
+
kind TEXT NOT NULL CHECK (kind IN ('overview', 'prd', 'design')),
|
|
8
|
+
name TEXT NOT NULL,
|
|
9
|
+
title TEXT NOT NULL,
|
|
10
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
11
|
+
status TEXT NOT NULL CHECK (status IN ('changing', 'locked')) DEFAULT 'changing',
|
|
12
|
+
file_path TEXT NOT NULL,
|
|
13
|
+
parent_doc_id INTEGER REFERENCES docs(id) ON DELETE SET NULL,
|
|
14
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
15
|
+
locked_at TEXT,
|
|
16
|
+
metadata TEXT DEFAULT '{}'
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_docs_name_version ON docs(name, version);
|
|
20
|
+
|
|
21
|
+
CREATE TABLE IF NOT EXISTS doc_links (
|
|
22
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
from_doc_id INTEGER NOT NULL REFERENCES docs(id) ON DELETE CASCADE,
|
|
24
|
+
to_doc_id INTEGER NOT NULL REFERENCES docs(id) ON DELETE CASCADE,
|
|
25
|
+
link_type TEXT NOT NULL CHECK (link_type IN ('overview_to_prd', 'overview_to_design', 'prd_to_design', 'design_patch')),
|
|
26
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
27
|
+
UNIQUE(from_doc_id, to_doc_id),
|
|
28
|
+
CHECK(from_doc_id != to_doc_id)
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE TABLE IF NOT EXISTS task_doc_links (
|
|
32
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
33
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
34
|
+
doc_id INTEGER NOT NULL REFERENCES docs(id) ON DELETE CASCADE,
|
|
35
|
+
link_type TEXT NOT NULL CHECK (link_type IN ('implements', 'references')),
|
|
36
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
37
|
+
UNIQUE(task_id, doc_id)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
CREATE TABLE IF NOT EXISTS invariants (
|
|
41
|
+
id TEXT PRIMARY KEY,
|
|
42
|
+
rule TEXT NOT NULL,
|
|
43
|
+
enforcement TEXT NOT NULL CHECK (enforcement IN ('integration_test', 'linter', 'llm_as_judge')),
|
|
44
|
+
doc_id INTEGER NOT NULL REFERENCES docs(id) ON DELETE CASCADE,
|
|
45
|
+
subsystem TEXT,
|
|
46
|
+
test_ref TEXT,
|
|
47
|
+
lint_rule TEXT,
|
|
48
|
+
prompt_ref TEXT,
|
|
49
|
+
status TEXT NOT NULL CHECK (status IN ('active', 'deprecated')) DEFAULT 'active',
|
|
50
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
51
|
+
metadata TEXT DEFAULT '{}'
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
CREATE TABLE IF NOT EXISTS invariant_checks (
|
|
55
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
56
|
+
invariant_id TEXT NOT NULL REFERENCES invariants(id) ON DELETE CASCADE,
|
|
57
|
+
passed INTEGER NOT NULL CHECK (passed IN (0, 1)),
|
|
58
|
+
details TEXT,
|
|
59
|
+
checked_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
60
|
+
duration_ms INTEGER
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
CREATE INDEX IF NOT EXISTS idx_invariant_checks_invariant_id ON invariant_checks(invariant_id);
|
|
64
|
+
|
|
65
|
+
-- Record this migration
|
|
66
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (22, datetime('now'));
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
-- Migration 023: Task labels (Linear-style simplified label system)
|
|
2
|
+
-- Tables: task_labels, task_label_assignments
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS task_labels (
|
|
5
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6
|
+
name TEXT NOT NULL,
|
|
7
|
+
color TEXT NOT NULL,
|
|
8
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
9
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_task_labels_name_ci
|
|
13
|
+
ON task_labels(lower(name));
|
|
14
|
+
|
|
15
|
+
CREATE TABLE IF NOT EXISTS task_label_assignments (
|
|
16
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
17
|
+
label_id INTEGER NOT NULL REFERENCES task_labels(id) ON DELETE CASCADE,
|
|
18
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
19
|
+
PRIMARY KEY (task_id, label_id)
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
CREATE INDEX IF NOT EXISTS idx_task_label_assignments_task
|
|
23
|
+
ON task_label_assignments(task_id);
|
|
24
|
+
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_task_label_assignments_label
|
|
26
|
+
ON task_label_assignments(label_id);
|
|
27
|
+
|
|
28
|
+
-- Record this migration
|
|
29
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (23, datetime('now'));
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-- Migration 024: Task assignment columns with legacy backfill
|
|
2
|
+
-- Tables: tasks (alter)
|
|
3
|
+
|
|
4
|
+
ALTER TABLE tasks ADD COLUMN assignee_type TEXT
|
|
5
|
+
CHECK (assignee_type IN ('human', 'agent'));
|
|
6
|
+
|
|
7
|
+
ALTER TABLE tasks ADD COLUMN assignee_id TEXT;
|
|
8
|
+
|
|
9
|
+
ALTER TABLE tasks ADD COLUMN assigned_at TEXT;
|
|
10
|
+
|
|
11
|
+
ALTER TABLE tasks ADD COLUMN assigned_by TEXT;
|
|
12
|
+
|
|
13
|
+
UPDATE tasks
|
|
14
|
+
SET assignee_type = 'agent',
|
|
15
|
+
assignee_id = NULL,
|
|
16
|
+
assigned_at = datetime('now'),
|
|
17
|
+
assigned_by = 'migration:024_task_assignment'
|
|
18
|
+
WHERE assignee_type IS NULL;
|
|
19
|
+
|
|
20
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_assignee_type
|
|
21
|
+
ON tasks(assignee_type);
|
|
22
|
+
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_assignee_type_id
|
|
24
|
+
ON tasks(assignee_type, assignee_id);
|
|
25
|
+
|
|
26
|
+
-- Record this migration
|
|
27
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (24, datetime('now'));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
-- Version: 025
|
|
2
|
+
-- Migration: Add run heartbeat state table for transcript-progress monitoring
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS run_heartbeat_state (
|
|
5
|
+
run_id TEXT PRIMARY KEY REFERENCES runs(id) ON DELETE CASCADE,
|
|
6
|
+
last_check_at TEXT NOT NULL,
|
|
7
|
+
last_activity_at TEXT NOT NULL,
|
|
8
|
+
stdout_bytes INTEGER NOT NULL DEFAULT 0 CHECK (stdout_bytes >= 0),
|
|
9
|
+
stderr_bytes INTEGER NOT NULL DEFAULT 0 CHECK (stderr_bytes >= 0),
|
|
10
|
+
transcript_bytes INTEGER NOT NULL DEFAULT 0 CHECK (transcript_bytes >= 0),
|
|
11
|
+
last_delta_bytes INTEGER NOT NULL DEFAULT 0 CHECK (last_delta_bytes >= 0),
|
|
12
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_run_heartbeat_check_at
|
|
16
|
+
ON run_heartbeat_state(last_check_at);
|
|
17
|
+
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_run_heartbeat_activity_at
|
|
19
|
+
ON run_heartbeat_state(last_activity_at);
|
|
20
|
+
|
|
21
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (25, datetime('now'));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
-- Version: 026
|
|
2
|
+
-- Migration: Add composite task ordering indexes for dashboard task list polling
|
|
3
|
+
--
|
|
4
|
+
-- Dashboard /api/tasks uses ORDER BY score DESC, id ASC with optional status filter.
|
|
5
|
+
-- Existing single-column indexes can trigger temporary sort B-trees under pagination.
|
|
6
|
+
-- These composite indexes support index-backed ordering for both query shapes:
|
|
7
|
+
-- 1) Unfiltered: ORDER BY score DESC, id ASC
|
|
8
|
+
-- 2) Filtered: WHERE status IN (...) ORDER BY score DESC, id ASC
|
|
9
|
+
|
|
10
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_score_id
|
|
11
|
+
ON tasks(score DESC, id ASC);
|
|
12
|
+
|
|
13
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status_score_id
|
|
14
|
+
ON tasks(status, score DESC, id ASC);
|
|
15
|
+
|
|
16
|
+
-- Record this migration
|
|
17
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (26, datetime('now'));
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
-- Version: 027
|
|
2
|
+
-- Migration: Add runs/events composite + expression indexes for watchdog/dashboard trace hot paths
|
|
3
|
+
--
|
|
4
|
+
-- Targets:
|
|
5
|
+
-- 1) runs list/filter/sort queries:
|
|
6
|
+
-- ORDER BY started_at DESC, id ASC
|
|
7
|
+
-- optional WHERE status = ? or agent = ?
|
|
8
|
+
-- 2) orphan-active task checks:
|
|
9
|
+
-- EXISTS/NOT EXISTS on runs(task_id, status='running')
|
|
10
|
+
-- 3) watchdog worker burst checks:
|
|
11
|
+
-- json_extract(metadata, '$.worker') + status + started_at window
|
|
12
|
+
-- 4) trace error spans:
|
|
13
|
+
-- events WHERE event_type='span' AND json_extract(metadata, '$.status')='error'
|
|
14
|
+
-- ORDER BY timestamp DESC LIMIT ?
|
|
15
|
+
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_runs_started_id
|
|
17
|
+
ON runs(started_at DESC, id ASC);
|
|
18
|
+
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_runs_status_started_id
|
|
20
|
+
ON runs(status, started_at DESC, id ASC);
|
|
21
|
+
|
|
22
|
+
CREATE INDEX IF NOT EXISTS idx_runs_agent_started_id
|
|
23
|
+
ON runs(agent, started_at DESC, id ASC);
|
|
24
|
+
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_runs_task_status
|
|
26
|
+
ON runs(task_id, status);
|
|
27
|
+
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_runs_worker_status_started
|
|
29
|
+
ON runs(json_extract(metadata, '$.worker'), status, started_at DESC);
|
|
30
|
+
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_events_type_metadata_status_timestamp
|
|
32
|
+
ON events(event_type, json_extract(metadata, '$.status'), timestamp DESC);
|
|
33
|
+
|
|
34
|
+
-- Record this migration
|
|
35
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (27, datetime('now'));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- Version: 028
|
|
2
|
+
-- Migration: Add task group context storage and source lookup index
|
|
3
|
+
--
|
|
4
|
+
-- Adds first-class task-group context that can be inherited across parent/child lineage.
|
|
5
|
+
|
|
6
|
+
ALTER TABLE tasks ADD COLUMN group_context TEXT;
|
|
7
|
+
|
|
8
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_group_context_present
|
|
9
|
+
ON tasks(id, updated_at DESC)
|
|
10
|
+
WHERE group_context IS NOT NULL AND length(trim(group_context)) > 0;
|
|
11
|
+
|
|
12
|
+
-- Record this migration
|
|
13
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at) VALUES (28, datetime('now'));
|
package/package.json
CHANGED
|
@@ -1,48 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jamesaphoenix/tx-core",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.9",
|
|
4
4
|
"description": "Core business logic for tx - Effect-TS services and repositories",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"bun": "./src/index.ts",
|
|
11
10
|
"types": "./dist/index.d.ts",
|
|
12
11
|
"import": "./dist/index.js"
|
|
13
12
|
},
|
|
14
13
|
"./services": {
|
|
15
|
-
"bun": "./src/services/index.ts",
|
|
16
14
|
"types": "./dist/services/index.d.ts",
|
|
17
15
|
"import": "./dist/services/index.js"
|
|
18
16
|
},
|
|
19
17
|
"./repo": {
|
|
20
|
-
"bun": "./src/repo/index.ts",
|
|
21
18
|
"types": "./dist/repo/index.d.ts",
|
|
22
19
|
"import": "./dist/repo/index.js"
|
|
23
20
|
},
|
|
24
21
|
"./schemas": {
|
|
25
|
-
"bun": "./src/schemas/index.ts",
|
|
26
22
|
"types": "./dist/schemas/index.d.ts",
|
|
27
23
|
"import": "./dist/schemas/index.js"
|
|
28
24
|
},
|
|
29
25
|
"./mappers": {
|
|
30
|
-
"bun": "./src/mappers/index.ts",
|
|
31
26
|
"types": "./dist/mappers/index.d.ts",
|
|
32
27
|
"import": "./dist/mappers/index.js"
|
|
33
28
|
},
|
|
34
29
|
"./layer": {
|
|
35
|
-
"bun": "./src/layer.ts",
|
|
36
30
|
"types": "./dist/layer.d.ts",
|
|
37
31
|
"import": "./dist/layer.js"
|
|
38
32
|
}
|
|
39
33
|
},
|
|
40
34
|
"files": [
|
|
41
35
|
"dist",
|
|
36
|
+
"migrations",
|
|
42
37
|
"README.md"
|
|
43
38
|
],
|
|
44
39
|
"scripts": {
|
|
45
|
-
"build": "tsc -b",
|
|
40
|
+
"build": "tsc -b && cp -r ../../migrations ./migrations",
|
|
46
41
|
"typecheck": "tsc --noEmit",
|
|
47
42
|
"lint": "eslint src/",
|
|
48
43
|
"test": "bunx --bun vitest run --passWithNoTests"
|