@neuroverseos/governance 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/autoresearch.cjs +19 -1
- package/dist/adapters/autoresearch.d.cts +1 -1
- package/dist/adapters/autoresearch.d.ts +1 -1
- package/dist/adapters/autoresearch.js +2 -2
- package/dist/adapters/deep-agents.cjs +19 -1
- package/dist/adapters/deep-agents.d.cts +2 -2
- package/dist/adapters/deep-agents.d.ts +2 -2
- package/dist/adapters/deep-agents.js +2 -2
- package/dist/adapters/express.cjs +19 -1
- package/dist/adapters/express.d.cts +1 -1
- package/dist/adapters/express.d.ts +1 -1
- package/dist/adapters/express.js +2 -2
- package/dist/adapters/github.cjs +19 -1
- package/dist/adapters/github.d.cts +2 -2
- package/dist/adapters/github.d.ts +2 -2
- package/dist/adapters/github.js +2 -2
- package/dist/adapters/index.cjs +19 -1
- package/dist/adapters/index.d.cts +2 -2
- package/dist/adapters/index.d.ts +2 -2
- package/dist/adapters/index.js +8 -8
- package/dist/adapters/langchain.cjs +19 -1
- package/dist/adapters/langchain.d.cts +2 -2
- package/dist/adapters/langchain.d.ts +2 -2
- package/dist/adapters/langchain.js +2 -2
- package/dist/adapters/mentraos.cjs +19 -1
- package/dist/adapters/mentraos.d.cts +2 -2
- package/dist/adapters/mentraos.d.ts +2 -2
- package/dist/adapters/mentraos.js +2 -2
- package/dist/adapters/openai.cjs +19 -1
- package/dist/adapters/openai.d.cts +2 -2
- package/dist/adapters/openai.d.ts +2 -2
- package/dist/adapters/openai.js +2 -2
- package/dist/adapters/openclaw.cjs +19 -1
- package/dist/adapters/openclaw.d.cts +2 -2
- package/dist/adapters/openclaw.d.ts +2 -2
- package/dist/adapters/openclaw.js +2 -2
- package/dist/admin/index.cjs +19 -1
- package/dist/admin/index.js +1 -1
- package/dist/audit-JYNN3MOQ.js +98 -0
- package/dist/audit-behavior-C62FdRAC.d.cts +100 -0
- package/dist/audit-behavior-DFy7LeYv.d.ts +100 -0
- package/dist/{behavioral-SPWPGYXL.js → behavioral-4TKMHZQZ.js} +2 -2
- package/dist/{chunk-OQU65525.js → chunk-24YW7BHC.js} +1 -1
- package/dist/{chunk-BZYQHJDM.js → chunk-2KTPIE57.js} +25 -5
- package/dist/{chunk-TJ5L2UTE.js → chunk-5K3LATTM.js} +1 -1
- package/dist/{chunk-HDNDL6D5.js → chunk-5LDBYOSJ.js} +1 -1
- package/dist/{chunk-FDPPZLSQ.js → chunk-5ZWKM7MO.js} +1 -1
- package/dist/{chunk-B3IIPTY3.js → chunk-6MB6TMAG.js} +1 -1
- package/dist/{chunk-IOVXB6QN.js → chunk-GXTAHCND.js} +1 -1
- package/dist/{chunk-FKQCPRKI.js → chunk-MAOIHKFO.js} +1 -1
- package/dist/{chunk-ZAF6JH23.js → chunk-MBOW6YXN.js} +19 -1
- package/dist/{chunk-A2UZTLRV.js → chunk-MLXKSX3L.js} +1 -1
- package/dist/{chunk-7FL3U7Z5.js → chunk-MWGEXHOD.js} +1 -1
- package/dist/{chunk-6CV4XG3J.js → chunk-QFDFAWZ6.js} +1 -1
- package/dist/{chunk-2VAWP6FI.js → chunk-RAS62JXV.js} +1 -1
- package/dist/{chunk-OTZU76DH.js → chunk-XAF3CYCW.js} +1 -1
- package/dist/{chunk-T6GMRZWC.js → chunk-XTYQCTDD.js} +1 -1
- package/dist/{chunk-TIXVEPS2.js → chunk-YN7OI5ZV.js} +1 -1
- package/dist/cli/neuroverse.cjs +229 -93
- package/dist/cli/neuroverse.js +16 -12
- package/dist/cli/plan.cjs +18 -0
- package/dist/cli/radiant.cjs +42 -4
- package/dist/cli/radiant.js +3 -3
- package/dist/cli/run.cjs +18 -0
- package/dist/cli/run.js +4 -4
- package/dist/{decision-flow-IJPNMVQK.js → decision-flow-5VI5YG6A.js} +2 -2
- package/dist/{demo-6W3YXLAX.js → demo-GYX6CYHC.js} +2 -2
- package/dist/engine/guard-engine.cjs +19 -1
- package/dist/engine/guard-engine.d.cts +21 -1
- package/dist/engine/guard-engine.d.ts +21 -1
- package/dist/engine/guard-engine.js +1 -1
- package/dist/{equity-penalties-CCO3GVHS.js → equity-penalties-NOM46NEO.js} +2 -2
- package/dist/{guard-IHJEKHL2.js → guard-PQ3SYV4Y.js} +3 -3
- package/dist/{guard-contract-ddiIPlOg.d.cts → guard-contract-Oznf-Kgq.d.cts} +32 -0
- package/dist/{guard-contract-q6HJAq3Q.d.ts → guard-contract-w_i_6gh-.d.ts} +32 -0
- package/dist/{impact-WIAM66IH.js → impact-LDJLTVRU.js} +3 -3
- package/dist/index.cjs +62 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +49 -8
- package/dist/{mcp-server-CKYBHXWK.js → mcp-server-W3MWSKD7.js} +2 -2
- package/dist/{playground-3TTBN7XD.js → playground-SSZRNUAF.js} +1 -1
- package/dist/radiant/index.cjs +450 -5
- package/dist/radiant/index.d.cts +151 -1
- package/dist/radiant/index.d.ts +151 -1
- package/dist/radiant/index.js +405 -2
- package/dist/{redteam-W644UMWN.js → redteam-KCULS7EW.js} +1 -1
- package/dist/{server-EI5JCIBU.js → server-EGRGGSM2.js} +2 -2
- package/dist/{session-FMAROEIE.js → session-PZLTL22G.js} +2 -2
- package/dist/{shared-PpalGKxc.d.cts → shared-BC8mOpt0.d.cts} +1 -1
- package/dist/{shared-DAzdfWtU.d.ts → shared-CP63gNNW.d.ts} +1 -1
- package/dist/{test-XDB2DH3L.js → test-LIHGWHBA.js} +1 -1
- package/dist/{trace-2YDNAXMK.js → trace-DC3D7XPD.js} +2 -2
- package/package.json +1 -1
- /package/dist/{doctor-XEMLO6UA.js → doctor-SIWQGTAO.js} +0 -0
package/dist/radiant/index.cjs
CHANGED
|
@@ -56,16 +56,20 @@ __export(radiant_exports, {
|
|
|
56
56
|
fetchDiscordActivity: () => fetchDiscordActivity,
|
|
57
57
|
fetchGitHubActivity: () => fetchGitHubActivity,
|
|
58
58
|
fetchGitHubOrgActivity: () => fetchGitHubOrgActivity,
|
|
59
|
+
fetchGoogleWorkspaceActivity: () => fetchGoogleWorkspaceActivity,
|
|
59
60
|
fetchLinearActivity: () => fetchLinearActivity,
|
|
60
61
|
fetchNotionActivity: () => fetchNotionActivity,
|
|
62
|
+
fetchSalesforceActivity: () => fetchSalesforceActivity,
|
|
61
63
|
fetchSlackActivity: () => fetchSlackActivity,
|
|
62
64
|
filterEventsByUser: () => filterEventsByUser,
|
|
63
65
|
formatActiveWorlds: () => formatActiveWorlds,
|
|
64
66
|
formatDiscordSignalsForPrompt: () => formatDiscordSignalsForPrompt,
|
|
65
67
|
formatExocortexForPrompt: () => formatExocortexForPrompt,
|
|
68
|
+
formatGoogleWorkspaceSignalsForPrompt: () => formatGoogleWorkspaceSignalsForPrompt,
|
|
66
69
|
formatLinearSignalsForPrompt: () => formatLinearSignalsForPrompt,
|
|
67
70
|
formatNotionSignalsForPrompt: () => formatNotionSignalsForPrompt,
|
|
68
71
|
formatPriorReadsForPrompt: () => formatPriorReadsForPrompt,
|
|
72
|
+
formatSalesforceSignalsForPrompt: () => formatSalesforceSignalsForPrompt,
|
|
69
73
|
formatScope: () => formatScope,
|
|
70
74
|
formatSlackSignalsForPrompt: () => formatSlackSignalsForPrompt,
|
|
71
75
|
formatTeamExocorticesForPrompt: () => formatTeamExocorticesForPrompt,
|
|
@@ -2296,6 +2300,405 @@ async function fetchLinearGraphQL(apiKey, query, variables) {
|
|
|
2296
2300
|
return json.data;
|
|
2297
2301
|
}
|
|
2298
2302
|
|
|
2303
|
+
// src/radiant/adapters/google-workspace.ts
|
|
2304
|
+
async function fetchGoogleWorkspaceActivity(options) {
|
|
2305
|
+
const windowDays = options.windowDays ?? 14;
|
|
2306
|
+
const maxEmails = options.maxEmails ?? 100;
|
|
2307
|
+
const maxEvents = options.maxEvents ?? 100;
|
|
2308
|
+
const leaderEmail = options.leaderEmail?.toLowerCase();
|
|
2309
|
+
const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
|
|
2310
|
+
const [emailEvents, emailSignals] = await fetchGmailSent(
|
|
2311
|
+
options.accessToken,
|
|
2312
|
+
since,
|
|
2313
|
+
maxEmails,
|
|
2314
|
+
leaderEmail
|
|
2315
|
+
);
|
|
2316
|
+
const [calendarEvents, calendarSignals] = await fetchCalendarEvents(
|
|
2317
|
+
options.accessToken,
|
|
2318
|
+
since,
|
|
2319
|
+
maxEvents,
|
|
2320
|
+
leaderEmail
|
|
2321
|
+
);
|
|
2322
|
+
const events = [...emailEvents, ...calendarEvents].sort(
|
|
2323
|
+
(a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp)
|
|
2324
|
+
);
|
|
2325
|
+
return {
|
|
2326
|
+
events,
|
|
2327
|
+
signals: {
|
|
2328
|
+
...emailSignals,
|
|
2329
|
+
...calendarSignals
|
|
2330
|
+
}
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2333
|
+
function formatGoogleWorkspaceSignalsForPrompt(signals) {
|
|
2334
|
+
if (signals.emailsSent === 0 && signals.meetingsHeld === 0) return "";
|
|
2335
|
+
const lines = [
|
|
2336
|
+
"## Google Workspace Activity (external coordination + meeting load)",
|
|
2337
|
+
""
|
|
2338
|
+
];
|
|
2339
|
+
if (signals.emailsSent > 0) {
|
|
2340
|
+
lines.push(
|
|
2341
|
+
`${signals.emailsSent} emails sent in window, to ${signals.uniqueRecipients} unique recipients.`
|
|
2342
|
+
);
|
|
2343
|
+
if (signals.topRecipients.length > 0) {
|
|
2344
|
+
lines.push(`Most-emailed: ${signals.topRecipients.slice(0, 5).join(", ")}.`);
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
if (signals.meetingsHeld > 0) {
|
|
2348
|
+
const hours = Math.round(signals.totalMeetingMinutes / 60 * 10) / 10;
|
|
2349
|
+
lines.push(
|
|
2350
|
+
`${signals.meetingsHeld} meetings held (${signals.meetingsOrganized} organized by the leader), ${hours}h total.`
|
|
2351
|
+
);
|
|
2352
|
+
if (signals.avgMeetingAttendees !== null) {
|
|
2353
|
+
lines.push(
|
|
2354
|
+
`Average ${signals.avgMeetingAttendees} attendees per meeting, ${signals.uniqueAttendees} unique attendees total.`
|
|
2355
|
+
);
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
lines.push("");
|
|
2359
|
+
lines.push(
|
|
2360
|
+
"Gmail sent volume + Calendar meeting load reveal a leader's external coordination shape."
|
|
2361
|
+
);
|
|
2362
|
+
lines.push(
|
|
2363
|
+
"Compare against shipped work (GitHub, Linear) to find the stated-strategy-vs-actual-time gap."
|
|
2364
|
+
);
|
|
2365
|
+
return lines.join("\n");
|
|
2366
|
+
}
|
|
2367
|
+
async function fetchGmailSent(token, since, maxEmails, leaderEmail) {
|
|
2368
|
+
const sinceUnix = Math.floor(since.getTime() / 1e3);
|
|
2369
|
+
const listUrl = new URL("https://gmail.googleapis.com/gmail/v1/users/me/messages");
|
|
2370
|
+
listUrl.searchParams.set("q", `in:sent after:${sinceUnix}`);
|
|
2371
|
+
listUrl.searchParams.set("maxResults", String(Math.min(maxEmails, 100)));
|
|
2372
|
+
const listRes = await fetch(listUrl.toString(), {
|
|
2373
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
2374
|
+
});
|
|
2375
|
+
if (!listRes.ok) {
|
|
2376
|
+
throw new Error(`Gmail list failed ${listRes.status}: ${(await listRes.text()).slice(0, 200)}`);
|
|
2377
|
+
}
|
|
2378
|
+
const listJson = await listRes.json();
|
|
2379
|
+
const ids = (listJson.messages ?? []).slice(0, maxEmails);
|
|
2380
|
+
const events = [];
|
|
2381
|
+
const recipientCounts = /* @__PURE__ */ new Map();
|
|
2382
|
+
const PARALLEL = 5;
|
|
2383
|
+
for (let i = 0; i < ids.length; i += PARALLEL) {
|
|
2384
|
+
const chunk = ids.slice(i, i + PARALLEL);
|
|
2385
|
+
const results = await Promise.all(
|
|
2386
|
+
chunk.map(
|
|
2387
|
+
(m) => fetch(
|
|
2388
|
+
`https://gmail.googleapis.com/gmail/v1/users/me/messages/${m.id}?format=metadata&metadataHeaders=From&metadataHeaders=To&metadataHeaders=Subject&metadataHeaders=Date`,
|
|
2389
|
+
{ headers: { Authorization: `Bearer ${token}` } }
|
|
2390
|
+
).then((r) => r.ok ? r.json() : null).catch(() => null)
|
|
2391
|
+
)
|
|
2392
|
+
);
|
|
2393
|
+
for (const msg of results) {
|
|
2394
|
+
if (!msg) continue;
|
|
2395
|
+
const headers = msg.payload?.headers || [];
|
|
2396
|
+
const header = (n) => headers.find((h) => h.name.toLowerCase() === n.toLowerCase())?.value ?? "";
|
|
2397
|
+
const subject = header("Subject") || "(no subject)";
|
|
2398
|
+
const to = header("To");
|
|
2399
|
+
const dateHdr = header("Date");
|
|
2400
|
+
const timestamp = dateHdr ? new Date(dateHdr).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
|
|
2401
|
+
const snippet = msg.snippet ?? "";
|
|
2402
|
+
const recipients = parseAddressList(to);
|
|
2403
|
+
for (const r of recipients) {
|
|
2404
|
+
recipientCounts.set(r, (recipientCounts.get(r) ?? 0) + 1);
|
|
2405
|
+
}
|
|
2406
|
+
events.push({
|
|
2407
|
+
id: `gmail-${msg.id}`,
|
|
2408
|
+
timestamp,
|
|
2409
|
+
actor: {
|
|
2410
|
+
id: leaderEmail ?? "leader",
|
|
2411
|
+
kind: "human",
|
|
2412
|
+
name: leaderEmail ?? "Leader"
|
|
2413
|
+
},
|
|
2414
|
+
kind: "email_sent",
|
|
2415
|
+
content: `${subject} \u2014 ${snippet.slice(0, 200)}`,
|
|
2416
|
+
metadata: {
|
|
2417
|
+
to: recipients.slice(0, 5),
|
|
2418
|
+
subject
|
|
2419
|
+
}
|
|
2420
|
+
});
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
const topRecipients = [...recipientCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10).map(([addr]) => addr);
|
|
2424
|
+
return [
|
|
2425
|
+
events,
|
|
2426
|
+
{
|
|
2427
|
+
emailsSent: events.length,
|
|
2428
|
+
uniqueRecipients: recipientCounts.size,
|
|
2429
|
+
topRecipients
|
|
2430
|
+
}
|
|
2431
|
+
];
|
|
2432
|
+
}
|
|
2433
|
+
function parseAddressList(raw) {
|
|
2434
|
+
if (!raw) return [];
|
|
2435
|
+
return raw.split(",").map((a) => {
|
|
2436
|
+
const match = a.match(/<([^>]+)>/);
|
|
2437
|
+
const addr = (match ? match[1] : a).trim().toLowerCase();
|
|
2438
|
+
return addr;
|
|
2439
|
+
}).filter((a) => a.includes("@") && a.length < 100);
|
|
2440
|
+
}
|
|
2441
|
+
async function fetchCalendarEvents(token, since, maxEvents, leaderEmail) {
|
|
2442
|
+
const timeMin = since.toISOString();
|
|
2443
|
+
const timeMax = (/* @__PURE__ */ new Date()).toISOString();
|
|
2444
|
+
const url = new URL("https://www.googleapis.com/calendar/v3/calendars/primary/events");
|
|
2445
|
+
url.searchParams.set("timeMin", timeMin);
|
|
2446
|
+
url.searchParams.set("timeMax", timeMax);
|
|
2447
|
+
url.searchParams.set("singleEvents", "true");
|
|
2448
|
+
url.searchParams.set("orderBy", "startTime");
|
|
2449
|
+
url.searchParams.set("maxResults", String(Math.min(maxEvents, 250)));
|
|
2450
|
+
const res = await fetch(url.toString(), {
|
|
2451
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
2452
|
+
});
|
|
2453
|
+
if (!res.ok) {
|
|
2454
|
+
throw new Error(`Calendar list failed ${res.status}: ${(await res.text()).slice(0, 200)}`);
|
|
2455
|
+
}
|
|
2456
|
+
const json = await res.json();
|
|
2457
|
+
const events = [];
|
|
2458
|
+
const attendeeSet = /* @__PURE__ */ new Set();
|
|
2459
|
+
let totalMinutes = 0;
|
|
2460
|
+
let meetingsOrganized = 0;
|
|
2461
|
+
const attendeeCounts = [];
|
|
2462
|
+
for (const ev of json.items ?? []) {
|
|
2463
|
+
if (ev.status === "cancelled") continue;
|
|
2464
|
+
const start = ev.start?.dateTime || ev.start?.date;
|
|
2465
|
+
const end = ev.end?.dateTime || ev.end?.date;
|
|
2466
|
+
if (!start) continue;
|
|
2467
|
+
const startMs = new Date(start).getTime();
|
|
2468
|
+
const endMs = end ? new Date(end).getTime() : startMs;
|
|
2469
|
+
const minutes = Math.max(0, Math.round((endMs - startMs) / 6e4));
|
|
2470
|
+
totalMinutes += minutes;
|
|
2471
|
+
const attendees = (ev.attendees ?? []).map((a) => a.email?.toLowerCase()).filter((e) => !!e && e.includes("@"));
|
|
2472
|
+
for (const a of attendees) attendeeSet.add(a);
|
|
2473
|
+
attendeeCounts.push(attendees.length);
|
|
2474
|
+
const organizedByLeader = leaderEmail && ev.organizer?.email?.toLowerCase() === leaderEmail;
|
|
2475
|
+
if (organizedByLeader) meetingsOrganized++;
|
|
2476
|
+
events.push({
|
|
2477
|
+
id: `gcal-${ev.id}`,
|
|
2478
|
+
timestamp: start,
|
|
2479
|
+
actor: {
|
|
2480
|
+
id: leaderEmail ?? "leader",
|
|
2481
|
+
kind: "human",
|
|
2482
|
+
name: leaderEmail ?? "Leader"
|
|
2483
|
+
},
|
|
2484
|
+
kind: organizedByLeader ? "meeting_organized" : "meeting_attended",
|
|
2485
|
+
content: `${ev.summary ?? "(no title)"} \u2014 ${minutes}min, ${attendees.length} attendees`,
|
|
2486
|
+
metadata: {
|
|
2487
|
+
attendees: attendees.slice(0, 10),
|
|
2488
|
+
minutes,
|
|
2489
|
+
organizer: ev.organizer?.email
|
|
2490
|
+
}
|
|
2491
|
+
});
|
|
2492
|
+
}
|
|
2493
|
+
const avgAttendees = attendeeCounts.length > 0 ? Math.round(
|
|
2494
|
+
attendeeCounts.reduce((a, b) => a + b, 0) / attendeeCounts.length
|
|
2495
|
+
) : null;
|
|
2496
|
+
return [
|
|
2497
|
+
events,
|
|
2498
|
+
{
|
|
2499
|
+
meetingsHeld: events.length,
|
|
2500
|
+
meetingsOrganized,
|
|
2501
|
+
uniqueAttendees: attendeeSet.size,
|
|
2502
|
+
totalMeetingMinutes: totalMinutes,
|
|
2503
|
+
avgMeetingAttendees: avgAttendees
|
|
2504
|
+
}
|
|
2505
|
+
];
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
// src/radiant/adapters/salesforce.ts
|
|
2509
|
+
async function fetchSalesforceActivity(options) {
|
|
2510
|
+
const windowDays = options.windowDays ?? 14;
|
|
2511
|
+
const maxRecords = Math.min(options.maxRecords ?? 200, 200);
|
|
2512
|
+
const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
|
|
2513
|
+
const sinceSoql = since.toISOString();
|
|
2514
|
+
const events = [];
|
|
2515
|
+
const signals = {
|
|
2516
|
+
opportunitiesMoved: 0,
|
|
2517
|
+
stageTransitions: 0,
|
|
2518
|
+
amountChanges: 0,
|
|
2519
|
+
closedWon: 0,
|
|
2520
|
+
closedLost: 0,
|
|
2521
|
+
tasksLogged: 0,
|
|
2522
|
+
callsLogged: 0,
|
|
2523
|
+
feedPostsByLeader: 0,
|
|
2524
|
+
totalPipelineAmount: 0,
|
|
2525
|
+
topStages: []
|
|
2526
|
+
};
|
|
2527
|
+
const opps = await soqlQuery(
|
|
2528
|
+
options,
|
|
2529
|
+
`SELECT Id, Name, StageName, Amount, CloseDate, IsClosed, IsWon, LastModifiedDate, Owner.Name
|
|
2530
|
+
FROM Opportunity
|
|
2531
|
+
WHERE LastModifiedDate >= ${sinceSoql}
|
|
2532
|
+
ORDER BY LastModifiedDate DESC
|
|
2533
|
+
LIMIT ${maxRecords}`
|
|
2534
|
+
);
|
|
2535
|
+
const stageCounts = /* @__PURE__ */ new Map();
|
|
2536
|
+
for (const opp of opps) {
|
|
2537
|
+
signals.opportunitiesMoved++;
|
|
2538
|
+
signals.totalPipelineAmount += opp.Amount ?? 0;
|
|
2539
|
+
stageCounts.set(opp.StageName, (stageCounts.get(opp.StageName) ?? 0) + 1);
|
|
2540
|
+
if (opp.IsClosed && opp.IsWon) signals.closedWon++;
|
|
2541
|
+
if (opp.IsClosed && !opp.IsWon) signals.closedLost++;
|
|
2542
|
+
events.push({
|
|
2543
|
+
id: `sf-opp-${opp.Id}`,
|
|
2544
|
+
timestamp: opp.LastModifiedDate,
|
|
2545
|
+
actor: {
|
|
2546
|
+
id: opp.Owner?.Name ?? "unknown",
|
|
2547
|
+
kind: "human",
|
|
2548
|
+
name: opp.Owner?.Name ?? "unknown"
|
|
2549
|
+
},
|
|
2550
|
+
kind: opp.IsClosed ? opp.IsWon ? "deal_won" : "deal_lost" : "deal_updated",
|
|
2551
|
+
content: `${opp.Name} \u2014 ${opp.StageName}${opp.Amount ? ` \xB7 $${Math.round(opp.Amount).toLocaleString()}` : ""} \xB7 close ${opp.CloseDate}`,
|
|
2552
|
+
metadata: {
|
|
2553
|
+
opportunityId: opp.Id,
|
|
2554
|
+
stage: opp.StageName,
|
|
2555
|
+
amount: opp.Amount,
|
|
2556
|
+
closeDate: opp.CloseDate
|
|
2557
|
+
}
|
|
2558
|
+
});
|
|
2559
|
+
}
|
|
2560
|
+
signals.topStages = [...stageCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([stage, count]) => ({ stage, count }));
|
|
2561
|
+
const history = await soqlQuery(
|
|
2562
|
+
options,
|
|
2563
|
+
`SELECT Id, OpportunityId, Field, OldValue, NewValue, CreatedDate, CreatedBy.Name
|
|
2564
|
+
FROM OpportunityFieldHistory
|
|
2565
|
+
WHERE CreatedDate >= ${sinceSoql} AND Field IN ('StageName', 'Amount', 'CloseDate')
|
|
2566
|
+
ORDER BY CreatedDate DESC
|
|
2567
|
+
LIMIT ${maxRecords}`
|
|
2568
|
+
).catch(() => []);
|
|
2569
|
+
for (const h of history) {
|
|
2570
|
+
if (h.Field === "StageName") signals.stageTransitions++;
|
|
2571
|
+
if (h.Field === "Amount") signals.amountChanges++;
|
|
2572
|
+
events.push({
|
|
2573
|
+
id: `sf-hist-${h.Id}`,
|
|
2574
|
+
timestamp: h.CreatedDate,
|
|
2575
|
+
actor: {
|
|
2576
|
+
id: h.CreatedBy?.Name ?? "unknown",
|
|
2577
|
+
kind: "human",
|
|
2578
|
+
name: h.CreatedBy?.Name ?? "unknown"
|
|
2579
|
+
},
|
|
2580
|
+
kind: `deal_${h.Field.toLowerCase()}_changed`,
|
|
2581
|
+
content: `${h.Field}: ${String(h.OldValue)} \u2192 ${String(h.NewValue)}`,
|
|
2582
|
+
metadata: {
|
|
2583
|
+
opportunityId: h.OpportunityId,
|
|
2584
|
+
field: h.Field
|
|
2585
|
+
}
|
|
2586
|
+
});
|
|
2587
|
+
}
|
|
2588
|
+
const tasks = await soqlQuery(
|
|
2589
|
+
options,
|
|
2590
|
+
`SELECT Id, Subject, Status, Type, CreatedDate, Owner.Name
|
|
2591
|
+
FROM Task
|
|
2592
|
+
WHERE CreatedDate >= ${sinceSoql}
|
|
2593
|
+
ORDER BY CreatedDate DESC
|
|
2594
|
+
LIMIT ${maxRecords}`
|
|
2595
|
+
).catch(() => []);
|
|
2596
|
+
for (const t of tasks) {
|
|
2597
|
+
signals.tasksLogged++;
|
|
2598
|
+
if (t.Type === "Call" || (t.Subject || "").toLowerCase().includes("call")) {
|
|
2599
|
+
signals.callsLogged++;
|
|
2600
|
+
}
|
|
2601
|
+
events.push({
|
|
2602
|
+
id: `sf-task-${t.Id}`,
|
|
2603
|
+
timestamp: t.CreatedDate,
|
|
2604
|
+
actor: {
|
|
2605
|
+
id: t.Owner?.Name ?? "unknown",
|
|
2606
|
+
kind: "human",
|
|
2607
|
+
name: t.Owner?.Name ?? "unknown"
|
|
2608
|
+
},
|
|
2609
|
+
kind: t.Type === "Call" ? "call_logged" : "task_logged",
|
|
2610
|
+
content: `${t.Subject} \u2014 ${t.Status}`,
|
|
2611
|
+
metadata: { taskId: t.Id, type: t.Type, status: t.Status }
|
|
2612
|
+
});
|
|
2613
|
+
}
|
|
2614
|
+
if (options.leaderName) {
|
|
2615
|
+
const feed = await soqlQuery(
|
|
2616
|
+
options,
|
|
2617
|
+
`SELECT Id, Body, CreatedDate, CreatedBy.Name, ParentId
|
|
2618
|
+
FROM FeedItem
|
|
2619
|
+
WHERE CreatedDate >= ${sinceSoql} AND CreatedBy.Name = '${escapeSoql(options.leaderName)}'
|
|
2620
|
+
ORDER BY CreatedDate DESC
|
|
2621
|
+
LIMIT ${Math.min(maxRecords, 50)}`
|
|
2622
|
+
).catch(() => []);
|
|
2623
|
+
for (const f of feed) {
|
|
2624
|
+
signals.feedPostsByLeader++;
|
|
2625
|
+
events.push({
|
|
2626
|
+
id: `sf-feed-${f.Id}`,
|
|
2627
|
+
timestamp: f.CreatedDate,
|
|
2628
|
+
actor: {
|
|
2629
|
+
id: f.CreatedBy?.Name ?? "unknown",
|
|
2630
|
+
kind: "human",
|
|
2631
|
+
name: f.CreatedBy?.Name ?? "unknown"
|
|
2632
|
+
},
|
|
2633
|
+
kind: "feed_post",
|
|
2634
|
+
content: (f.Body || "").slice(0, 280),
|
|
2635
|
+
metadata: { feedId: f.Id, parent: f.ParentId }
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
2640
|
+
return { events, signals };
|
|
2641
|
+
}
|
|
2642
|
+
function formatSalesforceSignalsForPrompt(signals) {
|
|
2643
|
+
if (signals.opportunitiesMoved === 0 && signals.tasksLogged === 0 && signals.stageTransitions === 0) {
|
|
2644
|
+
return "";
|
|
2645
|
+
}
|
|
2646
|
+
const lines = [
|
|
2647
|
+
"## Salesforce Activity (stated pipeline vs observed motion)",
|
|
2648
|
+
""
|
|
2649
|
+
];
|
|
2650
|
+
if (signals.opportunitiesMoved > 0) {
|
|
2651
|
+
const pipelineM = Math.round(signals.totalPipelineAmount / 1e4) / 100;
|
|
2652
|
+
lines.push(
|
|
2653
|
+
`${signals.opportunitiesMoved} opportunities touched in window ($${pipelineM}M total pipeline represented).`
|
|
2654
|
+
);
|
|
2655
|
+
lines.push(
|
|
2656
|
+
`${signals.stageTransitions} stage changes, ${signals.amountChanges} amount changes.`
|
|
2657
|
+
);
|
|
2658
|
+
if (signals.closedWon + signals.closedLost > 0) {
|
|
2659
|
+
lines.push(`${signals.closedWon} closed won, ${signals.closedLost} closed lost.`);
|
|
2660
|
+
}
|
|
2661
|
+
if (signals.topStages.length > 0) {
|
|
2662
|
+
lines.push(
|
|
2663
|
+
`Most active stages: ${signals.topStages.map((s) => `${s.stage} (${s.count})`).join(", ")}.`
|
|
2664
|
+
);
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
if (signals.tasksLogged > 0) {
|
|
2668
|
+
lines.push(
|
|
2669
|
+
`${signals.tasksLogged} tasks logged (${signals.callsLogged} calls).`
|
|
2670
|
+
);
|
|
2671
|
+
}
|
|
2672
|
+
if (signals.feedPostsByLeader > 0) {
|
|
2673
|
+
lines.push(`${signals.feedPostsByLeader} feed posts by the leader.`);
|
|
2674
|
+
}
|
|
2675
|
+
lines.push("");
|
|
2676
|
+
lines.push(
|
|
2677
|
+
"Salesforce shows what the team said would happen (stages, forecast) vs. what is actually happening (movement, activity, close)."
|
|
2678
|
+
);
|
|
2679
|
+
lines.push(
|
|
2680
|
+
"Compare stage transitions against stated strategy \u2014 are the deals the leader said would close actually moving, or is the pipeline drifting?"
|
|
2681
|
+
);
|
|
2682
|
+
return lines.join("\n");
|
|
2683
|
+
}
|
|
2684
|
+
async function soqlQuery(opts, query) {
|
|
2685
|
+
const url = new URL(`${opts.instanceUrl}/services/data/v59.0/query`);
|
|
2686
|
+
url.searchParams.set("q", query);
|
|
2687
|
+
const res = await fetch(url.toString(), {
|
|
2688
|
+
headers: { Authorization: `Bearer ${opts.accessToken}` }
|
|
2689
|
+
});
|
|
2690
|
+
if (!res.ok) {
|
|
2691
|
+
throw new Error(
|
|
2692
|
+
`Salesforce SOQL ${res.status}: ${(await res.text()).slice(0, 200)}`
|
|
2693
|
+
);
|
|
2694
|
+
}
|
|
2695
|
+
const json = await res.json();
|
|
2696
|
+
return json.records ?? [];
|
|
2697
|
+
}
|
|
2698
|
+
function escapeSoql(raw) {
|
|
2699
|
+
return raw.replace(/['\\]/g, "");
|
|
2700
|
+
}
|
|
2701
|
+
|
|
2299
2702
|
// src/radiant/core/vocabulary.ts
|
|
2300
2703
|
function extractDeclaredVocabulary(worldmodelContent) {
|
|
2301
2704
|
const aligned = extractSection(worldmodelContent, "Aligned Behaviors").map(
|
|
@@ -3560,8 +3963,26 @@ function isExternalScope(scope) {
|
|
|
3560
3963
|
];
|
|
3561
3964
|
return !internalPatterns.some((p) => p.test(scope));
|
|
3562
3965
|
}
|
|
3563
|
-
var MAX_INPUT_LENGTH = 1e5;
|
|
3564
3966
|
function evaluateGuard(event, world, options = {}) {
|
|
3967
|
+
const verdict = evaluateGuardCore(event, world, options);
|
|
3968
|
+
return options.mode === "observe" ? toShadowVerdict(verdict) : verdict;
|
|
3969
|
+
}
|
|
3970
|
+
function toShadowVerdict(verdict) {
|
|
3971
|
+
if (verdict.status === "ALLOW") return verdict;
|
|
3972
|
+
return {
|
|
3973
|
+
...verdict,
|
|
3974
|
+
status: "ALLOW",
|
|
3975
|
+
shadowStatus: verdict.status,
|
|
3976
|
+
shadowReason: verdict.reason,
|
|
3977
|
+
// Preserve the original reason as shadowReason and wipe the
|
|
3978
|
+
// top-level reason so callers that display `reason` for BLOCK/PAUSE
|
|
3979
|
+
// don't accidentally surface an enforcement message.
|
|
3980
|
+
reason: void 0,
|
|
3981
|
+
warning: verdict.reason ? `Observe mode: would have ${verdict.status.toLowerCase()} \u2014 ${verdict.reason}` : `Observe mode: would have ${verdict.status.toLowerCase()}`
|
|
3982
|
+
};
|
|
3983
|
+
}
|
|
3984
|
+
var MAX_INPUT_LENGTH = 1e5;
|
|
3985
|
+
function evaluateGuardCore(event, world, options = {}) {
|
|
3565
3986
|
const startTime = performance.now();
|
|
3566
3987
|
const level = options.level ?? "standard";
|
|
3567
3988
|
const includeTrace = options.trace ?? false;
|
|
@@ -4451,6 +4872,7 @@ async function auditGovernance(events, worldPath) {
|
|
|
4451
4872
|
return emptyAudit(events.length, "Could not load compiled worldmodel for governance audit.");
|
|
4452
4873
|
}
|
|
4453
4874
|
const verdicts = [];
|
|
4875
|
+
const crossings = [];
|
|
4454
4876
|
for (const ce of events) {
|
|
4455
4877
|
const intent = ce.event.content?.slice(0, 500) || ce.event.kind || "activity";
|
|
4456
4878
|
const scope = ce.event.metadata?.scope || void 0;
|
|
@@ -4461,16 +4883,32 @@ async function auditGovernance(events, worldPath) {
|
|
|
4461
4883
|
scope,
|
|
4462
4884
|
actionCategory: mapKindToCategory(ce.event.kind)
|
|
4463
4885
|
},
|
|
4464
|
-
world
|
|
4886
|
+
world,
|
|
4887
|
+
{ mode: "observe" }
|
|
4465
4888
|
);
|
|
4889
|
+
const shadow = result.shadowStatus ?? "ALLOW";
|
|
4466
4890
|
verdicts.push({
|
|
4467
4891
|
eventId: ce.event.id,
|
|
4468
4892
|
domain: ce.domain,
|
|
4469
|
-
status:
|
|
4470
|
-
reason: result.
|
|
4893
|
+
status: shadow,
|
|
4894
|
+
reason: result.shadowReason,
|
|
4471
4895
|
ruleId: result.ruleId,
|
|
4472
4896
|
warning: result.warning
|
|
4473
4897
|
});
|
|
4898
|
+
if (shadow !== "ALLOW") {
|
|
4899
|
+
crossings.push({
|
|
4900
|
+
eventId: ce.event.id,
|
|
4901
|
+
timestamp: ce.event.timestamp,
|
|
4902
|
+
kind: ce.event.kind,
|
|
4903
|
+
actorId: ce.event.actor.id,
|
|
4904
|
+
shadowStatus: shadow,
|
|
4905
|
+
shadowReason: result.shadowReason,
|
|
4906
|
+
ruleId: result.ruleId,
|
|
4907
|
+
excerpt: intent.length > 280 ? intent.slice(0, 279) + "\u2026" : intent,
|
|
4908
|
+
wouldHaveBlocked: true,
|
|
4909
|
+
verdict: result
|
|
4910
|
+
});
|
|
4911
|
+
}
|
|
4474
4912
|
} catch {
|
|
4475
4913
|
verdicts.push({
|
|
4476
4914
|
eventId: ce.event.id,
|
|
@@ -4489,6 +4927,7 @@ async function auditGovernance(events, worldPath) {
|
|
|
4489
4927
|
human,
|
|
4490
4928
|
cyber,
|
|
4491
4929
|
joint,
|
|
4930
|
+
crossings,
|
|
4492
4931
|
summary
|
|
4493
4932
|
};
|
|
4494
4933
|
}
|
|
@@ -4544,6 +4983,7 @@ function emptyAudit(total, reason) {
|
|
|
4544
4983
|
human: { allow: 0, modify: 0, block: 0, details: [] },
|
|
4545
4984
|
cyber: { allow: 0, modify: 0, block: 0, details: [] },
|
|
4546
4985
|
joint: { allow: 0, modify: 0, block: 0, details: [] },
|
|
4986
|
+
crossings: [],
|
|
4547
4987
|
summary: reason
|
|
4548
4988
|
};
|
|
4549
4989
|
}
|
|
@@ -4926,7 +5366,8 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
|
|
|
4926
5366
|
scores,
|
|
4927
5367
|
eventCount: events.length,
|
|
4928
5368
|
activeAdapters,
|
|
4929
|
-
worldStack
|
|
5369
|
+
worldStack,
|
|
5370
|
+
governance
|
|
4930
5371
|
};
|
|
4931
5372
|
}
|
|
4932
5373
|
function filterEventsByUser(events, username) {
|
|
@@ -5011,16 +5452,20 @@ var RADIANT_PACKAGE_VERSION = "0.0.0";
|
|
|
5011
5452
|
fetchDiscordActivity,
|
|
5012
5453
|
fetchGitHubActivity,
|
|
5013
5454
|
fetchGitHubOrgActivity,
|
|
5455
|
+
fetchGoogleWorkspaceActivity,
|
|
5014
5456
|
fetchLinearActivity,
|
|
5015
5457
|
fetchNotionActivity,
|
|
5458
|
+
fetchSalesforceActivity,
|
|
5016
5459
|
fetchSlackActivity,
|
|
5017
5460
|
filterEventsByUser,
|
|
5018
5461
|
formatActiveWorlds,
|
|
5019
5462
|
formatDiscordSignalsForPrompt,
|
|
5020
5463
|
formatExocortexForPrompt,
|
|
5464
|
+
formatGoogleWorkspaceSignalsForPrompt,
|
|
5021
5465
|
formatLinearSignalsForPrompt,
|
|
5022
5466
|
formatNotionSignalsForPrompt,
|
|
5023
5467
|
formatPriorReadsForPrompt,
|
|
5468
|
+
formatSalesforceSignalsForPrompt,
|
|
5024
5469
|
formatScope,
|
|
5025
5470
|
formatSlackSignalsForPrompt,
|
|
5026
5471
|
formatTeamExocorticesForPrompt,
|