P1 · Canonical Scan I/O Contract & Versioning

Technical spec · all specs

Source: docs/specs/P1-scan-io-contract.md
Updated: 2026-06-22

P1 · Canonical Scan I/O Contract & Versioning

1. Purpose

Define and freeze the canonical request, result, evidence, coordinate, identity, and versioning contracts used by every TroveSnap Vision scan. This work establishes the language shared by:

P1 is not merely an API envelope. It defines the semantic contract for TroveSnap's progressive visual-discovery system:

Wide scene image(s)
  → candidate discovery
  → candidate selection
  → centered item identification
  → mark and condition evidence
  → appraisal readiness
  → valuation using supplied comparables

The contract must preserve what was observed, what was inferred, where the evidence came from, how certain the result is, and what scan should happen next. Changing these contracts after provider, UI, storage, and appraisal work begins would be expensive. P1 therefore defines the stable canonical model before provider-specific vision implementation starts.

2. Product Principle

Scan broadly, highlight selectively, inspect deeply, and appraise only when justified. TroveSnap Vision progressively allocates inference cost. A broad scene scan should identify a small number of promising objects rather than appraise or richly describe every visible item. More expensive analysis occurs only after an object has been isolated and additional evidence has been captured. The contract must support this staged progression without requiring every scan type to return the same payload shape.

3. Scope

3.1 Included in P1

P1 defines:

  1. The canonical scan request envelope.
  2. The canonical scan result envelope.
  3. Seven independently versioned scan-result schemas:
    • table_hunt
    • room_scan
    • item_scan
    • mark_scan
    • condition_scan
    • appraisal_prepare
    • appraisal_value
  4. Shared image and image-role contracts.
  5. The normalized coordinate and region contract.
  6. Evidence, observation, claim, certainty, and provenance primitives.
  7. Provisional candidate identity and cross-image sighting contracts.
  8. Watchlist-reference and watchlist-match contracts.
  9. Appraisal-candidate and appraisal-readiness contracts.
  10. Retake, partial-result, warning, and failure states.
  11. Follow-up-photo and next-scan directives.
  12. Shared enums, reason codes, and taxonomy references.
  13. Request, scan-behavior, result-schema, taxonomy, and profile versioning.
  14. Golden fixtures and semantic contract tests.
  15. Compatibility rules for future schema evolution.

3.2 Explicitly excluded from P1

P1 does not implement:

P1 may define fields required by these later systems, but it does not implement their behavior.

4. Architectural Boundary

4.1 Vision-derived information

The canonical scan results may contain:

4.2 Application-owned information

Vision results must not invent or own:

Those belong to TroveSnap application services and later workflows.

5. Core Contract Decisions

5.1 Results use a discriminated schema family

The seven scan types do not share a generic candidates[].fields payload. Each result identifies its concrete schema:

result:
  schema: room_scan_result
  version: 3.0.0
  payload:
    coverage: partial
    visible_instances: 44
    estimated_distinct: 31

Shared primitives are reused, but each scan type has a semantically appropriate payload.

5.2 Provisional candidate identity begins in P1

P1 defines provisional identity within a scan and across images in the same scan request. A room candidate may have multiple sightings:

candidate_id: cand_7

sightings:
  - image_id: img_room_02
    region:
      bbox: [510, 165, 825, 770]
    primary: true

  - image_id: img_room_03
    region:
      bbox: [80, 210, 370, 790]
    primary: false

P1 does not create durable item identity. E4 or the corresponding item-promotion workflow converts a provisional candidate into a persistent TroveSnap item or inventory record.

5.3 Result schemas version independently

Each scan type has its own result-schema version. A change to condition_scan_result must not force a version change to table_hunt_result. The common request and response envelopes are also versioned independently.

5.4 Evidence is distinct from ranking

P1 defines observable evidence, claims, confidence, certainty, watchlist matches, and candidate signals. P4 defines how those inputs are weighted and converted into a final deterministic candidate rank.

5.5 Unknown is a valid result

The contract must distinguish:

Models must not fill missing information with plausible guesses.

6. Versioning Model

The contract has four independently evolving version dimensions.

6.1 Envelope version

Controls the common request or response wrapper:

contract:
  schema: scan_request
  version: 1.0.0

6.2 Scan behavior version

Controls the expected behavior of a particular scan type, including:

scan:
  type: table_hunt
  version: 2.0.0

6.3 Result-schema version

Controls field names, required properties, enum meanings, and serialization for one result type:

result:
  schema: table_hunt_result
  version: 2.0.0

6.4 Supporting-data versions

Requests and results may reference:

versions:
  taxonomy: 12
  watchlists:
    paul_personal: 17
    regional_demand: 6
  condition_vocabulary: 3
  appraisal_reason_vocabulary: 2

6.5 Compatibility rules

Semantic versioning applies:

Stored scan records must retain the exact versions used at execution time.

7. Canonical Request Envelope

contract:
  schema: scan_request
  version: 1.0.0

request_id: req_8f29
tenant_id: tenant_123

scan:
  type: table_hunt
  version: 2.0.0

input:
  images:
    - id: img_table_01
      role: scene
      uri: signed-image-reference
      width_px: 3024
      height_px: 4032
      orientation_applied: true

  comparables: [] # required for appraisal_value; empty/omitted for other scan types

context:
  sale_id: sale_221
  zone_id: garage_table_1
  zone_type: garage
  location:
    postal_code: "95682"
    country: US

profiles:
  watchlists:
    - id: paul_personal
      version: 17
    - id: regional_demand
      version: 6

target:
  selection: scene_candidates

known_facts: {}

prior_evidence: []

options:
  max_candidates: 6
  include:
    - watchlist_match
    - potential_value
    - unusual_item

7.1 Required common request fields

Every request must include:

7.2 Image roles

Image roles are part of the contract and must not be treated as informal labels. Initial roles include:

image_role:
  - scene
  - overview
  - table
  - shelving
  - centered_item
  - front
  - back
  - top
  - side
  - underside
  - mark_closeup
  - label_closeup
  - signature_closeup
  - serial_closeup
  - damage_closeup
  - detail

Each scan type restricts the permitted or required roles.

8. Canonical Result Envelope

contract:
  schema: scan_result
  version: 1.0.0

request_id: req_8f29
tenant_id: tenant_123

scan:
  type: table_hunt
  version: 2.0.0

result:
  schema: table_hunt_result
  version: 2.0.0
  status: completed
  payload: {}

warnings: []

provenance:
  taxonomy_version: 12
  watchlist_versions:
    paul_personal: 17
    regional_demand: 6

8.1 Common result statuses

result_status:
  - completed
  - completed_with_warnings
  - partial
  - retake_required
  - insufficient_evidence
  - rejected
  - failed

8.2 Retake contract

A result with retake_required must include:

retake:
  reason: multiple_center_objects
  guidance: Move closer and center one item.
  requested_photos:
    - centered_item

8.3 Warning contract

Warnings must use stable reason codes:

warnings:
  - code: low_visibility
    message: Candidate is partially obscured.
    related_candidate_id: cand_3
    related_image_id: img_table_01

Messages are descriptive. Consumers must branch on code, not free-form text.

9. Coordinate and Region Contract

All canonical coordinates use normalized integer values.

coordinate_space:
  format: xyxy
  origin: top_left
  range: [0, 1000]
  relative_to: orientation_corrected_image

A region is represented as:

region:
  image_id: img_table_01
  bbox: [65, 310, 280, 690]
  center: [173, 500]

Rules:

  1. x_min < x_max.
  2. y_min < y_max.
  3. Every value is an integer from 0 through 1000.
  4. The region references an image included in the request.
  5. Coordinates are relative to the orientation-corrected image.
  6. center may be derived but, when supplied, must lie inside the bounding box.
  7. Provider pixel coordinates are normalized by P2 adapters.
  8. Bounding boxes are required for scene candidates and room sightings.
  9. Polygons and masks are deferred extensions.

10. Evidence and Claim Contract

P1 must preserve the difference between visual evidence and interpretation.

10.1 Evidence source types

evidence_source:
  - visual_observation
  - ocr
  - normalized_ocr
  - user_supplied
  - prior_scan
  - supplied_comparable
  - deterministic_system
  - model_inference

10.2 Claim status

claim_status:
  - observed
  - extracted
  - supplied
  - normalized
  - inferred
  - possible
  - contradicted
  - unknown

10.3 Claim example

claim:
  field: brand
  value: Pioneer
  status: observed
  certainty: exact
  confidence: 99

  evidence:
    - source: ocr
      image_id: img_mark_01
      region:
        bbox: [110, 220, 770, 510]
      raw_value: PIONEER

10.4 Evidence rules

11. Shared Semantic Types

11.1 Identity certainty

identity_certainty:
  - exact
  - probable
  - possible
  - unknown

11.2 Visibility

visibility:
  - clear
  - partial
  - occluded
  - distant
  - blurred
  - unknown

11.3 Condition grade

condition_grade:
  - sealed
  - like_new
  - excellent
  - good
  - fair
  - poor
  - parts_only
  - unknown

11.4 Priority

priority:
  - low
  - medium
  - high
  - critical

11.5 Appraisal state

appraisal_state:
  - no
  - candidate
  - priority
  - blocked

11.6 Appraisal readiness

appraisal_readiness:
  - not_recommended
  - candidate
  - needs_item_photo
  - needs_mark_photo
  - needs_condition_details
  - ready
  - ready_with_limitations

11.7 Appraisal reason codes

appraisal_reason:
  - visible_maker_mark
  - visible_model
  - visible_signature
  - possible_antique
  - collectible_category
  - premium_material
  - scarce_item
  - unusual_design
  - complete_set
  - provenance_present
  - high_value_variance
  - possible_high_value
  - watchlist_interest
  - insufficient_identification

11.8 Next actions

next_action:
  - none
  - isolate_item
  - centered_item
  - crop_item
  - photograph_front
  - photograph_back
  - photograph_top
  - photograph_sides
  - photograph_underside
  - photograph_maker_mark
  - photograph_brand_model
  - photograph_signature
  - photograph_damage
  - photograph_serial
  - enter_dimensions
  - verify_quantity
  - verify_working
  - request_appraisal

11.9 Overlay states

overlay_state:
  - watchlist_match
  - appraisal_candidate
  - high_demand
  - unusual_item
  - uncertain_candidate
  - scan_recommended

The UI owns presentation color, iconography, animation, and callout placement.

12. Watchlist Contract

Watchlists are versioned request inputs, not provider-owned configuration.

watchlist:
  id: paul_personal
  version: 17

  entries:
    - id: vintage_pyrex
      query: vintage patterned Pyrex bowls
      aliases:
        - Pyrex nesting bowls
        - vintage milk-glass bowls
      clues:
        - printed_pattern
        - nesting_set
        - milk_glass
        - bottom_maker_mark
      priority: high

Allowed match types:

watch_match_type:
  - exact
  - brand_model
  - maker
  - visual_pattern
  - attribute
  - semantic
  - category

A result may reference only:

A model must never invent a watchlist ID or entry ID.

Boundary (P1 ↔ E8): P1 owns the watchlist request + match I/O shape above. E8 owns the matching behavior/implementation and must consume this contract rather than redefine it. See Open Questions §21.

13. Candidate and Sighting Contract

Scene candidates are provisional discoveries.

candidate:
  id: cand_7
  label: sculptural lounge chair
  category: furniture.chair.lounge
  confidence: 86
  identity_certainty: possible
  model_priority_hint: high

  sightings:
    - image_id: img_room_02
      region:
        bbox: [510, 165, 825, 770]
        center: [668, 468]
      visibility: clear
      primary: true

  watchlist_matches: []

  appraisal:
    state: candidate
    reasons:
      - unusual_design

  ui:
    overlay_state: appraisal_candidate
    overlay_label: A
    callout: Photograph chair separately
    selectable: true

  next_scan:
    type: item_scan
    version: 2.0.0
    reason: candidate_requires_isolation
    requested_photos:
      - centered_item

Rules:

14. Next-Scan Directive

Any scan may recommend a follow-up scan where appropriate.

next_scan:
  type: mark_scan
  version: 1.0.0
  reason: exact_model_unconfirmed

  requested_photos:
    - photograph_brand_model
    - photograph_serial

  target:
    parent_candidate_id: cand_7

A next-scan directive is a recommendation, not proof that the next scan has been scheduled or completed.

15. Scan-Type Result Contracts

15.1 table_hunt_result

Purpose — Find a limited number of items in a single crowded scene that deserve separate scanning.

Required payload fields

payload:
  image_id: img_table_01
  visible_items_estimate: 24
  candidates: []

Each candidate must include:

Invariants

15.2 room_scan_result

Purpose — Analyze multiple images of one physical zone, estimate visible and distinct objects, categorize the space, and identify promising candidates.

Required payload fields

payload:
  coverage: partial
  visible_instances: 44
  estimated_distinct: 31

  categories:
    - category: furniture
      count: 8
      tags: [sofa, chair, table, cabinet]

  candidates: []

  missing_coverage:
    - cabinet_interior
    - rear_shelf

Invariants

15.3 item_scan_result

Purpose — Identify and summarize the primary centered object.

Success shape

payload:
  status: identified

  item:
    category: electronics.audio.receiver
    name: Pioneer SX-series stereo receiver

    identity:
      certainty: probable
      confidence: 91

    summary: >
      Silver-face stereo receiver with an analog tuning display,
      wood cabinet, and visible wear along the upper cabinet edge.
      Pioneer branding is visible. The exact model should be
      confirmed from the rear label.

    visual_attributes:
      colors: [silver, brown]
      materials: [metal, wood_or_veneer]
      features:
        - analog_tuning_dial
        - wood_case
        - front_control_knobs

    visible_condition:
      grade: fair
      issues:
        - cabinet_edge_wear
        - surface_dust

    claims: []

    tags:
      - stereo_receiver
      - vintage_audio
      - analog_tuner
      - silver_face
      - wood_case

    appraisal:
      state: candidate
      reasons:
        - visible_maker_mark
        - high_value_variance

    next_scan:
      type: mark_scan
      version: 1.0.0
      requested_photos:
        - photograph_brand_model
        - photograph_serial

Retake shape

result:
  status: retake_required

retake:
  reason: multiple_center_objects
  guidance: Move closer and center one item.
  requested_photos:
    - centered_item

Invariants

15.4 mark_scan_result

Purpose — Extract and normalize a mark, label, signature, maker, model, serial number, or visible date.

Payload

payload:
  status: readable
  mark_type: manufacturer_label

  raw_text:
    - PIONEER
    - STEREO RECEIVER
    - MODEL SX-780
    - SERIAL NO. ZF3602189

  normalized:
    brand: Pioneer
    model: SX-780
    serial: ZF3602189

  uncertain_characters: []
  confidence: 99
  claims: []

Invariants

15.5 condition_scan_result

Purpose — Record visible condition, defects, damage, and apparently missing parts across one or more images of the same item.

Payload

payload:
  grade: fair

  observations:
    - area: cabinet_top
      issue: finish_wear
      severity: moderate
      evidence:
        - image_id: img_condition_top

    - area: cabinet_edge
      issue: veneer_chip
      severity: minor
      evidence:
        - image_id: img_condition_damage

  apparently_missing_parts: []
  functional_status: unknown
  confidence: 92

Invariants

15.6 appraisal_prepare_result

Purpose — Determine whether sufficient evidence exists for valuation and create a normalized comparable-search fingerprint.

Payload

payload:
  readiness: ready_with_limitations

  identification:
    brand: Pioneer
    model: SX-780
    confidence: 98

  sufficient:
    - model_identification
    - front_condition
    - cabinet_condition
    - rear_label
    - location

  missing:
    - audio_channel_test
    - service_history
    - interior_condition

  conflicts: []

  search_fingerprint:
    query: Pioneer SX-780 stereo receiver powers on cosmetic wear
    category: vintage_audio_receiver
    region: "95682"

  appraisal_confidence_ceiling: medium

  next_scan:
    type: condition_scan
    version: 1.0.0
    reason: additional_condition_evidence_would_improve_valuation

Invariants

15.7 appraisal_value_result

Purpose — Synthesize value ranges and adjustments from normalized item evidence and supplied comparable records.

Payload

payload:
  currency: USD

  estimates:
    quick_sale: [225, 285]
    normal_estate_sale: [285, 375]
    patient_local_sale: [350, 450]

  recommended_starting_price: 395
  confidence: medium

  adjustments:
    - factor: powers_on
      effect: positive

    - factor: audio_untested
      effect: negative

    - factor: cabinet_wear
      effect: negative

    - factor: recognized_model
      effect: positive

  strongest_comps:
    - tc_102
    - tc_101
    - ext_201

  missing_evidence:
    - audio_channel_test
    - service_history

  limitations: []

Invariants

16. Category Taxonomy References

Results reference a versioned hierarchical taxonomy. Initial root categories include:

category_root:
  - furniture
  - art
  - decor
  - kitchen
  - appliances
  - electronics
  - tools
  - garden
  - clothing
  - jewelry
  - collectibles
  - books_media
  - toys_games
  - sports_outdoor
  - musical
  - automotive
  - office
  - miscellaneous

Example paths:

category_examples:
  - furniture.table.dining
  - furniture.table.side
  - furniture.chair.arm
  - furniture.chair.lounge
  - kitchen.cookware.cast_iron
  - kitchen.glassware.mixing_bowl
  - electronics.audio.receiver
  - collectibles.ceramic
  - art.painting

P1 defines how taxonomy IDs are referenced and versioned. Taxonomy curation is maintained in a separate work item (WI-057, Backlog).

17. Required Contract Artifacts

P1 is complete only when the repository contains:

  1. Common request-envelope JSON Schema.
  2. Common result-envelope JSON Schema.
  3. Shared primitive schemas:
    • image input;
    • image role;
    • normalized region;
    • evidence reference;
    • claim;
    • warning;
    • retake instruction;
    • candidate;
    • sighting;
    • watchlist match;
    • next-scan directive;
    • provenance and version references.
  4. Seven scan-specific result schemas.
  5. Scan-specific request constraints.
  6. Shared enum and reason-code definitions.
  7. Taxonomy-reference schema.
  8. Watchlist-reference schema.
  9. Golden valid fixtures.
  10. Golden invalid fixtures.
  11. Deterministic schema-validation tests.
  12. Semantic contract tests.
  13. Version-compatibility documentation.
  14. Generated developer documentation or schema reference.

The implementation language may generate types from JSON Schema, but JSON Schema is the canonical interchange definition.

18. Test Plan

P1 is schema- and contract-focused. It does not require a live model or provider.

18.1 Schema validation

For each scan type:

18.2 Coordinate tests

18.3 Semantic invariant tests

The contract test suite must verify:

18.4 Versioning tests

18.5 Cross-image identity tests

Room-scan fixtures must cover:

19. Acceptance Criteria

P1 is complete when:

  1. A canonical request envelope exists and supports typed image roles; scan type and behavior version; tenant and contextual scope; target selection; known facts; prior evidence; watchlist/profile references; scan-specific options.
  2. A canonical result envelope exists and supports result status; scan echo; independently versioned result schema; warnings; provenance and supporting-data versions; scan-specific payload.
  3. All seven scan types have concrete, separately versioned result schemas.
  4. The result model does not depend on a generic untyped fields object.
  5. Normalized 0–1000 coordinates are fully specified and tested.
  6. Scene candidates and room sightings support tappable image overlays.
  7. Room results support provisional cross-image identity and multiple sightings.
  8. Evidence contracts distinguish observation; OCR extraction; normalized OCR; supplied facts; inference; uncertainty; unknown.
  9. Retake, partial, insufficient-evidence, warning, and failure states are represented structurally.
  10. Scan results can recommend a typed next scan and required photographs.
  11. Watchlist matches can reference only supplied and versioned watchlist entries.
  12. appraisal_prepare and appraisal_value remain separate contracts.
  13. appraisal_prepare cannot return a valuation.
  14. appraisal_value cannot cite unsupplied comparables.
  15. Golden valid and invalid fixtures pass the deterministic contract suite.
  16. Semantic invariant tests cover the prohibited and required behavior for every scan type.
  17. The schemas are provider-neutral and can be implemented by OpenAI, Gemini, Claude, local VLMs, or future providers without changing the application-facing contract.

20. Definition of Done

P1 is done when the schema package, shared vocabulary, fixtures, and contract tests are merged and can be consumed by P2, P3, P4, UI, storage, and appraisal work without requiring those teams to invent missing semantic fields. A live provider call is not required for P1 completion. P2 will prove that at least one real provider can populate these contracts. P3 will prove that invalid provider responses can be detected, retried, repaired, or rejected. P4 will define deterministic candidate ranking from the canonical evidence and signals. The outcome of P1 is a stable, provider-independent visual evidence and scan-orchestration language, not merely a request/response DTO.

21. Open Questions & Boundary Reconciliations

Resolved for the WI-010 freeze:

  1. P1 / E8 (watchlists) - resolved. P1 owns the watchlist request + match I/O shape (Section 12); E8 owns the matching behavior/implementation and must consume this contract, not redefine it.
  2. appraisal_value comparables input - resolved. The value scan uses a dedicated input.comparables[] channel. It is required for appraisal_value, and appraisal_value_result.strongest_comps[] may reference only supplied comparable IDs.
  3. Cross-scan identity / scan session - deferred to P10. Candidate IDs are unique within a result (Section 13). The progressive flow and next_scan.target.parent_candidate_id remain provisional caller-carried lineage until P10 defines scan-session identity and orchestration.
  4. Taxonomy curation - deferred to WI-057. Section 16 references a versioned taxonomy whose curation + versioning is tracked separately as WI-057 (Backlog).
  5. Version capture in observability - resolved by P8. All version dimensions (scan/result/taxonomy/watchlist + policy) are captured on every operation + provider attempt. See P8-observability-cost.md Sections 8.3, 10, 41, 61.
  6. Candidate priority -> model_priority_hint - resolved. P1 uses model_priority_hint; it is a provider/model hint only. P4 computes the authoritative priority_band, final_score, and rank.