git:20261012.ef63379 to git:20261015.b69c71b

4 added, 2 removed. Audit A to A.

---
name: sheet-splitter
description: >
Split a bound drawing set PDF into individual sheet PDFs. Extracts sheet
numbers from title blocks via vision, renames files. Triggers: 'split
drawings', 'break up the drawing set', 'separate sheets'. Run after
/project-setup.
argument-hint: "<drawing_set.pdf> [--output-dir <path>]"
disable-model-invocation: true
---
# Sheet Splitter
Splits a bound drawing set PDF into individual page PDFs. Mirrors what spec-splitter does for specifications.
## Pipeline Position
Run after `/project-setup` identifies bound drawing sets. Produces split PDFs and `sheet_index.yaml` consumed by `/schedule-extractor` and all drawing analysis skills.
This is valuable for:
- **Project teams**: Navigate drawings by sheet number instead of scrolling a multi-page PDF
- **Other skills**: schedule-extractor, tag-audit-and-takeoff, pe-review and every other drawing analysis skill work better with individual sheet files
In an AgentCM project the app splits drawing sets (Split & Rename), and this skill only says so (Step 1).
## Workflow
```
Sheet Split Progress:
- [ ] Step 1: Check the mode, and whether drawings are already split
- [ ] Step 2: Locate the bound drawing set
- [ ] Step 3: Split into individual page PDFs
- [ ] Step 4: Extract sheet numbers from title blocks
- [ ] Step 5: Rename files with sheet number + title
- [ ] Step 6: Update project context
```
### Step 1: Check the Mode, and Whether Drawings Are Already Split
First read `.construction/project.yaml`. If it exists, AgentCM manages this folder: do not split, rename or index anything.
- Read `.construction/index/sheet_index.yaml`. When its entries carry AgentCM's sheet ids (a `sheets:` list whose entries each have an `id:`), report how many sheets AgentCM holds and tell the PE that a new or reissued bound set is split with **Split & Rename** in AgentCM, which keeps every sheet's id. A split made here writes PDFs AgentCM never registers, and its Rescan would index them as a second drawing set. Then stop.
- When that file is missing, or its entries have no `id` (an older sheet-splitter wrote a `pages:` list with `filename` and `page_index`), say which, say that this skill does not guess sheet ids, and stop. Do not edit the file.
Without `.construction/project.yaml`, drawings are already split if:
- Multiple PDFs exist with sheet number patterns in filenames (e.g., `A-1.1 - FLOOR PLAN.pdf`)
- A `sheet_index.yaml` exists in the drawings directory
If already split, report the count and skip.
### Step 2: Find ALL Drawing PDFs
Search the project directory for ALL PDFs that are drawings. Many projects have multiple drawing PDFs:
- **Multi-part sets**: Part1.pdf, Part2.pdf, Part3.pdf (split by file size)
- **Discipline sets**: Architectural.pdf, Civil.pdf, Electrical.pdf, Mechanical.pdf
- **Single combined**: one large PDF with all sheets
Search in:
- Folders named `drawings/`, `plans/`, `01 - Drawings/`, or similar (case-insensitive)
- The project root (some projects have no folder structure)
- Look for PDFs > 2MB with keywords: "plan", "drawing", "bid set", "dwg", discipline names
Process EACH PDF found. All split pages go to the same `sheets/` output directory.
If the user specifies a single file (`/sheet-splitter path/to/specific.pdf`), process only that file.
### Step 3: Split Pages
Run the split script on each drawing PDF found:
```bash
"${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_SKILL_DIR}/scripts/split_drawing_set.py" \
"{drawing_set.pdf}" \
--output-dir "{drawings_directory}/sheets"
```
The script splits each page into its own PDF: `page_001.pdf`, `page_002.pdf`, etc. It does NOT attempt to read sheet numbers — that's unreliable across different title block formats.
### Step 4: Identify Sheets via Vision
After splitting, read each page to identify sheet numbers and titles:
Use PDF bookmarks and the title-block text layer only as candidates — they are often abbreviated or stale (e.g. a bookmark "Site Grading Plan" on a sheet printed "Proposed Site Plan"). The printed title block wins. Read the title block by vision whenever there is no candidate, the candidate disagrees with the title-block text, or the sheet number carries a suffix (e.g. `C9.04H`, `K-1.1`).
- 1. Rasterize the title block region of each page:
+ 1. Rasterize the title block region of each page, from the project folder:
```bash
- "${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_PLUGIN_ROOT}/scripts/pdf/rasterize_page.py" "page_NNN.pdf" 1 --dpi 200 --output tb.png
+ mkdir -p ".construction/skills/sheet-splitter/pages"
+ "${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_PLUGIN_ROOT}/scripts/pdf/rasterize_page.py" "{sheets_dir}/page_NNN.pdf" 1 --dpi 200 --output ".construction/skills/sheet-splitter/pages/tb_NNN.png"
```
+ Title-block images are working data: keep them under `.construction/skills/sheet-splitter/pages/`. Never put them in the sheets folder, where the PE's split sheets are, and never in `/tmp` or any other folder outside the project.
2. Use vision on the rasterized title block: "Read the title block on this construction drawing. What is the sheet number and sheet title?"
3. Rename the file: `page_001.pdf` → `A-1.1 - FLOOR PLAN.pdf`
4. Update `sheet_index.yaml` with the identified sheet number, title, and discipline. When a bookmark title differs from the printed title, keep it as `bookmark_title`.
**Title blocks vary significantly across firms** — they can be on the east side, south side, or bottom-center. Some use VA standard forms, some use firm-specific formats. Vision handles all these variations.
### Step 5: Write Sheet Index
After identifying all sheets, write `{drawings_directory}/sheets/sheet_index.yaml` (shown below). Never write `.construction/index/` — that folder belongs to AgentCM; only read it.
### Output
```
sheets/
A-1.1 - FLOOR PLAN.pdf ← renamed by Claude via vision
A-2.1 - ELEVATIONS.pdf
S-1.1 - FOUNDATION PLAN.pdf
page_006.pdf ← could not read title block
...
sheet_index.yaml
```
### Step 6: Update Project Context
After splitting and identifying, update `.construction/skills/project_context.yaml` with:
- `documents.drawing_count`: number of sheets
- `documents.disciplines`: list of unique discipline prefixes found
The `sheet_index.yaml` in the sheets folder is the record of the split.
### Multi-Set Projects
When a project has multiple drawing set PDFs (e.g., Architectural, MEP, Civil as separate files), use the source PDF name as a subdirectory to avoid filename collisions:
```
sheets/
Architectural_Bid_Set/
page_001.pdf ... page_050.pdf
MEP_Bid_Set/
page_001.pdf ... page_030.pdf
sheet_index.yaml ← merged from all sets
```
Pass `--output-dir "{drawings_directory}/sheets/{source_pdf_stem}"` to the split script for each set. The `sheet_index.yaml` merge logic combines entries from all subdirectories into a single index.
Report to user: number of pages split, how many identified via vision, output location.
## File Safety
Never overwrite existing split sheet PDFs. If `sheets/` directory already contains files, check for conflicts before writing. The `sheet_index.yaml` merge uses additive logic — existing entries are preserved.
---
## Allowed Scripts
**Allowed scripts — exhaustive list.** Only execute these scripts during this skill:
- `scripts/split_drawing_set.py` — split bound PDF into per-page PDFs
- `${CLAUDE_PLUGIN_ROOT}/scripts/pdf/rasterize_page.py` — rasterize PDF pages for vision identification