@neuroverseos/governance 0.8.0 → 0.8.1
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/README.md +61 -9
- package/dist/{chunk-MC6O5GV5.js → chunk-ETDIEVAX.js} +766 -131
- package/dist/{chunk-VGFDMPVB.js → chunk-F2LWMOM5.js} +283 -1
- package/dist/cli/neuroverse.cjs +1500 -346
- package/dist/cli/radiant.cjs +1095 -217
- package/dist/cli/radiant.js +4 -4
- package/dist/cli/worldmodel.cjs +300 -21
- package/dist/cli/worldmodel.js +76 -1
- package/dist/{lenses-K5FVSALR.js → lenses-YDMKSXDL.js} +5 -3
- package/dist/radiant/index.cjs +654 -130
- package/dist/radiant/index.d.cts +136 -10
- package/dist/radiant/index.d.ts +136 -10
- package/dist/radiant/index.js +23 -397
- package/dist/{server-DFNY5N5A.js → server-ZSQ6DRSN.js} +2 -2
- package/dist/worldmodel-create-5SWHVNMQ.js +195 -0
- package/package.json +1 -1
package/dist/radiant/index.js
CHANGED
|
@@ -6,17 +6,29 @@ import {
|
|
|
6
6
|
classifyActorDomain,
|
|
7
7
|
classifyEvents,
|
|
8
8
|
composeSystemPrompt,
|
|
9
|
+
compressExocortex,
|
|
10
|
+
compressLens,
|
|
11
|
+
compressPriorReads,
|
|
12
|
+
compressWorldmodel,
|
|
9
13
|
computePersistence,
|
|
10
14
|
createAnthropicAI,
|
|
11
15
|
createMockAI,
|
|
12
16
|
createMockGitHubAdapter,
|
|
17
|
+
discoverWorlds,
|
|
13
18
|
emergent,
|
|
14
19
|
extractSignals,
|
|
20
|
+
fetchDiscordActivity,
|
|
15
21
|
fetchGitHubActivity,
|
|
16
22
|
fetchGitHubOrgActivity,
|
|
23
|
+
fetchNotionActivity,
|
|
24
|
+
fetchSlackActivity,
|
|
25
|
+
formatActiveWorlds,
|
|
26
|
+
formatDiscordSignalsForPrompt,
|
|
17
27
|
formatExocortexForPrompt,
|
|
28
|
+
formatNotionSignalsForPrompt,
|
|
18
29
|
formatPriorReadsForPrompt,
|
|
19
30
|
formatScope,
|
|
31
|
+
formatSlackSignalsForPrompt,
|
|
20
32
|
formatTeamExocorticesForPrompt,
|
|
21
33
|
interpretPatterns,
|
|
22
34
|
isPresent,
|
|
@@ -37,412 +49,19 @@ import {
|
|
|
37
49
|
think,
|
|
38
50
|
updateKnowledge,
|
|
39
51
|
writeRead
|
|
40
|
-
} from "../chunk-
|
|
52
|
+
} from "../chunk-ETDIEVAX.js";
|
|
41
53
|
import {
|
|
42
54
|
LENSES,
|
|
43
55
|
aukiBuilderLens,
|
|
44
56
|
getLens,
|
|
45
|
-
listLenses
|
|
46
|
-
|
|
57
|
+
listLenses,
|
|
58
|
+
sovereignConduitLens
|
|
59
|
+
} from "../chunk-F2LWMOM5.js";
|
|
47
60
|
import "../chunk-I4RTIMLX.js";
|
|
48
61
|
import "../chunk-ZAF6JH23.js";
|
|
49
62
|
import "../chunk-QLPTHTVB.js";
|
|
50
63
|
import "../chunk-QWGCMQQD.js";
|
|
51
64
|
|
|
52
|
-
// src/radiant/adapters/discord.ts
|
|
53
|
-
async function fetchDiscordActivity(guildId, token, options = {}) {
|
|
54
|
-
const windowDays = options.windowDays ?? 14;
|
|
55
|
-
const perChannel = options.perChannel ?? 100;
|
|
56
|
-
const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
|
|
57
|
-
const headers = {
|
|
58
|
-
Authorization: `Bot ${token}`,
|
|
59
|
-
"Content-Type": "application/json"
|
|
60
|
-
};
|
|
61
|
-
const channels = await fetchJSON(
|
|
62
|
-
`https://discord.com/api/v10/guilds/${guildId}/channels`,
|
|
63
|
-
headers
|
|
64
|
-
);
|
|
65
|
-
const textChannels = channels.filter((c) => {
|
|
66
|
-
if (c.type !== 0) return false;
|
|
67
|
-
if (options.channelIds && options.channelIds.length > 0) {
|
|
68
|
-
return options.channelIds.includes(c.id);
|
|
69
|
-
}
|
|
70
|
-
if (options.visibility === "public") {
|
|
71
|
-
return !c.name.startsWith("private-") && !c.nsfw;
|
|
72
|
-
}
|
|
73
|
-
return true;
|
|
74
|
-
});
|
|
75
|
-
const events = [];
|
|
76
|
-
let totalMessages = 0;
|
|
77
|
-
let helpRequests = 0;
|
|
78
|
-
let unresolvedThreads = 0;
|
|
79
|
-
let newcomerMessages = 0;
|
|
80
|
-
const responseTimes = [];
|
|
81
|
-
const participants = /* @__PURE__ */ new Set();
|
|
82
|
-
const knownParticipants = /* @__PURE__ */ new Set();
|
|
83
|
-
const topicCounts = /* @__PURE__ */ new Map();
|
|
84
|
-
for (const channel of textChannels.slice(0, 15)) {
|
|
85
|
-
try {
|
|
86
|
-
const messages = await fetchJSON(
|
|
87
|
-
`https://discord.com/api/v10/channels/${channel.id}/messages?limit=${perChannel}`,
|
|
88
|
-
headers
|
|
89
|
-
);
|
|
90
|
-
const inWindow = messages.filter(
|
|
91
|
-
(m) => new Date(m.timestamp) >= since
|
|
92
|
-
);
|
|
93
|
-
totalMessages += inWindow.length;
|
|
94
|
-
const topic = channel.name.replace(/-/g, " ");
|
|
95
|
-
topicCounts.set(topic, (topicCounts.get(topic) ?? 0) + inWindow.length);
|
|
96
|
-
for (const msg of inWindow) {
|
|
97
|
-
const actor = mapDiscordUser(msg.author);
|
|
98
|
-
participants.add(actor.id);
|
|
99
|
-
const lowerContent = msg.content.toLowerCase();
|
|
100
|
-
if (lowerContent.includes("help") || lowerContent.includes("stuck") || lowerContent.includes("how do i") || lowerContent.includes("anyone know")) {
|
|
101
|
-
helpRequests++;
|
|
102
|
-
}
|
|
103
|
-
if (msg.referenced_message) {
|
|
104
|
-
const refTime = new Date(msg.referenced_message.timestamp).getTime();
|
|
105
|
-
const msgTime = new Date(msg.timestamp).getTime();
|
|
106
|
-
const diffMinutes = (msgTime - refTime) / 6e4;
|
|
107
|
-
if (diffMinutes > 0 && diffMinutes < 10080) {
|
|
108
|
-
responseTimes.push(diffMinutes);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
events.push({
|
|
112
|
-
id: `discord-${msg.id}`,
|
|
113
|
-
timestamp: msg.timestamp,
|
|
114
|
-
actor,
|
|
115
|
-
kind: "discord_message",
|
|
116
|
-
content: msg.content.slice(0, 500),
|
|
117
|
-
respondsTo: msg.referenced_message ? {
|
|
118
|
-
eventId: `discord-${msg.referenced_message.id}`,
|
|
119
|
-
actor: mapDiscordUser(msg.referenced_message.author)
|
|
120
|
-
} : void 0,
|
|
121
|
-
metadata: {
|
|
122
|
-
channel: channel.name,
|
|
123
|
-
guildId
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
} catch {
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
const avgResponseMinutes = responseTimes.length > 0 ? responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length : null;
|
|
131
|
-
const topTopics = [...topicCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([t]) => t);
|
|
132
|
-
const signals = {
|
|
133
|
-
totalMessages,
|
|
134
|
-
activeChannels: textChannels.length,
|
|
135
|
-
uniqueParticipants: participants.size,
|
|
136
|
-
avgResponseMinutes: avgResponseMinutes ? Math.round(avgResponseMinutes) : null,
|
|
137
|
-
helpRequests,
|
|
138
|
-
unresolvedThreads,
|
|
139
|
-
topTopics,
|
|
140
|
-
newcomerMessages
|
|
141
|
-
};
|
|
142
|
-
events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
143
|
-
return { events, signals };
|
|
144
|
-
}
|
|
145
|
-
function formatDiscordSignalsForPrompt(signals) {
|
|
146
|
-
if (signals.totalMessages === 0) return "";
|
|
147
|
-
const lines = [
|
|
148
|
-
"## Discord Activity (conversational behavior)",
|
|
149
|
-
"",
|
|
150
|
-
`${signals.totalMessages} messages across ${signals.activeChannels} channels.`,
|
|
151
|
-
`${signals.uniqueParticipants} unique participants.`
|
|
152
|
-
];
|
|
153
|
-
if (signals.avgResponseMinutes !== null) {
|
|
154
|
-
lines.push(`Average response time: ${signals.avgResponseMinutes} minutes.`);
|
|
155
|
-
}
|
|
156
|
-
if (signals.helpRequests > 0) {
|
|
157
|
-
lines.push(`${signals.helpRequests} help requests detected.`);
|
|
158
|
-
}
|
|
159
|
-
if (signals.unresolvedThreads > 0) {
|
|
160
|
-
lines.push(`${signals.unresolvedThreads} unresolved threads.`);
|
|
161
|
-
}
|
|
162
|
-
if (signals.topTopics.length > 0) {
|
|
163
|
-
lines.push(`Top discussion topics: ${signals.topTopics.join(", ")}.`);
|
|
164
|
-
}
|
|
165
|
-
lines.push("");
|
|
166
|
-
lines.push("Compare conversational activity against GitHub shipping activity.");
|
|
167
|
-
lines.push("Where debates happen in Discord but nothing ships in GitHub, name the gap.");
|
|
168
|
-
lines.push("Where work ships in GitHub but nobody discusses it in Discord, name the visibility gap.");
|
|
169
|
-
return lines.join("\n");
|
|
170
|
-
}
|
|
171
|
-
function mapDiscordUser(user) {
|
|
172
|
-
return {
|
|
173
|
-
id: user.username,
|
|
174
|
-
kind: user.bot ? "bot" : "human",
|
|
175
|
-
name: user.username
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
async function fetchJSON(url, headers) {
|
|
179
|
-
const res = await fetch(url, { headers });
|
|
180
|
-
if (!res.ok) {
|
|
181
|
-
if (res.status === 404 || res.status === 403) return [];
|
|
182
|
-
throw new Error(`Discord API error ${res.status}: ${(await res.text()).slice(0, 300)}`);
|
|
183
|
-
}
|
|
184
|
-
return await res.json();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// src/radiant/adapters/slack.ts
|
|
188
|
-
async function fetchSlackActivity(token, options = {}) {
|
|
189
|
-
const windowDays = options.windowDays ?? 14;
|
|
190
|
-
const perChannel = options.perChannel ?? 100;
|
|
191
|
-
const oldest = String(
|
|
192
|
-
Math.floor((Date.now() - windowDays * 24 * 60 * 60 * 1e3) / 1e3)
|
|
193
|
-
);
|
|
194
|
-
const headers = {
|
|
195
|
-
Authorization: `Bearer ${token}`,
|
|
196
|
-
"Content-Type": "application/json"
|
|
197
|
-
};
|
|
198
|
-
const channelsResponse = await fetchSlackAPI("https://slack.com/api/conversations.list?types=public_channel&limit=200", headers);
|
|
199
|
-
let channels = channelsResponse.channels ?? [];
|
|
200
|
-
if (options.channelIds && options.channelIds.length > 0) {
|
|
201
|
-
const ids = new Set(options.channelIds);
|
|
202
|
-
channels = channels.filter((c) => ids.has(c.id));
|
|
203
|
-
}
|
|
204
|
-
if (options.visibility === "public") {
|
|
205
|
-
channels = channels.filter((c) => !c.is_private && !c.is_archived);
|
|
206
|
-
}
|
|
207
|
-
const events = [];
|
|
208
|
-
let totalMessages = 0;
|
|
209
|
-
let reactionCount = 0;
|
|
210
|
-
let unresolvedThreads = 0;
|
|
211
|
-
const responseTimes = [];
|
|
212
|
-
const participants = /* @__PURE__ */ new Set();
|
|
213
|
-
const externalParticipants = /* @__PURE__ */ new Set();
|
|
214
|
-
const channelMessageCounts = /* @__PURE__ */ new Map();
|
|
215
|
-
for (const channel of channels.slice(0, 15)) {
|
|
216
|
-
try {
|
|
217
|
-
const historyResponse = await fetchSlackAPI(
|
|
218
|
-
`https://slack.com/api/conversations.history?channel=${channel.id}&limit=${perChannel}&oldest=${oldest}`,
|
|
219
|
-
headers
|
|
220
|
-
);
|
|
221
|
-
const messages = historyResponse.messages ?? [];
|
|
222
|
-
totalMessages += messages.length;
|
|
223
|
-
channelMessageCounts.set(channel.name, messages.length);
|
|
224
|
-
for (const msg of messages) {
|
|
225
|
-
if (msg.subtype === "channel_join" || msg.subtype === "channel_leave") continue;
|
|
226
|
-
const actor = mapSlackUser(msg.user ?? "unknown");
|
|
227
|
-
participants.add(actor.id);
|
|
228
|
-
if (msg.reactions) {
|
|
229
|
-
reactionCount += msg.reactions.reduce(
|
|
230
|
-
(sum, r) => sum + (r.count ?? 0),
|
|
231
|
-
0
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
if (msg.thread_ts && msg.thread_ts !== msg.ts) {
|
|
235
|
-
const parentTs = parseFloat(msg.thread_ts) * 1e3;
|
|
236
|
-
const msgTs = parseFloat(msg.ts) * 1e3;
|
|
237
|
-
const diffMinutes = (msgTs - parentTs) / 6e4;
|
|
238
|
-
if (diffMinutes > 0 && diffMinutes < 10080) {
|
|
239
|
-
responseTimes.push(diffMinutes);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
if (msg.thread_ts === msg.ts && (!msg.reply_count || msg.reply_count === 0)) {
|
|
243
|
-
if (msg.text && (msg.text.includes("?") || msg.text.toLowerCase().includes("help"))) {
|
|
244
|
-
unresolvedThreads++;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
const timestamp = new Date(parseFloat(msg.ts) * 1e3).toISOString();
|
|
248
|
-
events.push({
|
|
249
|
-
id: `slack-${msg.ts}`,
|
|
250
|
-
timestamp,
|
|
251
|
-
actor,
|
|
252
|
-
kind: "slack_message",
|
|
253
|
-
content: (msg.text ?? "").slice(0, 500),
|
|
254
|
-
respondsTo: msg.thread_ts && msg.thread_ts !== msg.ts ? {
|
|
255
|
-
eventId: `slack-${msg.thread_ts}`,
|
|
256
|
-
actor: { id: "thread-parent", kind: "unknown" }
|
|
257
|
-
} : void 0,
|
|
258
|
-
metadata: {
|
|
259
|
-
channel: channel.name,
|
|
260
|
-
isPrivate: channel.is_private,
|
|
261
|
-
hasReactions: (msg.reactions?.length ?? 0) > 0
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
} catch {
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
const avgResponseMinutes = responseTimes.length > 0 ? Math.round(responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length) : null;
|
|
269
|
-
const topChannels = [...channelMessageCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([name]) => name);
|
|
270
|
-
const signals = {
|
|
271
|
-
totalMessages,
|
|
272
|
-
activeChannels: channelMessageCounts.size,
|
|
273
|
-
uniqueParticipants: participants.size,
|
|
274
|
-
avgResponseMinutes,
|
|
275
|
-
externalParticipants: externalParticipants.size,
|
|
276
|
-
unresolvedThreads,
|
|
277
|
-
topChannels,
|
|
278
|
-
reactionCount
|
|
279
|
-
};
|
|
280
|
-
events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
281
|
-
return { events, signals };
|
|
282
|
-
}
|
|
283
|
-
function formatSlackSignalsForPrompt(signals) {
|
|
284
|
-
if (signals.totalMessages === 0) return "";
|
|
285
|
-
const lines = [
|
|
286
|
-
"## Slack Activity (external coordination)",
|
|
287
|
-
"",
|
|
288
|
-
`${signals.totalMessages} messages across ${signals.activeChannels} channels.`,
|
|
289
|
-
`${signals.uniqueParticipants} unique participants.`
|
|
290
|
-
];
|
|
291
|
-
if (signals.avgResponseMinutes !== null) {
|
|
292
|
-
lines.push(`Average thread response time: ${signals.avgResponseMinutes} minutes.`);
|
|
293
|
-
}
|
|
294
|
-
if (signals.unresolvedThreads > 0) {
|
|
295
|
-
lines.push(`${signals.unresolvedThreads} questions/threads with no reply.`);
|
|
296
|
-
}
|
|
297
|
-
if (signals.reactionCount > 0) {
|
|
298
|
-
lines.push(`${signals.reactionCount} reactions (engagement signal).`);
|
|
299
|
-
}
|
|
300
|
-
if (signals.topChannels.length > 0) {
|
|
301
|
-
lines.push(`Most active channels: ${signals.topChannels.join(", ")}.`);
|
|
302
|
-
}
|
|
303
|
-
lines.push("");
|
|
304
|
-
lines.push("Slack carries external coordination \u2014 partner and client communication.");
|
|
305
|
-
lines.push("Compare partner engagement against internal activity. Where partners are");
|
|
306
|
-
lines.push("active but internal follow-through is low, name the gap.");
|
|
307
|
-
return lines.join("\n");
|
|
308
|
-
}
|
|
309
|
-
function mapSlackUser(userId) {
|
|
310
|
-
return {
|
|
311
|
-
id: userId,
|
|
312
|
-
kind: "human",
|
|
313
|
-
name: userId
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
async function fetchSlackAPI(url, headers) {
|
|
317
|
-
const res = await fetch(url, { headers });
|
|
318
|
-
if (!res.ok) {
|
|
319
|
-
throw new Error(`Slack API error ${res.status}: ${(await res.text()).slice(0, 300)}`);
|
|
320
|
-
}
|
|
321
|
-
const data = await res.json();
|
|
322
|
-
if (!data.ok) {
|
|
323
|
-
throw new Error(`Slack API error: ${data.error ?? "unknown"}`);
|
|
324
|
-
}
|
|
325
|
-
return data;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// src/radiant/adapters/notion.ts
|
|
329
|
-
async function fetchNotionActivity(token, options = {}) {
|
|
330
|
-
const windowDays = options.windowDays ?? 14;
|
|
331
|
-
const maxPages = options.maxPages ?? 100;
|
|
332
|
-
const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
|
|
333
|
-
const headers = {
|
|
334
|
-
Authorization: `Bearer ${token}`,
|
|
335
|
-
"Notion-Version": "2022-06-28",
|
|
336
|
-
"Content-Type": "application/json"
|
|
337
|
-
};
|
|
338
|
-
const searchResponse = await fetchNotionAPI("https://api.notion.com/v1/search", headers, {
|
|
339
|
-
method: "POST",
|
|
340
|
-
body: JSON.stringify({
|
|
341
|
-
filter: { property: "object", value: "page" },
|
|
342
|
-
sort: { direction: "descending", timestamp: "last_edited_time" },
|
|
343
|
-
page_size: maxPages
|
|
344
|
-
})
|
|
345
|
-
});
|
|
346
|
-
const pages = searchResponse.results ?? [];
|
|
347
|
-
const events = [];
|
|
348
|
-
const editors = /* @__PURE__ */ new Set();
|
|
349
|
-
let pagesCreated = 0;
|
|
350
|
-
let pagesUpdated = 0;
|
|
351
|
-
let stalePages = 0;
|
|
352
|
-
const editAges = [];
|
|
353
|
-
const topPages = [];
|
|
354
|
-
const now = Date.now();
|
|
355
|
-
for (const page of pages) {
|
|
356
|
-
const lastEdited = new Date(page.last_edited_time);
|
|
357
|
-
const created = new Date(page.created_time);
|
|
358
|
-
const daysSinceEdit = (now - lastEdited.getTime()) / (24 * 60 * 60 * 1e3);
|
|
359
|
-
editAges.push(daysSinceEdit);
|
|
360
|
-
if (daysSinceEdit > 30) stalePages++;
|
|
361
|
-
const title = extractTitle(page);
|
|
362
|
-
const editorId = page.last_edited_by?.id ?? "unknown";
|
|
363
|
-
editors.add(editorId);
|
|
364
|
-
if (lastEdited >= since) {
|
|
365
|
-
const isNew = created >= since;
|
|
366
|
-
if (isNew) pagesCreated++;
|
|
367
|
-
else pagesUpdated++;
|
|
368
|
-
topPages.push({ title, editedAt: page.last_edited_time });
|
|
369
|
-
events.push({
|
|
370
|
-
id: `notion-${page.id}`,
|
|
371
|
-
timestamp: page.last_edited_time,
|
|
372
|
-
actor: {
|
|
373
|
-
id: editorId,
|
|
374
|
-
kind: "human",
|
|
375
|
-
name: editorId
|
|
376
|
-
},
|
|
377
|
-
kind: isNew ? "doc_created" : "doc_updated",
|
|
378
|
-
content: `${isNew ? "Created" : "Updated"}: ${title}`,
|
|
379
|
-
metadata: {
|
|
380
|
-
pageId: page.id,
|
|
381
|
-
url: page.url,
|
|
382
|
-
createdAt: page.created_time
|
|
383
|
-
}
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
const avgDaysSinceEdit = editAges.length > 0 ? Math.round(editAges.reduce((a, b) => a + b, 0) / editAges.length) : null;
|
|
388
|
-
const signals = {
|
|
389
|
-
pagesActive: pagesCreated + pagesUpdated,
|
|
390
|
-
pagesCreated,
|
|
391
|
-
pagesUpdated,
|
|
392
|
-
uniqueEditors: editors.size,
|
|
393
|
-
stalePages,
|
|
394
|
-
avgDaysSinceEdit,
|
|
395
|
-
topPages: topPages.slice(0, 5).map((p) => p.title)
|
|
396
|
-
};
|
|
397
|
-
events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
398
|
-
return { events, signals };
|
|
399
|
-
}
|
|
400
|
-
function formatNotionSignalsForPrompt(signals) {
|
|
401
|
-
if (signals.pagesActive === 0 && signals.stalePages === 0) return "";
|
|
402
|
-
const lines = [
|
|
403
|
-
"## Notion Activity (documentation behavior)",
|
|
404
|
-
"",
|
|
405
|
-
`${signals.pagesActive} pages active in window (${signals.pagesCreated} created, ${signals.pagesUpdated} updated).`,
|
|
406
|
-
`${signals.uniqueEditors} unique editors.`
|
|
407
|
-
];
|
|
408
|
-
if (signals.stalePages > 0) {
|
|
409
|
-
lines.push(`${signals.stalePages} pages haven't been touched in 30+ days.`);
|
|
410
|
-
}
|
|
411
|
-
if (signals.avgDaysSinceEdit !== null) {
|
|
412
|
-
lines.push(`Average page age since last edit: ${signals.avgDaysSinceEdit} days.`);
|
|
413
|
-
}
|
|
414
|
-
if (signals.topPages.length > 0) {
|
|
415
|
-
lines.push(`Recently active pages: ${signals.topPages.join(", ")}.`);
|
|
416
|
-
}
|
|
417
|
-
lines.push("");
|
|
418
|
-
lines.push("Documentation is how the team crystallizes and shares knowledge.");
|
|
419
|
-
lines.push("High code velocity + low documentation = building without recording.");
|
|
420
|
-
lines.push("High documentation + low code = planning without shipping.");
|
|
421
|
-
lines.push("Compare Notion activity against GitHub and Discord to find the balance.");
|
|
422
|
-
return lines.join("\n");
|
|
423
|
-
}
|
|
424
|
-
function extractTitle(page) {
|
|
425
|
-
for (const prop of Object.values(page.properties)) {
|
|
426
|
-
if (prop.type === "title" && prop.title) {
|
|
427
|
-
return prop.title.map((t) => t.plain_text).join("") || "Untitled";
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
return "Untitled";
|
|
431
|
-
}
|
|
432
|
-
async function fetchNotionAPI(url, headers, init) {
|
|
433
|
-
const res = await fetch(url, {
|
|
434
|
-
method: init?.method ?? "GET",
|
|
435
|
-
headers,
|
|
436
|
-
body: init?.body
|
|
437
|
-
});
|
|
438
|
-
if (!res.ok) {
|
|
439
|
-
throw new Error(
|
|
440
|
-
`Notion API error ${res.status}: ${(await res.text()).slice(0, 300)}`
|
|
441
|
-
);
|
|
442
|
-
}
|
|
443
|
-
return await res.json();
|
|
444
|
-
}
|
|
445
|
-
|
|
446
65
|
// src/radiant/index.ts
|
|
447
66
|
var RADIANT_PACKAGE_VERSION = "0.0.0";
|
|
448
67
|
export {
|
|
@@ -456,10 +75,15 @@ export {
|
|
|
456
75
|
classifyActorDomain,
|
|
457
76
|
classifyEvents,
|
|
458
77
|
composeSystemPrompt,
|
|
78
|
+
compressExocortex,
|
|
79
|
+
compressLens,
|
|
80
|
+
compressPriorReads,
|
|
81
|
+
compressWorldmodel,
|
|
459
82
|
computePersistence,
|
|
460
83
|
createAnthropicAI,
|
|
461
84
|
createMockAI,
|
|
462
85
|
createMockGitHubAdapter,
|
|
86
|
+
discoverWorlds,
|
|
463
87
|
emergent,
|
|
464
88
|
extractSignals,
|
|
465
89
|
fetchDiscordActivity,
|
|
@@ -467,6 +91,7 @@ export {
|
|
|
467
91
|
fetchGitHubOrgActivity,
|
|
468
92
|
fetchNotionActivity,
|
|
469
93
|
fetchSlackActivity,
|
|
94
|
+
formatActiveWorlds,
|
|
470
95
|
formatDiscordSignalsForPrompt,
|
|
471
96
|
formatExocortexForPrompt,
|
|
472
97
|
formatNotionSignalsForPrompt,
|
|
@@ -491,6 +116,7 @@ export {
|
|
|
491
116
|
scoreCyber,
|
|
492
117
|
scoreLife,
|
|
493
118
|
scoreNeuroVerse,
|
|
119
|
+
sovereignConduitLens,
|
|
494
120
|
summarizeExocortex,
|
|
495
121
|
think,
|
|
496
122
|
updateKnowledge,
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
emergent,
|
|
4
4
|
parseRepoScope,
|
|
5
5
|
think
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-ETDIEVAX.js";
|
|
7
|
+
import "./chunk-F2LWMOM5.js";
|
|
8
8
|
import "./chunk-I4RTIMLX.js";
|
|
9
9
|
import "./chunk-ZAF6JH23.js";
|
|
10
10
|
import "./chunk-QLPTHTVB.js";
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import "./chunk-QWGCMQQD.js";
|
|
2
|
+
|
|
3
|
+
// src/cli/worldmodel-create.ts
|
|
4
|
+
import { createInterface } from "readline";
|
|
5
|
+
import { writeFileSync } from "fs";
|
|
6
|
+
import { resolve } from "path";
|
|
7
|
+
var QUESTIONS = [
|
|
8
|
+
{
|
|
9
|
+
id: "name",
|
|
10
|
+
question: "What should we call this model? (Your name, your org, your project)",
|
|
11
|
+
placeholder: 'e.g., "Kirsten", "Auki", "My Startup"'
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: "mission",
|
|
15
|
+
question: "In one or two sentences \u2014 what does this system exist to do? Not a slogan. The real purpose.",
|
|
16
|
+
placeholder: 'e.g., "Protect human thinking while expanding cognitive capability through AI"'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "domains",
|
|
20
|
+
question: "What are the 2-3 big areas of focus? Not departments \u2014 the major kinds of work that matter most. Separate with commas.",
|
|
21
|
+
placeholder: 'e.g., "Safety and boundaries, Individual authority, AI as cognitive extension"'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "overlaps",
|
|
25
|
+
question: "When those areas work well TOGETHER, what does that feel like? Name a feeling for each pair.",
|
|
26
|
+
placeholder: 'e.g., "Safety + Authority = Trust, Authority + AI = Possibility"'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "center",
|
|
30
|
+
question: "When EVERYTHING is aligned \u2014 all areas working together \u2014 what does the system become? One name or phrase.",
|
|
31
|
+
placeholder: 'e.g., "The Sovereign Conduit", "Collective Vanguard Leader"'
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "nonnegotiables",
|
|
35
|
+
question: "What's absolutely non-negotiable? What would you walk away over? List a few.",
|
|
36
|
+
placeholder: 'e.g., "Humans retain authority over thinking. AI extends, never replaces. People can always leave."'
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "success",
|
|
40
|
+
question: `What does success look like in action? What would you point at and say "that's what I mean"?`,
|
|
41
|
+
placeholder: 'e.g., "Someone maintaining clear authorship of decisions even when AI contributed"'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "drift",
|
|
45
|
+
question: "What does drift look like? What would worry you if you saw it happening?",
|
|
46
|
+
placeholder: 'e.g., "Decision ownership quietly shifting to AI without explicit delegation"'
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "priorities",
|
|
50
|
+
question: 'When tradeoffs appear, what wins? Give a few "X over Y" pairs.',
|
|
51
|
+
placeholder: 'e.g., "Safety over speed, sovereignty over convenience, diversity over uniformity"'
|
|
52
|
+
}
|
|
53
|
+
];
|
|
54
|
+
async function askQuestions() {
|
|
55
|
+
const rl = createInterface({
|
|
56
|
+
input: process.stdin,
|
|
57
|
+
output: process.stderr
|
|
58
|
+
// questions to stderr so stdout stays clean
|
|
59
|
+
});
|
|
60
|
+
const answers = {};
|
|
61
|
+
process.stderr.write("\n");
|
|
62
|
+
process.stderr.write(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n");
|
|
63
|
+
process.stderr.write(" \u2551 NeuroVerseOS \u2014 Build your thinking constitution \u2551\n");
|
|
64
|
+
process.stderr.write(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
|
|
65
|
+
process.stderr.write("\n");
|
|
66
|
+
process.stderr.write(" Answer these questions in your own words.\n");
|
|
67
|
+
process.stderr.write(" There are no wrong answers \u2014 just say what you mean.\n");
|
|
68
|
+
process.stderr.write(" The AI will structure your answers into a worldmodel.\n\n");
|
|
69
|
+
for (const q of QUESTIONS) {
|
|
70
|
+
const answer = await new Promise((resolve2) => {
|
|
71
|
+
process.stderr.write(` \x1B[1m${q.question}\x1B[0m
|
|
72
|
+
`);
|
|
73
|
+
process.stderr.write(` \x1B[2m${q.placeholder}\x1B[0m
|
|
74
|
+
`);
|
|
75
|
+
rl.question(" > ", (ans) => {
|
|
76
|
+
process.stderr.write("\n");
|
|
77
|
+
resolve2(ans.trim());
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
answers[q.id] = answer;
|
|
81
|
+
}
|
|
82
|
+
rl.close();
|
|
83
|
+
return answers;
|
|
84
|
+
}
|
|
85
|
+
async function structureWorldmodel(answers, apiKey) {
|
|
86
|
+
const prompt = buildStructuringPrompt(answers);
|
|
87
|
+
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
88
|
+
method: "POST",
|
|
89
|
+
headers: {
|
|
90
|
+
"x-api-key": apiKey,
|
|
91
|
+
"anthropic-version": "2023-06-01",
|
|
92
|
+
"content-type": "application/json"
|
|
93
|
+
},
|
|
94
|
+
body: JSON.stringify({
|
|
95
|
+
model: "claude-sonnet-4-20250514",
|
|
96
|
+
max_tokens: 4096,
|
|
97
|
+
system: "You are a behavioral model architect. You take conversational answers about an organization's values, purpose, and priorities, and structure them into a precise .worldmodel.md file that follows the NeuroVerseOS three-layer format. Output ONLY the markdown file content, nothing else.",
|
|
98
|
+
messages: [{ role: "user", content: prompt }]
|
|
99
|
+
})
|
|
100
|
+
});
|
|
101
|
+
if (!res.ok) {
|
|
102
|
+
throw new Error(`AI structuring failed: ${res.status}`);
|
|
103
|
+
}
|
|
104
|
+
const data = await res.json();
|
|
105
|
+
const text = data.content?.filter((c) => c.type === "text").map((c) => c.text ?? "").join("");
|
|
106
|
+
if (!text) throw new Error("AI returned no content");
|
|
107
|
+
return text.replace(/^```markdown\n?/, "").replace(/\n?```$/, "").trim();
|
|
108
|
+
}
|
|
109
|
+
function buildStructuringPrompt(answers) {
|
|
110
|
+
return `Structure these conversational answers into a .worldmodel.md file.
|
|
111
|
+
|
|
112
|
+
The file MUST follow this exact three-layer format:
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
name: ${answers.name}
|
|
116
|
+
version: 1.0.0
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
# Core Model Geometry
|
|
120
|
+
|
|
121
|
+
## Mission
|
|
122
|
+
(from the mission answer)
|
|
123
|
+
|
|
124
|
+
## Domains
|
|
125
|
+
(2-4 domains from the domains answer, each with:)
|
|
126
|
+
### Domain Name
|
|
127
|
+
#### Skills (8-10 skills per domain, inferred from the answers)
|
|
128
|
+
#### Values (3-4 values per domain, drawn from the non-negotiables + mission)
|
|
129
|
+
|
|
130
|
+
## Overlap Effects
|
|
131
|
+
(from the overlaps answer, formatted as: Domain A + Domain B = Emergent State)
|
|
132
|
+
|
|
133
|
+
## Center Identity
|
|
134
|
+
(from the center answer)
|
|
135
|
+
|
|
136
|
+
# Contextual Modifiers
|
|
137
|
+
|
|
138
|
+
## Authority Layers
|
|
139
|
+
(infer 4-5 authority levels appropriate to this organization)
|
|
140
|
+
|
|
141
|
+
## Spatial Contexts
|
|
142
|
+
(infer 4-5 contexts where behavior happens)
|
|
143
|
+
|
|
144
|
+
## Interpretation Rules
|
|
145
|
+
(infer 3-5 rules about how context changes meaning)
|
|
146
|
+
|
|
147
|
+
# Evolution Layer
|
|
148
|
+
|
|
149
|
+
## Aligned Behaviors
|
|
150
|
+
(from the success answer, expanded to 5-8 items)
|
|
151
|
+
|
|
152
|
+
## Drift Behaviors
|
|
153
|
+
(from the drift answer, expanded to 5-8 items)
|
|
154
|
+
|
|
155
|
+
## Signals
|
|
156
|
+
(infer 5-7 observable signals from the answers, snake_case)
|
|
157
|
+
|
|
158
|
+
## Decision Priorities
|
|
159
|
+
(from the priorities answer, formatted as: preferred > secondary)
|
|
160
|
+
|
|
161
|
+
## Evolution Conditions
|
|
162
|
+
(infer 3-5 conditions for when the model should adapt)
|
|
163
|
+
|
|
164
|
+
HERE ARE THE ANSWERS:
|
|
165
|
+
|
|
166
|
+
Name: ${answers.name}
|
|
167
|
+
|
|
168
|
+
Mission: ${answers.mission}
|
|
169
|
+
|
|
170
|
+
Domains: ${answers.domains}
|
|
171
|
+
|
|
172
|
+
Overlaps: ${answers.overlaps}
|
|
173
|
+
|
|
174
|
+
Center identity: ${answers.center}
|
|
175
|
+
|
|
176
|
+
Non-negotiables: ${answers.nonnegotiables}
|
|
177
|
+
|
|
178
|
+
Success looks like: ${answers.success}
|
|
179
|
+
|
|
180
|
+
Drift looks like: ${answers.drift}
|
|
181
|
+
|
|
182
|
+
Priorities: ${answers.priorities}
|
|
183
|
+
|
|
184
|
+
Output ONLY the .worldmodel.md content. No explanation. No commentary. Just the file.`;
|
|
185
|
+
}
|
|
186
|
+
function saveWorldmodel(content, outputPath) {
|
|
187
|
+
const resolved = resolve(outputPath);
|
|
188
|
+
writeFileSync(resolved, content, "utf-8");
|
|
189
|
+
return resolved;
|
|
190
|
+
}
|
|
191
|
+
export {
|
|
192
|
+
askQuestions,
|
|
193
|
+
saveWorldmodel,
|
|
194
|
+
structureWorldmodel
|
|
195
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neuroverseos/governance",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Deterministic governance engine for AI agents — enforce worlds (permanent rules) and plans (mission constraints) with full audit trace",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|