# Field patch: a Ratchet Loop 4.4 Grok Build kit on grok 1.0.50

**Apply this to any lineage that started from a 4.4 Grok Build kit and now runs on grok 1.0.50 or
later.** It changes no method rule. Every round you have already run stays valid. What it
repairs is the harness wiring: on 1.0.50 the 4.4 kit's boundary does not hold, its judges' tool
lists are ignored, and its builders' commits are unreachable from the main repository.

Measured on grok 1.0.50, Windows, 2026-10-09, with the 4.4 kit installed as its START-HERE says:

- **The hook fails open.** Grok runs a hook command under the detected Windows shell, and Windows
  PowerShell reports the script's exit 2 as 1. Grok treats 1 as a failed hook and lets the call
  through. In that run a write into `gauntlet/sealed/` landed, `Remove-Item
  gauntlet/sealed/INDEX.md` deleted the file, and a builder wrote under `gauntlet/`. The script
  had decided "deny" every time.
- **`monitor` bypasses the hook.** It runs a shell command in the background, and the 4.4 matcher
  does not name it.
- **Judges get every tool.** `run_terminal_command` in a `tools:` line cannot be mapped, and one
  unmappable entry makes Grok keep the full toolset.
- **Builder SHAs do not exist in your repository.** `isolation: worktree` now makes a standalone
  copy with its own `.git`, under `~/.grok/worktrees/`.
- **A misspelled model slug is not refused.** Grok silently runs that child on the session's model.

Stop the run at a round boundary first: `/goal pause`, or let the current round finish. Then
apply the five items below by hand. `install-hooks.mjs` never overwrites a file that differs from
the one it would install, so it will not do this for you.

---

## 1. The hook registration — `.grok/hooks/deny-gauntlet.json`

Change two values and nothing else.

`command` becomes exactly:

```
node "${GROK_WORKSPACE_ROOT}/.claude/hooks/deny-gauntlet.mjs" --harness=grok --emit-json
```

`matcher` gains `|monitor` at its end:

```
Bash|PowerShell|Edit.*|Write|Read|Glob|Grep|run_terminal_command|read_file|search_replace|write|list_dir|grep|monitor
```

With `--emit-json` the script prints `{"decision":"deny","reason":"..."}` on stdout, and Grok
honours that on any exit code.

## 2. The hook script — `.claude/hooks/deny-gauntlet.mjs`

Find the one line that begins `const isShell =` and add `|monitor` before the closing parenthesis:

```js
const isShell = /(bash|powershell|shell|terminal|exec|run_?command|process|cmd|monitor)/i.test(toolName);
```

Without this, the matcher change alone still fences children (the role check reads the `command`),
but the orchestrator's integrity rules would not inspect a `monitor` command. Or replace the
whole file with `https://ratchet.babzlabz.com/kit/grok/deny-gauntlet.mjs`. Its rules are the 4.4
rules plus this line.

## 3. The judge tool lists — `.grok/agents/judge-a.md` and `.grok/agents/judge-b.md`

In each file the `tools:` line becomes exactly:

```
tools: read_file, list_dir, grep, run_terminal_cmd
```

`run_terminal_cmd` is the shell's internal id. With it, the grok log reads
`tools allowlist applied`; with `run_terminal_command` it reads
`tools allowlist had unmappable entries; keeping full grok toolset`.

## 4. The operations paragraph — append to the root `AGENTS.md`

Append this paragraph verbatim. The run reads `AGENTS.md` at session start once the folder is
trusted.

```
## grok ≥1.0.50 operations (field patch to the 4.4 kit)

- A builder's worktree is a standalone copy of the working tree under ~/.grok/worktrees/, with
  its own .git. After every builder returns, from the main checkout run
  `git fetch <worktree_path> <sha>` and then `git cat-file -t <sha>`, which must print
  `commit`, BEFORE Gate 1 or the preparer touches the SHA. A SHA that will not fetch is a
  builder that returned nothing. Remove a worktree you did not keep with
  `grok worktree rm <worktree_path>`, the path the spawn result reported.
- The copy includes untracked files and uncommitted edits and skips gitignored files: gauntlet/
  is absent only because it is gitignored. Spawn builders only from a clean champion checkout
  (`git status --porcelain` prints nothing). workbench.md, progress.html and .rl-scratch/
  (the one directory for every clean checkout, slate, capture and server log made outside
  gauntlet/) are gitignored for exactly this reason; keep run files there and nowhere else.
- Every builder commits only the paths it changed, by name (`git add <path>…`), never
  `git add -A`: a candidate that carries run files cannot be promoted cleanly.
- To prove gauntlet/ is absent, run `Test-Path <worktree_path>/gauntlet` from your own shell.
  Do not ask a builder to list it: the hook denies a builder any call that names gauntlet/.
- An unknown model slug is NOT refused; the child silently runs on the session's model. Copy
  every slug exactly from `grok models`, never pass `model` on a spawn, and after each judge's
  calibration spawn (and the first builder) completes, run `grok usage <subagent_id>` and
  record `primaryModelId` as the resolved model. Family means vendor: grok-* xAI; claude-* and
  opus-* Anthropic; gpt-* OpenAI; anything else has no declared vendor. "No usage recorded"
  means unverified.
- grok 1.0.50 delivers subagentType to the hook in children, so role guards now apply: builders
  and judges get nothing under gauntlet/, the critic its inbox and criteria.md, the preparer
  the champion snapshots and criteria.md. Hand every role its text in the spawn prompt.
- resume_from returns a NEW subagent id. The judge is still the calibration spawn's id; record
  the resumed id beside it.
```

## 5. Commit, restart, check

1. Gitignore the run's own files, then commit the changed files. A 4.4 lineage's run files
   are untracked, and on 1.0.50 every untracked file rides into every builder's copy. At a
   round boundary no scratch checkout should remain; from now on make them under
   `.rl-scratch/`.

   ```powershell
   Add-Content .gitignore "`nworkbench.md`nprogress.html`n.rl-scratch/"
   git add .gitignore .grok .claude AGENTS.md
   git commit -m "field patch: grok 1.0.50"
   git status --porcelain
   ```

   ```sh
   printf '\nworkbench.md\nprogress.html\n.rl-scratch/\n' >> .gitignore
   git add .gitignore .grok .claude AGENTS.md
   git commit -m "field patch: grok 1.0.50"
   git status --porcelain
   ```

   The last line must print nothing.
2. **Restart the Grok session.** Hooks and `AGENTS.md` are loaded when a session starts. In the
   TUI, `/hooks` and its reload action also work.
3. From a shell in the project, run `grok inspect` (free, no model call). It must show:
   - `Project trusted: yes`
   - `Hooks (1)`, with `monitor` in the matcher (`grok inspect --json` shows the command as the
     hook's `target`, which must end in `--emit-json`)
   - `AGENTS.md` under Project Instructions, as `(project)`
   - the five agents
4. Probe the live boundary once with throwaway children:
   - Have the orchestrator try `rm gauntlet/sealed/INDEX.md`. It must come back
     `Hook denied: BOUNDARY [grok/orchestrator]`.
   - Append a ledger line. It must succeed.
   - Spawn a throwaway builder with `isolation: worktree`, have it write to
     `<repo>/gauntlet/probe.txt` by absolute path, and see it denied.
   - Run `Test-Path <worktree_path>/gauntlet` from your own shell. It must be `False`.
5. Paste the same `/goal` line again. The run resumes from its ledger.

**A Relay lineage needs one more file.** Relay 5.0-beta.2's doctor rejects the new registration
and `relay run` stops with "doctor failed". In `run-kit/relay/bin/doctor.mjs`, change exactly two
regular expressions:

- on line 72, the tail `(?:\s+--harness=grok)?$` becomes
  `(?:\s+--harness=grok)?(?:\s+--emit-json)?$`;
- line 102 becomes
  `if (event === 'PreToolUse' && !/--harness=grok(?:\s+--emit-json)?$/.test(command))`.

Relay 5.0-beta.3 ships both changes.

The full evidence is in the generator repository, at `docs/verify-2026-10/GROK-1.0.50.md`.
