# Desk Authority Map: five rules and a five-check script (free sample)

Version 1.0, 2026-10-28. By PaperChaseWebb. For anyone running more than one agent, in Grok Bot, Claude Code, Codex, Hermes or a mix, who wants it written down which agent may do what on its own. One Markdown file and one Python 3 script, standard library only. The script was tested on its worked example (5 findings, then 0) and on a missing file (exit 2). It was not run inside any agent harness or on a real fleet.

Most agent setups have an org chart: a research agent, a support agent, a builder. Titles, tools, a reporting line. What the chart rarely says is the part that matters on a bad day: which of them may send, spend, delete or change access without asking, and who checks their work. These five rules cover the gaps that cost the most, and the script checks them in one small file.

## Install in one line

Save this page as FREE-SAMPLE.md, then:

```
python3 -c "import re;t=open('FREE-SAMPLE.md').read();open('authority_mini.py','w').write(re.search(r'~~~python\n(.*?)~~~',t,re.S).group(1))"
python3 authority_mini.py authority-lite.json
```

## Five rules

1. **Every desk has a human owner.** A person answers for it. Not "TBD", and not another agent.
2. **No desk checks its own work.** Another desk or a person reads what it did.
3. **Nothing that cannot be undone is decided alone.** A sent email, a deletion, a refund: prepare it, then someone releases it.
4. **Money gets a dollar limit.** If a desk may spend on its own, write down how much. Above that, it goes up a level.
5. **Some actions belong to the owner.** Access changes, contracts and changes to the map itself are only ever ask-owner or never.

## The five checks

| Id | Check |
|---|---|
| M1 | every desk names a human owner |
| M2 | no desk checks its own work |
| M3 | nothing marked as impossible to undo is decide |
| M4 | money at decide carries a dollar limit |
| M5 | owner-only actions are only ask-owner or never |

Levels are decide (do it alone), propose (prepare it, someone else releases it), ask-owner (stop and wait for the owner) and never. Exit 0 clean, 1 findings, 2 missing or unreadable file. The script only reads.

## Worked example

A made-up tile supply shop with four desks. Before (authority-lite.json):

```json
{
 "owner": "Dana Owner",
 "owner_only": [
  "grant_access",
  "sign_contract"
 ],
 "desks": [
  {
   "desk": "chief",
   "owner": "Dana Owner",
   "checked_by": "reviewer"
  },
  {
   "desk": "support",
   "owner": "Dana Owner",
   "checked_by": "chief"
  },
  {
   "desk": "builder",
   "owner": "TBD",
   "checked_by": "reviewer"
  },
  {
   "desk": "reviewer",
   "owner": "Dana Owner",
   "checked_by": "reviewer"
  }
 ],
 "rules": [
  {
   "desk": "support",
   "action": "draft_reply",
   "level": "decide",
   "reversible": true,
   "money": false
  },
  {
   "desk": "support",
   "action": "send_customer_email",
   "level": "decide",
   "reversible": false,
   "money": false
  },
  {
   "desk": "builder",
   "action": "small_purchase",
   "level": "decide",
   "reversible": true,
   "money": true
  },
  {
   "desk": "builder",
   "action": "grant_access",
   "level": "propose",
   "reversible": false,
   "money": false
  },
  {
   "desk": "chief",
   "action": "sign_contract",
   "level": "ask-owner",
   "reversible": false,
   "money": false
  }
 ]
}
```

Output:

```
M1 desk builder has no human owner
M2 desk reviewer checks its own work
M3 support / send_customer_email cannot be undone but is decide
M4 builder / small_purchase moves money at decide with no dollar limit
M5 builder / grant_access is owner-only but set to propose
5 checks, 5 findings
```

The fixes: Jo is named as the builder desk's owner, the reviewer desk is checked by the owner, sending a customer email goes back to propose, the $25 purchase limit is written in, and access changes go back to never for the builder. After:

```
5 checks, 0 findings
```

## One prompt to try

Paste into your agent: "Read authority-lite.json. List every action you have done in the last week that is not in it, and the level you think each should have. Do not change the file; I will."

## What the full pack adds

The Desk Authority Map (pp-desk-authority-map, $29) turns these rules into a map your agents ask before they act. Four small files (fleet, desks, actions, rules) with risk classes, dollar limits, escalation and the evidence each desk owes. authority.py answers decide, propose, ask-owner or never with an exit code an agent can follow, and anything not in the map answers never. Owner yeses are typed at the owner's own terminal, tied to the sha256 of one request, good for one use within a set number of days, and refused inside an agent or on piped input. Nothing is decided while the map is unratified. Fifteen read-only checks, 60 tests, a skill file for Claude Code, Codex and Hermes, an AGENTS.md snippet and a Grok Bot rules block. If you want it built with you across a whole fleet, that is the Expand work on paperchasewebb.ai, which starts with a $5,000 Install sprint.

## The script

~~~python
#!/usr/bin/env python3
"""authority_mini.py: five read-only checks on a one-file authority map (authority-lite.json).
Usage: python3 authority_mini.py authority-lite.json
Exit 0 clean, 1 findings, 2 missing or unreadable file. Standard library only. Writes nothing."""
import json, sys

PLACEHOLDERS = {"", "tbd", "todo", "owner", "someone", "agent", "ai", "team"}


def main(a):
    if len(a) < 2:
        print(__doc__); return 2
    try:
        m = json.load(open(a[1]))
    except Exception as e:
        print(f"cannot read {a[1]}: {e}", file=sys.stderr); return 2
    desks = {x.get("desk"): x for x in m.get("desks", [])}
    F = []
    for name, x in desks.items():
        if str(x.get("owner", "")).strip().lower() in PLACEHOLDERS or x.get("owner") in desks:
            F.append(("M1", f"desk {name} has no human owner"))
        if str(x.get("checked_by", "")).strip() in ("", name):
            F.append(("M2", f"desk {name} checks its own work"))
    oo = set(m.get("owner_only", []))
    for r in m.get("rules", []):
        k = f"{r.get('desk')} / {r.get('action')}"
        if r.get("level") == "decide" and r.get("reversible") is False:
            F.append(("M3", f"{k} cannot be undone but is decide"))
        if r.get("level") == "decide" and r.get("money") and not (isinstance(r.get("limit_usd"), (int, float)) and r.get("limit_usd") > 0):
            F.append(("M4", f"{k} moves money at decide with no dollar limit"))
        if r.get("action") in oo and r.get("level") not in ("ask-owner", "never"):
            F.append(("M5", f"{k} is owner-only but set to {r.get('level')}"))
    for c, msg in sorted(F):
        print(c, msg)
    print(f"5 checks, {len(F)} findings")
    return 1 if F else 0


if __name__ == "__main__":
    sys.exit(main(sys.argv))
~~~

Made-up example; no real business or results are described.

PaperChaseWebb 💸
