Problem
`nvisy-cli` today is exclusively an HTTP server entry point (`crates/nvisy-cli/src/main.rs`). There is no way to invoke `Engine::run` from the terminal for one-off redaction, scripting, local testing, or CI.
What's needed
A `run` subcommand on the CLI:
```
nvisy run --config Nvisy.toml --policy --input --output [--dry-run]
```
Behavior:
- Load `Nvisy.toml` (existing config loader)
- Build an `Engine` (existing path)
- Construct an `EngineInput` with: the policy ref(s), one `ImportFile` from `--input`, one `ExportFile` pointing at `--output`, sensible defaults for the phase configs
- Call `engine.run(input)`
- Print a summary (entities detected, redactions applied, validation result, exit code reflecting success/leak/error)
Design notes
- Reuse whatever phase-config defaults the HTTP `/runs` POST handler uses — don't reinvent them
- Stream stdout/stderr in a structured way (text by default, `--json` for machine-readable)
- The serve mode stays the default when no subcommand is given (backwards compatible)
- `--dry-run` maps to `EngineInput.dry_run = true` (skips redaction and export, returns audit only)
Why
References
- `crates/nvisy-cli/src/main.rs` — current server-only entry
- `crates/nvisy-engine/src/pipeline/default.rs` — `EngineInput` shape
- `crates/nvisy-server/` — HTTP handler for `POST /runs` (the equivalent code path to mirror)
Problem
`nvisy-cli` today is exclusively an HTTP server entry point (`crates/nvisy-cli/src/main.rs`). There is no way to invoke `Engine::run` from the terminal for one-off redaction, scripting, local testing, or CI.
What's needed
A `run` subcommand on the CLI:
```
nvisy run --config Nvisy.toml --policy --input --output [--dry-run]
```
Behavior:
Design notes
Why
References