@jamesaphoenix/tx-core 0.5.8 → 0.5.10

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.
Files changed (46) hide show
  1. package/README.md +7 -0
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/migrations-embedded.d.ts +9 -0
  7. package/dist/migrations-embedded.d.ts.map +1 -0
  8. package/dist/migrations-embedded.js +143 -0
  9. package/dist/migrations-embedded.js.map +1 -0
  10. package/dist/services/index.d.ts +1 -1
  11. package/dist/services/index.d.ts.map +1 -1
  12. package/dist/services/index.js +1 -1
  13. package/dist/services/index.js.map +1 -1
  14. package/dist/services/migration-service.d.ts +8 -2
  15. package/dist/services/migration-service.d.ts.map +1 -1
  16. package/dist/services/migration-service.js +35 -15
  17. package/dist/services/migration-service.js.map +1 -1
  18. package/migrations/001_initial.sql +57 -0
  19. package/migrations/002_learnings.sql +64 -0
  20. package/migrations/003_file_learnings.sql +19 -0
  21. package/migrations/004_attempts.sql +18 -0
  22. package/migrations/005_runs.sql +34 -0
  23. package/migrations/006_events.sql +33 -0
  24. package/migrations/007_sync_config.sql +18 -0
  25. package/migrations/008_learning_anchors.sql +28 -0
  26. package/migrations/009_learning_edges.sql +43 -0
  27. package/migrations/010_learning_candidates.sql +30 -0
  28. package/migrations/011_processed_hashes.sql +35 -0
  29. package/migrations/012_invalidation.sql +32 -0
  30. package/migrations/013_content_preview.sql +13 -0
  31. package/migrations/014_daemon_tracked_projects.sql +20 -0
  32. package/migrations/015_worker_orchestration.sql +64 -0
  33. package/migrations/016_tracing_io_paths.sql +13 -0
  34. package/migrations/017_span_metric_events.sql +47 -0
  35. package/migrations/018_compaction_learnings.sql +15 -0
  36. package/migrations/019_tasks_updated_at_index.sql +11 -0
  37. package/migrations/020_task_id_check.sql +32 -0
  38. package/migrations/021_agent_outbox.sql +34 -0
  39. package/migrations/022_docs_as_primitives.sql +66 -0
  40. package/migrations/023_task_labels.sql +29 -0
  41. package/migrations/024_task_assignment.sql +27 -0
  42. package/migrations/025_run_heartbeat_state.sql +21 -0
  43. package/migrations/026_task_order_composite_indexes.sql +17 -0
  44. package/migrations/027_runs_events_hot_query_indexes.sql +35 -0
  45. package/migrations/028_task_group_context.sql +13 -0
  46. package/package.json +4 -8
@@ -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,44 @@
1
1
  {
2
2
  "name": "@jamesaphoenix/tx-core",
3
- "version": "0.5.8",
3
+ "version": "0.5.10",
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
+ "prebuild": "node ../../scripts/bundle-migrations.js",
41
+ "build": "tsc -b && { rm -r ./migrations 2>/dev/null; cp -r ../../migrations ./migrations; }",
46
42
  "typecheck": "tsc --noEmit",
47
43
  "lint": "eslint src/",
48
44
  "test": "bunx --bun vitest run --passWithNoTests"