Orchestrata Ultimate › Gates › dispatch-brief

Gate: dispatch-brief

At a glance

Purpose No worker starts from an under-specified brief: every Agent spawn carries GOAL/FILES/CONSTRAINTS/DONE WHEN/VERIFY, coding and testing briefs carry the AST of the module they change, and builder/wirer/refactorer dispatches carry design authority.
Where it runs PreToolUse hooks of the orchestrata plugin (plugins/orchestrata/hooks/hooks.json): task_context_hook.py on Agent|Edit|MultiEdit|Write|NotebookEdit; _dispatch.sh require-design-before-build.sh on Agent; _dispatch.sh workflow-default-sonnet.sh on Workflow.
Trigger Every Agent tool call (forks included) and every Workflow script.
Exact command No manual command. The hooks receive the tool payload on stdin.
Blocks task_context_hook.py answers permissionDecision: deny with a reason; require-design-before-build.sh and workflow-default-sonnet.sh exit 2 with remediation on stderr. All three fail open on malformed input.
Ruling / ADR RUL-022 and ADR-0048 (a ratified ADR is design authority); RUL-026; hook placement RUL-035 / ADR-0070. The five labels have no RUL page; their origin is the hook's own comment (below).

The flow

Diagram projects-orchestrata-ultimate-gates-dispatch-brief-1

What task_context_hook.py checks

Read with the AST toolkit (claude/hooks/task_context_hook.py; the plugin copy is byte-identical, and the deployed ~/.claude/hooks copy is identical after line 1, which deploy/install-claude-config.sh rewrites to the deployed interpreter).

What require-design-before-build.sh checks

Its decision table (header, mirrors plans/contracts/rul-022-design-gate.contract.json):

  1. tool is not Agent → allow.
  2. subagent_type not in {builder, wirer, refactorer} → allow. The comparison is an exact set membership, so a namespaced type such as orchestrata:builder is not in the set (read from the script, 2026-10-23; whether such dispatches occur was not measured).
  3. a line matching ^DESIGN_WAIVER:[ \t]*(.*)$ with a non-empty reason → allow, reason echoed to stderr. A bare DESIGN_WAIVER: does not count, and a waiver embedded mid-sentence does not match (memory agent-brief-hook-fields, 2026-10-06).
  4. an existing plans/contracts/… path in the prompt → allow.
  5. --requirements, --spec-file and --artifact-file all named and scripts/factory_decision.py decide exits 0 → allow.
  6. otherwise → BLOCKED (RUL-022): implementation dispatch with no ratified design, exit 2, with the remediation (dispatch analyst for a contract, run gen-skeleton, re-dispatch naming it, or add DESIGN_WAIVER: <reason>).

It runs through _dispatch.sh, which scopes plugin hooks to the orchestrata tree. PreToolUse(Agent) payloads carry no path, so the dispatcher uses a per-session memo of the repo the session last operated on; in a session that has not yet touched the repo through a path-bearing call, the guard does not fire (_dispatch.sh header: measured 2026-08-23, 14 of 25 project hooks were dark in $HOME sessions before the memo). task_context_hook.py is registered directly and fires in every session.

workflow-default-sonnet.sh (Workflow tool)

Blocks (exit 2) a Workflow script with an agent() call that names no model, unless it is a resumeFromRunId replay. Measured cause (header): on 2026-08-05 two scripts with no model ran 58 agents, all on Opus, 10.4M subagent tokens, for Sonnet-shaped work. "The rule is 'state the tier', not 'always Sonnet'."

Evidence of the gate biting

When What was refused Source
2026-10-06 Two builder dispatches: missing labels, and a waiver inside the GOAL line memory agent-brief-hook-fields
2026-10-22 (D16) A rehearsal dispatch, twice: FILES named no .py path, then the label read FILES (read-only context; ...): IMPROVEMENT-LOG D16
2026-10-22 (D19) A test-writer dispatch for FILES (yours alone; ...):, an hour after the template rule against it IMPROVEMENT-LOG D19; mechanism queue item "brief_lint.py label check"
2026-10-22 Three bounces for label variants such as VERIFY (budget…): memory better-briefs
2026-10-23 ~04:50 UTC Three fork dispatches by the documentation session: "Agent brief is missing required field(s): GOAL:, FILES:, CONSTRAINTS:, DONE WHEN:, VERIFY:" — the hook applies to forks too this session

Typical failures and how to fix them

Message Fix
Agent brief is missing required field(s): … Put each label literally, e.g. FILES: with nothing between the word and the colon. Copy the skeleton from the brief template (briefs).
… the brief must carry the AST of the module being changed — and FILES names no .py path at all Name at least one .py path in FILES:, even for read-only work (mark it read-only after the path).
module_context.py is MISSING at … The plugin's delivery layout is broken; regenerate and redeploy the plugin (the message says so), or embed a === MODULE CONTEXT block.
BLOCKED (RUL-022) First line DESIGN_WAIVER: <ADR/RUL/ruling and date>, or name a ratified plans/contracts/ file.
Workflow blocked for a missing model Pass model: on every agent() call.