| name | drive |
| description | Execute one livespec-orchestrator-beads-fabro action-id: impl:<id> dispatch, approve/accept/reject valves, or set-admission/set-acceptance policy edits. Invoke as livespec-orchestrator-beads-fabro:drive. |
drive - Codex binding
Thin Codex operator binding for the shared Python CLI.
Resolving the plugin root
PLUGIN_ROOT="${LIVESPEC_ORCH_PLUGIN_ROOT:-}"
PLUGIN_ROOT_DIAGNOSTICS=""
if [ -z "$PLUGIN_ROOT" ] && [ -d "./.claude-plugin/scripts/bin" ]; then
CANDIDATE_PLUGIN_ROOT="$(pwd)/.claude-plugin"
if [ -f "$CANDIDATE_PLUGIN_ROOT/plugin.json" ] && python3 - "$CANDIDATE_PLUGIN_ROOT/plugin.json" <<'PY'
import json
import sys
try:
with open(sys.argv[1], encoding="utf-8") as f:
data = json.load(f)
except Exception:
sys.exit(1)
sys.exit(0 if data.get("name") == "livespec-orchestrator-beads-fabro" else 1)
PY
then
PLUGIN_ROOT="$CANDIDATE_PLUGIN_ROOT"
fi
fi
if [ -z "$PLUGIN_ROOT" ]; then
CODEX_CACHE_PARENT="$HOME/.codex/plugins/cache/livespec-orchestrator-beads-fabro/livespec-orchestrator-beads-fabro"
if [ -d "$CODEX_CACHE_PARENT" ]; then
CANDIDATE_PLUGIN_ROOT="$(find "$CODEX_CACHE_PARENT" -mindepth 1 -maxdepth 1 -type d | sort -V | tail -n 1)"
if [ -n "$CANDIDATE_PLUGIN_ROOT" ] && [ -d "$CANDIDATE_PLUGIN_ROOT/scripts/bin" ]; then
PLUGIN_ROOT="$CANDIDATE_PLUGIN_ROOT"
else
PLUGIN_ROOT_DIAGNOSTICS="$PLUGIN_ROOT_DIAGNOSTICS
cache root not found: no valid version under $CODEX_CACHE_PARENT"
fi
else
PLUGIN_ROOT_DIAGNOSTICS="$PLUGIN_ROOT_DIAGNOSTICS
cache root not found: $CODEX_CACHE_PARENT"
fi
fi
if [ -z "$PLUGIN_ROOT" ]; then
CODEX_BIN=""
CODEX_TRIED="command -v codex, $HOME/.local/bin/codex, $HOME/.bun/bin/codex"
if command -v codex >/dev/null 2>&1; then
CODEX_BIN="$(command -v codex)"
elif [ -x "$HOME/.local/bin/codex" ]; then
CODEX_BIN="$HOME/.local/bin/codex"
elif [ -x "$HOME/.bun/bin/codex" ]; then
CODEX_BIN="$HOME/.bun/bin/codex"
else
PLUGIN_ROOT_DIAGNOSTICS="$PLUGIN_ROOT_DIAGNOSTICS
codex executable not found; tried: $CODEX_TRIED"
fi
if [ -n "$CODEX_BIN" ]; then
PLUGIN_ROOT="$("$CODEX_BIN" plugin list --json -m livespec-orchestrator-beads-fabro 2>/tmp/livespec-orchestrator-beads-fabro-codex-plugin-list.err | python3 -c 'import json, sys
try:
data = json.load(sys.stdin)
except Exception:
sys.exit(0)
for plugin in data.get("installed", []):
if plugin.get("pluginId") == "livespec-orchestrator-beads-fabro@livespec-orchestrator-beads-fabro":
sys.stdout.write(plugin.get("source", {}).get("path", ""))
break' 2>/dev/null || true)"
if [ -z "$PLUGIN_ROOT" ]; then
PLUGIN_ROOT_DIAGNOSTICS="$PLUGIN_ROOT_DIAGNOSTICS
plugin not installed according to: $CODEX_BIN plugin list --json -m livespec-orchestrator-beads-fabro"
if [ -s /tmp/livespec-orchestrator-beads-fabro-codex-plugin-list.err ]; then
PLUGIN_ROOT_DIAGNOSTICS="$PLUGIN_ROOT_DIAGNOSTICS
codex plugin list stderr: $(cat /tmp/livespec-orchestrator-beads-fabro-codex-plugin-list.err)"
fi
fi
fi
fi
if [ -z "$PLUGIN_ROOT" ] || [ ! -d "$PLUGIN_ROOT/scripts/bin" ]; then
echo "livespec-orchestrator-beads-fabro plugin root not found." >&2
if [ -n "$PLUGIN_ROOT_DIAGNOSTICS" ]; then
printf "%b\n" "$PLUGIN_ROOT_DIAGNOSTICS" >&2
fi
echo "Install it first:" >&2
echo " codex plugin marketplace add thewoolleyman/livespec-orchestrator-beads-fabro" >&2
echo " codex plugin add livespec-orchestrator-beads-fabro@livespec-orchestrator-beads-fabro" >&2
exit 1
fi
python3 "$PLUGIN_ROOT/scripts/bin/drive.py" "$@"
Command
--action <action-id> [--repo <path>] [--json] executes exactly one action-id. --repo defaults to the current working directory. --json emits the machine-readable result; Markdown is the default human output.
Accepted action ids:
impl:<work-item-id> dispatches the selected implementation work-item through Dispatcher/Fabro in shadow mode with budget=1, parallel=1, and --item <work-item-id>.
approve:<work-item-id> moves an effective-manual pending-approval item to ready.
accept:<work-item-id> moves an acceptance item to done.
reject:<work-item-id>:rework moves an acceptance item back to active.
reject:<work-item-id>:regroom reverts the recorded merge SHA, then moves an acceptance item to backlog.
set-admission:<work-item-id>:auto|manual updates admission policy without changing status.
set-acceptance:<work-item-id>:ai-only|human-only|ai-then-human updates acceptance policy without changing status.
drive does not plan, rank, compose spec-side and impl-side next, present an interactive walkthrough, execute spec-side indexed action ids, or create work-items. Spec lifecycle actions remain human handoffs outside this executor.