File size: 8,030 Bytes
458d3c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
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()