widgettdc-api / apps /backend /src /scripts /holographic_match.ts
Kraft102's picture
Update backend source
34367da verified
import 'dotenv/config';
import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
import neo4j from 'neo4j-driver';
// ESM Shim
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Output sti til rapporten
const REPORT_PATH = path.resolve(__dirname, '../../../../docs/HOLOGRAPHIC_GAP_REPORT.json');
async function runHolographicAnalysis() {
console.log('🌌 Operation Holographic Match: Initializing...');
const uri = process.env.NEO4J_URI;
const user = process.env.NEO4J_USER;
const password = process.env.NEO4J_PASSWORD;
if (!uri || !user || !password) {
console.error('❌ FEJL: Mangler Neo4j credentials.');
process.exit(1);
}
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password));
const session = driver.session();
try {
console.log('🧠 Connecting to Cortex...');
// THE HOLOGRAPHIC QUERY (Fra Blackboardet)
// Finder udbud (Tenders) hvor vi MANGLER koden (File content) til at løse opgaven
// Bemærk: Denne query antager at t.keywords eksisterer på Tender noder.
// Vores tidligere scripts har muligvis ikke sat denne property eksplicit på noden, men relationen har 'matches'.
// Lad os justere queryen til at bruge relationen POTENTIAL_FIT's 'matches' property.
const result = await session.run(`
MATCH (org:Organization)-[f:POTENTIAL_FIT]->(t:Tender)
// Unwind alle keywords fra 'matches' arrayet på relationen
UNWIND f.matches as keyword
WITH t, keyword, org
// Tjek om vi har en fil der matcher dette keyword
CALL {
WITH keyword
MATCH (file:File)
WHERE toLower(file.name) CONTAINS toLower(keyword)
OR toLower(file.path) CONTAINS toLower(keyword)
RETURN count(file) > 0 as hasCapability
}
WITH t, keyword, hasCapability
WHERE NOT hasCapability
// Aggreger manglende keywords per tender
RETURN t.title as Title,
t.buyer as Buyer,
'Gap Detected' as Status,
t.url as Url,
collect(keyword) as MissingKeywords
LIMIT 20
`);
const gaps = result.records.map(r => ({
title: r.get('Title'),
buyer: r.get('Buyer'),
status: r.get('Status'),
url: r.get('Url'),
missingKeywords: r.get('MissingKeywords'),
recommendation: "INITIATE R&D SPRINT"
}));
console.log(`🔍 Analysis Complete. Found ${gaps.length} capability gaps.`);
// Gem rapporten
fs.writeFileSync(REPORT_PATH, JSON.stringify(gaps, null, 2));
console.log(`📄 Report saved to: ${REPORT_PATH}`);
if (gaps.length > 0) {
console.log('\nTop 3 Missing Capabilities (Opportunities):');
gaps.slice(0, 3).forEach((g, i) => {
console.log(`${i+1}. ${g.title} (${g.buyer})`);
console.log(` Missing: ${g.missingKeywords.join(', ')}`);
});
} else {
console.log('✨ No gaps found! We are fully synced with the market.');
}
} catch (error) {
console.error('💥 Holographic Failure:', error);
} finally {
await session.close();
await driver.close();
}
}
runHolographicAnalysis();