# === Signet-Eval Main CLI (src_main.rs) v1 ===
#  Dependencies: clap, std::path::PathBuf, std::env, std::fs, std::process, serde_yaml, serde_json, serde::Deserialize, rpassword, chrono, tokio::runtime::Runtime, hook, policy, vault, mcp_server, mcp_proxy
# Command-line interface for policy-enforced AI agent tool calls. Parses command-line arguments, routes to subcommands (eval, init, setup, status, store, rules, log, test, delete, reset-session, sign, unlock, validate, serve, proxy, preflight-status, preflight-override, pause, resume, disable, enable), and executes policy evaluation, vault management, and MCP server operations. Entry point for the signet-eval binary.

# Module invariants:
#   - Policy path default is ~/.signet/policy.yaml
#   - Vault metadata stored at ~/.signet/vault.meta (implicit from vault module)
#   - Policy HMAC signature stored at <policy_path>.hmac (implicit from vault::sign_policy)
#   - Pause state file at ~/.signet/pause_until (implicit from vault module)
#   - Disable state file at ~/.signet/disabled (implicit from vault module)
#   - Exit code 0 indicates success, 1 indicates error
#   - Passphrase minimum length is 8 characters
#   - Pause duration range is 1-60 minutes
#   - Default log limit is 20 entries
#   - Default pause duration is 10 minutes
#   - Policy version in Init command is 1
#   - Default action in Init command is Allow
#   - Self-protection rules are prepended to policy rules in Init command
#   - Vault is tier-3 encrypted (as per Store command)
#   - Policy integrity check (HMAC) is performed on Eval if vault exists
#   - Failed HMAC check falls back to safe defaults (policy::default_policy())
#   - MCP commands (Serve, Proxy) require 'mcp' feature flag

class Cli:
    """Main CLI argument parser for signet-eval. Contains optional subcommand and policy file path."""
    command: Option<Command> = None          # optional, Subcommand to execute. None defaults to Eval.
    policy_path: String                      # required, Path to policy file, default ~/.signet/policy.yaml

class Command(Enum):
    """All subcommands available in the signet-eval CLI."""
    Eval = "Eval"
    Init = "Init"
    Setup = "Setup"
    Status = "Status"
    Store { name: String, value: String } = "Store { name: String, value: String }"
    Rules = "Rules"
    Log { limit: u32 } = "Log { limit: u32 }"
    Test { json: String } = "Test { json: String }"
    Delete { name: String } = "Delete { name: String }"
    ResetSession = "ResetSession"
    Sign = "Sign"
    Unlock = "Unlock"
    Validate = "Validate"
    Serve = "Serve"
    Proxy = "Proxy"
    PreflightStatus = "PreflightStatus"
    PreflightOverride = "PreflightOverride"
    Pause { minutes: u32 } = "Pause { minutes: u32 }"
    Resume = "Resume"
    Disable = "Disable"
    Enable = "Enable"

class TestInput:
    """Deserialized JSON test input for Command::Test. Contains tool_name and optional parameters."""
    tool_name: String                        # required, Name of the tool being tested
    parameters: Option<serde_json::Value> = None # optional, Tool input parameters (aliased as tool_input)

def expand_home(
    path: str,
) -> PathBuf:
    """
    Expands tilde (~/) prefix in path strings to the HOME environment variable value. Falls back to the path as-is if HOME is not set or path does not start with ~/.

    Postconditions:
      - Returns PathBuf with ~/ replaced by $HOME if path starts with ~/ and HOME is set
      - Returns PathBuf from path as-is otherwise

    Side effects: reads environment variable HOME
    Idempotent: no
    """
    ...

def run() -> i32:
    """
    Main logic of signet-eval. Parses CLI arguments, expands policy path, and dispatches to subcommand handlers. Returns exit code (0 for success, 1 for errors).

    Preconditions:
      - Command-line arguments are parseable by clap::Parser

    Postconditions:
      - Returns 0 on successful execution
      - Returns 1 on error (vault locked, invalid input, file I/O failure, authentication failure, validation error, etc.)
      - Policy file may be created or modified (Init, Sign commands)
      - Vault may be created or modified (Setup, Store, Delete, ResetSession, Unlock, PreflightOverride commands)
      - Pause/disable state files may be created or deleted (Pause, Resume, Disable, Enable commands)
      - Outputs status/diagnostic information to stdout
      - Outputs errors/warnings to stderr

    Errors:
      - vault_locked_or_missing (exit_code_1): Vault required but not set up or locked (Status, Store, Log, Delete, ResetSession, Sign, PreflightStatus, PreflightOverride commands)
          stderr: Vault not set up or locked. Run: signet-eval setup
      - vault_already_exists (exit_code_1): Vault already exists when running Setup
          stderr: Vault already exists. Delete ~/.signet/vault.meta to reset.
      - passphrase_mismatch (exit_code_1): Passphrase and confirmation don't match during Setup
          stderr: Passphrases don't match.
      - passphrase_too_short (exit_code_1): Passphrase less than 8 characters during Setup
          stderr: Passphrase must be at least 8 characters.
      - policy_load_error (exit_code_1): Policy file cannot be loaded or parsed (Rules, Validate commands)
          stderr: Error: <error_message>
      - policy_write_error (exit_code_1): Policy file cannot be written during Init
          stderr: Error: <error_message>
      - invalid_json (exit_code_1): JSON input cannot be parsed during Test command
          stderr: Invalid JSON: <error_message>
      - credential_not_found (exit_code_1): Credential name not found during Delete command
          stderr: Credential '<name>' not found.
      - vault_setup_error (exit_code_1): Vault setup fails (Setup command)
          stderr: Error: <error_message>
      - policy_sign_error (exit_code_1): Policy signing fails (Sign command or auto-sign in Init)
          stderr: Error: <error_message> OR Warning: could not sign policy: <error_message>
      - vault_unlock_error (exit_code_1): Vault unlock fails due to incorrect passphrase or error (Unlock, PreflightOverride commands)
          stderr: Error: <error_message> OR Authentication failed: <error_message>
      - policy_validation_error (exit_code_1): Policy validation fails (Validate command)
          stderr: ERROR: <validation_error>
      - mcp_server_error (exit_code_1): MCP server/proxy fails to start or run (Serve, Proxy commands)
          stderr: MCP server error: <error_message> OR MCP proxy error: <error_message>
      - preflight_override_error (exit_code_1): Preflight override fails (PreflightOverride command)
          stderr: Error: <error_message>
      - pause_duration_invalid (exit_code_1): Pause duration not in range 1-60 minutes (Pause command)
          stderr: Pause duration must be 1-60 minutes.
      - already_paused (exit_code_1): Attempting to pause when already paused (Pause command)
          stderr: Already paused until timestamp <timestamp>.

    Side effects: Reads from stdin (Eval command), Writes to stdout (status, rules, log, test results, confirmations), Writes to stderr (warnings, errors), Reads policy file from disk, Writes policy file to disk (Init command), Writes policy HMAC signature to disk (Init with vault, Sign command), Reads vault metadata from ~/.signet/vault.meta, Writes vault metadata to ~/.signet/vault.meta (Setup, Store, Delete, ResetSession, Unlock, PreflightOverride commands), Reads pause state file from ~/.signet/pause_until, Writes pause state file to ~/.signet/pause_until (Pause command), Deletes pause state file (Resume command), Reads disable state file from ~/.signet/disabled, Writes disable state file to ~/.signet/disabled (Disable command), Deletes disable state file (Enable command), Prompts for passphrase via rpassword (Setup, Unlock, PreflightOverride commands), Spawns Tokio runtime and runs async MCP server/proxy (Serve, Proxy commands with mcp feature), Logs actions to vault ledger (Eval, Test commands), Verifies policy HMAC (Eval command with vault)
    Idempotent: no
    """
    ...

def main() -> !:
    """
    Entry point for the signet-eval binary. Calls run() and exits with its return code.

    Postconditions:
      - Process exits with code returned by run()

    Side effects: Calls run() which has extensive side effects (see run() documentation), Exits process with exit code
    Idempotent: no
    """
    ...

# ── REQUIRED EXPORTS ──────────────────────────────────
# Your implementation module MUST export ALL of these names
# with EXACTLY these spellings. Tests import them by name.
# __all__ = ['Cli', 'Command', 'TestInput', 'expand_home', 'run', 'exit_code_1', 'main']
