@allpepper/task-orchestrator 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/package.json +51 -0
- package/src/db/client.ts +34 -0
- package/src/db/index.ts +1 -0
- package/src/db/migrate.ts +51 -0
- package/src/db/migrations/001_initial_schema.sql +160 -0
- package/src/domain/index.ts +1 -0
- package/src/domain/types.ts +225 -0
- package/src/index.ts +7 -0
- package/src/repos/base.ts +151 -0
- package/src/repos/dependencies.ts +356 -0
- package/src/repos/features.ts +507 -0
- package/src/repos/index.ts +4 -0
- package/src/repos/projects.ts +350 -0
- package/src/repos/sections.ts +505 -0
- package/src/repos/tags.example.ts +125 -0
- package/src/repos/tags.ts +175 -0
- package/src/repos/tasks.ts +581 -0
- package/src/repos/templates.ts +649 -0
- package/src/server.ts +121 -0
- package/src/services/index.ts +2 -0
- package/src/services/status-validator.ts +100 -0
- package/src/services/workflow.ts +104 -0
- package/src/tools/apply-template.ts +129 -0
- package/src/tools/get-blocked-tasks.ts +63 -0
- package/src/tools/get-next-status.ts +183 -0
- package/src/tools/get-next-task.ts +75 -0
- package/src/tools/get-tag-usage.ts +54 -0
- package/src/tools/index.ts +30 -0
- package/src/tools/list-tags.ts +56 -0
- package/src/tools/manage-container.ts +333 -0
- package/src/tools/manage-dependency.ts +198 -0
- package/src/tools/manage-sections.ts +388 -0
- package/src/tools/manage-template.ts +313 -0
- package/src/tools/query-container.ts +296 -0
- package/src/tools/query-dependencies.ts +68 -0
- package/src/tools/query-sections.ts +70 -0
- package/src/tools/query-templates.ts +137 -0
- package/src/tools/query-workflow-state.ts +198 -0
- package/src/tools/registry.ts +180 -0
- package/src/tools/rename-tag.ts +64 -0
- package/src/tools/setup-project.ts +189 -0
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# task-orchestrator-bun
|
|
2
|
+
|
|
3
|
+
To install dependencies:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bun install
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
To run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bun run index.ts
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This project was created using `bun init` in bun v1.3.8. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@allpepper/task-orchestrator",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for hierarchical task orchestration with SQLite persistence",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"task-orchestrator": "src/server.ts"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"!src/**/*.test.ts",
|
|
13
|
+
"!src/**/__tests__"
|
|
14
|
+
],
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/alioshr/task-orchestrator.git"
|
|
21
|
+
},
|
|
22
|
+
"keywords": ["mcp", "task-orchestrator", "claude", "ai", "bun", "sqlite"],
|
|
23
|
+
"author": "alioshr",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/alioshr/task-orchestrator/issues"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/alioshr/task-orchestrator#readme",
|
|
29
|
+
"engines": {
|
|
30
|
+
"bun": ">=1.0.0"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"start": "bun run src/server.ts",
|
|
34
|
+
"dev": "bun --watch run src/server.ts",
|
|
35
|
+
"test": "bun test",
|
|
36
|
+
"prepublishOnly": "bun test"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
40
|
+
"yaml": "^2.8.2"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/bun": "latest",
|
|
44
|
+
"semantic-release": "^24.0.0",
|
|
45
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
46
|
+
"@semantic-release/git": "^10.0.1"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"typescript": "^5"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/db/client.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Database } from 'bun:sqlite';
|
|
2
|
+
import { mkdirSync } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
|
|
5
|
+
const DB_PATH = process.env.DATABASE_PATH || 'data/tasks.db';
|
|
6
|
+
|
|
7
|
+
// Ensure directory exists
|
|
8
|
+
mkdirSync(dirname(DB_PATH), { recursive: true });
|
|
9
|
+
|
|
10
|
+
export const db = new Database(DB_PATH);
|
|
11
|
+
|
|
12
|
+
// Set pragmas for performance and correctness
|
|
13
|
+
db.run('PRAGMA journal_mode = WAL');
|
|
14
|
+
db.run('PRAGMA busy_timeout = 5000');
|
|
15
|
+
db.run('PRAGMA foreign_keys = ON');
|
|
16
|
+
db.run('PRAGMA synchronous = NORMAL');
|
|
17
|
+
|
|
18
|
+
// Transaction helper
|
|
19
|
+
export function transaction<T>(fn: () => T): T {
|
|
20
|
+
return db.transaction(fn)();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// UUID helper - generates a random UUID v4 as hex string (no dashes)
|
|
24
|
+
export function generateId(): string {
|
|
25
|
+
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
|
26
|
+
bytes[6] = (bytes[6]! & 0x0f) | 0x40;
|
|
27
|
+
bytes[8] = (bytes[8]! & 0x3f) | 0x80;
|
|
28
|
+
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Timestamp helper
|
|
32
|
+
export function now(): string {
|
|
33
|
+
return new Date().toISOString();
|
|
34
|
+
}
|
package/src/db/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { db } from './client';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
|
+
|
|
5
|
+
// Create migrations tracking table
|
|
6
|
+
db.run(`
|
|
7
|
+
CREATE TABLE IF NOT EXISTS _migrations (
|
|
8
|
+
version INTEGER PRIMARY KEY,
|
|
9
|
+
name TEXT NOT NULL,
|
|
10
|
+
applied_at TEXT NOT NULL
|
|
11
|
+
)
|
|
12
|
+
`);
|
|
13
|
+
|
|
14
|
+
interface Migration {
|
|
15
|
+
version: number;
|
|
16
|
+
name: string;
|
|
17
|
+
sql: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function loadMigrations(): Migration[] {
|
|
21
|
+
const migrationsDir = join(dirname(import.meta.path), 'migrations');
|
|
22
|
+
const files = ['001_initial_schema.sql'];
|
|
23
|
+
|
|
24
|
+
return files.map((file, i) => ({
|
|
25
|
+
version: i + 1,
|
|
26
|
+
name: file,
|
|
27
|
+
sql: readFileSync(join(migrationsDir, file), 'utf-8')
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function runMigrations(): void {
|
|
32
|
+
const migrations = loadMigrations();
|
|
33
|
+
const applied = new Set(
|
|
34
|
+
db.query<{ version: number }, []>('SELECT version FROM _migrations')
|
|
35
|
+
.all()
|
|
36
|
+
.map(r => r.version)
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
for (const migration of migrations) {
|
|
40
|
+
if (applied.has(migration.version)) continue;
|
|
41
|
+
|
|
42
|
+
console.log(`Applying migration ${migration.version}: ${migration.name}`);
|
|
43
|
+
db.transaction(() => {
|
|
44
|
+
db.run(migration.sql);
|
|
45
|
+
db.run(
|
|
46
|
+
'INSERT INTO _migrations (version, name, applied_at) VALUES (?, ?, ?)',
|
|
47
|
+
[migration.version, migration.name, new Date().toISOString()]
|
|
48
|
+
);
|
|
49
|
+
})();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
-- Consolidated v2.0 schema for Task Orchestrator Bun.js port
|
|
2
|
+
-- Combines Kotlin V1-V7 migrations, strips locking tables
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
5
|
+
id TEXT PRIMARY KEY,
|
|
6
|
+
name VARCHAR(255) NOT NULL,
|
|
7
|
+
summary TEXT NOT NULL,
|
|
8
|
+
description TEXT,
|
|
9
|
+
status VARCHAR(20) NOT NULL CHECK (status IN ('PLANNING', 'IN_DEVELOPMENT', 'ON_HOLD', 'CANCELLED', 'COMPLETED', 'ARCHIVED')),
|
|
10
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
11
|
+
created_at TEXT NOT NULL,
|
|
12
|
+
modified_at TEXT NOT NULL,
|
|
13
|
+
search_vector TEXT
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status);
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_projects_created_at ON projects(created_at);
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_projects_modified_at ON projects(modified_at);
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_projects_version ON projects(version);
|
|
20
|
+
CREATE INDEX IF NOT EXISTS idx_projects_search_vector ON projects(search_vector);
|
|
21
|
+
|
|
22
|
+
CREATE TABLE IF NOT EXISTS templates (
|
|
23
|
+
id TEXT PRIMARY KEY,
|
|
24
|
+
name VARCHAR(200) NOT NULL UNIQUE,
|
|
25
|
+
description TEXT NOT NULL,
|
|
26
|
+
target_entity_type VARCHAR(50) NOT NULL,
|
|
27
|
+
is_built_in INTEGER NOT NULL DEFAULT 0,
|
|
28
|
+
is_protected INTEGER NOT NULL DEFAULT 0,
|
|
29
|
+
is_enabled INTEGER NOT NULL DEFAULT 1,
|
|
30
|
+
created_by VARCHAR(200),
|
|
31
|
+
tags TEXT NOT NULL,
|
|
32
|
+
created_at TEXT NOT NULL,
|
|
33
|
+
modified_at TEXT NOT NULL
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
CREATE INDEX IF NOT EXISTS idx_templates_target_entity_type ON templates(target_entity_type);
|
|
37
|
+
CREATE INDEX IF NOT EXISTS idx_templates_is_built_in ON templates(is_built_in);
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_templates_is_enabled ON templates(is_enabled);
|
|
39
|
+
|
|
40
|
+
CREATE TABLE IF NOT EXISTS features (
|
|
41
|
+
id TEXT PRIMARY KEY,
|
|
42
|
+
project_id TEXT,
|
|
43
|
+
name TEXT NOT NULL,
|
|
44
|
+
summary TEXT NOT NULL,
|
|
45
|
+
description TEXT,
|
|
46
|
+
status VARCHAR(20) NOT NULL CHECK (status IN ('DRAFT', 'PLANNING', 'IN_DEVELOPMENT', 'TESTING', 'VALIDATING', 'PENDING_REVIEW', 'BLOCKED', 'ON_HOLD', 'DEPLOYED', 'COMPLETED', 'ARCHIVED')),
|
|
47
|
+
priority VARCHAR(10) NOT NULL CHECK (priority IN ('HIGH', 'MEDIUM', 'LOW')),
|
|
48
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
49
|
+
created_at TEXT NOT NULL,
|
|
50
|
+
modified_at TEXT NOT NULL,
|
|
51
|
+
search_vector TEXT,
|
|
52
|
+
FOREIGN KEY (project_id) REFERENCES projects(id)
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_features_project_id ON features(project_id);
|
|
56
|
+
CREATE INDEX IF NOT EXISTS idx_features_status ON features(status);
|
|
57
|
+
CREATE INDEX IF NOT EXISTS idx_features_priority ON features(priority);
|
|
58
|
+
CREATE INDEX IF NOT EXISTS idx_features_created_at ON features(created_at);
|
|
59
|
+
CREATE INDEX IF NOT EXISTS idx_features_modified_at ON features(modified_at);
|
|
60
|
+
CREATE INDEX IF NOT EXISTS idx_features_version ON features(version);
|
|
61
|
+
CREATE INDEX IF NOT EXISTS idx_features_search_vector ON features(search_vector);
|
|
62
|
+
CREATE INDEX IF NOT EXISTS idx_features_status_priority ON features(status, priority);
|
|
63
|
+
CREATE INDEX IF NOT EXISTS idx_features_project_status ON features(project_id, status);
|
|
64
|
+
|
|
65
|
+
CREATE TABLE IF NOT EXISTS entity_tags (
|
|
66
|
+
id TEXT PRIMARY KEY,
|
|
67
|
+
entity_id TEXT NOT NULL,
|
|
68
|
+
entity_type VARCHAR(20) NOT NULL,
|
|
69
|
+
tag VARCHAR(100) NOT NULL,
|
|
70
|
+
created_at TEXT NOT NULL
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_entity_tags_unique ON entity_tags(entity_id, entity_type, tag);
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_entity_tags_tag ON entity_tags(tag);
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_entity_tags_entity ON entity_tags(entity_id, entity_type);
|
|
76
|
+
|
|
77
|
+
CREATE TABLE IF NOT EXISTS sections (
|
|
78
|
+
id TEXT PRIMARY KEY,
|
|
79
|
+
entity_type VARCHAR(50) NOT NULL,
|
|
80
|
+
entity_id TEXT NOT NULL,
|
|
81
|
+
title VARCHAR(200) NOT NULL,
|
|
82
|
+
usage_description TEXT NOT NULL,
|
|
83
|
+
content TEXT NOT NULL,
|
|
84
|
+
content_format VARCHAR(50) NOT NULL,
|
|
85
|
+
ordinal INTEGER NOT NULL,
|
|
86
|
+
tags TEXT NOT NULL,
|
|
87
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
88
|
+
created_at TEXT NOT NULL,
|
|
89
|
+
modified_at TEXT NOT NULL
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
CREATE INDEX IF NOT EXISTS idx_sections_entity ON sections(entity_type, entity_id);
|
|
93
|
+
CREATE INDEX IF NOT EXISTS idx_sections_entity_id ON sections(entity_id);
|
|
94
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_sections_entity_ordinal ON sections(entity_type, entity_id, ordinal);
|
|
95
|
+
|
|
96
|
+
CREATE TABLE IF NOT EXISTS template_sections (
|
|
97
|
+
id TEXT PRIMARY KEY,
|
|
98
|
+
template_id TEXT NOT NULL,
|
|
99
|
+
title VARCHAR(200) NOT NULL,
|
|
100
|
+
usage_description TEXT NOT NULL,
|
|
101
|
+
content_sample TEXT NOT NULL,
|
|
102
|
+
content_format VARCHAR(50) NOT NULL,
|
|
103
|
+
ordinal INTEGER NOT NULL,
|
|
104
|
+
is_required INTEGER NOT NULL DEFAULT 0,
|
|
105
|
+
tags TEXT NOT NULL,
|
|
106
|
+
FOREIGN KEY (template_id) REFERENCES templates(id)
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
CREATE INDEX IF NOT EXISTS idx_template_sections_template_id ON template_sections(template_id);
|
|
110
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_template_sections_template_ordinal ON template_sections(template_id, ordinal);
|
|
111
|
+
|
|
112
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
113
|
+
id TEXT PRIMARY KEY,
|
|
114
|
+
project_id TEXT,
|
|
115
|
+
feature_id TEXT,
|
|
116
|
+
title TEXT NOT NULL,
|
|
117
|
+
summary TEXT NOT NULL,
|
|
118
|
+
description TEXT,
|
|
119
|
+
status VARCHAR(20) NOT NULL CHECK (status IN ('BACKLOG', 'PENDING', 'IN_PROGRESS', 'IN_REVIEW', 'CHANGES_REQUESTED', 'TESTING', 'READY_FOR_QA', 'INVESTIGATING', 'BLOCKED', 'ON_HOLD', 'DEPLOYED', 'COMPLETED', 'CANCELLED', 'DEFERRED')),
|
|
120
|
+
priority VARCHAR(20) NOT NULL CHECK (priority IN ('HIGH', 'MEDIUM', 'LOW')),
|
|
121
|
+
complexity INTEGER NOT NULL,
|
|
122
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
123
|
+
last_modified_by TEXT,
|
|
124
|
+
lock_status VARCHAR(20) NOT NULL DEFAULT 'UNLOCKED' CHECK (lock_status IN ('UNLOCKED', 'LOCKED_EXCLUSIVE', 'LOCKED_SHARED', 'LOCKED_SECTION')),
|
|
125
|
+
created_at TEXT NOT NULL,
|
|
126
|
+
modified_at TEXT NOT NULL,
|
|
127
|
+
search_vector TEXT,
|
|
128
|
+
FOREIGN KEY (project_id) REFERENCES projects(id),
|
|
129
|
+
FOREIGN KEY (feature_id) REFERENCES features(id)
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_project_id ON tasks(project_id);
|
|
133
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_feature_id ON tasks(feature_id);
|
|
134
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
135
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);
|
|
136
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_version ON tasks(version);
|
|
137
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_lock_status ON tasks(lock_status);
|
|
138
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_last_modified_by ON tasks(last_modified_by);
|
|
139
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_search_vector ON tasks(search_vector);
|
|
140
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status_priority ON tasks(status, priority);
|
|
141
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_feature_status ON tasks(feature_id, status);
|
|
142
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_project_status ON tasks(project_id, status);
|
|
143
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_priority_created ON tasks(priority DESC, created_at ASC);
|
|
144
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_project_feature ON tasks(project_id, feature_id);
|
|
145
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status_priority_complexity ON tasks(status, priority, complexity);
|
|
146
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_feature_status_priority ON tasks(feature_id, status, priority);
|
|
147
|
+
|
|
148
|
+
CREATE TABLE IF NOT EXISTS dependencies (
|
|
149
|
+
id TEXT PRIMARY KEY,
|
|
150
|
+
from_task_id TEXT NOT NULL,
|
|
151
|
+
to_task_id TEXT NOT NULL,
|
|
152
|
+
type VARCHAR(20) NOT NULL CHECK (type IN ('BLOCKS', 'IS_BLOCKED_BY', 'RELATES_TO')),
|
|
153
|
+
created_at TEXT NOT NULL,
|
|
154
|
+
FOREIGN KEY (from_task_id) REFERENCES tasks(id),
|
|
155
|
+
FOREIGN KEY (to_task_id) REFERENCES tasks(id)
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_dependencies_unique ON dependencies(from_task_id, to_task_id, type);
|
|
159
|
+
CREATE INDEX IF NOT EXISTS idx_dependencies_from_task_id ON dependencies(from_task_id);
|
|
160
|
+
CREATE INDEX IF NOT EXISTS idx_dependencies_to_task_id ON dependencies(to_task_id);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain Types for Task Orchestrator v2.0
|
|
3
|
+
*
|
|
4
|
+
* All TypeScript interfaces and enums for the domain model.
|
|
5
|
+
* Based on the v2.0 schema specification.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Enums
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
export enum ProjectStatus {
|
|
13
|
+
PLANNING = 'PLANNING',
|
|
14
|
+
IN_DEVELOPMENT = 'IN_DEVELOPMENT',
|
|
15
|
+
ON_HOLD = 'ON_HOLD',
|
|
16
|
+
CANCELLED = 'CANCELLED',
|
|
17
|
+
COMPLETED = 'COMPLETED',
|
|
18
|
+
ARCHIVED = 'ARCHIVED'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export enum FeatureStatus {
|
|
22
|
+
DRAFT = 'DRAFT',
|
|
23
|
+
PLANNING = 'PLANNING',
|
|
24
|
+
IN_DEVELOPMENT = 'IN_DEVELOPMENT',
|
|
25
|
+
TESTING = 'TESTING',
|
|
26
|
+
VALIDATING = 'VALIDATING',
|
|
27
|
+
PENDING_REVIEW = 'PENDING_REVIEW',
|
|
28
|
+
BLOCKED = 'BLOCKED',
|
|
29
|
+
ON_HOLD = 'ON_HOLD',
|
|
30
|
+
DEPLOYED = 'DEPLOYED',
|
|
31
|
+
COMPLETED = 'COMPLETED',
|
|
32
|
+
ARCHIVED = 'ARCHIVED'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export enum TaskStatus {
|
|
36
|
+
BACKLOG = 'BACKLOG',
|
|
37
|
+
PENDING = 'PENDING',
|
|
38
|
+
IN_PROGRESS = 'IN_PROGRESS',
|
|
39
|
+
IN_REVIEW = 'IN_REVIEW',
|
|
40
|
+
CHANGES_REQUESTED = 'CHANGES_REQUESTED',
|
|
41
|
+
TESTING = 'TESTING',
|
|
42
|
+
READY_FOR_QA = 'READY_FOR_QA',
|
|
43
|
+
INVESTIGATING = 'INVESTIGATING',
|
|
44
|
+
BLOCKED = 'BLOCKED',
|
|
45
|
+
ON_HOLD = 'ON_HOLD',
|
|
46
|
+
DEPLOYED = 'DEPLOYED',
|
|
47
|
+
COMPLETED = 'COMPLETED',
|
|
48
|
+
CANCELLED = 'CANCELLED',
|
|
49
|
+
DEFERRED = 'DEFERRED'
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export enum Priority {
|
|
53
|
+
HIGH = 'HIGH',
|
|
54
|
+
MEDIUM = 'MEDIUM',
|
|
55
|
+
LOW = 'LOW'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export enum ContentFormat {
|
|
59
|
+
PLAIN_TEXT = 'PLAIN_TEXT',
|
|
60
|
+
MARKDOWN = 'MARKDOWN',
|
|
61
|
+
JSON = 'JSON',
|
|
62
|
+
CODE = 'CODE'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export enum EntityType {
|
|
66
|
+
PROJECT = 'PROJECT',
|
|
67
|
+
FEATURE = 'FEATURE',
|
|
68
|
+
TASK = 'TASK',
|
|
69
|
+
TEMPLATE = 'TEMPLATE',
|
|
70
|
+
SECTION = 'SECTION'
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export enum DependencyType {
|
|
74
|
+
BLOCKS = 'BLOCKS',
|
|
75
|
+
IS_BLOCKED_BY = 'IS_BLOCKED_BY',
|
|
76
|
+
RELATES_TO = 'RELATES_TO'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export enum LockStatus {
|
|
80
|
+
UNLOCKED = 'UNLOCKED',
|
|
81
|
+
LOCKED_EXCLUSIVE = 'LOCKED_EXCLUSIVE',
|
|
82
|
+
LOCKED_SHARED = 'LOCKED_SHARED',
|
|
83
|
+
LOCKED_SECTION = 'LOCKED_SECTION'
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ============================================================================
|
|
87
|
+
// Interfaces
|
|
88
|
+
// ============================================================================
|
|
89
|
+
|
|
90
|
+
export interface Project {
|
|
91
|
+
id: string;
|
|
92
|
+
name: string;
|
|
93
|
+
summary: string;
|
|
94
|
+
description?: string;
|
|
95
|
+
status: ProjectStatus;
|
|
96
|
+
version: number;
|
|
97
|
+
createdAt: Date;
|
|
98
|
+
modifiedAt: Date;
|
|
99
|
+
searchVector?: string;
|
|
100
|
+
tags?: string[];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface Feature {
|
|
104
|
+
id: string;
|
|
105
|
+
projectId?: string;
|
|
106
|
+
name: string;
|
|
107
|
+
summary: string;
|
|
108
|
+
description?: string;
|
|
109
|
+
status: FeatureStatus;
|
|
110
|
+
priority: Priority;
|
|
111
|
+
version: number;
|
|
112
|
+
createdAt: Date;
|
|
113
|
+
modifiedAt: Date;
|
|
114
|
+
searchVector?: string;
|
|
115
|
+
tags?: string[];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface Task {
|
|
119
|
+
id: string;
|
|
120
|
+
projectId?: string;
|
|
121
|
+
featureId?: string;
|
|
122
|
+
title: string;
|
|
123
|
+
summary: string;
|
|
124
|
+
description?: string;
|
|
125
|
+
status: TaskStatus;
|
|
126
|
+
priority: Priority;
|
|
127
|
+
complexity: number;
|
|
128
|
+
version: number;
|
|
129
|
+
lastModifiedBy?: string;
|
|
130
|
+
lockStatus: LockStatus;
|
|
131
|
+
createdAt: Date;
|
|
132
|
+
modifiedAt: Date;
|
|
133
|
+
searchVector?: string;
|
|
134
|
+
tags?: string[];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface Section {
|
|
138
|
+
id: string;
|
|
139
|
+
entityType: EntityType;
|
|
140
|
+
entityId: string;
|
|
141
|
+
title: string;
|
|
142
|
+
usageDescription: string;
|
|
143
|
+
content: string;
|
|
144
|
+
contentFormat: ContentFormat;
|
|
145
|
+
ordinal: number;
|
|
146
|
+
tags: string;
|
|
147
|
+
version: number;
|
|
148
|
+
createdAt: Date;
|
|
149
|
+
modifiedAt: Date;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface Template {
|
|
153
|
+
id: string;
|
|
154
|
+
name: string;
|
|
155
|
+
description: string;
|
|
156
|
+
targetEntityType: EntityType;
|
|
157
|
+
isBuiltIn: boolean;
|
|
158
|
+
isProtected: boolean;
|
|
159
|
+
isEnabled: boolean;
|
|
160
|
+
createdBy?: string;
|
|
161
|
+
tags: string;
|
|
162
|
+
createdAt: Date;
|
|
163
|
+
modifiedAt: Date;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface TemplateSection {
|
|
167
|
+
id: string;
|
|
168
|
+
templateId: string;
|
|
169
|
+
title: string;
|
|
170
|
+
usageDescription: string;
|
|
171
|
+
contentSample: string;
|
|
172
|
+
contentFormat: ContentFormat;
|
|
173
|
+
ordinal: number;
|
|
174
|
+
isRequired: boolean;
|
|
175
|
+
tags: string;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface Dependency {
|
|
179
|
+
id: string;
|
|
180
|
+
fromTaskId: string;
|
|
181
|
+
toTaskId: string;
|
|
182
|
+
type: DependencyType;
|
|
183
|
+
createdAt: Date;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface EntityTag {
|
|
187
|
+
id: string;
|
|
188
|
+
entityId: string;
|
|
189
|
+
entityType: EntityType;
|
|
190
|
+
tag: string;
|
|
191
|
+
createdAt: Date;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ============================================================================
|
|
195
|
+
// Result Type
|
|
196
|
+
// ============================================================================
|
|
197
|
+
|
|
198
|
+
export type Result<T> =
|
|
199
|
+
| { success: true; data: T }
|
|
200
|
+
| { success: false; error: string; code?: string };
|
|
201
|
+
|
|
202
|
+
// ============================================================================
|
|
203
|
+
// Error Types
|
|
204
|
+
// ============================================================================
|
|
205
|
+
|
|
206
|
+
export class NotFoundError extends Error {
|
|
207
|
+
constructor(entity: string, id: string) {
|
|
208
|
+
super(`${entity} not found: ${id}`);
|
|
209
|
+
this.name = 'NotFoundError';
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export class ValidationError extends Error {
|
|
214
|
+
constructor(message: string) {
|
|
215
|
+
super(message);
|
|
216
|
+
this.name = 'ValidationError';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export class ConflictError extends Error {
|
|
221
|
+
constructor(message: string) {
|
|
222
|
+
super(message);
|
|
223
|
+
this.name = 'ConflictError';
|
|
224
|
+
}
|
|
225
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Re-export everything for library consumers
|
|
2
|
+
export * from './domain';
|
|
3
|
+
export * from './repos';
|
|
4
|
+
export * from './services/workflow';
|
|
5
|
+
export * from './services/status-validator';
|
|
6
|
+
export { db } from './db/client';
|
|
7
|
+
export { runMigrations } from './db/migrate';
|