# SPEC-COVERAGE-A1A2A3 — Phase 2A spec-fedés a Bejelentés-ágra

**Dátum.** 2026.05.25 · **Phase.** 2A (lezárva — Batch 1+2+3 mind kész)
**Hatókör.** A1 (`/bejelentesek`) + A1 mobil (`/bejelentesek` < `lg`) + A1 adatlap (`/bejelentesek/details/<id>`, A3 beágyazva) + A2 (`/bejelentesek/uj`)
**Forrás.** `uploads/urbino-docs/00_domain_model.md` §1.1–1.5 (Ticket + Attachment + ActivityLog + TicketNote) + `10_bejelentes_lista_es_adatlap.md` + `20_duplikacio_es_osszevonas.md` + `02_globalis_allapotgep.md` §1–4 + `00_architektura_v4.md` §6.1
**Screen-mock-ok.** `manager-system/preview/screens/a1-bejelentes-lista.html` · `a1-bejelentes-lista-mobile.html` · `a1-bejelentes-adatlap.html` · `a2-uj-bejelentes.html`

> **Módszertan.** Forward pass (spec → screen) + backward pass (screen → spec). Mező-szinten. A mock-doksi-réteg (`screen-header`, `DesignCanvas`, `DCArtboard` label, `State<X>` komponens) a backward-pass-on **kizárva** (SCREEN-CONVENTIONS.md §5). Az AUDIT-2.md 3.3 inline-organism-pótlás-jegyzéke a Bejelentés-ágat **NEM érinti** (A1/A2/A3-ban minden organism kanonikus).
>
> **4 lista.** ✅ Spec-ben + screen-en megvan · ⚠ Spec-ben van, screen-en nincs · 🟡 Screen-en van, spec-ben nincs, DE D-X rögzíti · 🔍 Screen-en van, spec-ben nincs, NEM dokumentált (UI-találmány). A `⚠` és `🔍` tételek **külön** szerepelnek a `SPEC-FEEDBACK.md` `## A1+A2+A3 spec-szelídítések` fejezetében.

---

## Batch-térkép

| Batch | Tartalom | Mezők | Státusz |
|---|---|---|---|
| **1** | `Ticket` törzs · triage-mag · állapot | 13 mező | ✓ lezárva |
| **2** | `Ticket` meta · helyszín · eredet · duplikáció · audit | 17 elem (13 mező + 4 derived) | ✓ lezárva |
| **3** | Kísérők: `TicketNote` · `ActivityLog` (×7 eseménytípus) · `SimilarTicket`-DTO | 22 elem (5 + 7 + 10) + 7 enum-érték | ✓ lezárva |

---

# Batch 1 — `Ticket` törzs · triage-mag · állapot

## Forward pass — 13 mező

### ✅ Spec-ben + screen-en is megvan

| Mező | Spec-forrás | Screen-evidence |
|---|---|---|
| `ticketNumber` (int) | `00_domain_model.md` §1.2.1; `10` 3.2 `displayId` DTO-derived | A1 lista `TitleCell` `a1-title__id` (`ALM-{row.num}`); A1 adatlap `TicketMetaBar.displayId` (`ALM-1058`); A1 adatlap breadcrumb (`['Bejelentések', 'ALM-1058']`); A1 mobil sor-fejléc. Implicit `Tenant.displayPrefix === 'ALM'`. |
| `title` (string ≤200) | §1.2.1 | A1 lista `TitleCell.a1-title__main`; A1 adatlap `TicketMetaBar.title`; A1 mobil `crd__title`; A2 form "A probléma" szekció `title` mező (`PRE_FILLED_VALUE.title`). |
| `description` (string ≤4000) | §1.2.1 (TD-2 egyetlen szabad szöveges mező) | A1 adatlap `Description` blokk "A polgár leírása" (Folyamatban + Új + Megoldva + Elutasítva mind kibontva); A2 form `description` mező (`PRE_FILLED_VALUE.description`). |
| `categoryId` (FK→Category) | §1.2.2 (K-031 triage 1. mezeje) | A1 lista `CategoryCell` (icon + name); A1 adatlap `TriageBar.category={{ id: 11, label: 'Utak és járdák › kátyú' }}`; A2 form triage-szekció. SD-18 (bármely szintű kategória) tisztelve: a mock `'Utak és járdák › kátyú'` formátum gyökér + alkategória fát mutat. |
| `dueDate` (DateTime?) | §1.2.2 (TD-szerű belső mérce, nem polgári ígéret) | A1 lista `DueDateCell` (3 vetület: dátum / `—` / overdue red-dot + szöveg); A1 adatlap `TriageBar.dueDate={{ formatted, isOverdue }}`; ActivityTimeline esemény "határidő-módosítás: 2026.05.21 → 2026.05.23". A `dueDate === null` eset a `StateNew`-ben (`dueDate={null}`). |
| `status` (enum ×5: New/Assigned/InProgress/Resolved/Rejected) | §1.2.3 (K-029); manager-oldali kódok: `uj`/`jovahagyva`/`folyamatban`/`megoldva`/`elutasitva` (SD-30) | **Mind az 5 érték renderelve**: A1 lista `StatusChip` 5 variánssal (mock `STATUS_LABEL`); A1 adatlap 4 állapot-screen `StateNew`/`StateFolyamatban`/`StateResolved`/`StateRejected`; A1 mobil `crd--dim` lezárt+elutasított halványítása. `StatusTrack` 4 fő-ági állapotot mutat (SD-27 — "Triage" elem NÉLKÜL — `STATUS_STEPS = [uj, jovahagyva, folyamatban, megoldva]`). |
| `rejectionReasonCode` (enum ×4) | §1.2.3 + `10` 5.2 | A1 adatlap `StateRejected` `StatusTrackBranched.reason.title = 'Magánterület'` (a `PrivateProperty` enum-érték magyar i18n-vetülete). |
| `rejectionReasonText` (string ≤1000, opt.) | §1.2.3 + SD-40 (Duplicate-esetben üres) | A1 adatlap `StateRejected` `StatusTrackBranched.reason.text` — "A bejelentés szomszédjogi vita — magánterületre vonatkozó kérelmet a város nem kezel hatáskörben. A polgárt a Békéltető Testülethez irányítottuk." |
| **`citizenSuggestedCategoryId` — RÉSZBEN ✅ (csak adatlapon)** | §1.2.2 (TD-3) | A1 adatlap `TriageBar.citizenSuggestedCategory={{ id: 3, label: 'Közvilágítás' }}` a `StateNew`-ben; a TriageBar amber "javasolt" tag-et renderel (D-4/T-3B). A Description meta-attrs "Kategória (polgári javaslat)" oszlopa is mutatja. **Lista vetület hiányzik → lásd `⚠ #2`.** |
| **`assignedUserId` (FK→TenantUser) — RÉSZBEN ✅ (csak `user`-típus)** | §1.2.2 (TD-4 xor) | A1 lista `AssigneeCell` `UserChip name + role`; A1 adatlap `TriageBar.assignee={{ type: 'user', label: 'Szabó Zoltán', initials: 'SZ' }}`. **Lista nem támogatja a `group`-felelőst → lásd `⚠ #3`.** |
| **`assignedGroupId` (FK→Group) — RÉSZBEN ✅ (csak adatlap-DTO-szinten)** | §1.2.2 (TD-4 xor) | A1 adatlap `TriageBar.assignee.type` képes `'group'`-t fogadni a komponens-szerződés alapján (organism-doksi sor 26–28); a 4 mock-state mindegyike `type: 'user'`-t használ — a `group`-renderelt példa **a teljes A1 mock-screenen nincs**. ActivityTimeline "Tóth Béla kategorizálta + kiosztotta: Szabó Zoltán (Útkarbantartó csapat)" denormalizált csoport-utalás. **Lásd `⚠ #3`.** |


### ⚠ Spec-ben van, screen-en nincs — hiányosság

#### ⚠ #1 — `id` (long PK)
- **Spec:** `00_domain_model.md` §1.2.1 — *"A felhasználónak soha nem jelenik meg — lásd `ticketNumber`."*
- **Screen:** sehol nem renderelt — helyette `displayId`/`ticketNumber` áll.
- **Döntés:** **tudatosan kihagyott** (a spec maga írja elő a kihagyást). Nincs SPEC-FEEDBACK-tétel; csak audit-konzisztencia végett rögzítve.

#### ⚠ #2 — `priority` oszlop az A1 listáról hiányzik
- **Spec:** `10` 4.2 `TableStateConfig`-vázlat — *"Prioritás | priority | badge (Alacsony/Normál/Magas) | ✓ szűrhető | ✓ rendezhető | ✓ alap-látható"*.
- **Screen:** `a1-bejelentes-lista.html:337–344` `ticketColumns` 6 oszlopot definiál (Cím, Kategória, Állapot, Felelős, Határidő, Beérkezett); **a Prioritás oszlop nincs benne.** A mock-data `TICKETS` a `priority` mezőt szállítja (`priority: 'Normal'`), de a CellRenderer nem rajzolja.
- **Spec szerinti vetület.** A spec szerint a Prioritás alap-látható oszlop; a SimilarTicket-DTO (Batch 3) is mutathat majd `priority`-t a heurisztika-jelben. A pilot triage-élmény szempontjából a Magas prioritás színes badge-ének hiánya érzékelhető funkcionális rés.
- **Adatlap fedés van** (`TriageBar.priority={{ ... }}` mind a 4 állapot-screenen), így a `priority` mező maga nem teljesen "elveszik".
- **Döntés:** **JAVÍTANDÓ** — a screen-fázis fejlesztője az Angular-portoláskor a 7. oszlopot felveszi. A javítás **most a mock-szinten NEM kötelező** (SCREEN-CONVENTIONS.md §scope: "ez a fájl ÚJ screen építéséhez ad mintát, NEM régi javításához"); **a HANDOFF.md átadási megjegyzésként szerepel**, és a `TableStateConfig`-vázlat `columns` listáján visszacsatolva. (SPEC-FEEDBACK SF-1.)

#### ⚠ #3 — A1 lista felelős-oszlopa nem támogatja a `group`-felelőst
- **Spec:** `10` 3.2.1 `TicketListDto.assigneeLabel: string?` — *"a felelős `Group` vagy `TenantUser` neve; `null`, ha még nincs"*. Az `assigneeType` a detail-DTO-n szerepel (3.2.2), de a lista a denormalizált `assigneeLabel`-t adja.
- **Screen:** `a1-bejelentes-lista.html` `AssigneeCell` `userById(row.assignee)` hívást tesz, és csak `UserChip name + role` renderel; ha az `assignee` integer nem talál `User`-t (mert valójában csoport-ID), `—` jelenik meg. A mock `TICKETS` adata kizárólag `User`-felelősöket szállít — a csoport-eset a listán nem demonstrált. Az A1 mobil `crd__assignee` szintén csak `userById`-vel működik.
- **Döntés:** **JAVÍTANDÓ** — az AssigneeCell olyan típus-szétválasztó renderelést igényel, ami a `TicketListDto.assigneeLabel`-t literal string-ként rajzolja (badge-szerűen, csoport-kontextusban más glyph-fel — pl. Lucide `users` ikon az `user-circle` helyett). A `TicketListDto`-ban érdemes lehet egy `assigneeType: 'user'|'group'|null` mezőt felvenni az SD-30 alapján (a detail-DTO-n már létezik). **SPEC-FEEDBACK SF-2** — a lista-DTO bővítés-javaslat a 3.2.1-hez.

#### ⚠ #4 — `citizenSuggestedCategoryId` lista-oldali "(javasolt)" jelölés
- **Spec:** `10` 3.2.1 `TicketListDto.categoryLabel: string?` — *"`categoryId` neve, ha kitöltött; különben `citizenSuggestedCategoryId` neve **"(javasolt)" jelöléssel**; különben `null` (SD-30)"*.
- **Screen:** `a1-bejelentes-lista.html` `CategoryCell` csak a confirmed kategóriát ismeri: `const c = CATS[row.category]; if (!c) return <span>—</span>;`. Ha egy `Új` ügynek nincs még `categoryId`-ja, de van `citizenSuggestedCategoryId`-ja, a screen `—`-t mutat — a polgári javaslat-vetület a listán **láthatatlan**.
- **Döntés:** **JAVÍTANDÓ** — a CellRenderer-nek esnie kell a `citizenSuggestedCategoryLabel` fallback-re, "(javasolt)" suffix-szel. A mock-szinten nem kötelező; a HANDOFF.md átadási megjegyzés. **SPEC-FEEDBACK SF-3** (de ez nem spec-szelídítés, hanem screen-mock-pótlás — egyik valódi spec-gap, amit a screen-mock nem fed).

#### ⚠ #5 — `resolutionNote` dedikált megjelenítése a Resolved-adatlapon
- **Spec:** `10` 4.3 layout-blokkok "Bal: fotók, leírás, belső jegyzetek" — a lezárás-megjegyzést a Resolved adatlap **valahol** megjeleníti. `00_domain_model.md` 1.2.3 `resolutionNote` max 2000 char szabad szöveg.
- **Screen:** A1 adatlap `StateResolved` `Description`-blokk csak a polgári leírást ismétli; a `Description.attrs` "Lezárta / Munkaidő / Felhasznált anyag / Várt visszajelzés" — **a `resolutionNote` mező mint önálló szöveg-blokk sehol nincs rajzolva**. A spec a `Resolved` állapotban `resolutionNote` vagy `ResolutionPhoto` legalább egyikét kötelezőnek írja (a mock fotókat mutat).
- **Döntés:** **JAVÍTANDÓ** — a Resolved-state Description-blokk után érdemes egy `mgr-resolution-note` szekciót felvenni (eyebrow + body), ami megjeleníti a szabad szöveges lezárás-megjegyzést. A 4 strukturált `Description.attrs` jelenleg **🔍 UI-találmányt** képez (lásd lent #🔍 #1). **SPEC-FEEDBACK SF-4**.


### 🟡 Screen-en van, spec-ben nincs, DE D-X rögzíti

| Screen-elem | Hol jelenik meg | D-X hivatkozás |
|---|---|---|
| TriageBar amber "javasolt" tag a polgári javaslat mellett | A1 adatlap `StateNew` `TriageBar` `mgr-triage-bar__tag--suggested` | **D-4/T-3B** — *"pre-fill amber 'javasolt' tag-gel; klikkre megerősítés vagy felülírás. Egy klikk a triage-gyorshoz."* |
| TriageBar "· kötelező" eyebrow-suffix az Új ügyön (Kategória, Felelős) | TriageBar `mgr-triage-bar__field` `required` állapota; eyebrow-ban renderelt | **D-4/T-4B** — *"subtle „· kötelező" eyebrow + disabled gomb-tooltip; a spec elvét tükrözi: 'a kliens előjelezheti — kényelmi réteg' (`10` 4.3)."* |
| ActionBar disabled-Assign + tooltip "Hiányzik: Kategória, Felelős" | A1 adatlap `StateNew` `ActionBar.actions[1].disabled+tooltip` | **D-4/T-4B** + D-5/AB-2 — *"Új-ban primer 'Triage kész — Kiosztás', disabled-tooltip a hiányokat listázza. A szerver így is 422-zik."* |
| TriageBar always-visible chevron (szerkeszthetőség kódolva nyugalmi állapotban) | TriageBar `Field` komponens trailing chevron | **D-4/T-2B** — *"mindig látható chevron; a szerkeszthetőség nyugalmi állapotban is kódolt."* |
| TriageBar locked-state (Resolved + Rejected) | A1 adatlap `StateResolved` és `StateRejected` `mgr-triage-bar--locked` modifier | **SD-26** (spec rögzíti a végállapotot mint zárolt) **+ D-4** (vizuális megvalósítás) — itt a vizuális D-4-szintű, az invariáns spec-szintű. |
| StatusTrack 4 fő-ági állapot, "Triage" elem NÉLKÜL | A1 adatlap minden state `StatusTrack steps={STATUS_STEPS}` | **SD-27** (spec: `10` 4.3 + VF-1 visszacsorgó jelzés — a `00_architektura_v4.md` 4.2 ezt pontosítja) — a screen ezt **explicit** implementálja, SD-27 a forrás. |
| StatusTrackBranched a Rejected-state-en (banner + actor + date) | A1 adatlap `StateRejected` `StatusTrackBranched` | **D-5** (vizuális minta) + `10` 4.3 (csík helyett önálló "Elutasítva" jelző) |
| A1 lista T-7 dim Lezárt+Elutasítva sorok | A1 lista `dimResolved` rowClassName | **D-13** (DataTable contract-bővítés — `rowClassName` hook) + **Tier-2 UX-explorer T-7** (a vizuális dim-minta forrása) |
| A1 lista TabFilter overdue piros dot | A1 lista `TABS_BASE.overdue.tone='overdue'` | **D-2** (DataTable Tier-2 csoport, TabFilter mellé) + Tier-2 UX-explorer (overdue-tone) |
| A1 mobil FAB ("+Új bejelentés" lebegő gomb) | A1 mobil `PhoneShell fab` | **D-1** (page-CTA elv — desktopon PageHeader, mobilon FAB konzisztens) + a mobil-screen Q1=B/Q2=A explorer döntései |
| A1 mobil `crd--dim` lezárt+elutasított halványítás | A1 mobil `StateOverdue`/`StateFirstTime` etc. | **D-13** Tier-2 T-7 mobil-vetülete |


### 🔍 Screen-en van, spec-ben nincs, NEM dokumentált — UI-találmány

#### 🔍 #1 — A1 adatlap `Description.attrs` 4 strukturált meta-mezője a Resolved-state-en
- **Hol.** `a1-bejelentes-adatlap.html` `StateResolved` `Description.attrs`:
  - `{ label: 'Lezárta', value: 'Szabó Zoltán · 2026.05.19. 16:42' }` — származtatott `resolvedAt` + `Resolved`-esemény `actorId` → részben spec-fed, **OK** (DTO-derived).
  - `{ label: 'Munkaidő', value: '6 óra (2 nap)' }` — **nincs spec-mező**.
  - `{ label: 'Felhasznált anyag', value: '2 m³ macskakő-aljzat + 5 db zsalukő' }` — **nincs spec-mező**.
  - `{ label: 'Várt visszajelzés', value: 'Nincs panasz a polgártól' }` — **nincs spec-mező**.
- **Spec.** `00_domain_model.md` §1.2.3 — *"`resolutionNote` mező opcionális, max 2000 karakter, **egyetlen** szabad szöveges lezárás-megjegyzés"*. Az adatmodell strukturálatlan szabad szöveget rögzít — a 4 strukturált attrs ennek dekomponálási kísérlete a screen-mockon.
- **Döntés.** **Spec-be visszacsatolás** vagy **törlés**. Két opció:
  - **(a)** A mock-on a 4 attrs törlésre, a Resolved-state-en helyette egyetlen `resolutionNote` szöveg-blokk (ez egyúttal a ⚠ #5-t is megoldja).
  - **(b)** A spec bővíthető strukturált lezárás-mezőkkel (`workHours: int?`, `materialUsed: string?`, `citizenFeedback: string?`); ez a pilot-scope-ot bővíti, és nem indokolt a `40_riport.md`-ből (a riport ezeket nem aggregálja).
- **Javasolt.** **(a) törlés a mockból**, és a Resolved-state-en a `resolutionNote` szabad szöveges megjelenítése. **SPEC-FEEDBACK SF-5** mint screen-mock-pótlás (NEM spec-szelídítés).

#### 🔍 #2 — A1 adatlap "Várható lezárás" `Description.attrs` érték a Folyamatban-state-en
- **Hol.** `StateFolyamatban` `Description.attrs.{ label: 'Várható lezárás', value: '2026.05.23. (péntek)' }`.
- **Spec.** Nincs explicit "várható lezárás" mező — a `dueDate` (belső munkahatáridő) a TriageBar dedikált cellájában megjelenítve. A "péntek" napnév-formátum `dueDate`-derived; magában a `dueDate`-formázás `tabular-nums + relatív-napnév` nem spec-szintű döntés.
- **Döntés.** **🟡 → reklasszifikálva** — ez a `dueDate` derivált megjelenítése, és az A1 lista a `DueDateCell`-en is hasonló mono-formátumot használ. Az értelmezett "Várható lezárás" valójában a TriageBar D-cella szöveg-vetülete; a Description.attrs csak újra-mutatja. **Inkább konzisztencia-zaj, mint UI-találmány** — javasolt törlésre (Folyamatban + Megoldva `Description.attrs`-ből), mert duplikálja a TriageBar tartalmát.

#### 🔍 #3 — A1 adatlap `StateFolyamatban` `Description.attrs` "Bejelentő kontakt" → Batch 2 hatókör
- **Hol.** `Description.attrs.{ label: 'Bejelentő kontakt', value: '+36 30 555 1234' }`.
- **Spec.** `reporterContactText` — Batch 2 fed. **Batch 2-be áthelyezve**, itt nem értékeljük.

---

## Backward pass — későbbi iter

A backward-pass előzetes jegyzeteit a Batch 1 idejére korlátozva a fenti `🟡` és `🔍` listák már részben elindítják (TriageBar tagok + Description.attrs). A teljes backward-pass-ot az utolsó iter-ben végzem, miután mind a 3 batch forward-passa lezárult — így a screen-szintű decorations (pl. A2 "Telefonos felvétel" amber banner, A2 validation-error banner, MapMini, BackToList, A1 mobil FAB-pozíció) egyszerre kerülnek értékelésre, a 4 lista konzisztensen rendezhető.

---

## Batch 1 összegzés

| | Tétel-szám |
|---|---|
| ✅ Teljes fed | 7 mező |
| ✅ Részleges fed (adatlap fed, lista hiány) | 3 mező (`citizenSuggestedCategoryId`, `assignedUserId`, `assignedGroupId`) |
| ⚠ Hiányosság | 5 (1 tudatos kihagyott + 4 javítandó) |
| 🟡 D-X-rögzített UX-választás | 11 elem |
| 🔍 UI-találmány | 2 érdemi (#1 Resolved-attrs, #2 várható-lezárás) + 1 áthelyezett |

**A SPEC-FEEDBACK.md `## A1+A2+A3 spec-szelídítések` 4 tétellel megnyitva: SF-1..SF-4** (a `⚠ #2..#5` tételek; a `⚠ #1` tudatos kihagyott nem feedback).

---

# Batch 2 — `Ticket` meta · helyszín · eredet · duplikáció · audit

## Forward pass — 17 elem (13 mező + 4 DTO-derived)

### ✅ Spec-ben + screen-en is megvan

| Mező / derived | Spec-forrás | Screen-evidence |
|---|---|---|
| `addressText` (string ≤300, opt.) | §1.2.4 | **A1 adatlap** `TicketMetaBar.addressText` (Lucide `map-pin` + szöveg, 4 állapot mind); `MapMini.addr` "📍 8220 Balatonalmádi, Petőfi Sándor utca 12."; **A2** `LocationPicker.value.addressText` (auto-geocode-pre-fill — D-7/L-3). A `null`-eset (manuális nyitás koordináta-nélkül) az A2 `EMPTY_VALUE`-ban (`addressText: ''`). |
| `origin` (enum `CitizenApp`/`Manual`) | §1.2.5 | **A1 adatlap** `TicketMetaBar.origin='CitizenApp'`; `Description.attrs.{ 'Eredet': 'Urbino mobilapp' }`. **A2** `PhoneBanner` amber-tinted banner explicit: *"A polgár nem az appon keresztül jelentett. Az origin mező értéke Manual lesz."* `Manual`-eset az A2 `StatePhoneIntake`-ben; `CitizenApp`-eset minden A1 adatlap-state-en. |
| `reporterId` → `reporterDisplayName` (DTO-derived) | §1.2.5 + `10` 3.2.2 (`reporterDisplayName: "Mária K."`, NY-2 nyitott) | A1 adatlap `TicketMetaBar.reporterName='Mária K.'` (Lucide `user` ikon + név); `Description.attrs` is mutatja. A 4 állapot mind tartalmazza (Folyamatban=Mária K., Új=Kiss György, Megoldva=Mária K., Elutasítva=Horváth Anna). |
| `reporterContactText` (string ≤200, opt.) | §1.2.5 | **A1 adatlap** Folyamatban `Description.attrs.{ 'Bejelentő kontakt': '+36 30 555 1234' }`. **A2** `LocationPicker` után dedikált `reporterContactText` form-mező (D-7/F-3 szekció-sorrend "Bejelentő"); `PRE_FILLED_VALUE.reporterContactText='Szabó Ferenc · +36 30 555 1234'`. A2 banner explicit kódolja: *"a bejelentő-mezőt szabad szöveggel töltöd („név · telefon")."* |
| `assignedAt` (DateTime?, denormalizált SD-14) | §1.2.8 | A1 adatlap `StatusTrack.steps[1].date='2026.05.17.'` (a `Jóváhagyva`-lépésnél a denormalizált `assignedAt` formázott vetülete); ActivityTimeline `id:2, eventType:'Assigned', occurredAt:'2026.05.17. · 14:48'` (a primary forrás az `ActivityLog` `Assigned`-eseményből, az `assignedAt` ennek denormalizált tükre). |
| `resolvedAt` (DateTime?, denormalizált SD-14) | §1.2.8 | A1 adatlap `StateResolved` `STATUS_STEPS_SOLVED[3].date='2026.05.19.'`; `ActionBar.hint=<>Lezárva <span title="2026.05.19. · 16:42">3 napja</span> · Szabó Zoltán.</>` (relatív + tooltip-abszolút, D-5/AT-1 minta). |
| `createdAt` (auditable) | §1.2.8 | **A1 lista** `CreatedAtCell` (mono-formátum); **A1 adatlap** `TicketMetaBar.createdAt='2026.05.17. · 14:22'` (Lucide `calendar`-ikon); ActivityTimeline `id:1, eventType:'Created', occurredAt='...'`; **A1 mobil** sor-meta. A `LocationPicker` lista-DTO-rejtve a "5 napja"-szerű derived `ageLabel`-be a hasonló-dobozban (Batch 3 hatókör). |
| `updatedAt` (auditable + SD-32 concurrency-token) | §1.2.8 + `10` 2.1 SD-32 | **Belső szerződés** — `expectedUpdatedAt`-token a 4 inline-mentő + 6 akció-végponton; nem felületi mező. Vizuális vetülete: A1 adatlap `StateFolyamatban` `ActionBar.hint=<>Utolsó mentés <span title="2026.05.20. · 10:42">2 napja</span>.</>` Ez a derived "utolsó mentés" szöveg a `updatedAt` relatív megjelenítése. |
| **`thumbnailRef` + `attachmentCount` (DTO-derived) — RÉSZBEN ✅ (csak adatlap fed)** | `10` 3.2.1 lista-DTO + 4.2 oszlop "Bélyegkép + 📷-szám" | A1 adatlap `PhotoGallery` blokk 4 fotót mutat caption-nel + "4 kép · polgári feltöltés" `__count`-jelzés; SimilarTicketsBox findings-row `attachmentCount` propot a SimilarTicket-DTO-ból kapja (Batch 3 fed). **Lista bélyegkép-oszlop hiányzik → lásd `⚠ #7` és kapcsolódik SF-1.** |
| **`latitude` / `longitude` (decimal, F-feltételes) — RÉSZBEN ✅ (csak A2 fed)** | §1.2.4 (együtt-járás invariáns) | **A2** `TicketCreateForm` `LocationPicker.value={lat:47.0341, lng:18.0181}` — Leaflet-pin él térképes click+drag interakcióval (D-7/L-1, L-2, L-3); reverse geocoding auto-tölt `addressText`-et. **A1 adatlap** `MapMini` egy CSS-pin stub-ot rajzol fix pozícióval — **a lat/lng-prop nincs átadva**, a komponens decoration-szerű. **Lásd `⚠ #6`.** |


### ⚠ Spec-ben van, screen-en nincs — hiányosság

#### ⚠ #6 — A1 adatlap MapMini koord-prop nélkül renderelt
- **Spec.** `00_domain_model.md` §1.2.4 — `latitude`/`longitude` mező a `Ticket`-en, `10` 4.3 layout-blokkok **"Jobb: térkép"** explicit szekció. `20_duplikacio` 2.5 a heurisztika térbeli jele ezekre épít.
- **Screen.** `a1-bejelentes-adatlap.html` `MapMini` komponens CSS-pseudo-elemekkel rajzol fix pozíciójú pint és fix világoskék/zöld háttér-gradient-et — **a `lat`/`lng` prop nincs definiálva**, csak `status` és `address`. A bejelentés tényleges koordinátáját a screen-mock NEM hordozza. A `MapMini` decoration-szerű placeholder, nem valódi térkép-vetület.
- **Döntés.** **JAVÍTANDÓ — Angular-portoláskor.** A MapMini-t cserélje le a `MapWidget` (`map-widget.jsx`, D-7-ben kiemelve) `mode='view'` változata, és kapja meg a `lat`/`lng`/`status`/`addressText` propokat (a SimilarTicketsBox is így fogyasztja). A mock-szinten nem kötelező (SCREEN-CONVENTIONS.md scope). **SPEC-FEEDBACK SF-6** — átadási megjegyzés.

#### ⚠ #7 — A1 lista bélyegkép-oszlop + `attachmentCount` badge
- **Spec.** `10` 4.2 `TableStateConfig`-vázlat — *"Bélyegkép | thumbnailRef + attachmentCount | kis kép + 📷-szám badge | — szűrhető | — rendezhető | ✓ alap-látható"*.
- **Screen.** A1 lista `ticketColumns` 6 oszlop, bélyegkép nincs köztük. Mock-data sem szállít `thumbnailRef` mezőt a `TICKETS` rekordokon. Az A1 mobil `crd__cover` szintén placeholder.
- **Döntés.** **JAVÍTANDÓ** — Angular-portoláskor (a SF-1 priority-oszlop részhalmazaként kezelve). A `SPEC-FEEDBACK.md` **SF-1 bővítve** a bélyegkép-oszloppal — nem új SF, hanem SF-1 hatókör-pontosítás.

#### ⚠ #8 — `originalTicketId` és redukált duplikátum-nézet (SD-29) hiányzik a screen-mock-ról
- **Spec.** `00_domain_model.md` §1.2.6 `originalTicketId` (self-FK, F-feltételes); `10` 3.2.2 `originalTicketDisplayId` (DTO-derived); **`10` 4.3 SD-29** kiemelt szekció: *"Ha `originalTicketId` kitöltött: redukált, csak-olvasható nézet — a polgári nyersanyag (cím, leírás, fotók, helyszín) + hangsúlyos link az eredetire. **Nincs triage-sáv, nincs akció-gombsor, nincs duplikáció-doboz.**"*; `10` AC-C4: *"egy ügy `originalTicketId`-ja kitöltött → adatlap betöltődik redukált nézettel."*
- **Screen.** Az A1 adatlap **4 állapot-screenje** (`StateFolyamatban`, `StateNew`, `StateResolved`, `StateRejected`) közül **egyik sem reprezentálja a duplikátum-vetületet**. Az `originalTicketId`/`originalTicketDisplayId` mezőket egyik mock-ticket sem hordozza, a `SimilarTicketsBox`-ban szereplő hasonló-ügyek `displayId`-ja a TARGET-oldalt mutatja (nem a duplikátum-irányt), és a `MergeDialog`/`ConfirmDialog` is csak az explorer-fájlban él (`tier-4-duplikacio*.html`), NEM az A1 adatlap-mockban. A duplikációs `Rejected` ügyre van mock (`StateRejected`, `rejectionReasonCode='PrivateProperty'`), de **`Duplicate`-reason + `originalTicketId`-link kombináció nincs renderelt**.
- **Hatás.** A spec szerint **5. A1 adatlap-állapot** szükséges: `StateDuplicate` — egy `Rejected` ügy `originalTicketId` kitöltve + `rejectionReasonCode='Duplicate'`. Ennek tartalma:
  - `TicketMetaBar` lockolt nézet (státusz=elutasítva)
  - **NINCS** `TriageBar` (SD-29)
  - **NINCS** `ActionBar` (SD-29)
  - **NINCS** `SimilarTicketsBox` (SD-29)
  - **VAN** egy explicit "Duplikátuma az ALM-1052-nek →" link-blokk (a `MergeBody` D-6 alapján vagy egyszerűbb `mgr-original-link` decoration); klikkre az eredeti adatlap.
  - **VAN** a polgári nyersanyag: PhotoGallery + Description + MapMini (read-only).
  - **VAN** ActivityTimeline `Merged`-eseménnyel.
- **Döntés.** **JAVÍTANDÓ** — egy 5. state-artboard felvétele az A1 adatlap-mockra. Mock-szinten nem kötelező (SCREEN-CONVENTIONS.md scope), **de a HANDOFF.md kritikus átadási megjegyzésként hordozza**: az Angular-feature-portoláskor a route-resolver az `originalTicketId` jelenléte alapján a redukált nézetet rajzolja, és ennek mock-adatát a fejlesztő építse meg. **SPEC-FEEDBACK SF-6 (új tétel, 1-gyel feljebb csúsztat — lásd alább a numerationben)** — kritikus, mert teljes vizuális vetület hiányzik.

#### ⚠ #9 — `createdBy` és `updatedBy` (Core User.id)
- **Spec.** §1.2.8 implicit (auditable-örökölt mezők, az `AppDbContext` automatikusan tölti).
- **Screen.** Felületen sehol nem renderelt — helyette a denormalizált `actorName` (Activity-eseményekben) és a `reporterDisplayName` (TicketMetaBar) áll.
- **Döntés.** **Tudatosan kihagyott** — a `createdBy`/`updatedBy` audit-célú, nem polgári vagy belső munka-flow szempont; a `01_kozos_mintak.md` 7.1 a Core `User.id`-ját ad referenciát, ami nem fordítható közvetlenül név-megjelenítésre tenant-oldalon (cross-DB join nélkül, SD-2). Nincs SPEC-FEEDBACK-tétel.


### 🟡 Screen-en van, spec-ben nincs, DE D-X rögzíti

| Screen-elem | Hol jelenik meg | D-X hivatkozás |
|---|---|---|
| ActionBar.hint "Utolsó mentés 2 napja" relatív időbélyeg + tooltip-abszolút | A1 adatlap `StateFolyamatban` `ActionBar.hint` | **D-5/AT-1** — *"Relatív főszöveg, dotted-underline jelzi az affordance-t, `title`-attribútum hordozza az abszolút értéket"*. Az ActionBar.hint a TimeLine mintát örökli — konzisztens döntés. |
| StatusTrack lépés-dátumok (`Új — 2026.05.17.` / `Jóváhagyva — 2026.05.17.` / `Folyamatban — 2026.05.18.` / `Megoldva — 2026.05.19.`) | A1 adatlap minden state `StatusTrack` | **SD-27** + **SD-14** — a 4 fő-ági állapot dátum-vetülete (SD-27); a `assignedAt`/`resolvedAt` denormalizációra építve (SD-14). Spec-fed (a `StatusTrack` ezeket az `ActivityLog`-eseményekből deriválja); a szöveg-formátum (`YYYY.MM.DD.`) `01_kozos_mintak.md` 5.2 i18n-konvenció. |
| A2 form 4 szekció sorrend (probléma → helyszín → bejelentő → triage) | A2 `TicketCreateForm` | **D-7/F-3A** — *"1-oszlopos szekciók, természetes 'mese-sorrend'."* |
| A2 két submit-gomb ("Mentés vázlatként" / "Mentés és kiosztás") | A2 sticky `ActionBar` form-submit | **D-7/F-2A** — *"két submit, explicit; vázlat → status=New; kiosztás → status=Assigned csak teljes triage-vel."* `00_architektura_v4.md` 6.1 fedi a manuális nyitás két útját. |
| A2 LocationPicker map-first layout, Leaflet click+drag, auto-geocode | A2 `LocationPicker` (Leaflet integráció, valódi térkép) | **D-7/L-1, L-2, L-3** — *"nagy térkép felül, cím-mező alatta; click + drag; auto-geocode override-pattern."* |
| StatusTrackBranched banner ("Magánterület" + magyarázat + actor + date) | A1 adatlap `StateRejected` `StatusTrackBranched` | **D-5** vizuális minta (a `rejectionReasonText` és a kiváltó actor-info kombinált rajzolása) + `10` 4.3 implicit ("`Rejected`-ügyön a csík helyett önálló 'Elutasítva' jelző"). |
| A1 adatlap `BackToList` "Vissza a listához" link | A1 adatlap minden state, a `TicketMetaBar` előtt | **`10` AC-G2** + **SCREEN-CONVENTIONS.md §5** (PageHeader-back-row pattern, közvetlen breadcrumb-on felül). A funkcionális visszatérés tab+pagination-megőrzéssel spec-fed; a vizuális ergonomia (Lucide `arrow-left` ikon + kék link) D-1 page-szintű döntés-mintája. |


### 🔍 Screen-en van, spec-ben nincs, NEM dokumentált — UI-találmány

#### 🔍 #4 — A1 adatlap PhotoGallery `caption` mező (kép-aláírás)
- **Hol.** `a1-bejelentes-adatlap.html` `PHOTOS=[{id:1, caption:'Felülnézet'}, {caption:'Közelről'}, {caption:'Méret'}, {caption:'Buszmegálló'}]` → `PhotoGallery` minden képet egy `.a1d-photo__caption` overlay-jel renderel a bal-alsó sarokban.
- **Spec.** `00_domain_model.md` §1.3 `Attachment` mezői: `id`, `ticketId`, `kind`, `fileRef`, `fileName` (opt., max nincs def.), `contentType`, `sortOrder`. **`caption`/`description`/`title` mezőt az `Attachment` NEM tartalmaz.**
- **Probléma.** A polgári app-on a polgár nem fűz caption-t a fotókhoz (a Flutter `screen_uj_bejelentes_2` egyetlen fotó-feltöltő gombot ad, nem fotó-szöveg-páros UI-t). A `caption` adatforrása **bizonytalan** — vagy a `fileName` (de az csak rendszer-fájlnév), vagy egy nem-létező spec-mező. A mock-on a "Felülnézet"/"Közelről"/"Méret"/"Buszmegálló" szövegek **fejlesztői találmányok** a vizuális density növelésére.
- **Döntés.** Két opció:
  - **(a) Spec-bővítés** — `Attachment`-re `caption: string?` (max 100 char) mező. Ezzel egyúttal a polgári app UX-igényeit is felveti (a polgár címkézheti a fotót?), és a 1.3 SD-15 jelenlegi minimum-séma-elvével konfliktust kerülhet. **NEM javasolt** — a polgári UX-ot a 99_donesnaplo nem rögzíti így.
  - **(b) Mock-szintű korrekció** — a `caption` mező törölve a screen-mockból, a fotók caption nélkül jelennek meg (ahogy a polgári Flutter is). Esetleg a `sortOrder` natural-szám-sorszám-ozással kiegészítve (1/4, 2/4, ...) — ez `Attachment.sortOrder`-derived.
- **Javasolt.** **(b) törlés a mockból**, Angular-portoláskor a fotók caption nélkül. **SPEC-FEEDBACK SF-7** — mock-szintű korrekció, NEM spec-szelídítés.

#### 🔍 #5 — A2 `PhoneBanner` amber "Telefonos felvétel" banner
- **Hol.** `a2-uj-bejelentes.html` `PhoneBanner` 📞-ikonnal + `a2-origin-banner__title=`"Telefonos bejelentés-felvétel" + `__desc` 3-mondatos magyarázat az `origin=Manual`-ról.
- **Spec.** `00_architektura_v4.md` §6.1 a két create-utat rögzíti (`New` vagy azonnali `Assigned`), de a `Manual`-eredet **explicit banner-figyelmeztetésével** nem foglalkozik. `10` 5.1 sem említi a banner-mintát.
- **D-X.** **D-7-ben sincs explicit kódolva** — a D-7 a form-elrendezést, két-submit-mintát és LocationPicker-magatartást rögzíti, de a `Manual`-banner nem szerepel a 6 explorer-kérdés között. A banner **nem-dokumentált UX-választás**.
- **Probléma.** A banner pedagógiai értéke nagy (a diszpécser tudja, hogy ezen az ágon a `reporterContactText` kötelezővé válik), de mint UI-elem a D-7 hatókörén túli találmány.
- **Döntés.** Két opció:
  - **(a) D-7 retrofittel** — a D-7 ki kell egészüljön egy **F-4 ponttal** (Manual-eredet banner + magatartás), ami formalizálja a banner-mintát. Ez ⚠ tételt 🟡-ba toldná át.
  - **(b) Törlés** — a banner mock-szinten redundáns (a `PageHeader.description` is szöveges magyarázatot ad). A `reporterContactText`-kötelezőség a form-field-error-state-en jelenik meg, nem banner-szinten.
- **Javasolt.** **(a) D-7 retrofit** — a banner valódi pedagógiai értéke a pilot-célközönség (Béla, Anna) számára nagy. **SPEC-FEEDBACK SF-8** — D-X-formalizálás kérése a DECISIONS.md-be (mini-revízió: D-7 F-4 új pont vagy új D-18 a Manual-eredet banner-pattern-jén).

#### 🔍 #6 — A2 `ValidationBanner` piros "A bejelentés nem menthető" banner
- **Hol.** `a2-uj-bejelentes.html` `StateValidationError` `ValidationBanner` !-ikonnal + 2-elemes mező-hiba-lista.
- **Spec.** `10` 4.6 hibakezelési kulcs-csoport (`ticket.error.*`) — a szerver **mezőszintű** `fieldErrors`-t ad vissza, a meglévő `[validationForm]` minta szerint. **Banner-szintű összesítő hiba-megjelenítés nincs spec-elve.**
- **D-X.** D-7-ben sincs (ott az F-elrendezés és L-LocationPicker döntései szerepelnek).
- **Probléma.** A `[validationForm]` mintában a hiba-megjelenítés a form-field szintjén történik (`<form-field>` jelenítteti meg az `fieldErrors[name]`-t). A banner egy plusz vizuális réteg, amit a spec nem ír elő — viszont a banner összesít, és nagyobb formokon (10+ mező) értékes UX. A2 4 szekciójának kontextusában az érték kétséges.
- **Döntés.** Két opció:
  - **(a) Spec-szelídítés** — a banner-pattern-t a `01_kozos_mintak.md` 6.3 hibakezelés szakasza opcióként rögzíti (form-banner + per-field-error kombináció).
  - **(b) Törlés** — a per-field-error elég, a banner redundáns.
- **Javasolt.** **(b) törlés** — a 4 form-mező + 4-szekció kontextusában a per-field-error a `<form-field>`-en a bejáratott pattern, és a banner felesleges figyelem-konfliktust ad a per-field jelzéssel. **SPEC-FEEDBACK SF-9** — mock-szintű korrekció.

---

## Backward pass — későbbi iter

Lásd Batch 1 backward-pass-szövegét. A Batch 2-ben felmerült backward-pass-elemek (BackToList, MapMini-fix-rajzolás, A2 banner-ek, A2 LocationPicker auto-geocode override) jelenleg a forward-pass `🟡`/`🔍` rovataiban már kezeltek.

---

## Batch 2 összegzés

| | Tétel-szám |
|---|---|
| ✅ Teljes fed | 8 elem (addressText, origin, reporterId→reporterDisplayName, reporterContactText, assignedAt, resolvedAt, createdAt, updatedAt) |
| ✅ Részleges fed | 2 elem (`latitude`/`longitude` — A2 fed, A1 adatlap MapMini stub; `thumbnailRef`/`attachmentCount` — adatlap PhotoGallery fed, lista oszlop hiány) |
| ⚠ Hiányosság | 4 (#6 MapMini koord-nélküli, #7 lista bélyegkép-oszlop, **#8 originalTicketId redukált nézet — kritikus**, #9 createdBy/updatedBy tudatosan kihagyott) |
| 🟡 D-X-rögzített UX-választás | 7 elem (ActionBar.hint relatív, StatusTrack-dátumok, A2 4-szekció-sorrend, A2 két submit, A2 LocationPicker Leaflet, StatusTrackBranched banner, BackToList link) |
| 🔍 UI-találmány | 3 (#4 PhotoGallery caption · #5 A2 PhoneBanner · #6 A2 ValidationBanner) |

**Új SPEC-FEEDBACK-tételek:** SF-6 (MapMini→MapWidget), **SF-7 (originalTicketId redukált nézet — kritikus, új 5. state szükséges)**, SF-8 (PhotoGallery caption törlése), SF-9 (A2 PhoneBanner → D-7 retrofit), SF-10 (A2 ValidationBanner törlése).

> **Megjegyzés a renumerationhez.** A Batch 1-ben SF-1..SF-5 nyitottam (`priority` lista-oszlop · `assigneeType` DTO-bővítés · "(javasolt)" fallback · `resolutionNote` Resolved-adatlap · Resolved Description.attrs törlés). A Batch 2 SF-6..SF-10-t ad — **a SF-1-be a bélyegkép-oszlop is belekerül** mint hatókör-pontosítás (NEM új SF). Lásd SPEC-FEEDBACK.md.

---

## Batch 3 — Kísérő-entitások: `TicketNote` · `ActivityLog` · `SimilarTicket`-DTO

## Forward pass — 22 elem + 7 enum-érték

### ✅ Spec-ben + screen-en is megvan

#### TicketNote (`00_domain_model.md` §1.5)

| Mező | Spec-forrás | Screen-evidence |
|---|---|---|
| `id`, `ticketId` (long PK, FK) | §1.5 | Belső; nem felületi. A spec is implicit kihagyja a megjelenítésből — ⚠ tudatos kihagyás (alább). |
| `authorId` → `authorName` (derived) | §1.5 + `10` 3.2.2 `notes[].authorName` | A1 adatlap `InternalNotesPanel.notes[].authorName` (`'Kovács Anna'`, `'Szabó Zoltán'`, `'Tóth Béla'` mind a 3 jegyzeten). |
| `body` (string ≤2000) | §1.5 | `InternalNotesPanel.notes[].body` — pl. *"Helyszínen voltam tegnap este — a kátyú valóban nőtt..."* (`NOTES[0].body`); a composer-textarea-ban szintén. **Hosszkorlát-validáció vizuálisan NEM kódolt** (a textarea nem mutat counter-t); szerver-oldali `FluentValidation` érvényesít (`10` 3.6). |
| `createdAt` (auditable) | §1.5 (öröklött) | `InternalNotesPanel.notes[].occurredAt='2026.05.18. · 09:15'` (abszolút tooltip-vetülete) + `notes[].relative='4 napja'` (relatív főszöveg) — D-5/AT-1 hybrid. |

#### ActivityLog (`00_domain_model.md` §1.4)

| Mező | Spec-forrás | Screen-evidence |
|---|---|---|
| `id`, `ticketId` (long PK, FK) | §1.4 | Belső; nem felületi. |
| `eventType` ×7 enum | §1.4 + `10` 4.6 i18n-sablonok | **Részleges fed — 7-ből 4** renderelt: `Created` ✅ (4/4 state), `StatusChanged` ✅ (Folyamatban+Resolved+Rejected), `Assigned` ✅ (Folyamatban event #2), `Reassigned` ⚠ (mock-on rosszul címkézve, lásd 🔍 #7). **3 hiányzó**: `Rejected`, `Reopened`, `Merged` — lásd ⚠ #10. |
| `actorId` → `actorName` (derived, F-feltételes) | §1.4 + `10` 4.6 i18n `ticket.activity.actor.system` | A1 adatlap `ActivityTimeline.events[].actorName` minden esemény-soron. **`actorId === null` rendszer-eset fed**: `StateResolved` 7. eseménye `{actorName:'Rendszer', text:'lezárás-emlékeztetőt küldött a bejelentőnek'}` — a `ActivityTimeline` `systemEventActor || 'A rendszer'` fallback-jét triggereli. |
| `occurredAt` (DateTime) | §1.4 | `events[].occurredAt='2026.05.17. · 14:22'` (abszolút) + `events[].relative='5 napja'` (relatív) — D-5/AT-1 hybrid. |
| `note` (string, opt.) | §1.4 + `10` 4.6 `Rejected`-sablon `{reason}` placeholder | **Rejected-eseten denormalizálva**: `REJ_ACTIVITY[1].text='státusz: Új → Elutasítva · indok: Magánterület'` — a `note` szöveg a `text` mezőbe olvasztva (lásd ⚠ #11 — stable-ID vs. magyar-szöveg eltérés). |

#### SimilarTicket-DTO (`20_duplikacio` 3.1)

| Mező | Spec-forrás | Screen-evidence |
|---|---|---|
| `id` (long) | 20_dup 3.1.2 | A1 adatlap `SIMILAR_FINDINGS[*].id` (1052, 1048); `onOpen(id)` callback paraméter. |
| `displayId` (string) | 20_dup 3.1.2 | `SIMILAR_FINDINGS[*].displayId='ALM-1052'` (mono-formázott a `.mgr-similar__display-id` cellán). |
| `title` (string) | 20_dup 3.1.2 | `SIMILAR_FINDINGS[*].title='Felázott útburkolat a Hősök terén'`. |
| `status` (enum → `statusKey`+`statusLabel`) | 20_dup 3.1.2 | `SIMILAR_FINDINGS[*].statusKey='jovahagyva', statusLabel='Kiosztva'` — a `status` enum-érték kliens-oldali bontása a `StatusChip` rendereléséhez. ✅ funkcionálisan azonos. |
| `categoryLabel` (string) | 20_dup 3.1.2 | `SIMILAR_FINDINGS[*].categoryLabel='Utak és járdák'` (a gyökér-szintű feloldás — `20_dup` 2.5 heurisztika-szabály a gyökérre szól). |
| `distanceMeters` (int) | 20_dup 3.1.2 + sorrend-előírás | `SIMILAR_FINDINGS[0].distanceMeters=320, [1].distanceMeters=420` — növekvő sorrendben (`20_dup` 3.1.3), a `.mgr-similar__signal-distance` cellán "320 m" formátumban. |
| `ageDifferenceDays` (int) → `ageLabel` (derived) | 20_dup 3.1.2 | `SIMILAR_FINDINGS[*].ageLabel='3 napja' / '6 napja'` — a `ageDifferenceDays` kliens-oldali relatív-formázása. ✅ funkcionálisan azonos. |
| **`thumbnailRef` (string?) — RÉSZBEN ✅** | 20_dup 3.1.2 | `SIMILAR_FINDINGS[*].thumbnailUrl=null` — a prop fogadva, de mind `null`-érték; a `Thumb` komponens placeholder-jelzéssel él (`IconImagePlaceholder` Lucide-szerű). Valódi bélyegkép-rendering a mock-on nincs (a polgári app fotók még nem szállítva). Funkcionálisan kész, csak adat-rés a mock-on. |


### ⚠ Spec-ben van, screen-en nincs — hiányosság

#### ⚠ #10 — ActivityLog 3 eseménytípus hiányzik (`Rejected` · `Reopened` · `Merged`)
- **Spec.** `00_domain_model.md` §1.4 — 7 értékű `ActivityEventType`. `10` 4.6 i18n-sablonok mind a 7-re: `ticket.activity.{created|statusChanged|assigned|reassigned|rejected|reopened|merged}`.
- **Screen.** A 4 A1 adatlap-állapot ActivityTimeline-jaiban a 7 enum közül **csak 3 renderelt** dedikált `eventType`-pal: `Created`, `StatusChanged`, `Assigned`. A `Reassigned` mock-on **rosszul címkézve** (lásd 🔍 #7). A `Rejected` esemény **NEM renderelt** — a `StateRejected` `REJ_ACTIVITY[1].eventType='StatusChanged'`, helyette a magyar szöveg "státusz: Új → Elutasítva · indok: Magánterület" magában hordozza az elutasítást, de az ikon nem a piros 'X' (Rejected), hanem a kék nyíl (StatusChanged). A `Reopened` és `Merged` események egyik mock-state-en sem szerepelnek.
- **Hatás.** Az `ActivityTimeline` organism teljes ikon-szettje (7 ICONS-mapping) **vizuálisan nem demonstrált** — a fejlesztő a screen-mockból a 4 ikon-variánst látja, és nem tudja, hogyan néz ki a Rejected/Reopened/Merged ikon-rendering kontextusban. A `Merged` ikon hiánya közvetlenül **kapcsolódik SF-7**-hez (originalTicketId redukált nézet — egyik mellékhatása a `Merged`-esemény).
- **Döntés.** **JAVÍTANDÓ — mock-bővítés** — a screen-fázis fejlesztője a 9. lépés `starter/` mintaprojektjében a 3 esemény-vetületet építse be. Vagy:
  - **(a) SF-7 5. state-en belül:** `StateDuplicate` `ActivityTimeline` `Merged`-eseményt rendereli — a SF-7 része. Plusz egy `Rejected`-eseményt is, mert a duplikátum-ügy `Rejected`-be lép.
  - **(b) `StateResolved` mock-bővítése:** egy `Reopened`-esemény demonstrálása (pl. `id:8, eventType:'Reopened', actorName:'Tóth Béla', text:'visszanyitotta a bejelentést — a polgár jelezte, hogy a kátyú újra megnyílt'`).
- **SPEC-FEEDBACK SF-11** — mock-szintű korrekció, NEM spec-szelídítés.

#### ⚠ #11 — `ActivityLog.fromValue` / `toValue` (stable ID) **a mockon nincs külön mező**
- **Spec.** `00_domain_model.md` §1.4 + `10` 3.2.2 + SD-30: *"`activityLog.fromValue` / `toValue` — stabil, nyelvfüggetlen azonosítót hordoz (`enum`-név, vagy `type:id` referencia, pl. `'group:3'`), **nem magyar szöveget**. Az `actorName` viszont megjelenítésre kész."* Az i18n-sablon (`ticket.activity.statusChanged` = `'{actor} módosította a státuszt: {from} → {to}'`) helyettesíti be a stable ID-t magyar szövegre.
- **Screen.** Az `ActivityTimeline` `events[].text` egy **magyar-szöveg-vetület**, ami a `fromValue` és `toValue` **már denormalizált** változatát hordozza:
  - `'státusz: Jóváhagyva → Folyamatban'` — a magyar szöveg
  - **vs. spec szerinti DTO**: `fromValue='Assigned'`, `toValue='InProgress'`, i18n sablon-feloldás kliens-oldalon
- **Probléma.** A screen-mock a magyar-szöveg-vetületet hordozza, **kihagyva a stable-ID-réteget**. A 9. lépés Angular-portolásakor a fejlesztő ezt **nem** veheti át literál módon — a sablon-feloldás kliens-oldali kell legyen. A mock-on a magyar szöveg **kényelmes hardcode**, nem spec-szerű DTO.
- **Döntés.** **JAVÍTANDÓ — mock-mintaadat-szerkezet** — a `events[].text` mező cserélendő `events[].fromValue` + `events[].toValue` + `events[].note` mezőtripletre, és az `ActivityTimeline` organism prop-szerződését bővíteni egy `t(key, params)` i18n-callback-kel. Ez azonban **mély organism-átstrukturálás**, ami a screen-mock-fázisban (SCREEN-CONVENTIONS.md scope) nem kötelező.
- **SPEC-FEEDBACK SF-12** — **átadási megjegyzés** a HANDOFF.md-be: az Angular-portoláskor az `ActivityTimeline` consume-szerződését a stable-ID-DTO-ra kell formálni, NEM a magyar-szöveg-mock-szerződésre.

#### ⚠ #12 — `SimilarTicket-DTO.updatedAt` mező nincs a mockon
- **Spec.** `20_duplikacio` 3.1.2 `SimilarTicketDto.updatedAt: DateTime` — *"A találat concurrency-tokene — ha a felhasználó az összevonás-párbeszédben megfordítja a szerepeket, a `merge` ezt küldi `expectedUpdatedAt`-ként (lásd 4.3.2)."* SD-32 minta.
- **Screen.** A `SIMILAR_FINDINGS` mock 7 mezőt szállít: `id, displayId, title, statusKey, statusLabel, distanceMeters, ageLabel, categoryLabel, attachmentCount, thumbnailUrl`. **`updatedAt` NINCS.**
- **Probléma.** A 9. lépés Angular-portolásakor a fejlesztő a `MergeConfirmDialog`/`ConfirmDialog` `MergeBody` (D-6/MD-1A) szerep-csere flow-jánál a `targetTicket.updatedAt`-ot kell elküldje az `originalTicketId`-vetületben. A mock ezt **nem hordozza**, és a Tier-4 `MergeDialog` explorer-fájl (`tier-4-duplikacio*`) ezt feltehetően mock-szinten szintén kihagyja.
- **Döntés.** **JAVÍTANDÓ — mock-bővítés** — a `SIMILAR_FINDINGS` `updatedAt` mezővel bővítendő (mock-érték: ISO-string). A `SimilarTicketsBox.items[].updatedAt`-ot a komponens nem feltétlenül rajzolja, de a `MergeDialog.onConfirm`-flow-nak kell.
- **SPEC-FEEDBACK SF-13** — mock-szintű korrekció, NEM spec-szelídítés.

#### ⚠ #13 — `TicketNote.id` / `ticketId` / `body` szerkesztés-edit-mode-ja
- **Spec.** `00_domain_model.md` §1.5: *"A pilotra a `TicketNote` a létrehozás után **módosítható és törölhető** a szerző (és a vezető) által — standard CRUD."* `10` 3.5 `PUT /v1/ticket-notes/{id}` + `DELETE /v1/ticket-notes/{id}`.
- **Screen.** Az `InternalNotesPanel` jegyzet-sorai csak olvasott megjelenítést mutatnak — **edit/delete sor-akció nincs**. A composer az új-jegyzet-be-vitelt szolgálja, de meglévő jegyzet módosítása/törlése nem érhető el a komponensből.
- **Döntés.** **JAVÍTANDÓ — organism-bővítés** — `InternalNotesPanel.notes[].editable: boolean` prop, és minden szerkeszthető soron egy kebab-menü ('Szerkesztés' · 'Törlés'). A jogosultság-szabály (`05` 6.1): csak a szerző és a vezető láthatja az edit/delete akciókat.
- **Hatás.** Pilot-feature; HANDOFF.md átadási megjegyzés.
- **SPEC-FEEDBACK SF-14** — organism-bővítés.

#### ⚠ #14 — A4-tudatosan kihagyott (`TicketNote.id`, `TicketNote.ticketId`, `ActivityLog.id`, `ActivityLog.ticketId`)
- **Spec.** Belső PK + FK; felületen sosem jelennek meg.
- **Döntés.** **Tudatos kihagyás** — nincs SPEC-FEEDBACK-tétel.


### 🟡 Screen-en van, spec-ben nincs, DE D-X rögzíti

| Screen-elem | Hol jelenik meg | D-X hivatkozás |
|---|---|---|
| ActivityTimeline esemény-típusonkénti ikon-háttér + szín (kék = StatusChanged, piros = Rejected, amber = Reopened, violet = Merged, …) | A1 adatlap minden state `ActivityTimeline` 7 ikon-variánssal | **D-5/AT-2B** — *"Event-type ikon halvány színes háttéren; státusz-átmenet kék, elutasítás piros, visszanyitás amber, merge violet. A 7 eseménytípus egy pillantással szétválasztható."* |
| ActivityTimeline relatív főszöveg + dotted-underline + `title`-tooltip-abszolút | minden esemény-sor `.mgr-timeline__text-meta` | **D-5/AT-1** hibrid pattern. |
| InternalNotesPanel composer alul (chat-szerű, N-1B) | `.mgr-notes__composer` a notes-lista végén | **D-5/N-1B** — *"Beszélgetés-szerű együttműködés természetesebb."* |
| InternalNotesPanel régi → új sorrend (kronológiai, N-2A) | `notes` lista nem rendez (a komponens leírása expl.) | **D-5/N-2A** — *"Konzisztens N-1B chat-form-mal: a legfrissebb jegyzet közvetlenül a composer mellé kerül."* |
| InternalNotesPanel `readOnly` mód (composer rejtve, `field_worker`-re) | `StateResolved` `<InternalNotesPanel readOnly />` | **`05_jogosultsagok_v2.md` 6.1** + `10` 4.3 elemtérkép — spec-fed; a `readOnly` prop az implementáció-szintje D-szerű. |
| SimilarTicketsBox findings-fejléc amber + alert-ikon + count-badge + 3px bal accent-border | `state='findings'` `.mgr-similar__head--findings` | **D-6/SB-4A** — *"Találatok esetén amber fejléc-háttér + alert-ikon + 'N találat' badge + 3px bal accent-border."* |
| SimilarTicketsBox empty-state csendes szöveg ("Nincs hasonló nyitott bejelentés.") | `state='empty'` `.mgr-similar__empty` | **D-6/SB-1A** — *"Egyetlen halvány szövegsor. Jelzi, hogy a rendszer ellenőrzött, de figyelmet nem kér."* |
| SimilarTicketsBox sor: bélyegkép balra 56×56, `displayId` mono, status-chip + meta-row, jobbra "Összevonás" gomb | `.mgr-similar__item` szerkezet | **D-6/SB-2A** (bélyegkép) + **D-6/SB-3A** (akciók mindig látható jobb-end). |
| ActivityTimeline `actor`-bold renderelés, `text-meta` halvány szöveg | `.mgr-timeline__text strong + meta` | **`10` 4.6 sablon-szerkezet** + D-5 vizuális megvalósítás (a `{actor}` placeholder bold-rendereléses az i18n-feloldás után). Spec-fed; vizuális finomítás D-5. |
| ActivityTimeline `isSystem` halvány szöveg variáns (`actorName === null`) | `.mgr-timeline__text--system` modifier | **`10` 4.6** + §1.4 — *"`actorId` lehet üres → semleges alany (`ticket.activity.actor.system`)."* Spec-fed elv; vizuális tone-differenciálás D-5. |


### 🔍 Screen-en van, spec-ben nincs, NEM dokumentált — UI-találmány

#### 🔍 #7 — ActivityLog `Reassigned` esemény mock-on rosszul címkézve
- **Hol.** `a1-bejelentes-adatlap.html` `StateFolyamatban` `ACTIVITY[3]`:
  ```jsx
  { id: 4, eventType: 'Reassigned',    actorName: 'Tóth Béla',
    occurredAt: '2026.05.19. · 07:30', relative: '3 napja',
    text: 'határidő-módosítás: 2026.05.21 → 2026.05.23' },
  ```
- **Spec.** `00_domain_model.md` §1.4 `ActivityEventType` táblája: *"`Reassigned` — Felelős-váltás (nem státuszváltás)"*; `10` 4.6 sablon: *"`ticket.activity.reassigned` → `{actor} felelőst váltott: {from} → {to}`"*. A `Reassigned` eseménytípus **kizárólag** felelős-cserét jelez.
- **Probléma.** A mock-on a `Reassigned` event-type egy **dueDate-módosítást** címkéz — ami nem felelős-csere. Sőt, a spec szerint a `dueDate` inline-edit (`PUT .../due-date`) **NEM** vált `ActivityLog`-eseményt (`10` 3.3 + AC-D1: *"`PUT .../category` `200`, … nem keletkezik `ActivityLog`-bejegyzés"*; a `dueDate` ugyanaz a csoport, lásd `10` 3.7).
- **Döntés.** **Mock-szintű korrekció** — a 4. esemény vagy:
  - **(a) Törlés** — a `dueDate`-inline-edit nem keletkezik napló-eseményt; a mock 4. sora hibás, törlésre javasolt.
  - **(b) Cserelés valódi `Reassigned`-re** — pl. `{eventType:'Reassigned', text:'felelőst váltott: Kovács Anna → Szabó Zoltán'}`. Ez vizuálisan értékes a fejlesztőnek, mert a Reassigned ikon-variánst (`refresh-ccw`-szerű) demonstrálja.
- **Javasolt.** **(b)** — a mock-on a `Reassigned` valódi felelős-cserét reprezentáljon. **SPEC-FEEDBACK SF-15** — mock-szintű korrekció.

#### 🔍 #8 — `SimilarTicketDto.attachmentCount` mező a spec-ben hiányzik
- **Hol.** `SIMILAR_FINDINGS[0].attachmentCount=2, [1].attachmentCount=1` — a `SimilarTicketsBox.Thumb` komponens `attachmentCount > 1` esetén egy `mgr-similar__thumb-badge` Lucide `camera` + szám badge-et rajzol jobb-alul.
- **Spec.** `20_duplikacio` 3.1.2 `SimilarTicketDto` 10 mező: `id, displayId, title, status, categoryLabel, distanceMeters, ageDifferenceDays, createdAt, updatedAt, thumbnailRef`. **`attachmentCount` NINCS.**
- **D-X.** **D-6/SB-2A** expicit kódolja a darabszám-badge UI-mintát: *"Bélyegkép balra 56×56; fotó-darabszám-badge jobb-alul."* A D-X tehát rögzíti az UI-elemet, **de a spec-DTO nem hordozza az adatot.**
- **Probléma.** Vagy:
  - **(a) Spec-DTO bővítendő** `attachmentCount: int`-tel — a D-6 megerősíti az UI-igényt.
  - **(b) A `SimilarTicketsBox.Thumb` badge-renderelést törölni kell** — a mock-on jelen állapot meghaladja a spec-szerződést.
- **Javasolt.** **(a) Spec-DTO bővítés** — az adat triviálisan számolható szerver-oldalon (`Attachment.WHERE kind='ReportPhoto'.COUNT`), a D-6 UI-mintát igazolja, és a fejlesztő szándékát is fedi. **SPEC-FEEDBACK SF-16** — **érdemi spec-szelídítés**: `20_duplikacio` 3.1.2 `SimilarTicketDto` bővítendő `attachmentCount: int` mezővel.

#### 🔍 #9 — `TicketNote.role` mező mock-szinten (a szerző tenant-szerepköre)
- **Hol.** `a1-bejelentes-adatlap.html` `NOTES[*].role='diszpécser' / 'terepi dolgozó' / 'vezető'` — az `InternalNotesPanel` `.mgr-notes__item-role` "· diszpécser" suffix-szel megjeleníti.
- **Spec.** `00_domain_model.md` §1.5 `TicketNote` mezők: `id, ticketId, authorId, body` + `AuditableEntity`-örökölt mezők. **`role` mező NINCS.**
- **Honnan jönne.** A `TenantUser.roles` (`enum[] TenantRole`, lásd §2.3) — a jegyzet szerzőjének tenant-szintű szerepkörei. A megjelenítés egy `roles[0]` (vagy első nem-üres) `enum`-érték magyar-i18n-vetülete. **A jegyzet-DTO ezt nem hordozza** (csak `authorId` + `authorName`).
- **Probléma.** A role-suffix pedagogikai érték (a jegyzet kontextusa: "a vezető írta", "a terepi dolgozó írta") — de a `TicketNote`-DTO bővítése **a `TenantUser`-cross-lookup-pal** rontaná a `notes`-DTO denormalizációját (jelenleg csak `authorName`-et tartalmaz, ami `TenantUser.displayName`-projekció — egy cross-lookup minden notes-betöltéskor).
- **Döntés.** Két opció:
  - **(a) `TicketNoteDto` bővítés** `authorRole: string`-gel (a `TenantUser.roles[0]` denormalizált vetülete a beágyazott notes-DTO-ban). Pilot-szinten kis költségű.
  - **(b) Törlés a mockból** — a role-suffix elveszik, a jegyzet csak `authorName`-mel renderel.
- **Javasolt.** **(a) Spec-DTO bővítés** — a role-kontextus a belső együttműködés pedagogikája szempontjából értékes (a diszpécser tudja, kitől származik a jegyzet típusa szerint). **SPEC-FEEDBACK SF-17** — **érdemi spec-szelídítés**: `10` 3.2.2 `notes[]` bővítendő `authorRole: string?` mezővel.

#### 🔍 #10 — `TicketNote.authorInitials` mock-szinten
- **Hol.** `NOTES[*].authorInitials='KA' / 'SZ' / 'TB'` — az `InternalNotesPanel` `.mgr-notes__avatar` cellán renderel.
- **Spec.** Nincs `authorInitials` mező a `TicketNote`-on. **Trivial-derived** — a `authorName.split(' ').map(w => w[0]).join('').toUpperCase()` kliens-oldali számítás.
- **Döntés.** **NEM SPEC-FEEDBACK** — a `authorInitials` kliens-oldali computed string a `authorName`-ből; a mock-on direkt mezőként hordozni mock-kényelem, nem UI-találmány. Nincs SF.


---

## Backward pass — lezárva

A backward-pass az előző 2 batch-ben a `🟡` és `🔍` rovatokban már lefutott (TriageBar tag-ok, ActionBar.hint, A2 banner-ek, MapMini stub, BackToList link, PhotoGallery caption, Description.attrs Resolved-en). A Batch 3 további elemei:

| Screen-elem | Hová sorolva |
|---|---|
| `InternalNotesPanel` "Még nincs belső jegyzet" empty-state — két variáns (`readOnly` vs. szerkeszthető) | 🟡 — D-5 implicit (a komponens leírása rögzíti) |
| `InternalNotesPanel` composer Enter/Shift+Enter-hint (`kbd`-elem) | 🟡 — D-5 N-1B chat-pattern része; a `kbd`-hint a modern editor-pattern (GitHub Issues, Linear) |
| `ActivityTimeline` `text-meta` mező (a magyar szöveg-vetület mint denormalizált adat) | ⚠ #11 (Batch 3 fent) |
| `SimilarTicketsBox` "Mind 4" / "Mégsem" expand-collapse-link (3-on felüli találatok) | 🟡 — `20_duplikacio` 3.1.3 limit 20 + D-6 (3-4 közvetlen) implicit-fed |
| `SimilarTicketsBox` row-click → `onOpen(id)` + "Összevonás" gomb külön | 🟡 — D-6/SB-3A *"Megnyitás mint row-click + chevron; Összevonás mint mindig látható secondary."* |

---

## Batch 3 összegzés

| | Tétel-szám |
|---|---|
| ✅ Teljes fed | 12 elem (TicketNote `authorName`/`body`/`createdAt`; ActivityLog `occurredAt`/`actorName`+`null`-eset/`note`; SimilarTicket `id`/`displayId`/`title`/`status`/`categoryLabel`/`distanceMeters`/`ageDifferenceDays`) |
| ✅ Részleges fed | 2 elem (`SimilarTicket.thumbnailRef` — prop fogadva, mock-érték null; `ActivityLog.eventType` — 4/7 enum-érték renderelt) |
| ⚠ Hiányosság | 5 (#10 3 hiányzó eseménytípus · **#11 stable-ID vs. magyar-szöveg eltérés** · #12 SimilarTicket.updatedAt · #13 TicketNote edit/delete · #14 belső PK/FK tudatos kihagyott) |
| 🟡 D-X-rögzített | 10 elem |
| 🔍 UI-találmány | 4 (#7 Reassigned mock-bug · **#8 SimilarTicketDto.attachmentCount spec-bővítés** · **#9 TicketNote.role spec-bővítés** · #10 authorInitials trivial-derived) |

**Új SPEC-FEEDBACK-tételek:** SF-11 (3 hiányzó eseménytípus mock-bővítés), **SF-12 (stable-ID DTO-szerződés vs. magyar-szöveg mock — HANDOFF.md kritikus)**, SF-13 (SimilarTicket.updatedAt mock-bővítés), SF-14 (TicketNote edit/delete organism-bővítés), SF-15 (Reassigned mock-bug törlés vagy csere), **SF-16 (SimilarTicketDto.attachmentCount spec-bővítés)**, **SF-17 (TicketNote.authorRole spec-bővítés)**.

---

# Phase 2A — záró összegzés

A 3 batch-ből álló forward-pass + backward-pass **lezárva**. 52 elem mező-szinten vizsgálva, **17 SPEC-FEEDBACK-tétel** (SF-1..SF-17) keletkezett.

## Globális számszerű eredmény

| Kategória | Batch 1 | Batch 2 | Batch 3 | **Összesen** |
|---|---|---|---|---|
| ✅ Teljes fed | 7 | 8 | 12 | **27** |
| ✅ Részleges fed | 3 | 2 | 2 | **7** |
| ⚠ Hiányosság | 5 | 4 | 5 | **14** |
| 🟡 D-X-rögzített | 11 | 7 | 10 | **28** |
| 🔍 UI-találmány | 2 | 3 | 4 | **9** |

**Megjegyzés.** A "tudatosan kihagyott" `⚠` tételek (id PK-k, `createdBy`/`updatedBy`) NEM nyitnak SF-et — azok spec-szerinti kihagyások. A 14 `⚠`-ból **10 érdemi javítandó** + **4 tudatos kihagyott**. A 9 `🔍`-ből **2 érdemi spec-bővítés** (SF-16, SF-17), **5 mock-szintű korrekció**, **2 trivial-derived nem-SF**.

## Phase 3-ban konszolidálandó

1. **SF-1..SF-17 prioritás-mátrix.** A spec-csapat döntse el a `under-review`-státuszú tételeket. A `accepted-pending-mock-update` tételek (SF-5, SF-8, SF-10, SF-15) NEM kell spec-szelídítést; a HANDOFF.md átadási megjegyzésként hordozza.

2. **3 kritikus SF.**
   - **SF-7** (originalTicketId redukált nézet) — vizuálisan teljes hiány; a 9. lépés `starter/` projekt építse meg. Kapcsolódik SF-10-hez (Merged-esemény).
   - **SF-11** + SF-12 (ActivityLog stable-ID DTO-szerződés) — HANDOFF.md kritikus átadási megjegyzés; a fejlesztő ne vegye literál módon a mock-adatot.
   - **SF-16** + SF-17 (SimilarTicketDto.attachmentCount + TicketNoteDto.authorRole spec-bővítés) — valódi spec-szelídítések, érdemes a spec-csapatnak elfogadni; minimális kost, magas pedagógiai érték.

3. **A 14 `⚠`-ból 4 a `TicketListDto`-hoz kötődik** (#1 id-PK-tudatos · #2 priority oszlop · #3 group-felelős · #4 "(javasolt)" fallback · #7 bélyegkép-oszlop) — ez egy **közös TableStateConfig javítás** Phase 3 Angular-portoláskor.
