#!/usr/bin/env bash # # create-task-worktree.sh # # Create or reuse a git worktree for a specific task branch under agentydragon/tasks/.worktrees. # Usage: create-task-worktree.sh [-a|--agent] [-t|--tmux] [...] set -euo pipefail agent_mode=false tmux_mode=false interactive_mode=false shell_mode=false while [[ $# -gt 0 ]]; do case "$1" in -a|--agent) agent_mode=true shift ;; -t|--tmux) tmux_mode=true shift ;; -h|--help) cat << EOF Usage: $0 [-a|--agent] [-s|--shell] [-i|--interactive] [-t|--tmux] [...] Options: -a, --agent create/reuse worktree, run pre-commit checks (aborting on failure), and launch a Codex agent with prompt injection; when the agent exits, auto-run commit helper -s, --shell create/reuse worktree and launch an interactive Codex shell (no prompt injection, skip auto-commit) -i, --interactive run the agent in interactive mode (no 'exec'); implies --agent -t, --tmux open each task in its own tmux window; implies --agent -h, --help show this help message and exit EOF exit 0 ;; -i|--interactive) interactive_mode=true agent_mode=true shift ;; -s|--shell) # Launch agent in an interactive shell (no prompt injection, no auto-commit) shell_mode=true agent_mode=true shift ;; *) break ;; esac done # Validate number of task arguments based on mode if [ "$tmux_mode" = true ]; then if [ "$#" -lt 1 ]; then echo "Usage: $0 [-a|--agent] [-t|--tmux] - [...]" exit 1 fi else if [ "$#" -ne 1 ]; then echo "Usage: $0 [-a|--agent] [-t|--tmux] - [...]" exit 1 fi fi # Capture raw input so we can accept just a two-digit task ID task_inputs=("$@") # If tmux mode, batch-create worktrees and launch in tmux if [ "$tmux_mode" = true ]; then # Implicitly enable agent mode in tmux panes agent_mode=true # Build a unique session name from task IDs session="agentydragon-${task_inputs[*]// /_}" cmd="$0" # First pane: first task first="${task_inputs[0]}" pane_cmd="$cmd${agent_mode:+ -a} $first" tmux new-session -d -s "$session" "$pane_cmd" # Open each additional task in its own tmux window for task in "${task_inputs[@]:1}"; do tmux new-window -t "$session" "$cmd${agent_mode:+ -a} $task" done tmux attach -t "$session" exit 0 fi task_input="${task_inputs[0]}" # Determine repository root and tasks directory repo_root=$(git rev-parse --show-toplevel) tasks_dir="$repo_root/agentydragon/tasks" # If given only a two-digit ID, resolve to the full task slug if [[ "$task_input" =~ ^[0-9]{2}$ ]]; then matches=( "$tasks_dir/${task_input}-"*.md ) if [ "${#matches[@]}" -eq 1 ]; then task_slug="$(basename "${matches[0]}" .md)" echo "Resolved task ID '$task_input' to slug '$task_slug'" else echo "Error: expected exactly one task file matching '${task_input}-*.md', found ${#matches[@]}" >&2 exit 1 fi else task_slug="$task_input" fi # Use dash-separated branch name to avoid ref-dir conflicts branch="agentydragon-$task_slug" worktrees_dir="$tasks_dir/.worktrees" worktree_path="$worktrees_dir/$task_slug" mkdir -p "$worktrees_dir" # Create branch if it does not exist if ! git show-ref --verify --quiet "refs/heads/$branch"; then echo "Creating branch $branch from agentydragon branch..." git branch --track "$branch" agentydragon fi # Create worktree if it does not exist if [ ! -d "$worktree_path" ]; then echo "Creating worktree for $branch at $worktree_path" git worktree add "$worktree_path" "$branch" # Install pre-commit hooks in the new worktree if pre-commit is available if command -v pre-commit >/dev/null 2>&1; then (cd "$worktree_path" && pre-commit install) else echo "Warning: pre-commit not found; skipping hook install in $worktree_path" fi else echo "Worktree for $branch already exists at $worktree_path" fi echo "Done." if [ "$agent_mode" = true ]; then echo "Launching Developer Codex agent for task $task_slug in sandboxed worktree" cd "${worktree_path}" # Before launching the developer agent, run pre-commit checks and abort if hooks fail if command -v pre-commit >/dev/null 2>&1; then echo "Running pre-commit checks in $(pwd)" if ! pre-commit run --all-files; then echo "Error: pre-commit checks failed. Fix issues before launching the developer agent." >&2 exit 1 fi else echo "Warning: pre-commit is not installed; skipping pre-commit checks." >&2 fi echo "Launching Developer Codex agent for task $task_slug in sandboxed worktree" if [ "$shell_mode" = true ]; then # Interactive shell mode: no prompt, skip commit helper cmd=(codex --full-auto) echo "${cmd[*]}" exec "${cmd[@]}" fi prompt_file="$repo_root/agentydragon/prompts/developer.md" task_file="$repo_root/agentydragon/tasks/$task_slug.md" if [ ! -f "$prompt_file" ]; then echo "Error: developer prompt file not found at $prompt_file" >&2 exit 1 fi # Launch the agent under Landlock+seccomp sandbox: writable only in cwd and TMPDIR, network disabled cmd=(codex --full-auto) if [ "${interactive_mode:-}" != true ]; then cmd+=(exec) fi echo "${cmd[*]}" # Run Developer agent (non-interactive by default) to implement the task "${cmd[@]}" "$(<"$prompt_file")"$'\n\n'"$(<"$task_file")" # After the Developer agent exits, stage and commit via the Commit agent helper echo "Running Commit agent to finalize task $task_slug" "$repo_root/agentydragon/tools/launch-commit-agent.sh" "$task_slug" fi