- name
- skill-orchestrate-hard
- description
- Full structural hard-mode orchestration state machine with per-phase dispatch (H1), adversarial verification (H4), convergence policing (H6), territory contracts (H7), and churn detection (H5). Invoke for /orchestrate --hard.
- allowed-tools
- Agent, Bash, Read
# Orchestrate Hard Skill
**IMPORTANT**: This is a FULL STRUCTURAL VARIANT, not a thin wrapper over `skill-orchestrate`.
Loop-level changes (per-phase dispatch, churn detection, adversarial verification gate) cannot
be expressed as prompt injection into the base skill. Maintenance: both skills should evolve
together -- changes to escalation ladder and handoff schema in `skill-orchestrate` should be
reflected here.
Hard-mode additions over base `skill-orchestrate`:
- **H1 Per-Phase Dispatch**: Each implement cycle dispatches exactly one phase, not the whole plan
- **H4 Adversarial Verification Gate**: Research output is verified before plan/implement dispatch
- **H5 Divergence Audit**: Three-strikes on any target triggers a dedicated audit research dispatch
- **H6 Convergence Policing**: Churn detection with per-target counters (defect_claims, sorry_relocations)
- **H7 Territory Contracts**: Territory context informs single-phase dispatch prompts (parallel-wave
dispatch is disabled — see "Tool Constraints (Pure Dispatcher)" below and Stage 4's Per-Phase
Dispatch handler; exactly one blocking `Agent` call happens per cycle)
## Tool Constraints (Pure Dispatcher)
<!-- BEGIN 772 pure-dispatcher tool constraints (standalone block; 773 must compose around this,
not overwrite it) -->
The orchestrator is a pure dispatcher: it reads state, dispatches exactly one implementation
agent per cycle, and reads that agent's handoff. It never edits implementation source, never
runs build/test/compiler tooling, and never reads implementation source files itself. This
section is the human/audit-readable statement of intent backing the frontmatter tool scoping
above (`allowed-tools: Agent, Bash, Read` — `Edit` intentionally absent).
**Permitted Bash**: orchestration bookkeeping only — `jq` reads/writes against state.json and
handoff/loop-guard/churn JSON files, file bookkeeping (`mkdir`, `mv`, `rm`, `ls`), text utilities
(`sort`, `tail`, `grep`, `cat`, `date`, `echo`), and `source .claude/scripts/*.sh` helper
scripts. These are the 12 commands the state machine above actually issues: `jq, mkdir, mv, rm,
ls, sort, tail, grep, cat, date, echo, source`.
**Forbidden Bash Operations**: `lake build` (or any `lake` invocation), `lean` / `lean-lsp` /
`mcp__lean-lsp__*`, `nvim --headless`, `npm` / `pytest` / `cargo test` / `go test`, or ANY
language build/test/compiler/linter tool. These belong exclusively to the dispatched
implementation agent (`$IMPLEMENT_AGENT`) — the orchestrator must never invoke them directly,
even to "verify" a phase before or after dispatch.
**Read allowlist (4 categories)**:
1. `specs/state.json` — task status and metadata.
2. `specs/{NNN}_{SLUG}/.orchestrator-handoff.json` and its siblings
`.orchestrator-loop-guard` / `.orchestrator-churn-state.json`.
3. `specs/{NNN}_{SLUG}/plans/*.md` and `specs/{NNN}_{SLUG}/reports/*.md`. Plan- and
report-file access covers exactly three bounded, grep-only uses, none of which is a
full-file comprehension read: (a) the H4 adversarial-verification grep over reports in
Stage 4; (b) Stage 4's `### Phase N: ... [STATUS]` next-phase selection grep over the plan;
and (c) Stage 5's count-only phase-marker recovery grep over the plan, bounded to ≤10 tokens
per recovery event (two `grep -c` integers) and fired from exactly three bounded uses: the
missing/stale-handoff branch's own diagnostic-only recovery grep (still the raw inline
two-`grep -c` idiom directly — it has no recoverable `dispatch_status` to corroborate
against, so it never calls the shared function below); the recovered=true branch's
evidence-corroboration call, fired only when return-meta recovery's own
`evidence_suspect`/`evidence_reason` report `PHASES_ZERO_ON_SUCCESS` for a claimed
`implemented` status; and the handoff-present branch's corroboration call, which fires only
when the handoff itself reports `dispatch_status = "implemented"` AND `phases_total -eq 0` —
never on the normal path of a fresh handoff with populated phase accounting. The latter two
uses both call the SAME shared `skill_corroborate_phase_counts` (`scripts/skill-base.sh`),
which performs the same two `grep -c` calls inside itself rather than inline — the single
anchor both uses (and their base-mode and multi-task mirrors) now share, in the same way
`scripts/lib/phase-heading-patterns.sh` is the single grammar anchor every phase-heading
consumer sources rather than re-deriving. Any other use of these files is outside the
allowlist. (The recovered=true branch's site also carries a sibling `elif` arm on
`evidence_reason="ARTIFACTS_SHAPE_MISMATCH"` — Deliverable 2(a), a non-fatal
`system-defect-record.sh` consumer call. It shares the `recovered=true` precondition but
performs no `grep -c` of any kind and calls no new Read, so it is not a fifth bounded use of
this allowlist.)
4. `.claude/context/contracts/*.md` and `.claude/docs/architecture/*.md` (this skill's own
contracts and architecture docs, per Context References above).
**Forbidden Reads**: implementation source of any kind — `lua/**`, `after/**`, or any
per-project source root an `$IMPLEMENT_AGENT` would modify. If the orchestrator finds itself
about to Read a source file to "check" an implementation, that is a signal it has drifted from
pure-dispatcher behavior; the correct action is to dispatch (or re-dispatch) the implementation
agent and read its handoff instead.
<!-- END 772 pure-dispatcher tool constraints -->
## Context References
Architecture documentation (load as needed):
- `.claude/context/contracts/convergence.md` - H6 convergence policing rules
- `.claude/context/contracts/territory.md` - H7 territory contract for parallel dispatch
- `.claude/context/contracts/anti-analysis.md` - H2 contract injected into each implement dispatch
- `.claude/context/contracts/wrap-up.md` - H9 contract for handoff discipline
- `.claude/context/contracts/recovery.md` - Fix-forward recovery ladder referenced by the
Recovery Discipline contract slot (see CONTRACT SLOTS below)
- `.claude/context/contracts/orchestrator-discipline.md` - Orchestrator-role discipline
contract governing this state-machine loop itself (Stage 1c preamble, Stage 3c burnout
circuit-breaker gate) — not the implement dispatches that anti-analysis.md governs
- `.claude/docs/architecture/orchestrate-state-machine.md` - Base state table (reference)
- `.claude/docs/architecture/handoff-schema.md` - Handoff JSON schema
---
## Execution Flow
### Stage 0: Multi-Task Mode Detection
Same as base `skill-orchestrate`. Parse `multi_task_mode`. If true, use base multi-task
stages (per-phase dispatch applies to each task independently within the wave).
```bash
source .claude/scripts/skill-base.sh
multi_task_mode=$(echo "$delegation_context" | jq -r '.multi_task_mode // false')
session_id=$(echo "$delegation_context" | jq -r '.session_id')
focus_prompt=$(echo "$delegation_context" | jq -r '.focus_prompt // ""')
effort_flag=$(echo "$delegation_context" | jq -r '.effort_flag // "hard"')
# Defect B: explicit, operator-typed budget-continuation override. Parsed here (never inferred
# from session_id, mtime, or any automatic signal) so Stage 2's MAX_CYCLES exhaustion branch can
# read it. See Stage 2 below for the full override mechanism and its rationale.
continue_budget_flag=$(echo "$delegation_context" | jq -r '.continue_budget // false')
```
---
### Stage 1: Input Validation
```bash
task_number=$(echo "$delegation_context" | jq -r '.task_context.task_number')
PADDED_NUM=$(printf "%03d" "$task_number")
TASK_DATA=$(jq -r --argjson num "$task_number" \
'.active_projects[] | select(.project_number == $num)' \
specs/state.json)
if [ -z "$TASK_DATA" ]; then
echo "ERROR: Task $task_number not found in state.json" >&2
exit 1
fi
PROJECT_NAME=$(echo "$TASK_DATA" | jq -r '.project_name')
TASK_TYPE=$(echo "$TASK_DATA" | jq -r '.task_type // "general"')
DESCRIPTION=$(echo "$TASK_DATA" | jq -r '.description // ""')
TASK_DIR="specs/${PADDED_NUM}_${PROJECT_NAME}"
# Absolute companion. TASK_DIR stays relative for existing consumers; TASK_DIR_ABS is the
# anchor handed to dispatched agents, which cannot know the ambient working directory their
# Write tool will resolve against. SKILL_REPO_ROOT is exported by skill-base.sh.
TASK_DIR_ABS="${TASK_DIR_ABS:-${SKILL_REPO_ROOT:-$(pwd)}/${TASK_DIR}}"
HANDOFF_PATH_ABS="${TASK_DIR_ABS}/.orchestrator-handoff.json"
```
---
### Stage 1b: Resolve Hard-Mode Agent Routing
Map task_type to hard-mode research, plan, and implementation agents via the single canonical
agent resolver, `command-route-agent.sh` — the same script `skill-orchestrate`'s (base) Stage 1b
calls, sourced here with effort `"hard"` and hard-mode defaults. Resolution runs against each
manifest's `routing_agents_hard` declarations; a miss falls through directly to the
caller-supplied hard-mode default below (NOT to the standard, non-hard `routing_agents` block),
preserving today's default-to-general-hard-agent behavior exactly. The two engines now differ
only in the effort argument and these three defaults — no case table, no manifest loop, no sed
derivation.
```bash
source .claude/scripts/command-route-agent.sh "research" "$TASK_TYPE" "general-research-hard-agent" "hard"
RESEARCH_AGENT="$AGENT_NAME"
source .claude/scripts/command-route-agent.sh "plan" "$TASK_TYPE" "planner-hard-agent" "hard"
PLANNER_AGENT="$AGENT_NAME"
source .claude/scripts/command-route-agent.sh "implement" "$TASK_TYPE" "general-implementation-hard-agent" "hard"
IMPLEMENT_AGENT="$AGENT_NAME"
echo "[hard-orchestrate] Routing: research=$RESEARCH_AGENT, implement=$IMPLEMENT_AGENT, plan=$PLANNER_AGENT"
```
---
### Dispatch Context Anchor Invariant
Every `delegation_context` in this file states `orchestrator_mode` explicitly, giving two
checkable properties: (I1) no site relies on the reader's `// "false"` default — the key is
always present, `true` or `false`; (I2) `task_dir` / `handoff_path` are present on a context if
and only if it declares `orchestrator_mode: true`. The one indirection: `delegation_context:
$dispatch_context` (Stage 4, per-phase implement dispatch) refers to the JSON literal built
immediately above it — that literal, not the reference line, carries `orchestrator_mode` and the
anchors. `orchestrator_mode` is dual-consumer (handoff-write gate plus the literature Stage 4a
autonomy gate — see the Dual-Consumer Note in `docs/architecture/handoff-schema.md`), so a future
edit here weighs both; the `false` sub-dispatches (H4 verification, H5 divergence audit, Stage 6
blocker research) pass no `lit_flag` at all, leaving the literature path disabled there regardless.
```bash
F=agent-system/extensions/core/skills/skill-orchestrate-hard/SKILL.md
# Anchored at line-start (after leading whitespace) so this check does not self-match its own
# quoted grep patterns below — an unanchored 'delegation_context: {' pattern matches its own
# source line once embedded in this same file.
PAT='^[[:space:]]*delegation_context: \{'
[ "$(grep -cE "$PAT" "$F")" = "$(grep -cE "$PAT.*orchestrator_mode" "$F")" ] && echo "I1 holds"
grep -E "$PAT.*orchestrator_mode: true" "$F" | grep -qv 'task_dir' && echo "I2 VIOLATED (true without task_dir)" || echo "I2 holds (true sites)"
grep -E "$PAT.*orchestrator_mode: false" "$F" | grep -q 'task_dir\|handoff_path' && echo "I2 VIOLATED (false with anchor)" || echo "I2 holds (false sites)"
```
---
### Stage 1c: Orchestrator Discipline Preamble
Runs ONCE per invocation, immediately after Stage 1b and before the loop begins.
`Read .claude/context/contracts/orchestrator-discipline.md`
State (to yourself, in your own transcript) that this session is bound by the orchestrator
discipline contract just read: no inline design/proof analysis, no reading implementation
source, no running builds, no mid-cycle strategy reconsideration without a fresh dispatch; when
a phase cannot complete in a bounded dispatch, the only allowed responses are (a) dispatch a
fresh research/audit agent or (b) escalate via the blocker ladder — never absorb the work
inline. This preamble is the pointer; the enforceable checklist is inlined at every loop
iteration in Stage 3c below.
---
### Stage 2: Loop Guard and Churn State Initialization
Create or read the loop guard file with hard-mode churn counters.
**Both `.orchestrator-loop-guard` and `.orchestrator-churn-state.json` are ephemeral, gitignored,
and never committed.** Neither has a freshness check on read — the resume branch below trusts any
syntactically valid file at these paths unconditionally, with no `session_id` or mtime comparison
against the current dispatch. A git-restored copy of either would silently resume a wrong cycle
count, burnout-signal count, or churn history. See
`context/standards/orchestrator-runtime-files.md` for the full two-class policy and rationale.
```bash
MAX_CYCLES=13
# Single shared implementation, orchestrate-loop-guard-init.sh — see that script's header for
# the full contract. Same call skill-orchestrate/SKILL.md's Stage 2 makes for its own
# genuinely-common portion — everything else in this stage (MAX_CYCLES's own value, the
# hard-only loop-guard-staleness detector immediately below, churn-state init) stays per-engine.
loop_guard_init_json=$(bash .claude/scripts/orchestrate-loop-guard-init.sh "$TASK_DIR" "${HANDOFF_PATH_ABS}")
loop_guard_file=$(echo "$loop_guard_init_json" | jq -r '.loop_guard_file')
handoff_file=$(echo "$loop_guard_init_json" | jq -r '.handoff_file')
MAX_INFRA_FAILURES=$(echo "$loop_guard_init_json" | jq -r '.max_infra_failures')
churn_file="${TASK_DIR}/.orchestrator-churn-state.json"
# Live plan-lineage reference for the loop-guard-staleness detector (Stage 2, below) and the
# guard's own `plan_version` schema field. Safe when plans/ does not exist yet (task in
# researching/planning status): the ls glob then matches nothing, `sort -V | tail -1` on empty
# input yields an empty string, and `basename ""` also yields an empty string here, so the
# explicit `:-none` fallback is required -- never treat an absent plans/ directory as evidence of
# staleness.
current_plan_version=$(basename "$(ls -1 "${TASK_DIR}/plans/"*.md 2>/dev/null | sort -V | tail -1)" 2>/dev/null)
current_plan_version="${current_plan_version:-none}"
# --- loop-guard-staleness:begin ---
# Operational-staleness detector: a genuinely-present, never-git-touched guard that is simply
# superseded or old on disk (distinct from the git-restoration hazard the ephemeral/gitignored
# classification protects against). Three OR-combined signals; any one tripping is sufficient.
# See context/standards/orchestrator-runtime-files.md's "Operational staleness: a second,
# orthogonal freshness axis" for the full policy, thresholds, and the anti-session_id defense.
# No task-lock.sh dependency in this region -- it only reads, decides, and archives (mv), so it
# is directly executable in a fixture harness. The pre-existing `if [ -f "$loop_guard_file" ]`
# block immediately below this region, and the churn-state block below that, are left completely
# unmodified: once a stale guard/churn file is mv'd aside, `[ -f ]` is false and each falls
# through to its own existing fresh-init branch naturally, at cycle_count=0 / total_churn=0.
loop_guard_stale=false
Ver no GitHub