Track T gave the server a full verification model and never gave it a design. A homeowner who spent more money than they ever have, on something that did not exist yet, should be able to see that what was decided actually got checked. This is the surface where the person holding the job puts that proof on the record, and the record they both read afterward.
0073’s append trigger compares. Q131 now gives the kind an attributed writer; null kinds stay in frame 11 until somebody classifies them.Framing, north elevation
Passed 6 August · R. Alvarez
Framing, garage
Booked 12 August · nobody has resulted it yet
Framing, re-inspection
Failed 2 August · R. Alvarez
A booked inspection with no result yet is in the list. The trigger requires the event’s four snapshot columns to equal the live inspection row, and a booked one matches on nulls, so attaching it is legal and the result lands afterward. The decision stays pending until it does. A failed inspection is in the list too: attaching a failure is the honest act, and it is what puts the amber on the homeowner’s screen.
Reached from the Checked row on page 43, which every reader shares. Without manage_decisions this same screen draws the state and the way into history and blocks attachment and removal. A separate book_inspection grant may still offer classification and save that attributed fact. Capabilities control what a screen offers, never where a link goes.
Nothing on this project can satisfy this yet.
Frame 1’s “Attach this proof” is live because a row above it can be chosen. Here nothing on the screen can put a row in that list, so the same button would sit disabled for the life of the project. Frame 6 already says it: never a disabled button that says nothing about itself. The row is the act, and tapping it opens frame 3.
Eligibility still turns only on inspections.evidence_kind. A differently classified inspection does not appear merely because it is convenient, and a null-kind inspection appears separately in frame 11 rather than being treated as eligible. This exact frame means neither set has a row; it never means the project has no inspections.
Drop the report here, or pick from your files
It passed
It passed in part
It failed
You are recording what the report says. Your name goes on this alongside it, and the record keeps both.
This is the only place in the app where somebody attests to a reading of somebody else’s document. The builder is standing behind that reading, and it should be stated before they save rather than discovered in the history afterward. The line is part of the design, not decoration.
The date is a calendar date and is sent exactly as written: converting it moves the day west of Greenwich. The signer is optional, and empty means absent rather than present-and-empty, which is a different request and one the server rejects.
Only a verification letter satisfies this one. An inspection or a test report will not do, and the server refuses them.
Truss engineering letter.pdf
Added 6 August by Dana Ruiz
Or drop a new letter here
Whatever is chosen is what gets sent. An upload and a tapped row cannot both be live at once, or the shown choice and the sent evidence can disagree — and on the one screen whose subject is proof, that is the failure that matters. Both funnel through a single selection.
A project with no letter on file yet still needs a way in, which is why the drop is here rather than only the list. A lane that can only pick from an empty list is a requirement nobody can ever satisfy.
Nothing here can be edited or deleted. The record is what it is.
The log carries attach, refresh and clear. A refresh is appended by the database itself: when a result lands on an inspection somebody already attached, the trigger writes one. It reads Result updated by rather than Attached by, because the person whose seat updated the inspection did not attach the proof, and crediting them with it would be a lie the log tells quietly.
Same screen for the homeowner and the builder, from the same row. A clear is never silent, and the current proof is the only row that carries Now.
Connect to add verification
Proof is written straight to the record and cannot be queued, because a record that might be true later is not a record.
The constraint is architectural rather than principled, and the spec says so plainly: putEvidence calls the API directly and there is no outbox path, so an offline save has nowhere to go. The sentence in the callout is what we give a reader, not the reason it is so. Nobody chose online-only on that argument.
Every other write in this app queues, so the exception needs its reason stated or it reads as a bug. What it must never be is a grayed control that says only no.
Marcus Reed attached proof while you were filling this in.
Framing inspection, passed on 6 August, signed by R. Alvarez.
This is the only lane that has typed fields, so the card carries the outcome, the date and the signer as well as the file. Without them, Replace it with mine posts three facts the reader cannot see and cannot check.
Replace is primary because the builder came here to attach something and still has it ready; keeping the other proof is the outlined twin rather than a ghost, so the two read as one real choice instead of an action and an afterthought. .btn-area is a flex row with no column variant, so this page scopes its own stack. A stacked variant belongs in the sheet: raised, not designed here.
What the server sends back is only a refusal, with no body naming the winner, so the screen syncs first and then builds this from what came down. Building it from what we already held would show the reader their own rejected proof under somebody else’s name.
This decision was settled again on 20 August.
Proof belongs to the settlement in force. What is below is the record of the one it replaced, and it cannot take anything new.
“Settled again on 20 August” is the resolution’s timestamp, not the verification’s. They are different rows with different clocks, and reaching for the nearer one prints the day the old proof was attached and calls it the day the decision moved — wrong by two weeks, stated as fact.
It is captured before the sync that discovers the move. After the sync the client has followed the new settlement and the old proof is gone, so anything read afterward would be the wrong settlement’s record under a header naming the right one.
When nothing was ever attached to the replaced settlement, the callout says so rather than promising a record below it that does not exist. The row pointing forward stays either way: a screen that refuses every action still owes the reader somewhere to go.
Under the proof row and the history row, above the eligible list and “Attach this proof”. Appended below the lane instead, a reader wanting to take proof off scrolled past every way of putting more on to reach it.
With nothing attached, or with the proof already removed, there is no control here at all. The server refuses a clear in both states, so a button would be one whose only outcome is a refusal — the same rule the letter lane’s dead CTA cost three rounds to learn. Offline it is absent too: a clear goes straight to the API with no outbox, so frame 6’s reason is what the reader gets instead.
Nothing is destroyed. 0073 appends a clear event beside the attach, so the record keeps both and the history screen names who removed what. A modal would claim a finality the act does not have. What the reader actually needs is to know whose work this is and what removing it will say about them, which is a sentence.
With nothing attached, or with the proof already removed, there is no control here at all. The server refuses a clear in both states, so a button would be one whose only outcome is a refusal — the same rule the letter lane’s dead CTA cost three rounds to learn.
The gate is manage_decisions, the same capability that gates attaching, so the homeowner may remove: they own the data. Ruled with it, and deliberately not built, is the payer rule — if the builder is paying, the homeowner cannot remove the builder’s proof. No builder can be the payer yet, so the branch is unreachable and would be a gate nothing enters. Q132 holds it for whoever builds Z14.
Framing, north elevation
Blower-door visit
The durable vocabulary remains exactly inspection or test. Null means nobody has stated the fact yet, so it is offered for classification but never sent as proof.
Both inspection projections are live and ordered by the inspection’s own updated_at DESC. No independently fetched list can disagree with the booked summary above it.
Framing, north elevation
This says what kind of evidence the inspection produces. It stays with the inspection, and other decisions can use it.
The first tap saves an attributed classification with the inspection’s observed timestamp. Only after that saved fact reconciles locally does a matching kind trigger the separate proof attachment.
book_inspection permits classification. manage_decisions permits attachment. No role name stands in for either, and a seat may hold one without the other.
Classification saved as a test. It does not satisfy this inspection proof.
This is not a failed classification and it is not retried as an inspection. The row leaves the unclassified list and may become eligible for a test requirement elsewhere.
A seat holding manage_decisions can still open the report-and-attest route. The automatic attachment path stops before its first proof call.
Classification was saved, but this device has not caught up. No proof was attached.
The saved fact is authoritative. The row is read-only in this state, and the original idempotency key remains bound to the inspection, stated kind and observed timestamp.
Attachment starts only from a matching locally reconciled classification. This frame exits when a later sync moves the row, never by guessing that it probably did.
book_inspection can still attach or attest to proof. The unclassified group explains who must act, but it offers no classification control.Someone handling inspections must classify these before they can be used as proof.
This frame means the capability read answered and book_inspection is absent. A failed access read gets the separate unknown explanation; neither branches on a role string.
The report row remains because this seat does hold manage_decisions. Classification denial cannot silently revoke an independent proof capability.
The summary does not issue a second booking query. It walks the already ordered matching list and takes the first row whose booked_for is not null.
booked_for keeps its own year, month and day. Converting it to the device timezone would move the date west of Greenwich and state the wrong appointment.
The sentence is about the requirement’s eligible set. A differently classified or still-unclassified inspection may exist, so “there are no inspections” would be a different and unsupported claim.
The schema carries no deadline, expiry or due date. This state never says late, overdue, urgent or due because none of those facts exists.
manage_decisions grant. The fact is saved; the separate proof write never starts.Classification was saved. Someone who can manage decisions must attach it as proof.
book_inspection authorized the classification that already landed. Denied or unknown attachment access cannot turn that success into a failed classification.
The client makes zero proof calls until manage_decisions is known granted. An authorized seat can later attach the now-eligible inspection; no role name substitutes for either permission.
Proof was accepted, but this device could not confirm the refreshed record. Retrying here safely checks the same submission.
The accepted acknowledgment is why this never says the file did not save, the proof did not go through or the proof was not attached. An accepted removal also never says proof remains attached: it names the accepted removal and the unread refreshed record separately.
The document and idempotency key stay scoped to this proof. A retry reconciles the same submission rather than inviting a duplicate. Removal uses its own same-removal sentence and retained key; when classification preceded attachment, its sentence also keeps “Classification was saved” true.
A requirement has no age. 0073 carries no due date, no deadline and no expiry, so a decision unchecked for six weeks is indistinguishable in the data from one settled yesterday. Every frame here keys loudness to outcome, and the state that most deserves a homeowner’s question is often the one with no outcome at all — the pending row on page 43, sitting quietly, six weeks old and looking exactly like one settled this morning.
Ruled 2026-08-28 (Q130): say what is true, not what is invented. A due date was rejected because a homeowner who is told something is late when it is not stops believing the amber signal the week it has to be believed. The pending row now states the fact already stored: “Nobody has signed it off yet. Framing inspection is booked for Aug 12, 2026.” or “Nobody has signed it off yet, and no matching inspection is booked.” No column, no policy, no invented deadline.
Built from the Q131 ruling. The kind is a stated, attributed fact about the inspection. A null kind is shown separately; choosing inspection or test writes exactly that fact with the row’s observed version. A matching saved classification may then attach as a second act only for a known manage_decisions grant. A mismatch stays truthful, and neither a stale local view nor unknown attachment access becomes permission to attach.