# VERDICT ALIGNMENT PLAN Plan complet de aliniere PG ↔ Redis ↔ Cod pentru tot sistemul de verdict. **Regula de aur**: PG = source of truth. Redis = cache rapid. Cod = zero hardcodari (doar defaults de fallback). **Flow**: Admin Dashboard → CRUD PG (didiFramework) → Sync Redis → agent-v3 citeste din Redis. --- ## 1. INVENTAR ACTUAL — UNDE E FIECARE PARAMETRU ### VERDE — Aliniat PG ↔ Redis ↔ UI (functioneaza corect) | # | Parametru | PG tabel | Redis cheie | UI | agent-v3 citeste din | |---|---|---|---|---|---| | 1 | Verdict categories (ranges, culori) | `verdict_category` | `didi:framework:verdicts` | FrameworkDashboard | Redis | | 2 | Risk mappings (ranges) | `risk_mapping` | `didi:framework:verdicts` | FrameworkDashboard | Redis | | 3 | Severity (ranges + actiuni) | `severity_assessment` | `didi:framework:verdicts` | FrameworkDashboard | Redis | | 4 | Component weights (35/25/20/10/10) | `component_weight` | `didi:framework:weights` | FrameworkDashboard | Redis | | 5 | Weight scenarios | `weight_scenario` | `didi:framework:weights` | FrameworkDashboard | Redis | | 6 | Topic multipliers | `multiplier` | `didi:framework:weights` | FrameworkDashboard | Redis | | 7 | Claim statuses (VT, LT, UV...) | `claim` | `didi:framework:claims` | FrameworkDashboard | Redis | | 8 | Claim types (VF, SC, QA...) | `claim_type` | `didi:framework:claims` | FrameworkDashboard | Redis | | 9 | Claim confidence levels | `confidence` | `didi:framework:claims` | FrameworkDashboard | Redis | | 10 | Claim interpretations | `interpretation` | `didi:framework:claims` | FrameworkDashboard | Redis | | 11 | LLM stage assignments | `component_stage_assignment` | `didi:config:*:stage_assignments` | LLMComponentsConfig | Redis | | 12 | LLM prompts | `component_prompt` | `didi:config:*:prompts:*` | LLMComponentsConfig | Redis | | 13 | LLM available models | derivat din assignments | `didi:config:*:available_models` | LLMComponentsConfig | Redis | | 14 | Platforms (social media) | `platform` | `didi:framework:sources` | FrameworkDashboard | Redis | | 15 | Source credibility params | `source_credibility` + altele | `didi:framework:sources` | FrameworkDashboard | Redis | | 16 | Techniques hierarchy | `dimension/subdimension/technique/indicator` | `didi:framework:techniques` | FrameworkDashboard | Redis | **Total: 16 parametri complet aliniati.** Functionale, cu UI, cu sync. --- ### GALBEN — Exista in Redis dar NU in PG (puse manual, fara persistenta) Mecanismul `component_config` (tabel PG) → `didi:config:*` (Redis) exista in sync-redis.ts (linia 576-583). Dar nimeni nu a inserat randurile in PG. Cheile au fost puse direct in Redis manual. | # | Redis cheie | Continut (rezumat) | In PG? | In UI? | Risc | |---|---|---|---|---|---| | 17 | `didi:config:techniques:v3:scoring_config` | countBonus, dimensionBonus, intensityBonus, manipulation_levels, warning_flags | **NU** | **NU** | Se pierde daca Redis se sterge | | 18 | `didi:config:techniques:v3:coupling_registry` | Coupling config | **NU** | **NU** | | | 19 | `didi:config:techniques:v3:schemas:*` (3 chei) | Zod schemas export | **NU** | **NU** | | | 20 | `didi:config:techniques:v3:dimensions_compact` | Dimensiuni compacte pt screening | **NU** | **NU** | Derivabil din techniques hierarchy | | 21 | `didi:config:ai-tampered:v1:scoring_config` | thresholds (70/50/30), disclosure_impact (0.3/0.5/0.7/1.0), category_weights, confidence_levels | **NU** | **NU** | Se pierde | | 22 | `didi:config:ai-tampered:v1:categories_compact` | Categorii AI compacte pt screening | **NU** | **NU** | | | 23 | `didi:config:ai-tampered:v1:indicators_hierarchy` | Categorii + indicatori AI | **NU** | **NU** | | | 24 | `didi:config:ai-tampered:v1:quick_patterns` | Hedging patterns (regex) | **NU** | **NU** | | | 25 | `didi:config:ai-tampered:v1:coupling_registry` | Coupling config AI | **NU** | **NU** | | | 26 | `didi:config:ai-tampered:v1:schemas:*` (3 chei) | Zod schemas AI | **NU** | **NU** | | | 27 | `didi:config:ai-tampered:v1:vision_models` | Cascade viziune (Qwen→Gemini→GPT-4o) | **NU** | **NU** | | | 28 | `didi:config:claims:v1:scoring_config` | status_thresholds, claim_type_weights, source_reliability_weights | **NU** | **NU** | Se pierde | | 29 | `didi:config:pipeline:v1:verdict_config` | synergy, overrides, confidence, confidence_levels | **NU** | **NU** | Se pierde — CRITIC | | 30 | `didi:config:pipeline:v1:component_config` | Components enabled/disabled, applies_to, timeouts | **NU** | **NU** | Se pierde | | 31 | `didi:config:pipeline:v1:session_config` | Session config | **NU** | **NU** | | | 32 | `didi:config:pipeline:v1:external_apis` | API URLs externe | **NU** | **NU** | | | 33 | `didi:config:pipeline:v1:prompts:verdict_explanation` | Prompt verdict reviewer | **NU** | **NU** | | | 34 | `didi:config:vision:v1:prompts:extraction` | Prompt Vision OCR | **NU** | **NU** | | | 35 | `didi:config:vision:v1:prompts:video_frames` | Prompt Vision video frames | **NU** | **NU** | | | 36 | `didi:config:vision:v1:prompts:ai_detection` | Prompt Vision AI detection | **NU** | **NU** | | | 37 | `didi:config:verdict:v1:available_models` | Modele LLM verdict reviewer | **NU** | **NU** | | | 38 | `didi:config:source-assessment:v1:available_models` | Modele LLM source assessment | **NU** | **NU** | | **Total: 22 parametri (unele cu sub-chei) in Redis fara PG. RISC: se pierd la orice Redis flush/restart fara persistenta.** --- ### ROSU — Hardcodat DOAR in cod (nici PG, nici Redis) | # | Parametru | Fisier | Valoare actuala | Ar trebui in | |---|---|---|---|---| | 39 | Count scaler divisor | `techniques/executor.ts:614` | `3` (1 tech=33%) | `techniques.scoring_config` | | 40 | Severe technique threshold | `techniques/executor.ts:686` | `severity >= 8` | `techniques.scoring_config` | | 41 | Intensity bonus formula | `techniques/executor.ts:635` | `min(0.15, sqrt(x-1)*0.05)` | `techniques.scoring_config` (codul sa citeasca parametrii, nu formula string) | | 42 | AI blend screening/deep | `ai-tampered/executor.ts:705` | `0.6 / 0.4` | `ai-tampered.scoring_config` | | 43 | AI undisclosed threshold | `ai-tampered/executor.ts:725` | `>= 50` | `ai-tampered.scoring_config` | | 44 | AI disclosure rating vals | `ai-tampered/executor.ts:792-798` | `80/40/25/+15/+5` | Inlocuit de `disclosure_impact` din Redis #21 | | 45 | AI quick analyze scores | `ai-tampered/executor.ts:378-410` | `+10/+30/+15/+40/+25` | `ai-tampered.scoring_config.quick_scores` | | 46 | Source axis weights | `source-assessment/executor.ts:110-113` | `0.35/0.25/0.25/0.15` | `source-assessment.scoring_config` (NOU) | | 47 | Source verdict thresholds | `source-assessment/executor.ts:296-299` | `70/50/30` | `source-assessment.scoring_config` (NOU) | | 48 | Video track weights | `component-worker.ts` | `0.40/0.60` | `pipeline.component_config` | | 49 | Video min text chars | `component-worker.ts` | `200` | `pipeline.component_config` | | 50 | Claims status weights | `claims/executor.ts:681-688` | `VT=1.0,LT=0.75,UV=0.5,...` | `claims.scoring_config.status_weights` (exista partial in Redis dar codul NU citeste) | | 51 | Claims "all UV = 75%" | `claims/executor.ts:673` | `0.75` | `claims.scoring_config.all_unverified_credibility` | | 52 | Input profiles per type | NICAIERI | nu exista | `pipeline.input_profiles` (NOU) | | 53 | INCONCLUSIVE rules | `verdict-calculator.ts:321-337` | 3 if-uri | `pipeline.input_profiles` (NOU) | | 54 | Context = -1 always | `verdict-calculator.ts:448` | `-1` | ELIMINAT din formula | **Total: 16 parametri hardcodati in cod.** --- ### DIVERGENTE — Acelasi parametru cu valori diferite in Redis vs Cod | # | Parametru | In Redis | In Cod | Codul citeste din | |---|---|---|---|---| | D1 | Claims status weights | Redis: `claim_type_weights: {EF:0.95, VF:0.85...}` (tip → weight) | Cod: `{VT:1.0, LT:0.75, UV:0.5...}` (status → weight) | **COD** — sunt concepte DIFERITE, nu duplicate | | D2 | Intensity bonus | Redis: `formula: "(avg_intensity - 1) * 0.05"` (string, neexecutat) | Cod: `min(0.15, sqrt(x-1)*0.05)` (formula diferita!) | **COD** — Redis are formula veche, codul are noua | | D3 | Override false_claims | Redis: `per_claim:5, max:20, threshold:3` | Cod DEFAULT: `per_claim:15, max:40, threshold:1` | **REDIS** (codul citeste din Redis, defaults doar fallback) | | D4 | Disclosure impact | Redis: `explicit:0.3, partial:0.5, implied:0.7` | Cod: doar `undisclosed_ai: +15` override | **REDIS** pt disclosure_impact, **COD** pt override bonus | **D3 e important**: Redis are `false_claims.per_claim=5` si `max=20`, dar codul DEFAULT are `per_claim=15` si `max=40`. Daca Redis e disponibil → se folosesc valorile mici din Redis. Daca Redis e indisponibil → fallback la valorile mari din cod. Comportament inconsistent. --- ## 2. PLAN DE ALINIERE — FAZE DE IMPLEMENTARE ### FAZA 0: Backup + Inventar (1 ora) ``` 0.1 Export TOATE cheile Redis didi:config:* si didi:framework:* in JSON local → redis-cli --scan --pattern 'didi:*' | while read key; do echo "$key"; redis-cli -a redis123 GET "$key"; done > redis_backup.json 0.2 Verifica ca PG e accesibil si tabelele bos_parammgmt exista → psql → \dt bos_parammgmt.* 0.3 Lista randuri existente in component_config → SELECT * FROM bos_parammgmt.component_config ORDER BY component_code; ``` --- ### FAZA 1: Redis → PG (persistenta, fara schimbari de comportament) **Scop**: Tot ce e in Redis dar nu in PG → inserat in `component_config`. **Impact**: Zero — agent-v3 citeste tot din Redis, sync-redis le va rescrie identic. **Risc**: Zero — doar adaugam randuri in PG. ``` 1.1 Script SQL: INSERT INTO component_config pentru fiecare cheie Redis din sectiunea GALBEN - Citeste din Redis, formateaza ca INSERT - 22 INSERT-uri (unele cu JSONB mare) 1.2 Testeaza: POST /api/sync-redis → verifica ca Redis e identic dupa sync - Compara output sync cu backup-ul de la 0.1 1.3 Randuri noi in component_config: | component_code | config_key | sursa | |---|---|---| | techniques | scoring_config | din Redis didi:config:techniques:v3:scoring_config | | techniques | coupling_registry | din Redis | | techniques | schemas_screening | din Redis | | techniques | schemas_deep_per_dimension | din Redis | | techniques | schemas_complete | din Redis | | ai-tampered | scoring_config | din Redis | | ai-tampered | categories_compact | din Redis | | ai-tampered | indicators_hierarchy | din Redis | | ai-tampered | quick_patterns | din Redis | | ai-tampered | coupling_registry | din Redis | | ai-tampered | schemas_screening | din Redis | | ai-tampered | schemas_deep_per_category | din Redis | | ai-tampered | schemas_complete | din Redis | | ai-tampered | vision_models | din Redis | | claims | scoring_config | din Redis | | pipeline | verdict_config | din Redis | | pipeline | component_config | din Redis | | pipeline | session_config | din Redis | | pipeline | external_apis | din Redis | | vision | prompts_extraction | din Redis (sau in component_prompt) | | vision | prompts_video_frames | din Redis | | vision | prompts_ai_detection | din Redis | Nota: Prompturile vision pot merge in component_prompt (component_code='vision', stage_code='extraction/video_frames/ai_detection') Nota: verdict_explanation prompt merge in component_prompt (component_code='verdict', stage_code='explanation') Nota: source-assessment available_models si verdict available_models merg in component_stage_assignment ``` --- ### FAZA 2: Cod → Redis+PG (externalizare hardcodari) **Scop**: Toate hardcodarile din sectiunea ROSU → adaugate in scoring_config (PG+Redis). **Impact**: Zero daca valorile sunt identice cu ce era hardcodat. **Risc**: Minim — codul citeste din Redis cu fallback la exact aceleasi valori. ``` 2.1 Extinde techniques scoring_config in PG cu: { "count_scaler_divisor": 3, "severe_threshold": 8, "intensity_bonus_cap": 0.15, "intensity_bonus_coefficient": 0.05, "intensity_bonus_type": "sqrt" // sqrt | linear } Modifica techniques/executor.ts: - Citeste count_scaler_divisor din scoringConfig (linia 614) - Citeste severe_threshold din scoringConfig (linia 686) - Citeste intensity params din scoringConfig (linia 635) - Fallback la valorile actuale daca Redis e gol 2.2 Extinde ai-tampered scoring_config in PG cu: { "blend_weights": { "screening": 0.6, "deep": 0.4 }, "undisclosed_threshold": 50, "quick_scores": { "hedging": 10, "self_reference": 30, "tool_mention": 15, "explicit_disclosure": 40, "partial_disclosure": 25 } } Modifica ai-tampered/executor.ts: - Citeste blend_weights din scoringConfig (linia 705) - Citeste undisclosed_threshold din scoringConfig (linia 725) - Citeste quick_scores din scoringConfig (liniile 378-410) 2.3 Extinde claims scoring_config in PG cu: { "status_weights": { "VT": 1.0, "LT": 0.75, "UV": 0.5, "OP": 0.3, "LF": 0.25, "VF": 0.0 }, "all_unverified_credibility": 0.75, "all_unverified_behavior": "fixed" // fixed | calculate_per_type } Modifica claims/executor.ts: - Citeste status_weights din scoringConfig (linia 681) - Citeste all_unverified din scoringConfig (linia 670-676) 2.4 Adauga source-assessment scoring_config (NOU) in PG: { "axis_weights": { "publication": 0.35, "domain": 0.25, "author": 0.25, "platform": 0.15 }, "verdict_thresholds": { "TRUSTED": 70, "NEUTRAL": 50, "SUSPICIOUS": 30 }, "domain_unavailable_default": 50 } Modifica source-assessment/executor.ts: - Citeste axis_weights din Redis (liniile 110-113) - Citeste verdict_thresholds din Redis (liniile 296-299) 2.5 Extinde pipeline component_config in PG cu: { "video_track_weights": { "text": 0.40, "visual": 0.60 }, "video_min_text_chars": 200 } Modifica component-worker.ts: - Citeste video_track_weights din Redis - Citeste video_min_text_chars din Redis 2.6 POST /api/sync-redis → toate valorile noi apar in Redis 2.7 Testeaza: ruleaza aceeasi analiza, scoruri identice (valorile sunt identice) ``` --- ### FAZA 3: Fix divergente + aliniere defaults **Scop**: Rezolva cele 4 divergente (D1-D4). Defaults in cod = identice cu Redis. **Impact**: Mic — doar aliniaza valorile. ``` 3.1 D2 (intensity formula): Actualizeaza Redis scoring_config cu formula noua: "intensity_bonus_type": "sqrt", "intensity_bonus_cap": 0.15, "intensity_bonus_coefficient": 0.05 (sterge string-ul vechi "formula": "(avg_intensity - 1) * 0.05") 3.2 D3 (override false_claims): Decide valori canonice: Propunere: per_claim=15, max=40, threshold=1 (valorile din cod, nu din Redis) → Actualizeaza Redis verdict_config.overrides.false_claims → Actualizeaza DEFAULT_VERDICT_CONFIG in verdict-calculator.ts sa fie identic 3.3 D4 (disclosure): disclosure_impact RAMINE in Redis (codul deja citeste de acolo) Override undisclosed_ai RAMINE in verdict_config Nu e divergenta — sunt mecanisme complementare 3.4 Actualizeaza TOATE DEFAULT_* in verdict-calculator.ts sa fie identice cu Redis: - DEFAULT_VERDICTS ← sync cu PG verdict_category - DEFAULT_WEIGHTS ← sync cu PG component_weight - DEFAULT_VERDICT_CONFIG ← sync cu Redis verdict_config ``` --- ### FAZA 4: Tabele PG noi + migratie **Scop**: Adauga structuri PG noi pentru input profiles si claims weights. ``` 4.1 Migration SQL: -- Input type profiles CREATE TABLE bos_parammgmt.input_type_profile ( profile_id SERIAL PRIMARY KEY, profile_code VARCHAR(30) UNIQUE NOT NULL, profile_name VARCHAR(100) NOT NULL, description TEXT, weight_techniques INTEGER NOT NULL DEFAULT 25, weight_claims INTEGER NOT NULL DEFAULT 25, weight_ai_tampered INTEGER NOT NULL DEFAULT 25, weight_source INTEGER NOT NULL DEFAULT 25, role_techniques VARCHAR(20) DEFAULT 'secondary', role_claims VARCHAR(20) DEFAULT 'secondary', role_ai_tampered VARCHAR(20) DEFAULT 'secondary', role_source VARCHAR(20) DEFAULT 'secondary', min_components INTEGER DEFAULT 2, primary_components TEXT[] DEFAULT '{}', required_any TEXT[] DEFAULT '{}', missing_techniques VARCHAR(30) DEFAULT 'redistribute', missing_claims VARCHAR(30) DEFAULT 'redistribute', missing_ai_tampered VARCHAR(30) DEFAULT 'redistribute', missing_source VARCHAR(30) DEFAULT 'redistribute', confidence_config JSONB DEFAULT '{}', ai_disclosure_multipliers JSONB DEFAULT '{"explicit":0.15,"partial":0.4,"implied":0.6,"none":1.0}', is_active BOOLEAN DEFAULT true, parameter_id INTEGER REFERENCES bos_parammgmt.parameter(parameter_id) ); -- Override rules per profile CREATE TABLE bos_parammgmt.profile_override_config ( override_id SERIAL PRIMARY KEY, profile_code VARCHAR(30) REFERENCES bos_parammgmt.input_type_profile(profile_code), override_code VARCHAR(40) NOT NULL, enabled BOOLEAN DEFAULT true, threshold INTEGER, bonus_per_unit INTEGER, bonus_fixed INTEGER, max_bonus INTEGER, description TEXT, UNIQUE(profile_code, override_code) ); -- Override cap per profile (in input_type_profile) ALTER TABLE bos_parammgmt.input_type_profile ADD COLUMN override_cap INTEGER DEFAULT 50; -- Unverified weight per claim type ALTER TABLE bos_parammgmt.claim_type ADD COLUMN unverified_weight NUMERIC(3,2) DEFAULT 0.50; -- Credibility weight per claim status ALTER TABLE bos_parammgmt.claim ADD COLUMN credibility_weight NUMERIC(3,2) DEFAULT 0.50; 4.2 Seed data — 6 profiluri: INSERT INTO input_type_profile (profile_code, profile_name, weight_techniques, weight_claims, weight_ai_tampered, weight_source, role_techniques, role_claims, role_ai_tampered, role_source, primary_components, required_any, min_components) VALUES ('text_no_url', 'Text simplu', 35, 35, 15, 15, 'primary', 'primary', 'secondary', 'secondary', '{techniques,claims}', '{techniques,claims}', 2), ('text_with_url', 'Text cu URL', 25, 25, 15, 35, 'secondary', 'secondary', 'secondary', 'primary', '{source}', '{techniques,claims,source}', 2), ('image', 'Imagine', 20, 15, 50, 15, 'secondary', 'secondary', 'primary', 'secondary', '{ai_tampered}', '{ai_tampered}', 1), ('audio', 'Audio', 35, 30, 20, 15, 'primary', 'secondary', 'secondary', 'secondary', '{techniques}', '{techniques}', 1), ('video', 'Video', 25, 20, 40, 15, 'secondary', 'secondary', 'primary', 'secondary', '{ai_tampered}', '{ai_tampered}', 1), ('url', 'URL articol', 25, 25, 15, 35, 'secondary', 'secondary', 'secondary', 'primary', '{source}', '{techniques,claims,source}', 2); 4.3 Seed data — 48 override rules (8 × 6 profiluri): (vezi VERDICT_UI_SPEC.md Tab 2 pentru valorile per profil) 4.4 Seed data — claim_type unverified_weight: UPDATE claim_type SET unverified_weight = 0.25 WHERE claim_code IN ('VF', 'SC'); UPDATE claim_type SET unverified_weight = 0.30 WHERE claim_code = 'QA'; UPDATE claim_type SET unverified_weight = 0.35 WHERE claim_code = 'EF'; UPDATE claim_type SET unverified_weight = 0.40 WHERE claim_code IN ('CC', 'RE'); -- PC, OP, VC raman 0.50 (default) 4.5 Seed data — claim status credibility_weight: UPDATE claim SET credibility_weight = 1.00 WHERE claim_code = 'VT'; UPDATE claim SET credibility_weight = 0.75 WHERE claim_code = 'LT'; UPDATE claim SET credibility_weight = 0.50 WHERE claim_code = 'UV'; UPDATE claim SET credibility_weight = 0.30 WHERE claim_code = 'OP'; UPDATE claim SET credibility_weight = 0.25 WHERE claim_code = 'LF'; UPDATE claim SET credibility_weight = 0.00 WHERE claim_code = 'VF'; -- NV exclus din calcul (ramane NULL sau 0) ``` --- ### FAZA 5: CRUD didiFramework (backend endpoints) **Scop**: API-uri CRUD pentru noile tabele + extindere sync-redis. ``` 5.1 Fisier nou: routes/input-profiles.ts GET /api/input-profiles → lista toate profilurile GET /api/input-profiles/:code → un profil cu override-uri PUT /api/input-profiles/:code → update profil (ponderi, reguli) GET /api/input-profiles/:code/overrides → override-uri per profil PUT /api/input-profiles/:code/overrides → update override-uri Nota: NU avem POST/DELETE — cele 6 profiluri sunt fixe, nu se adauga/sterg. 5.2 Fisier nou: routes/scoring-configs.ts (sau extinde providers.ts) GET /api/scoring-configs → lista toate scoring_config per component GET /api/scoring-configs/:component → scoring_config pentru o componenta PUT /api/scoring-configs/:component → update scoring_config GET /api/scoring-configs/disclosure-multipliers → multiplicatori disclosure PUT /api/scoring-configs/disclosure-multipliers → update multiplicatori Nota: Astea sunt wrapper-e peste component_config CRUD existent. 5.3 Extinde routes/claims.ts (deja exista): - GET /api/claims/types → include unverified_weight in raspuns - PUT /api/claims/types/:id → accepta unverified_weight - GET /api/claims/status → include credibility_weight in raspuns - PUT /api/claims/status/:id → accepta credibility_weight 5.4 Extinde routes/sync-redis.ts: - fetchInputProfiles() → citeste din input_type_profile + profile_override_config - Scrie la didi:config:pipeline:v1:input_profiles - fetchClaimsExtended() → include unverified_weight si credibility_weight - Include in didi:framework:claims sync 5.5 Extinde routes/sync-redis.ts: - fetchScoringConfigs() → citeste din component_config pentru source-assessment - Scrie la didi:config:source-assessment:v1:scoring_config (NOU) ``` --- ### FAZA 6: Agent-v3 — verdict-calculator citeste profiles **Scop**: verdict-calculator foloseste input profiles din Redis. ``` 6.1 VerdictCalculator.loadFramework() extins: - Citeste didi:config:pipeline:v1:input_profiles din Redis - Fallback la DEFAULT_PROFILES (identice cu seed data din Faza 4) 6.2 VerdictCalculator.calculate() primeste input_type: - Selecteaza profil pe baza input_type + has_url - Foloseste ponderi din profil (nu din didi:framework:weights global) - Aplica override-uri din profil (nu DEFAULT_VERDICT_CONFIG global) - Aplica INCONCLUSIVE rules din profil 6.3 Component weights globale (didi:framework:weights.components) devin FALLBACK: - Daca input_profiles nu exista in Redis → foloseste weights globale (backward compat) - Daca input_profiles exista → ignora weights globale 6.4 Source Assessment override-uri: - applyOverrides() primeste source_assessment in loc de domain - Citeste verdict, is_blacklisted, red_flags din source_assessment 6.5 Claims scoring: - claims/executor.ts citeste status_weights din Redis (in loc de hardcodat) - claims/executor.ts citeste unverified_weight per tip din Redis (via claims framework data) ``` --- ### FAZA 7: Admin Dashboard — UI verdict config **Scop**: Interfata pentru editarea tuturor parametrilor. ``` 7.1 Pagina noua: /admin/verdict-config - Sau sub-pagina in LLM Components Config (depinde de layout) 7.2 Tab 1: Input Profiles (vezi VERDICT_UI_SPEC.md) - Consuma: GET /api/input-profiles - Editeaza: PUT /api/input-profiles/:code - Slidere ponderi cu validare total=100 7.3 Tab 2: Override Rules (vezi VERDICT_UI_SPEC.md) - Consuma: GET /api/input-profiles/:code/overrides - Editeaza: PUT /api/input-profiles/:code/overrides 7.4 Tab 3: AI Disclosure - Consuma: GET /api/scoring-configs/disclosure-multipliers - Editeaza: PUT /api/scoring-configs/disclosure-multipliers 7.5 Tab 4: Claims Weights - Consuma: GET /api/claims/types (cu unverified_weight) + GET /api/claims/status (cu credibility_weight) - Editeaza: PUT existente 7.6 Tab 5-6: Verdict Categories + Risk/Severity - Muta componentele existente din FrameworkDashboard (sau link catre) 7.7 Tab 7: Confidence Config - Consuma: din input profile confidence_config JSONB - Editeaza: ca parte din PUT /api/input-profiles/:code 7.8 Tab 8: Topic Multipliers — link/embed din FrameworkDashboard 7.9 Tab 9: LLM Reviewer - Consuma: GET /api/scoring-configs/pipeline (verdict_config JSONB) - Editeaza: PUT /api/scoring-configs/pipeline 7.10 Tab 10: Score Simulator - Frontend JS pur — incarca configuratia din /api/input-profiles + /api/verdicts/all - Calculeaza local, zero API calls per calcul - Optiune "Compare with production" → POST la agent-v3 cu scoruri mock ``` --- ### FAZA 8: Cleanup + Documentare ``` 8.1 Elimina context (10%) din component_weight PG + formula 8.2 Elimina domain legacy din verdict-calculator (inlocuit de source_assessment) 8.3 Actualizeaza DEFAULT_* constants sa fie identice cu PG seed data 8.4 Actualizeaza INDEX.md agent-v3 cu noul flow 8.5 Actualizeaza VERDICT_BUSINESS_ANALYSIS.md ca "implementat" ``` --- ## 3. VERIFICARE FINALA — DUPA TOATE FAZELE ### Fiecare parametru → exact un loc in PG, exact o cheie Redis, exact un UI element | # | Parametru | PG | Redis | UI | Cod | |---|---|---|---|---|---| | 1 | Ponderi per input type | `input_type_profile.weight_*` | `input_profiles[code].weights` | Tab 1 slidere | citeste Redis, fallback defaults | | 2 | INCONCLUSIVE rules | `input_type_profile.primary_components` etc | `input_profiles[code].inconclusive` | Tab 1 checkboxes | citeste Redis | | 3 | Missing component handling | `input_type_profile.missing_*` | `input_profiles[code].missing` | Tab 1 dropdowns | citeste Redis | | 4 | Override per profil | `profile_override_config` | `input_profiles[code].overrides` | Tab 2 toggles + inputs | citeste Redis | | 5 | Override cap | `input_type_profile.override_cap` | `input_profiles[code].override_cap` | Tab 2 input | citeste Redis | | 6 | Disclosure multipliers | `input_type_profile.ai_disclosure_multipliers` | `input_profiles[code].disclosure` | Tab 3 slidere | citeste Redis | | 7 | Claims UV weight per tip | `claim_type.unverified_weight` | `didi:framework:claims.types[].unverified_weight` | Tab 4 inputs | citeste Redis | | 8 | Claims status credibility weight | `claim.credibility_weight` | `didi:framework:claims.status[].credibility_weight` | Tab 4 inputs | citeste Redis | | 9 | Verdict categories | `verdict_category` | `didi:framework:verdicts.categories` | Tab 5 table | citeste Redis | | 10 | Risk mappings | `risk_mapping` | `didi:framework:verdicts.risk_mappings` | Tab 6 table | citeste Redis | | 11 | Severity | `severity_assessment` | `didi:framework:verdicts.severity` | Tab 6 table | citeste Redis | | 12 | Confidence config | `input_type_profile.confidence_config` | `input_profiles[code].confidence` | Tab 7 inputs | citeste Redis | | 13 | Topic multipliers | `multiplier` | `didi:framework:weights.multipliers` | Tab 8 table | citeste Redis | | 14 | LLM max adjustment | `component_config(pipeline, verdict_config)` | `verdict_config.llm_review.max_adjustment` | Tab 9 input | citeste Redis | | 15 | LLM models + prompts | `component_stage_assignment + component_prompt` | `didi:config:verdict:*` | Tab 9 selects | citeste Redis | | 16 | Techniques scoring params | `component_config(techniques, scoring_config)` | `didi:config:techniques:v3:scoring_config` | Tab 9 sau sectiune dedicata | citeste Redis | | 17 | AI scoring params | `component_config(ai-tampered, scoring_config)` | `didi:config:ai-tampered:v1:scoring_config` | Tab 9 sau sectiune dedicata | citeste Redis | | 18 | Claims scoring params | `component_config(claims, scoring_config)` | `didi:config:claims:v1:scoring_config` | Tab 9 sau sectiune dedicata | citeste Redis | | 19 | Source scoring params | `component_config(source-assessment, scoring_config)` | `didi:config:source-assessment:v1:scoring_config` | Tab 9 sau sectiune dedicata | citeste Redis | | 20 | Video track weights | `component_config(pipeline, component_config)` | `didi:config:pipeline:v1:component_config` | Tab 1 sub-sectiune sau Tab 9 | citeste Redis | **20 parametri × 3 locuri (PG + Redis + UI) = complet aliniat. Zero hardcodari in cod.** --- ## 4. EFORT ESTIMAT PER FAZA | Faza | Ce | Fisiere afectate | Complexitate | |---|---|---|---| | 0 | Backup + inventar | 0 (doar comenzi) | Mica | | 1 | Redis → PG (22 INSERT-uri) | 1 SQL migration | Mica | | 2 | Cod → Redis+PG (citire din Redis) | 5 executori + 1 worker | Medie | | 3 | Fix divergente | 2 fisiere (verdict-calculator + Redis data) | Mica | | 4 | Tabele PG noi + seed | 1 SQL migration | Medie | | 5 | CRUD didiFramework | 2 fisiere noi + 2 extinse + sync-redis | Medie-mare | | 6 | Agent-v3 verdict-calculator | 1 fisier (verdict-calculator.ts) + 1 (executor.ts pipeline) | Medie | | 7 | Admin Dashboard UI | 1 pagina noua cu 10 tab-uri | Mare | | 8 | Cleanup + docs | 3-4 fisiere | Mica | **Dependente**: - Faza 1 → independent - Faza 2 → dupa Faza 1 - Faza 3 → dupa Faza 2 - Faza 4 → independent (poate in paralel cu 2-3) - Faza 5 → dupa Faza 4 - Faza 6 → dupa Faza 5 (sau 3) - Faza 7 → dupa Faza 5 - Faza 8 → dupa toate