Skip to main content

tix/cli/
cli_initiative.rs

1#[allow(clippy::wildcard_imports)]
2use super::*;
3
4/// The `tix initiative` subcommands (mission `roadmap-initiatives-01M3C8SX`, WP04).
5///
6/// A **required** subcommand, like `tix project` and `tix epic`. Selection is by the
7/// stable id (the registry key); a name resolves to the same initiative as a
8/// convenience. A rename through `edit --name` changes the label only: the id is not
9/// re-keyed, so every association and derived value survives.
10#[derive(Subcommand)]
11pub enum InitiativeCommand {
12    /// Create an initiative and allocate a stable id
13    ///
14    /// The name is a display label, not the identity: `tix initiative edit --name`
15    /// changes it and every association survives, because the record is keyed by id.
16    Create {
17        /// Display name (unique within the registry, case-insensitively)
18        #[arg(value_name = "NAME")]
19        name: String,
20        /// Optional strategic outcome
21        #[arg(long)]
22        outcome: Option<String>,
23        /// Owner identity string; no lookup, never inferred
24        #[arg(long)]
25        owner: Option<String>,
26        /// Free-form initiative status (not a board column)
27        #[arg(long)]
28        status: Option<String>,
29        /// Initiative priority (a known spelling is normalized; an unknown one is kept)
30        #[arg(long)]
31        priority: Option<String>,
32        /// Filterable labels, comma-separated
33        #[arg(long)]
34        labels: Option<String>,
35        /// Target date (`YYYY-MM-DD`)
36        #[arg(long = "target-date")]
37        target_date: Option<String>,
38        /// Project ids this initiative concerns, comma-separated
39        ///
40        /// Shape-checked only, never resolved: a well-formed id the registry does not
41        /// hold is stored and diagnosed by `tix roadmap`/`tix lint`, so it is
42        /// repairable.
43        #[arg(long, value_name = "ID")]
44        projects: Option<String>,
45        /// Epic ids this initiative concerns, comma-separated
46        #[arg(long, value_name = "ID")]
47        epics: Option<String>,
48        /// Milestone names this initiative concerns, comma-separated
49        #[arg(long, value_name = "NAME")]
50        milestones: Option<String>,
51    },
52    /// Edit an initiative's fields; a rename changes the label only
53    ///
54    /// Nothing is re-keyed, so every association and derived value stays intact. An
55    /// optional value with a blank spelling clears the field (`--owner ""`), and a
56    /// blank reference list clears it (`--projects ""`).
57    Edit {
58        /// Initiative id (a name is accepted as a convenience)
59        #[arg(value_name = "ID")]
60        reference: String,
61        /// New display name
62        #[arg(long)]
63        name: Option<String>,
64        /// New strategic outcome (`--outcome ""` clears)
65        #[arg(long)]
66        outcome: Option<String>,
67        /// New owner identity string (`--owner ""` clears)
68        #[arg(long)]
69        owner: Option<String>,
70        /// New free-form status (`--status ""` clears)
71        #[arg(long)]
72        status: Option<String>,
73        /// New priority (`--priority ""` clears)
74        #[arg(long)]
75        priority: Option<String>,
76        /// Replace the label list, comma-separated (`--labels ""` clears)
77        #[arg(long)]
78        labels: Option<String>,
79        /// New target date (`YYYY-MM-DD`; `--target-date ""` clears)
80        #[arg(long = "target-date")]
81        target_date: Option<String>,
82        /// Replace the project ids, comma-separated (`--projects ""` clears)
83        #[arg(long, value_name = "ID")]
84        projects: Option<String>,
85        /// Replace the epic ids, comma-separated (`--epics ""` clears)
86        #[arg(long, value_name = "ID")]
87        epics: Option<String>,
88        /// Replace the milestone names, comma-separated (`--milestones ""` clears)
89        #[arg(long, value_name = "NAME")]
90        milestones: Option<String>,
91    },
92    /// List initiatives in declaration order, with ids, target dates and status
93    List,
94    /// Show one initiative's record, metadata and references
95    Show {
96        /// Initiative id (a name is accepted as a convenience)
97        #[arg(value_name = "ID")]
98        reference: String,
99    },
100    /// Delete an initiative's registry entry (nothing else is ever deleted)
101    ///
102    /// The record's own references are reported and nothing cascades: no project,
103    /// epic, milestone or issue is touched, and no association is silently repaired.
104    Delete {
105        /// Initiative id (a name is accepted as a convenience)
106        #[arg(value_name = "ID")]
107        reference: String,
108        /// Confirm without prompting
109        #[arg(long)]
110        yes: bool,
111    },
112    /// Associate an initiative with exactly one project, epic or milestone
113    ///
114    /// Name exactly one of `--project`, `--epic`, `--milestone`; the kind is part of
115    /// the record, so guessing is worse than asking. A well-formed reference that
116    /// names nothing is stored and stays diagnosable, and a repeated association is
117    /// an idempotent no-op that writes no bytes.
118    Associate {
119        /// Initiative id (a name is accepted as a convenience)
120        #[arg(value_name = "ID")]
121        reference: String,
122        /// Project **id** to associate
123        #[arg(long, value_name = "ID")]
124        project: Option<String>,
125        /// Epic **id** to associate
126        #[arg(long, value_name = "ID")]
127        epic: Option<String>,
128        /// Milestone **name** to associate
129        #[arg(long, value_name = "NAME")]
130        milestone: Option<String>,
131    },
132    /// Drop an explicit association from an initiative
133    ///
134    /// Name exactly one of `--project`, `--epic`, `--milestone`. Dropping an
135    /// association that is not recorded is an idempotent no-op that writes no bytes.
136    Dereference {
137        /// Initiative id (a name is accepted as a convenience)
138        #[arg(value_name = "ID")]
139        reference: String,
140        /// Project **id** to drop
141        #[arg(long, value_name = "ID")]
142        project: Option<String>,
143        /// Epic **id** to drop
144        #[arg(long, value_name = "ID")]
145        epic: Option<String>,
146        /// Milestone **name** to drop
147        #[arg(long, value_name = "NAME")]
148        milestone: Option<String>,
149    },
150}