Adds three new Aphoria CLI commands and supporting infrastructure for org-pattern alignment and claim tier advancement: - `aphoria claims search` — find claims by concept pattern, predicate, category, or max authority tier (works local and hosted mode) - `aphoria claims promote` — raise a claim to a higher authority tier by creating a superseding claim (append-only; original marked Deprecated) - `aphoria claims stats` — breakdown of claim counts by tier and status for a given concept_path + predicate pair New modules: - `convergence.rs` — pure engine comparing local scan observations to remote org claims, producing `ConvergenceSuggestion`s at read time - `types/convergence.rs` — `ConvergenceSuggestion` type with severity derived from the driving claim's authority tier - `types/promotion.rs` — `PromotionRequest` / `PromotionResult` types - `handlers/promote.rs` — promotion handler; validates tier ordering Remote client: adds `search_claims` and `claim_stats` methods to `RemoteClaimStore`, wiring hosted mode for all three new commands. API (`stemedb-api`): new `/v1/claims/search` and `/v1/claims/stats` endpoints with DTOs, plus report formatters (JSON/Markdown/SARIF/table) for search and stats output. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
526 lines
14 KiB
Rust
526 lines
14 KiB
Rust
//! CLI argument definitions for Aphoria
|
|
//!
|
|
//! This module is split into submodules to keep file sizes manageable:
|
|
//! - `extractors`: Extractor and shadow mode commands
|
|
//! - `governance`: Governance and Audit commands
|
|
//! - `lifecycle`: Lifecycle and Migration commands
|
|
//! - `patterns`: Pattern and Eval commands
|
|
//! - `scope`: Scope commands
|
|
|
|
mod claims;
|
|
mod extractors;
|
|
mod governance;
|
|
mod lifecycle;
|
|
mod patterns;
|
|
mod scope;
|
|
mod verify;
|
|
|
|
pub use claims::ClaimsCommands;
|
|
pub use extractors::ExtractorCommands;
|
|
pub use governance::{AuditCommands, GovernanceCommands};
|
|
pub use lifecycle::{LifecycleCommands, MigrationCommands};
|
|
pub use patterns::{EvalCommands, PatternCommands};
|
|
pub use scope::ScopeCommands;
|
|
pub use verify::VerifyCommands;
|
|
|
|
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)]
|
|
#[command(
|
|
after_help = "Examples:\n aphoria scan Scan current directory\n aphoria scan --format sarif Output for IDE integration\n aphoria scan --strict Stricter conflict thresholds\n aphoria verify run Check code against claims\n aphoria coverage Show claim density per module\n aphoria explain Onboarding summary"
|
|
)]
|
|
pub struct Cli {
|
|
/// Path to aphoria.toml configuration file
|
|
#[arg(short, long, global = true)]
|
|
pub config: Option<PathBuf>,
|
|
|
|
/// Enable verbose logging (shows internal tracing output)
|
|
#[arg(short, long, global = true)]
|
|
pub verbose: bool,
|
|
|
|
#[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.
|
|
#[arg(long)]
|
|
debug: bool,
|
|
|
|
/// Enable write-back of observations to local Episteme (requires --persist).
|
|
#[arg(long)]
|
|
sync: bool,
|
|
|
|
/// Scan only git-staged files (for pre-commit hooks).
|
|
#[arg(long)]
|
|
staged: bool,
|
|
|
|
/// Preview what would be shared with the community corpus.
|
|
#[arg(long)]
|
|
community_preview: bool,
|
|
|
|
/// Run performance benchmark with timing breakdown.
|
|
#[arg(long)]
|
|
benchmark: bool,
|
|
|
|
/// Show all extracted claims in the output
|
|
#[arg(long)]
|
|
show_claims: bool,
|
|
|
|
/// Show all observations with concept paths (for debugging extractor alignment)
|
|
#[arg(long)]
|
|
show_observations: bool,
|
|
|
|
/// Show detailed authority tier breakdown for conflicts
|
|
#[arg(long)]
|
|
explain_authority: bool,
|
|
|
|
/// Fetch remote org claims and show where your code diverges from org patterns.
|
|
/// Requires hosted mode configuration (aphoria.toml with [hosted] section).
|
|
#[arg(long)]
|
|
suggest_convergence: bool,
|
|
},
|
|
|
|
/// Manage acknowledgments (mark conflicts as intentional)
|
|
Ack {
|
|
#[command(subcommand)]
|
|
command: AckCommands,
|
|
},
|
|
|
|
/// Bless a code pattern as the authoritative standard
|
|
Bless {
|
|
/// The concept path to bless
|
|
concept_path: String,
|
|
|
|
/// The predicate (e.g., "enabled", "min_version")
|
|
#[arg(short, long)]
|
|
predicate: String,
|
|
|
|
/// The value (e.g., "true", "1.2")
|
|
#[arg(short = 'V', long)]
|
|
value: String,
|
|
|
|
/// Reason/description for this standard
|
|
#[arg(short, long)]
|
|
reason: String,
|
|
},
|
|
|
|
/// Record an intentional configuration change as a policy update
|
|
Update {
|
|
/// The concept path being updated
|
|
concept_path: String,
|
|
|
|
/// The new value for this concept
|
|
value: String,
|
|
|
|
/// Reason for the update
|
|
#[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,
|
|
},
|
|
|
|
/// Manage learned patterns and extractor promotion
|
|
Extractors {
|
|
#[command(subcommand)]
|
|
command: ExtractorCommands,
|
|
},
|
|
|
|
/// Evaluate LLM prompt effectiveness
|
|
Eval {
|
|
#[command(subcommand)]
|
|
command: EvalCommands,
|
|
},
|
|
|
|
/// Manage cross-project pattern learning
|
|
Patterns {
|
|
#[command(subcommand)]
|
|
command: PatternCommands,
|
|
},
|
|
|
|
/// Manage knowledge scopes and inheritance
|
|
Scope {
|
|
#[command(subcommand)]
|
|
command: ScopeCommands,
|
|
},
|
|
|
|
/// Manage knowledge lifecycle (deprecation, archival)
|
|
Lifecycle {
|
|
#[command(subcommand)]
|
|
command: LifecycleCommands,
|
|
},
|
|
|
|
/// Track migration progress for deprecated patterns
|
|
Migrations {
|
|
#[command(subcommand)]
|
|
command: MigrationCommands,
|
|
},
|
|
|
|
/// Manage approval workflows for pattern promotion
|
|
Governance {
|
|
#[command(subcommand)]
|
|
command: GovernanceCommands,
|
|
},
|
|
|
|
/// View and export audit trails for compliance
|
|
Audit {
|
|
#[command(subcommand)]
|
|
command: AuditCommands,
|
|
},
|
|
|
|
/// Manage human-authored claims (create, list, explain, update, supersede, deprecate)
|
|
Claims {
|
|
#[command(subcommand)]
|
|
command: ClaimsCommands,
|
|
},
|
|
|
|
/// Verify code against authored claims
|
|
Verify {
|
|
#[command(subcommand)]
|
|
command: VerifyCommands,
|
|
},
|
|
|
|
/// Show claim coverage metrics per module
|
|
Coverage {
|
|
/// Path to the project root
|
|
#[arg(default_value = ".")]
|
|
path: PathBuf,
|
|
|
|
/// Output format: table, json, markdown
|
|
#[arg(short, long, default_value = "table")]
|
|
format: String,
|
|
|
|
/// Sort modules by: name, density, unclaimed, observations
|
|
#[arg(long, default_value = "name")]
|
|
sort_by: String,
|
|
},
|
|
|
|
/// Generate a narrative explanation of this project's claims (onboarding)
|
|
Explain {
|
|
/// Path to the project root
|
|
#[arg(default_value = ".")]
|
|
path: PathBuf,
|
|
|
|
/// Write output to a file instead of stdout
|
|
#[arg(short, long)]
|
|
output: Option<PathBuf>,
|
|
|
|
/// Output format: markdown or json
|
|
#[arg(long, default_value = "markdown")]
|
|
format: String,
|
|
},
|
|
|
|
/// Generate enhanced documentation from claims + verification
|
|
Docs {
|
|
#[command(subcommand)]
|
|
command: DocsCommands,
|
|
},
|
|
|
|
/// Manage curated Trust Packs (install, list)
|
|
TrustPack {
|
|
#[command(subcommand)]
|
|
command: TrustPackCommands,
|
|
},
|
|
|
|
/// Install Claude Code skills for Aphoria workflows
|
|
InstallClaude {
|
|
/// Preview what would be installed without copying
|
|
#[arg(long)]
|
|
dry_run: bool,
|
|
|
|
/// Force reinstall even if files exist
|
|
#[arg(short, long)]
|
|
force: bool,
|
|
},
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
pub enum TrustPackCommands {
|
|
/// Install a curated Trust Pack by name
|
|
Install {
|
|
/// Pack name (e.g., "security-hardening", "rfc-compliance", "owasp-top10")
|
|
name: String,
|
|
|
|
/// Custom registry URL (overrides built-in registry)
|
|
#[arg(long)]
|
|
registry: Option<String>,
|
|
},
|
|
|
|
/// List available curated Trust Packs
|
|
List,
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
pub enum DocsCommands {
|
|
/// Generate a claims overview document
|
|
Generate {
|
|
/// Path to the project root
|
|
#[arg(default_value = ".")]
|
|
path: PathBuf,
|
|
|
|
/// Output path (default: stdout)
|
|
#[arg(short, long)]
|
|
output: Option<PathBuf>,
|
|
|
|
/// Output format: markdown or json
|
|
#[arg(long, default_value = "markdown")]
|
|
format: String,
|
|
},
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
pub enum AckCommands {
|
|
/// Create a new acknowledgment for a conflict
|
|
Add {
|
|
/// The concept path to acknowledge
|
|
concept_path: String,
|
|
|
|
/// Reason for acknowledgment
|
|
#[arg(short, long)]
|
|
reason: String,
|
|
|
|
/// Optional expiry for acknowledgment (e.g., "90d" or "2026-12-31")
|
|
#[arg(long, alias = "expires-at")]
|
|
expires: Option<String>,
|
|
},
|
|
|
|
/// Export acknowledgments to .aphoria/acks.toml for version control
|
|
Export {
|
|
/// Output path (default: .aphoria/acks.toml)
|
|
#[arg(short, long)]
|
|
output: Option<PathBuf>,
|
|
},
|
|
|
|
/// Import acknowledgments from .aphoria/acks.toml
|
|
Import {
|
|
/// Input path (default: .aphoria/acks.toml)
|
|
#[arg(short, long)]
|
|
input: Option<PathBuf>,
|
|
},
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
pub enum CorpusCommands {
|
|
/// Build the authoritative corpus from configured sources
|
|
Build {
|
|
/// Only include specific sources (comma-separated)
|
|
#[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,
|
|
|
|
/// Import patterns from external sources to bootstrap the corpus
|
|
Import {
|
|
#[command(subcommand)]
|
|
source: ImportSource,
|
|
},
|
|
|
|
/// Export the corpus as a signed Trust Pack
|
|
ExportPack {
|
|
/// Name for the exported pack
|
|
#[arg(long)]
|
|
name: String,
|
|
|
|
/// Output path for the .pack file
|
|
#[arg(short, long)]
|
|
output: PathBuf,
|
|
|
|
/// Only include specific corpus sources (comma-separated)
|
|
#[arg(long)]
|
|
only: Option<String>,
|
|
|
|
/// Run in offline mode (skip sources requiring network)
|
|
#[arg(long)]
|
|
offline: bool,
|
|
},
|
|
|
|
/// Create a new corpus item from structured data
|
|
Create {
|
|
/// Subject path (e.g., "ml/dependencies/basicsr/torchvision")
|
|
#[arg(long)]
|
|
subject: String,
|
|
|
|
/// Predicate (e.g., "incompatible_with", "requires", "recommends")
|
|
#[arg(long)]
|
|
predicate: String,
|
|
|
|
/// Value (string, number, or boolean)
|
|
#[arg(long)]
|
|
value: String,
|
|
|
|
/// Full explanation/context for this claim
|
|
#[arg(long)]
|
|
explanation: String,
|
|
|
|
/// Authority source (GitHub URL, paper citation, docs URL)
|
|
#[arg(long)]
|
|
authority: String,
|
|
|
|
/// Category (compatibility, performance, security, architecture)
|
|
#[arg(long)]
|
|
category: String,
|
|
|
|
/// Authority tier (0=regulatory, 1=clinical, 2=observational, 3=community)
|
|
#[arg(long)]
|
|
tier: u8,
|
|
},
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
pub enum ImportSource {
|
|
/// Import patterns from wiki markdown documentation
|
|
Wiki {
|
|
/// Path to wiki directory containing markdown files
|
|
path: PathBuf,
|
|
},
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
pub enum ResearchCommands {
|
|
/// Run the research agent to fill corpus gaps
|
|
Run {
|
|
/// Minimum projects that must report a gap before researching
|
|
#[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
|
|
#[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
|
|
#[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 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,
|
|
},
|
|
|
|
/// Re-sign a Trust Pack with a new key
|
|
Resign {
|
|
/// Path to the .pack file to re-sign
|
|
file: PathBuf,
|
|
|
|
/// Output path for the re-signed pack
|
|
#[arg(short, long)]
|
|
output: PathBuf,
|
|
|
|
/// Path to new signing key
|
|
#[arg(long)]
|
|
key: Option<PathBuf>,
|
|
|
|
/// Reason for re-signing (for audit trail)
|
|
#[arg(long)]
|
|
reason: Option<String>,
|
|
|
|
/// Preserve signature chain for audit trail
|
|
#[arg(long, default_value = "true")]
|
|
chain_signatures: bool,
|
|
},
|
|
}
|