@pi-orca/tasks 0.0.2-dev.20260413162335
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 +43 -0
- package/dist/commands.d.ts +29 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +213 -0
- package/dist/commands.js.map +1 -0
- package/dist/engine/crud.d.ts +81 -0
- package/dist/engine/crud.d.ts.map +1 -0
- package/dist/engine/crud.js +214 -0
- package/dist/engine/crud.js.map +1 -0
- package/dist/engine/dag.d.ts +30 -0
- package/dist/engine/dag.d.ts.map +1 -0
- package/dist/engine/dag.js +99 -0
- package/dist/engine/dag.js.map +1 -0
- package/dist/engine/index.d.ts +8 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +8 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/notes.d.ts +26 -0
- package/dist/engine/notes.d.ts.map +1 -0
- package/dist/engine/notes.js +45 -0
- package/dist/engine/notes.js.map +1 -0
- package/dist/engine/state-machine.d.ts +57 -0
- package/dist/engine/state-machine.d.ts.map +1 -0
- package/dist/engine/state-machine.js +302 -0
- package/dist/engine/state-machine.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +229 -0
- package/dist/index.js.map +1 -0
- package/dist/tool.d.ts +19 -0
- package/dist/tool.d.ts.map +1 -0
- package/dist/tool.js +188 -0
- package/dist/tool.js.map +1 -0
- package/dist/widget.d.ts +10 -0
- package/dist/widget.d.ts.map +1 -0
- package/dist/widget.js +59 -0
- package/dist/widget.js.map +1 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# pi-orca-tasks
|
|
2
|
+
|
|
3
|
+
**Task Management**
|
|
4
|
+
|
|
5
|
+
Version: 0.0.1 (Phase 0 - Stub)
|
|
6
|
+
License: MIT
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
File-backed task DAG with locking, dependency validation, and state machine.
|
|
11
|
+
|
|
12
|
+
**Status:** Phase 0 scaffold complete. Full implementation pending.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install pi-orca-tasks
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
This package is currently in stub mode. Tools and commands are registered but return "Not implemented yet" messages.
|
|
23
|
+
|
|
24
|
+
## Development Status
|
|
25
|
+
|
|
26
|
+
- [x] Package scaffold
|
|
27
|
+
- [x] TypeScript configuration
|
|
28
|
+
- [x] Tool registration (stub)
|
|
29
|
+
- [x] Command registration (stub)
|
|
30
|
+
- [x] Event emission (ready signal)
|
|
31
|
+
- [ ] Full implementation (pending)
|
|
32
|
+
|
|
33
|
+
## Dependencies
|
|
34
|
+
|
|
35
|
+
- `pi-orca-core` — Shared types and utilities
|
|
36
|
+
|
|
37
|
+
## Documentation
|
|
38
|
+
|
|
39
|
+
See the [Pi Orca specification](../../docs/spec-v0.3.0.md) for the complete design.
|
|
40
|
+
|
|
41
|
+
## License
|
|
42
|
+
|
|
43
|
+
MIT License — see [LICENSE](../../LICENSE) for details.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slash command implementations for pi-orca-tasks.
|
|
3
|
+
* Spec: §3.10 — Slash Commands
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* /task (no args) — return widget string for display
|
|
7
|
+
*/
|
|
8
|
+
export declare function cmdTaskToggle(projectSlug?: string): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* /task list [status] — list tasks
|
|
11
|
+
*/
|
|
12
|
+
export declare function cmdTaskList(statusFilter?: string, projectSlug?: string): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* /task stuck — scan for stuck tasks
|
|
15
|
+
*/
|
|
16
|
+
export declare function cmdTaskStuck(projectSlug?: string): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* /task unlock <id> — force-release a stuck lock
|
|
19
|
+
*/
|
|
20
|
+
export declare function cmdTaskUnlock(taskId: string, projectSlug?: string): Promise<string>;
|
|
21
|
+
/**
|
|
22
|
+
* /task deps <id> — show dependency graph for a task
|
|
23
|
+
*/
|
|
24
|
+
export declare function cmdTaskDeps(taskId: string, projectSlug?: string): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* /task validate [id] — validate task files
|
|
27
|
+
*/
|
|
28
|
+
export declare function cmdTaskValidate(taskId?: string, projectSlug?: string): Promise<string>;
|
|
29
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH;;GAEG;AACH,wBAAsB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEzE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4B9F;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwDxE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOzF;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgDvF;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,MAAM,CAAC,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAmDjB"}
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slash command implementations for pi-orca-tasks.
|
|
3
|
+
* Spec: §3.10 — Slash Commands
|
|
4
|
+
*/
|
|
5
|
+
import { listTasks, readTask, getTaskLockPath } from "./engine/crud.js";
|
|
6
|
+
import { renderTaskWidget } from "./widget.js";
|
|
7
|
+
import { readLock, isPidAlive, getOrcaTasksDir } from "@pi-orca/core";
|
|
8
|
+
import { readdir } from "fs/promises";
|
|
9
|
+
import { existsSync } from "fs";
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
/**
|
|
12
|
+
* /task (no args) — return widget string for display
|
|
13
|
+
*/
|
|
14
|
+
export async function cmdTaskToggle(projectSlug) {
|
|
15
|
+
return renderTaskWidget(projectSlug);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* /task list [status] — list tasks
|
|
19
|
+
*/
|
|
20
|
+
export async function cmdTaskList(statusFilter, projectSlug) {
|
|
21
|
+
const tasks = await listTasks({
|
|
22
|
+
status: statusFilter,
|
|
23
|
+
projectSlug,
|
|
24
|
+
});
|
|
25
|
+
if (tasks.length === 0) {
|
|
26
|
+
return statusFilter
|
|
27
|
+
? `No tasks with status '${statusFilter}'.`
|
|
28
|
+
: "No tasks found. Use /task create <title> to create one.";
|
|
29
|
+
}
|
|
30
|
+
const STATUS_ICONS = {
|
|
31
|
+
completed: "✓",
|
|
32
|
+
in_progress: "◉",
|
|
33
|
+
pending: "○",
|
|
34
|
+
failed: "✗",
|
|
35
|
+
blocked: "⊘",
|
|
36
|
+
abandoned: "—",
|
|
37
|
+
};
|
|
38
|
+
const lines = tasks.map((t) => {
|
|
39
|
+
const icon = STATUS_ICONS[t.task.status] ?? "?";
|
|
40
|
+
const assignee = t.task.status === "in_progress" ? ` [${t.task.assignedTo?.slice(0, 8)}]` : "";
|
|
41
|
+
return ` ${icon} ${t.task.id} ${t.task.title}${assignee}`;
|
|
42
|
+
});
|
|
43
|
+
return `Tasks (${tasks.length}):\n${lines.join("\n")}`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* /task stuck — scan for stuck tasks
|
|
47
|
+
*/
|
|
48
|
+
export async function cmdTaskStuck(projectSlug) {
|
|
49
|
+
const tasksDir = getOrcaTasksDir(projectSlug);
|
|
50
|
+
if (!existsSync(tasksDir)) {
|
|
51
|
+
return "No tasks directory found.";
|
|
52
|
+
}
|
|
53
|
+
let entries;
|
|
54
|
+
try {
|
|
55
|
+
entries = await readdir(tasksDir);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return "Could not read tasks directory.";
|
|
59
|
+
}
|
|
60
|
+
const lockFiles = entries.filter((e) => e.endsWith(".lock"));
|
|
61
|
+
if (lockFiles.length === 0) {
|
|
62
|
+
return "No locked tasks found.";
|
|
63
|
+
}
|
|
64
|
+
const stuck = [];
|
|
65
|
+
const alive = [];
|
|
66
|
+
for (const lockFile of lockFiles) {
|
|
67
|
+
const taskId = lockFile.replace(".lock", "");
|
|
68
|
+
const lockPath = join(tasksDir, lockFile);
|
|
69
|
+
const lockInfo = await readLock(lockPath);
|
|
70
|
+
if (!lockInfo) {
|
|
71
|
+
stuck.push(`${taskId} (unreadable lock file)`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (!isPidAlive(lockInfo.pid)) {
|
|
75
|
+
stuck.push(`${taskId} (PID ${lockInfo.pid} dead, locked by session ${lockInfo.sessionId})`);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
alive.push(`${taskId} (PID ${lockInfo.pid} alive, held by session ${lockInfo.sessionId})`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const lines = [];
|
|
82
|
+
if (stuck.length > 0) {
|
|
83
|
+
lines.push(`⚠ Stuck tasks (${stuck.length}):`);
|
|
84
|
+
stuck.forEach((s) => lines.push(` ${s}`));
|
|
85
|
+
lines.push("");
|
|
86
|
+
lines.push("Run /task unlock <id> to release a stuck lock.");
|
|
87
|
+
}
|
|
88
|
+
if (alive.length > 0) {
|
|
89
|
+
lines.push(`Active locks (${alive.length}):`);
|
|
90
|
+
alive.forEach((a) => lines.push(` ${a}`));
|
|
91
|
+
}
|
|
92
|
+
if (lines.length === 0) {
|
|
93
|
+
return "No stuck tasks found.";
|
|
94
|
+
}
|
|
95
|
+
return lines.join("\n");
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* /task unlock <id> — force-release a stuck lock
|
|
99
|
+
*/
|
|
100
|
+
export async function cmdTaskUnlock(taskId, projectSlug) {
|
|
101
|
+
const { unlockTask } = await import("./engine/state-machine.js");
|
|
102
|
+
const result = await unlockTask(taskId, projectSlug);
|
|
103
|
+
if (result.success) {
|
|
104
|
+
return result.message ?? `Unlocked task ${taskId}`;
|
|
105
|
+
}
|
|
106
|
+
return `Error: ${result.error}`;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* /task deps <id> — show dependency graph for a task
|
|
110
|
+
*/
|
|
111
|
+
export async function cmdTaskDeps(taskId, projectSlug) {
|
|
112
|
+
const taskFile = await readTask(taskId, projectSlug);
|
|
113
|
+
if (!taskFile) {
|
|
114
|
+
return `Task ${taskId} not found.`;
|
|
115
|
+
}
|
|
116
|
+
const STATUS_ICONS = {
|
|
117
|
+
completed: "✓",
|
|
118
|
+
in_progress: "◉",
|
|
119
|
+
pending: "○",
|
|
120
|
+
failed: "✗",
|
|
121
|
+
blocked: "⊘",
|
|
122
|
+
abandoned: "—",
|
|
123
|
+
};
|
|
124
|
+
const lines = [`${taskId}: ${taskFile.task.title} [${taskFile.task.status}]`];
|
|
125
|
+
if ((taskFile.task.dependencies ?? []).length > 0) {
|
|
126
|
+
lines.push(" Dependencies (must complete before this task):");
|
|
127
|
+
for (const depId of taskFile.task.dependencies) {
|
|
128
|
+
const dep = await readTask(depId, projectSlug);
|
|
129
|
+
if (dep) {
|
|
130
|
+
const icon = STATUS_ICONS[dep.task.status] ?? "?";
|
|
131
|
+
lines.push(` ${icon} ${depId}: ${dep.task.title}`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
lines.push(` ? ${depId}: (not found)`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
lines.push(" Dependencies: none");
|
|
140
|
+
}
|
|
141
|
+
if ((taskFile.task.dependents ?? []).length > 0) {
|
|
142
|
+
lines.push(" Dependents (tasks that depend on this one):");
|
|
143
|
+
for (const depId of taskFile.task.dependents) {
|
|
144
|
+
const dep = await readTask(depId, projectSlug);
|
|
145
|
+
if (dep) {
|
|
146
|
+
const icon = STATUS_ICONS[dep.task.status] ?? "?";
|
|
147
|
+
lines.push(` ${icon} ${depId}: ${dep.task.title}`);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
lines.push(` ? ${depId}: (not found)`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
lines.push(" Dependents: none");
|
|
156
|
+
}
|
|
157
|
+
return lines.join("\n");
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* /task validate [id] — validate task files
|
|
161
|
+
*/
|
|
162
|
+
export async function cmdTaskValidate(taskId, projectSlug) {
|
|
163
|
+
const tasks = taskId
|
|
164
|
+
? [await readTask(taskId, projectSlug)].filter(Boolean)
|
|
165
|
+
: await listTasks({ projectSlug });
|
|
166
|
+
const errors = [];
|
|
167
|
+
const warnings = [];
|
|
168
|
+
for (const t of tasks) {
|
|
169
|
+
if (!t)
|
|
170
|
+
continue;
|
|
171
|
+
const { task } = t;
|
|
172
|
+
if (!task.id)
|
|
173
|
+
errors.push(`${task.id ?? "?"}: missing id`);
|
|
174
|
+
if (!task.title)
|
|
175
|
+
errors.push(`${task.id}: missing title`);
|
|
176
|
+
if (!task.status)
|
|
177
|
+
errors.push(`${task.id}: missing status`);
|
|
178
|
+
if (!task.createdAt)
|
|
179
|
+
warnings.push(`${task.id}: missing createdAt`);
|
|
180
|
+
// Check deps exist
|
|
181
|
+
for (const dep of task.dependencies ?? []) {
|
|
182
|
+
const depFile = await readTask(dep, projectSlug);
|
|
183
|
+
if (!depFile) {
|
|
184
|
+
errors.push(`${task.id}: dependency ${dep} does not exist`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Check lock file consistency
|
|
188
|
+
const lockPath = getTaskLockPath(task.id, projectSlug);
|
|
189
|
+
const lockInfo = await readLock(lockPath);
|
|
190
|
+
if (lockInfo && task.status !== "in_progress") {
|
|
191
|
+
warnings.push(`${task.id}: has lock file but status is '${task.status}'`);
|
|
192
|
+
}
|
|
193
|
+
if (!lockInfo && task.status === "in_progress") {
|
|
194
|
+
warnings.push(`${task.id}: status is 'in_progress' but has no lock file`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const lines = [];
|
|
198
|
+
if (errors.length === 0 && warnings.length === 0) {
|
|
199
|
+
lines.push(`✓ Validated ${tasks.length} task(s) — no issues found`);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
if (errors.length > 0) {
|
|
203
|
+
lines.push(`✗ Errors (${errors.length}):`);
|
|
204
|
+
errors.forEach((e) => lines.push(` ${e}`));
|
|
205
|
+
}
|
|
206
|
+
if (warnings.length > 0) {
|
|
207
|
+
lines.push(`⚠ Warnings (${warnings.length}):`);
|
|
208
|
+
warnings.forEach((w) => lines.push(` ${w}`));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return lines.join("\n");
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task file CRUD operations.
|
|
3
|
+
* Spec: §3.3 — Task File Schema, §3.4 — Lock File Schema
|
|
4
|
+
*/
|
|
5
|
+
import { Task, TaskStatus, Labels } from "@pi-orca/core";
|
|
6
|
+
export interface CreateTaskParams {
|
|
7
|
+
title: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
dependencies?: string[];
|
|
10
|
+
labels?: Labels;
|
|
11
|
+
projectSlug?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface UpdateTaskParams {
|
|
14
|
+
title?: string;
|
|
15
|
+
dependencies?: string[];
|
|
16
|
+
labels?: Labels;
|
|
17
|
+
projectSlug?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ListTasksFilter {
|
|
20
|
+
status?: TaskStatus | TaskStatus[];
|
|
21
|
+
labels?: Labels;
|
|
22
|
+
includeArchived?: boolean;
|
|
23
|
+
projectSlug?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Task file with its path on disk.
|
|
27
|
+
*/
|
|
28
|
+
export interface TaskFile {
|
|
29
|
+
task: Task;
|
|
30
|
+
filePath: string;
|
|
31
|
+
body: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate the next sequential task ID.
|
|
35
|
+
*/
|
|
36
|
+
export declare function generateTaskId(tasksDir: string): Promise<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Get full path to a task file.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getTaskFilePath(taskId: string, projectSlug?: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Get full path to a task lock file.
|
|
43
|
+
*/
|
|
44
|
+
export declare function getTaskLockPath(taskId: string, projectSlug?: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Create a new task file.
|
|
47
|
+
* Spec: §2.1.1
|
|
48
|
+
*/
|
|
49
|
+
export declare function createTask(params: CreateTaskParams): Promise<TaskFile>;
|
|
50
|
+
/**
|
|
51
|
+
* Read a task file from disk.
|
|
52
|
+
* Spec: §2.1.2
|
|
53
|
+
*/
|
|
54
|
+
export declare function readTask(taskId: string, projectSlug?: string): Promise<TaskFile | null>;
|
|
55
|
+
/**
|
|
56
|
+
* Write a task file to disk (replaces content).
|
|
57
|
+
*/
|
|
58
|
+
export declare function writeTask(taskFile: TaskFile): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Update task frontmatter fields.
|
|
61
|
+
* Spec: §2.1.3
|
|
62
|
+
*/
|
|
63
|
+
export declare function updateTask(taskId: string, patch: Partial<Task>, projectSlug?: string): Promise<TaskFile | null>;
|
|
64
|
+
/**
|
|
65
|
+
* List tasks with optional filters.
|
|
66
|
+
* Spec: §2.1.4
|
|
67
|
+
*/
|
|
68
|
+
export declare function listTasks(filter?: ListTasksFilter): Promise<TaskFile[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Build dependency map from all task files.
|
|
71
|
+
* Returns { dependencies: task→deps[], dependents: task→dependents[] }
|
|
72
|
+
*/
|
|
73
|
+
export declare function buildDependencyMaps(projectSlug?: string): Promise<{
|
|
74
|
+
dependencies: Map<string, string[]>;
|
|
75
|
+
dependents: Map<string, string[]>;
|
|
76
|
+
}>;
|
|
77
|
+
/**
|
|
78
|
+
* Update reverse dependency (dependents) links when a task's dependencies change.
|
|
79
|
+
*/
|
|
80
|
+
export declare function syncDependentLinks(taskId: string, oldDeps: string[], newDeps: string[], projectSlug?: string): Promise<void>;
|
|
81
|
+
//# sourceMappingURL=crud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.d.ts","sourceRoot":"","sources":["../../src/engine/crud.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EACL,IAAI,EACJ,UAAU,EAQV,MAAM,EACP,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiC5E;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAO1B;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjE;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,EACpB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAY1B;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAoD7E;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC;IACT,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACnC,CAAC,CAmBD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE,MAAM,EAAE,EACjB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAyBf"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task file CRUD operations.
|
|
3
|
+
* Spec: §3.3 — Task File Schema, §3.4 — Lock File Schema
|
|
4
|
+
*/
|
|
5
|
+
import { readdir } from "fs/promises";
|
|
6
|
+
import { existsSync } from "fs";
|
|
7
|
+
import { join } from "path";
|
|
8
|
+
import { parseFrontmatter, serializeFrontmatter, atomicWrite, ensureDir, readFileIfExists, matchLabels, getOrcaTasksDir, } from "@pi-orca/core";
|
|
9
|
+
/**
|
|
10
|
+
* Generate the next sequential task ID.
|
|
11
|
+
*/
|
|
12
|
+
export async function generateTaskId(tasksDir) {
|
|
13
|
+
await ensureDir(tasksDir);
|
|
14
|
+
if (!existsSync(tasksDir)) {
|
|
15
|
+
return "task-001";
|
|
16
|
+
}
|
|
17
|
+
let entries;
|
|
18
|
+
try {
|
|
19
|
+
entries = await readdir(tasksDir);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return "task-001";
|
|
23
|
+
}
|
|
24
|
+
// Find highest existing task number
|
|
25
|
+
const taskNums = entries
|
|
26
|
+
.filter((e) => /^task-\d+\.md$/.test(e))
|
|
27
|
+
.map((e) => parseInt(e.replace("task-", "").replace(".md", ""), 10))
|
|
28
|
+
.filter((n) => !isNaN(n));
|
|
29
|
+
const max = taskNums.length > 0 ? Math.max(...taskNums) : 0;
|
|
30
|
+
return `task-${String(max + 1).padStart(3, "0")}`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get full path to a task file.
|
|
34
|
+
*/
|
|
35
|
+
export function getTaskFilePath(taskId, projectSlug) {
|
|
36
|
+
return join(getOrcaTasksDir(projectSlug), `${taskId}.md`);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get full path to a task lock file.
|
|
40
|
+
*/
|
|
41
|
+
export function getTaskLockPath(taskId, projectSlug) {
|
|
42
|
+
return join(getOrcaTasksDir(projectSlug), `${taskId}.lock`);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a new task file.
|
|
46
|
+
* Spec: §2.1.1
|
|
47
|
+
*/
|
|
48
|
+
export async function createTask(params) {
|
|
49
|
+
const tasksDir = getOrcaTasksDir(params.projectSlug);
|
|
50
|
+
await ensureDir(tasksDir);
|
|
51
|
+
const taskId = await generateTaskId(tasksDir);
|
|
52
|
+
const now = new Date().toISOString();
|
|
53
|
+
const task = {
|
|
54
|
+
id: taskId,
|
|
55
|
+
title: params.title,
|
|
56
|
+
status: "pending",
|
|
57
|
+
createdAt: now,
|
|
58
|
+
updatedAt: now,
|
|
59
|
+
completedAt: "",
|
|
60
|
+
assignedTo: "",
|
|
61
|
+
assignedSessionPath: "",
|
|
62
|
+
dependencies: params.dependencies ?? [],
|
|
63
|
+
dependents: [],
|
|
64
|
+
blockedReason: "",
|
|
65
|
+
retryCount: 0,
|
|
66
|
+
labels: params.labels ?? {},
|
|
67
|
+
archivable: false,
|
|
68
|
+
};
|
|
69
|
+
const body = params.description
|
|
70
|
+
? `## Description\n\n${params.description}\n`
|
|
71
|
+
: `## Description\n\n_No description provided._\n`;
|
|
72
|
+
const content = serializeFrontmatter(task, body);
|
|
73
|
+
const filePath = getTaskFilePath(taskId, params.projectSlug);
|
|
74
|
+
await atomicWrite(filePath, content);
|
|
75
|
+
return { task, filePath, body };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Read a task file from disk.
|
|
79
|
+
* Spec: §2.1.2
|
|
80
|
+
*/
|
|
81
|
+
export async function readTask(taskId, projectSlug) {
|
|
82
|
+
const filePath = getTaskFilePath(taskId, projectSlug);
|
|
83
|
+
const content = await readFileIfExists(filePath);
|
|
84
|
+
if (!content)
|
|
85
|
+
return null;
|
|
86
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
87
|
+
return { task: frontmatter, filePath, body };
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Write a task file to disk (replaces content).
|
|
91
|
+
*/
|
|
92
|
+
export async function writeTask(taskFile) {
|
|
93
|
+
const content = serializeFrontmatter(taskFile.task, taskFile.body);
|
|
94
|
+
await atomicWrite(taskFile.filePath, content);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Update task frontmatter fields.
|
|
98
|
+
* Spec: §2.1.3
|
|
99
|
+
*/
|
|
100
|
+
export async function updateTask(taskId, patch, projectSlug) {
|
|
101
|
+
const taskFile = await readTask(taskId, projectSlug);
|
|
102
|
+
if (!taskFile)
|
|
103
|
+
return null;
|
|
104
|
+
taskFile.task = {
|
|
105
|
+
...taskFile.task,
|
|
106
|
+
...patch,
|
|
107
|
+
updatedAt: new Date().toISOString(),
|
|
108
|
+
};
|
|
109
|
+
await writeTask(taskFile);
|
|
110
|
+
return taskFile;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* List tasks with optional filters.
|
|
114
|
+
* Spec: §2.1.4
|
|
115
|
+
*/
|
|
116
|
+
export async function listTasks(filter) {
|
|
117
|
+
const tasksDir = getOrcaTasksDir(filter?.projectSlug);
|
|
118
|
+
await ensureDir(tasksDir);
|
|
119
|
+
let entries;
|
|
120
|
+
try {
|
|
121
|
+
entries = await readdir(tasksDir);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
const results = [];
|
|
127
|
+
for (const entry of entries) {
|
|
128
|
+
// Skip archived, lock files, non-md files
|
|
129
|
+
if (!entry.endsWith(".md"))
|
|
130
|
+
continue;
|
|
131
|
+
if (entry.startsWith("archived"))
|
|
132
|
+
continue;
|
|
133
|
+
const filePath = join(tasksDir, entry);
|
|
134
|
+
const content = await readFileIfExists(filePath);
|
|
135
|
+
if (!content)
|
|
136
|
+
continue;
|
|
137
|
+
try {
|
|
138
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
139
|
+
// Filter by status
|
|
140
|
+
if (filter?.status) {
|
|
141
|
+
const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];
|
|
142
|
+
if (!statuses.includes(frontmatter.status))
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
// Filter by labels
|
|
146
|
+
if (filter?.labels && Object.keys(filter.labels).length > 0) {
|
|
147
|
+
if (!matchLabels(frontmatter.labels ?? {}, filter.labels))
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
// Filter archived (unless includeArchived)
|
|
151
|
+
if (!filter?.includeArchived && frontmatter.archivable) {
|
|
152
|
+
// Still include — archivable just marks eligible for sweep
|
|
153
|
+
// Actually archivable=true items can still be listed; only skip if in archived/ folder
|
|
154
|
+
}
|
|
155
|
+
results.push({ task: frontmatter, filePath, body });
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// Skip malformed files
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Sort by task ID (e.g., task-001, task-002)
|
|
162
|
+
results.sort((a, b) => a.task.id.localeCompare(b.task.id));
|
|
163
|
+
return results;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Build dependency map from all task files.
|
|
167
|
+
* Returns { dependencies: task→deps[], dependents: task→dependents[] }
|
|
168
|
+
*/
|
|
169
|
+
export async function buildDependencyMaps(projectSlug) {
|
|
170
|
+
const tasks = await listTasks({ projectSlug });
|
|
171
|
+
const dependencies = new Map();
|
|
172
|
+
const dependents = new Map();
|
|
173
|
+
for (const { task } of tasks) {
|
|
174
|
+
dependencies.set(task.id, task.dependencies ?? []);
|
|
175
|
+
if (!dependents.has(task.id)) {
|
|
176
|
+
dependents.set(task.id, []);
|
|
177
|
+
}
|
|
178
|
+
for (const dep of task.dependencies ?? []) {
|
|
179
|
+
if (!dependents.has(dep)) {
|
|
180
|
+
dependents.set(dep, []);
|
|
181
|
+
}
|
|
182
|
+
dependents.get(dep).push(task.id);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return { dependencies, dependents };
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Update reverse dependency (dependents) links when a task's dependencies change.
|
|
189
|
+
*/
|
|
190
|
+
export async function syncDependentLinks(taskId, oldDeps, newDeps, projectSlug) {
|
|
191
|
+
// Remove taskId from dependents of removed deps
|
|
192
|
+
const removed = oldDeps.filter((d) => !newDeps.includes(d));
|
|
193
|
+
const added = newDeps.filter((d) => !oldDeps.includes(d));
|
|
194
|
+
for (const depId of removed) {
|
|
195
|
+
const depFile = await readTask(depId, projectSlug);
|
|
196
|
+
if (depFile) {
|
|
197
|
+
depFile.task.dependents = (depFile.task.dependents ?? []).filter((id) => id !== taskId);
|
|
198
|
+
depFile.task.updatedAt = new Date().toISOString();
|
|
199
|
+
await writeTask(depFile);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
for (const depId of added) {
|
|
203
|
+
const depFile = await readTask(depId, projectSlug);
|
|
204
|
+
if (depFile) {
|
|
205
|
+
const deps = depFile.task.dependents ?? [];
|
|
206
|
+
if (!deps.includes(taskId)) {
|
|
207
|
+
depFile.task.dependents = [...deps, taskId];
|
|
208
|
+
depFile.task.updatedAt = new Date().toISOString();
|
|
209
|
+
await writeTask(depFile);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=crud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.js","sourceRoot":"","sources":["../../src/engine/crud.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DAG validation and cascading for tasks.
|
|
3
|
+
* Spec: §3.5 — Dependency Validation
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Validate that adding a dependency does not create a cycle.
|
|
7
|
+
* Returns cycle path string if cycle found, null if safe.
|
|
8
|
+
* Spec: §3.5 — Cycle Detection
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateNoCycle(taskId: string, newDependency: string, projectSlug?: string): Promise<string | null>;
|
|
11
|
+
/**
|
|
12
|
+
* Validate all new dependencies for a task do not create cycles.
|
|
13
|
+
* Returns error message if any cycle found, null if all safe.
|
|
14
|
+
*/
|
|
15
|
+
export declare function validateDependencies(taskId: string, newDependencies: string[], projectSlug?: string): Promise<string | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Cascade failure to all transitive dependents.
|
|
18
|
+
* When a task fails, all tasks that depend on it (directly or transitively)
|
|
19
|
+
* are blocked with blockedReason pointing to the root failed task.
|
|
20
|
+
* Spec: §3.5 — Failure Cascading
|
|
21
|
+
*/
|
|
22
|
+
export declare function cascadeFailure(failedTaskId: string, projectSlug?: string): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Re-evaluate and unblock dependents after a task's failure is resolved.
|
|
25
|
+
* When a failed task is retried and completes, all dependents whose
|
|
26
|
+
* blockedReason traced back to this task are re-evaluated.
|
|
27
|
+
* Spec: §3.5 — Unblock Cascading
|
|
28
|
+
*/
|
|
29
|
+
export declare function cascadeUnblock(resolvedTaskId: string, projectSlug?: string): Promise<void>;
|
|
30
|
+
//# sourceMappingURL=dag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag.d.ts","sourceRoot":"","sources":["../../src/engine/dag.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,EAAE,EACzB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMxB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,cAAc,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAwCf"}
|