210 lines
6.3 KiB
TypeScript
210 lines
6.3 KiB
TypeScript
// ─── Task Model ───────────────────────────────────────────────────────────────
|
|
|
|
export type TaskStatus =
|
|
| "pending"
|
|
| "in_progress"
|
|
| "completed"
|
|
| "failed"
|
|
| "skipped";
|
|
export type TaskStatusChar = " " | "~" | "x" | "!" | "-";
|
|
|
|
export interface Task {
|
|
/** Unique task identifier */
|
|
id: string;
|
|
/** Task title */
|
|
title: string;
|
|
/** Detailed task description */
|
|
description?: string;
|
|
/** Path to detailed spec file (relative to sourceDir) */
|
|
file?: string;
|
|
/** Current status */
|
|
status: TaskStatus;
|
|
/** Task IDs this task depends on */
|
|
dependencies: string[];
|
|
/** Explicit parallel group (optional, overrides dependency-based batching) */
|
|
parallelGroup?: number;
|
|
/** Task-level timeout in milliseconds (parsed from meta block) */
|
|
timeoutMs?: number;
|
|
/** Original index in task list for deterministic ordering */
|
|
index?: number;
|
|
/** Phase number this task belongs to (1-indexed, from ## Phase N headings) */
|
|
phase?: number;
|
|
}
|
|
|
|
export interface ParallelGroup {
|
|
/** Group index (0-based, determines execution order) */
|
|
index: number;
|
|
/** Human-readable label for the group (e.g. "Play Store prep") */
|
|
label?: string;
|
|
/** Task IDs in this group — all can run concurrently */
|
|
taskIds: string[];
|
|
}
|
|
|
|
export interface Phase {
|
|
/** Phase number (1-indexed, matches the heading number) */
|
|
number: number;
|
|
/** Phase title (e.g. "Push-to-Talk MVP") */
|
|
title: string;
|
|
/** Task IDs in this phase, in order */
|
|
taskIds: string[];
|
|
}
|
|
|
|
export interface Project {
|
|
/** Project-level objective / goal */
|
|
objective?: string;
|
|
/** All tasks in the project */
|
|
tasks: Task[];
|
|
/** Explicit dependency map: taskId → [dependency taskIds] */
|
|
dependencies: Record<string, string[]>;
|
|
/** Explicit parallel groups from "can be done in parallel" declarations */
|
|
parallelGroups?: ParallelGroup[];
|
|
/** Phased sections from ## Phase N headings (in order) */
|
|
phases?: Phase[];
|
|
/** Exit criteria (from README ## Exit Criteria section) */
|
|
exitCriteria?: string[];
|
|
/** Path to the source task file */
|
|
sourcePath: string;
|
|
/** Directory containing the source file */
|
|
sourceDir: string;
|
|
}
|
|
|
|
// ─── Execution Plan ───────────────────────────────────────────────────────────
|
|
|
|
export interface ExecutionBatch {
|
|
/** Tasks that can run concurrently in this batch */
|
|
tasks: Task[];
|
|
/** Batch number (0-indexed) */
|
|
batchIndex: number;
|
|
}
|
|
|
|
export interface ExecutionPlan {
|
|
/** Ordered batches (each batch contains parallelizable tasks) */
|
|
batches: ExecutionBatch[];
|
|
/** Total task count */
|
|
totalTasks: number;
|
|
/** Tasks skipped (already completed) */
|
|
skippedTasks: Task[];
|
|
}
|
|
|
|
// ─── Progress Model ───────────────────────────────────────────────────────────
|
|
|
|
export interface Reflection {
|
|
taskId: string;
|
|
title: string;
|
|
/** What was accomplished */
|
|
summary: string;
|
|
/** Key decisions, patterns, and learnings for downstream tasks */
|
|
keyLearnings: string[];
|
|
/** Files created or modified */
|
|
filesChanged: string[];
|
|
/** Unresolved issues or caveats */
|
|
blockers?: string[];
|
|
/** ISO timestamp */
|
|
timestamp: string;
|
|
}
|
|
|
|
export interface ToolUsage {
|
|
read: number;
|
|
write: number;
|
|
edit: number;
|
|
bash: number;
|
|
other: number;
|
|
}
|
|
|
|
export interface TaskProgressInfo {
|
|
status: Task["status"];
|
|
startedAt?: string;
|
|
completedAt?: string;
|
|
retries: number;
|
|
durationMs?: number;
|
|
reflection?: Reflection;
|
|
error?: string;
|
|
/** Tool usage counts from parsed subprocess output */
|
|
toolUsage?: ToolUsage;
|
|
/** Truncated output preview for expanded view */
|
|
outputPreview?: string;
|
|
/** Git commit messages from task execution */
|
|
commitMessages?: string[];
|
|
/** Summary derived from git commits */
|
|
commitSummary?: string;
|
|
}
|
|
|
|
export interface ProgressState {
|
|
/** Path to the source task file (legacy single-PRD mode) */
|
|
sourcePath: string;
|
|
/** Per-task status tracking (legacy single-PRD mode) */
|
|
tasks: Record<string, TaskProgressInfo>;
|
|
/** When execution started (legacy single-PRD mode) */
|
|
startedAt: string;
|
|
/** When execution last updated (legacy single-PRD mode) */
|
|
lastUpdatedAt: string;
|
|
/** Whether execution is currently paused/stopped (legacy single-PRD mode) */
|
|
paused: boolean;
|
|
/** Multiple PRDs tracked simultaneously (keyed by normalized source path) */
|
|
prds?: Record<string, PRDProgress>;
|
|
}
|
|
|
|
export interface PRDProgress {
|
|
/** Path to the source task file for this PRD */
|
|
sourcePath: string;
|
|
/** Per-task status tracking */
|
|
tasks: Record<string, TaskProgressInfo>;
|
|
/** When execution started */
|
|
startedAt: string;
|
|
/** When execution last updated */
|
|
lastUpdatedAt: string;
|
|
/** Whether execution is currently paused/stopped */
|
|
paused: boolean;
|
|
}
|
|
|
|
// ─── Configuration ────────────────────────────────────────────────────────────
|
|
|
|
export interface RalpiConfig {
|
|
paths: {
|
|
/** Directory for ralpi state files */
|
|
stateDir: string;
|
|
/** Directory for per-task reflections */
|
|
reflectionsDir: string;
|
|
};
|
|
execution: {
|
|
/** Maximum retries per task */
|
|
maxRetries: number;
|
|
/** Delay between retries in milliseconds */
|
|
retryDelayMs: number;
|
|
/** Task execution timeout in milliseconds */
|
|
timeoutMs: number;
|
|
/** Maximum parallel tasks (0 = unlimited) */
|
|
maxParallel: number;
|
|
/** Round-robin model list for parallel tasks (empty = inherit parent model) */
|
|
models: string[];
|
|
};
|
|
prompts: {
|
|
/** Additional context injected into every task prompt */
|
|
projectContext: string;
|
|
/** Custom prompt suffix for reflection extraction */
|
|
reflectionPrompt: string;
|
|
};
|
|
/** Parent session model to inherit in child agent sessions */
|
|
model?: unknown;
|
|
/** Parent session thinking level to inherit in child agent sessions */
|
|
thinkingLevel?: unknown;
|
|
}
|
|
|
|
export const DEFAULT_CONFIG: RalpiConfig = {
|
|
paths: {
|
|
stateDir: ".ralpi",
|
|
reflectionsDir: ".ralpi/reflections",
|
|
},
|
|
execution: {
|
|
maxRetries: 0,
|
|
retryDelayMs: 0,
|
|
timeoutMs: 0, // 0 = inherit Pi's own defaults (no ralpi-level timeout)
|
|
maxParallel: 3,
|
|
models: [],
|
|
},
|
|
prompts: {
|
|
projectContext: "",
|
|
reflectionPrompt: "",
|
|
},
|
|
};
|