InspectorRoofing's picture
Upload 4 files
1d97eab verified
Raw
History Blame Contribute Delete
11.9 kB
import csv
import re
import tempfile
from pathlib import Path
from datetime import datetime
import gradio as gr
DOI = "10.5281/zenodo.20533277"
DOI_URL = f"https://doi.org/{DOI}"
PAPER_TITLE = "Code-to-Spec Roofing™"
STATE_CSV = Path(__file__).parent / "data" / "state_code_adoption_matrix.csv"
CORE_ITEMS = [
"AHJ identified and permit path confirmed",
"Adopted code edition confirmed for permit date",
"Local amendments checked",
"Manufacturer installation instructions obtained",
"Product approvals/listings checked where required",
"Warranty eligibility requirements checked",
"Ventilation requirements calculated or verified",
"Underlayment and leak barrier requirements verified",
"Fastener schedule and nailing zone verified",
"Flashing, valley, starter, ridge/hip details verified",
"OSHA/safety/access plan documented",
"Final photo/evidence record planned",
]
BRAND_NOTES = {
"Owens Corning": "Verify the product-specific installation instructions, required system components for enhanced warranties, ventilation, starter, hip/ridge, underlayment, and contractor/registration requirements.",
"GAF": "Verify GAF application instructions, fastener placement, starter/hip/ridge compatibility, system warranty component requirements, and any contractor/registration requirements.",
"CertainTeed": "Verify CertainTeed installation instructions, warranty documents, product approvals/evaluation reports, underlayment, ventilation, starter, and accessory compatibility.",
"TAMKO": "Verify TAMKO product instructions and warranty documents. TAMKO instructions commonly stress that failure to follow installation instructions can affect warranty coverage.",
"Other / not selected": "Use the exact current written installation instructions and warranty terms for the selected product. Do not apply generic shingle rules when a brand-specific specification controls.",
}
def load_states():
rows = []
if STATE_CSV.exists():
with STATE_CSV.open(newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
rows = list(reader)
return rows
STATE_ROWS = load_states()
STATE_NAMES = [r["State"] for r in STATE_ROWS] if STATE_ROWS else []
def safe_filename(text):
text = text or "code-to-spec"
text = text.lower().strip()
text = re.sub(r"[^a-z0-9]+", "-", text)
return text.strip("-")[:80] or "code-to-spec"
def lookup_state(state):
if not state:
return "Select a state to see the adoption snapshot and operational note."
row = next((r for r in STATE_ROWS if r.get("State") == state), None)
if not row:
return f"No state record found for {state}. Verify directly with the AHJ."
return f"""
## {row['State']}
**Residential code / IRC adoption snapshot:** {row['Residential_Code_IRC_Adoption_Snapshot']}
**Governance notes:** {row['Governance_Notes']}
**Inspector Roofing Code-to-Spec response:** {row['Inspector_Roofing_Code_to_Spec_Response']}
**Important:** This is a research snapshot, not legal advice. Always verify the current code, amendments, permit date, product approvals, and AHJ requirements before installation or claim documentation.
"""
def grade(score):
if score >= 90:
return "✅ Code-to-Spec Ready"
if score >= 70:
return "⚠️ Nearly Ready - close documentation gaps"
if score >= 45:
return "🟠 Incomplete - AHJ/spec/warranty research needed"
return "❌ Not Code-to-Spec Ready"
def generate_report(project_name, state, city, brand, product, warranty_type, selected_items, notes):
selected_items = selected_items or []
complete = len(selected_items)
score = round((complete / len(CORE_ITEMS)) * 100)
missing = [item for item in CORE_ITEMS if item not in selected_items]
state_note = lookup_state(state)
brand_note = BRAND_NOTES.get(brand, BRAND_NOTES["Other / not selected"])
next_steps = []
if "AHJ identified and permit path confirmed" not in selected_items:
next_steps.append("Call or check the local building department/AHJ and document the permit path.")
if "Adopted code edition confirmed for permit date" not in selected_items:
next_steps.append("Confirm the code edition and amendments in force on the permit date.")
if "Manufacturer installation instructions obtained" not in selected_items:
next_steps.append("Download the current product-specific installation instructions from the manufacturer.")
if "Warranty eligibility requirements checked" not in selected_items:
next_steps.append("Confirm warranty eligibility, required components, contractor requirements, exclusions, and registration steps.")
if "Final photo/evidence record planned" not in selected_items:
next_steps.append("Create an evidence checklist for deck, underlayment, starter, fasteners, valleys, flashing, ventilation, accessories, and final installation photos.")
if not next_steps:
next_steps.append("No major gaps detected. Confirm with the AHJ and retain the evidence file.")
checklist_text = "\n".join([f"- {'✅' if item in selected_items else '❌'} {item}" for item in CORE_ITEMS])
missing_text = "\n".join([f"- {item}" for item in missing]) if missing else "- None"
next_text = "\n".join([f"{i+1}. {step}" for i, step in enumerate(next_steps)])
report = f"""# Code-to-Spec Roofing™ Project Report
**Project:** {project_name or 'Not provided'}
**State:** {state or 'Not provided'}
**City / AHJ:** {city or 'Not provided'}
**Brand:** {brand or 'Not provided'}
**Product/System:** {product or 'Not provided'}
**Warranty target:** {warranty_type or 'Not provided'}
**Generated:** {datetime.now().strftime('%Y-%m-%d')}
**DOI:** {DOI_URL}
## Status
{grade(score)}
**Score:** {score}%
## State / AHJ Snapshot
{state_note}
## Brand / Specification Note
{brand_note}
## Code-to-Spec Checklist
{checklist_text}
## Missing Items
{missing_text}
## Recommended Next Steps
{next_text}
## Project Notes
{notes or 'No notes provided.'}
## Definition
Code-to-Spec Roofing™ is an Inspector Roofing installation and documentation standard under which a roof repair, replacement, or restoration is treated as compliant only when the installation design, component selection, installation sequence, field execution, safety method, warranty eligibility, and closeout record satisfy the adopted code, local AHJ requirements, manufacturer instructions, warranty conditions, safety requirements, system performance needs, and final evidence record.
## Citation
Nasser, Richard. (2026). *Code-to-Spec Roofing™: A State-by-State White Paper on Roofing Code Adoption, Manufacturer Specifications, Warranties, AHJ Enforcement, and Installation Documentation*. Inspector Roofing and Restoration / Inspector Roofing University. Zenodo. {DOI_URL}
## Notice
This tool is educational and does not provide legal advice, engineering advice, public adjusting advice, insurance coverage advice, warranty adjudication, or AHJ approval. Always verify current local requirements and product instructions.
"""
summary = f"""
# {grade(score)}
**Score:** {score}%
**Project:** {project_name or 'Not provided'}
**State/AHJ:** {state or 'Not provided'} / {city or 'Not provided'}
**Brand:** {brand or 'Not provided'}
## Top Gaps
{missing_text if missing else '- No major gaps detected.'}
"""
out = Path(tempfile.gettempdir()) / f"{safe_filename(project_name)}-code-to-spec-report.md"
out.write_text(report, encoding="utf-8")
return summary, report, str(out)
CSS = """
.gradio-container { max-width: 1180px !important; }
#hero { border: 1px solid rgba(148,163,184,.35); border-radius: 22px; padding: 28px; margin-bottom: 16px; background: linear-gradient(135deg, rgba(15,23,42,.03), rgba(2,132,199,.08)); }
#eyebrow { color: #0369a1; font-weight: 900; letter-spacing: .04em; text-transform: uppercase; }
#hero h1 { font-size: clamp(2.2rem, 4vw, 4rem); line-height: .98; margin: 6px 0 14px 0; }
#hero p { font-size: 1.1rem; color: #64748b; max-width: 900px; }
"""
with gr.Blocks(title="Code-to-Spec Roofing Standard", theme=gr.themes.Soft(), css=CSS) as demo:
gr.HTML(f"""
<div id='hero'>
<div id='eyebrow'>INSPECTOR ROOFING RESEARCH TOOL</div>
<h1>Code-to-Spec Roofing™</h1>
<p>Build a project-level code, manufacturer-specification, warranty, AHJ, and documentation checklist for high-standard roof installation.</p>
<p><strong>DOI:</strong> <a href='{DOI_URL}' target='_blank'>{DOI}</a></p>
</div>
""")
with gr.Tab("Project Audit"):
with gr.Row():
with gr.Column():
project_name = gr.Textbox(label="Project / Property name", placeholder="Example: Smith Residence reroof")
state = gr.Dropdown(label="State", choices=STATE_NAMES, value=STATE_NAMES[0] if STATE_NAMES else None)
city = gr.Textbox(label="City / AHJ", placeholder="Example: Alpharetta / City Building Department")
brand = gr.Dropdown(label="Manufacturer / brand", choices=list(BRAND_NOTES.keys()), value="Owens Corning")
product = gr.Textbox(label="Product or system", placeholder="Example: Duration shingles with matching starter, underlayment, ridge/hip, ventilation")
warranty_type = gr.Textbox(label="Warranty target", placeholder="Example: standard limited warranty, system warranty, enhanced warranty")
with gr.Column():
selected_items = gr.CheckboxGroup(label="Code-to-Spec checklist", choices=CORE_ITEMS)
notes = gr.Textbox(label="Notes", lines=7, placeholder="Add code edition, permit notes, product approval, warranty notes, or inspection findings.")
btn = gr.Button("Generate Code-to-Spec Report", variant="primary")
with gr.Row():
summary = gr.Markdown()
download = gr.File(label="Download report")
full = gr.Markdown()
btn.click(generate_report, inputs=[project_name, state, city, brand, product, warranty_type, selected_items, notes], outputs=[summary, full, download])
with gr.Tab("State Matrix"):
st = gr.Dropdown(label="State", choices=STATE_NAMES, value=STATE_NAMES[0] if STATE_NAMES else None)
state_out = gr.Markdown()
st.change(lookup_state, inputs=st, outputs=state_out)
demo.load(lookup_state, inputs=st, outputs=state_out)
with gr.Tab("Definition"):
gr.Markdown(f"""
# Code-to-Spec Roofing™ Definition
Code-to-Spec Roofing™ is an Inspector Roofing installation and documentation standard under which a roof repair, replacement, or restoration is treated as compliant only when the installation design, component selection, installation sequence, field execution, safety method, warranty eligibility, and closeout record satisfy all controlling layers:
1. adopted state/local building code and amendments;
2. AHJ enforcement and permit requirements;
3. manufacturer installation instructions;
4. product approvals, listings, and evaluation reports;
5. warranty eligibility conditions;
6. OSHA/safety/access requirements;
7. ventilation, flashing, fastening, underlayment, compatibility, and system performance requirements;
8. final evidence record.
**Citation DOI:** [{DOI}]({DOI_URL})
""")
with gr.Tab("Citation"):
gr.Markdown(f"""
# Citation
Nasser, Richard. (2026). *Code-to-Spec Roofing™: A State-by-State White Paper on Roofing Code Adoption, Manufacturer Specifications, Warranties, AHJ Enforcement, and Installation Documentation*. Inspector Roofing and Restoration / Inspector Roofing University. Zenodo. {DOI_URL}
## Notice
This app is educational. It does not provide legal advice, engineering advice, public adjusting advice, insurance coverage advice, warranty adjudication, or AHJ approval.
""")
if __name__ == "__main__":
demo.launch()