Skip to content

feat(guard): make command allowances configurable - #286

Merged
slowdini merged 2 commits into
devfrom
feat/write-guard-real-dev
Aug 23, 2026
Merged

feat(guard): make command allowances configurable#286
slowdini merged 2 commits into
devfrom
feat/write-guard-real-dev

Conversation

@slowdini

Copy link
Copy Markdown
Owner

Closes #259.

Summary

This PR makes the following changes:

  • Moves development-command allowances out of hard-coded tool handling and into eval-authored guard policies.
  • Supports broad executable allowances, token-prefix command allowances, and composable packaged profiles.
  • Detects language and framework profiles only when an eval author has not supplied an explicit policy.
  • Freezes the expanded policy into dispatch artifacts and guard markers so live enforcement and post-run auditing agree.
  • Keeps destination, output, repository-routing, and remote Git containment checks non-overridable.

Strategy

The ticket identifies false positives from applying command-text heuristics to realistic development work. Making each common tool a special case would address the immediate examples, but it would also make eval-magic responsible for predicting every build system, package manager, and project-specific workflow an eval might need.

This change separates two concerns:

  1. Containment is fixed runner policy. Direct writes, redirects, tee targets, remote Git mutations, repository-routing escapes, and recognized package or build destinations are checked before any allowance. Relative and implicit destinations resolve from the tool invocation cwd. An eval cannot configure its way around this boundary.
  2. Expected development commands are eval policy. Eval authors can allow an executable basename with allow_tools, narrow token prefixes with allow_commands, or include packaged profiles. A claimed tool has unmatched subcommands denied, while commands outside the recognized development-command surface remain best-effort rather than turning the guard into an incomplete shell allowlist.

Configuration can be declared once at the top level or replaced per eval. Replacement is intentional: a narrow per-eval policy should not accidentally inherit broader config-level permissions. Even an empty per-eval object is meaningful and disables both the config default and automatic profile detection.

When no explicit guard block exists, eval-magic recursively detects and joins packaged profiles from the fully staged task tree. Packaged profiles cover Rust, JavaScript, Next.js, and Python. They live as TOML files under guard-profiles/ and are discovered by the build script, so additional languages or framework-specific defaults do not require editing a central Rust registry.

The effective policy is expanded before execution. The complete policy is recorded on each dispatch.json task and copied into the armed guard marker. detect-stray-writes reads that frozen task policy instead of redetecting the project later, keeping live denials and post-run evidence on the same decision path even if task files change during the eval.

Configuration examples

Allow every Cargo invocation for a Rust maintenance eval:

{
  "guard": {
    "allow_tools": ["cargo"]
  }
}

Allow only the lifecycle commands expected by a Next.js eval:

{
  "guard": {
    "allow_commands": [
      "npm run dev",
      "npm run build",
      "npm run start"
    ]
  }
}

With no explicit block, a task tree containing a Next.js frontend and Python backend composes language/javascript, framework/nextjs, and language/python automatically.

Verification

The following checks pass:

  • cargo fmt --check
  • cargo build
  • cargo test --quiet — 1,253 tests passed
  • cargo clippy --all-targets -- -D warnings
  • cargo package --allow-dirty
  • package archive inspection — all four TOML guard profiles are present
  • git diff --check origin/dev

Replace the built-in development-tool whitelist with eval-authored tool and command allowances plus composable packaged profiles. Auto-detect profiles only when no explicit guard policy is present.

Freeze the expanded policy into dispatch tasks and guard markers so live enforcement and stray-write auditing make the same decision, while keeping containment checks non-overridable.
@slowdini
slowdini merged commit 3347030 into dev Aug 23, 2026
7 checks passed
@slowdini
slowdini deleted the feat/write-guard-real-dev branch August 23, 2026 00:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Write-guard policy for real development work

1 participant