A gate is a checkpoint that has to pass before something happens. A release publishes when its launch gate passes - not when someone flips a flag - and the difference is that a gate can say no.
Conditions have kinds
A gate holds a list of conditions, and each one declares how it gets satisfied:
- manual - a person marks it done and their name is on it.
- automated - a check reports a result. Evidence is attached, not asserted.
- ai-assessed - an agent evaluates it and records its judgement as a judgement, with the reasoning attached. It is still a condition a human can override.
A gate with zero conditions passes. That is not a loophole, it is a gate you have not written yet.
A refusal is never a bare no
This is the part worth internalising, because it shapes how everything else behaves. When a gate refuses a transition, the answer is not 403. It is:
{
"code": "GATE_NOT_PASSED",
"message": "Gate LAUNCH-1 cannot pass: 1 of 5 conditions is unmet.",
"hint": "Complete 'Security review' (tsk_41c), then retry."
}
Three parts, always: a code you can branch on, a message a person can read, and a hint naming the exact next call that would succeed. The same three parts come back over REST and over MCP, because both are the same service.
The reason is not politeness. An agent told "forbidden" learns nothing and retries forever; an agent told which condition is open goes and closes it. Every refusal in makermap is written to be actionable, and one that is not is treated as a bug.
Authorization is per gate
Who may pass a gate is a property of that gate, not a global setting. A gate governing a production release can require a different authority than one governing a design review, and neither inherits from a workspace-wide default that somebody set once.