Skip to main content

heddle_cli_args/cli/cli_args/
commands_context.rs

1// SPDX-License-Identifier: Apache-2.0
2//! Context annotation subcommands.
3
4/// Context subcommands.
5#[derive(Clone, Debug, clap::Subcommand)]
6pub enum ContextCommands {
7    /// Attach a context annotation to a file, symbol, line range, or state.
8    Set(ContextSetArgs),
9
10    /// Show current context annotations for a file or state target.
11    Get(ContextGetArgs),
12
13    /// List all active context targets.
14    List(ContextListArgs),
15
16    /// Show full revision history for one logical annotation.
17    History(ContextHistoryArgs),
18
19    /// Add a new revision to an existing logical annotation.
20    Edit(ContextEditArgs),
21
22    /// Create a replacement logical annotation and supersede an older one.
23    Supersede(ContextSupersedeArgs),
24
25    /// Remove context annotations.
26    Rm(ContextRmArgs),
27
28    /// Check annotation staleness against current code.
29    Check(ContextCheckArgs),
30
31    /// Suggest low-noise targets that may benefit from context.
32    Suggest(ContextSuggestArgs),
33
34    /// Audit stale, superseded, and duplicate context.
35    Audit(ContextAuditArgs),
36
37    /// Mine external sources for context annotations.
38    #[cfg(all(feature = "git-overlay", feature = "ingest"))]
39    Reason {
40        #[command(subcommand)]
41        command: ContextReasonCommands,
42    },
43}
44
45#[derive(Clone, Debug, clap::Args)]
46pub struct ContextTargetArgs {
47    /// File path to annotate/query.
48    #[arg(long, conflicts_with = "state")]
49    pub path: Option<String>,
50
51    /// State/change ID for broader guidance.
52    #[arg(long, conflicts_with = "path")]
53    pub state: Option<String>,
54}
55
56#[cfg(all(feature = "git-overlay", feature = "ingest"))]
57#[derive(Clone, Debug, clap::Subcommand)]
58pub enum ContextReasonCommands {
59    /// Mine Git-agent transcripts and attach reasoning as context annotations.
60    Git(ContextReasonGitArgs),
61}
62
63#[cfg(all(feature = "git-overlay", feature = "ingest"))]
64#[derive(Clone, Debug, clap::Args)]
65pub struct ContextReasonGitArgs {
66    /// Source git repository the transcripts are about.
67    #[arg(long)]
68    pub path: std::path::PathBuf,
69
70    /// Cap candidates per commit. Higher = more coverage at the cost of cross-attribution.
71    #[arg(long, default_value_t = 5)]
72    pub max_sessions_per_commit: usize,
73
74    /// Drop sessions below this confidence.
75    #[arg(long, default_value_t = 0.20)]
76    pub min_match_confidence: f32,
77
78    /// Limit how many commits the reason pass walks.
79    #[arg(long)]
80    pub limit: Option<usize>,
81
82    /// Override the Claude transcript store. Empty string disables.
83    #[arg(long = "claude-home")]
84    pub claude_home: Option<String>,
85
86    /// Override the Codex transcript store. Empty string disables.
87    #[arg(long = "codex-home")]
88    pub codex_home: Option<String>,
89
90    /// Override the OpenCode data dir. Empty string disables.
91    #[arg(long = "opencode-home")]
92    pub opencode_home: Option<String>,
93
94    /// Do not write annotations; only report what would happen.
95    #[arg(long)]
96    pub dry_run: bool,
97}
98
99/// Arguments for `heddle context set`.
100#[derive(Clone, Debug, clap::Args)]
101pub struct ContextSetArgs {
102    #[command(flatten)]
103    pub target: ContextTargetArgs,
104
105    /// Annotation scope: "file" (default), "symbol:<name>", or "lines:<start>-<end>".
106    #[arg(short, long)]
107    pub scope: Option<String>,
108
109    /// Primary annotation kind: constraint, invariant, or rationale.
110    #[arg(
111        long,
112        default_value = "rationale",
113        value_parser = ["constraint", "invariant", "rationale"]
114    )]
115    pub kind: String,
116
117    /// Explicit tags for categorization (can be repeated).
118    #[arg(long)]
119    pub tag: Vec<String>,
120
121    /// Annotation content (inline).
122    #[arg(short = 'm', long)]
123    pub message: Option<String>,
124
125    /// Read annotation content from a file.
126    #[arg(long)]
127    pub file: Option<std::path::PathBuf>,
128}
129
130/// Arguments for `heddle context get`.
131#[derive(Clone, Debug, clap::Args)]
132pub struct ContextGetArgs {
133    #[command(flatten)]
134    pub target: ContextTargetArgs,
135
136    /// Filter by scope.
137    #[arg(short, long)]
138    pub scope: Option<String>,
139
140    /// Filter by tag.
141    #[arg(long)]
142    pub tag: Option<String>,
143
144    /// Read context from an explicit historical ref/state instead of HEAD.
145    #[arg(long)]
146    pub r#ref: Option<String>,
147}
148
149/// Arguments for `heddle context list`.
150#[derive(Clone, Debug, clap::Args)]
151pub struct ContextListArgs {
152    /// Optional path prefix to filter file targets by.
153    #[arg(long)]
154    pub prefix: Option<String>,
155
156    /// Filter by tag.
157    #[arg(long)]
158    pub tag: Option<String>,
159
160    /// Read context from an explicit historical ref/state instead of HEAD.
161    #[arg(long)]
162    pub r#ref: Option<String>,
163
164    /// Include superseded logical annotations in listings.
165    #[arg(long)]
166    pub include_superseded: bool,
167}
168
169#[derive(Clone, Debug, clap::Args)]
170pub struct ContextHistoryArgs {
171    /// Stable logical annotation ID.
172    pub annotation_id: String,
173
174    /// Read context from an explicit historical ref/state instead of HEAD.
175    #[arg(long)]
176    pub r#ref: Option<String>,
177}
178
179#[derive(Clone, Debug, clap::Args)]
180pub struct ContextEditArgs {
181    /// Stable logical annotation ID.
182    pub annotation_id: String,
183
184    /// Override the annotation kind for the new revision.
185    #[arg(long, value_parser = ["constraint", "invariant", "rationale"])]
186    pub kind: Option<String>,
187
188    /// Explicit tags for the new revision (can be repeated).
189    #[arg(long)]
190    pub tag: Vec<String>,
191
192    /// New revision content (inline).
193    #[arg(short = 'm', long)]
194    pub message: Option<String>,
195
196    /// Read revision content from a file.
197    #[arg(long)]
198    pub file: Option<std::path::PathBuf>,
199}
200
201#[derive(Clone, Debug, clap::Args)]
202pub struct ContextSupersedeArgs {
203    /// Stable logical annotation ID to supersede.
204    pub annotation_id: String,
205
206    #[command(flatten)]
207    pub target: ContextTargetArgs,
208
209    /// Replacement annotation scope.
210    #[arg(short, long)]
211    pub scope: Option<String>,
212
213    /// Replacement annotation kind: constraint, invariant, or rationale.
214    #[arg(
215        long,
216        default_value = "rationale",
217        value_parser = ["constraint", "invariant", "rationale"]
218    )]
219    pub kind: String,
220
221    /// Explicit tags for the replacement annotation.
222    #[arg(long)]
223    pub tag: Vec<String>,
224
225    /// Replacement annotation content (inline).
226    #[arg(short = 'm', long)]
227    pub message: Option<String>,
228
229    /// Read replacement content from a file.
230    #[arg(long)]
231    pub file: Option<std::path::PathBuf>,
232}
233
234/// Arguments for `heddle context rm`.
235#[derive(Clone, Debug, clap::Args)]
236pub struct ContextRmArgs {
237    #[command(flatten)]
238    pub target: ContextTargetArgs,
239
240    /// Remove only annotations matching this scope.
241    #[arg(short, long)]
242    pub scope: Option<String>,
243
244    /// Remove all annotations for this target.
245    #[arg(long)]
246    pub all: bool,
247}
248
249/// Arguments for `heddle context check`.
250#[derive(Clone, Debug, clap::Args)]
251pub struct ContextCheckArgs {
252    /// File path to check (checks all annotated files if omitted).
253    #[arg(long)]
254    pub path: Option<String>,
255
256    /// State ID to check broader guidance on.
257    #[arg(long)]
258    pub state: Option<String>,
259
260    /// Filter by tag.
261    #[arg(long)]
262    pub tag: Option<String>,
263
264    /// Read context from an explicit historical ref/state instead of HEAD.
265    #[arg(long)]
266    pub r#ref: Option<String>,
267}
268
269#[derive(Clone, Debug, clap::Args)]
270pub struct ContextSuggestArgs {
271    /// Read suggestions from an explicit historical ref/state instead of HEAD.
272    #[arg(long)]
273    pub r#ref: Option<String>,
274
275    /// Maximum suggestions to print.
276    #[arg(short = 'n', long, default_value = "10")]
277    pub limit: usize,
278}
279
280#[derive(Clone, Debug, clap::Args)]
281pub struct ContextAuditArgs {
282    /// Read context from an explicit historical ref/state instead of HEAD.
283    #[arg(long)]
284    pub r#ref: Option<String>,
285}