---
name: match-builder
description: "Compose a complete USPSA match (the .usmatch file consumed by Match Day) by interviewing a match director about match shape (stage count, classifier mix, round count, character) and venue/MD details, then picking a balanced selection of stages from the bundled classifier set (plus any saved custom stages the user names), driving the Match Builder dialog at https://itsmatchday.app/build/, and writing the final .usmatch to the user's preferred save location. Profiles for repeat venues + MDs persist to ~/Documents/Match Day/profiles/. Use this skill when the user says anything like 'build me a match', 'plan a match', 'compose a match', 'use the match builder', 'let's plan Saturday's match', 'put a match together for the club', or asks for a complete match deliverable they can hand to a club. NOT for designing individual stages — for that, use the stage-builder skill instead."
---

# Match Builder

End-to-end skill for composing a USPSA match: interview the match director, pick a balanced stage selection from bundled classifiers + named custom stages, drive the web Match Builder, and produce a `.usmatch` file ready to share or open on the iOS app.

## When to invoke

Trigger phrases:
- "Build me a match" / "plan a match" / "compose a match" / "put together a match"
- "Let's plan Saturday's match" / "the club match"
- "Use the match builder" / "match builder"

**Do NOT invoke for:**
- Individual stage design — use `stage-builder` for that
- USPSA classifier authoring (CM XX-YY from a PDF) — that's a separate workflow

## Pipeline overview

```
1. Greet + ask name + date (conversational)
2. Load saved venue + MD profiles from ~/Documents/Match Day/profiles/
3. Call 1 — match shape (4 questions via AskUserQuestion)
4. Call 2 — venue + MD selection (1-3 questions, choices populated from profiles)
5. (Optional) Ask the user for any named custom stages to include
6. Plan: pick stages from references/classifier_index.md based on prefs
7. State the plan; let the user redirect before authoring
8. Compose Match JSON (mostly `ref` entries; `inline` for custom stages)
9. Drive the editor's Match Builder to validate + visualize
10. Write .usmatch file to user's preferred location
11. Offer to save venue/MD as a profile for next time
12. Iterate on critique
```

## Step 1 — Greet + match basics (conversational)

Short, no preamble. Ask the user:
- **Match name** (e.g., "APSC Pistol Match", "Saturday Night Pistol")
- **Date** (default suggestion: next Saturday)

Use a sensible default and offer it, don't force them to type the full date:

> *"Sure — what's the match called? And what date is it? (I'll default to next Saturday if you don't specify.)"*

## Step 2 — Load saved profiles

Before the AskUserQuestion calls, check `~/Documents/Match Day/profiles/`:
- `venues/*.json` — venue profile files
- `directors/*.json` — MD profile files

If profiles exist, surface them as named options in Call 2. If the directory doesn't exist, that's fine — it'll be created on first save.

See `references/profile_storage.md` for the JSON shape + read/write conventions.

## Step 3 — Call 1: match shape (4 questions)

Use `AskUserQuestion` with these four:

1. **Stage count**
   - Header: `Stages`
   - Options: `3 stages (short club night)`, `4 stages`, `5 stages`, `6 stages (full club match)`
   - This drives total round count and skill's stage-picking strategy.

2. **Classifier inclusion**
   - Header: `Classifiers`
   - Options: `None — all field courses`, `1 classifier`, `2 classifiers`, `Balanced — let the skill decide`
   - "Balanced" picks ~30-50% classifiers depending on stage count.

3. **Round count target**
   - Header: `Round count`
   - Options: `~80 (short)`, `~120 (medium)`, `~150`, `~180+ (long)`
   - Used to pick between short (12-round) and longer (24-round) classifiers.

4. **Stage character**
   - Header: `Character`
   - Options: `Speed-focused (lots of steel, open targets)`, `Balanced`, `Accuracy-focused (hard cover, partials, distance)`, `Standards-heavy (mandatory reloads, fixed-position)`
   - Maps to the `style` tag in `references/classifier_index.md`.

## Step 4 — Call 2: venue + MD

If saved profiles exist, build options like:

1. **Venue**
   - Header: `Venue`
   - Options: `Brazos Valley Shooting Club (saved)`, `Add new venue`, `Skip — no venue info`
   - "Other" lets the user type a free-text venue name to populate just the name.

2. **Match Director**
   - Header: `Director`
   - Options: `Jory Hanus (saved)`, `Add new MD`, `Skip — no MD attribution`

If "Add new venue" / "Add new MD" is picked, ask conversationally for the fields (venue name, address, parking notes, etc.; MD name, USPSA member #, email). See `references/usmatch_format.md` for the field list.

## Step 5 — Optional custom stages

Ask conversationally: *"Want to include any of your own field courses? Tell me the name (I'll find the file) or say no."*

If the user names a stage, resolve it per `references/stage_resolution.md`:
- Check bundled classifiers (e.g., "Three Doors" → no, that's a custom stage)
- Check `~/Desktop/new stage designs/`
- Check `~/Downloads/`
- Fall back to asking the user for a path if ambiguous

When you resolve a custom stage, the skill INLINES the full Stage JSON into the match's `stages` array (vs `ref` for bundled classifiers).

## Step 6 — Plan + state the thesis

Based on the answers, pick a stage list from `references/classifier_index.md`. Stating the plan back is important — the user may redirect before authoring:

> *"Going with 5 stages, ~120 rounds, balanced character — CM 99-08 (Melody Line, hardcover standards), CM 99-28 (Hillbillton Drill, paper + steel), CM 99-42 (Fast'n Furious, big movement), CM 99-19 (Payne's Pain, port shooting), plus your Three Doors field course. Sound good?"*

## Step 7 — Compose the Match JSON

See `references/usmatch_format.md` for the full v1 schema. Minimum viable shape:

```json
{
  "schemaVersion": 1,
  "id": "<uuid>",
  "name": "<match name>",
  "date": "2026-05-30T00:00:00Z",
  "stages": [
    { "ref": "CM 99-08" },
    { "ref": "CM 99-28" },
    { "inline": { ...full Stage v2 JSON for the custom course... } }
  ],
  "venue": { ... },
  "matchDirector": { ... }
}
```

## Step 8 — Drive the Match Builder

Follow `references/match_builder_api.md` to:
1. Start the preview server (`preview_start name="match-day-editor"`).
2. Navigate to `https://itsmatchday.app/build/?match=<base64-or-url>` so the Match Builder dialog opens with the composed match pre-loaded.
3. (Alternative if the deep-link isn't available in the user's editor version) Open the Match Builder dialog manually + use `mbApplyUsmatch()` via `preview_eval` to inject the composed JSON.
4. Screenshot the result; ask the user to flag anything wrong.

## Step 9 — Write the .usmatch file

Default save location: ask the user. Sensible defaults to suggest:
- `~/Desktop/Match Day matches/<YYYY-MM-DD>_<name>.usmatch`
- `~/Documents/Match Day/matches/<YYYY-MM-DD>_<name>.usmatch`

Create the folder if it doesn't exist. The `.usmatch` extension matters — Match Day iOS recognizes it for AirDrop import.

## Step 10 — Offer to save the venue/MD profile

After the file is written:

> *"Save the venue and MD details as a profile for next time? Yes / Yes (venue only) / Yes (MD only) / No"*

If yes, write to `~/Documents/Match Day/profiles/venues/<slug>.json` and/or `~/Documents/Match Day/profiles/directors/<slug>.json`. See `references/profile_storage.md`.

## Step 11 — Iterate

After save, ask: *"What would you change?"* Common iterations:
- Swap one stage for another (re-pick from index)
- Add or remove a classifier
- Change the round-count target
- Adjust venue or MD details
- Add notes for the squad chief

For each iteration: apply the change as a small JSON patch (don't rebuild from scratch), screenshot, then re-save the `.usmatch`.

## Critical rules

1. **Match name is required.** The editor's export validation rejects empty names.
2. **At least 1 stage is required.** Empty stages array fails validation.
3. **Each stage Entry has EXACTLY ONE of `ref` or `inline`** — never both, never neither.
4. **Use `ref` for bundled classifiers** (compact; recipient resolves from their bundled set). Use `inline` for custom stages (self-contained; recipient gets the full Stage JSON).
5. **Date should be in ISO 8601 UTC** (e.g., `2026-05-30T00:00:00Z`).
6. **schemaVersion is `1`** for matches (NOT 2 — that's the stage schema).
7. **No round-count balance rule is enforced**, but as a guideline: standard club match is ~100-180 rounds across 4-6 stages.

## References (load on demand)

- `references/classifier_index.md` — bundled classifier catalog with characteristics
- `references/match_pipeline.md` — assembly logic, stage-picking algorithm
- `references/match_builder_api.md` — concrete recipes for driving the web Match Builder via `preview_eval`
- `references/stage_resolution.md` — name-to-file resolution across bundled + saved stages
- `references/profile_storage.md` — venue + MD profile read/write conventions
- `references/usmatch_format.md` — Match JSON v1 schema reference

## Tone

Default to **terse engineering** with the user — short status updates between steps, no preamble. State the plan in one sentence before composing. Save the prose for the final match's `notes` field if the user wants squad-chief instructions.
