Skip to main content

heddle_cli_args/cli/cli_args/
commands_review.rs

1// SPDX-License-Identifier: Apache-2.0
2//! `heddle review` — signed Thread comparison review workflow.
3
4use clap::{Args, Subcommand, ValueEnum};
5
6use super::RemoteChoiceArgs;
7
8#[derive(Clone, Debug, Subcommand)]
9pub enum ReviewCommands {
10    /// Show the exact source and target comparison for a Thread.
11    Show(ReviewShowArgs),
12    /// Approve the exact source and target comparison shown for this thread, using your configured signing identity.
13    #[command(
14        about = "Approve the exact source and target comparison shown for this thread, using your configured signing identity."
15    )]
16    Approve(ReviewApproveArgs),
17    /// List signed review decisions for a Thread.
18    List(ReviewListArgs),
19    /// Revoke one of your signed approvals.
20    Revoke(ReviewRevokeArgs),
21    /// Check whether a Thread's exact comparison is ready to land into a target.
22    Readiness(ReviewReadinessArgs),
23    /// Submit a low-level review signature on a state.
24    #[command(hide = true)]
25    Sign(ReviewSignArgs),
26    /// Walk to the next pending review when review selection is configured.
27    #[command(hide = true)]
28    Next(ReviewNextArgs),
29    /// Per-module signal health over a rolling window.
30    #[command(hide = true)]
31    Health(ReviewHealthArgs),
32}
33
34#[derive(Clone, Debug, Args)]
35pub struct ReviewShowArgs {
36    /// Thread to review. Defaults to the current Thread.
37    pub thread: Option<String>,
38    #[command(flatten)]
39    pub remote_choice: RemoteChoiceArgs,
40}
41
42#[derive(Clone, Debug, Args)]
43pub struct ReviewApproveArgs {
44    /// Thread to approve. Defaults to the current Thread.
45    pub thread: Option<String>,
46    /// Human note attached to the approval.
47    #[arg(short = 'm', long)]
48    pub message: Option<String>,
49    #[command(flatten)]
50    pub remote_choice: RemoteChoiceArgs,
51}
52
53#[derive(Clone, Debug, Args)]
54pub struct ReviewListArgs {
55    /// Thread whose review decisions to list. Defaults to the current Thread.
56    pub thread: Option<String>,
57    #[command(flatten)]
58    pub remote_choice: RemoteChoiceArgs,
59}
60
61#[derive(Clone, Debug, Args)]
62pub struct ReviewRevokeArgs {
63    /// UUID of the approval to revoke.
64    #[arg(value_name = "REVIEW_ID")]
65    pub review_id: String,
66    /// Thread containing the approval.
67    #[arg(long, value_name = "THREAD")]
68    pub thread: String,
69    #[command(flatten)]
70    pub remote_choice: RemoteChoiceArgs,
71}
72
73#[derive(Clone, Debug, Args)]
74pub struct ReviewReadinessArgs {
75    /// Source Thread to assess. Defaults to the current Thread.
76    pub thread: Option<String>,
77    /// Target Thread that would receive the source.
78    #[arg(long, value_name = "TARGET")]
79    pub into: String,
80    #[command(flatten)]
81    pub remote_choice: RemoteChoiceArgs,
82}
83
84#[derive(Clone, Debug, Args)]
85pub struct ReviewSignArgs {
86    pub state: String,
87    /// Review kind.
88    #[arg(long, value_enum)]
89    pub kind: SignKindArg,
90    /// Optional justification (unused for read/preview/co-review).
91    #[arg(long)]
92    pub justification: Option<String>,
93    /// Optional symbol-level scope. Format: `file:symbol`. Repeat for
94    /// multiple. Without any, the signature covers the whole change.
95    #[arg(long)]
96    pub symbols: Vec<String>,
97    /// Cryptographic algorithm. Defaults to `ed25519`.
98    #[arg(long, default_value = "ed25519")]
99    pub algorithm: String,
100    /// Public key in hex. Required.
101    #[arg(long)]
102    pub public_key: String,
103    /// Signature bytes in hex. Required.
104    #[arg(long)]
105    pub signature: String,
106    /// Unix timestamp (seconds) the client signed at. Required — the
107    /// server verifies the signature over this exact timestamp and rejects
108    /// values outside a small skew window.
109    #[arg(long)]
110    pub signed_at_unix: i64,
111}
112
113#[derive(Clone, Debug, ValueEnum)]
114pub enum SignKindArg {
115    Read,
116    AgentPreview,
117    AgentCoReview,
118}
119
120impl SignKindArg {
121    pub fn as_wire(&self) -> &'static str {
122        match self {
123            Self::Read => "read",
124            Self::AgentPreview => "agent_preview",
125            Self::AgentCoReview => "agent_co_review",
126        }
127    }
128
129    pub fn as_proto(&self) -> objects::object::ReviewKind {
130        match self {
131            Self::Read => objects::object::ReviewKind::Read,
132            Self::AgentPreview => objects::object::ReviewKind::AgentPreview,
133            Self::AgentCoReview => objects::object::ReviewKind::AgentCoReview,
134        }
135    }
136}
137
138#[derive(Clone, Debug, Args)]
139pub struct ReviewNextArgs {
140    /// Only show reviews assigned to the current actor.
141    #[arg(long)]
142    pub mine_only: bool,
143    /// Filter by review kind.
144    #[arg(long)]
145    pub kind: Option<String>,
146}
147
148#[derive(Clone, Debug, Args)]
149pub struct ReviewHealthArgs {
150    /// Number of recent states to consider. Server clamps to a sensible
151    /// default when unset.
152    #[arg(long)]
153    pub window: Option<u32>,
154}