Skip to main content

ralph/commands/task/decompose/
types.rs

1//! Shared task decomposition data models.
2//!
3//! Responsibilities:
4//! - Define the public preview/write types exposed to CLI and machine consumers.
5//! - Hold planner-response parsing structs shared by normalization helpers.
6//! - Keep decomposition-only internal state localized away from the facade module.
7//!
8//! Not handled here:
9//! - Runner invocation, prompt rendering, or queue mutation logic.
10//! - Tree normalization algorithms or task materialization helpers.
11//!
12//! Invariants/assumptions:
13//! - Serialized public types remain stable for current CLI and machine output contracts.
14//! - Internal planner structs mirror the planner JSON schema with unknown fields rejected.
15
16use crate::contracts::{Model, ReasoningEffort, Runner, Task, TaskStatus};
17use serde::{Deserialize, Serialize};
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
20#[serde(rename_all = "snake_case")]
21pub enum DecompositionChildPolicy {
22    Fail,
23    Append,
24    Replace,
25}
26
27#[derive(Debug, Clone)]
28pub struct TaskDecomposeOptions {
29    pub source_input: String,
30    pub attach_to_task_id: Option<String>,
31    pub max_depth: u8,
32    pub max_children: usize,
33    pub max_nodes: usize,
34    pub status: TaskStatus,
35    pub child_policy: DecompositionChildPolicy,
36    pub with_dependencies: bool,
37    pub runner_override: Option<Runner>,
38    pub model_override: Option<Model>,
39    pub reasoning_effort_override: Option<ReasoningEffort>,
40    pub runner_cli_overrides: crate::contracts::RunnerCliOptionsPatch,
41    pub repoprompt_tool_injection: bool,
42}
43
44#[derive(Debug, Clone, Serialize)]
45#[serde(tag = "kind", rename_all = "snake_case")]
46pub enum DecompositionSource {
47    Freeform { request: String },
48    ExistingTask { task: Box<Task> },
49}
50
51#[derive(Debug, Clone, Serialize)]
52pub struct DecompositionAttachTarget {
53    pub task: Box<Task>,
54    pub has_existing_children: bool,
55}
56
57#[derive(Debug, Clone, Serialize)]
58pub struct DecompositionPreview {
59    pub source: DecompositionSource,
60    pub attach_target: Option<DecompositionAttachTarget>,
61    pub plan: DecompositionPlan,
62    pub write_blockers: Vec<String>,
63    pub child_status: TaskStatus,
64    pub child_policy: DecompositionChildPolicy,
65    pub with_dependencies: bool,
66}
67
68#[derive(Debug, Clone, Serialize)]
69pub struct DecompositionPlan {
70    pub root: PlannedNode,
71    pub warnings: Vec<String>,
72    pub total_nodes: usize,
73    pub leaf_nodes: usize,
74    pub dependency_edges: Vec<DependencyEdgePreview>,
75}
76
77#[derive(Debug, Clone, Serialize)]
78pub struct DependencyEdgePreview {
79    pub task_title: String,
80    pub depends_on_title: String,
81}
82
83#[derive(Debug, Clone, Serialize)]
84pub struct TaskDecomposeWriteResult {
85    pub root_task_id: Option<String>,
86    pub parent_task_id: Option<String>,
87    pub created_ids: Vec<String>,
88    pub replaced_ids: Vec<String>,
89    pub parent_annotated: bool,
90}
91
92#[derive(Debug, Clone, Deserialize)]
93#[serde(deny_unknown_fields)]
94pub(super) struct RawDecompositionResponse {
95    #[serde(default)]
96    pub(super) warnings: Vec<String>,
97    pub(super) tree: RawPlannedNode,
98}
99
100#[derive(Debug, Clone, Deserialize)]
101#[serde(deny_unknown_fields)]
102pub(super) struct RawPlannedNode {
103    #[serde(default)]
104    pub(super) key: Option<String>,
105    pub(super) title: String,
106    #[serde(default)]
107    pub(super) description: Option<String>,
108    #[serde(default)]
109    pub(super) plan: Vec<String>,
110    #[serde(default)]
111    pub(super) tags: Vec<String>,
112    #[serde(default)]
113    pub(super) scope: Vec<String>,
114    #[serde(default)]
115    pub(super) depends_on: Vec<String>,
116    #[serde(default)]
117    pub(super) children: Vec<RawPlannedNode>,
118}
119
120#[derive(Debug, Clone, Serialize)]
121pub struct PlannedNode {
122    pub planner_key: String,
123    pub title: String,
124    pub description: Option<String>,
125    pub plan: Vec<String>,
126    pub tags: Vec<String>,
127    pub scope: Vec<String>,
128    pub depends_on_keys: Vec<String>,
129    pub children: Vec<PlannedNode>,
130    #[serde(skip_serializing)]
131    pub(super) dependency_refs: Vec<String>,
132}
133
134#[derive(Debug, Clone, Copy, PartialEq, Eq)]
135pub(super) enum SourceKind {
136    Freeform,
137    ExistingTask,
138}
139
140pub(super) struct PlannerState {
141    pub(super) remaining_nodes: usize,
142    pub(super) warnings: Vec<String>,
143    pub(super) with_dependencies: bool,
144}