Session 7e: Grade adapter, normalize consolidation, ARCH-2 banners

This commit is contained in:
Kev
2026-06-10 03:37:07 -04:00
parent 6f4a353de9
commit 012c0ef47e
11 changed files with 571 additions and 60 deletions
+48 -20
View File
@@ -411,24 +411,50 @@ No circular imports detected.
### ARCH — Architecture
- **[ARCH-1] Dual grading paths.** Severity: Medium. Status:
**DEFERRED in Session 7d**the legacy `propAnalyzer → grader →
UnifiedOddsProvider` chain returns a 4-letter grade + 0-100
confidence + kill-conditions + reasoning.steps shape; the new
`engine1` returns an 11-step grade + 0-1 confidence + factors. Both
shapes are consumed by different surfaces (GradeCard + DemoScan vs
the orchestrator's grade_history writer). Unification requires
frontend + backend coordination — out of scope for the audit-fix
session. Migration plan: (1) decide which shape the UI keeps; (2)
write an adapter from the other shape; (3) rewire one route at a
time, starting with `/api/analyze/prop`. Session 7d added a
DEPRECATED banner to `src/services/grader.js` to signal that new
features should land in engine1.js.
**PARTIAL in Session 7e**Step 1 of the migration (the adapter)
is complete and tested. Steps 2-6 deferred per ESCAPE HATCH.
Step 1 ✓ — `src/utils/gradeAdapter.js` translates engine1 output
into the legacy shape `DemoScan` reads. 26 unit
tests covering grade collapse, confidence math,
kill-condition mapping, reasoning fallback, partial
input safety.
Step 2-6 deferred — legacy `analyzeProp` and `engine1.gradeProp()`
have incompatible INPUT contracts: the legacy
analyzer takes a raw prop and self-fetches data
(odds, stats, opponent, spread, kill conditions);
engine1 takes a pre-computed feature vector and is
a pure grading function. To rewire any route to
engine1 we'd first need to extract an
orchestrator-lite preprocessor — that's the kind
of architectural change 7c/7d's no-restructure
rule blocks. The reasoning.summary string-level
parity is also currently lost (concrete numbers
in legacy vs abstract factor labels in engine1).
Migration roadmap (now actionable for the next session):
(a) Extract `gradingOrchestrator.gradeProp()` into a standalone
`computeFeaturesForProp({player, stat_type, line, direction})`
that lifts the player-roster + feature-fetch + trap-detect +
consistency-score logic into a reusable callable.
(b) Wrap engine1 + gradeAdapter behind a thin
`analyzeViaEngine1(prop)` helper.
(c) Rewire one route at a time — `/api/analyze/prop` first
(lowest risk: single prop, public, well-tested), then
`/api/analyze/batch`, then `/api/scan/parlay`, then
`/api/bets/*`.
(d) Remove `grader.js` + `propAnalyzer.js` + the legacy book
adapters only after every consumer has migrated and a soak
period.
Session 7d's DEPRECATED banner on `src/services/grader.js` stays
put.
- **[ARCH-2] Two circuit-breaker / rate-limiter modules.** Severity:
Low (documented in 6a). `src/services/{circuitBreaker.js,
rateLimiter.js}` (keyed registry, legacy) coexist with
`src/utils/rateLimiter.js` (factory, new). Consolidation is purely
cosmetic — both work. Scope: half-session. Status: open.
Low. Status: **DOCUMENTED in Session 7e.** Both legacy modules now
carry banners listing their three callers:
- `src/services/UnifiedOddsProvider.js`
- `src/services/adapters/ESPNAdapter.js`
- `src/services/adapters/PinnacleAdapter.js`
Full removal blocks on ARCH-1 Step 6 — the legacy book adapters
retire together with the legacy grading path.
### SEC — Security
@@ -466,10 +492,12 @@ No circular imports detected.
### DUP — Duplicates
- **[DUP-1] `normalizeName()` exists twice.** Severity: Low. Status:
**DOCUMENTED in Session 7d.** Both implementations now carry
cross-reference comments explaining the divergence (script keeps
digits for legacy roster fields; trap detector strips them). Full
consolidation deferred until the script can drop its digit support.
**FIXED in Session 7e.** Consolidated into `src/utils/normalize.js`
with a `keepDigits` option (default false). `trapDetection.js`
imports the default; `scripts/populate-player-ids.js` wraps with
`keepDigits: true` via `normalizeRosterName`. 9 unit tests cover
accent strip, suffix removal, digit options, idempotency, null
input.
- **[DUP-2] `oddsToImplied` etc. only live in `src/utils/odds.js`.**
Confirmed not duplicated despite the `oddsNormalizer.js` neighbor —