|
|
@@ -1,5 +1,9 @@
|
|
|
# Backlog
|
|
|
|
|
|
+## Notes
|
|
|
+- First-time setup: `fastapi`/`uvicorn`/`starlette` are listed in `requirements.txt` but are not installed by default in a fresh `.venv` — run `pip install -r requirements.txt` before running the API.
|
|
|
+- `ComponentCategory.other` maps to an empty subcategory list in `suppliers/lcsc/categories.py:89` (`_SUBCATEGORY_NAMES[other] = []`) — rows classified as `other` can never resolve to an LCSC subcategory. Needs a taxonomy decision (which LCSC categories represent the catch-all), not a code fix.
|
|
|
+
|
|
|
## Done
|
|
|
|
|
|
### Ingestion Pipeline
|
|
|
@@ -12,6 +16,17 @@
|
|
|
- [x] `classification/param_extractor.py` — value parsing, description fallback, package extraction, AI fallback
|
|
|
- [x] `classification/package_patterns.json` — file-backed regex patterns + known_footprints dict
|
|
|
|
|
|
+### LCSC Category Resolution
|
|
|
+- [x] `suppliers/base.py` — abstract `SupplierAdapter(ABC)`, `search(category_id, params, filters=None, page=1) -> SearchResult`
|
|
|
+- [x] `suppliers/category_resolver.py` — generic AI category resolver, caches by `(category, package, value)`
|
|
|
+- [x] `suppliers/lcsc/category_resolver.py` — LCSC-specific wrapper over generic resolver
|
|
|
+- [x] `suppliers/lcsc/fetch_categories.py` + `suppliers/lcsc/categories.json` — scraped LCSC category tree, 600 subcategories committed
|
|
|
+- [x] `suppliers/lcsc/categories.py` — `load_categories()`, internal `ComponentCategory` → curated LCSC subcategory lists
|
|
|
+- [x] `suppliers/lcsc/enrich_categories.py` + `make_enrich_input.py` / `apply_enrich_output.py` — scrape example products + LLM one-line descriptions per subcategory, applied to all 600/600
|
|
|
+- [x] `suppliers/lcsc/category_cache.json` — file-backed resolution cache (69 entries)
|
|
|
+- [x] `suppliers/lcsc/product_lookup.py`, `scout_ground_truth.py`, `eval_ground_truth.py` — ground-truth harness (60 rows from real LCSC part numbers) + accuracy eval
|
|
|
+ - Current accuracy: **top-1 68% (41/60), top-3 88% (53/60)**
|
|
|
+
|
|
|
### Bug Fixes
|
|
|
- [x] Double-space header normalization (`_normalize_key` collapses whitespace) — fixed `Ref Des (Multi-4)` mismatch
|
|
|
- [x] `Comment` → `part_number` disambiguation — passive value sampling prevents `pn='100nF'`
|
|
|
@@ -27,16 +42,9 @@
|
|
|
- [ ] Strip `Elec_` prefix from package — store `"6.3x5.8"` not `"Elec_6.3x5.8"` (change capture group in `package_patterns.json`)
|
|
|
- [ ] Persian-header BOM support — AI column mapping for non-Latin headers (currently returns 0 rows)
|
|
|
|
|
|
-### LCSC Category Resolution
|
|
|
-- [ ] `suppliers/lcsc/fetch_categories.py` — one-time CLI to scrape LCSC category pages → `categories.json` (1.5s grace period between requests)
|
|
|
-- [ ] `suppliers/lcsc/categories.json` — committed static category tree (refresh quarterly)
|
|
|
-- [ ] `suppliers/lcsc/categories.py` — `load_categories()`, `get_subcategories_for(internal_cat)`
|
|
|
-- [ ] `suppliers/lcsc/category_resolver.py` — LLM (Claude Haiku) category inference + `category_cache.json` persistence
|
|
|
-- [ ] `suppliers/lcsc/category_cache.json` — file-backed cache (same pattern as `package_patterns.json`)
|
|
|
-
|
|
|
### LCSC Search Adapter
|
|
|
-- [ ] `suppliers/base.py` — abstract `SupplierAdapter(api_token=None)` with `search(category_id, params, page)` interface
|
|
|
-- [ ] `suppliers/lcsc/lcsc.py` — scraper mode: CSRF session + POST to `lcsc.com/api/products/search`; token mode stub for official API
|
|
|
+- [x] `suppliers/lcsc/lcsc.py` — scraper mode: CSRF session + POST to `lcsc.com/api/products/search`
|
|
|
+- [ ] `suppliers/lcsc/lcsc.py` — official API mode (`_search_official`) still a stub, raises `NotImplementedError`; needs HMAC signing + LCSC API key
|
|
|
|
|
|
### Scouting Loop
|
|
|
- [ ] Scouting orchestrator — drive pending rows through scouting → filtering → confirmed
|
|
|
@@ -48,10 +56,10 @@
|
|
|
- [ ] `POST /upload` — ingest file, return BomSession
|
|
|
- [ ] `GET /session/{id}` — return session state
|
|
|
- [ ] `GET /session/{id}/row/{row_id}/scout` — LLM category inference, return `{subcategory, alternatives[]}`
|
|
|
-- [ ] `POST /session/{id}/row/{row_id}/confirm-category` — lock LCSC subcategory, advance state to filtering
|
|
|
-- [ ] `POST /session/{id}/row/{row_id}/search` — search within confirmed category + param filters
|
|
|
-- [ ] `POST /session/{id}/row/{row_id}/confirm` — lock part pick, advance state to confirmed
|
|
|
-- [ ] `GET /session/{id}/export` — collate confirmed picks → downloadable BOM
|
|
|
+- [ ] `POST /session/{id}/row/{row_id}/confirm-category` — lock LCSC subcategory, advance state to filtering — **deferred** until category inference is validated interactively (only inference itself has been tested so far, not the full loop)
|
|
|
+- [ ] `POST /session/{id}/row/{row_id}/search` — search within confirmed category + param filters — **deferred**, same reason
|
|
|
+- [ ] `POST /session/{id}/row/{row_id}/confirm` — lock part pick, advance state to confirmed — **deferred**, same reason
|
|
|
+- [ ] `GET /session/{id}/export` — collate confirmed picks → downloadable BOM — **deferred**, same reason
|
|
|
|
|
|
### Future: Other Suppliers
|
|
|
- [ ] DigiKey adapter
|
|
|
@@ -59,7 +67,8 @@
|
|
|
- [ ] Nexar adapter
|
|
|
|
|
|
### Frontend
|
|
|
-- [ ] React scaffold + build setup
|
|
|
+- [ ] HTMX-based test page (server-rendered by FastAPI, no separate frontend process) for interactively testing category inference — backbone, in progress
|
|
|
+- [ ] React scaffold + build setup — deferred until the scouting loop is validated; HTMX test page covers interim needs
|
|
|
- [ ] Upload page
|
|
|
- [ ] Row-by-row scouting UI (category dropdown, results grid, confirm/reject)
|
|
|
- [ ] Session progress view (rows confirmed vs pending)
|