Usages:
  conventions: .goga/usages/conventions.md
  ralphex: .goga/usages/cooks/ralphex.md

Annotations: |
  The `conventions` practice is used for:
  - Working with the codebase
  - Organizing the REPL development cycle
  - Debugging and testing
  - Organizing the test infrastructure
  - Understanding the general principles and rules of development and testing in the project

  This cell is a thin launcher over the external `ralphex` binary — its sole responsibility
  is to invoke ralphex with the resolved plan and ralphex options, then propagate the
  subprocess exit code. Config generation (.ralphex/config), ralphex option resolution
  (CLI > ProjectConfig > omit), and agent-wrapper resolution live in the caller
  (goga/build): this cell performs none of them.

  Use the `ralphex` practice to interact with the external ralphex binary (CLI contract,
  invocation shape, flag set, PATH-resolved invocation, exit-code propagation).

  The launcher inherits the process environment for the ralphex subprocess; an
  optional env layer (dict of strings), supplied by the caller, is applied on
  top of the inherited environment for that subprocess only. The layer is never
  logged and never printed on dry-run (secret-safe). The standard library
  subprocess and shutil modules are used for invoking the binary and the PATH
  check. All output goes to sys.stderr (click is not used).

---

"run_ralphex(plan: str, options: dict[str, str | int | bool], dry_run: bool, env: dict[str, str] | None = None) -> exit_code: int":
  location: run_ralphex.py
  annotations: |
    Launch the external `ralphex` binary to execute the given build plan with the resolved
    ralphex options. goga-side entry point to ralphex; performs no config generation,
    option resolution, or wrapper resolution — those live in goga/build.

    `plan`: path to the plan file (markdown), resolved by the caller (goga/build). Passed
           to ralphex as the positional argument.
    `options`: resolved ralphex options — the caller (goga/build) has already applied CLI >
              ProjectConfig > omit precedence. Keys are ralphex option names; each key maps
              to exactly one ralphex CLI flag:
              - worktree (bool)        → --worktree         (bare flag)
              - skip_finalize (bool)   → --skip-finalize    (bare flag)
              - review (bool)          → --review            (bare flag)
              - tasks_only (bool)      → --tasks-only        (bare flag)
              - session_timeout (str)  → --session-timeout  (value flag)
              - idle_timeout (str)     → --idle-timeout     (value flag)
              - wait (str)             → --wait             (value flag)
              - max_iterations (int)   → --max-iterations   (value flag)
              - review_patience (int)  → --review-patience  (value flag)
    `dry_run`: when True, print the assembled ralphex command to sys.stderr and return 0
              without launching.
    `env`: optional environment layer ({str: str}) applied on top of the inherited
           process environment for the ralphex subprocess — keys of `env` override
           same-named inherited variables, every other inherited variable passes through
           unchanged. None or an empty dict means pure inheritance with no layer. The
           layer scopes to this subprocess only.
    `exit_code`: 0 on success, 1 when the ralphex binary is missing from PATH —
                including when an `env` layer's PATH override hides it from the
                exec — or when the launch is rejected before the exec (an `env`
                layer key that is not a legal environment variable name, an
                oversized layer, or a PATH override resolving a non-executable
                or non-directory ralphex), otherwise ralphex's own exit code

    Algorithm:
    1. Receive `plan`, `options`, `dry_run`, and `env` from the caller
    2. Invoke ralphex via the `ralphex` practice with `plan` as the positional argument,
       --config-dir .ralphex/, and the flags mapped from `options` (precedence already
       applied by the caller)
    3. On `dry_run`: print the assembled command to sys.stderr and return 0 — never print
       the `env` layer values
    4. Verify `ralphex` is on PATH via the `ralphex` practice; when absent — return `exit_code` 1
    5. Execute `ralphex` via subprocess with the environment composed as the inherited
       process environment overlaid with `env` (a None or empty `env` leaves the inherited
       environment untouched) and propagate its exit code. A launch rejected before the
       exec — FileNotFoundError when the layer's PATH override hides the binary, or
       OSError/ValueError on an illegal env-variable name, an oversized layer, or a
       PATH override resolving a non-executable/non-directory ralphex — is reported as a
       clean one-line message to sys.stderr and exit code 1, never a traceback, and the
       message never reveals the `env` layer contents

    Apply the `conventions` practice for error-handling style and docstring formatting.
    Apply the `ralphex` practice for the general ralphex CLI contract (binary invocation,
    --config-dir, PATH-resolved invocation, exit-code propagation); the option→flag
    mapping is fixed by this contract (see `options`), not by the practice.

    Requirements:
    - Always invoke ralphex with `plan` as the positional argument and --config-dir .ralphex/,
      plus the mapped flags — never omit the plan or --config-dir
    - Map `options` to ralphex CLI flags per the table in `options`: a bool key that is
      True emits a bare --<flag> (False or absent → omit the flag); a scalar key emits
      --<flag> <value> and is omitted when the value is None, an empty string, or 0
    - Invoke ralphex through PATH — do not hard-code the ralphex binary path
    - Compose the subprocess environment as the inherited os.environ overlaid with `env`;
      apply the layer only to this subprocess
    - On `dry_run`, the printed command carries no environment values
    - A launch rejection (see Algorithm step 5) surfaces as a clean message plus exit
      code 1 — no traceback escapes to the caller, and no `env` layer value is printed
    - Apply the `ralphex` practice's exit-code rules verbatim

    Constraints:
    - Do not generate the .ralphex/config file — that is the caller's responsibility
    - Do not resolve ralphex options (CLI > ProjectConfig > omit) — caller's responsibility
    - Do not resolve the agent wrapper path — caller's responsibility
    - Do not hard-code the ralphex binary path — rely on PATH inside the container
    - Do not construct the environment from a config object — `env` is an explicitly
      passed primitive layer, not a config-derived environment
    - Do not log or otherwise expose the `env` layer contents

---

Author: Goga
CreatedAt: 26/07/26
Description: |
  Thin launcher over the external `ralphex` binary. Invokes ralphex with the resolved
  plan and ralphex options (resolved by the caller), then propagates the subprocess exit
  code. Config generation, option resolution, and wrapper resolution live in goga/build.
