174 lines
5.5 KiB
Bash
Executable File
174 lines
5.5 KiB
Bash
Executable File
#!/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}")"
|
|
execution_mode="$(jq -r '.data.message.payload_json.execution_mode // 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
|
|
|
|
if [ "${execution_mode}" != "analysis" ] && [ "${execution_mode}" != "code" ]; then
|
|
printf 'dispatch json is missing a supported execution_mode in message.payload_json\n' >&2
|
|
exit 1
|
|
fi
|
|
if [ "${execution_mode}" = "code" ] && [ -z "${worktree_path}" ]; then
|
|
printf 'dispatch json is inconsistent: execution_mode=code requires a worktree_path\n' >&2
|
|
exit 1
|
|
fi
|
|
if [ "${execution_mode}" = "analysis" ] && [ -n "${worktree_path}" ]; then
|
|
printf 'dispatch json is inconsistent: execution_mode=analysis must not include a worktree_path\n' >&2
|
|
exit 1
|
|
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: ${execution_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
|