Feat/gt analytics openclaw (#392)

* feat(telegram): auto-translate OSINT channel posts to English

Cherry-picked from @Bobpick PR #391 (telegram-only slice): server-side translation during fetch, SHOW ORIGINAL toggle in TelegramOsintPopup, and on-demand /api/telegram-feed?lang=.

Co-authored-by: Robert Pickett <bobpickettsr@yahoo.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(gt): experimental Derived OSINT analytics with lean-node safeguards

Cherry-picked from @Bobpick PR #391 (GT + OpenClaw slice): Bayesian strategic-risk engine, map overlay, OpenClaw commands, and telegram_rhetoric watchdog. Off by default (GT_ANALYTICS_ENABLED=false, gt_risk layer false). 1 vCPU nodes get cgroup detection, UI warning on layer toggle, and lean profile that skips scheduled ingest/Louvain unless GT_ANALYTICS_ACK_LOW_CPU=true. Backtest HUD removed from dashboard (OpenClaw/API regression only).

Co-authored-by: Robert Pickett <bobpickettsr@yahoo.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Robert Pickett <bobpickettsr@yahoo.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Shadowbroker
2026-06-16 17:05:46 -06:00
committed by GitHub
parent 9c5a4054f6
commit cfbeabda1e
69 changed files with 8102 additions and 78 deletions
@@ -1956,3 +1956,64 @@ export function buildSarAoisGeoJSON(aois?: SarAoi[]): FC {
if (features.length === 0) return null;
return { type: 'FeatureCollection' as const, features };
}
// ─── Strategic Risk Analytics (GT early warning) ────────────────────────────
export function buildGtRiskGeoJSON(
payload?: {
enabled?: boolean;
heatmap?: { features?: Array<GTRiskHeatmapFeatureLike> };
} | null,
): FC {
const features = payload?.heatmap?.features;
if (!features?.length) return null;
const normalized = features
.map((feature, index) => {
const coords = feature.geometry?.coordinates;
if (!coords || coords.length < 2) return null;
const [lng, lat] = coords;
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null;
if (Math.abs(lat) < 0.001 && Math.abs(lng) < 0.001) return null;
const props = feature.properties || {};
const region = String(props.region || `region-${index}`);
return {
type: 'Feature' as const,
properties: {
...props,
type: 'gt_risk',
id: region,
name: region,
lat,
lng,
risk: Number(props.risk ?? 0),
financial: Number(props.financial ?? 0),
unrest: Number(props.unrest ?? 0),
conflict: Number(props.conflict ?? 0),
contagion: Number(props.contagion ?? 0),
},
geometry: {
type: 'Point' as const,
coordinates: [lng, lat] as [number, number],
},
};
})
.filter(Boolean) as GeoJSON.Feature[];
if (!normalized.length) return null;
return { type: 'FeatureCollection' as const, features: normalized };
}
type GTRiskHeatmapFeatureLike = {
properties?: {
region?: string;
risk?: number;
financial?: number;
unrest?: number;
conflict?: number;
contagion?: number;
};
geometry?: {
coordinates?: [number, number];
};
};