# MARKETENGINE CORE V1 — KONTRATA FINALE E OUTPUT-IT (E NGRIRË)
**schema_version: 1** · Data e ngrirjes: 2026-10-05 · Statusi: **CONTRACT FROZEN**
Baza: `marketengine-phase0-kontrata.md` (6 vendimet) + gjithë gate-t P2.1–P2.5 PASS.
Çdo ndryshim i kësaj kontrate = `schema_version` i ri ose amendament i datuar këtu.

---

## 1. Top-level (V4 dhe output-i i merge-it)

```json
{
  "schema_version": 1,
  "generated_at": "<ISO8601>",
  "source": "<string informues>",
  "provider": "betsapi",
  "event_count": 0,
  "events": []
}
```
Output-i i merge-it shton `rregullat` + `burimet` (metadata operacionale, jo kontratë semantike).

## 2. Event

```json
{
  "fi": "<string>",
  "home": "<string>", "away": "<string>",
  "league": "<string|null>",
  "start_time": "<string|null>",
  "market_count": 0,
  "markets": [],
  "bet_builder": { "available": false, "pointer": "I99|null", "sections": [] }
}
```
Metadata e plotë e eventit (league_id, country_code nga `league.cc`|null, status,
first/last_seen, odds_updated_at) jeton në `bet365-sync-state.json` — burimi i
vetëm i state-it të eventit (V5: kurrë inferencë shteti nga emri i ligës).

## 3. Market

```json
{
  "market": "<CANONICAL_TYPE | \"UNMAPPED\">",
  "period": "FT | 1H | 2H | 10MIN | null",
  "market_name": "<emri raw i provider-it>",
  "market_ids": ["<id raw>"],
  "sections": ["<seksion raw>"],
  "lines": [],
  "selections": []
}
```
- `market`: një nga 153 tipet kanonike të ngrira (V1: NUK rinormalizohen; rinormalizim vetëm nën schema_version 2) ose sentineli **"UNMAPPED"** (state eksplicit; `market_name` mbetet autoriteti i emrit real).
- `period` i derivuar VETËM nga harta eksplicite `_lib/period-map.js`; tip i panjohur → `null`, kurrë "FT" default. `null` = scope i paprovueshëm (11 tipe të dokumentuara) — kurrë default teknik.

## 4. Selection (forma e plotë, shape konstant — çdo fushë ekziston gjithmonë)

```json
{
  "id": "<PA id — identiteti i provider-it>",
  "selection": "<etiketa | null>",
  "n2": "<string | null>",
  "line": "<string | null>",
  "qualifier": "<string | null>",
  "odd": "<frakcion raw — IMMUTABLE>",
  "decimal": 0.0,
  "pi": "<string|null>", "pk": "<string|null>",

  "raw_selection_name": "<PA.NA raw | null>",
  "grid_context": { "group": "<raw|null>", "row": "<raw|null>", "column": "<raw|null>" },

  "dimension": "FIRST|ANYTIME|LAST|TWO_OR_MORE|THREE_OR_MORE|SCORE|ASSIST|SCORE_OR_ASSIST|HEADER|OUTSIDE_THE_BOX|BOOKED|SENT_OFF|FIRST_CARD|null",
  "subject": { "type": "team|player", "name": "<string>" },
  "subject_2": { "type": "player", "name": "<string>" },

  "quality_status": "ok | unmapped | ambiguous | unlabeled",
  "publishable": true,
  "quality_reasons": []
}
```
`grid_context`, `subject`, `subject_2` janë objekte ose `null` (explicit, kurrë mungesë fushe).

### Aliases të kontratës (VENDIM I NGRIRË: vetëm në API/doc, KURRË të materializuara në dataset — P2.1/P2.6)
```
provider_selection_id := selection.id
provider_market_id    := market.market_ids[]
raw_market_name       := market.market_name
raw_section           := market.sections[]
provider_event_id     := event.fi (+ event_id në sync-state)
odds_raw              := selection.odd (frakcion raw, immutable; decimal = konvertim i pastër)
legacy_qualifier      := selection.qualifier (semantikisht legacy; fizikisht i pandryshuar)
```

### Fushat semantike — rregullat e ngrira
- `qualifier` = fusha LEGACY, byte/value e paprekur përgjithmonë brenda V1 (mban 3 semantika të provuara: DIMENSION, SUBJECT, CONTEXT — auditet p23/p24).
- `dimension` ≠ null ⇔ (canonical_type, qualifier) ∈ DIMENSION_MAP (15 çiftet eksplicite).
- `subject` ≠ null ⇔ njëra nga 3 format: (a) 13 SUBJECT-tipet me qualifier == home|away; (b) TEAM_GOALS_RANGE me n2 == home|away; (c) 5 EITHER_*-tipet me subject={player, selection}.
- `subject_2` ≠ null ⇔ 5 EITHER_*-tipet, {player, n2}, GJITHMONË në çift me subject (orientimi i source-it: subject←selection, subject_2←n2).
- `grid_context`: provenance strukturore raw e grid-it dbm (group←MA bosht dp/dv/dx/dcs, row←etiketa PC, column←MA/CO kolonë), ZERO interpretim; jo-grid → null; nuk hyn në dedup.
- `period`, `dimension`, `subject`, `subject_2`: tip/çift i panjohur → `null` (fail-closed kudo).

## 5. Kontrata e quality-t

```
severity:  ok < unmapped < ambiguous          (unlabeled: në enum, 0 raste sot —
                                               rezervuar, pa prodhim artificial)
ekuivalenca V1 (invariant i përhershëm):
  quality_status === "ok"  ⇔  publishable === true  ⇔  quality_reasons.length === 0
reasons: additive + të deduplikuara; statusi = severity më e lartë
```

| reason | kuptimi | statusi |
|---|---|---|
| `unmapped_type` | tip tregu i pamapuar; mbajtur si market "UNMAPPED" | unmapped |
| `provider_duplicate_identity` | ≥2 PA id UNIKE me të njëjtin identitet strukturor (çelësi §6) brenda eventit | ambiguous |
| `same_identity_diff_price` | manifestimi: grupi i mësipërm ka >1 odd unik; shtohet VETËM atëherë, kurrë sinonim automatik | ambiguous |

Taksonomia e rezervuar nga Phase 0 (pa raste sot, hyjnë me evidencë): `dup_label`, `same_id_diff_label`, `unlabeled_market`, `degenerate_label`, `dimension_lost`, `no_identity`.

## 6. Identiteti & provenance — semantika e ngrirë

- **Identiteti i provider-it** = `id` (PA). **Identiteti strukturor** = `(canonical_type[+market_name për UNMAPPED], period, selection, qualifier, n2, line, dimension, subject, subject_2, grid_context)` brenda eventit.
- **Dedup brenda marketit**: çelësi `[id, selection, n2, line, qualifier, odd]` — heq vetëm kopje byte-identike; fushat e reja P2.x NUK hyjnë kurrë në të.
- **cross_section_copies**: i njëjti PA id me identitet të njëjtë nëpër seksione (main/goals/result) të pa-bashkuara nga merge-i strukturor = multiple representations i të njëjtës selection → observability metric, JO defekt, JO flag.
- **duplicates_removed** (kopjet exact të hequra nga dedup) = observability metric (Phase 3 audit-core), jo reason.
- **V6**: provenance raw kurrë nuk humbet — `id` + `raw_selection_name` + `grid_context` + `market_name/market_ids/sections` në dataset; grid-i i plotë i adresueshëm në RAW përmes `id` (retention: current + previous cikël).

## 7. Asertimet e përhershme të Core-it (gate-t në repo)

```
priced provider selections silently dropped = 0     (gate-p25a / gate-p25b, kundër RAW)
ODDS MODIFIED = 0 · OLD FIELDS CHANGED = 0 · OLD IDENTITIES LOST = 0   (gate-additive)
unknown canonical type => period === null            (gate-p22-period)
dimension/subject/subject_2: format e lejuara A1–A3  (gate-p23-identity)
grid_context: round-trip 100% kundër RAW             (gate-p24c-grid)
ok ⇔ publishable ⇔ reasons bosh · flagët ekzakt grupet e llogaritura  (gate-p25b-quality)
```

Orkestruesi i plotë: `scripts/gate-core-v1.js <baseline> <v4> <raw>` → të gjitha gate-t + fingerprint-i i Core V1.
