141 lines
10 KiB
Markdown
141 lines
10 KiB
Markdown
---
|
|
name: orchestrate-agent-task-loop
|
|
description: Execute dependency-ready PLAN and CODE_REVIEW task loops with workspace write claims, a bundled default agent/model catalog, runtime catalog overrides, deterministic target failover, and persistent recovery state.
|
|
---
|
|
|
|
# Orchestrate Agent Task Loop
|
|
|
|
## Final-channel gate
|
|
|
|
Do not end the caller turn through `final` until either:
|
|
|
|
- every in-scope task has a verified archived `complete.log`, every generated work log is archived, no task or execution remains active, and the dispatcher exits `0`; or
|
|
- the user explicitly asks to stop the current run.
|
|
|
|
Use `commentary` for non-terminal status, blockers, questions, recovery notices, and partial completion. If the user asked for a persistent run, successful completion alone does not release this gate.
|
|
|
|
## Purpose
|
|
|
|
Monitor the file-backed workflow under `agent-task/` and converge ready PLAN implementation, optional self-check, official review, follow-up PLAN, and archive completion. The dispatcher owns deterministic scheduling, recovery, target transitions, and runtime evidence. Child agents own implementation and review judgments within their assigned artifact.
|
|
|
|
## Inputs
|
|
|
|
- `workspace`: trusted repository root containing `agent-task/`; defaults to the current directory.
|
|
- `execution_catalog`: optional runtime agent/model catalog override, supplied with `--execution-catalog` or `AGENT_TASK_EXECUTION_CATALOG`; otherwise use `assets/default-execution-catalog.json`.
|
|
- `task_group`: optional `agent-task/<task_group>` scope.
|
|
- `dry_run`: inspect routes, dependencies, claims, and catalog validity without launching an agent.
|
|
- `max_parallel`: workspace-wide active task-stage limit; defaults to `3`; `0` means unlimited.
|
|
- `retry_blocked`: retry eligible blocked tasks without changing their catalog route history.
|
|
|
|
`--validate-plan` validates one PLAN without launching orchestration and therefore does not require an execution catalog.
|
|
|
|
## Preconditions
|
|
|
|
- Read the current plan and code-review contracts routed by `agent-ops/skills/common/router.md`.
|
|
- Use the bundled default catalog unless the runtime or project layer supplies an override.
|
|
- Run `--dry-run` before the first live execution.
|
|
- Never bypass the physical-workspace dispatcher lock.
|
|
- Keep automatic approval inside the current workspace and the PLAN's declared write set.
|
|
|
|
## Runtime catalog contract
|
|
|
|
The bundled catalog is `assets/default-execution-catalog.json`. Catalog resolution order is explicit argument, `AGENT_TASK_EXECUTION_CATALOG`, then the bundled default. Every catalog root contains exactly `schema_version`, `targets`, and `routes`. It must cover `worker` and `review`, and each stage must define every `local-G01` through `local-G10` and `cloud-G01` through `cloud-G10` route.
|
|
|
|
Each target has:
|
|
|
|
- an opaque `agent` identity;
|
|
- an opaque `model` identity;
|
|
- `execution_class`: `local_model` or `cloud_model`;
|
|
- optional `selfcheck_required` boolean;
|
|
- `runtime.command`: a non-empty argv template executed without a shell;
|
|
- optional `runtime.resume_command`, `preflight_command`, `environment`, `session_path`, `native_session_monitor`, and `auxiliary_logs`;
|
|
- optional `runtime.output_format`: `text` or `jsonl`.
|
|
|
|
Command templates may use only `{agent}`, `{model}`, `{target_id}`, `{workspace}`, `{attempt_dir}`, `{session_id}`, `{resume_session}`, and `{prompt}`. The catalog must not embed repository secrets; environment values should refer only to runtime-provided non-secret configuration.
|
|
|
|
Each route owns its ordered `candidates` plus optional `rule_id`, `policy_priority`, and `reason_codes`. A route may use catalog-owned `windows` instead of a fixed candidate list; every window supplies an IANA timezone, start/end time, and candidates. Exactly one window must match.
|
|
|
|
Before work starts, the dispatcher:
|
|
|
|
1. resolves and validates the entire catalog;
|
|
2. verifies exact route coverage and every target reference;
|
|
3. verifies each target command is executable;
|
|
4. runs an optional target `preflight_command` for live execution;
|
|
5. records the catalog source and SHA-256 revision in the decision.
|
|
|
|
A persisted decision is valid only while the resolved catalog revision and selected target snapshot still match. Catalog changes fail closed instead of silently changing an active work unit.
|
|
|
|
## Selection and failover
|
|
|
|
- Initial execution selects the first candidate in the resolved route.
|
|
- Resume pins the persisted target and route revision.
|
|
- The dispatcher never queries quota before admission and never accepts a quota snapshot as selector input.
|
|
- Classify actual terminal output after an attempt. `provider-quota`, `context-limit`, `model-unavailable`, `provider-stream-disconnect`, and `provider-connection` may advance to the next unused route candidate.
|
|
- In particular, a confirmed quota/rate-limit error advances directly to the next candidate. A plain mention of quota in source text, model prose, or non-terminal output is not sufficient evidence.
|
|
- `generic-error`, process termination, work-log failure, and review-control failure do not imply quota and do not change the selected target.
|
|
- Never use a hidden promotion table or provider-specific fallback. If no next catalog candidate exists, keep recovery within the stage budget or block the task with evidence.
|
|
- Transfer logical context using the prior locator, normalized output, raw stream, workspace, and PLAN. Use native resume only when both targets opt into the same catalog-declared native-session mechanism and the session belongs to the current workspace.
|
|
|
|
## Scheduling and write claims
|
|
|
|
- Admit every dependency-ready task whose canonical PLAN write set does not collide with another active claim.
|
|
- Require exactly one non-empty `Modified Files Summary` or supported legacy heading. Reject broad, malformed, directory, outside-workspace, or missing paths.
|
|
- Atomically claim canonical paths before worker, self-check, or review execution. Keep a task's claim across retries and follow-up PLANs; release it only after verified archive completion.
|
|
- Treat explicit predecessors as unfinished while matching live execution evidence exists, even if a `complete.log` is already visible.
|
|
- Apply `max_parallel` across the physical workspace, independent of task-group filtering. Do not count internal helper coroutines as agent slots.
|
|
- A blocker delays only that task and its dependency closure. Continue draining independent work.
|
|
|
|
## Prompt and child boundary
|
|
|
|
Prefix worker and review prompts with the dispatcher-child boundary that prohibits starting or monitoring another orchestration loop. A child may use `dispatch.py --validate-plan` only when its plan or review finalization requires it.
|
|
|
|
Prompts must include absolute artifact paths and instruct the child to follow the repository's language and output rules. Do not hardcode a programming language, human language, agent, model, or provider in common prompts.
|
|
|
|
Never ask a child to create, edit, or summarize `WORK_LOG.md`; that file is dispatcher-owned.
|
|
|
|
## Self-check
|
|
|
|
Run self-check only when the selected catalog target declares `selfcheck_required=true`. The completing decision, not a fixed agent identity or execution class, determines the requirement.
|
|
|
|
Accept self-check completion only when `## Implementation Checklist` or its supported legacy heading contains at least one checkbox and every checkbox has a non-empty value. Run one full pass, then resume the latest successful native context for at most 10 unchecked-item retries when the target supports native resume. Block instead of silently starting a new context when a required persisted context is unavailable.
|
|
|
|
## Runtime evidence and recovery
|
|
|
|
- Store each attempt under the dispatcher state directory with `locator.json`, `stream.log`, `normalized-output.log`, and `heartbeat.log`.
|
|
- Record the target id, opaque agent/model identity, execution class, runtime contract, catalog evidence, process identity, workspace identity, timestamps, result, and exact failure evidence.
|
|
- Treat stderr as terminal diagnostic evidence. For JSONL, recognize generic terminal event fields such as error/fatal type or severity, rejected/failed status with an error code, and explicit error flags.
|
|
- Determine liveness from PID/start-token/process-marker evidence and actual stream or native-session progress. Heartbeat mtime is never agent progress.
|
|
- Never start a duplicate attempt while owned live evidence remains.
|
|
- Keep a 10-consecutive-failure budget per task stage. Reset only that stage's budget after success.
|
|
- Preserve failed attempt logs. Delete successful attempt logs only after verified archive completion and no live evidence.
|
|
|
|
## Work log
|
|
|
|
- Keep one dispatcher-owned `WORK_LOG.md` per task group.
|
|
- Append chronological `START` and `FINISH` rows with UTC time, task artifact, plan loop, role, attempt, selected agent/model display, result, and locator.
|
|
- Archive the group log as the next `work_log_N.log` only after every observed task in the group is verified complete and idle.
|
|
- Work-log write or archive failure is a retryable control-plane failure and prevents exit `0`.
|
|
|
|
## Invocation
|
|
|
|
```bash
|
|
python3 agent-ops/skills/common/orchestrate-agent-task-loop/scripts/dispatch.py \
|
|
--workspace /absolute/repository \
|
|
--dry-run
|
|
```
|
|
|
|
Remove `--dry-run` to start execution. Add `--execution-catalog <path>` only to override the bundled default. Add `--task-group <name>`, `--max-parallel <n>`, or `--retry-blocked` only when requested by the workflow.
|
|
|
|
Launch the live dispatcher as one persistent foreground process. Do not wrap it in an arbitrary timeout and do not start a second dispatcher after a normal tool yield. Wait on the same execution handle until an attention event or terminal exit.
|
|
|
|
## Completion checklist
|
|
|
|
- [ ] The resolved catalog was fully validated, preflighted, and revision-pinned.
|
|
- [ ] No hidden route outside the resolved catalog or quota probe was used.
|
|
- [ ] Runtime quota errors moved only to the next catalog candidate.
|
|
- [ ] Dependencies, write claims, and workspace concurrency were enforced.
|
|
- [ ] Required self-check and official review stages completed.
|
|
- [ ] Every observed task has a verified archived `complete.log`.
|
|
- [ ] Work logs and successful attempt cleanup were reconciled.
|
|
- [ ] No active, waiting, pending, or blocked in-scope task remains.
|
|
- [ ] Dispatcher exited `0` before successful final response.
|