Недостижимые от index.js -> App компоненты (23 файла):
- MobileForm.jsx/.tsx/.css (живая мобильная форма = CaseForm)
- BehavioralProfile.tsx/.css
- AnalysisLayout/, MapView/, ResultPanel/ (MapView/ResultPanel
импортировались только из неиспользуемого AnalysisLayout; живая
карта = SearchMap.jsx)
- admin/ (CaseDetail, CasesList, HeatmapView, Statistics) - AdminDashboard
использует inline-UI, не эти компоненты
- CaseForm/Step5Resources.jsx - не подключён в CaseForm.jsx
Сборка проходит. Мёртвый код с его багами (isPsycotypeSelected опечатка,
хардкод URL, NaN-гварды) уходит вместе с файлами.
Co-Authored-By: Claude <noreply@anthropic.com>
- api/client.js: apiFetch подставляет Bearer-токен, выставляет
Content-Type: application/json для не-FormData тел, ловит 401 -> событие
- context/AuthContext: валидация токена через /auth/me, loading-гейт,
logout(), подписка на 401
- components/ProtectedRoute: guard с ролями и заглушкой на время проверки
- pages/Login: форма входа (OAuth2 form-urlencoded), редирект на from
- App.js: AuthProvider, /login, ProtectedRoute на /sar /desktop
/analysis /admin (admin -> roles=[admin]) /mobile
- AdminDashboard/CaseForm/AnalysisResult: переход на apiFetch
- AdminDashboard: кнопка "Выйти" в шапке (useAuth().logout)
Co-Authored-By: Claude <noreply@anthropic.com>
Both are Section B (needs-context): B11 touches the AnalysisResult
contract and the question of where an LLM is needed at all; B12 touches
scoring coefficients and the DB schema, which project rules keep off
limits to automated edits.
B11 records the key finding that the LLM does not compute priorities --
the math already lives in geo_service/scoring_service/psychotype_service
and analyze_with_fallback already returns a full AnalysisResult with no
API. The only unique in-hot-path LLM role is parsing free-text reports,
so a strict intake form and a local provider are independent levers.
B12 notes ISRID supplies empirical priors for the currently hand-tuned
zone weights, with the legal status of the database flagged as a
blocking question to resolve before any data enters the repo.
Summary table updated to B1-B12.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Revert of A9 address change. The .108 value was inferred from the
container VMID (108), not from its actual network config: net0 is
ip=dhcp and the container currently holds 192.168.0.99. Requests to
.108 fail with "No route to host", making the UI look down while all
four compose services are healthy.
A9 section in vector_tasks.md is kept as history and flagged stale so
the .99 -> .108 replacement is not repeated.
Note: the address is DHCP-assigned and may change again; a static IP
would be needed to make these docs durable. Hardcoded .99 URLs remain
in MobileForm.jsx:49 and HeatmapView.jsx:73 (tracked in vector_tasks.md,
untouched here).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B7: stop AdminDashboard refetching the case list on selection change
selectedCaseId was both read and written inside the list-loading effect and
listed in its deps, causing a second fetch on first render and after every
filter reset. Auto-select now uses a functional state update, so the effect
no longer depends on selectedCaseId; editForm stays in sync via the existing
selectedCase effect.
_extract_json_payload handles a json/JSON/bare fence, raw JSON and JSON
embedded in prose; any unparseable response or contract violation now
degrades to the deterministic scoring_service instead of raising.
Also guards the response envelope itself (content[0].text).
B3: single home for recommendation scoring
services/recommendation_service.py holds the rules; routers/stats.py and
backend/services/stats_service.py both delegate to it. Unified rules are the
union of the two old copies: same weights/threshold, substring matching
(superset of the old exact match), tolerant key aliases, health_flags rule
kept. Endpoint response contract unchanged.
Plus: Overpass circuit breaker and concurrent zone queries in geo_service -
128 sequential calls per analysis no longer each burn a connect timeout when
the host has no outbound network.
Tests: 152 -> 194 passed.
backend/routers/analyze.py imports services.* (root package), not
backend.services.* - so the earlier A1/A2/A3 edits landed in an unused
duplicate. Also COPY/mount services/ so the container can start at all
(ModuleNotFoundError: No module named services).