# Chio code-agent default policy (Phase 4.1 / 4.2)
#
# Zero-config policy for coding agents (Claude Code, Cursor, MCP clients).
# Fail-closed: anything not explicitly allowed is denied.
#
# This YAML is the single source of truth for both:
#   * the Python package `chio_code_agent` (loaded at import time)
#   * the Rust `chio-cli` `--preset code-agent` flag (embedded with
#     `include_str!`).
#
# Keep the two copies byte-identical (tested via chio-cli/tests/preset_parity.rs).

kernel:
  max_capability_ttl: 3600
  delegation_depth_limit: 3

guards:
  # Block the filesystem minefield: secrets, VCS internals, shell rc files.
  forbidden_path:
    enabled: true
    additional_patterns:
      - "**/.env"
      - "**/.env.*"
      - "**/.git/**"
      - "**/.ssh/**"
      - "**/.aws/credentials"
      - "**/.aws/config"
      - "**/.netrc"
      - "**/.npmrc"
      - "**/.pypirc"
      - "**/.gnupg/**"
      - "**/id_rsa"
      - "**/id_ed25519"
      - "**/*.pem"
      - "**/*.key"

  # Restrict shell commands: require explicit allow for anything destructive.
  shell_command:
    enabled: true
    forbidden_patterns:
      - "(?i)rm\\s+-rf\\s+/"
      - "(?i)rm\\s+-rf\\s+~"
      - "(?i)rm\\s+-rf\\s+\\$HOME"
      - "(?i)chmod\\s+777"
      - "(?i)curl\\s+[^|]+\\|\\s*(sh|bash|zsh|fish)"
      - "(?i)wget\\s+[^|]+\\|\\s*(sh|bash|zsh|fish)"
      # `git push --force` and `-f` stay blocked (destructive), but
      # `--force-with-lease` is the standard-safe rebased-feature-branch
      # workflow and MUST be allowed. Match `--force` only when followed
      # by whitespace or end-of-string, which naturally excludes
      # `--force-with-lease` without relying on negative lookahead (the
      # `regex` crate does not support `(?!...)`).
      - "(?i)git\\s+push\\s+.*--force(\\s|$)"
      - "(?i)git\\s+push\\s+.*-f(\\s|$)"
      - "(?i)git\\s+reset\\s+--hard\\s+origin"
      - "(?i)sudo\\s+"
      - "(?i)eval\\s*\\("
      - "(?i):\\(\\)\\s*\\{.*\\};:"
      - "(?i)mkfs\\."
      - "(?i)dd\\s+if=.*of=/dev/"

  # Block obvious secret leaks in the patch surface.
  secret_patterns:
    enabled: true

  # Keep patch sizes sane so agents cannot accidentally rewrite the world.
  patch_integrity:
    enabled: true

capabilities:
  default:
    tools:
      # File reads are allowed. The forbidden_path guard above filters
      # secrets, .git, .ssh, and friends out of the allowed read surface.
      - server: "fs"
        tool: "read_file"
        operations: [invoke]
        ttl: 3600
      - server: "fs"
        tool: "list_directory"
        operations: [invoke]
        ttl: 3600
      - server: "fs"
        tool: "search_files"
        operations: [invoke]
        ttl: 3600

      # File writes are allowed -- guards filter forbidden paths.
      - server: "fs"
        tool: "write_file"
        operations: [invoke]
        ttl: 3600
      - server: "fs"
        tool: "edit_file"
        operations: [invoke]
        ttl: 3600
      - server: "fs"
        tool: "create_directory"
        operations: [invoke]
        ttl: 3600

      # Shell: restricted by the shell_command guard. Destructive commands
      # are denied; approval-required commands surface a verdict that the
      # host can route to an approval prompt.
      - server: "shell"
        tool: "run_command"
        operations: [invoke]
        ttl: 600

      # Git: safe read ops. `git push` / force-push are blocked by the
      # shell_command forbidden_patterns above.
      - server: "git"
        tool: "status"
        operations: [invoke]
        ttl: 3600
      - server: "git"
        tool: "diff"
        operations: [invoke]
        ttl: 3600
      - server: "git"
        tool: "log"
        operations: [invoke]
        ttl: 3600
      - server: "git"
        tool: "add"
        operations: [invoke]
        ttl: 3600
      - server: "git"
        tool: "commit"
        operations: [invoke]
        ttl: 3600

# --- code-agent metadata (ignored by the Rust policy parser, consumed only by
# the Python SDK for local pre-flight checks; kept under a clearly-scoped key
# so `deny_unknown_fields` doesn't fire) ---
# (No top-level extra keys are allowed by the Rust parser, so this comment
# block is purely informational.)
