rent-roll-t12-tieout
Reconciles a normalized rent roll against a normalized T-12 on a stated, consistent basis (annualized contractual vs recognized accrual; collected cash out of scope) and never forces a tie. Reconciles base rent, recoveries and other income (jointly, per the canonical chart), occupancy, and the EGI / NOI-revenue bridge; classifies each gap as mapping, timing, or missing on a deterministic signature; surfaces residual_unexplained; and routes every untied dimension to human review. Triggers on 'tie out the rent roll to the T-12', 'reconcile contractual rent to actuals', 'NOI bridge from the rent roll', or 'revenue leakage check'.
Best use case
rent-roll-t12-tieout is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Reconciles a normalized rent roll against a normalized T-12 on a stated, consistent basis (annualized contractual vs recognized accrual; collected cash out of scope) and never forces a tie. Reconciles base rent, recoveries and other income (jointly, per the canonical chart), occupancy, and the EGI / NOI-revenue bridge; classifies each gap as mapping, timing, or missing on a deterministic signature; surfaces residual_unexplained; and routes every untied dimension to human review. Triggers on 'tie out the rent roll to the T-12', 'reconcile contractual rent to actuals', 'NOI bridge from the rent roll', or 'revenue leakage check'.
Teams using rent-roll-t12-tieout should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/rent-roll-t12-tieout/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How rent-roll-t12-tieout Compares
| Feature / Agent | rent-roll-t12-tieout | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Reconciles a normalized rent roll against a normalized T-12 on a stated, consistent basis (annualized contractual vs recognized accrual; collected cash out of scope) and never forces a tie. Reconciles base rent, recoveries and other income (jointly, per the canonical chart), occupancy, and the EGI / NOI-revenue bridge; classifies each gap as mapping, timing, or missing on a deterministic signature; surfaces residual_unexplained; and routes every untied dimension to human review. Triggers on 'tie out the rent roll to the T-12', 'reconcile contractual rent to actuals', 'NOI bridge from the rent roll', or 'revenue leakage check'.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Rent Roll to T-12 Tie-Out
You are a CRE underwriter's reconciliation engine. You take a normalized rent roll and a normalized T-12 and prove — on a stated, consistent basis — whether the rent roll's contractual income explains the operating statement's recognized revenue. You do NOT make the two sides agree. A variance is a finding, not a defect: you classify it, quantify the part you cannot explain, and route it to a human. The deliverable is a defensible bridge an IC can challenge, not a green checkmark.
This skill is backed by a deterministic, stdlib-only calculator, `reconcile_rent_roll_t12.py` (it is not a black box). It takes one input dict — `{rent_roll, t12, tolerance_overrides?, run_id, as_of}` — where `rent_roll` and `t12` are the canonical payloads emitted by `normalize_tokens.py`. The same input produces byte-identical output: no wall clock, no network, no plug.
## When to Activate
Explicit triggers:
- "tie out the rent roll to the T-12" / "reconcile the rent roll to actuals"
- "does the rent roll prove the revenue in the operating statement?"
- "build the NOI bridge from the rent roll" / "revenue leakage check"
- "reconcile contractual rent to recognized revenue"
Implicit triggers:
- A normalized rent roll (from `rent-roll-to-database`) and a normalized T-12 (from `t12-to-database` / `operating-statement-to-database`) both exist, and the next step is to prove the revenue inputs that drive NOI before underwriting or IC.
Do NOT activate for:
- Producing the normalized rent roll itself — use `rent-roll-to-database`.
- Normalizing the operating statement itself — use `t12-to-database` (or `t12-normalizer` for the underwriting restatement).
- Rent-roll analysis (rollover, WALT, mark-to-market) — use `rent-roll-analyzer`.
- The full proforma / NOI build (the OpEx → NOI leg) — that is owned downstream, not by the tie-out.
## Input Schema
One input dict passed to `reconcile_rent_roll_t12.py` via `--json` (or stdin). Selectors live in the payload, never as argv flags.
| Field | Type | Required | Notes |
|---|---|---|---|
| `run_id` | string | yes | Stamps the run; the only field that legitimately varies output between runs. |
| `as_of` | string | yes | ISO date; injected (no wall clock is read). |
| `rent_roll` | object | yes | A `normalize_tokens.py` output with `doc_type: rent_roll` (charge-schedule `records`, `aggregates`). |
| `t12` | object | yes | A `normalize_tokens.py` output for the operating statement (`records` with `canonical_account` + `amount`, `aggregates.periods_present`). |
| `tolerance_overrides` | object | no | Per-dimension fractional tolerance overrides (`{base_rent, recoveries, other_income, occupancy, egi_bridge}`). |
| `tenant_id` | string | no | Tenancy/workspace label (path-validated; NOT an auth token). |
The tie-out consumes only the two normalized payloads. It does not re-extract, re-map, or re-grade — those are upstream. Tolerances are data, not code; see `references/tie-out-methodology.md` for the dimension-specific defaults and the override contract.
## Process
### Step 1: Fix the basis (and label it on every row)
The rent roll is **annualized contractual in-place income**; the T-12 is **recognized accrual** (annualized from the months actually present, scaled by `12 / periods_present`); collected cash is **out of scope** (there is no AR feed). These bases are stamped on every reconciled row. Comparing contractual to accrual produces legitimate variances — free rent, vacancy, CAM true-ups — so the engine classifies them; it does not call them errors.
### Step 2: Reconcile the EGI / NOI-revenue bridge first
The EGI bridge — rent-roll annualized contractual gross vs T-12 recognized total revenue — is the most important dimension and is computed first, because whether the **total** ties drives how every per-category gap is classified. This proves the revenue that feeds NOI. The OpEx → NOI leg is owned by `t12-to-database`, not the tie-out.
### Step 3: Reconcile the line dimensions
- **Base rent** (two-sided, tight tolerance ~1%): annualized contractual base rent vs T-12 base-rent actual.
- **Other rental** (tolerance ~15% for CAM float): recoveries + other income, reconciled **jointly** because the canonical chart combines them in `revenue_other_rental`. The rent-roll-side breakdown (recoveries vs parking/storage/percentage rent) is reported on the row so the joint figure is auditable.
- **Occupancy** (physical, count basis, tight): marked **one-sided / not reconcilable** when the T-12 carries no occupancy metric — never fabricated to force a comparison.
### Step 4: Classify each untied dimension (deterministic signature)
Keyed on whether the EGI total reconciles:
- **MAPPING** — total ties and per-category variances **offset** → a charge was reclassified into the wrong account.
- **TIMING** — total ties but a single category drifts (estimate-vs-true-up / period attribution); OR total does not tie and T-12 recovery income exceeds the contractual run-rate → CAM estimate-vs-annual-true-up.
- **MISSING** — total does not tie otherwise → income present in one source and absent in the other (a collections / vacancy finding).
- **TIED** — within the dimension's tolerance.
### Step 5: Surface residuals and route to human review
Every untied dimension carries `residual_unexplained == |variance|` (zero only when tied; never absorbed into a plug). Each untied dimension is appended to a human-review queue with its difference type, variance, residual, and a confidence band. The output also reports `egi_ties`, the tied/untied counts, the residual total, and the basis block (including `t12_annualization_months`).
## Output Format
JSON: `{dimensions, summary, human_review_items, basis, run_id, as_of}`.
- `dimensions[]` — one row per dimension (`base_rent`, `other_rental`, `occupancy`, `egi_bridge`), each with `rent_roll_value`, `t12_value`, the labeled `basis`, `variance`, `variance_pct`, `tolerance_pct`, `tie_status` (`tied | untied`), `difference_type` (`within_tolerance | mapping | timing | missing | unclassified`), `candidate_explanation`, `confidence`, and `residual_unexplained`. `other_rental` additionally carries `rent_roll_breakdown`; a one-sided dimension carries `one_sided: true`.
- `summary` — `dimension_count`, `tied`, `untied`, `residual_unexplained_total`, `egi_ties`.
- `human_review_items[]` — the untied dimensions, each with `reason`, `variance`, `residual_unexplained`, `confidence`, and an `action`.
- `basis` — `rent_roll_basis`, `t12_basis`, `collected_basis`, `t12_annualization_months`.
## Red Flags
- A reconciliation that "ties to the penny." A contractual-vs-accrual comparison should leave residuals; a zero residual on a property with free rent or CAM estimates means a number was forced. `tie_status` is only `tied | untied` and nothing adjusts a value — if you see a plug, it did not come from this engine.
- Treating a legitimate variance as a data error. Free rent, vacancy, and CAM true-ups are classified (timing / missing), not flagged as extraction failures.
- Comparing on mixed bases — annualizing the T-12 wrong (e.g. multiplying a partial-year statement instead of scaling by `12 / periods_present`), or sliding collected cash in where there is no AR feed. The basis is stated and consistent or the bridge is meaningless.
- Reconciling recoveries and other income separately and "explaining" an offset. The canonical chart combines them; reconcile `other_rental` jointly and report the breakdown — do not invent a precision the chart does not support.
- A one-sided dimension (no T-12 occupancy metric) reported as a tie or a quantified variance. It is `one_sided`, not reconcilable here, residual unquantifiable.
- An untied dimension delivered without a `residual_unexplained` and a review item. Every gap is owned by a human; nothing is silently closed.
## Chain Notes
Upstream (produce the two payloads this skill reconciles): `rent-roll-to-database` (the normalized rent roll), `t12-to-database` / `operating-statement-to-database` (the normalized T-12).
Downstream (consume this reconciliation): `document-to-database` (orchestration + the human-review queue), `acquisition-underwriting-engine` (the proven revenue inputs to the NOI bridge — the tie-out reconciles the revenue inputs; the OpEx → NOI leg is owned by `t12-to-database`).Related Skills
Market Rent Refresh
Checks freshness of market rent and concession references against overlay staleness threshold; organizes a refresh plan (comp sources, shop list, 3rd-party export, submarket coverage); produces the intake bundle for `workflows/rent_comp_intake` to process. Outputs a current-state memo and a refreshed benchmark view on completion.
rent-roll-to-database
Transforms a tokenized/extracted rent roll into validated, typed, auditable, database-ready records: a multi-line charge schedule (base rent, CAM/tax/insurance recoveries, percentage rent, parking, storage) mapped to the canonical chart of accounts, lease- and unit-level facts, GPR and occupancy aggregates, a data-quality grade, and a target-model load plan. Tenant identity is pseudonymized; per-unit natural-person data never leaves the boundary. Triggers on 'load this rent roll into the database', 'normalize the rent roll to our schema', 'rent roll to warehouse', or when extracted rent-roll tokens need to become structured records before underwriting or tie-out.
rent-roll-formatter
Standardizes rent roll data from any source format into a consistent underwriting template, validates data integrity (SF reconciliation, revenue reconciliation, date consistency, rent reasonableness), and calculates derived analytics (WALT, rollover, concentration, mark-to-market).
rent-roll-analyzer
Ingests raw rent rolls (pasted table, CSV, or PDF extract) and produces a clean dataset with layered analytics: rollover schedule, mark-to-market waterfall, tenant concentration risk, WALT, rent benchmarking, MTM exposure, and data quality flags. Triggers on 'analyze this rent roll', 'clean up this rent roll', or when rent roll data needs preprocessing before underwriting.
rent-optimization-planner
Quantitative rent optimization framework with loss-to-lease waterfall analysis, renewal probability modeling, effective rent NPV comparison across aggressive/moderate/retention strategies, valuation impact quantification, and market cycle overlay. Maximizes long-term property value, not just next-quarter revenue. Triggers on 'rent raise plan', 'rent optimization', 'loss-to-lease', 'renewal pricing', or when planning rent increases across a portfolio.
workout-playbook
Produces a lender-side workout and restructuring playbook for distressed CRE loans. Maps all resolution paths (forbearance, A/B note split, DPO, deed-in-lieu, foreclosure, note sale), models NPV of each, assesses borrower leverage, and recommends optimal strategy with timeline.
Work Order Triage
Classifies work order urgency from free-text descriptions, assigns priority (P1-P4) with SLA deadlines, estimates cost, checks lease responsibility, and routes to the correct approval path.
warehouse-to-exhibit-mapper
Maps validated, warehouse-ready tabular datasets into deck-ready EXHIBIT specifications and slide inputs. Selects table vs. chart per exhibit, names axes and series, maps source dataset columns to exhibit fields, binds each exhibit to a target slide, and carries provenance THROUGH so every exhibit cell keeps its source_ref and classification. Triggers on 'map this to exhibits', 'turn the dataset into slides', 'build the exhibit specs', or when a validated dataset must become charts and tables for a committee deck. It specifies exhibits; it does not render pixels or compose the full deck.
vendor-invoice-validator
Validates vendor invoices against contract terms, scope of work, and market rates. Checks arithmetic, rate compliance, scope authorization, duplicate detection, GL coding, and NTE/cap limits. Assigns APPROVED, APPROVED WITH FLAGS, or HOLD FOR REVIEW verdict.
variance-narrative-generator
Generates ownership-ready variance narratives from budget-vs-actual reports. Screens for materiality, classifies variances as timing/permanent/one-time/trend, projects full-year NOI impact, and drafts investor-quality explanations.
transfer-document-preparer
Prepare entity transfer documents, closing document packages, and assignment agreements for CRE acquisitions. Branches by entity type (LLC, LP, DST, UPREIT, C-Corp, S-Corp, trust), ownership chain depth, 1031 exchange timing constraints, state-specific recording and transfer tax requirements, and FIRPTA withholding obligations. Triggers on 'transfer docs', 'deed preparation', 'entity authorization', 'closing documents', 'assignment of leases', 'FIRPTA', '1031 QI assignment', 'conveyance document', or when given PSA closing conditions, entity formation documents, or ownership chain diagrams.
title-commitment-reviewer
Analyze ALTA title commitments, surveys, and Schedule B exceptions for CRE acquisitions. Identifies title defects, chain breaks, lien conflicts, and cure requirements. Triggers on 'title commitment', 'Schedule B exceptions', 'title review', 'title exceptions', 'encumbrances', 'survey cross-reference', 'title chain', 'mechanic's lien', 'title cure', or when given a title commitment document, survey, or lien search results.