feat(FN-411): Merge pull request 'dev' (#3) from dev into main (+16 more)

Commits merged:
- docs(FN-411): scoping output — spawned FN-415 (FN-367 mechanical verification) and FN-416 (FN-368 mechanical verification)
- Merge pull request #21 — feat(FN-403): parts panel manifest
- Merge pull request #20 — feat(FN-401): blocker note
- Merge pull request #19 — feat(FN-400): selector manifest
- Merge pull request #18 — feat(FN-399): PostHog cross-session funnel audit
- Merge pull request #17 — chore(payments): Stripe-only
- Merge pull request #16 — feat(FN-395): P1 candidate shortlist
- Merge pull request #15 — broaden leaf detection
- fix(categories): broaden leaf detection to all /extern/*/{vin,mdl}_items endpoints
- Merge pull request #14 — fix(pl24): Ford VIN flow
- Merge pull request 'dev' (#13) from dev into main
- Merge pull request 'feat(FN-367): add inline retry affordance after VIN decode failure (FN-367, gitea #11)' (#12) from dev into main
- Merge pull request 'dev' (#9) from dev into main
- Merge pull request 'dev' (#8) from dev into main
- Merge pull request 'docs(readme): spacing tweak — measure cache-enabled dev deploy speed' (#7) from dev into main
- Merge pull request 'docs(readme): add staging URL — gitea deploy flow smoke test' (#4) from dev into main
- Merge pull request 'dev' (#3) from dev into main

Files changed:
SCOPING-FN-411.md                             | 85 +++++++++++++++++++++++++++
 apps/api/src/catalog/catalog.service.ts       |  8 ++-
 apps/api/src/categories/categories.service.ts | 23 +++++---
 3 files changed, 107 insertions(+), 9 deletions(-)

Fusion-Task-Id: FN-411
This commit is contained in:
Fusion
2026-05-16 23:54:09 +00:00
parent d4baececee
commit 78ab45d512
2 changed files with 88 additions and 0 deletions

85
SCOPING-FN-411.md Normal file
View File

@@ -0,0 +1,85 @@
# FN-411 — Recon-to-Implementation Scoping Output
**Date:** 2026-05-16
**Inputs:**
- `MANIFEST.md` (FN-400 recon over FN-367 / VIN decoder)
- `MANIFEST-FN-403.md` (FN-403 recon over FN-368 / parts panel)
**Output:** Two new triage tasks created. Both classified **mechanical** per memory
`recon-to-implementation-scoping-pattern` — no FN-406-style UX-spec precursor required.
---
## Spawned tasks
### FN-415 — FN-367 VIN-decode retry verification + hit-target audit
- **Parent:** FN-367 (shipped `e274e02`).
- **Route:** `/dashboard/search` (`apps/web/src/routes/dashboard/search.tsx`).
- **New spec file:** `apps/web/e2e/vin-decode-retry.spec.ts` (location subject to repo Playwright dir convention; selectors are canonical).
- **Production edit (conditional):** Retry button hit-target widen to ≥44 px if measurement on `375 × 667` viewport fails the Apple HIG / Material baseline.
- **AC anchors:** locator stability (data-faro + role/name), retry-render guard
(NOT rendered on `"abone olun"` / `"tanınamadı"` branches), PostHog
`vin_decode_retry_clicked`, hit-target ≥44 px, no line-number assertions.
- **UX-spec precursor:** Not required.
### FN-416 — FN-368 parts-panel verification + hit-target audit
- **Parent:** FN-368 (shipped `0ce68a7`).
- **Component:** `apps/web/src/components/schema/parts-panel.tsx`.
- **Mount routes (4):** `vehicles_/$id/categories_/$categoryId`,
`catalog_/$brandName_/$modelId/categories_/$categoryId`,
`catalog_/emex/$catalogCode_/$vehicleId_/groups/$groupId`,
`catalog_/pcat/$catalogId_/$modelId_/$carId_/groups/$groupId`.
- **New spec file:** `apps/web/e2e/parts-panel.spec.ts`.
- **Production edits (conditional):** OEM copy button (≈18 px today), parts row
vertical (≈36 px today), "Geri don" empty-state escape (≈40 px today) — widen
to ≥44 px via minimal Tailwind token swap. Escalate to UX-spec precursor if
any widen forces layout reflow.
- **AC anchors:** inert-row no-op (FN-368 core fix), available-row toggle +
scrollIntoView, OEM copy `stopPropagation` + clipboard + PostHog +
`/analytics/oem-copy`, loading skeleton count = `SKELETON_ROW_KEYS.length`,
empty-state `Geri don``history.back()`, no line-number assertions.
- **UX-spec precursor:** Not required for verification + hit-target widen.
Required IF scope drifts into inline error UI on `<PartsPanel>` (currently
bubbles `use-parts` failures to `<SchemaViewer>` skeleton — design-novel).
---
## Classification rationale
Both follow-ups satisfy the **Mechanical** criteria from memory
`recon-to-implementation-scoping-pattern`:
1. Playwright/E2E verification of an already-shipped, UX-reviewed fix.
2. Hit-target widening to a published platform baseline (44 px).
3. Locator-stability assertions that consume existing
`data-faro-user-action-name` + ARIA hooks — no new hook attributes
requested.
Neither task introduces new copy, color, layout primitives, or skeleton
dimensions. Anything that would (e.g. an inline error UI on PartsPanel for
`use-parts` failures) is explicitly carved out as out-of-scope and gated on a
separate FN-406-style UX-spec precursor.
## Rubric scoring (FN-395 P1)
Per memory `rubric-scoring-for-verification-follow-ups`: both tasks inherit
their parent's P1 gate rather than competing on the FN-395 shortlist. Scored
for visibility, not gated on the 6-point floor.
## Drift hardening
Acceptance criteria in both child tasks refer to selectors by
`data-faro-user-action-name`, ARIA role/name, or visible text — never by line
number. FN-400 → FN-403 already demonstrated the cost of line-number coupling
(`schema-viewer.tsx:69-83``:72-86` shift in 2 days). See memory
`manifest-drift-convention`.
---
## Non-goals (for this scoping task — FN-411)
- No implementation. FN-411 is scoping only.
- No baseline/PostHog work (that's FN-396's surface).
- No EMEX/PL24/PartsCatalogs fetch-layer work.

View File

@@ -527,6 +527,9 @@ export class CategoriesService {
lp.includes("/bomdetails") ||
lp.includes("/partinfo/") ||
/\/extern\/[^/]+\/(vin_items|mdl_items)\b/.test(lp) ||
// PSA / Hyundai / Opel / Volvo image-board pages and the Ford VIN
// vin-image-board.action equivalent. Drilling into them yields BOM rows,
// not sub-groups — let getCategoryWithParts handle those as parts.
lp.includes("image-board.action") ||
lp.includes("json-vin-bom-detail.action")
) {