Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 73 additions & 15 deletions agents/codex-implementer.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,48 +48,106 @@ and include its actual output in your final message."]
SPEC_EOF
```

2. Invoke codex non-interactively, sandboxed to the workspace, with reasoning effort pinned high:
2. Invoke codex non-interactively, sandboxed to the workspace, with reasoning effort pinned high — under a **hard wall-clock cap that works on every OS**:

```bash
# Portable timeout: macOS has no `timeout` unless coreutils is installed
T=$(command -v gtimeout || command -v timeout || true)
[ -z "$T" ] && echo "WARN: no timeout binary — codex runs uncapped (brew install coreutils to cap)"

${T:+$T 600} codex exec \
# --- Hard wall-clock cap (cross-platform, Windows-safe) ---------------------
# The old `${T:+$T 600}` cap failed two ways on Windows/Git Bash:
# 1. `command -v timeout` can resolve to system32 timeout.exe (an interactive
# countdown, NOT a process capper) — so codex ran UNCAPPED.
# 2. Even GNU timeout / a plain `kill` only reach the DIRECT child. codex is an
# npm shim (sh -> node); killing the shim leaves the node worker running.
# So: on Windows we skip `timeout` entirely and tree-kill the whole Windows
# process tree via taskkill; elsewhere we use validated GNU coreutils timeout.
# The run is ALWAYS bounded — codex can never spin past the deadline. rc 124 = hit cap.
run_capped() { # run_capped <seconds> <cmd...> (stdin/redirects pass through)
local secs=$1; shift
case "$(uname -s)" in
MINGW*|MSYS*|CYGWIN*) : ;; # Windows -> tree-kill path below
*) # macOS/Linux -> idiomatic GNU timeout
local T; T=$(command -v gtimeout || command -v timeout || true)
if [ -n "$T" ] && "$T" --version 2>/dev/null | grep -qi coreutils; then
"$T" -k 15 "$secs" "$@"; return $? # TERM at <secs>, KILL 15s later; 124 on cap
fi ;; # else fall through to the bash-native guard
esac
local flag; flag=$(mktemp)
"$@" <&0 & # <&0 forces stdin (the spec) onto the bg job
local pid=$!
( i=0 # watcher: bounded by BOTH a deadline AND
while [ "$i" -lt "$secs" ]; do # a kill -0 liveness check, so an abnormal
sleep 1; i=$((i+1)) # codex exit ends the watch — never spins.
kill -0 "$pid" 2>/dev/null || exit 0 # job finished on its own -> stop watching
done
echo 1 > "$flag" # deadline reached -> mark BEFORE killing (no race)
local wp; wp=$(cat "/proc/$pid/winpid" 2>/dev/null)
if [ -n "$wp" ]; then taskkill //T //F //PID "$wp" >/dev/null 2>&1 # kill the whole tree
else kill -TERM "$pid" 2>/dev/null; sleep 15; kill -KILL "$pid" 2>/dev/null; fi
) >/dev/null 2>&1 & # redirect: watcher never holds the tool's pipe
local killer=$!
wait "$pid"; local rc=$?
wait "$killer" 2>/dev/null # watcher self-exits within 1s; reap, don't kill mid-sleep
[ -s "$flag" ] && rc=124 # normalize: deadline fired -> timeout
rm -f "$flag"
return $rc
}

# --- Sandbox mode: Windows can't ENFORCE workspace-write --------------------
# Codex only writes under an OS-enforced sandbox (Seatbelt/Landlock). Windows has
# none, so `--sandbox workspace-write` silently downgrades to read-only and rejects
# every patch. Rather than a blocked-write failure, on Windows run codex READ-ONLY
# as a cross-vendor REVIEWER: it reads the tree and returns its implementation as a
# patch in its final message, which the caller (or the grok lane) applies. Grok is
# the writer on Windows; codex is the second-family check. macOS/Linux write for real.
case "$(uname -s)" in
MINGW*|MSYS*|CYGWIN*)
SANDBOX=read-only
printf '\n\nENVIRONMENT NOTE: read-only sandbox (Windows) — you CANNOT write files. Deliver your full implementation in your final message as (a) a single `git apply`-able unified diff AND (b) the complete final contents of every changed file. Do not attempt to write; the caller applies your patch.\n' >> "$SPEC" ;;
*) SANDBOX=workspace-write ;;
esac

# Run codex in the FOREGROUND under the cap. Cap is 540s (9 min), deliberately
# under the Bash tool's 600000 ms max so the KILL escalation completes before the
# tool would kill bash and re-orphan the child. Set the tool timeout to 600000 ms.
run_capped 540 codex exec \
--model gpt-5.6-sol \
-c model_reasoning_effort=high \
--sandbox workspace-write \
--sandbox "$SANDBOX" \
--skip-git-repo-check \
--cd "$(pwd)" \
--output-last-message "$FINAL" \
- < "$SPEC"
rc=$?
[ "$rc" = 124 ] && echo "STATUS: timeout — codex exceeded the 540s wall clock"
```

**Foreground only — never background codex behind a marker poll.** Run the block above as one foreground Bash call (tool timeout `600000` ms). Do **not** launch codex as a background task: the harness then polls the log for codex's `tokens used` completion marker (`until grep -q "tokens used" …`), and an **abnormal** codex exit under its sandbox bug never writes that marker — so the watcher loop spins forever as an orphaned process. The wall-clock guard already bounds the run; foreground + `run_capped` needs no watcher. If you ever must poll anyway, bound the loop with a deadline **and** a `kill -0 "$pid"` liveness check (as `run_capped`'s own watcher does) so an abnormal exit ends the watch instead of looping.

Flag discipline (non-negotiable):

| Flag | Why |
|---|---|
| `--sandbox workspace-write` | Codex writes code, scoped to the working tree. Never `danger-full-access`. |
| `-c model_reasoning_effort=high` | Pins GPT-5.6 Sol to high reasoning for complex implementation work. |
| `--sandbox "$SANDBOX"` | `workspace-write` on macOS/Linux (codex writes, scoped to the tree). **`read-only` on Windows** — no OS sandbox exists there, so codex reviews + returns a patch instead of writing (grok is the Windows writer). Never `danger-full-access`. |
| `-c model_reasoning_effort=high` | The lane's whole value is maximum-effort GPT-5.6 Sol. |
| `--skip-git-repo-check` + `--cd "$(pwd)"` | Deterministic working root; works outside git repos. |
| `- < spec file` | Prompt via stdin. No quoting hazards, no truncated specs. |
| `${T:+$T 600}` | Ten-minute wall clock when `timeout`/`gtimeout` exists (macOS needs `brew install coreutils`); runs uncapped otherwise. On timeout, report `STATUS: timeout` with whatever landed. |
| `run_capped 540` | Hard wall clock (540s, under the Bash tool's 600000 ms max) enforced on **every** OS: Windows tree-kills the process tree via `taskkill //T //F` on the win PID (GNU `timeout`/`kill` only reach the npm shim, not the node worker); macOS/Linux use validated GNU `timeout`/`gtimeout` (`brew install coreutils`). Never trusts Windows `timeout.exe`. On timeout `rc=124` → report `STATUS: timeout` with whatever landed. |

`--model gpt-5.6-sol` selects the Sol capability tier — if the caller's spec names a different codex model, use that instead; the slug is a documented default, not a constant.
`--model gpt-5.6-sol` is the current top GPT tier — if the caller's spec names a different codex model, use that instead; the slug is a documented default, not a constant.

3. **Verify independently.** Read the diff (`git diff` / `git status`), run the spec's verification command yourself, and read codex's final message from `"$FINAL"`. Codex's claim of success is not evidence; your re-run is.
3. **Verify independently.** On macOS/Linux: read the diff (`git diff` / `git status`), run the spec's verification command yourself, and read codex's final message from `"$FINAL"`. Codex's claim of success is not evidence; your re-run is. **On Windows (read-only reviewer):** there is no diff — codex's deliverable IS the patch in `"$FINAL"`. Sanity-check the patch applies cleanly (`git apply --check`) and report it as a `proposal`; do not apply it yourself unless the caller asked (fix/apply decisions belong upstream — the caller routes it to the grok lane or applies it).

## What you return

```
CODEX REPORT
STATUS: complete | partial | timeout | unavailable
STATUS: complete | proposal | partial | timeout | unavailable
OBJECTIVE: [restated in one line]
CHANGES: [file — one-line summary, per file, from the actual diff]
VERIFIED: [verification command you re-ran — actual output evidence]
CHANGES: [file — one-line summary, per file, from the actual diff | on Windows: from codex's proposed patch]
VERIFIED: [verification command you re-ran — actual output evidence | on Windows: `git apply --check` result for the proposed patch]
CODEX SAID: [one-line summary of codex's final message, note any disagreement with the diff]
GAPS: [spec ambiguities, unfinished items, or "none"]
```
(`STATUS: proposal` = the Windows read-only path — codex returned a reviewed patch for the caller to apply, not a completed write.)

## Rules

Expand Down
71 changes: 59 additions & 12 deletions agents/grok-implementer.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,36 +45,83 @@ and include its actual output in your final message."]
SPEC_EOF
```

2. Invoke grok headlessly, scoped to the working tree:
2. Invoke grok headlessly, scoped to the working tree — under a **hard wall-clock cap that works on every OS**:

```bash
# Portable timeout: macOS has no `timeout` unless coreutils is installed
T=$(command -v gtimeout || command -v timeout || true)
[ -z "$T" ] && echo "WARN: no timeout binary — grok runs uncapped (brew install coreutils to cap)"

${T:+$T 600} grok --prompt-file "$SPEC" \
# --- Hard wall-clock cap (cross-platform, Windows-safe) ---------------------
# The old `${T:+$T 600}` cap failed two ways on Windows/Git Bash:
# 1. `command -v timeout` can resolve to system32 timeout.exe (an interactive
# countdown, NOT a process capper) — so grok ran UNCAPPED.
# 2. Even GNU timeout / a plain `kill` only reach the DIRECT child, leaving any
# grandchild grok spawns (to run commands) alive.
# So: on Windows we skip `timeout` entirely and tree-kill the whole Windows
# process tree via taskkill; elsewhere we use validated GNU coreutils timeout.
# The run is ALWAYS bounded — grok can never spin past the deadline. rc 124 = hit cap.
run_capped() { # run_capped <seconds> <cmd...> (stdin/redirects pass through)
local secs=$1; shift
case "$(uname -s)" in
MINGW*|MSYS*|CYGWIN*) : ;; # Windows -> tree-kill path below
*) # macOS/Linux -> idiomatic GNU timeout
local T; T=$(command -v gtimeout || command -v timeout || true)
if [ -n "$T" ] && "$T" --version 2>/dev/null | grep -qi coreutils; then
"$T" -k 15 "$secs" "$@"; return $? # TERM at <secs>, KILL 15s later; 124 on cap
fi ;; # else fall through to the bash-native guard
esac
local flag; flag=$(mktemp)
"$@" <&0 &
local pid=$!
( i=0 # watcher: bounded by BOTH a deadline AND
while [ "$i" -lt "$secs" ]; do # a kill -0 liveness check, so an abnormal
sleep 1; i=$((i+1)) # grok exit ends the watch — never spins.
kill -0 "$pid" 2>/dev/null || exit 0 # job finished on its own -> stop watching
done
echo 1 > "$flag" # deadline reached -> mark BEFORE killing (no race)
local wp; wp=$(cat "/proc/$pid/winpid" 2>/dev/null)
if [ -n "$wp" ]; then taskkill //T //F //PID "$wp" >/dev/null 2>&1 # kill the whole tree
else kill -TERM "$pid" 2>/dev/null; sleep 15; kill -KILL "$pid" 2>/dev/null; fi
) >/dev/null 2>&1 & # redirect: watcher never holds the tool's pipe
local killer=$!
wait "$pid"; local rc=$?
wait "$killer" 2>/dev/null # watcher self-exits within 1s; reap, don't kill mid-sleep
[ -s "$flag" ] && rc=124 # normalize: deadline fired -> timeout
rm -f "$flag"
return $rc
}

# Run grok in the FOREGROUND under the cap. Cap is 540s (9 min), deliberately
# under the Bash tool's 600000 ms max so the KILL escalation completes before the
# tool would kill bash and re-orphan the child. Set the tool timeout to 600000 ms.
FINAL=$(mktemp -t grok-final.XXXXXX)
# ⚠ permission-mode: use `auto`, NOT `acceptEdits`. On Windows headless, `acceptEdits`
# (and `dontAsk`/`default`) SILENTLY DROP every file write — grok exits 0, narrates
# success, and no file lands (verified A/B 2026-07-10). Only `auto` and
# `bypassPermissions` actually write headless; `auto` is the least-privilege of the two.
run_capped 540 grok --prompt-file "$SPEC" \
-m grok-4.5 \
--permission-mode acceptEdits \
--permission-mode auto \
--output-format plain \
--cwd "$(pwd)" \
> /tmp/grok-final-$$.txt 2>&1
FINAL=/tmp/grok-final-$$.txt
> "$FINAL" 2>&1
rc=$?
[ "$rc" = 124 ] && echo "STATUS: timeout — grok exceeded the 540s wall clock"
```

**Foreground only — never background grok behind a marker poll.** Run the block above as one foreground Bash call (tool timeout `600000` ms). Do **not** launch grok as a background task: the harness then polls the log for a completion marker (`until grep -q … "$FINAL"`), and an **abnormal** grok exit never writes that marker — so the watcher loop spins forever as an orphaned process. The wall-clock guard already bounds the run; foreground + `run_capped` needs no watcher. If you ever must poll anyway, bound the loop with a deadline **and** a `kill -0 "$pid"` liveness check (as `run_capped`'s own watcher does) so an abnormal exit ends the watch instead of looping.

Flag discipline (non-negotiable):

| Flag | Why |
|---|---|
| `--prompt-file "$SPEC"` | Headless single-task run from a file. No quoting hazards, no truncated specs. |
| `-m grok-4.5` | The lane's producer is Grok 4.5, pinned explicitly — never rely on the CLI default. |
| `--permission-mode acceptEdits` | Grok edits files without prompting, but does not get blanket command approval. Never `--always-approve` — you re-run verification yourself. |
| `--permission-mode auto` | Grok applies edits (and runs commands) without prompting — **required for headless writes on Windows**, where `acceptEdits` silently drops every write (exit 0, no file). `auto` is the least-privilege mode that actually writes; you still re-run verification yourself. |
| `--cwd "$(pwd)"` | Deterministic working root. |
| `--output-format plain` | Final message to stdout, captured for the report. |
| `${T:+$T 600}` | Ten-minute wall clock when `timeout`/`gtimeout` exists. On timeout, report `STATUS: timeout` with whatever landed. |
| `run_capped 540` | Hard wall clock (540s, under the Bash tool's 600000 ms max) enforced on **every** OS: Windows tree-kills the process tree via `taskkill //T //F` on the win PID; macOS/Linux use validated GNU `timeout`/`gtimeout` (`brew install coreutils`). Never trusts Windows `timeout.exe`. On timeout `rc=124` → report `STATUS: timeout` with whatever landed. |

`-m grok-4.5` is the current top Grok tier — if the caller's spec names a different grok model, use that instead; the slug is a documented default, not a constant.

3. **Verify independently.** Read the diff (`git diff` / `git status`), run the spec's verification command yourself, and read grok's final message from `"$FINAL"`. Grok's claim of success is not evidence; your re-run is. (`acceptEdits` may have blocked grok from running the verification itself — your re-run covers that by design.)
3. **Verify independently.** Read the diff (`git diff` / `git status`), run the spec's verification command yourself, and read grok's final message from `"$FINAL"`. Grok's claim of success is not evidence; your re-run is — **doubly so on Windows**, where a wrong permission-mode makes grok narrate a write that never happened. Confirm files actually changed on disk, not just that grok *said* so.

## What you return

Expand Down