# CM Market Evidence Kit Contract v1

Status: draft contract for product restructuring  
Branch: `feature/price-kit-trivago-market-lab`  
Date: 2026-06-30

## 1. Product definition

CM Market Evidence Kit is a standalone evidence-to-signal tool for accommodation hosts.

It turns pasted, uploaded or manually entered external market material into a normalized, cleaned and understandable pricing signal for a selected period.

It is not a reservation manager.  
It is not an occupancy manager.  
It is not a scraper-first product.  
It does not directly write prices by default.  
It does not replace CM PRO Market Lab.

Short product sentence:

```text
Paste market data. Get a pricing signal you can trust.
```

Slovenian product sentence:

```text
Prilepi tržne podatke. Dobi razumljiv cenovni signal.
```

## 2. Core rule

```text
The product does not sell parsers.
The product sells a clear evidence workflow.
```

The application must be built from one product flow, not from separate parser pages.

Core flow:

```text
external market material
→ input UI
→ source detector
→ source adapter
→ normalized observations
→ market core
→ cleaned market signal
→ own price position
→ standalone report
→ evidence package export
```

## 3. Target user

Primary user:

- small or medium accommodation host,
- operator who manually checks market prices,
- CM Free / CM Plus user who needs pricing help,
- CM PRO user who later wants evidence import into Market Lab.

The product must remain useful without CM PRO.

## 4. Supported input surfaces

The first product version should provide one unified input surface for:

- Trivago capture JSON,
- Trivago DOM / outerHTML,
- Airbnb search outerHTML,
- Airbnb capture JSON,
- Booking visible copy/paste,
- Booking saved HTML,
- CSV / table data,
- manual text,
- manual form values,
- structured JSON,
- later official/statistical provider responses.

Parsers are source adapters behind one workflow. They must not become separate main products.

## 5. Adapter priority

Current implementation priority:

```text
1. Trivago = broad aggregated market evidence source
2. Airbnb = strong platform-specific host market source
3. Booking = additional / fallback / comparison source
4. CSV/manual = universal local fallback source
5. Structured JSON = technical/core import path
```

Trivago and Airbnb are both high-value sources, but their roles differ:

- Trivago provides an aggregated market view across providers.
- Airbnb provides a cleaner Airbnb-only view that is useful for own listing position and host-oriented market comparison.

All adapters must finish in the same `cm_market_evidence_package_v1` export contract.

## 6. Context contract

Every market signal must be tied to explicit context.

Required or preferred context fields:

```json
{
  "market_anchor": "Radovljica / Bled",
  "period": {
    "from": "2026-11-11",
    "to": "2026-11-18"
  },
  "nights": 7,
  "guests": 2,
  "currency": "EUR",
  "subject_profile_id": "apartma_matevz_a1"
}
```

The form context is the source of truth for period, nights, guests and market anchor. Imported material is evidence, not authority.

## 7. Subject Profile

The user must be able to select or define a Subject Profile.

A Subject Profile represents the host/listing for which the market signal is being interpreted.

Example:

```json
{
  "id": "apartma_matevz_a1",
  "label": "Apartma Matevž A1",
  "location_anchor": "Radovljica / near Bled",
  "capacity": 4,
  "quality_position": "mid_high",
  "own_listing_names": [
    "Apartma Matevž",
    "Apartment Matevz",
    "Apartma Matevž A1"
  ],
  "preferred_strategy": "balanced"
}
```

The same market sample can mean different things for a studio, a family apartment, a premium listing, an EV-enabled listing or a location-sensitive listing. Therefore the subject must be selectable.

## 8. Normalized observation contract

All source adapters must output compatible observations.

Minimum normalized observation shape:

```json
{
  "id": "obs_001",
  "source": "trivago",
  "source_type": "trivago_dom_outerhtml",
  "property_name": "Apartment Example",
  "provider": "Booking.com",
  "location_label": "0.7 km do: Mestno središče",
  "nightly_price": 127,
  "total_price": 889,
  "nights": 7,
  "currency": "EUR",
  "score": 9.8,
  "review_count": 86,
  "is_own_listing": false,
  "quality_flags": [],
  "raw": {}
}
```

Adapter-specific fields may be preserved in `raw`, but market core must work from normalized fields.

Airbnb-specific observations may use:

```json
{
  "source": "airbnb",
  "source_type": "airbnb_search_outerhtml",
  "property_name": "Apartma Matevž",
  "location_label": "Stanovanje v mestu Radovljica, Slovenija",
  "nightly_price": 117.5,
  "total_price": 235,
  "nights": 2,
  "currency": "EUR",
  "score": 5.0,
  "review_count": 25,
  "is_own_listing": true,
  "quality_flags": ["guest_favorite"],
  "raw": {
    "listing_id": "1213751959099409340"
  }
}
```

## 9. Market signal contract

The market core should produce both raw and cleaned signal data.

Required report values:

- sample size,
- used observations,
- excluded observations,
- raw median nightly price,
- cleaned median nightly price,
- P25 nightly price,
- P75 nightly price,
- outliers,
- own listing found / missing,
- source quality,
- confidence,
- warnings,
- suggested manual range.

Example warnings:

- `small_market_sample`,
- `own_listing_not_found`,
- `high_season_scarcity_sample`,
- `outlier_high_price`,
- `source_is_ranked_visible_results_only`,
- `mixed_provider_sample`,
- `missing_review_quality_data`.

## 10. Own Price Position

If the selected Subject Profile can be matched to one or more imported observations, the application should detect the subject's own visible market price and compare it against the cleaned market signal.

The report should show:

- detected own listing name,
- detected own nightly price,
- raw market median,
- cleaned market median,
- P25 / P75 range,
- own price difference from cleaned median,
- percentile-style market position where possible,
- interpretation label,
- manual suggestion.

Example interpretation labels:

- `below_market`,
- `slightly_below_market`,
- `near_market_median`,
- `slightly_above_market`,
- `premium_position`,
- `out_of_range_high`,
- `out_of_range_low`,
- `own_price_not_detected`.

Own Price Position is advisory. It must not automatically change prices.

Product sentence:

```text
CM Market Evidence Kit ne pokaže samo, kakšen je trg, ampak tudi kje je tvoja zaznana cena znotraj tega trga.
```

## 11. Manual suggestion rules

The product may suggest a manual price range.

The suggestion must remain explainable and conservative:

- conservative range: close to P25 / below cleaned median,
- balanced range: around cleaned median,
- aggressive range: between cleaned median and P75,
- premium position: above P75 only when quality/context supports it.

The product must use wording such as:

```text
This looks like a balanced position.
For faster occupancy, consider a lower manual range.
For strong demand or premium positioning, the current price may still be justified.
```

The product must not use wording such as:

```text
Set the price to X.
```

## 12. Export package contract

The machine-readable export must be usable by CM PRO Market Lab and future applications.

Planned export shape:

```json
{
  "schema_version": "cm_market_evidence_package_v1",
  "created_at": "",
  "source": {
    "type": "ota_observation",
    "name": "Trivago",
    "capture_method": "browser_helper",
    "url": ""
  },
  "context": {
    "market_anchor": "",
    "period": {
      "from": "",
      "to": ""
    },
    "nights": null,
    "guests": null,
    "currency": "EUR",
    "subject_profile_id": null
  },
  "subject_profile": {},
  "observations": [],
  "market_signal": {
    "sample_size": 0,
    "used": 0,
    "excluded": 0,
    "raw_median_nightly": null,
    "cleaned_median_nightly": null,
    "p25_nightly": null,
    "p75_nightly": null,
    "suggested_manual_range": {
      "conservative": null,
      "balanced": null,
      "aggressive": null
    },
    "confidence": "unknown",
    "warnings": []
  },
  "own_price_position": {
    "detected": false,
    "listing_name": null,
    "nightly_price": null,
    "diff_from_cleaned_median": null,
    "diff_percent_from_cleaned_median": null,
    "position_label": "own_price_not_detected",
    "suggestion": null
  },
  "connector": {
    "target": "cm_pro_market_lab",
    "source_type": "ota_observation",
    "import_mode": "preview_first",
    "write_policy": "no_direct_price_write"
  }
}
```

## 13. Relationship to CM PRO

CM Market Evidence Kit owns:

- external evidence intake,
- source detection,
- source adapters,
- normalized observations,
- standalone evidence report,
- own price position,
- exportable evidence package.

CM PRO Market Lab owns:

- saved market snapshots,
- relation to internal price data,
- future Price Engine advisory,
- protected write workflow,
- analytics connection,
- Time Engine / reservations / occupancy context.

Target connector flow:

```text
CM Market Evidence Kit
→ export evidence package
→ CM PRO Market Lab import
→ Market Engine snapshot
→ Price Engine advisory
→ admin-confirmed price write
```

## 14. Standalone vs. PRO Basket boundary

CM Market Evidence Kit should produce one evidence package at a time.

One package usually represents:

- one source or input batch,
- one selected context,
- one selected period,
- one normalized observation set,
- one market signal,
- one own price position result,
- one human-readable summary,
- one machine-readable JSON export.

The standalone kit may support several input types, but each input flow should end in the same `cm_market_evidence_package_v1` contract.

Multi-package comparison does not belong to the standalone kit.

The following belong to CM PRO Market Lab as a future module:

- importing multiple evidence packages,
- grouping packages by period, source, market anchor or unit,
- comparing Trivago vs. Airbnb vs. Booking vs. CSV/manual evidence,
- comparing several periods such as low season, holidays, shoulder season and high season,
- weighting packages by confidence and source quality,
- creating a multi-period pricing policy draft,
- connecting evidence to internal reservations, occupancy, revenue and Price Engine rules,
- any admin-confirmed price write workflow.

Proposed PRO module name:

```text
CM PRO Market Evidence Basket
```

Alternative technical name:

```text
Market Evidence Comparator
```

PRO Basket flow:

```text
cm_market_evidence_package_v1[]
→ normalize package metadata
→ group by period/source/subject
→ compare market signals
→ identify seasonal patterns
→ draft pricing policy
→ CM PRO Market Lab snapshot
→ Price Engine advisory
→ admin-confirmed write workflow
```

Boundary rule:

```text
Standalone kit creates evidence.
CM PRO Basket compares evidence and turns it into pricing policy intelligence.
```

## 15. MVP boundary

MVP includes:

1. one main input/report UI,
2. Subject Profile selection,
3. period/context form,
4. paste/upload/manual input,
5. Trivago adapter as first strong adapter,
6. Airbnb adapter as next strong adapter,
7. manual/CSV adapter as fallback,
8. normalized observations table,
9. outlier cleaning,
10. market signal report,
11. Own Price Position,
12. human-readable copy summary,
13. JSON evidence package export.

MVP does not include:

- direct `prices.json` writing,
- automatic live scraping,
- live CM Plus writes,
- multiple parser-first pages,
- multi-package comparator / basket,
- cross-period pricing policy draft,
- complex Price Engine automation,
- unconfirmed price changes.

## 16. PM rule

```text
Ne gradimo več iz skript.
Gradimo iz enega produkta in enega toka.
```
