Adds an optional `justification` parameter to the `prefix_rule()`
execpolicy DSL so policy authors can attach human-readable rationale to
a rule. That justification is propagated through parsing/matching and
can be surfaced to the model (or approval UI) when a command is blocked
or requires approval.
When a command is rejected (or gated behind approval) due to policy, a
generic message makes it hard for the model/user to understand what went
wrong and what to do instead. Allowing policy authors to supply a short
justification improves debuggability and helps guide the model toward
compliant alternatives.
Example:
```python
prefix_rule(
pattern = ["git", "push"],
decision = "forbidden",
justification = "pushing is blocked in this repo",
)
```
If Codex tried to run `git push origin main`, now the failure would
include:
```
`git push origin main` rejected: pushing is blocked in this repo
```
whereas previously, all it was told was:
```
execpolicy forbids this command
```
28 lines
846 B
Rust
28 lines
846 B
Rust
use starlark::Error as StarlarkError;
|
|
use thiserror::Error;
|
|
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum Error {
|
|
#[error("invalid decision: {0}")]
|
|
InvalidDecision(String),
|
|
#[error("invalid pattern element: {0}")]
|
|
InvalidPattern(String),
|
|
#[error("invalid example: {0}")]
|
|
InvalidExample(String),
|
|
#[error("invalid rule: {0}")]
|
|
InvalidRule(String),
|
|
#[error(
|
|
"expected every example to match at least one rule. rules: {rules:?}; unmatched examples: \
|
|
{examples:?}"
|
|
)]
|
|
ExampleDidNotMatch {
|
|
rules: Vec<String>,
|
|
examples: Vec<String>,
|
|
},
|
|
#[error("expected example to not match rule `{rule}`: {example}")]
|
|
ExampleDidMatch { rule: String, example: String },
|
|
#[error("starlark error: {0}")]
|
|
Starlark(StarlarkError),
|
|
}
|