#!/usr/bin/env zsh

# Standalone plan-build launcher. This file is intentionally sourceable so its
# command seams can be replaced by the test suite.

_plan_build_usage() {
  print -r -- "Usage: plan_build [--yolo] [--prompt]
       plan_build --architect [--new] [--yolo]"
}

_plan_build_require_cli() {
  local binary="$1"
  local label="$2"
  local resolved

  resolved="$(command -v "$binary" 2>/dev/null)" || resolved=""
  if [[ -n "$resolved" && -x "$resolved" ]]; then
    return 0
  fi

  print -u2 -r -- "Error: ${label} ('${binary}') is not installed or not in your PATH."
  return 1
}

_plan_build_confirm_indexing() {
  local project_root="$1"
  local reply

  if ! (: </dev/tty) 2>/dev/null; then
    print -u2 -r -- "Notice: No interactive terminal available; enhancing without project indexing."
    return 1
  fi

  printf "Allow Auggie to index and use project context from '%s'? (y/N) " "$project_root" >/dev/tty
  if ! IFS= read -r reply </dev/tty; then
    print -u2 -r -- "\nNotice: Unable to read confirmation; enhancing without project indexing."
    return 1
  fi

  [[ "$reply" == (y|Y|yes|YES|Yes) ]]
}

_plan_build_parse_auggie_output() {
  local log_file="$1"
  local output_file="$2"

  perl -ne '
    s/\r$//;
    s/.*\r//;
    1 while s/[^\x08]\x08//g;
    s/\x08//g;
    s/\e\][^\a]*(?:\a|\e\\)//g;
    s/\e\[[0-?]*[ -\/]*[@-~]//g;
    next if /Script started on/ || /Script done on/;
    if (/^(?:✨\s*)?Enhanced prompt:\s*(.*)$/) {
      $capturing = 1;
      $output .= "$1\n" if length $1;
      next;
    }
    next unless $capturing;
    exit if /^🤖/ || /Tool call:/ || /Session terminated/;
    $output .= $_;
    END {
      $output =~ s/^\s*\n//;
      $output =~ s/\s+\z//;
      print "$output\n" if length $output;
    }
  ' "$log_file" >| "$output_file"
}

_plan_build_platform() {
  command uname -s
}

_plan_build_start_auggie_script() {
  local platform="$1" log_file="$2" workspace="$3" cache_dir="$4"
  local auth_file="$5" prompt_file="$6" use_project_context="$7"
  shift 7

  if [[ "$platform" == Darwin ]]; then
    command script -q -t 0 "$log_file" auggie "$@" </dev/null >/dev/null 2>&1 &
  else
    AUGGIE_WORKSPACE="$workspace" AUGGIE_CACHE_DIR="$cache_dir" \
    AUGGIE_AUTH_FILE="$auth_file" AUGGIE_PROMPT_FILE="$prompt_file" \
    AUGGIE_INDEXING="$use_project_context" \
      command script -q -f -e -O "$log_file" -c '
        if [ "$AUGGIE_INDEXING" = 1 ]; then
          exec auggie --print --enhance-prompt --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --allow-indexing --wait-for-indexing --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"
        else
          exec auggie --print --enhance-prompt --no-discover-workspaces --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"
        fi
      ' </dev/null >/dev/null 2>&1 &
  fi
  REPLY=$!
}

_plan_build_enhance_prompt() {
  emulate -L zsh
  setopt localtraps
  local prompt="$1"
  local output_file="$2"
  local run_dir prompt_file workspace cache_dir auth_file log_file parsed_file
  local project_root use_project_context timeout_seconds script_pid= waited child_status=0
  local -a auggie_args

  trap 'return 130' INT
  trap 'return 143' TERM
  trap 'return 129' HUP

  if [[ -z "$prompt" ]]; then
    print -u2 -r -- "Error: Prompt was empty."
    return 1
  fi
  if [[ ! -s "$HOME/.augment/session.json" ]]; then
    print -u2 -r -- "Error: Auggie session file not found. Run 'auggie login' first."
    return 1
  fi

  run_dir="$(mktemp -d "${TMPDIR:-/tmp}/plan-build-auggie.XXXXXX")" || return 1
  trap "rm -rf -- ${(q)run_dir}" EXIT
  prompt_file="$run_dir/prompt.txt"
  workspace="$run_dir/workspace"
  cache_dir="$run_dir/cache"
  auth_file="$HOME/.augment/session.json"
  log_file="$run_dir/auggie.log"
  parsed_file="$run_dir/enhanced.txt"
  mkdir -p "$workspace" "$cache_dir" || {
    return 1
  }
  print -r -- "$prompt" >| "$prompt_file" || return 1

  project_root="$(command git rev-parse --show-toplevel 2>/dev/null)" || project_root="$PWD"
  use_project_context=0
  timeout_seconds=90
  if _plan_build_confirm_indexing "$project_root"; then
    use_project_context=1
    timeout_seconds=300
    workspace="$project_root"
    cache_dir="$HOME/.augment"
    print -u2 -r -- "Indexing approved; enhancing with project context from '${project_root}'."
  else
    print -u2 -r -- "Enhancing without project indexing."
  fi

  auggie_args=(--print --enhance-prompt --workspace-root "$workspace"
    --augment-cache-dir "$cache_dir" --augment-session-json "$auth_file"
    --dont-save-session --instruction-file "$prompt_file")
  if (( use_project_context )); then
    auggie_args+=(--allow-indexing --wait-for-indexing)
  else
    auggie_args+=(--no-discover-workspaces)
  fi

  _plan_build_start_auggie_script "$(_plan_build_platform)" "$log_file" \
    "$workspace" "$cache_dir" "$auth_file" "$prompt_file" \
    "$use_project_context" "${auggie_args[@]}" || return 1
  script_pid="$REPLY"
  trap "kill ${(q)script_pid} >/dev/null 2>&1
        wait ${(q)script_pid} >/dev/null 2>&1
        rm -rf -- ${(q)run_dir}" EXIT
  waited=0
  while kill -0 "$script_pid" >/dev/null 2>&1; do
    if command grep -aq "🤖" "$log_file" 2>/dev/null ||
       command grep -aq "Tool call:" "$log_file" 2>/dev/null; then
      kill "$script_pid" >/dev/null 2>&1 || true
      wait "$script_pid" >/dev/null 2>&1 || true
      script_pid=
      trap "rm -rf -- ${(q)run_dir}" EXIT
      child_status=0
      break
    fi
    if (( waited >= timeout_seconds )); then
      kill "$script_pid" >/dev/null 2>&1 || true
      wait "$script_pid" >/dev/null 2>&1 || true
      script_pid=
      trap "rm -rf -- ${(q)run_dir}" EXIT
      print -u2 -r -- "Error: Timed out waiting for Auggie to enhance the prompt."
      return 124
    fi
    sleep 1
    waited=$((waited + 1))
  done
  if [[ -n "$script_pid" ]]; then
    wait "$script_pid"
    child_status=$?
    script_pid=
    trap "rm -rf -- ${(q)run_dir}" EXIT
  fi
  if (( child_status != 0 )); then
    print -u2 -r -- "Error: Auggie process failed with status ${child_status}."
    return "$child_status"
  fi

  _plan_build_parse_auggie_output "$log_file" "$parsed_file"
  if [[ ! -s "$parsed_file" ]]; then
    print -u2 -r -- "Error: Auggie did not return an enhanced prompt."
    return 1
  fi
  command cp "$parsed_file" "$output_file" || {
    print -u2 -r -- "Error: Unable to save the enhanced prompt."
    return 1
  }
}

_plan_build_confirm_enhanced_prompt() {
  local reply

  if ! (: </dev/tty) 2>/dev/null; then
    print -r -- "❌ Error: Cannot review the enhanced prompt without an interactive terminal; Claude was not launched."
    return 2
  fi
  printf "Proceed with this enhanced prompt? (y/N) " >/dev/tty
  if ! IFS= read -r reply </dev/tty; then
    printf '\n' >/dev/tty
    print -r -- "🛑 Review cancelled; Claude was not launched."
    return 2
  fi
  [[ "$reply" == (y|Y|yes|YES|Yes) ]]
}

_plan_build_claude_plugin_state() {
  local plugin_id="$1"
  awk -v plugin_id="$plugin_id" '
    $0 ~ plugin_id {
      found = 1
      next
    }
    found && /Status:/ {
      if ($0 ~ /enabled/) print "enabled"
      else print "disabled"
      printed = 1
      exit
    }
    found && /❯/ {
      print "installed"
      printed = 1
      exit
    }
    END { if (!printed) print found ? "installed" : "missing" }
  '
}

_plan_build_safe_mode_preflight() {
  case "${CLAUDE_CODE_SAFE_MODE:-}" in
    1|true|TRUE|yes|YES|on|ON)
      print -r -- "Error: Claude Code safe mode disables the Matt Pocock and AgentMemory plugins."
      print -r -- "Unset CLAUDE_CODE_SAFE_MODE before using plan_build."
      return 1
      ;;
  esac
}

_plan_build_matt_preflight() {
  local plugin_json plugin_state

  if ! plugin_json="$(command claude plugin list 2>/dev/null)"; then
    print -r -- "Error: Unable to inspect Claude Code plugins."
    print -r -- "Run 'claude plugin list' to diagnose the problem."
    return 1
  fi
  plugin_state="$(print -r -- "$plugin_json" | _plan_build_claude_plugin_state \
    "mattpocock-skills@mattpocock")"
  case "$plugin_state" in
    enabled) return 0 ;;
    disabled)
      print -r -- "Error: Matt Pocock skills are installed in Claude Code but disabled."
      print -r -- "Enable the mattpocock-skills@mattpocock plugin, then retry."
      ;;
    missing)
      print -r -- "Error: Matt Pocock skills are required for the default workflow."
      print -r -- "Install the mattpocock-skills@mattpocock Claude Code plugin, then retry."
      ;;
    *)
      print -r -- "Error: Unable to determine Matt Pocock plugin status."
      print -r -- "Run 'claude plugin list' to diagnose the problem."
      ;;
  esac
  return 1
}

_plan_build_agentmemory_health() {
  local pid exit_status waited=0
  command -v agentmemory >/dev/null 2>&1 || return 2
  command agentmemory status >/dev/null 2>&1 &
  pid=$!
  while kill -0 "$pid" >/dev/null 2>&1; do
    if (( waited >= 10 )); then
      kill "$pid" >/dev/null 2>&1 || true
      wait "$pid" >/dev/null 2>&1 || true
      return 124
    fi
    sleep 1
    waited=$((waited + 1))
  done
  wait "$pid"
  exit_status=$?
  return "$exit_status"
}

_plan_build_claude_agentmemory_state() {
  local plugin_json
  plugin_json="$(command claude plugin list 2>/dev/null)" || return 1
  print -r -- "$plugin_json" | _plan_build_claude_plugin_state \
    "agentmemory@agentmemory"
}

_plan_build_codex_agentmemory_state() {
  local plugin_list
  plugin_list="$(command codex plugin list 2>/dev/null)" || return 1
  print -r -- "$plugin_list" | _plan_build_codex_plugin_state
}

_plan_build_codex_plugin_state() {
  awk '
    $1 == "agentmemory@agentmemory" {
      if ($0 ~ /installed, enabled/) print "enabled"
      else print "disabled"
      found = 1
      exit
    }
    END { if (!found) print "missing" }
  '
}

_plan_build_agentmemory_check() {
  local claude_state codex_state failed=0 health_status

  _plan_build_agentmemory_health
  health_status=$?
  case "$health_status" in
    0) ;;
    2)
      print -r -- "AgentMemory CLI is not installed or not in PATH."
      print -r -- "Install @agentmemory/agentmemory, then retry."
      failed=1
      ;;
    124)
      print -r -- "AgentMemory status check timed out after 10 seconds."
      failed=1
      ;;
    *)
      print -r -- "AgentMemory server is unavailable."
      failed=1
      ;;
  esac
  claude_state="$(_plan_build_claude_agentmemory_state)" || claude_state="unknown"
  if [[ "$claude_state" != enabled ]]; then
    print -r -- "Claude Code AgentMemory plugin state: $claude_state."
    failed=1
  fi
  codex_state="$(_plan_build_codex_agentmemory_state)" || codex_state="unknown"
  if [[ "$codex_state" != enabled ]]; then
    print -r -- "Codex AgentMemory plugin state: $codex_state."
    failed=1
  fi

  (( failed == 0 ))
}

_plan_build_confirm_memory_action() {
  local reply

  if ! _plan_build_has_tty; then
    print -r -- "Error: AgentMemory preflight failed without an interactive terminal."
    return 1
  fi
  printf "AgentMemory preflight failed. [r]etry, [c]ontinue without memory, or [s]top? " >/dev/tty
  if ! IFS= read -r reply </dev/tty; then
    return 1
  fi
  _plan_build_memory_action_from_reply "$reply"
}

_plan_build_memory_action_from_reply() {
  local reply="$1"
  case "$reply" in
    r|R|retry|Retry|RETRY) return 2 ;;
    c|C|continue|Continue|CONTINUE) return 0 ;;
    *) return 1 ;;
  esac
}

_plan_build_agentmemory_preflight() {
  local action_status

  while ! _plan_build_agentmemory_check; do
    _plan_build_confirm_memory_action
    action_status=$?
    if (( action_status == 2 )); then
      continue
    elif (( action_status == 0 )); then
      print -r -- "Warning: Continuing in explicitly approved memoryless mode."
      REPLY="degraded"
      return 0
    fi
    print -r -- "Memory preflight was not approved; Claude was not launched."
    return 1
  done
  REPLY="required"
}

_plan_build_project_root() {
  command git rev-parse --show-toplevel 2>/dev/null
}

_plan_build_project_id_is_valid() {
  [[ "$1" =~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{1,127}$' ]]
}

_plan_build_default_project_id() {
  local root="$1" remote is_url=0
  remote="$(command git -C "$root" remote get-url origin 2>/dev/null)" || return 1
  [[ "$remote" == *://* ]] && is_url=1
  remote="${remote#*://}"
  remote="${remote#*@}"
  if (( ! is_url )) && [[ "$remote" == *:* ]]; then
    remote="${remote%%:*}/${remote#*:}"
  fi
  remote="${remote%.git}"
  [[ -n "$remote" ]] || return 1
  print -r -- "$remote"
}

_plan_build_initialize_project_id() {
  local root="$1" candidate reply

  if ! _plan_build_has_tty; then
    print -r -- "Error: Missing $root/.agentmemory-project and no interactive terminal is available."
    return 1
  fi
  candidate="$(_plan_build_default_project_id "$root")" || candidate=""
  if [[ -n "$candidate" ]] && ! _plan_build_project_id_is_valid "$candidate"; then
    candidate=""
  fi
  if [[ -n "$candidate" ]]; then
    printf "Create .agentmemory-project with ID '%s'? (Y/n) " "$candidate" >/dev/tty
    if ! IFS= read -r reply </dev/tty; then
      return 1
    fi
    case "$reply" in
      n|N|no|No|NO) candidate="" ;;
    esac
  fi
  if [[ -z "$candidate" ]]; then
    printf "Enter a stable AgentMemory project ID: " >/dev/tty
    if ! IFS= read -r candidate </dev/tty; then
      return 1
    fi
  fi
  if ! _plan_build_project_id_is_valid "$candidate"; then
    print -r -- "Error: Project ID must be 2-128 characters using letters, numbers, '.', '_', ':', '/', or '-'."
    return 1
  fi
  print -r -- "$candidate" >| "$root/.agentmemory-project" || return 1
  print -r -- "Created $root/.agentmemory-project. Commit it, then rerun plan_build."
  return 1
}

_plan_build_resolve_project_id() {
  local root project_file project_id committed_id
  root="$(_plan_build_project_root)" || return 1
  project_file="$root/.agentmemory-project"
  if [[ ! -e "$project_file" ]]; then
    _plan_build_initialize_project_id "$root"
    return $?
  fi
  if [[ ! -f "$project_file" || ! -r "$project_file" ]]; then
    print -r -- "Error: AgentMemory project ID file is not a readable regular file: $project_file"
    return 1
  fi
  project_id="$(<"$project_file")"
  if ! _plan_build_project_id_is_valid "$project_id"; then
    print -r -- "Error: Invalid AgentMemory project ID in $project_file"
    return 1
  fi
  committed_id="$(command git -C "$root" show HEAD:.agentmemory-project 2>/dev/null)" || {
    print -r -- "Error: .agentmemory-project must be committed before plan_build can use it."
    return 1
  }
  if [[ "$project_id" != "$committed_id" ]]; then
    print -r -- "Error: Working-tree .agentmemory-project differs from the committed identity."
    return 1
  fi
  REPLY="$project_id"
}

_plan_build_is_worktree() {
  local inside_work_tree
  inside_work_tree="$(command git rev-parse --is-inside-work-tree 2>/dev/null)" || return 1
  [[ "$inside_work_tree" == true ]]
}

_plan_build_has_tty() {
  (: </dev/tty) 2>/dev/null
}

_plan_build_common_preflight() {
  local skill_path="$1" require_matt="$2"

  if ! _plan_build_has_tty; then
    print -r -- "Error: plan_build requires an interactive terminal."
    return 1
  fi
  _plan_build_require_cli claude "Claude Code CLI" || return 1
  _plan_build_require_cli codex "Codex CLI" || return 1
  _plan_build_require_cli coderabbit "CodeRabbit CLI" || return 1
  _plan_build_require_cli git "Git CLI" || return 1
  if ! _plan_build_is_worktree; then
    print -r -- "Error: plan_build must run inside a Git worktree."
    print -r -- "Change to a checked-out Git worktree, then retry."
    return 1
  fi
  if [[ ! -r "$skill_path" || ! -s "$skill_path" ]]; then
    print -r -- "Error: Workflow skill is missing, unreadable, or empty: $skill_path"
    return 1
  fi
  _plan_build_safe_mode_preflight || return 1
  if (( require_matt )); then
    _plan_build_matt_preflight || return 1
  fi
}

_plan_build_launch_claude() {
  local use_yolo="$1" project_id="$2" memory_mode="$3"
  local inject_context="true"
  shift 3
  [[ "$memory_mode" == degraded ]] && inject_context="false"
  if (( use_yolo )); then
    AGENTMEMORY_PROJECT_NAME="$project_id" AGENTMEMORY_INJECT_CONTEXT="$inject_context" \
    PLAN_BUILD_MEMORY_MODE="$memory_mode" \
      command claude --dangerously-skip-permissions "$@"
  else
    AGENTMEMORY_PROJECT_NAME="$project_id" AGENTMEMORY_INJECT_CONTEXT="$inject_context" \
    PLAN_BUILD_MEMORY_MODE="$memory_mode" command claude "$@"
  fi
}

_plan_build_read_payload() {
  local line payload=""
  while IFS= read -r line; do
    [[ "$line" == EOF ]] && break
    if [[ -z "$payload" ]]; then
      payload="$line"
    else
      payload+=$'\n'"$line"
    fi
  done
  print -r -- "$payload"
}

plan_build() {
  emulate -L zsh
  setopt localtraps
  local use_yolo=0 use_architect=0 use_new=0 enhance_payload=0
  local payload enhanced_file= confirm_status enhance_status architect_start_mode
  local project_id memory_mode
  local standard_skill="${PLAN_BUILD_SKILL_PATH:-$HOME/.claude/skills/plan-build/SKILL.md}"
  local architect_skill="${PLAN_BUILD_ARCHITECT_SKILL_PATH:-$HOME/.claude/skills/plan-build-architect/SKILL.md}"

  trap 'return 130' INT
  trap 'return 143' TERM
  trap 'return 129' HUP

  while (( $# )); do
    case "$1" in
      --yolo)
        (( use_yolo )) && {
          print -r -- "Error: Duplicate argument: --yolo"
          _plan_build_usage
          return 1
        }
        use_yolo=1
        ;;
      --architect)
        (( use_architect )) && {
          print -r -- "Error: Duplicate argument: --architect"
          _plan_build_usage
          return 1
        }
        use_architect=1
        ;;
      --new)
        (( use_new )) && {
          print -r -- "Error: Duplicate argument: --new"
          _plan_build_usage
          return 1
        }
        use_new=1
        ;;
      --prompt)
        (( enhance_payload )) && {
          print -r -- "Error: Duplicate argument: --prompt"
          _plan_build_usage
          return 1
        }
        enhance_payload=1
        ;;
      *)
        print -r -- "Error: Unknown argument: $1"
        _plan_build_usage
        return 1
        ;;
    esac
    shift
  done

  if (( use_new && ! use_architect )); then
    print -r -- "Error: --new requires --architect."
    _plan_build_usage
    return 1
  fi
  if (( use_architect && enhance_payload )); then
    print -r -- "Error: --architect may combine only with --new and --yolo."
    _plan_build_usage
    return 1
  fi

  if (( use_architect )); then
    _plan_build_common_preflight "$architect_skill" 0 || return 1
  else
    _plan_build_common_preflight "$standard_skill" 1 || return 1
    if (( enhance_payload )); then
      _plan_build_require_cli auggie "Auggie CLI" || return 1
      _plan_build_require_cli script "script utility" || return 1
      _plan_build_require_cli perl "Perl" || return 1
    fi
  fi
  _plan_build_resolve_project_id || return 1
  project_id="$REPLY"
  _plan_build_agentmemory_preflight || return 1
  memory_mode="$REPLY"

  print -r -- "📥 Reading payload... Type 'EOF' on a new line and press Enter when finished."
  payload="$(_plan_build_read_payload)"
  if [[ -z "$payload" ]]; then
    print -r -- "❌ Error: Payload was empty."
    return 1
  fi

  if (( enhance_payload )); then
    enhanced_file="$(mktemp "${TMPDIR:-/tmp}/plan-build-enhanced.XXXXXX")" || return 1
    trap "rm -f -- ${(q)enhanced_file}" EXIT
    print -r -- "✨ Enhancing payload with Auggie..."
    _plan_build_enhance_prompt "$payload" "$enhanced_file"
    enhance_status=$?
    if (( enhance_status != 0 )); then
      print -r -- "❌ Error: Prompt enhancement failed; Claude was not launched."
      return "$enhance_status"
    fi
    payload="$(<"$enhanced_file")"
    rm -f -- "$enhanced_file"
    enhanced_file=
    trap - EXIT
    if [[ -z "$payload" ]]; then
      print -r -- "❌ Error: Enhanced payload was empty; Claude was not launched."
      return 1
    fi
    printf '\n%s\n%s\n%s\n\n' \
      "━━━━━━━━━━━━━━━━ Auggie enhanced prompt ━━━━━━━━━━━━━━━━" \
      "$payload" \
      "━━━━━━━━━━━━━━━━ End enhanced prompt ━━━━━━━━━━━━━━━━━"
    _plan_build_confirm_enhanced_prompt
    confirm_status=$?
    if (( confirm_status == 2 )); then
      return 1
    elif (( confirm_status != 0 )); then
      print -r -- "🛑 Enhanced prompt not approved; Claude was not launched."
      return 0
    fi
    print -r -- "✅ Enhanced prompt approved."
  fi

  if (( use_architect )); then
    if (( use_new )); then
      architect_start_mode="Start mode: archive-and-start-new. Explicitly archive the prior planning state as the skill directs, then begin a new architecture plan."
    else
      architect_start_mode="Start mode: safe-resume-detection. Safely detect whether an existing architecture planning session should be resumed; do not archive or replace it automatically."
    fi
    print -r -- "🚀 Launching Claude Code in architect mode..."
    _plan_build_launch_claude "$use_yolo" "$project_id" "$memory_mode" "Read \`$architect_skill\` and follow it strictly, including every gate even when permissive Claude execution is active. Stay in the documentation-first architect/orchestrator role: produce and coordinate documentation and planning only, and do not implement the requirement.

AgentMemory project: $project_id
Memory mode: $memory_mode. Run the skill's mandatory recall gate before workflow detection or repository modification. Pass this same project identity to every Codex process.

$architect_start_mode

Use the following payload as the initial requirement:

$payload"
    return $?
  fi

  print -r -- "🚀 Launching Claude Code with the memory-aware Matt workflow..."
  _plan_build_launch_claude "$use_yolo" "$project_id" "$memory_mode" "Read \`$standard_skill\` and strictly follow its memory-aware Matt Pocock workflow.

AgentMemory project: $project_id
Memory mode: $memory_mode. Run the mandatory recall gate before routing or modifying the repository. Pass this same project identity to every Codex process.

$payload"
}

_plan_build_main() {
  plan_build "$@"
}

if [[ "${ZSH_EVAL_CONTEXT:-}" == toplevel ]]; then
  _plan_build_main "$@"
fi
