Policies
AX engineering is about controlled capability, not maximum autonomy. Reads are broad, writes are narrow and reviewed, and the highest-impact actions belong to people. 2 of 8 roles may change a file.
12 of 19 capabilities are checked by an AX command. The quality executor checks run_tests; ax git, ax pr, ax ci and ax deploy check the delivery capabilities before touching git, GitHub, or a provider. The rest are declarations. Nothing here constrains a tool used outside AX: git or gh typed into a shell is unaffected, so this is a boundary only for work that goes through AX.
Delivery workflows
Git workflow
ax git: new working branch, exact files, non-forced push.
create_branchImplementedNew prefixed working branch; never the default or a reserved name.commit_worktreeImplementedNamed files only; secret paths and private-key content refused.push_working_branchImplementedOne explicit non-forced refspec to a non-mirror remote.direct_main_pushDeniedA default or reserved branch is refused at plan time.force_pushDeniedNo forced or lease-forced push can be constructed.
PR workflow
ax pr: one approval per repository, head, base, and commit. No merge.
github_readImplementedRepository metadata and open pull requests through gh.create_pull_requestRequires approvalApproval bound to repository, head, base, commit, title, and body.
CI inspection
ax ci: pending and absent CI are never reported as passed.
read_ciImplementedCheck runs and statuses for one exact commit.
Deployment
ax deploy: exact pushed commits to declared targets. Production denied.
preview_deployImplementedDeclared preview/development targets with an adapter.staging_deployRequires approvalApproval bound to target and commit; CI must have passed.production_deployDeniedEvery production target is refused before any adapter is consulted.
Capability matrix
| Capability | Backend Engineer | Database Reviewer | Frontend Engineer | Integration Reviewer | Investigator | Planner | QA Reviewer | Security Reviewer |
|---|---|---|---|---|---|---|---|---|
read_codeRead repository code | Backend Engineer holds read_code | Database Reviewer holds read_code | Frontend Engineer holds read_code | Integration Reviewer holds read_code | Investigator holds read_code | Planner holds read_code | QA Reviewer holds read_code | Security Reviewer holds read_code |
read_docsRead documentation and context | Backend Engineer holds read_docs | Database Reviewer holds read_docs | Frontend Engineer holds read_docs | Integration Reviewer holds read_docs | Investigator holds read_docs | Planner holds read_docs | QA Reviewer holds read_docs | Security Reviewer holds read_docs |
github_readRead GitHub metadata | Backend Engineer holds github_read | Database Reviewer holds github_read | Frontend Engineer holds github_read | Integration Reviewer holds github_read | Investigator holds github_read | Planner holds github_read | QA Reviewer holds github_read | Security Reviewer holds github_read |
database_metadataRead database metadata | Backend Engineer holds database_metadata | Database Reviewer holds database_metadata | Frontend Engineer does not hold database_metadata | Integration Reviewer does not hold database_metadata | Investigator holds database_metadata | Planner does not hold database_metadata | QA Reviewer does not hold database_metadata | Security Reviewer does not hold database_metadata |
run_testsRun declared quality commands | Backend Engineer holds run_tests | Database Reviewer does not hold run_tests | Frontend Engineer holds run_tests | Integration Reviewer does not hold run_tests | Investigator holds run_tests | Planner does not hold run_tests | QA Reviewer holds run_tests | Security Reviewer does not hold run_tests |
edit_worktreeEdit an isolated worktree | Backend Engineer holds edit_worktree | Database Reviewer does not hold edit_worktree | Frontend Engineer holds edit_worktree | Integration Reviewer does not hold edit_worktree | Investigator does not hold edit_worktree | Planner does not hold edit_worktree | QA Reviewer does not hold edit_worktree | Security Reviewer does not hold edit_worktree |
create_branchCreate a working branch | Backend Engineer holds create_branch | Database Reviewer does not hold create_branch | Frontend Engineer holds create_branch | Integration Reviewer does not hold create_branch | Investigator does not hold create_branch | Planner does not hold create_branch | QA Reviewer does not hold create_branch | Security Reviewer does not hold create_branch |
commit_worktreeCommit selected files | Backend Engineer holds commit_worktree | Database Reviewer does not hold commit_worktree | Frontend Engineer holds commit_worktree | Integration Reviewer does not hold commit_worktree | Investigator does not hold commit_worktree | Planner does not hold commit_worktree | QA Reviewer does not hold commit_worktree | Security Reviewer does not hold commit_worktree |
push_working_branchPush a working branch | Backend Engineer holds push_working_branch | Database Reviewer does not hold push_working_branch | Frontend Engineer holds push_working_branch | Integration Reviewer does not hold push_working_branch | Investigator does not hold push_working_branch | Planner does not hold push_working_branch | QA Reviewer does not hold push_working_branch | Security Reviewer does not hold push_working_branch |
read_ciRead CI status | Backend Engineer holds read_ci | Database Reviewer does not hold read_ci | Frontend Engineer holds read_ci | Integration Reviewer does not hold read_ci | Investigator does not hold read_ci | Planner does not hold read_ci | QA Reviewer holds read_ci | Security Reviewer does not hold read_ci |
comment_issue_or_prComment on an issue or pull request | Backend Engineer holds comment_issue_or_pr | Database Reviewer holds comment_issue_or_pr | Frontend Engineer holds comment_issue_or_pr | Integration Reviewer holds comment_issue_or_pr | Investigator does not hold comment_issue_or_pr | Planner does not hold comment_issue_or_pr | QA Reviewer holds comment_issue_or_pr | Security Reviewer holds comment_issue_or_pr |
create_pull_requestRequires human approval | Backend Engineer holds create_pull_request | Database Reviewer does not hold create_pull_request | Frontend Engineer holds create_pull_request | Integration Reviewer does not hold create_pull_request | Investigator does not hold create_pull_request | Planner does not hold create_pull_request | QA Reviewer does not hold create_pull_request | Security Reviewer does not hold create_pull_request |
database_writeDenied to every role | Backend Engineer does not hold database_write | Database Reviewer does not hold database_write | Frontend Engineer does not hold database_write | Integration Reviewer does not hold database_write | Investigator does not hold database_write | Planner does not hold database_write | QA Reviewer does not hold database_write | Security Reviewer does not hold database_write |
direct_main_pushDenied to every role | Backend Engineer does not hold direct_main_push | Database Reviewer does not hold direct_main_push | Frontend Engineer does not hold direct_main_push | Integration Reviewer does not hold direct_main_push | Investigator does not hold direct_main_push | Planner does not hold direct_main_push | QA Reviewer does not hold direct_main_push | Security Reviewer does not hold direct_main_push |
force_pushDenied to every role | Backend Engineer does not hold force_push | Database Reviewer does not hold force_push | Frontend Engineer does not hold force_push | Integration Reviewer does not hold force_push | Investigator does not hold force_push | Planner does not hold force_push | QA Reviewer does not hold force_push | Security Reviewer does not hold force_push |
preview_deployDeploy to a preview environment | Backend Engineer does not hold preview_deploy | Database Reviewer does not hold preview_deploy | Frontend Engineer does not hold preview_deploy | Integration Reviewer does not hold preview_deploy | Investigator does not hold preview_deploy | Planner does not hold preview_deploy | QA Reviewer does not hold preview_deploy | Security Reviewer does not hold preview_deploy |
staging_deployRequires human approval | Backend Engineer does not hold staging_deploy | Database Reviewer does not hold staging_deploy | Frontend Engineer does not hold staging_deploy | Integration Reviewer does not hold staging_deploy | Investigator does not hold staging_deploy | Planner does not hold staging_deploy | QA Reviewer does not hold staging_deploy | Security Reviewer does not hold staging_deploy |
production_deployDenied to every role | Backend Engineer does not hold production_deploy | Database Reviewer does not hold production_deploy | Frontend Engineer does not hold production_deploy | Integration Reviewer does not hold production_deploy | Investigator does not hold production_deploy | Planner does not hold production_deploy | QA Reviewer does not hold production_deploy | Security Reviewer does not hold production_deploy |
secrets_accessDenied to every role | Backend Engineer does not hold secrets_access | Database Reviewer does not hold secrets_access | Frontend Engineer does not hold secrets_access | Integration Reviewer does not hold secrets_access | Investigator does not hold secrets_access | Planner does not hold secrets_access | QA Reviewer does not hold secrets_access | Security Reviewer does not hold secrets_access |
Denied to every role
database_write— Insert, update, delete, or migrate data. Denied in v1; database access is metadata-only.direct_main_push— Denied in v1. Changes reach the default branch through a reviewed pull request. ax git refuses a branch that is the default or a reserved name.force_push— Denied in v1, because it can destroy history that other people depend on. ax git never constructs a forced or lease-forced push.production_deploy— Denied in v1. Deployment to production stays a human action outside the harness, and ax deploy refuses every production target whatever the flags.secrets_access— Denied in v1. Credentials never enter configuration, context, agent output, or diagnostics.
These use the same identifiers as the five permissions a project declaration forces to false, and a test asserts the two sets stay identical.
Requires human approval
create_pull_request— Propose changes for review. High impact because it asks other people to act. ax pr requires an approval bound to repository, head, base, and commit.staging_deploy— Start a declared staging deployment of one exact, pushed, verified commit. Requires an approval bound to target and commit. Enforced by ax deploy.
Approval is a property of the capability, not a per-role exception, and it cannot unlock anything the policy denies outright.
{
"schemaVersion": 1,
"id": "default",
"description": "Default AX Harness capability vocabulary. Reads are broad, writes are narrow and reviewed, and the five high-impact capabilities are denied to every role.",
"capabilities": [
{
"id": "read_code",
"title": "Read repository code",
"description": "Read source, tests, and configuration in the working repository.",
"tool": "codebase",
"risk": "low",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "read_docs",
"title": "Read documentation and context",
"description": "Read the Markdown context a project declares, plus repository documentation.",
"tool": "docs",
"risk": "low",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "github_read",
"title": "Read GitHub metadata",
"description": "Read GitHub repository metadata, the default branch, and pull requests. Executed by ax pr and ax doctor through the GitHub adapter.",
"tool": "github",
"risk": "low",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "database_metadata",
"title": "Read database metadata",
"description": "Inspect schema, tables, columns, indexes, and constraints. Never row data, and never writes.",
"tool": "database",
"risk": "medium",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "run_tests",
"title": "Run declared quality commands",
"description": "Run the build, lint, typecheck, or test commands the project declared. No other command is implied.",
"tool": "codebase",
"risk": "medium",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "edit_worktree",
"title": "Edit an isolated worktree",
"description": "Modify files on a working branch. Never on the default branch, and never in someone else's checkout.",
"tool": "codebase",
"risk": "medium",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "create_branch",
"title": "Create a working branch",
"description": "Create and switch onto a new local feature branch. Never the default branch or a reserved name. Enforced by ax git; pushing is push_working_branch.",
"tool": "codebase",
"risk": "medium",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "commit_worktree",
"title": "Commit selected files",
"description": "Stage an explicit list of files on a working branch and commit them. Never git add of a whole tree, never a secret path. Enforced by ax git.",
"tool": "codebase",
"risk": "medium",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "push_working_branch",
"title": "Push a working branch",
"description": "Push a feature branch to a declared remote without force. Never the default branch, never a tag or another ref. Enforced by ax git.",
"tool": "codebase",
"risk": "medium",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "read_ci",
"title": "Read CI status",
"description": "Read check runs and commit statuses for one exact commit. Pending, absent, and unreadable are never reported as passed. Executed by ax ci through the GitHub adapter.",
"tool": "github",
"risk": "low",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "comment_issue_or_pr",
"title": "Comment on an issue or pull request",
"description": "Add review comments. Comments are visible to others, so they are a write, not a read.",
"tool": "github",
"risk": "medium",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "create_pull_request",
"title": "Open a pull request",
"description": "Propose changes for review. High impact because it asks other people to act. ax pr requires an approval bound to repository, head, base, and commit.",
"tool": "github",
"risk": "high",
"humanApproval": true,
"deniedToAllAgents": false
},
{
"id": "database_write",
"title": "Write to a database",
"description": "Insert, update, delete, or migrate data. Denied in v1; database access is metadata-only.",
"tool": "database",
"risk": "high",
"humanApproval": false,
"deniedToAllAgents": true
},
{
"id": "direct_main_push",
"title": "Push directly to the default branch",
"description": "Denied in v1. Changes reach the default branch through a reviewed pull request. ax git refuses a branch that is the default or a reserved name.",
"tool": "github",
"risk": "high",
"humanApproval": false,
"deniedToAllAgents": true
},
{
"id": "force_push",
"title": "Force push",
"description": "Denied in v1, because it can destroy history that other people depend on. ax git never constructs a forced or lease-forced push.",
"tool": "github",
"risk": "high",
"humanApproval": false,
"deniedToAllAgents": true
},
{
"id": "preview_deploy",
"title": "Deploy to a preview environment",
"description": "Start a declared preview or development deployment of one exact, pushed, verified commit through a provider adapter. Enforced by ax deploy.",
"tool": "none",
"risk": "medium",
"humanApproval": false,
"deniedToAllAgents": false
},
{
"id": "staging_deploy",
"title": "Deploy to staging",
"description": "Start a declared staging deployment of one exact, pushed, verified commit. Requires an approval bound to target and commit. Enforced by ax deploy.",
"tool": "none",
"risk": "high",
"humanApproval": true,
"deniedToAllAgents": false
},
{
"id": "production_deploy",
"title": "Deploy to production",
"description": "Denied in v1. Deployment to production stays a human action outside the harness, and ax deploy refuses every production target whatever the flags.",
"tool": "none",
"risk": "high",
"humanApproval": false,
"deniedToAllAgents": true
},
{
"id": "secrets_access",
"title": "Read secrets",
"description": "Denied in v1. Credentials never enter configuration, context, agent output, or diagnostics.",
"tool": "none",
"risk": "high",
"humanApproval": false,
"deniedToAllAgents": true
}
]
}