# The Six-Step Drafter-Reviewer Pipeline in the `/apply` Workflow

> Discover the six-step drafter-reviewer pipeline in the /apply workflow. This AI system evaluates job fit, drafts LaTeX, researches, revises, validates PDFs, and delivers submission-ready output.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: deep-dive
- Published: 2026-07-20

---

**The six-step drafter-reviewer pipeline in the `/apply` workflow is a deterministic, two-agent system that evaluates job fit, drafts LaTeX application documents, performs isolated research and critique, applies structured revisions, compiles PDFs with mandatory validation, and delivers final output ready for submission.**

The MadsLorentzen/ai-job-search repository automates job application generation through a rigorous quality control process defined in [`.claude/commands/apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/apply.md). This **six-step drafter-reviewer pipeline** alternates between a **DRAFTER** agent that creates content and a **REVIEWER** agent that provides unbiased critique, ensuring every CV and cover letter is factually grounded, stylistically consistent, and ATS-compatible before final output.

## Step-by-Step Breakdown of the Pipeline

The pipeline executes six ordered stages after initial input parsing (Step 0), with each stage defined in [`apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/apply.md). Each step must complete successfully before the next begins.

### Step 1: Evaluate Fit (DRAFTER)

The **DRAFTER** agent begins by reading the candidate profile and the job-evaluation rubric from [`.claude/skills/job-application-assistant/04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/04-job-evaluation.md). It calculates a fit score and recommendation, optionally invoking the salary-lookup tool documented in [`tools/README_SALARY_TOOL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/README_SALARY_TOOL.md). This gate prevents wasted effort on low-fit postings (see [`apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/apply.md) lines 25–45).

### Step 2: Draft CV and Cover Letter (DRAFTER)

Upon passing the fit check, the **DRAFTER** generates LaTeX source files using the writing-style guide ([`.claude/skills/job-application-assistant/03-writing-style.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/03-writing-style.md)) and templates from [`05-cv-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/05-cv-templates.md) and [`06-cover-letter-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/06-cover-letter-templates.md). It produces `cv/main_<company>_<role>.tex` and `cover_letters/cover_<company>_<role>.tex` (see [`apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/apply.md) lines 54–90).

### Step 3: Research and Critique (REVIEWER)

The **REVIEWER** agent spawns as a fresh context isolated from the drafter to eliminate bias. Starting only from the company name, it researches the organization, audits factual grounding against the candidate profile ([`.claude/skills/job-application-assistant/01-candidate-profile.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/01-candidate-profile.md)), and emits structured JSON edits plus narrative suggestions (see [`apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/apply.md) lines 73–95).

### Step 4: Revise Based on Feedback (DRAFTER)

The **DRAFTER** applies the reviewer's JSON edits using the Edit tool and manually incorporates narrative suggestions. It preserves factual accuracy by never fabricating new facts beyond the canonical candidate profile (see [`apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/apply.md) lines 78–90).

### Step 5: Compile and Inspect PDFs (Mandatory)

The **DRAFTER** compiles the CV using `lualatex` and the cover letter using `xelatex`, then inspects the resulting PDFs for layout correctness, ATS readability, and keyword coverage. If validation fails, the drafter loops back to edit the LaTeX source and recompile until the documents pass all checks (see [`apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/apply.md) lines 35–95).

### Step 6: Present Final Output (DRAFTER)

In the final stage, the **DRAFTER** executes the verification checklist from [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md), lists the generated file paths, and confirms the application is ready for human review and submission (see [`apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/apply.md) lines 80–99).

## Pipeline Architecture and Source Files

The **six-step drafter-reviewer pipeline** relies on a single source of truth stored in skill files under `.claude/skills/job-application-assistant/`. This design eliminates drift between drafts and ensures reproducibility.

| File | Purpose in Pipeline |
|------|---------------------|
| [`.claude/commands/apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/apply.md) | Master specification defining the six-step execution order and agent handoffs. |
| [`.claude/skills/job-application-assistant/01-candidate-profile.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/01-candidate-profile.md) | Canonical candidate facts referenced during drafting and review. |
| [`.claude/skills/job-application-assistant/04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/04-job-evaluation.md) | Fit-evaluation rubric used in Step 1. |
| [`.claude/skills/job-application-assistant/03-writing-style.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/03-writing-style.md) | Style guide fed to both drafter and reviewer. |
| [`.claude/skills/job-application-assistant/05-cv-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/05-cv-templates.md) | LaTeX CV templates for Step 2 and 5. |
| [`.claude/skills/job-application-assistant/06-cover-letter-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/06-cover-letter-templates.md) | LaTeX cover letter templates for Step 2 and 5. |
| [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md) | Global verification checklist executed in Step 6. |
| [`tools/README_SALARY_TOOL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/README_SALARY_TOOL.md) | Documentation for the optional salary lookup in Step 1. |

## Workflow Implementation Example

The following Python pseudocode illustrates the logical flow of the `/apply` command as implemented in the repository:

```python

# Step 0: Parse input (handled by command framework)

posting = fetch_or_use_text(ARGUMENTS)
metadata = extract_metadata(posting)  # company, role, language

# Step 1: DRAFTER evaluates fit

fit_report = evaluate_fit(
    metadata, 
    candidate_profile=".claude/skills/job-application-assistant/01-candidate-profile.md"
)

# Step 2: DRAFTER drafts documents

cv_tex, cover_tex = draft_documents(
    metadata,
    style_guide=".claude/skills/job-application-assistant/03-writing-style.md",
    cv_template=".claude/skills/job-application-assistant/05-cv-templates.md",
    cover_template=".claude/skills/job-application-assistant/06-cover-letter-templates.md"
)

# Generates: cv/main_<company>_<role>.tex

# Generates: cover_letters/cover_<company>_<role>.tex

# Step 3: REVIEWER spawns fresh agent for critique

review = reviewer_agent(
    company=metadata['company'],
    role=metadata['role'],
    cv_draft=cv_tex,
    cover_draft=cover_tex,
    posting_text=posting
)

# Returns: structured JSON edits and narrative suggestions

# Step 4: DRAFTER applies feedback

cv_tex = apply_structured_edits(cv_tex, review['part_a'])
cover_tex = apply_structured_edits(cover_tex, review['part_a'])
cv_tex, cover_tex = apply_narrative_suggestions(cv_tex, cover_tex, review['part_b'])

# Step 5: Mandatory compilation and inspection

compile_latex(cv_tex, engine='lualatex', output='cv/main.pdf')
compile_latex(cover_tex, engine='xelatex', output='cover_letters/cover.pdf')
assert check_pdf_layout('cv/main.pdf')      # Validates ATS compatibility

assert check_pdf_layout('cover_letters/cover.pdf')

# Step 6: Final verification and output

execute_checklist("CLAUDE.md")
print("Application ready:")
print(f"- cv/main_{metadata['company']}_{metadata['role']}.tex")
print(f"- cover_letters/cover_{metadata['company']}_{metadata['role']}.tex")

```

This linear execution ensures that the **REVIEWER**'s critique in Step 3 remains isolated from the **DRAFTER**'s context, preventing confirmation bias during the research and audit phase.

## Summary

- The **six-step drafter-reviewer pipeline** executes linearly through [`.claude/commands/apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/apply.md), alternating between **DRAFTER** and **REVIEWER** agents.
- **Step 1** gates the workflow with a fit evaluation using [`.claude/skills/job-application-assistant/04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-application-assistant/04-job-evaluation.md).
- **Step 3** spawns an isolated reviewer agent to ensure unbiased company research and factual auditing.
- **Step 5** mandates PDF compilation with `lualatex` and `xelatex`, enforcing ATS compatibility through layout inspection.
- All steps reference canonical source files under `.claude/skills/job-application-assistant/` to maintain factual consistency.

## Frequently Asked Questions

### What is the purpose of isolating the reviewer agent in Step 3?

The **REVIEWER** agent spawns with a fresh context separate from the **DRAFTER** to eliminate confirmation bias. This isolation ensures the reviewer conducts independent company research starting only from the company name and audits facts objectively without being influenced by the drafter's initial assumptions.

### How does the pipeline handle compilation errors in Step 5?

If **Step 5** detects layout issues or ATS readability problems during PDF inspection, the **DRAFTER** automatically loops back to edit the LaTeX source files and recompiles using `lualatex` (for CV) or `xelatex` (for cover letters). This iterative process repeats until the documents pass all validation checks.

### Why does Step 1 include an optional salary lookup?

The fit evaluation in **Step 1** references [`tools/README_SALARY_TOOL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/README_SALARY_TOOL.md) to optionally enrich the recommendation with compensation data. This prevents candidates from investing effort in applications that fail basic compensation compatibility, ensuring the pipeline only processes viable opportunities.

### Where are the final LaTeX files stored?

Upon completion of **Step 6**, the pipeline stores the finalized source files as `cv/main_<company>_<role>.tex` and `cover_letters/cover_<company>_<role>.tex`, following the naming convention established in **Step 2** and verified against the checklist in [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md).