{
  "$schema": "https://stravica.dev/schemas/coordinator-allowlist.v1.json",
  "version": 1,
  "_comment": "Core three-tier allowlist for pa-coordinator-hook. Tier 1 tools never invoke the hook (see the settings.json matcher in packages/cli/docs/coordinator-hook.md) so they are not enumerated here for enforcement purposes — the tier1 array below is documentation only. Per-PA extensions belong in an overlay file (~/.claude/coordinator-overlay.json or <workspace>/.claude/coordinator-overlay.json), NOT in this file — this file ships inside the published package and is overwritten on every install/upgrade.",

  "tier1": [
    "Agent", "TaskStop", "SendMessage", "Workflow", "TaskCreate", "TaskList",
    "TaskGet", "TaskOutput", "TaskUpdate", "Monitor", "ScheduleWakeup",
    "AskUserQuestion", "Skill", "ToolSearch", "EnterPlanMode", "ExitPlanMode"
  ],

  "tier2": {
    "Bash": {
      "allowPatterns": [
        "^pa\\s",
        "^pnpm exec pa\\s",
        "^desk\\s",
        "^claude-relay\\s",
        "^node\\s+\\S*claude-relay\\S*\\s+",
        "^git status(\\s|$)",
        "^git log(\\s|$)",
        "^git diff --stat(\\s|$)",
        "^git branch --show-current(\\s|$)",
        "^git branch(\\s|$)",
        "^git remote -v(\\s|$)",
        "^gh pr view(\\s|$)",
        "^gh pr list(\\s|$)",
        "^gh pr merge(\\s|$)",
        "^gh pr close(\\s|$)",
        "^gh api\\s+(?!.*(-X|--method)[=\\s]*(POST|PUT|PATCH|DELETE|HEAD|post|put|patch|delete|head)\\b)",
        "^ls(\\s|$)",
        "^pwd(\\s|$)",
        "^hostname(\\s|$)",
        "^date(\\s|$)",
        "^whoami(\\s|$)",
        "^which\\s",
        "^echo\\s"
      ]
    },
    "Read": {
      "_comment": "`<self>` is substituted at runtime: the resolved paName when known (PA_SELF_AGENT env var, else operator/config/preferences.json#paName), else `[^/]+` — the spec's documented fallback ('if unknown, allow any agents/*/ path').",
      "allowPathPatterns": [
        "^\\.session/",
        "^agents/<self>/",
        "^work/",
        "^projects/[^/]+/project\\.json$",
        "^projects/[^/]+/progress\\.md$",
        "(^|/)spawn-log\\.json$",
        "^\\.cache/"
      ],
      "allowAbsolutePathPatterns": [
        "^/private/tmp/",
        "^/tmp/"
      ],
      "blockPathPatterns": [
        "^operator/knowledge/"
      ]
    },
    "Write": {
      "allowPathPatterns": [
        "^agents/<self>/staging/",
        "^agents/<self>/spawn-log\\.json$",
        "^\\.session/",
        "^\\.cache/"
      ],
      "allowAbsolutePathPatterns": [
        "^/private/tmp/",
        "^/tmp/"
      ]
    }
  },

  "tier3": ["Edit", "NotebookEdit", "Grep", "Glob", "WebFetch", "WebSearch"],

  "hardDeny": {
    "_comment": "Checked before any allow pattern (core or overlay), for both Bash commands and Read/Write paths. Overlays cannot add, remove, or shadow entries here — see policy.mjs. Not a security sandbox (a determined caller can still smuggle a second command past a naive prefix regex — see bashChainGuard below for the mitigation), just a mechanical backstop against the most obviously destructive one-liners, the specific 'obviously-destructive gh verbs' the spec calls out, and reads/writes of credential material even if some overlay pattern would otherwise match it.",
    "bashPatterns": [
      "^\\s*claude(\\s+[^-\\s]|\\s*$)",
      "rm\\s+-rf\\b",
      "curl[^\\n]*\\|\\s*(sh|bash|zsh)\\b",
      "wget[^\\n]*\\|\\s*(sh|bash|zsh)\\b",
      "^git\\s+push\\b[^\\n]*--force",
      "^git\\s+reset\\s+--hard\\b",
      "^git\\s+clean\\s+-f",
      "^git\\s+branch\\s+-D\\b",
      "--no-verify\\b",
      "--no-gpg-sign\\b",
      "^gh\\s+repo\\s+delete\\b",
      "^gh\\s+(release|workflow|secret|auth)\\s+(delete|remove|logout)\\b",
      "^sudo\\b",
      "^dd\\s+if=",
      "\\bmkfs\\b",
      ">\\s*/dev/(sd|nvme|disk|rdisk)"
    ],
    "bashChainGuardPattern": "[;&|`<>\\n]|\\$\\(",
    "bashChainGuardNote": "Tier2 Bash commands containing a shell-chaining metacharacter (;, &&, ||, |, backtick, $(...), <, >) or an embedded newline are blocked outright even if the leading command (or leading line) matches an allow pattern — a prefix match on 'pa knowledge search foo && rm -rf ~' must not slip through, nor must 'pa knowledge search foo\\nsudo apt-get purge -y openssh-server' or a redirect like 'echo foo > ~/.ssh/authorized_keys'. False positives (e.g. a quoted '&&' inside a search string) are an accepted cost; the hook always suggests a dispatch alternative.",
    "claudeLaunchNote": "The leading `^\\s*claude(\\s+[^-\\s]|\\s*$)` entry denies raw agent-CLI launches from Bash: bare `claude`, `claude help foo`, `claude -p <...>`, `claude mcp list`, any `claude <word>` form that would start a full session that boots the project PA. Flag-only inspection forms (`claude --help`, `claude --version`, `claude --mcp-list`, `claude -v`, `claude -h`) pass through because the character after the space is `-`. A dispatch that genuinely needs its own child session goes through pa-worker-launcher, which carries a signed PA_WORKER_GRANT; the pa-operator-attendance PreToolUse hook enforces the same deny with the launcher-grant exemption.",
    "pathPatterns": [
      "\\.vault/",
      "secrets\\.enc\\.json$",
      "\\.ssh/",
      "\\.aws/",
      "(^|/)\\.env$"
    ]
  },

  "messages": {
    "Bash": "Bash command not on the coordinator allowlist.",
    "Read": "Read path not on the coordinator allowlist.",
    "Write": "Write path not on the coordinator allowlist — any durable file change goes through a dispatch.",
    "Edit": "Dispatch tool-developer or writer for any durable file change — main thread is coordinator-mode.",
    "NotebookEdit": "Dispatch tool-developer or writer for any durable file change — main thread is coordinator-mode.",
    "Grep": "Dispatch Explore for search — main thread is coordinator-mode.",
    "Glob": "Dispatch Explore for file discovery — main thread is coordinator-mode.",
    "WebFetch": "Dispatch `/research` (or a worker) for web work — main thread is coordinator-mode.",
    "WebSearch": "Dispatch `/research` (or a worker) for web work — main thread is coordinator-mode.",
    "operator/knowledge/**": "Use `pa knowledge` (related/search/domain/orphans/path) retrieval verbs — a direct Read bypasses the knowledge graph.",
    "hardDeny": "This command/path matches a hard-deny pattern that no allowlist or overlay can override."
  }
}
