Spec sections — project heatmap by CSI MasterFormat

Joins RFIs, submittals, and change orders by spec section. The "where are reviews piling up across the project?" view a PM looks at on Monday morning.

Updated 2026-04-28

/spec-sections answers the project-level question every PM asks at the start of the week: "where on the project are reviews piling up?" It joins the three AEC daily-action surfaces (RFIs, submittals, change orders) by CSI MasterFormat spec section into one heatmap.

**Per row, you see:**

- **Spec section** — display form preserved from the source document ("08 41 13", "26 51 13", etc.). Spaced and unspaced forms aggregate into one row (the page normalizes by stripping whitespace). - **RFIs (open / total)** — open RFIs come from /rfi-tracker; matched by their location text containing the section number. Overdue RFIs (past their due date) tint red; open-but-not-yet-due tint ochre. - **Submittals (under-review / total)** — from /submittal-tracker. Same red/ochre tinting; red surfaces when any under-review submittal is past its required-by date. - **COs (pending / executed / rejected)** — from /change-order-tracker. Pending = pending + PCO; executed = signed; rejected = declined. Red appears on the pending count when any PCO older than 14 days hits the overdue-signature threshold. - **Executed cost impact** — sum of executed CO cost impacts for the section. Signed; red for additive, emerald for credits / savings. - **Pipeline cost impact** — same for pending + PCO COs (the not-yet-final dollars).

**Top-line stats** above the table: section count, total open RFIs, total open submittals, total pending COs, project-wide executed cost impact. A second line surfaces project-wide pipeline cost impact (PCO + pending) when non-zero.

**Sort order:** hottest section first. Hot = open RFIs + under-review submittals + pending COs. Sections with no open work but historical executed COs surface near the bottom for total-cost reference.

**RFI matching is typed-then-fallback (post-D130).** New RFI uploads extract a structured spec_section directly into a typed column on the rfis projection — Haiku isolates it from the more general `location` field at extract time. The page joins on the typed column when set; pre-D130 rows fall back to a case-insensitive substring match against `location` (the original heuristic). Operators see the spec sections aggregated either way; the typed path means tighter matching for new uploads (no false positives where "Sheet A-201" accidentally matches section "201").

**Why this matters.** Each individual tracker (/rfi-tracker, /submittal-tracker, /change-order-tracker) is the daily-action view for one artifact. /spec-sections is the cross-artifact strategic view: a single number per section that says "this part of the project is hot." Project managers running the Monday morning meeting want this view in seconds, not three tabs and a spreadsheet.