|
| 1 | +{ |
| 2 | + "schema_version": "operator.v0", |
| 3 | + "name": "rvl", |
| 4 | + "version": "0.4.0", |
| 5 | + "description": "Numeric change explainer — finds the smallest set of cell-level changes that account for the difference between two CSV files", |
| 6 | + "repository": "https://github.com/cmdrvl/rvl", |
| 7 | + "license": "MIT", |
| 8 | + "agent_guide": "https://github.com/cmdrvl/.github/blob/main/profile/AGENT_PROMPT.md", |
| 9 | + |
| 10 | + "invocation": { |
| 11 | + "binary": "rvl", |
| 12 | + "usage": [ |
| 13 | + "rvl <old.csv> <new.csv> [OPTIONS]", |
| 14 | + "rvl witness <query|last|count> [OPTIONS]" |
| 15 | + ], |
| 16 | + "output_mode": "report", |
| 17 | + "output_schema": "rvl.v0", |
| 18 | + "json_flag": "--json" |
| 19 | + }, |
| 20 | + |
| 21 | + "arguments": [ |
| 22 | + { "name": "old", "type": "file_path", "required": true, "position": 0, "description": "Old CSV file" }, |
| 23 | + { "name": "new", "type": "file_path", "required": true, "position": 1, "description": "New CSV file" } |
| 24 | + ], |
| 25 | + |
| 26 | + "options": [ |
| 27 | + { "name": "key", "flag": "--key", "type": "string", "description": "Align rows by this key column (otherwise align by row order)" }, |
| 28 | + { "name": "threshold", "flag": "--threshold", "type": "float", "default": 0.95, "description": "Coverage target: 0 < x <= 1" }, |
| 29 | + { "name": "tolerance", "flag": "--tolerance", "type": "float", "default": 1e-9, "description": "Per-cell noise floor: x >= 0" }, |
| 30 | + { "name": "delimiter", "flag": "--delimiter", "type": "string", "description": "Force CSV delimiter (comma/tab/semicolon/pipe/caret, 0xNN, or single ASCII byte)" }, |
| 31 | + { "name": "profile", "flag": "--profile", "type": "file_path", "description": "Use profile YAML at this path for key derivation and column scoping" }, |
| 32 | + { "name": "profile_id", "flag": "--profile-id", "type": "string", "description": "Resolve profile by ID from ~/.epistemic/profiles/*.yaml (or direct path)" }, |
| 33 | + { "name": "capsule_out", "flag": "--capsule-out", "type": "directory_path", "description": "Write deterministic repro capsule artifacts to this directory (default: disabled)" }, |
| 34 | + { "name": "json", "flag": "--json", "type": "flag", "description": "Emit JSON output (single object)" }, |
| 35 | + { "name": "no_witness", "flag": "--no-witness", "type": "flag", "description": "Suppress witness ledger recording" }, |
| 36 | + { "name": "describe", "flag": "--describe", "type": "flag", "description": "Print compiled operator.json and exit 0 without positional args" } |
| 37 | + ], |
| 38 | + |
| 39 | + "subcommands": [ |
| 40 | + { |
| 41 | + "name": "witness", |
| 42 | + "description": "Witness ledger query commands", |
| 43 | + "status": "available", |
| 44 | + "actions": [ |
| 45 | + { |
| 46 | + "name": "query", |
| 47 | + "usage": "rvl witness query [--tool <name>] [--since <iso8601>] [--until <iso8601>] [--outcome <REAL_CHANGE|NO_REAL_CHANGE|REFUSAL>] [--input-hash <substring>] [--limit <n>] [--json]" |
| 48 | + }, |
| 49 | + { |
| 50 | + "name": "last", |
| 51 | + "usage": "rvl witness last [--json]" |
| 52 | + }, |
| 53 | + { |
| 54 | + "name": "count", |
| 55 | + "usage": "rvl witness count [--tool <name>] [--since <iso8601>] [--until <iso8601>] [--outcome <REAL_CHANGE|NO_REAL_CHANGE|REFUSAL>] [--input-hash <substring>] [--json]" |
| 56 | + } |
| 57 | + ], |
| 58 | + "current_runtime_behavior": { |
| 59 | + "success_exit_code": 0, |
| 60 | + "no_match_exit_code": 1, |
| 61 | + "error_exit_code": 2, |
| 62 | + "ledger_path_resolution": [ |
| 63 | + "EPISTEMIC_WITNESS", |
| 64 | + "~/.epistemic/witness.jsonl" |
| 65 | + ] |
| 66 | + } |
| 67 | + } |
| 68 | + ], |
| 69 | + |
| 70 | + "exit_codes": { |
| 71 | + "0": { "meaning": "NO_REAL_CHANGE", "domain": "positive" }, |
| 72 | + "1": { "meaning": "REAL_CHANGE", "domain": "negative" }, |
| 73 | + "2": { "meaning": "REFUSAL / CLI error", "domain": "error" } |
| 74 | + }, |
| 75 | + |
| 76 | + "refusals": [ |
| 77 | + { "code": "E_IO", "message": "Cannot read input file", "action": "escalate" }, |
| 78 | + { "code": "E_ENCODING", "message": "Unsupported text encoding (UTF-16/32 BOM or NUL bytes)", "action": "escalate" }, |
| 79 | + { "code": "E_CSV_PARSE", "message": "CSV parse failure", "action": "escalate" }, |
| 80 | + { "code": "E_HEADERS", "message": "Invalid or duplicate headers", "action": "escalate" }, |
| 81 | + { "code": "E_NO_KEY", "message": "Key column missing from file", "action": "retry_with_flag", "flag": "--key" }, |
| 82 | + { "code": "E_KEY_EMPTY", "message": "Empty key value in row", "action": "escalate" }, |
| 83 | + { "code": "E_KEY_DUP", "message": "Duplicate key values (non-unique)", "action": "escalate" }, |
| 84 | + { "code": "E_KEY_MISMATCH", "message": "Key sets differ between files", "action": "escalate" }, |
| 85 | + { "code": "E_ROWCOUNT", "message": "Row count mismatch and no key provided", "action": "retry_with_flag", "flag": "--key" }, |
| 86 | + { "code": "E_NEED_KEY", "message": "Cannot deterministically align without a key", "action": "retry_with_flag", "flag": "--key" }, |
| 87 | + { "code": "E_DIALECT", "message": "Delimiter ambiguous or undetectable", "action": "retry_with_flag", "flag": "--delimiter" }, |
| 88 | + { "code": "E_AMBIGUOUS_PROFILE", "message": "Both --profile and --profile-id were provided", "action": "adjust_input" }, |
| 89 | + { "code": "E_PROFILE_NOT_FOUND", "message": "Profile could not be resolved from ID", "action": "escalate" }, |
| 90 | + { "code": "E_KEY_CONFLICT", "message": "--key flag conflicts with profile-defined key", "action": "adjust_input" }, |
| 91 | + { "code": "E_MIXED_TYPES", "message": "Mixed numeric and non-numeric values in column", "action": "escalate" }, |
| 92 | + { "code": "E_NO_NUMERIC", "message": "No numeric columns in common", "action": "escalate" }, |
| 93 | + { "code": "E_MISSINGNESS", "message": "Numeric-vs-missing mismatch", "action": "escalate" }, |
| 94 | + { "code": "E_DIFFUSE", "message": "Diffuse change below coverage threshold", "action": "retry_with_flag", "flag": "--threshold" } |
| 95 | + ], |
| 96 | + |
| 97 | + "capabilities": { |
| 98 | + "formats": ["csv"], |
| 99 | + "profile_aware": true, |
| 100 | + "streaming": false, |
| 101 | + "witness": { |
| 102 | + "ambient_recording": "enabled_by_default", |
| 103 | + "query_subcommands": "available", |
| 104 | + "no_witness_flag": "suppresses_recording" |
| 105 | + } |
| 106 | + }, |
| 107 | + |
| 108 | + "pipeline": { |
| 109 | + "upstream": ["shape", "profile"], |
| 110 | + "downstream": ["pack"] |
| 111 | + } |
| 112 | +} |
0 commit comments