stemedb/applications/aphoria/src/cli.rs
jordan b3e8a9a058 feat: Multi-application expansion with chaos testing and community UI
Major additions:
- Community Next.js app (port 18187) for browsing claims with API docs
- stemedb-chaos crate: Fault injection, chaos testing, CRDT properties
- Latent ingestion system: Reddit/FDA ingesters with ADK-Go agents
- Disputed claims handling: Manual review workflows and validation
- Aphoria security scanner: New extractors (SQL injection, command
  injection, weak crypto, TLS version), policy-based ignores, UAT reports
- Docker infrastructure: Dockerfile, docker-compose.yml for full stack
- VulnBank demo: Intentionally vulnerable multi-language test corpus

SDK & API enhancements:
- Source registry handlers for tracking data provenance
- Metrics endpoint
- Skeptic filtering improvements

Code quality:
- Split 14 large files (>500 lines) into focused modules
- All files now under 500-line limit per project guidelines

Documentation:
- Chaos testing guide, circuit breakers, observability docs
- Phase 7 UAT documentation updates
- Martin Kleppmann technical writer agent

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 01:24:14 -07:00

171 lines
4.3 KiB
Rust

//! CLI argument definitions for Aphoria
use std::path::PathBuf;
use clap::{Parser, Subcommand};
/// A code-level truth linter powered by Episteme.
///
/// Aphoria scans a codebase, extracts the decisions embedded in config and code,
/// and checks them against authoritative sources. It finds the places where what
/// your code *does* contradicts what the specs *say*.
#[derive(Parser)]
#[command(name = "aphoria")]
#[command(version, about, long_about = None)]
pub struct Cli {
/// Path to aphoria.toml configuration file
#[arg(short, long, global = true)]
pub config: Option<PathBuf>,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
/// Scan a project for epistemic drift
Scan {
/// Path to the project root to scan
#[arg(default_value = ".")]
path: PathBuf,
/// Output format: table, json, sarif, markdown
#[arg(short, long, default_value = "table")]
format: String,
/// Exit with non-zero code if conflicts found
#[arg(long)]
exit_code: bool,
/// Use stricter thresholds (FLAG at 0.3, BLOCK at 0.5)
#[arg(long)]
strict: bool,
/// Persist claims to Episteme storage (enables diff/baseline features).
/// Without this flag, scans are ephemeral and fast.
#[arg(long)]
persist: bool,
/// Enable debug output showing conflict resolution traces.
/// Shows why each conflict was raised, including authority matching.
#[arg(long)]
debug: bool,
},
/// Acknowledge a conflict (mark as intentional)
Ack {
/// The concept path to acknowledge
concept_path: String,
/// Reason for acknowledgment
#[arg(short, long)]
reason: String,
},
/// Set the current scan as the baseline
Baseline,
/// Show changes since last baseline
Diff,
/// Show current scan status
Status,
/// Initialize Aphoria with authoritative corpus
Init,
/// Manage the authoritative corpus
Corpus {
#[command(subcommand)]
command: CorpusCommands,
},
/// Manage the research agent for filling corpus gaps
Research {
#[command(subcommand)]
command: ResearchCommands,
},
/// Manage federated policies (Trust Packs)
Policy {
#[command(subcommand)]
command: PolicyCommands,
},
}
#[derive(Subcommand)]
pub enum CorpusCommands {
/// Build the authoritative corpus from configured sources
Build {
/// Only include specific sources (comma-separated: rfc,owasp,vendor,hardcoded)
#[arg(long)]
only: Option<String>,
/// Run in offline mode (skip sources requiring network)
#[arg(long)]
offline: bool,
/// Clear cache before building
#[arg(long)]
clear_cache: bool,
},
/// List available corpus sources
List,
}
#[derive(Subcommand)]
pub enum ResearchCommands {
/// Run the research agent to fill corpus gaps
Run {
/// Minimum projects that must report a gap before researching (default: 3)
#[arg(short, long, default_value = "3")]
threshold: u32,
/// Use strict quality validation
#[arg(long)]
strict: bool,
/// Prune old gaps before researching
#[arg(long)]
prune: bool,
/// Maximum age of gaps to consider in days (default: 90)
#[arg(long, default_value = "90")]
max_age: u64,
},
/// Show research agent status and gap statistics
Status,
/// List gaps eligible for research
Gaps {
/// Minimum projects that must report a gap (default: 1)
#[arg(short, long, default_value = "1")]
threshold: u32,
/// Show only gaps ready for research (seen in 3+ projects)
#[arg(long)]
ready: bool,
},
}
#[derive(Subcommand)]
pub enum PolicyCommands {
/// Export acknowledged conflicts and manual aliases as a Trust Pack
Export {
/// Name of the policy pack
#[arg(long)]
name: String,
/// Output path for the pack file
#[arg(short, long)]
output: PathBuf,
},
/// Import a Trust Pack into the local Episteme
Import {
/// Path to the .pack file
file: PathBuf,
},
}