Add orch Codex launch bridge workflow
This commit is contained in:
+36
-2
@@ -33,6 +33,7 @@ Use the bundled `./assets/orch` CLI to control leader-side orchestration through
|
||||
- Prefer `--json` whenever another agent or script will read the output.
|
||||
- Initialize a new database path once through the bundled `inbox init` command before the first real run.
|
||||
- Use `status` as the main operational view. It reconciles worker thread state first, then returns run, task, latest-attempt, and latest-message context.
|
||||
- For Codex worker launch, standardize the handoff through `./assets/orch-worker-brief` instead of improvising the worker prompt every time.
|
||||
- Use this skill for leader-side scheduling and control-plane actions, not worker-side lease or progress updates.
|
||||
|
||||
## Rules
|
||||
@@ -56,6 +57,36 @@ Use the bundled `./assets/orch` CLI to control leader-side orchestration through
|
||||
5. Launch or reuse a separate worker runtime or worker agent that uses `skills/inbox/` against the same DB path.
|
||||
6. Use `status`, `wait`, `blocked`, `answer`, `retry`, `reassign`, and `cleanup` to operate the run until the required tasks are complete.
|
||||
|
||||
## Dispatch-And-Launch Workflow
|
||||
|
||||
Use this when the leader wants durable `orch` state plus a worker sub-agent launched from the current Codex thread.
|
||||
|
||||
1. save the dispatch output:
|
||||
|
||||
```bash
|
||||
./assets/orch --db ./coord.db --json dispatch --run RUN_ID --task TASK_ID > TMPDIR/dispatch.json
|
||||
```
|
||||
|
||||
2. render a standardized worker brief:
|
||||
|
||||
```bash
|
||||
./assets/orch-worker-brief --dispatch-json TMPDIR/dispatch.json --db ./coord.db > TMPDIR/worker-brief.txt
|
||||
```
|
||||
|
||||
3. spawn one worker sub-agent with:
|
||||
- `skills/inbox/`
|
||||
- the generated worker brief
|
||||
- the repo defaults from `AGENTS.md`
|
||||
- model `gpt-5.4`
|
||||
- reasoning effort `xhigh`
|
||||
- `fork_context: true` first
|
||||
4. keep the leader on `orch wait`, `orch status`, `orch blocked`, `orch answer`, `orch retry`, or `orch reassign`
|
||||
|
||||
See:
|
||||
|
||||
- `./references/leader-dispatch-and-launch-checklist.md`
|
||||
- `./references/worker-brief-template.md`
|
||||
|
||||
## Worker Handoff Contract
|
||||
|
||||
- The worker side should use `skills/inbox/`, not this skill.
|
||||
@@ -72,8 +103,10 @@ Use the bundled `./assets/orch` CLI to control leader-side orchestration through
|
||||
./assets/orch --db ./coord.db --json task add --run blog_mvp_001 --task T2 --title "Summarize flaky tests" --summary "Read logs and report next steps" --default-to qa-worker --acceptance-json '{"kind":"analysis"}'
|
||||
./assets/orch --db ./coord.db --json dep add --run blog_mvp_001 --task T2 --depends-on T1
|
||||
./assets/orch --db ./coord.db --json ready --run blog_mvp_001
|
||||
./assets/orch --db ./coord.db --json dispatch --run blog_mvp_001 --task T1 --to foundation-worker --base-ref main --workspace-root .orch/worktrees --strict-worktree --body-file tasks/t1.md
|
||||
./assets/orch --db ./coord.db --json dispatch --run blog_mvp_001 --task T2 --to qa-worker --body "Read the failing test logs and summarize the root cause."
|
||||
./assets/orch --db ./coord.db --json dispatch --run blog_mvp_001 --task T1 --to foundation-worker --base-ref main --workspace-root .orch/worktrees --strict-worktree --body-file tasks/t1.md > /tmp/t1-dispatch.json
|
||||
./assets/orch-worker-brief --dispatch-json /tmp/t1-dispatch.json --db ./coord.db > /tmp/t1-worker-brief.txt
|
||||
./assets/orch --db ./coord.db --json dispatch --run blog_mvp_001 --task T2 --to qa-worker --body "Read the failing test logs and summarize the root cause." > /tmp/t2-dispatch.json
|
||||
./assets/orch-worker-brief --dispatch-json /tmp/t2-dispatch.json --db ./coord.db > /tmp/t2-worker-brief.txt
|
||||
./assets/orch --db ./coord.db --json status --run blog_mvp_001
|
||||
./assets/orch --db ./coord.db --json wait --run blog_mvp_001 --for task_blocked,task_done,task_failed --after-event 0 --timeout-seconds 900
|
||||
./assets/orch --db ./coord.db --json blocked --run blog_mvp_001
|
||||
@@ -104,6 +137,7 @@ Use the bundled `./assets/orch` CLI to control leader-side orchestration through
|
||||
|
||||
- `dispatch` supports `--repo-path`, `--workspace-root`, `--strict-worktree`, and `--base-ref` for worktree-backed code execution.
|
||||
- When worktree flags are omitted, code-like task metadata can still auto-enable strict worktree mode. Non-code tasks stay on the normal thread-only path.
|
||||
- `./assets/orch-worker-brief` is the supported way to turn a saved dispatch JSON response into a stable worker prompt for a spawned sub-agent.
|
||||
- `answer` supports `--payload-json` for structured decisions, not just freeform text.
|
||||
- `status` is the full run view; `run show` is the lighter aggregate view.
|
||||
- If the bundled binary cannot execute on the current host, stop and report the compatibility issue instead of guessing a replacement path or workflow.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
interface:
|
||||
display_name: "Orch CLI"
|
||||
short_description: "Leader-side orchestration CLI"
|
||||
default_prompt: "Use $orch to manage leader-side orchestration runs through the bundled orch CLI and a SQLite orchestration database. Treat it as a control plane only: dispatch creates attempts and inbox threads, while separate workers consume them through inbox."
|
||||
default_prompt: "Use $orch to manage leader-side orchestration runs through the bundled orch CLI and a SQLite orchestration database. Treat it as a control plane only: dispatch creates attempts and inbox threads, while separate workers consume them through inbox. When you choose to launch a worker sub-agent from the current Codex thread, standardize the handoff with ./assets/orch-worker-brief and keep the worker on skills/inbox only."
|
||||
|
||||
policy:
|
||||
allow_implicit_invocation: true
|
||||
|
||||
Executable
+164
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
readonly DEFAULT_INBOX_SKILL_PATH="$(cd "${SCRIPT_DIR}/../../inbox" && pwd)"
|
||||
|
||||
dispatch_json=""
|
||||
db_path=""
|
||||
inbox_skill_path="${DEFAULT_INBOX_SKILL_PATH}"
|
||||
extra_instructions_file=""
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: orch-worker-brief --dispatch-json PATH --db PATH [--inbox-skill-path PATH] [--extra-instructions-file PATH]
|
||||
|
||||
Read an `orch dispatch --json` response and render a standardized worker prompt
|
||||
for a Codex sub-agent that should execute the assigned inbox thread.
|
||||
|
||||
Required:
|
||||
--dispatch-json PATH Path to the saved `orch dispatch --json` response
|
||||
--db PATH Shared SQLite DB path for both orch and inbox
|
||||
|
||||
Optional:
|
||||
--inbox-skill-path PATH Path to the inbox skill bundle. Defaults to the
|
||||
sibling project-local skill at skills/inbox
|
||||
--extra-instructions-file Append extra operator-specific instructions
|
||||
-h, --help Show this help text
|
||||
EOF
|
||||
}
|
||||
|
||||
require_command() {
|
||||
local cmd="$1"
|
||||
if ! command -v "${cmd}" >/dev/null 2>&1; then
|
||||
printf 'missing required command: %s\n' "${cmd}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--dispatch-json)
|
||||
dispatch_json="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--db)
|
||||
db_path="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--inbox-skill-path)
|
||||
inbox_skill_path="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--extra-instructions-file)
|
||||
extra_instructions_file="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
printf 'unknown argument: %s\n' "$1" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
require_command jq
|
||||
|
||||
if [ -z "${dispatch_json}" ] || [ -z "${db_path}" ]; then
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "${dispatch_json}" ]; then
|
||||
printf 'dispatch json not found: %s\n' "${dispatch_json}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "${extra_instructions_file}" ] && [ ! -f "${extra_instructions_file}" ]; then
|
||||
printf 'extra instructions file not found: %s\n' "${extra_instructions_file}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run_id="$(jq -r '.data.attempt.run_id // .data.task.run_id // empty' "${dispatch_json}")"
|
||||
task_id="$(jq -r '.data.attempt.task_id // .data.task.task_id // empty' "${dispatch_json}")"
|
||||
attempt_no="$(jq -r '.data.attempt.attempt_no // empty' "${dispatch_json}")"
|
||||
assigned_to="$(jq -r '.data.attempt.assigned_to // .data.task.default_to // empty' "${dispatch_json}")"
|
||||
thread_id="$(jq -r '.data.attempt.thread_id // .data.thread.thread_id // empty' "${dispatch_json}")"
|
||||
worktree_path="$(jq -r '.data.attempt.worktree_path // empty' "${dispatch_json}")"
|
||||
base_ref="$(jq -r '.data.attempt.base_ref // empty' "${dispatch_json}")"
|
||||
task_title="$(jq -r '.data.task.title // empty' "${dispatch_json}")"
|
||||
task_summary="$(jq -r '.data.task.summary // empty' "${dispatch_json}")"
|
||||
leader_body="$(jq -r '.data.message.body // empty' "${dispatch_json}")"
|
||||
|
||||
if [ -z "${run_id}" ] || [ -z "${task_id}" ] || [ -z "${assigned_to}" ] || [ -z "${thread_id}" ]; then
|
||||
printf 'dispatch json is missing one or more required fields: run_id, task_id, assigned_to, thread_id\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mode="analysis"
|
||||
if [ -n "${worktree_path}" ]; then
|
||||
mode="code"
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
Use \$inbox at ${inbox_skill_path} to act as ${assigned_to} on SQLite DB ${db_path}. Only coordinate through the bundled inbox CLI from the skill. Do not use ordinary chat to coordinate with the leader. Do not use orch.
|
||||
|
||||
You are assigned one existing attempt:
|
||||
- run_id: ${run_id}
|
||||
- task_id: ${task_id}
|
||||
- attempt_no: ${attempt_no}
|
||||
- assigned_to: ${assigned_to}
|
||||
- thread_id: ${thread_id}
|
||||
- execution_mode: ${mode}
|
||||
EOF
|
||||
|
||||
if [ -n "${task_title}" ]; then
|
||||
printf '%s\n' "- task_title: ${task_title}"
|
||||
fi
|
||||
if [ -n "${task_summary}" ]; then
|
||||
printf '%s\n' "- task_summary: ${task_summary}"
|
||||
fi
|
||||
if [ -n "${base_ref}" ]; then
|
||||
printf '%s\n' "- base_ref: ${base_ref}"
|
||||
fi
|
||||
if [ -n "${worktree_path}" ]; then
|
||||
printf '%s\n' "- worktree_path: ${worktree_path}"
|
||||
fi
|
||||
|
||||
cat <<'EOF'
|
||||
|
||||
Required workflow:
|
||||
1. Fetch or inspect the assigned thread and claim exactly the listed thread_id.
|
||||
2. Inspect the thread with show before making assumptions about the task body or payload.
|
||||
3. Send one in_progress update when real work starts.
|
||||
4. If blocked, send one precise blocked question with update --status blocked and then use wait-reply.
|
||||
5. Finish with done on success or fail on failure.
|
||||
6. Stop after reporting the handled thread_id and a concise outcome summary.
|
||||
|
||||
Rules:
|
||||
- Do not claim any other thread.
|
||||
- Keep all coordination in inbox messages, not ordinary chat.
|
||||
- Do not change the assigned_to, thread_id, or worktree assignment yourself.
|
||||
EOF
|
||||
|
||||
if [ -n "${worktree_path}" ]; then
|
||||
cat <<EOF
|
||||
- Perform repository work only inside ${worktree_path}.
|
||||
- Do not modify the leader's primary checkout outside the assigned worktree.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ -n "${leader_body}" ]; then
|
||||
printf '\nLeader dispatch body:\n%s\n' "${leader_body}"
|
||||
fi
|
||||
|
||||
if [ -n "${extra_instructions_file}" ]; then
|
||||
printf '\nExtra instructions:\n'
|
||||
cat "${extra_instructions_file}"
|
||||
printf '\n'
|
||||
fi
|
||||
@@ -0,0 +1,52 @@
|
||||
# Leader Dispatch-And-Launch Checklist
|
||||
|
||||
Use this checklist when the leader wants durable `orch` scheduling plus a Codex sub-agent worker.
|
||||
|
||||
## Goal
|
||||
|
||||
Keep `orch` as the control plane and use a leader-side bridge to launch a worker sub-agent only after `dispatch` succeeds.
|
||||
|
||||
## Recommended Flow
|
||||
|
||||
1. initialize the shared DB once through `skills/inbox/assets/inbox --db PATH --json init`
|
||||
2. create the run and tasks with `run init`, `task add`, and `dep add`
|
||||
3. find dispatchable work with `ready`
|
||||
4. save the dispatch response:
|
||||
|
||||
```bash
|
||||
./assets/orch --db ./coord.db --json dispatch --run RUN_ID --task TASK_ID > TMPDIR/dispatch.json
|
||||
```
|
||||
|
||||
5. render a standardized worker brief:
|
||||
|
||||
```bash
|
||||
./assets/orch-worker-brief --dispatch-json TMPDIR/dispatch.json --db ./coord.db > TMPDIR/worker-brief.txt
|
||||
```
|
||||
|
||||
6. spawn one worker sub-agent with:
|
||||
- injected `skills/inbox/`
|
||||
- the generated worker brief
|
||||
- the repository defaults from `AGENTS.md`
|
||||
- model: `gpt-5.4`
|
||||
- reasoning effort: `xhigh`
|
||||
- `fork_context: true` first
|
||||
7. while the worker runs, keep the leader on:
|
||||
- `orch wait`
|
||||
- `orch status`
|
||||
- `orch blocked`
|
||||
- `orch answer`
|
||||
- `orch retry`
|
||||
- `orch reassign`
|
||||
|
||||
## Worker Launch Rules
|
||||
|
||||
- the worker should use `skills/inbox/`, not `skills/orch/`
|
||||
- the worker should claim only the exact `thread_id` from the dispatch result
|
||||
- if `worktree_path` exists, the worker should do all repository writes only inside that worktree
|
||||
- the worker should send progress, blocked questions, success, and failure through `inbox`
|
||||
|
||||
## Why This Layer Exists
|
||||
|
||||
- `orch` remains portable and durable
|
||||
- worker launch stays outside the core CLI
|
||||
- the same dispatch contract can later support Codex sub-agents, `codex exec`, daemons, or operator UI launchers
|
||||
@@ -0,0 +1,41 @@
|
||||
# Worker Brief Template
|
||||
|
||||
`assets/orch-worker-brief` renders a concrete prompt in this shape.
|
||||
|
||||
Use it when a leader has already dispatched a task and now wants to launch a worker sub-agent without hand-writing the thread handoff every time.
|
||||
|
||||
```text
|
||||
Use $inbox at INBOX_SKILL_PATH to act as ASSIGNED_TO on SQLite DB DB_PATH. Only coordinate through the bundled inbox CLI from the skill. Do not use ordinary chat to coordinate with the leader. Do not use orch.
|
||||
|
||||
You are assigned one existing attempt:
|
||||
- run_id: RUN_ID
|
||||
- task_id: TASK_ID
|
||||
- attempt_no: ATTEMPT_NO
|
||||
- assigned_to: ASSIGNED_TO
|
||||
- thread_id: THREAD_ID
|
||||
- execution_mode: analysis|code
|
||||
- task_title: ...
|
||||
- task_summary: ...
|
||||
- base_ref: ...
|
||||
- worktree_path: ...
|
||||
|
||||
Required workflow:
|
||||
1. Fetch or inspect the assigned thread and claim exactly the listed thread_id.
|
||||
2. Inspect the thread with show before making assumptions about the task body or payload.
|
||||
3. Send one in_progress update when real work starts.
|
||||
4. If blocked, send one precise blocked question with update --status blocked and then use wait-reply.
|
||||
5. Finish with done on success or fail on failure.
|
||||
6. Stop after reporting the handled thread_id and a concise outcome summary.
|
||||
|
||||
Rules:
|
||||
- Do not claim any other thread.
|
||||
- Keep all coordination in inbox messages, not ordinary chat.
|
||||
- Do not change the assigned_to, thread_id, or worktree assignment yourself.
|
||||
- If worktree_path exists, perform repository work only inside that path.
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The template is intentionally worker-only. Leader control stays with `orch`.
|
||||
- The generated brief should be passed into a spawned worker sub-agent together with `skills/inbox/`.
|
||||
- Keep the main-thread launch parameters in the leader workflow, not in the worker brief.
|
||||
Reference in New Issue
Block a user