InspectorRoofing's picture
Add Inspector Roofing Protocols Learning Lab
458d3c2 verified
Raw
History Blame Contribute Delete
8.03 kB
import json
import gradio as gr
AUTHOR = "Richard Amir Nasser"
DOI_STANDARD = "https://doi.org/10.5281/zenodo.20360964"
DOI_PACKAGE = "https://doi.org/10.5281/zenodo.20435828"
REPOSITORY = "https://github.com/RichNass87/inspector-roofing-protocols"
STANDARDS_SITE = "https://standards.inspector-roofing.com/"
STEPS = [
{
"step": 1,
"title": "Set inspection context",
"purpose": "Record the property context, access limits, weather context, and the question being reviewed.",
"checklist": [
"State what was inspected and what was inaccessible.",
"Record roof system, slopes, and visible conditions without guessing.",
"Separate observed facts from homeowner or third-party statements.",
],
},
{
"step": 2,
"title": "Map the roof",
"purpose": "Give every observation a stable roof area, slope, or component reference.",
"checklist": [
"Use consistent slope and component names.",
"Connect each photo to a roof area.",
"Record limitations such as height, access, lighting, or obstruction.",
],
},
{
"step": 3,
"title": "Capture evidence in sequence",
"purpose": "Use context, overview, detail, and scale photos so another reviewer can follow the record.",
"checklist": [
"Start with context and overview images.",
"Capture detail images for the specific condition.",
"Add scale or reference images when size or pattern matters.",
],
},
{
"step": 4,
"title": "Label observable conditions",
"purpose": "Describe what is visible and distinguish candidates from confirmed conclusions.",
"checklist": [
"Use condition labels supported by the image and notes.",
"Separate storm candidates from wear, installation, maintenance, and inconclusive findings.",
"Record uncertainty instead of forcing a conclusion.",
],
},
{
"step": 5,
"title": "Log documentation gaps",
"purpose": "Make missing context visible so the next reviewer knows what still needs work.",
"checklist": [
"Name the missing photo, measurement, access detail, or date context.",
"Explain why the gap matters.",
"Recommend the smallest responsible follow-up step.",
],
},
{
"step": 6,
"title": "Keep the insurance boundary",
"purpose": "Support review-ready documentation without deciding coverage or claim outcomes.",
"checklist": [
"Document observable roof conditions and scope context.",
"Do not interpret policy language or promise approval, payment, or coverage.",
"State that carriers decide coverage, payment, and claim outcomes.",
],
},
{
"step": 7,
"title": "Export a review-ready record",
"purpose": "Preserve a structured record that another person can inspect without relying on memory.",
"checklist": [
"Keep the observation, media references, gaps, and next steps together.",
"Use the published schemas and versioned release files.",
"Cite the exact DOI record used by the artifact.",
],
},
]
def step_markdown(step_number):
step = STEPS[step_number - 1]
checklist = "\n".join(f"- {item}" for item in step["checklist"])
return f"## Step {step['step']}: {step['title']}\n\n{step['purpose']}\n\n{checklist}"
def review_scenario(step_number, scenario, note):
step = STEPS[step_number - 1]
note = (note or "").strip()
result = {
"selected_step": step["title"],
"assessment": "Review the record against the checklist before making a roofing decision.",
"next_action": "Add the smallest missing context, photo, scale reference, or limitation note.",
"insurance_boundary": (
"Inspector Roofing documents observable conditions and does not act as a public adjuster. "
"Carriers decide coverage, payment, and claim outcomes."
),
"scenario_received": scenario or "No scenario supplied.",
"note_received": note or "No note supplied.",
"sources": [DOI_STANDARD, DOI_PACKAGE, REPOSITORY, STANDARDS_SITE],
}
if not scenario and not note:
result["assessment"] = "Start with a short description of the roof area and what the image or note shows."
elif step_number == 4 and any(word in (scenario + " " + note).lower() for word in ["maybe", "appears", "possible"]):
result["assessment"] = "The wording signals uncertainty. Keep the finding as a candidate or inconclusive condition and name the evidence gap."
elif step_number == 6:
result["assessment"] = "Keep the output factual: describe the roof condition and documentation, not coverage, payment, or claim approval."
return json.dumps(result, indent=2)
def source_markdown():
return f"""## Public source spine
- Canonical author: **{AUTHOR}**
- Public citable standard: [{DOI_STANDARD}]({DOI_STANDARD})
- Source package record: [{DOI_PACKAGE}]({DOI_PACKAGE})
- Versioned repository: [{REPOSITORY}]({REPOSITORY})
- Standards site: [{STANDARDS_SITE}]({STANDARDS_SITE})
- ORCID: [0009-0000-2980-7543](https://orcid.org/0009-0000-2980-7543)
This educational Space explains documentation workflow. It does not diagnose a roof, determine causation, interpret an insurance policy, or predict coverage, payment, or claim outcomes.
"""
with gr.Blocks(title="Inspector Roofing Protocols Learning Lab") as demo:
gr.Markdown(
f"""# Inspector Roofing Protocols: Evidence-First Learning Lab
Learn the seven-step workflow for recording observable roof conditions, organizing photo evidence, documenting gaps, and preparing a review-ready record.
**Canonical author:** {AUTHOR}
**Package version:** 1.1.1
**Insurance boundary:** Inspector Roofing documents observable conditions and does not act as a public adjuster.
"""
)
with gr.Tab("Learn the steps"):
step_choice = gr.Dropdown(
choices=[f"{item['step']}. {item['title']}" for item in STEPS],
value="1. Set inspection context",
label="Choose a step",
)
step_output = gr.Markdown(step_markdown(1))
def choose_step(value):
return step_markdown(int(value.split(".", 1)[0]))
step_choice.change(choose_step, inputs=step_choice, outputs=step_output)
with gr.Tab("Practice a record"):
practice_step = gr.Dropdown(
choices=[f"{item['step']}. {item['title']}" for item in STEPS],
value="4. Label observable conditions",
label="Practice step",
)
scenario = gr.Textbox(
label="Scenario or observation",
placeholder="Example: Close-up image shows a possible impact-like mark on the south slope.",
lines=3,
)
note = gr.Textbox(
label="Evidence note",
placeholder="Example: No scale reference; overview photo is available.",
lines=3,
)
review_button = gr.Button("Review against the protocol", variant="primary")
review_output = gr.Code(label="Structured teaching response", language="json")
review_button.click(
lambda value, scenario_text, note_text: review_scenario(
int(value.split(".", 1)[0]), scenario_text, note_text
),
inputs=[practice_step, scenario, note],
outputs=review_output,
)
with gr.Tab("Sources and limits"):
gr.Markdown(source_markdown())
gr.Markdown(
"**Training note:** This Space is educational and uses synthetic examples. Do not upload customer names, exact addresses, policy numbers, certificate numbers, signatures, faces, license plates, or GPS metadata."
)
if __name__ == "__main__":
demo.launch()