# Synthetic annotation decision and export workflow Version `0.2.1.dev0` extends the original CPU report with one bounded pixel ROI format. The motivating researcher task, VALIS extraction, and an external viewer handoff are still unconfirmed. These commands exercise a local engineering protocol; an `approve` record is not researcher acceptance or authentication. ```mermaid flowchart LR Inputs[Images, manifest and source ROIs] --> Review[Validate and review report] Review --> Decision{Explicit decision} Decision -->|Reject| Stop[Export blocked] Decision -->|Approve with acknowledgments| Export[Revalidate inputs and export] Export --> Verify[Read output and verify geometry and receipt] Changed[Any changed bound input or tool] --> Stop ``` ## Coordinate and geometry contract `annotations.schema.json` defines `sectioncheck-pixel-rois` version `0.1.0`. It uses a FeatureCollection-shaped JSON representation with explicit image ID, level-0 frame, x-right/y-down axes, pixel units, integer-center origin, and `synthetic` domain. Vertices may have fractional coordinates. The supported image extent is `[-0.5, width-0.5] × [-0.5, height-0.5]` in that basis. The RFC GeoJSON specification uses geographic WGS84 coordinates, so this pixel profile is not advertised as RFC 7946 geographic data. [RFC 7946](https://datatracker.ietf.org/doc/html/rfc7946#section-4) QuPath exports image ROIs in full-resolution pixel coordinates relative to the top-left origin. A future adapter must establish the precise basis conversion and supported properties and test them in QuPath; adding a `.geojson` suffix does not establish compatibility. [QuPath annotation documentation](https://qupath.readthedocs.io/en/stable/docs/advanced/exporting_annotations.html) Supported shapes are two-dimensional `Polygon` and `MultiPolygon`, including holes. Rings must be explicitly closed. Empty/zero-area polygons, self-intersections, holes outside shells, invalid multipart topology, Z/M coordinates, curves, points, lines, unknown properties and duplicate IDs are rejected. Shapely/GEOS checks planar topology; no automatic geometry repair is performed. [Shapely manual](https://shapely.readthedocs.io/en/stable/manual.html) Limits: 1 MB per JSON input and serialized annotation export, 100 features, 10,000 total vertices including ring closures, 4,097 vertices per ring, 32 rings per polygon and 32 polygons per multipart feature. Images retain the core 20 MB/4096×4096 limits. The transformation is `H` in level-0 coordinates; preview crop/downsample frames affect display only. Every mapped vertex must remain in the target image. Out-of-bounds geometry blocks approval/export and is never clipped. IDs, labels, part/ring order and original files are preserved. ## Review and decide After the README installation and fixture generation, run: ```bash .venv/bin/sectioncheck review examples/synthetic/manifest.json --annotations examples/synthetic/annotations.json --out roi-review ``` The report shows source, target, resampled source, overlay, source ROI boundaries, and proposed target ROI boundaries. `review.json` records checks, part/hole counts, bounds, areas, required acknowledgments and the review fingerprint. It contains no approval. Inspect both the image boundaries and the check explanations. The `source_roi_preview` and `target_roi_preview` checks warn when any ROI is partly clipped or completely outside the supplied crop. The review record names the affected ROI IDs. A covering preview is needed to inspect the complete ROI against the image. These warnings require their own explicit acknowledgments; acknowledgment records that limitation and does not establish image inspection. To record an explicit synthetic decision, replace the fingerprint, alias and reason below with the values for that review: ```bash .venv/bin/sectioncheck decide examples/synthetic/manifest.json --annotations examples/synthetic/annotations.json --review-fingerprint REVIEW_FINGERPRINT_FROM_REPORT --decision approve --reviewer-alias YOUR_LOCAL_ALIAS --reason "Your decision and reasoning" --acknowledge physical_calibration --acknowledge source_footprint --out decision.json ``` Those two acknowledgments match the bundled translated example. Another input may have a different set. Approval requires every warning and not-evaluated check to be named exactly once. Hard errors cannot be overridden. `--decision reject` records a negative decision and needs no acknowledgments; it cannot authorize export. Both decisions require a nonblank alias/reason and a valid timezone-bearing timestamp, generated locally by the command. Decisions bind exact manifest/annotation bytes, verified image hashes, transform and policy, core/ROI/decision schemas, the tool version and packaged Python source, and NumPy/Pillow/jsonschema/Shapely/GEOS versions. Even annotation reformatting invalidates a previous decision. Editing inputs after a report requires a new review and decision. A copied or edited local record is not trusted identity; this protects against accidental stale exports within the declared workflow. The 0.2.1 source and version changes invalidate 0.2.0 decisions. Generate and inspect a fresh report before recording another decision. ## Export and verify ```bash .venv/bin/sectioncheck export examples/synthetic/manifest.json --annotations examples/synthetic/annotations.json --decision-file decision.json --out roi-export .venv/bin/sectioncheck verify-export examples/synthetic/manifest.json --annotations examples/synthetic/annotations.json --decision-file decision.json --export-dir roi-export ``` Export re-reads and validates all bound inputs before writing a new directory containing `target-annotations.json` and `receipt.json`. Existing destinations are rejected. Verification re-imports the output, checks topology and exact expected coordinates, and checks the decision/output hashes and receipt. It rejects stale inputs, altered outputs and changed decision records. Originals remain untouched; target coordinates are separate derived geometry. The synthetic tests also compare against independently authored asymmetric coordinates, areas, hole and part counts using Shapely. They do not rely solely on a transform's own forward/inverse round trip. `verify-export` is local profile re-import, not a claim that QuPath or another researcher tool accepted the output. ## Evidence and continuation `examples/exercise_synthetic_workflow.py` runs review, explicit automated approve, export, verification, explicit reject, rejected export, stale-policy rejection and edited-output rejection in a new directory. It preserves input hashes and checks two authored ROIs, three polygon parts, one hole, and areas 2,700/3,775 pixels squared against independently written expected geometry. Its alias and reason explicitly identify automation. `--require-wheel` additionally checks that the imported package comes from `site-packages`. Next researcher-dependent work is to agree the actual review task and ROI contract, implement a pinned VALIS adapter, and demonstrate export/re-import in the chosen tool on an authorized pair. No real-data result, user benefit, external-viewer compatibility or release readiness is inferred from this demo.