Human in the loop
CONCEPT · WHO DECIDES, AND WITH WHAT POWER
The human owns authorization, design trade-offs, execution permissions, the review decision and the merge. AI proposes; it does not assume accountability. In Maverick this is not a guideline, it is built into the tool: approval gates the agent cannot pass on its own, a trust list, a permission ceiling, hooks that can veto a run, and no command that merges.
The decisions that stay human
| Moment | The human decides | How Maverick enforces it |
|---|---|---|
| Between planning stages | Whether the PRD, spec or task graph is right before the next stage starts | Every stage skill asks before moving on |
| Behavior spec (spec-driven) | Whether the behavior is what we want, before any design | - [x] Spec approved in SPEC.md, or maverick flow approve spec <task> spec-approval |
| Each subtask | Whether to continue to the next subtask | maverick-build asks after every subtask |
| Review | Approve, approve with follow-up, or request changes | Only a checked box in REVIEW.md or flow approve passes the human-review gate, unless you turn on auto-approval for the flow |
| Merge | Whether this goes in | Maverick has no merge command. maverick-ship commits, pushes or opens a PR only when you ask |
| Agent power | Which agents may run here, and how much they may do | runtime.trusted, runtime.maxPermission, hooks |
| A stuck or disputed loop | What a loop that ran out of rungs, or whose agent disputes a check, does next | The loop stops with LOOP-ESCALATION.md; only loop run --resume --note continues it (Loop engineering) |
| Judges that disagree | Whether a change meets its criteria when independent judges are not sure | The judge gate waits; flow approve records your decision for that exact change |
Why it matters
Agents are getting better at doing the work. They are not getting better at owning it. When an agent changes the payment flow, someone must be able to say why it was safe, and that person must have actually decided. Two failure modes make that impossible:
edit. Raising it is a reviewed change to a committed config file, not a flag.Headless agents
When an agent runs headlessly (maverick agent run, maverick generate, flow run --agent), there is no person watching each step, so the guardrails move into configuration:
maverick agent list # installed providers, trust and supported permissions
maverick agent trust claude-code # asks for confirmation, writes runtime.trusted
maverick agent run add-orders-pagination --subtask next --permission edit
maverick agent runs add-orders-pagination # every run, recorded as JSONL under the taskEvery run is resolved through the same checks, in this order:
Is the provider trusted here?
Only providers in
runtime.trustedcan run. Trust is per repository, asked for interactively, and written to.maverick/config.jsonso it is reviewed and committed like code.Is the permission under the ceiling?
Permission comes from the flag, then a matching route, then the stage default. A flag can lower it but never raise it above
runtime.maxPermission(defaultedit).Can this provider honor it?
Some CLIs cannot enforce a level. Cursor applies edits only with a flag that also allows shell commands, so Maverick refuses
editfor it rather than silently granting more.Do the hooks allow it?
A
before-agent-runhook receives the run as JSON. Exit 0 allows it (and may append to the prompt), exit 2 denies it with a reason, and any other failure also denies: blocking hooks fail closed.
Try it: resolve a run
Change the provider, the ceiling, the requested permission and the hook. The message is the one Maverick prints.
The permission levels
| Level | The agent may | Use for |
|---|---|---|
read-only | Read and plan; write nothing | Generating the PRD, TECHSPEC and tasks (maverick generate always runs read-only), reviews |
edit | Edit files in the repository | Building a subtask, fixing checks |
full | Edit and run shell commands without asking | Only in a sandbox or container you would be comfortable throwing away |
Configuration
{
"runtime": {
"trusted": ["claude-code", "codex"],
"maxPermission": "edit",
"default": { "provider": "claude-code" },
"stages": { "review": { "provider": "codex", "permission": "read-only" } },
"routes": [{ "match": { "type": "frontend" }, "provider": "claude-code", "effort": "high" }]
},
"hooks": [
{ "event": "before-agent-run", "run": "node scripts/deny-payments.mjs" },
{ "event": "after-agent-run", "run": "node scripts/notify.mjs" }
]
}Hooks run for before-agent-run (blocking), after-agent-run and after-flow-run (observing: a failure is reported as a warning). A typical before-agent-run hook denies runs that would touch a sensitive area without a human pairing session:
// scripts/deny-payments.mjs: exit 2 denies the run, stderr is the reason
const run = JSON.parse(await new Response(process.stdin).text());
if (JSON.stringify(run).includes('src/payments/')) {
console.error('touches src/payments/; needs a human pairing session');
process.exit(2);
}For team-wide rules on the diff itself, maverick policy init writes .maverick/policy.json: a maximum number of changed files, and sensitive paths that require the strict workflow. maverick policy check <task> enforces it.
Common mistakes
- Giving an agent broad permissions because a task appears routine. Routine tasks are where nobody is watching.
- Trusting a provider in a repository you have not read. Trust means "this CLI may run with my user account here".
- Raising
maxPermissionto unblock one run. Lower the request or change the provider instead; the ceiling is for every run after this one too. - Approving to keep the flow moving. "Request changes" is a valid, useful outcome.
- Letting the agent record the decision. The review skill never checks the Decision box. Do not ask it to.
Checklist
- [ ] Only providers you have reviewed are in
runtime.trusted - [ ]
runtime.maxPermissioniseditor lower, unless runs happen in a disposable sandbox - [ ] Planning and review stages run
read-only - [ ] Sensitive areas have a
before-agent-runhook or a policy rule - [ ] Spec approval and the review decision were made by a person
- [ ] A person opens and merges the PR
Commands
| Command | Does |
|---|---|
maverick agent list | Shows providers, whether installed and trusted, and supported permissions |
maverick agent trust <provider> · untrust | Adds or removes a provider from runtime.trusted, after confirmation |
maverick agent stage [<stage>] | Shows or edits the provider, model and effort per workflow stage |
maverick agent run <task> --subtask next | Runs a trusted agent on the next ready subtask, within the ceiling |
maverick agent runs <task> | Lists recorded runs with provider, status and duration |
maverick flow approve <flow> <task> <gate> | Records a human approval for an approval gate |
maverick flow auto-approve <flow> on|off | Lets a flow approve its own pending gates once every blocking check passes (opt-in, marked as auto-approved) |
maverick policy init · check <task> | Creates and enforces team rules on the diff |