Add orchestrator skill - long-running task automation framework#118
Add orchestrator skill - long-running task automation framework#118jshstorm wants to merge 1 commit intoopenclaw:mainfrom
Conversation
- Turn blocking operations into background daemons - Instant agent response (0.1s) + completion callbacks - Support for 4 worker types: shell, opencode, claude, python - Dependency DAG execution with parallel workers - Auto-judge with sub-agent delegation - JSONL file protocol for crash-safe communication - Tested with pilot (6 tasks) and stress (40 tasks) scenarios Features: - Context layers (L0-L3) for structured information flow - Task validation, retry, and timeout support - Dynamic task management (add/cancel mid-flight) - Independent daemon process (survives agent restarts) Author: Storm (@jshstorm)
|
Thanks for the pull request! This repository is read-only and is automatically synced from https://clawhub.ai, so we can’t accept changes here. Please make updates on the website instead. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2a340db95d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| task = Task( | ||
| id=t["id"], | ||
| name=t["name"], | ||
| worker=t.get("worker", "shell"), | ||
| command=t.get("command", ""), |
There was a problem hiding this comment.
Preserve per-task execution options from input
The loop creator rebuilds each task from a hardcoded subset of fields, so input options such as timeout, retry, validate, and on_fail are silently discarded and replaced by dataclass defaults in manifest.json. Any workflow that depends on non-default retry/timeout/validation behavior will execute with the wrong policy, which breaks core orchestrator behavior for real runs.
Useful? React with 👍 / 👎.
| ready = [] | ||
| for t in self.manifest.tasks: | ||
| if t.status != TaskStatus.PENDING.value: | ||
| continue | ||
| if all(dep in done_ids for dep in t.depends_on): |
There was a problem hiding this comment.
Propagate dependency failures instead of leaving tasks pending
Ready-task selection only treats dependencies as satisfied when upstream tasks are done, so if a prerequisite task fails or is cancelled, all dependents remain pending forever. Because terminal-state detection later requires every task to be done/cancelled/failed, these pending dependents can keep the loop running indefinitely without emitting completion.
Useful? React with 👍 / 👎.
| OutboxType.ERROR.value, | ||
| OutboxType.ALL_DONE.value, | ||
| ] | ||
| self._inbox_offset = 0 # 마지막으로 읽은 위치 |
There was a problem hiding this comment.
Persist inbox cursor across daemon restarts
The inbox read offset is kept only in memory and always initialized to 0, so restarting the loop process replays the entire historical inbox from the beginning. Previously handled commands like ADD_TASK or UPDATE_TASK are applied again after each restart, which can duplicate tasks or mutate state incorrectly.
Useful? React with 👍 / 👎.
| for task in self.manifest.tasks: | ||
| if task.status == TaskStatus.BLOCKED.value: | ||
| task.status = TaskStatus.PENDING.value | ||
| print(f"[Loop] Task {task.id} unblocked by decision {ref}") |
There was a problem hiding this comment.
Apply DECIDE messages only to the referenced task
The DECIDE handler ignores the incoming ref and unblocks every task currently in blocked state. In loops with multiple pending decisions, approving one item will incorrectly release unrelated blocked tasks, causing tasks to resume without the intended decision.
Useful? React with 👍 / 👎.
Turn blocking operations into background daemons with instant response.
Features: