Install and run
Plyvel runs on your own computer. It ships as a folder that holds the local server, this site and the checks; there is no installer or hosted service yet. Ask for the package through the contact page.
Requirements
- Windows (the only system it has been run on), with Python 3.12 or 3.14.
- Blender, only if you want to render a model. Without it, the example and image-pair flows work and the model flow says so.
- A current Chrome, Edge, Firefox or Safari. The automated tests pass in three engines (Chromium, Firefox and WebKit).
Set up once
From the folder that contains studio_server.py:
python -m venv .venv
.venv\Scripts\python.exe -m pip install -r project\week1\requirements.txt
Run
.venv\Scripts\python.exe -B studio_server.py --port 8787 --open
The server opens http://127.0.0.1:8787 in your browser. Any free port works; the server accepts requests only for its own host and port. Projects, uploads and exports are written to the data folder next to the server (choose another with --data).
Blender
Install Blender and, if it is not on your PATH, set BLENDER_EXE to its executable before starting the server. Rendering uses Blender Cycles: preview is 720 px at 32 samples, standard is 1440 px at 96 samples.
System requirements
A render at standard quality (1440 px, 96 samples) is CPU-bound unless Blender is set up for your GPU; preview quality is the quick check.
Start a project
Every project starts from one of three inputs. Jobs run one at a time on the local worker; a queued project starts when the current one finishes, and a running job cannot be cancelled.
Fields
- Project name: up to 100 characters.
- Lighting: day or dusk. For an image pair it selects the review context and does not edit the image. For a model it renders the day pass first, then dusk, and reviews dusk against day.
- Quality (models only): preview or standard, as above.
- Review brief: saved with the project for the reviewer. Nothing is generated from it and no AI call is made.
- Focus objects (models only): object names, separated by commas, that the camera should frame.
- Outline masks (image pairs only): binary PNGs at image size, white building on black, one for each image, both or neither. Without them the building outline cannot be measured and goes to the reviewer; openings and thin features go to the reviewer in this release either way.
Plyvel cannot tell whether a supplied mask is accurate. A mask you draw is your statement about the outline, and the receipt records it as such.
The review workspace
A finished project opens as one screen: the comparison on the left, the rail on the right with the project, what was measured and your review. The comparison opens at Fit. A tall pair opens side by side when the two images fit as large as one would alone; anything else opens in the slider. The Original and Result labels sit on the image itself.
Comparison modes
- Side by side: the approved image and the result at the same zoom and position.
- Slider: one image over the other with a divider you drag across the image; the divider and its grip run only over the image, never over the empty canvas beside it.
- Blink: the result, with the original shown while you hold Space.
- Difference map: the colour-difference image from the audit. It is mean absolute RGB change, tripled, and shows where pixels changed. It is not a geometry heatmap and does not establish architectural errors.
Zoom and pan
The minus and plus buttons step the zoom; the percentage between them opens Fit, 50%, 100% (native pixels) and 200%. Drag to pan; scroll to zoom once the viewer is focused, or Ctrl + scroll at any time; pinch on a touch screen. The overview in the corner shows where you are and moves the view when clicked. At 800% and above a pixel grid is drawn on source pixels.
Clipping on the image
Clipping (or J) lays the clipping check over the result: red where the result is newly blown out, blue where it is newly crushed. It is recomputed from your two images by the check itself (the same rule and thresholds), so it shows where the counted pixels are; it is evidence, not a new check. On a project blocked by clipping, Show the clipped area turns it on and zooms to the largest clipped area; Show on the image does the same from the checks.
Focus
Focus (or F) hides the rail and gives the image the full width. Press it again, or use Skip to the review, to bring the rail back.
The review panel
The review panel leads with the verdict: on a blocked project, what failed in one plain sentence, the numbers under it, and the ways forward. Then What was measured: a results bar with its counts, the checks that failed or need you open, and the ones that passed, could not be measured or are for information folded under their counts. Each check’s own note from the backend is folded under Instrument. Then Your review. On a dusk project the rail also shows the dark-area notice with its measurements.
The checks
Each check is one instrument. A verdict is a pass only when the check was measured and the value is within its threshold. A threshold marked hypothesis is an engineering hypothesis, not a validated limit, and the receipt says so.
Verdict words
- Passed: measured and within threshold.
- Failed: measured and outside threshold. A failure blocks export; it cannot be accepted, only fixed.
- Your review: handed to the reviewer.
- Not measurable: no instrument for it in this release, or no masks supplied.
- Not applicable: the check does not apply to this plan.
- Information: recorded, never a verdict.
Dusk
A dusk result is reviewed against the daylight base under the dusk review policy (version dusk-review/1). New bright clipping above the limit blocks export. New darkness is never approved automatically: it is shown as dark areas needing your review, with the raw detector result kept as measured.
Review and sign
Review opens only when no check failed. The checklist lists the review groups the backend returned for this project (for example design and details, lighting and shadows, overall finish), each with the items it covers.
- Inspect each group in the viewer.
- Confirm the group. Nothing is preselected.
- Write an observation for that group, 8 to 2000 characters: what you compared and what you saw. No note is copied between groups.
- Enter your name, 2 to 120 characters. It is recorded in the receipt as written and is not verified.
- Approve and export. Plyvel verifies the evidence again, signs the receipt and packages the archive. The download exists only after that succeeds.
Observations and your name are kept in the browser session until the review is sent, so a navigation does not lose them; confirmations are never kept. A blocked project cannot be approved: correct the render and start a corrected project with the same approved image.
Plyvel cannot judge whether an observation is adequate. The receipt records that a person looked and what they wrote.
The archive and the receipt
An exported project gives you a ZIP archive with the reviewed image and its receipt. Before export, the only download is an unreviewed draft PNG whose file name says it is unreviewed.
- final.png: the reviewed result.
- final.receipt.json: the signed receipt (the [sample receipt](#/receipt) page walks through its fields).
- evidence/: the plan, the source, the annotation, the gates file, the audit report and the approvals, each listed in the receipt with its SHA-256.
- heatmap.json and heatmap.png: the colour-difference data from the audit.
The receipt proves which files were bound together, what was measured against which thresholds, that a named reviewer confirmed each group with an observation, and that the archive is unchanged since signing. It does not prove the building is accurate, that the reviewer is who they claim, or that unmeasured details are preserved. The image is not a photograph and the receipt is not a certification.
The private signing key stays on the computer that signed and is never included. Downloading re-verifies both the evidence package and the archive hash; a failed verification is shown as an error, never as a download.
Verify a receipt
A receipt is a JSON file with four top-level fields: payload, signature, public_key and algorithm. The algorithm field states the recipe exactly: Ed25519 over the payload serialised as JSON with sorted keys and no spaces. Anyone with the file can check it; no key of yours is involved.
- Serialise payload with sorted keys and the separators (",", ":"), as UTF-8.
- Decode public_key and signature from hexadecimal.
- Verify the signature over those bytes with the public key.
import json
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
r = json.load(open("final.receipt.json", encoding="utf-8"))
data = json.dumps(r["payload"], sort_keys=True, separators=(",", ":")).encode("utf-8")
Ed25519PublicKey.from_public_bytes(bytes.fromhex(r["public_key"])).verify(bytes.fromhex(r["signature"]), data)
print("intact")
The call raises InvalidSignature if a byte of the payload has changed. This recipe was run against a receipt from this package on 22 September 2026 and verified.
In the receipt’s own words: a valid signature proves this record is intact and was issued by the holder of the named key. It does not prove the measurements are correct.
Keyboard
The review works without a pointer; the viewer, checklist and export are tested by keyboard. In the workspace, the viewer toolbar is one Tab stop with the arrow keys inside it, and a Skip to the review control moves focus to the checklist.
Checked against the local backend contract on 22 September 2026.