Skip to main content

ag_protocol/
subtask.rs

1//! Orchestrator subtask model shared across protocol, coordinator, and UI
2//! code.
3
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7/// One proposed child session in an orchestrator decomposition plan.
8///
9/// Each subtask is executed unattended by its own child session in its own
10/// worktree, branched from the same base branch as its siblings. Children never
11/// coordinate with each other while running, so a subtask is only well-formed
12/// when its prompt is self-contained and its `touched_areas` do not overlap any
13/// sibling's.
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
15#[schemars(
16    title = "SubtaskItem",
17    description = "One proposed child session in an orchestrator decomposition plan. Each subtask \
18                   runs unattended in its own worktree branched from the same base branch, so it \
19                   must be completable without coordinating with its siblings."
20)]
21pub struct SubtaskItem {
22    /// Observable conditions the worker must satisfy before the controller
23    /// may verify this task as complete.
24    #[serde(default)]
25    #[schemars(
26        title = "acceptance_criteria",
27        description = "Concrete, testable acceptance criteria for this subtask. The approval UI \
28                       shows these criteria and the controller verifies the finished child \
29                       against the same list."
30    )]
31    pub acceptance_criteria: Vec<String>,
32    /// Complete standalone prompt handed to the child session.
33    #[schemars(
34        title = "prompt",
35        description = "Complete standalone prompt for the child session. The child sees only this \
36                       prompt and the repository, so restate every constraint it needs instead of \
37                       referring back to the plan or to sibling subtasks."
38    )]
39    pub prompt: String,
40    /// Stable identifier for this subtask within one orchestration.
41    #[schemars(
42        title = "task_key",
43        description = "Short stable `kebab-case` identifier for this subtask, unique within the \
44                       plan. Reuse the exact same key when re-proposing a subtask so a retry \
45                       replaces the previous attempt instead of creating a duplicate."
46    )]
47    pub task_key: String,
48    /// Short human-readable subtask title.
49    #[schemars(
50        title = "title",
51        description = "Short human-readable title describing what this subtask delivers."
52    )]
53    pub title: String,
54    /// Literal repository-relative paths or directories this subtask expects
55    /// to change.
56    #[serde(default)]
57    #[schemars(
58        title = "touched_areas",
59        description = "Literal repository-relative file or directory paths this subtask expects \
60                       to modify. Wildcard patterns are not supported. These sets must not \
61                       overlap between subtasks in the same plan. Defaults to an empty list when \
62                       omitted, which is rejected as an unplanned subtask."
63    )]
64    pub touched_areas: Vec<String>,
65}