---
name: port-astgen
description: Iteratively port AstGen.zig to astgen.c by enabling skipped corpus tests, finding divergences, and mechanically copying upstream code.
allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task
disable-model-invocation: true
---

# Port AstGen — Orchestrator

You manage the iterative porting loop. For each iteration you either fix
existing failures or enable a new disabled test, dispatch a worker agent,
then verify and commit.

**You do NOT**: analyze test output in detail, compare Zig/C code, or
edit `astgen.c`. The worker handles all of that.

**CRITICAL RULES:**
1. **NEVER stop early.** Do not pause to ask the user if you should continue.
   Do not summarize remaining work and wait. Keep looping until every test is
   enabled and passing.
2. **ALWAYS run the test command (in Phase 0, below) yourself before
   committing.** Never trust the worker's claim that tests pass — verify it. If
   the test run fails (non-zero exit) or it emits any output, do NOT commit and
   let the worker fix it.

## Phase 0: Check for leftovers

Before enabling anything new, run the **full** test suite:

```sh
cd ~/code/zig
./zig-out/bin/zig build all-zig0 -Dvalgrind > /dev/null 2>&1 ; echo "EXIT: $?"
```

Also check for failures:

```sh
./zig-out/bin/zig build all-zig0 -Dvalgrind 2>&1 | grep -iE 'FAIL|error:' | head -5
```

If EXIT is non-zero or any FAIL/error lines appear: dispatch a worker
(Step 4 below) with context describing the failure — no test was
"enabled", just paste the output and tell the worker existing tests are
failing. After the worker returns, follow Steps 5–7 as normal. Re-run
Phase 0 until the full test suite passes before proceeding to the main
loop.

If EXIT is 0 with no failures: proceed to the main loop.

## Main Loop

Repeat until no `SkipZigTest` lines AND no commented corpus entries
remain in `astgen_test.zig`.

### Step 1: Find the next disabled test

Search `stage0/astgen_test.zig` in priority order:

**Priority A — SkipZigTest lines:**
Search for lines matching:
```
if (true) return error.SkipZigTest
```
Pick the first one. Note the test name (the `test "..."` header above
the skip line) and the line number.

**Priority B — Commented corpus entries:**
If no SkipZigTest lines exist, search for lines matching `//"..\` inside
the `corpus_files` tuple (between `const corpus_files = .{` and `};`).
Pick the first one. Note the file name and line number.

If neither is found, all tests are enabled — go to the final check.

### Step 2: Enable the test

**For SkipZigTest:** Comment out the `if (true) return error.SkipZigTest;`
line to enable the test.

**For commented corpus entry:** Uncomment the line (remove the leading
`//`).

### Step 3: Quick smoke test

Run:
```sh
./zig-out/bin/zig build test-zig0 -Dzig0-cc=tcc 2>&1 | head -10
```
Capture only the first ~10 lines. This tells you pass/fail at a glance
without bloating your context. The worker will run the full test itself.

### Step 4: Dispatch worker

1. Read the file `.claude/skills/port-astgen/worker-prompt.md`.
2. Replace the placeholder `{{TEST_CONTEXT}}` with the actual context:
   - What was enabled: test name + line number (SkipZigTest) or
     corpus file name + line number (corpus entry)
   - Whether this is a SkipZigTest or a corpus entry
   - The first ~10 lines of test output from Step 3
3. Launch via the Task tool:
   ```
   subagent_type=general-purpose
   prompt=<the worker prompt with context filled in>
   ```

### Step 5: Parse worker response

The worker returns a structured result. Extract:
- `STATUS`: one of `pass`, `progress`, or `no-progress`
- `COMMIT_MSG`: a descriptive commit message

### Step 6: Handle by status

**If STATUS is `pass` or `progress`:**

**You MUST verify before committing.** Run:

```sh
./zig-out/bin/zig build all-zig0 -Dvalgrind |& grep -v Warning | head -10 ; echo "EXIT: $?"
```

Check two things only: (1) EXIT is 0, (2) the ~10 lines of output
contain no unexpected errors. If either check fails, do NOT commit —
dispatch another worker to fix.

Only if clean, commit:

```sh
git add stage0/astgen.c stage0/astgen_test.zig
git commit -m "<COMMIT_MSG from worker>

Co-Authored-By: <whatever model is running this>"
```

**If STATUS is `no-progress`:**

Do NOT commit. The worker should have reverted the test file (re-added
SkipZigTest or re-commented the corpus entry). Verify with:

```sh
git diff stage0/astgen_test.zig
```

If there are leftover changes (the entry is still enabled), re-comment
the corpus entry or re-add the SkipZigTest yourself. Then:

```sh
git checkout -- stage0/astgen.c stage0/astgen_test.zig
```

Log that this test was skipped due to no progress and continue.

### Step 7: Repeat

Go back to Step 1. **Never stop early** — continue until all
`SkipZigTest` lines are gone AND all corpus entries are uncommented.

## Final Check

When no disabled tests remain, run:

    ./zig-out/bin/zig build all-zig0 -Dvalgrind

If that fails, go back to Phase 0 (treat it as a leftover).
