diff --git a/tools/loop-action/README.md b/tools/loop-action/README.md index 957bb012..616c2a9e 100644 --- a/tools/loop-action/README.md +++ b/tools/loop-action/README.md @@ -24,11 +24,57 @@ Instead of writing complex bash scripts to enforce circuit breakers, run readine | `command` | **Yes** | | The actual terminal command to invoke your agent (e.g., `claude`, `grok`, `aider`). | | `level` | No | `L1` | The autonomy level for budget constraint verification (`L1`, `L2`, `L3`). | | `sandbox` | No | `false` | If `'true'`, routes the execution through `loop-sandbox` to provide ephemeral worktree isolation, capturing changes securely without destroying the main working tree. | -| `sandbox-shell` | No | `false` | If `'true'`, routes the execution inside a shell environment (`--shell`). | +| `sandbox-shell` | No | `false` | Compatibility option for `loop-sandbox`: if `'true'`, passes `--shell` so `loop-sandbox` itself invokes the command through its own shell. `command` is always executed as a Bash script regardless of this setting (see below) — `sandbox-shell` does not gate shell syntax and can be left at its default in normal use. | ## What it does under the hood When this action runs, it sequentially executes: 1. **`loop-audit`**: Checks the repository against the Loop Readiness rubric (ensuring `STATE.md`, `gate.yaml`, and constraints are in place). 2. **`loop-context`**: Acts as a circuit breaker. It halts the workflow immediately if the loop is stuck in a failure cycle or has exhausted its daily token budget. -3. **Execution (`loop-sandbox`)**: If `sandbox: 'true'`, it dynamically isolates the agent inside an ephemeral git worktree, tracks all modifications into a patch file, and cleans up. Otherwise, it executes the command directly in the main tree. +3. **Write command script**: `command` is passed through the step's `env:` map (not spliced into the `run:` script text) and written verbatim to a temp file under `$RUNNER_TEMP`. This keeps multi-line commands, quotes, and shell metacharacters intact as a single script instead of being re-parsed by the surrounding workflow YAML. +4. **Execution (`loop-sandbox`)**: If `sandbox: 'true'`, that script is invoked as `bash -eo pipefail