use fallow_core::results::AnalysisResults;
use fallow_types::envelope::{
BaselineDeltas, BaselineMatch, CheckSummary, ElapsedMs, EntryPoints, Meta, RegressionResult,
SchemaVersion, ToolVersion,
};
use serde::Serialize;
use crate::audit::{AuditAttribution, AuditSummary, AuditVerdict};
use crate::health_types::{HealthGroup, HealthReport, RuntimeCoverageReport};
use crate::output_dupes::DupesReportPayload;
use crate::report::dupes_grouping::DuplicationGroup;
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "schema", schemars(title = "fallow coverage setup --json"))]
pub struct CoverageSetupOutput {
pub schema_version: CoverageSetupSchemaVersion,
pub framework_detected: CoverageSetupFramework,
pub package_manager: Option<CoverageSetupPackageManager>,
pub runtime_targets: Vec<CoverageSetupRuntimeTarget>,
pub members: Vec<CoverageSetupMember>,
pub config_written: Option<serde_json::Value>,
pub commands: Vec<String>,
pub files_to_edit: Vec<CoverageSetupFileToEdit>,
pub snippets: Vec<CoverageSetupSnippet>,
pub dockerfile_snippet: Option<String>,
pub next_steps: Vec<String>,
pub warnings: Vec<String>,
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
pub meta: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum CoverageSetupSchemaVersion {
#[serde(rename = "1")]
V1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
pub enum CoverageSetupFramework {
#[serde(rename = "nextjs")]
NextJs,
#[serde(rename = "nestjs")]
NestJs,
Nuxt,
#[serde(rename = "sveltekit")]
SvelteKit,
Astro,
Remix,
Vite,
PlainNode,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum CoverageSetupPackageManager {
Npm,
Pnpm,
Yarn,
Bun,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum CoverageSetupRuntimeTarget {
Node,
Browser,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CoverageSetupMember {
pub name: String,
pub path: String,
pub framework_detected: CoverageSetupFramework,
pub package_manager: Option<CoverageSetupPackageManager>,
pub runtime_targets: Vec<CoverageSetupRuntimeTarget>,
pub files_to_edit: Vec<CoverageSetupFileToEdit>,
pub snippets: Vec<CoverageSetupSnippet>,
pub dockerfile_snippet: Option<String>,
pub warnings: Vec<String>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CoverageSetupFileToEdit {
pub path: String,
pub reason: String,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CoverageSetupSnippet {
pub label: String,
pub path: String,
pub content: String,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "schema", schemars(title = "fallow audit --format json"))]
#[allow(
dead_code,
reason = "schema-source-of-truth: audit.rs still builds the wire via serde_json::json!; this struct locks the schema shape via the drift gate. Migration is a follow-up to issue #384 items 3a/3b/3c."
)]
pub struct AuditOutput {
pub schema_version: SchemaVersion,
pub version: ToolVersion,
pub command: AuditCommand,
pub verdict: AuditVerdict,
pub changed_files_count: u32,
pub base_ref: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub head_sha: Option<String>,
pub elapsed_ms: ElapsedMs,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub base_snapshot_skipped: Option<bool>,
pub summary: AuditSummary,
pub attribution: AuditAttribution,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub dead_code: Option<CheckOutput>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub duplication: Option<DupesReportPayload>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub complexity: Option<HealthReport>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
#[allow(dead_code, reason = "schema-source-of-truth: see `AuditOutput`.")]
pub enum AuditCommand {
Audit,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(
feature = "schema",
schemars(title = "fallow --format json (bare, combined)")
)]
pub struct CombinedOutput {
pub schema_version: SchemaVersion,
pub version: ToolVersion,
pub elapsed_ms: ElapsedMs,
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
pub meta: Option<CombinedMeta>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub check: Option<CheckOutput>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub dupes: Option<DupesReportPayload>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub health: Option<HealthReport>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CombinedMeta {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub check: Option<Meta>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub dupes: Option<Meta>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub health: Option<Meta>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum CoverageAnalyzeSchemaVersion {
#[serde(rename = "1")]
V1,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(
feature = "schema",
schemars(title = "fallow coverage analyze --format json")
)]
pub struct CoverageAnalyzeOutput {
pub schema_version: CoverageAnalyzeSchemaVersion,
pub version: ToolVersion,
pub elapsed_ms: ElapsedMs,
pub runtime_coverage: RuntimeCoverageReport,
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
pub meta: Option<Meta>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "schema", schemars(title = "fallow dupes --format json"))]
pub struct DupesOutput {
pub schema_version: SchemaVersion,
pub version: ToolVersion,
pub elapsed_ms: ElapsedMs,
#[serde(flatten)]
pub report: DupesReportPayload,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub grouped_by: Option<GroupByMode>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub total_issues: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub groups: Option<Vec<DuplicationGroup>>,
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
pub meta: Option<Meta>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub workspace_diagnostics: Vec<fallow_config::WorkspaceDiagnostic>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "schema", schemars(title = "fallow dead-code --format json"))]
pub struct CheckOutput {
pub schema_version: SchemaVersion,
pub version: ToolVersion,
pub elapsed_ms: ElapsedMs,
pub total_issues: usize,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub entry_points: Option<EntryPoints>,
pub summary: CheckSummary,
#[serde(flatten)]
pub results: AnalysisResults,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub baseline_deltas: Option<BaselineDeltas>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub baseline: Option<BaselineMatch>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub regression: Option<RegressionResult>,
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
pub meta: Option<Meta>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub workspace_diagnostics: Vec<fallow_config::WorkspaceDiagnostic>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(
feature = "schema",
schemars(
title = "fallow dead-code --group-by <owner|directory|package|section> --format json"
)
)]
pub struct CheckGroupedOutput {
pub schema_version: SchemaVersion,
pub version: ToolVersion,
pub elapsed_ms: ElapsedMs,
pub grouped_by: GroupByMode,
pub total_issues: usize,
pub groups: Vec<CheckGroupedEntry>,
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
pub meta: Option<Meta>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CheckGroupedEntry {
pub key: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub owners: Option<Vec<String>>,
pub total_issues: usize,
#[serde(flatten)]
pub results: AnalysisResults,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "schema", schemars(title = "fallow health --format json"))]
pub struct HealthOutput {
pub schema_version: SchemaVersion,
pub version: ToolVersion,
pub elapsed_ms: ElapsedMs,
#[serde(flatten)]
pub report: HealthReport,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub grouped_by: Option<GroupByMode>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub groups: Option<Vec<HealthGroup>>,
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
pub meta: Option<Meta>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub workspace_diagnostics: Vec<fallow_config::WorkspaceDiagnostic>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(
feature = "schema",
schemars(title = "fallow explain <issue-type> --format json")
)]
#[serde(deny_unknown_fields)]
pub struct ExplainOutput {
pub id: String,
pub name: String,
pub summary: String,
pub rationale: String,
pub example: String,
pub how_to_fix: String,
pub docs: String,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(
feature = "schema",
schemars(title = "fallow --format codeclimate / gitlab-codequality")
)]
#[serde(transparent)]
#[allow(
dead_code,
reason = "schema-source-of-truth wrapper: runtime emits a `Vec<CodeClimateIssue>` directly via `codeclimate::issues_to_value`; this newtype exists so `schemars` can title and document the bare-array shape for the drift gate."
)]
pub struct CodeClimateOutput(pub Vec<CodeClimateIssue>);
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CodeClimateIssue {
#[serde(rename = "type")]
pub kind: CodeClimateIssueKind,
pub check_name: String,
pub description: String,
pub categories: Vec<String>,
pub severity: CodeClimateSeverity,
pub fingerprint: String,
pub location: CodeClimateLocation,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum CodeClimateIssueKind {
Issue,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum CodeClimateSeverity {
#[allow(
dead_code,
reason = "schema-source-of-truth: documents the full CodeClimate severity spec; runtime never produces this variant today, but the schema needs it so consumers can validate against either fallow output or a third-party CodeClimate emitter without spec divergence."
)]
Info,
Minor,
Major,
Critical,
#[allow(
dead_code,
reason = "schema-source-of-truth: documents the full CodeClimate severity spec; runtime never produces this variant today, but the schema needs it so consumers can validate against either fallow output or a third-party CodeClimate emitter without spec divergence."
)]
Blocker,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CodeClimateLocation {
pub path: String,
pub lines: CodeClimateLines,
}
#[derive(Debug, Clone, Copy, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CodeClimateLines {
pub begin: u32,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(
feature = "schema",
schemars(title = "fallow --format review-github / review-gitlab")
)]
pub struct ReviewEnvelopeOutput {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub event: Option<ReviewEnvelopeEvent>,
pub body: String,
#[serde(default = "ReviewEnvelopeSummary::empty_default")]
pub summary: ReviewEnvelopeSummary,
pub comments: Vec<ReviewComment>,
#[serde(default = "default_marker_regex")]
pub marker_regex: String,
#[serde(default = "default_marker_regex_flags")]
pub marker_regex_flags: String,
pub meta: ReviewEnvelopeMeta,
}
#[must_use]
pub fn default_marker_regex() -> String {
MARKER_REGEX_V2.to_owned()
}
#[must_use]
pub fn default_marker_regex_flags() -> String {
MARKER_REGEX_FLAGS_V2.to_owned()
}
pub const MARKER_REGEX_V2: &str =
r"^<!-- fallow-fingerprint:v2: ((?:[a-z]+:)?[0-9a-f]{16}) -->\s*$";
pub const MARKER_REGEX_FLAGS_V2: &str = "m";
#[derive(Debug, Clone, Serialize, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ReviewEnvelopeSummary {
pub body: String,
pub fingerprint: String,
}
impl ReviewEnvelopeSummary {
#[must_use]
#[allow(
dead_code,
reason = "referenced via serde default = \"...\" attr; no direct callsite until Deserialize is derived"
)]
pub fn empty_default() -> Self {
Self::default()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum ReviewEnvelopeEvent {
#[serde(rename = "COMMENT")]
Comment,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(untagged)]
pub enum ReviewComment {
GitHub(GitHubReviewComment),
GitLab(GitLabReviewComment),
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct GitHubReviewComment {
pub path: String,
pub line: u32,
pub side: GitHubReviewSide,
pub body: String,
pub fingerprint: String,
#[serde(default, skip_serializing_if = "is_false")]
pub truncated: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum GitHubReviewSide {
#[serde(rename = "RIGHT")]
Right,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct GitLabReviewComment {
pub body: String,
pub position: GitLabReviewPosition,
pub fingerprint: String,
#[serde(default, skip_serializing_if = "is_false")]
pub truncated: bool,
}
#[must_use]
#[allow(
clippy::trivially_copy_pass_by_ref,
reason = "serde's skip_serializing_if requires fn(&T) -> bool"
)]
pub fn is_false(value: &bool) -> bool {
!*value
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct GitLabReviewPosition {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub base_sha: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub start_sha: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub head_sha: Option<String>,
pub position_type: GitLabReviewPositionType,
pub old_path: String,
pub new_path: String,
pub new_line: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum GitLabReviewPositionType {
Text,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ReviewEnvelopeMeta {
pub schema: ReviewEnvelopeSchema,
pub provider: ReviewProvider,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub check_conclusion: Option<ReviewCheckConclusion>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum ReviewEnvelopeSchema {
#[serde(rename = "fallow-review-envelope/v1")]
#[allow(
dead_code,
reason = "kept for forward-compat with v1 historical inputs once Deserialize is derived"
)]
V1,
#[serde(rename = "fallow-review-envelope/v2")]
V2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum ReviewProvider {
Github,
Gitlab,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum ReviewCheckConclusion {
Success,
Neutral,
Failure,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(
feature = "schema",
schemars(title = "fallow ci reconcile-review --format json")
)]
pub struct ReviewReconcileOutput {
pub schema: ReviewReconcileSchema,
pub provider: ReviewProvider,
pub target: Option<String>,
pub dry_run: bool,
pub comments: u32,
pub current_fingerprints: u32,
pub existing_fingerprints: u32,
pub new_fingerprints: u32,
pub stale_fingerprints: u32,
pub new: Vec<String>,
pub stale: Vec<String>,
pub provider_warning: Option<String>,
pub resolution_comments_posted: u32,
pub threads_resolved: u32,
pub apply_errors: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum ReviewReconcileSchema {
#[serde(rename = "fallow-review-reconcile/v1")]
V1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum GroupByMode {
Owner,
Directory,
Package,
Section,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(
feature = "schema",
schemars(title = "fallow list --boundaries --format json")
)]
#[allow(
dead_code,
reason = "schema-source-of-truth: list.rs still builds the wire via serde_json::json!; this struct and its sub-types lock the schema shape via the drift gate. Migration is a follow-up to issue #384 items 3a/3b/3c."
)]
pub struct ListBoundariesOutput {
pub boundaries: BoundariesListing,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[allow(
dead_code,
reason = "schema-source-of-truth: see `ListBoundariesOutput`."
)]
pub struct BoundariesListing {
pub configured: bool,
pub zone_count: usize,
pub zones: Vec<BoundariesListZone>,
pub rule_count: usize,
pub rules: Vec<BoundariesListRule>,
pub logical_group_count: usize,
pub logical_groups: Vec<BoundariesListLogicalGroup>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[allow(
dead_code,
reason = "schema-source-of-truth: see `ListBoundariesOutput`."
)]
pub struct BoundariesListZone {
pub name: String,
pub patterns: Vec<String>,
pub file_count: usize,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[allow(
dead_code,
reason = "schema-source-of-truth: see `ListBoundariesOutput`."
)]
pub struct BoundariesListRule {
pub from: String,
pub allow: Vec<String>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[allow(
dead_code,
reason = "schema-source-of-truth: see `ListBoundariesOutput`."
)]
pub struct BoundariesListLogicalGroup {
pub name: String,
pub children: Vec<String>,
pub auto_discover: Vec<String>,
pub status: fallow_config::LogicalGroupStatus,
pub source_zone_index: usize,
pub file_count: usize,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub authored_rule: Option<fallow_config::AuthoredRule>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fallback_zone: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub merged_from: Option<Vec<usize>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub original_zone_root: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub child_source_indices: Vec<usize>,
}
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(
feature = "schema",
schemars(title = "fallow --format json (typed root)")
)]
#[serde(untagged)]
#[allow(
dead_code,
reason = "consumed at schema-emit time only; runtime code uses the per-variant envelope structs directly"
)]
pub enum FallowOutput {
Audit(AuditOutput),
Explain(ExplainOutput),
ReviewEnvelope(ReviewEnvelopeOutput),
ReviewReconcile(ReviewReconcileOutput),
CoverageSetup(CoverageSetupOutput),
CoverageAnalyze(CoverageAnalyzeOutput),
ListBoundaries(ListBoundariesOutput),
Health(HealthOutput),
Dupes(DupesOutput),
CheckGrouped(CheckGroupedOutput),
Check(CheckOutput),
Combined(CombinedOutput),
}