Skip to content

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 ​

MomentThe human decidesHow Maverick enforces it
Between planning stagesWhether the PRD, spec or task graph is right before the next stage startsEvery 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 subtaskWhether to continue to the next subtaskmaverick-build asks after every subtask
ReviewApprove, approve with follow-up, or request changesOnly a checked box in REVIEW.md or flow approve passes the human-review gate, unless you turn on auto-approval for the flow
MergeWhether this goes inMaverick has no merge command. maverick-ship commits, pushes or opens a PR only when you ask
Agent powerWhich agents may run here, and how much they may doruntime.trusted, runtime.maxPermission, hooks
A stuck or disputed loopWhat a loop that ran out of rungs, or whose agent disputes a check, does nextThe loop stops with LOOP-ESCALATION.md; only loop run --resume --note continues it (Loop engineering)
Judges that disagreeWhether a change meets its criteria when independent judges are not sureThe 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:

Rubber stampThe human is technically in the loop but approves whatever arrives, because there is too much of it, or because the agent already said it was fine.
Ambient powerThe agent runs with full shell access "because the task looked routine", so the routine task can also delete files, push branches and call the network.
Few, real decisionsMaverick asks at the joints where a decision changes the outcome, and does the bookkeeping in between, so each decision gets attention.
Least privilege by defaultThe default ceiling is 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:

bash
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 task

Every run is resolved through the same checks, in this order:

  1. Is the provider trusted here?

    Only providers in runtime.trusted can run. Trust is per repository, asked for interactively, and written to .maverick/config.json so it is reviewed and committed like code.

  2. 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 (default edit).

  3. 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 edit for it rather than silently granting more.

  4. Do the hooks allow it?

    A before-agent-run hook 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.

TRY IT · WHO MAY RUN, WITH WHAT POWER
Provider
Ceiling · runtime.maxPermission
Requested · --permission
Hook · before-agent-run
$ maverick agent run add-orders-pagination --provider claude-code --permission edit
✓ Claude Code runs with edit permission; the run is recorded under the task's runs

The permission levels ​

LevelThe agent mayUse for
read-onlyRead and plan; write nothingGenerating the PRD, TECHSPEC and tasks (maverick generate always runs read-only), reviews
editEdit files in the repositoryBuilding a subtask, fixing checks
fullEdit and run shell commands without askingOnly in a sandbox or container you would be comfortable throwing away

Configuration ​

json
{
  "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:

js
// 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 maxPermission to 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.maxPermission is edit or lower, unless runs happen in a disposable sandbox
  • [ ] Planning and review stages run read-only
  • [ ] Sensitive areas have a before-agent-run hook or a policy rule
  • [ ] Spec approval and the review decision were made by a person
  • [ ] A person opens and merges the PR

Commands ​

CommandDoes
maverick agent listShows providers, whether installed and trusted, and supported permissions
maverick agent trust <provider> · untrustAdds 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 nextRuns 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|offLets 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

Next ​

AI writes. Engineers decide. · Code under MIT · content under CC BY-NC 4.0.