livrare lot 2

This commit is contained in:
EVOTECH IT SRL 2026-07-10 03:39:53 -07:00
commit 8ecc78e729
763 changed files with 164593 additions and 0 deletions

View file

@ -0,0 +1,224 @@
/**
* TECHNIQUES V3 PILOT - Test Script
*
* Usage: npx ts-node scripts/test-techniques-v3.ts
*/
import { createRedisConnection } from '../src/shared/redis/connection';
import { TechniquesV3Executor, LLMClient, ModelConfig } from '../src/components/techniques/executor';
// ============================================================================
// MOCK LLM CLIENT (for testing without real API calls)
// ============================================================================
class MockLLMClient implements LLMClient {
async call(prompt: string, systemPrompt: string, config: ModelConfig): Promise<string> {
console.log(`\n📡 LLM Call to: ${config.model_key}`);
console.log(` Prompt length: ${prompt.length} chars`);
// Simulate screening response
if (prompt.includes('AVAILABLE DIMENSIONS')) {
return JSON.stringify({
detected_dimensions: ['D1', 'D4'],
confidence_per_dimension: {
D1: 85,
D4: 72
},
quick_reasoning: 'Text contains fear appeal language and out-of-context claims'
});
}
// Simulate deep analysis response
if (prompt.includes('TECHNIQUES TO DETECT')) {
const dimension = prompt.match(/\(D\d\)/)?.[0]?.replace(/[()]/g, '') || 'D1';
if (dimension === 'D1') {
return JSON.stringify({
dimension: 'D1',
detected_techniques: [
{
technique_id: 5,
confidence: 92,
intensity: 3,
evidence: 'This is a THREAT to our survival!'
},
{
technique_id: 6,
confidence: 78,
intensity: 2,
evidence: 'We must ACT NOW before it is too late!'
}
]
});
}
if (dimension === 'D4') {
return JSON.stringify({
dimension: 'D4',
detected_techniques: [
{
technique_id: 77,
confidence: 65,
intensity: 2,
evidence: 'The image shows clear manipulation artifacts'
}
]
});
}
}
return '{}';
}
}
// ============================================================================
// TEST DATA
// ============================================================================
const TEST_TEXT = `
URGENT: This is a THREAT to our survival! The government is hiding the truth from you.
We must ACT NOW before it is too late! They don't want you to know about this conspiracy.
The image shows clear manipulation artifacts around the edges. Expert sources (who wish to remain anonymous)
confirm that this vaccine is dangerous.
Share this with everyone you know before they delete it! This is being censored on all platforms.
`;
// ============================================================================
// MAIN TEST
// ============================================================================
async function runTest() {
console.log('='.repeat(70));
console.log('TECHNIQUES V3 PILOT - TEST');
console.log('='.repeat(70));
const redis = createRedisConnection({ label: 'test-techniques-v3' });
try {
// Check if pilot data is loaded
const manifest = await redis.get('didi:config:techniques:v3:stage_assignments');
if (!manifest) {
console.log('\n⚠ Config data not found in Redis!');
console.log(' Run: curl -X POST http://localhost:3005/api/sync-redis');
return;
}
console.log('\n✅ Config data found in Redis');
console.log(` Manifest: ${manifest}`);
// Check for framework techniques (needed for deep analysis)
const frameworkTechniques = await redis.get('didi:framework:techniques');
if (!frameworkTechniques) {
console.log('\n⚠ Framework techniques not found!');
console.log(' Using mock technique hierarchy for test...');
// Create mock hierarchy
const mockHierarchy = {
dimensions: [
{
dimension_id: 1,
dimension_code: 'D1',
dimension_name: 'Emotional Manipulation',
subdimensions: [
{
subdimension_id: 1,
subdimension_name: 'Fear Appeals',
techniques: [
{ technique_id: 5, technique_name: 'Fear Appeal', severity: 8, confidence: 5, indicators: [] },
{ technique_id: 6, technique_name: 'Urgency Appeal', severity: 7, confidence: 5, indicators: [] }
]
}
]
},
{
dimension_id: 4,
dimension_code: 'D4',
dimension_name: 'Content Manipulation',
subdimensions: [
{
subdimension_id: 10,
subdimension_name: 'Media Manipulation',
techniques: [
{ technique_id: 77, technique_name: 'Deepfake', severity: 9, confidence: 5, indicators: [] }
]
}
]
}
]
};
await redis.set('didi:framework:techniques', JSON.stringify(mockHierarchy));
console.log(' Mock hierarchy created');
}
// Create executor with mock LLM
const mockLLM = new MockLLMClient();
const executor = new TechniquesV3Executor(redis, mockLLM);
// Run test
console.log('\n' + '-'.repeat(70));
console.log('RUNNING ANALYSIS...');
console.log('-'.repeat(70));
console.log(`\nInput text (${TEST_TEXT.length} chars):`);
console.log(TEST_TEXT.substring(0, 200) + '...');
const sessionId = `test-${Date.now()}`;
const result = await executor.execute(TEST_TEXT, sessionId);
// Display results
console.log('\n' + '='.repeat(70));
console.log('RESULTS');
console.log('='.repeat(70));
console.log('\n📊 MANIPULATION SCORE:', (result.manipulation_score * 100).toFixed(1) + '%');
console.log('📈 DIMENSIONS AFFECTED:', result.dimensions_affected.join(', '));
console.log('📝 TECHNIQUES DETECTED:', result.techniques.length);
console.log('\n🔍 DETECTED TECHNIQUES:');
for (const t of result.techniques) {
console.log(` [${t.id}] ${t.name} (${t.dimension})`);
console.log(` Confidence: ${t.confidence}%, Intensity: ${t.intensity}, Severity: ${t.severity}`);
console.log(` Evidence: "${t.evidence.substring(0, 50)}..."`);
}
console.log('\n🔗 COUPLING CONTEXT:');
console.log(' For Claims:');
console.log(` - Emotional manipulation: ${result.coupling_context.for_claims.has_emotional_manipulation}`);
console.log(` - Logical fallacies: ${result.coupling_context.for_claims.has_logical_fallacies}`);
console.log(` - Manipulation level: ${result.coupling_context.for_claims.manipulation_level}`);
console.log(` - Warning flags: ${result.coupling_context.for_claims.warning_flags.join(', ') || 'none'}`);
console.log(' For Verdict:');
console.log(` - Risk score: ${result.coupling_context.for_verdict.risk_score.toFixed(3)}`);
console.log(` - Dimension count: ${result.coupling_context.for_verdict.dimension_count}`);
console.log(` - Severe techniques: ${result.coupling_context.for_verdict.severe_technique_count}`);
console.log(` - Needs override check: ${result.coupling_context.for_verdict.needs_override_check}`);
console.log('\n⏱ TIMING:');
console.log(` Screening: ${result.metadata.screening_duration_ms}ms (${result.metadata.llm_screening})`);
console.log(` Deep analysis: ${result.metadata.deep_analysis_duration_ms}ms (${result.metadata.llm_deep})`);
console.log(` Total: ${result.metadata.total_duration_ms}ms`);
// Verify Redis storage
console.log('\n📦 REDIS STORAGE:');
const keys = await redis.keys(`agent:result:${sessionId}:*`);
for (const key of keys.sort()) {
console.log(` - ${key}`);
}
console.log('\n' + '='.repeat(70));
console.log('TEST COMPLETE ✅');
console.log('='.repeat(70));
} catch (error) {
console.error('\n❌ Test failed:', error);
} finally {
await redis.quit();
}
}
// Run test
runTest().catch(console.error);

View file

@ -0,0 +1,193 @@
/**
* RabbitMQ cluster readiness verification.
*
* Runs checks against the RabbitMQ instance configured via env vars
* (RABBITMQ_HOST/PORT/USER/PASS/VHOST). Intended to be run:
* - Pre-cutover: confirm cluster accessible + vhost + privileges
* - Post-cutover: confirm expected topology created
* - CI / healthcheck: block container start until broker is reachable
*
* Exit codes:
* 0 all checks pass
* 1 fatal issue (connectivity, auth, missing vhost)
* 2 warning (topology partially initialized normal pre-workers)
*
* Usage:
* RABBITMQ_HOST=10.11.50.100 RABBITMQ_PORT=16672 \
* RABBITMQ_USER=didi RABBITMQ_PASS=... RABBITMQ_VHOST=/didi \
* npx ts-node --transpile-only scripts/verify-rabbitmq-cluster.ts
*/
import amqp from 'amqplib';
import {
getRabbitMQUrl,
getRabbitMQConfig,
EXCHANGE_NAME,
QUEUE,
MEDIA_QUEUE,
ANALYSIS_COMPONENTS,
type PlanType,
} from '../src/shared/queue/constants';
const PLAN_TYPES: PlanType[] = [1, 2, 3, 4, 5, 6];
type Severity = 'OK' | 'WARN' | 'FAIL';
interface Check { name: string; severity: Severity; detail: string; }
const results: Check[] = [];
let fatal = 0, warn = 0;
function record(name: string, severity: Severity, detail: string) {
results.push({ name, severity, detail });
if (severity === 'FAIL') fatal++;
else if (severity === 'WARN') warn++;
}
async function main() {
const cfg = getRabbitMQConfig();
const target = `${cfg.host}:${cfg.port}${cfg.vhost}`;
console.log(`\n${'='.repeat(70)}`);
console.log(`RabbitMQ cluster readiness — ${target} (user: ${cfg.user})`);
console.log('='.repeat(70));
// -------------------------------------------------------------------------
// 1. Connect + auth
// -------------------------------------------------------------------------
let conn: any = null;
try {
conn = await amqp.connect(getRabbitMQUrl());
record('connectivity', 'OK', `amqp.connect → ${target}`);
} catch (err: any) {
// Map common errors to actionable messages
let hint = err.message;
if (err.code === 'ENOTFOUND') hint = `DNS resolution failed for ${cfg.host} — check network`;
else if (err.code === 'ECONNREFUSED') hint = `port ${cfg.port} refused — broker down?`;
else if (/ACCESS_REFUSED/i.test(err.message)) hint = `auth failed — check user/pass`;
else if (/NOT_ALLOWED.*vhost/i.test(err.message)) hint = `vhost '${cfg.vhost}' missing or no access`;
record('connectivity', 'FAIL', hint);
await finalize(null);
return;
}
// -------------------------------------------------------------------------
// 2. Channel creation
// -------------------------------------------------------------------------
let ch: any = null;
try {
ch = await conn.createChannel();
record('channel', 'OK', 'createChannel → ready');
} catch (err: any) {
record('channel', 'FAIL', `cannot create channel: ${err.message}`);
await finalize(conn);
return;
}
// -------------------------------------------------------------------------
// 3. Exchange declare (idempotent — won't break existing)
// -------------------------------------------------------------------------
try {
await ch.assertExchange(EXCHANGE_NAME, 'topic', { durable: true });
record('exchange:analysis', 'OK', `exchange '${EXCHANGE_NAME}' (topic, durable) asserted`);
} catch (err: any) {
record('exchange:analysis', 'FAIL', `cannot assert exchange: ${err.message}`);
}
// -------------------------------------------------------------------------
// 4. Test queue write privilege (create a temp queue, then delete)
// -------------------------------------------------------------------------
try {
const tempQueue = `didi.verify.${Date.now()}.${Math.random().toString(36).slice(2, 8)}`;
await ch.assertQueue(tempQueue, { durable: false, autoDelete: true, exclusive: true });
await ch.deleteQueue(tempQueue);
record('privileges:write', 'OK', 'can create + delete queues on vhost');
} catch (err: any) {
record('privileges:write', 'FAIL', `no write privilege on vhost '${cfg.vhost}': ${err.message}`);
}
// -------------------------------------------------------------------------
// 5. Expected topology — check which queues already exist
// (All 31 queues are OK if workers have started; 0 is OK pre-cutover)
// -------------------------------------------------------------------------
const expectedQueues: string[] = [];
for (const comp of ANALYSIS_COMPONENTS) {
for (const plan of PLAN_TYPES) {
expectedQueues.push(QUEUE.queueName(comp, plan));
}
}
for (const plan of PLAN_TYPES) {
expectedQueues.push(MEDIA_QUEUE.queueName(plan));
}
expectedQueues.push(QUEUE.RESULTS_QUEUE);
let foundQueues = 0;
for (const q of expectedQueues) {
try {
// checkQueue throws if queue doesn't exist (and poisons the channel!)
// Use a new channel per check to avoid cascade failures
const probeCh = await conn.createChannel();
probeCh.on('error', () => { /* swallow */ });
try {
await probeCh.checkQueue(q);
foundQueues++;
} catch {
// Queue doesn't exist yet — normal pre-cutover
}
try { await probeCh.close(); } catch { /* ignore */ }
} catch {
// Channel creation failed — broker issue
break;
}
}
if (foundQueues === expectedQueues.length) {
record('topology', 'OK', `all ${expectedQueues.length} expected queues present`);
} else if (foundQueues === 0) {
record('topology', 'WARN', `0/${expectedQueues.length} queues — normal if workers not started yet (will auto-create)`);
} else {
record('topology', 'WARN', `${foundQueues}/${expectedQueues.length} queues present (partial — may be mid-cutover)`);
}
// -------------------------------------------------------------------------
// 6. Cleanup
// -------------------------------------------------------------------------
try { await ch.close(); } catch { /* ignore */ }
await finalize(conn);
}
async function finalize(conn: any) {
if (conn) {
try { await conn.close(); } catch { /* ignore */ }
}
console.log('');
for (const r of results) {
const badge =
r.severity === 'OK' ? ' ✓ ' :
r.severity === 'WARN' ? ' ⚠ ' : ' ✘ ';
console.log(`${badge} [${r.severity.padEnd(4)}] ${r.name.padEnd(28)} ${r.detail}`);
}
console.log('');
console.log('='.repeat(70));
const passed = results.filter(r => r.severity === 'OK').length;
console.log(`Results: ${passed} OK · ${warn} WARN · ${fatal} FAIL`);
console.log('='.repeat(70));
if (fatal > 0) {
console.log(`\n✘ NOT READY — ${fatal} fatal issue(s).\n`);
process.exit(1);
}
if (warn > 0) {
console.log(`\n⚠ READY with ${warn} warning(s) — topology will auto-create when workers start.\n`);
process.exit(0); // warnings are expected pre-cutover
}
console.log(`\n✓ CLUSTER READY — safe to cutover.\n`);
process.exit(0);
}
main().catch((err) => {
console.error('Unhandled error:', err);
process.exit(1);
});

View file

@ -0,0 +1,239 @@
/**
* Redis cluster readiness verification.
*
* Runs a battery of checks against the Redis instance configured via env vars
* (REDIS_HOST/PORT/USERNAME/PASSWORD/DB). Intended to be run:
* - Pre-cutover: confirm the new cluster has all required keys before switching env
* - Post-cutover smoke test: confirm nothing got lost
* - CI / healthcheck: block container start until cluster is ready
*
* Exit codes:
* 0 all checks pass
* 1 at least one FATAL check fails (connectivity, missing framework keys)
* 2 only WARNING-level issues (missing optional keys, empty scan results)
*
* Usage:
* REDIS_HOST=10.11.50.100 REDIS_PORT=16379 REDIS_USERNAME=didi \
* REDIS_PASSWORD=... npx tsx scripts/verify-redis-cluster.ts
*/
import { createRedisConnection } from '../src/shared/redis/connection';
import { FrameworkKeys, ConfigKeys } from '../src/shared/redis/keys';
type Severity = 'OK' | 'WARN' | 'FAIL';
interface CheckResult {
name: string;
severity: Severity;
detail: string;
}
const results: CheckResult[] = [];
let fatalCount = 0;
let warnCount = 0;
function record(name: string, severity: Severity, detail: string) {
results.push({ name, severity, detail });
if (severity === 'FAIL') fatalCount++;
else if (severity === 'WARN') warnCount++;
}
async function main() {
const host = process.env.REDIS_HOST || 'didi-cache';
const port = process.env.REDIS_PORT || '6379';
const user = process.env.REDIS_USERNAME || '(legacy-auth)';
console.log(`\n${'='.repeat(70)}`);
console.log(`Redis cluster readiness check — ${host}:${port} (user: ${user})`);
console.log('='.repeat(70));
const redis = createRedisConnection({
label: 'verify-cluster',
overrides: { maxRetriesPerRequest: 3 },
});
// -------------------------------------------------------------------------
// 1. Connectivity + auth
// -------------------------------------------------------------------------
try {
const pong = await redis.ping();
if (pong !== 'PONG') throw new Error(`unexpected PING reply: ${pong}`);
record('connectivity', 'OK', 'PING → PONG');
} catch (err: any) {
record('connectivity', 'FAIL', `cannot reach cluster: ${err.message}`);
await finalize(redis);
return;
}
// -------------------------------------------------------------------------
// 2. Server info (master/replica, memory)
// -------------------------------------------------------------------------
try {
const info = await redis.info('replication');
const role = /role:(\w+)/.exec(info)?.[1] || 'unknown';
const slaves = /connected_slaves:(\d+)/.exec(info)?.[1] || '0';
record('replication', role === 'master' ? 'OK' : 'WARN',
`role=${role}, connected_slaves=${slaves}`);
} catch (err: any) {
record('replication', 'WARN', `INFO replication failed: ${err.message}`);
}
try {
const mem = await redis.info('memory');
const used = /used_memory_human:(\S+)/.exec(mem)?.[1] || '?';
const max = /maxmemory_human:(\S+)/.exec(mem)?.[1] || '?';
const policy = /maxmemory_policy:(\S+)/.exec(mem)?.[1] || '?';
record('memory', 'OK', `used=${used}, max=${max}, policy=${policy}`);
} catch {
// ignore
}
// -------------------------------------------------------------------------
// 3. Framework keys (REQUIRED — agent-v3 fails without these)
// -------------------------------------------------------------------------
const requiredFrameworkKeys = [
FrameworkKeys.manifest,
FrameworkKeys.techniques,
FrameworkKeys.sources,
FrameworkKeys.claims,
FrameworkKeys.verdicts,
FrameworkKeys.weights,
FrameworkKeys.dimensionsCompact,
];
for (const key of requiredFrameworkKeys) {
const exists = await redis.exists(key);
if (exists) {
const val = await redis.get(key);
const size = val ? val.length : 0;
record(`framework:${key.split(':').pop()}`, 'OK', `present (${size} bytes)`);
} else {
record(`framework:${key.split(':').pop()}`, 'FAIL', `MISSING: ${key}`);
}
}
// Optional
const providers = await redis.exists(FrameworkKeys.providers);
record('framework:providers', providers ? 'OK' : 'WARN',
providers ? 'present (optional)' : 'absent (optional, OK)');
// -------------------------------------------------------------------------
// 4. Component config keys (REQUIRED for tier routing)
// -------------------------------------------------------------------------
const stageAssignmentKeys = [
{ label: 'techniques', key: ConfigKeys.techniquesStageAssignments },
{ label: 'ai-tampered', key: ConfigKeys.aiTamperedStageAssignments },
{ label: 'claims', key: ConfigKeys.claimsStageAssignments },
{ label: 'source-assessment', key: ConfigKeys.sourceAssessmentStageAssignments },
{ label: 'vision', key: 'didi:config:vision:v1:stage_assignments' },
{ label: 'verdict', key: 'didi:config:verdict:v1:stage_assignments' },
];
for (const { label, key } of stageAssignmentKeys) {
const val = await redis.get(key);
if (!val) {
record(`stage_assignments:${label}`, 'FAIL', `MISSING: ${key}`);
continue;
}
try {
const parsed = JSON.parse(val);
const stages = Object.keys(parsed);
if (stages.length === 0) {
record(`stage_assignments:${label}`, 'FAIL', `empty object in ${key}`);
continue;
}
// Verify tier-nested structure on first stage
const firstStage = parsed[stages[0]];
const hasFree = firstStage?.free?.models && Array.isArray(firstStage.free.models);
const hasPremium = firstStage?.premium?.models && Array.isArray(firstStage.premium.models);
if (hasFree && hasPremium) {
record(`stage_assignments:${label}`, 'OK',
`${stages.length} stage(s), tier-nested (free+premium) ✓`);
} else if (hasFree) {
record(`stage_assignments:${label}`, 'WARN',
`${stages.length} stage(s), free only (premium missing — fallback works)`);
} else {
record(`stage_assignments:${label}`, 'FAIL',
`${stages.length} stage(s), not tier-nested — old format? Re-run sync-redis.`);
}
} catch (err: any) {
record(`stage_assignments:${label}`, 'FAIL', `invalid JSON: ${err.message}`);
}
}
// Available models (union, used for UI)
const availableModelKeys = [
ConfigKeys.techniquesAvailableModels,
ConfigKeys.aiTamperedAvailableModels,
ConfigKeys.claimsAvailableModels,
ConfigKeys.sourceAssessmentAvailableModels,
];
let missingModels = 0;
for (const key of availableModelKeys) {
if (!(await redis.exists(key))) missingModels++;
}
record('available_models',
missingModels === 0 ? 'OK' : missingModels < availableModelKeys.length ? 'WARN' : 'FAIL',
`${availableModelKeys.length - missingModels}/${availableModelKeys.length} keys present`);
// -------------------------------------------------------------------------
// 5. Pipeline config + input profiles (REQUIRED by verdict calculator)
// -------------------------------------------------------------------------
const pipelineKeys = [
ConfigKeys.pipelineComponentConfig,
ConfigKeys.pipelineSessionConfig,
ConfigKeys.pipelineInputProfiles,
];
for (const key of pipelineKeys) {
const exists = await redis.exists(key);
const label = key.split(':').slice(-1)[0];
record(`pipeline:${label}`, exists ? 'OK' : 'FAIL',
exists ? 'present' : `MISSING: ${key}`);
}
// -------------------------------------------------------------------------
// 6. Aggregate stats
// -------------------------------------------------------------------------
try {
const dbsize = await redis.dbsize();
record('dbsize', 'OK', `${dbsize} keys total`);
} catch {
// ignore
}
await finalize(redis);
}
async function finalize(redis: any) {
redis.disconnect();
// Pretty print
console.log('');
for (const r of results) {
const badge =
r.severity === 'OK' ? ' ✓ ' :
r.severity === 'WARN' ? ' ⚠ ' : ' ✘ ';
console.log(`${badge} [${r.severity.padEnd(4)}] ${r.name.padEnd(35)} ${r.detail}`);
}
console.log('');
console.log('='.repeat(70));
const passed = results.filter(r => r.severity === 'OK').length;
console.log(`Results: ${passed} OK · ${warnCount} WARN · ${fatalCount} FAIL`);
console.log('='.repeat(70));
if (fatalCount > 0) {
console.log(`\n✘ NOT READY — ${fatalCount} fatal issue(s). Run sync-redis against this cluster before cutover.\n`);
process.exit(1);
}
if (warnCount > 0) {
console.log(`\n⚠ READY with warnings — ${warnCount} non-blocking issue(s).\n`);
process.exit(2);
}
console.log(`\n✓ CLUSTER READY — safe to cutover.\n`);
process.exit(0);
}
main().catch((err) => {
console.error('Unhandled error:', err);
process.exit(1);
});