@neuroverseos/governance 0.7.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.
@@ -2002,10 +2002,10 @@ __export(world_loader_exports, {
2002
2002
  });
2003
2003
  async function loadWorldFromDirectory(dirPath) {
2004
2004
  const { readFile: readFile4 } = await import("fs/promises");
2005
- const { join: join18 } = await import("path");
2006
- const { readdirSync: readdirSync9 } = await import("fs");
2005
+ const { join: join19 } = await import("path");
2006
+ const { readdirSync: readdirSync11 } = await import("fs");
2007
2007
  async function readJson(filename) {
2008
- const filePath = join18(dirPath, filename);
2008
+ const filePath = join19(dirPath, filename);
2009
2009
  try {
2010
2010
  const content = await readFile4(filePath, "utf-8");
2011
2011
  return JSON.parse(content);
@@ -2035,11 +2035,11 @@ async function loadWorldFromDirectory(dirPath) {
2035
2035
  const metadataJson = await readJson("metadata.json");
2036
2036
  const rules = [];
2037
2037
  try {
2038
- const rulesDir = join18(dirPath, "rules");
2039
- const ruleFiles = readdirSync9(rulesDir).filter((f) => f.endsWith(".json")).sort();
2038
+ const rulesDir = join19(dirPath, "rules");
2039
+ const ruleFiles = readdirSync11(rulesDir).filter((f) => f.endsWith(".json")).sort();
2040
2040
  for (const file of ruleFiles) {
2041
2041
  try {
2042
- const content = await readFile4(join18(rulesDir, file), "utf-8");
2042
+ const content = await readFile4(join19(rulesDir, file), "utf-8");
2043
2043
  rules.push(JSON.parse(content));
2044
2044
  } catch (err) {
2045
2045
  process.stderr.write(
@@ -2093,8 +2093,8 @@ async function loadWorld(worldPath) {
2093
2093
  }
2094
2094
  async function loadBundledWorld(name = DEFAULT_BUNDLED_WORLD) {
2095
2095
  const { readFile: readFile4 } = await import("fs/promises");
2096
- const { join: join18, dirname: dirname4 } = await import("path");
2097
- const { existsSync: existsSync14 } = await import("fs");
2096
+ const { join: join19, dirname: dirname4 } = await import("path");
2097
+ const { existsSync: existsSync15 } = await import("fs");
2098
2098
  const { fileURLToPath: fileURLToPath3 } = await import("url");
2099
2099
  const { parseWorldMarkdown: parseWorldMarkdown2 } = await Promise.resolve().then(() => (init_bootstrap_parser(), bootstrap_parser_exports));
2100
2100
  const { emitWorldDefinition: emitWorldDefinition2 } = await Promise.resolve().then(() => (init_bootstrap_emitter(), bootstrap_emitter_exports));
@@ -2102,16 +2102,16 @@ async function loadBundledWorld(name = DEFAULT_BUNDLED_WORLD) {
2102
2102
  let packageRoot;
2103
2103
  try {
2104
2104
  const thisFile = typeof __dirname !== "undefined" ? __dirname : dirname4(fileURLToPath3(import_meta.url));
2105
- packageRoot = join18(thisFile, "..", "..");
2105
+ packageRoot = join19(thisFile, "..", "..");
2106
2106
  } catch {
2107
2107
  packageRoot = process.cwd();
2108
2108
  }
2109
2109
  const candidates = [
2110
- join18(packageRoot, "dist", "worlds", filename),
2111
- join18(packageRoot, "src", "worlds", filename)
2110
+ join19(packageRoot, "dist", "worlds", filename),
2111
+ join19(packageRoot, "src", "worlds", filename)
2112
2112
  ];
2113
2113
  for (const candidate of candidates) {
2114
- if (existsSync14(candidate)) {
2114
+ if (existsSync15(candidate)) {
2115
2115
  const markdown = await readFile4(candidate, "utf-8");
2116
2116
  const parsed = parseWorldMarkdown2(markdown);
2117
2117
  if (!parsed.world) {
@@ -2141,8 +2141,8 @@ function slugify(text) {
2141
2141
  }
2142
2142
  async function addGuard(worldDir, input) {
2143
2143
  const { readFile: readFile4, writeFile: writeFile6 } = await import("fs/promises");
2144
- const { join: join18 } = await import("path");
2145
- const guardsPath = join18(worldDir, "guards.json");
2144
+ const { join: join19 } = await import("path");
2145
+ const guardsPath = join19(worldDir, "guards.json");
2146
2146
  let config;
2147
2147
  try {
2148
2148
  const raw = await readFile4(guardsPath, "utf-8");
@@ -2182,13 +2182,13 @@ async function addGuard(worldDir, input) {
2182
2182
  }
2183
2183
  async function addRule(worldDir, input) {
2184
2184
  const { readFile: readFile4, writeFile: writeFile6, mkdir: mkdir3 } = await import("fs/promises");
2185
- const { join: join18 } = await import("path");
2186
- const { readdirSync: readdirSync9 } = await import("fs");
2187
- const rulesDir = join18(worldDir, "rules");
2185
+ const { join: join19 } = await import("path");
2186
+ const { readdirSync: readdirSync11 } = await import("fs");
2187
+ const rulesDir = join19(worldDir, "rules");
2188
2188
  await mkdir3(rulesDir, { recursive: true });
2189
2189
  let nextNum = 1;
2190
2190
  try {
2191
- const existing = readdirSync9(rulesDir).filter((f) => f.match(/^rule-\d+\.json$/)).sort();
2191
+ const existing = readdirSync11(rulesDir).filter((f) => f.match(/^rule-\d+\.json$/)).sort();
2192
2192
  if (existing.length > 0) {
2193
2193
  const lastFile = existing[existing.length - 1];
2194
2194
  const match = lastFile.match(/rule-(\d+)\.json/);
@@ -2214,7 +2214,7 @@ async function addRule(worldDir, input) {
2214
2214
  effect_text: input.effects ? input.effects.map((e) => `${e.target} ${e.operation} ${e.value}`).join(", ") : "No direct effects"
2215
2215
  }
2216
2216
  };
2217
- const rulePath = join18(rulesDir, `rule-${ruleNum}.json`);
2217
+ const rulePath = join19(rulesDir, `rule-${ruleNum}.json`);
2218
2218
  await writeFile6(rulePath, JSON.stringify(rule, null, 2) + "\n");
2219
2219
  const { loadWorldFromDirectory: loadWorldFromDirectory3 } = await Promise.resolve().then(() => (init_world_loader(), world_loader_exports));
2220
2220
  const world = await loadWorldFromDirectory3(worldDir);
@@ -2230,8 +2230,8 @@ async function addRule(worldDir, input) {
2230
2230
  }
2231
2231
  async function addInvariant(worldDir, input) {
2232
2232
  const { readFile: readFile4, writeFile: writeFile6 } = await import("fs/promises");
2233
- const { join: join18 } = await import("path");
2234
- const invariantsPath = join18(worldDir, "invariants.json");
2233
+ const { join: join19 } = await import("path");
2234
+ const invariantsPath = join19(worldDir, "invariants.json");
2235
2235
  let config;
2236
2236
  try {
2237
2237
  const raw = await readFile4(invariantsPath, "utf-8");
@@ -2849,27 +2849,27 @@ ${candidates.map((c) => ` - ${c}`).join("\n")}`
2849
2849
  }
2850
2850
  async function collectMarkdownSources(inputPath) {
2851
2851
  const { stat, readFile: rf, readdir } = await import("fs/promises");
2852
- const { join: pathJoin, extname: extname4, basename: basename4 } = await import("path");
2852
+ const { join: pathJoin, extname: extname4, basename: basename6 } = await import("path");
2853
2853
  const stats = await stat(inputPath);
2854
2854
  if (stats.isFile()) {
2855
2855
  const content = await rf(inputPath, "utf-8");
2856
- return [{ filename: basename4(inputPath), content }];
2856
+ return [{ filename: basename6(inputPath), content }];
2857
2857
  }
2858
2858
  if (stats.isDirectory()) {
2859
2859
  const sources = [];
2860
- await collectDir(inputPath, sources, rf, pathJoin, extname4, basename4);
2860
+ await collectDir(inputPath, sources, rf, pathJoin, extname4, basename6);
2861
2861
  sources.sort((a, b) => a.filename.localeCompare(b.filename));
2862
2862
  return sources;
2863
2863
  }
2864
2864
  throw new Error(`Input path is neither a file nor a directory: ${inputPath}`);
2865
2865
  }
2866
- async function collectDir(dir, sources, rf, pathJoin, extname4, basename4) {
2866
+ async function collectDir(dir, sources, rf, pathJoin, extname4, basename6) {
2867
2867
  const { readdir } = await import("fs/promises");
2868
2868
  const entries = await readdir(dir, { withFileTypes: true });
2869
2869
  for (const entry of entries) {
2870
2870
  const fullPath = pathJoin(dir, entry.name);
2871
2871
  if (entry.isDirectory()) {
2872
- await collectDir(fullPath, sources, rf, pathJoin, extname4, basename4);
2872
+ await collectDir(fullPath, sources, rf, pathJoin, extname4, basename6);
2873
2873
  } else if (entry.isFile() && extname4(entry.name).toLowerCase() === ".md") {
2874
2874
  const content = await rf(fullPath, "utf-8");
2875
2875
  sources.push({ filename: entry.name, content });
@@ -3528,21 +3528,21 @@ function parseArgs2(argv) {
3528
3528
  }
3529
3529
  async function writeWorldFiles(outputDir, world) {
3530
3530
  const { writeFile: writeFile6, mkdir: mkdir3 } = await import("fs/promises");
3531
- const { join: join18 } = await import("path");
3531
+ const { join: join19 } = await import("path");
3532
3532
  await mkdir3(outputDir, { recursive: true });
3533
- await writeFile6(join18(outputDir, "world.json"), JSON.stringify(world.world, null, 2));
3534
- await writeFile6(join18(outputDir, "invariants.json"), JSON.stringify({ invariants: world.invariants }, null, 2));
3535
- await writeFile6(join18(outputDir, "assumptions.json"), JSON.stringify(world.assumptions, null, 2));
3536
- await writeFile6(join18(outputDir, "state-schema.json"), JSON.stringify(world.stateSchema, null, 2));
3537
- await writeFile6(join18(outputDir, "gates.json"), JSON.stringify(world.gates, null, 2));
3538
- await writeFile6(join18(outputDir, "outcomes.json"), JSON.stringify(world.outcomes, null, 2));
3539
- await writeFile6(join18(outputDir, "metadata.json"), JSON.stringify(world.metadata, null, 2));
3540
- const rulesDir = join18(outputDir, "rules");
3533
+ await writeFile6(join19(outputDir, "world.json"), JSON.stringify(world.world, null, 2));
3534
+ await writeFile6(join19(outputDir, "invariants.json"), JSON.stringify({ invariants: world.invariants }, null, 2));
3535
+ await writeFile6(join19(outputDir, "assumptions.json"), JSON.stringify(world.assumptions, null, 2));
3536
+ await writeFile6(join19(outputDir, "state-schema.json"), JSON.stringify(world.stateSchema, null, 2));
3537
+ await writeFile6(join19(outputDir, "gates.json"), JSON.stringify(world.gates, null, 2));
3538
+ await writeFile6(join19(outputDir, "outcomes.json"), JSON.stringify(world.outcomes, null, 2));
3539
+ await writeFile6(join19(outputDir, "metadata.json"), JSON.stringify(world.metadata, null, 2));
3540
+ const rulesDir = join19(outputDir, "rules");
3541
3541
  await mkdir3(rulesDir, { recursive: true });
3542
3542
  const sortedRules = [...world.rules].sort((a, b) => a.order - b.order);
3543
3543
  for (let i = 0; i < sortedRules.length; i++) {
3544
3544
  const ruleNum = String(i + 1).padStart(3, "0");
3545
- await writeFile6(join18(rulesDir, `rule-${ruleNum}.json`), JSON.stringify(sortedRules[i], null, 2));
3545
+ await writeFile6(join19(rulesDir, `rule-${ruleNum}.json`), JSON.stringify(sortedRules[i], null, 2));
3546
3546
  }
3547
3547
  }
3548
3548
  function write(msg) {
@@ -3557,12 +3557,12 @@ function printInsight(finding2) {
3557
3557
  async function main2(argv = process.argv.slice(2)) {
3558
3558
  try {
3559
3559
  const args = parseArgs2(argv);
3560
- const { basename: basename4 } = await import("path");
3560
+ const { basename: basename6 } = await import("path");
3561
3561
  write(`
3562
3562
  NeuroVerse World Builder
3563
3563
  `);
3564
3564
  write(`
3565
- Analyzing: ${basename4(args.inputPath)}
3565
+ Analyzing: ${basename6(args.inputPath)}
3566
3566
  `);
3567
3567
  const derivedPath = args.outputDir ? `${args.outputDir}/source.nv-world.md` : ".neuroverse/build-output.nv-world.md";
3568
3568
  const { mkdir: mkdir3 } = await import("fs/promises");
@@ -3673,9 +3673,9 @@ World source written to: ${derivedPath}
3673
3673
  try {
3674
3674
  const emitResult = emitWorldDefinition(parseResult.world);
3675
3675
  await writeWorldFiles(outputDir, emitResult.world);
3676
- const { join: join18 } = await import("path");
3676
+ const { join: join19 } = await import("path");
3677
3677
  const { copyFile } = await import("fs/promises");
3678
- const sourceDest = join18(outputDir, "source.nv-world.md");
3678
+ const sourceDest = join19(outputDir, "source.nv-world.md");
3679
3679
  if (derivedPath !== sourceDest) {
3680
3680
  await copyFile(derivedPath, sourceDest);
3681
3681
  }
@@ -5009,8 +5009,8 @@ async function main6(argv = process.argv.slice(2)) {
5009
5009
  try {
5010
5010
  const args = parseArgs6(argv);
5011
5011
  const { writeFile: writeFile6 } = await import("fs/promises");
5012
- const { existsSync: existsSync14 } = await import("fs");
5013
- if (existsSync14(args.outputPath)) {
5012
+ const { existsSync: existsSync15 } = await import("fs");
5013
+ if (existsSync15(args.outputPath)) {
5014
5014
  process.stderr.write(`File already exists: ${args.outputPath}
5015
5015
  `);
5016
5016
  process.stderr.write("Use a different --output path or remove the existing file.\n");
@@ -5868,22 +5868,22 @@ function parseArgs9(argv) {
5868
5868
  }
5869
5869
  async function writeWorldFiles2(outputDir, world) {
5870
5870
  const { writeFile: writeFile6, mkdir: mkdir3 } = await import("fs/promises");
5871
- const { join: join18 } = await import("path");
5871
+ const { join: join19 } = await import("path");
5872
5872
  await mkdir3(outputDir, { recursive: true });
5873
- await writeFile6(join18(outputDir, "world.json"), JSON.stringify(world.world, null, 2));
5874
- await writeFile6(join18(outputDir, "invariants.json"), JSON.stringify({ invariants: world.invariants }, null, 2));
5875
- await writeFile6(join18(outputDir, "assumptions.json"), JSON.stringify(world.assumptions, null, 2));
5876
- await writeFile6(join18(outputDir, "state-schema.json"), JSON.stringify(world.stateSchema, null, 2));
5877
- const rulesDir = join18(outputDir, "rules");
5873
+ await writeFile6(join19(outputDir, "world.json"), JSON.stringify(world.world, null, 2));
5874
+ await writeFile6(join19(outputDir, "invariants.json"), JSON.stringify({ invariants: world.invariants }, null, 2));
5875
+ await writeFile6(join19(outputDir, "assumptions.json"), JSON.stringify(world.assumptions, null, 2));
5876
+ await writeFile6(join19(outputDir, "state-schema.json"), JSON.stringify(world.stateSchema, null, 2));
5877
+ const rulesDir = join19(outputDir, "rules");
5878
5878
  await mkdir3(rulesDir, { recursive: true });
5879
5879
  const sortedRules = [...world.rules].sort((a, b) => a.order - b.order);
5880
5880
  for (let i = 0; i < sortedRules.length; i++) {
5881
5881
  const ruleNum = String(i + 1).padStart(3, "0");
5882
- await writeFile6(join18(rulesDir, `rule-${ruleNum}.json`), JSON.stringify(sortedRules[i], null, 2));
5882
+ await writeFile6(join19(rulesDir, `rule-${ruleNum}.json`), JSON.stringify(sortedRules[i], null, 2));
5883
5883
  }
5884
- await writeFile6(join18(outputDir, "gates.json"), JSON.stringify(world.gates, null, 2));
5885
- await writeFile6(join18(outputDir, "outcomes.json"), JSON.stringify(world.outcomes, null, 2));
5886
- await writeFile6(join18(outputDir, "metadata.json"), JSON.stringify(world.metadata, null, 2));
5884
+ await writeFile6(join19(outputDir, "gates.json"), JSON.stringify(world.gates, null, 2));
5885
+ await writeFile6(join19(outputDir, "outcomes.json"), JSON.stringify(world.outcomes, null, 2));
5886
+ await writeFile6(join19(outputDir, "metadata.json"), JSON.stringify(world.metadata, null, 2));
5887
5887
  }
5888
5888
  async function main9(argv = process.argv.slice(2)) {
5889
5889
  const startTime = performance.now();
@@ -8242,13 +8242,13 @@ function handleHealthCheck() {
8242
8242
  }
8243
8243
  async function handleListPresets(policiesDir) {
8244
8244
  const { readdir, readFile: readFile4 } = await import("fs/promises");
8245
- const { join: join18 } = await import("path");
8246
- const dir = policiesDir ?? join18(process.cwd(), "policies");
8245
+ const { join: join19 } = await import("path");
8246
+ const dir = policiesDir ?? join19(process.cwd(), "policies");
8247
8247
  const presets = [];
8248
8248
  try {
8249
8249
  const files = await readdir(dir);
8250
8250
  for (const file of files.filter((f) => f.endsWith(".txt")).sort()) {
8251
- const content = await readFile4(join18(dir, file), "utf-8");
8251
+ const content = await readFile4(join19(dir, file), "utf-8");
8252
8252
  const id = file.replace(".txt", "");
8253
8253
  const name = id.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
8254
8254
  const firstLine = content.split("\n").find((l) => l.trim().length > 0) ?? "";
@@ -8320,7 +8320,7 @@ function govern(action, world, options) {
8320
8320
  }
8321
8321
  async function writeTempWorld(dir, policyLines) {
8322
8322
  const { writeFile: writeFile6, mkdir: mkdir3 } = await import("fs/promises");
8323
- const { join: join18 } = await import("path");
8323
+ const { join: join19 } = await import("path");
8324
8324
  await mkdir3(dir, { recursive: true });
8325
8325
  const worldJson = {
8326
8326
  world_id: "demo-live",
@@ -8362,9 +8362,9 @@ async function writeTempWorld(dir, policyLines) {
8362
8362
  authoring_method: "manual-authoring"
8363
8363
  };
8364
8364
  await Promise.all([
8365
- writeFile6(join18(dir, "world.json"), JSON.stringify(worldJson, null, 2)),
8366
- writeFile6(join18(dir, "kernel.json"), JSON.stringify(kernelJson, null, 2)),
8367
- writeFile6(join18(dir, "metadata.json"), JSON.stringify(metadataJson, null, 2))
8365
+ writeFile6(join19(dir, "world.json"), JSON.stringify(worldJson, null, 2)),
8366
+ writeFile6(join19(dir, "kernel.json"), JSON.stringify(kernelJson, null, 2)),
8367
+ writeFile6(join19(dir, "metadata.json"), JSON.stringify(metadataJson, null, 2))
8368
8368
  ]);
8369
8369
  }
8370
8370
  var init_govern = __esm({
@@ -8708,10 +8708,10 @@ data: ${data}
8708
8708
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
8709
8709
  }
8710
8710
  function readBody(req) {
8711
- return new Promise((resolve10, reject) => {
8711
+ return new Promise((resolve12, reject) => {
8712
8712
  const chunks = [];
8713
8713
  req.on("data", (chunk) => chunks.push(chunk));
8714
- req.on("end", () => resolve10(Buffer.concat(chunks).toString("utf-8")));
8714
+ req.on("end", () => resolve12(Buffer.concat(chunks).toString("utf-8")));
8715
8715
  req.on("error", reject);
8716
8716
  });
8717
8717
  }
@@ -11475,9 +11475,9 @@ async function main15(argv) {
11475
11475
  }
11476
11476
  if (worldPath) {
11477
11477
  try {
11478
- const { existsSync: existsSync14 } = await import("fs");
11479
- const { join: join18 } = await import("path");
11480
- const hasWorld = existsSync14(join18(worldPath, "world.json"));
11478
+ const { existsSync: existsSync15 } = await import("fs");
11479
+ const { join: join19 } = await import("path");
11480
+ const hasWorld = existsSync15(join19(worldPath, "world.json"));
11481
11481
  checks.push({
11482
11482
  label: "World file detected",
11483
11483
  status: hasWorld ? "pass" : "fail",
@@ -11492,12 +11492,12 @@ async function main15(argv) {
11492
11492
  });
11493
11493
  }
11494
11494
  } else {
11495
- const { existsSync: existsSync14 } = await import("fs");
11496
- const { join: join18 } = await import("path");
11495
+ const { existsSync: existsSync15 } = await import("fs");
11496
+ const { join: join19 } = await import("path");
11497
11497
  const candidates = ["./world", "./.neuroverse", "./worlds"];
11498
11498
  let found;
11499
11499
  for (const dir of candidates) {
11500
- if (existsSync14(join18(dir, "world.json"))) {
11500
+ if (existsSync15(join19(dir, "world.json"))) {
11501
11501
  found = dir;
11502
11502
  break;
11503
11503
  }
@@ -13148,7 +13148,7 @@ async function runPipeMode(config) {
13148
13148
  `);
13149
13149
  }
13150
13150
  const MAX_BUFFER_SIZE = 1e6;
13151
- return new Promise((resolve10, reject) => {
13151
+ return new Promise((resolve12, reject) => {
13152
13152
  let buffer = "";
13153
13153
  process.stdin.setEncoding("utf-8");
13154
13154
  process.stdin.on("data", (chunk) => {
@@ -13194,7 +13194,7 @@ async function runPipeMode(config) {
13194
13194
  `[neuroverse] Session complete: ${finalState.actionsEvaluated} evaluated, ${finalState.actionsAllowed} allowed, ${finalState.actionsBlocked} blocked, ${finalState.actionsPaused} paused
13195
13195
  `
13196
13196
  );
13197
- resolve10();
13197
+ resolve12();
13198
13198
  });
13199
13199
  process.stdin.on("error", reject);
13200
13200
  });
@@ -13310,8 +13310,8 @@ ${response.content}
13310
13310
  rl2.on("close", () => {
13311
13311
  session.stop();
13312
13312
  });
13313
- return new Promise((resolve10) => {
13314
- rl2.on("close", resolve10);
13313
+ return new Promise((resolve12) => {
13314
+ rl2.on("close", resolve12);
13315
13315
  });
13316
13316
  }
13317
13317
  var SessionManager;
@@ -14422,27 +14422,27 @@ function computeWorldDiff(a, b) {
14422
14422
  }
14423
14423
  async function worldSnapshot(worldPath) {
14424
14424
  const { readdir, readFile: readFile4, mkdir: mkdir3, writeFile: writeFile6 } = await import("fs/promises");
14425
- const { join: join18 } = await import("path");
14425
+ const { join: join19 } = await import("path");
14426
14426
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
14427
- const snapshotDir = join18(worldPath, ".snapshots", timestamp);
14427
+ const snapshotDir = join19(worldPath, ".snapshots", timestamp);
14428
14428
  await mkdir3(snapshotDir, { recursive: true });
14429
14429
  const files = await readdir(worldPath);
14430
14430
  let copied = 0;
14431
14431
  for (const file of files) {
14432
14432
  if (file.endsWith(".json")) {
14433
- const content = await readFile4(join18(worldPath, file), "utf-8");
14434
- await writeFile6(join18(snapshotDir, file), content, "utf-8");
14433
+ const content = await readFile4(join19(worldPath, file), "utf-8");
14434
+ await writeFile6(join19(snapshotDir, file), content, "utf-8");
14435
14435
  copied++;
14436
14436
  }
14437
14437
  }
14438
14438
  try {
14439
- const rulesDir = join18(worldPath, "rules");
14439
+ const rulesDir = join19(worldPath, "rules");
14440
14440
  const ruleFiles = await readdir(rulesDir);
14441
- await mkdir3(join18(snapshotDir, "rules"), { recursive: true });
14441
+ await mkdir3(join19(snapshotDir, "rules"), { recursive: true });
14442
14442
  for (const file of ruleFiles) {
14443
14443
  if (file.endsWith(".json")) {
14444
- const content = await readFile4(join18(rulesDir, file), "utf-8");
14445
- await writeFile6(join18(snapshotDir, "rules", file), content, "utf-8");
14444
+ const content = await readFile4(join19(rulesDir, file), "utf-8");
14445
+ await writeFile6(join19(snapshotDir, "rules", file), content, "utf-8");
14446
14446
  copied++;
14447
14447
  }
14448
14448
  }
@@ -14455,8 +14455,8 @@ async function worldSnapshot(worldPath) {
14455
14455
  }
14456
14456
  async function worldRollback(worldPath) {
14457
14457
  const { readdir, readFile: readFile4, writeFile: writeFile6, mkdir: mkdir3 } = await import("fs/promises");
14458
- const { join: join18 } = await import("path");
14459
- const snapshotsDir = join18(worldPath, ".snapshots");
14458
+ const { join: join19 } = await import("path");
14459
+ const snapshotsDir = join19(worldPath, ".snapshots");
14460
14460
  let snapshots;
14461
14461
  try {
14462
14462
  snapshots = (await readdir(snapshotsDir)).sort();
@@ -14471,34 +14471,34 @@ async function worldRollback(worldPath) {
14471
14471
  return;
14472
14472
  }
14473
14473
  const latest = snapshots[snapshots.length - 1];
14474
- const snapshotDir = join18(snapshotsDir, latest);
14474
+ const snapshotDir = join19(snapshotsDir, latest);
14475
14475
  const backupTimestamp = "pre-rollback-" + (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
14476
- const backupDir = join18(snapshotsDir, backupTimestamp);
14476
+ const backupDir = join19(snapshotsDir, backupTimestamp);
14477
14477
  await mkdir3(backupDir, { recursive: true });
14478
14478
  const currentFiles = await readdir(worldPath);
14479
14479
  for (const file of currentFiles) {
14480
14480
  if (file.endsWith(".json")) {
14481
- const content = await readFile4(join18(worldPath, file), "utf-8");
14482
- await writeFile6(join18(backupDir, file), content, "utf-8");
14481
+ const content = await readFile4(join19(worldPath, file), "utf-8");
14482
+ await writeFile6(join19(backupDir, file), content, "utf-8");
14483
14483
  }
14484
14484
  }
14485
14485
  const snapshotFiles = await readdir(snapshotDir);
14486
14486
  let restored = 0;
14487
14487
  for (const file of snapshotFiles) {
14488
14488
  if (file.endsWith(".json")) {
14489
- const content = await readFile4(join18(snapshotDir, file), "utf-8");
14490
- await writeFile6(join18(worldPath, file), content, "utf-8");
14489
+ const content = await readFile4(join19(snapshotDir, file), "utf-8");
14490
+ await writeFile6(join19(worldPath, file), content, "utf-8");
14491
14491
  restored++;
14492
14492
  }
14493
14493
  }
14494
14494
  try {
14495
- const rulesDir = join18(snapshotDir, "rules");
14495
+ const rulesDir = join19(snapshotDir, "rules");
14496
14496
  const ruleFiles = await readdir(rulesDir);
14497
- await mkdir3(join18(worldPath, "rules"), { recursive: true });
14497
+ await mkdir3(join19(worldPath, "rules"), { recursive: true });
14498
14498
  for (const file of ruleFiles) {
14499
14499
  if (file.endsWith(".json")) {
14500
- const content = await readFile4(join18(rulesDir, file), "utf-8");
14501
- await writeFile6(join18(worldPath, "rules", file), content, "utf-8");
14500
+ const content = await readFile4(join19(rulesDir, file), "utf-8");
14501
+ await writeFile6(join19(worldPath, "rules", file), content, "utf-8");
14502
14502
  restored++;
14503
14503
  }
14504
14504
  }
@@ -16400,27 +16400,27 @@ function closePrompts() {
16400
16400
  }
16401
16401
  function ask(question, defaultValue) {
16402
16402
  const suffix = defaultValue ? ` [${defaultValue}]` : "";
16403
- return new Promise((resolve10) => {
16403
+ return new Promise((resolve12) => {
16404
16404
  getRL().question(`
16405
16405
  ${question}${suffix}: `, (answer) => {
16406
16406
  const val = answer.trim();
16407
- resolve10(val || defaultValue || "");
16407
+ resolve12(val || defaultValue || "");
16408
16408
  });
16409
16409
  });
16410
16410
  }
16411
16411
  function confirm(question, defaultYes = true) {
16412
16412
  const hint = defaultYes ? "[Y/n]" : "[y/N]";
16413
- return new Promise((resolve10) => {
16413
+ return new Promise((resolve12) => {
16414
16414
  getRL().question(`
16415
16415
  ${question} ${hint}: `, (answer) => {
16416
16416
  const val = answer.trim().toLowerCase();
16417
- if (val === "") resolve10(defaultYes);
16418
- else resolve10(val === "y" || val === "yes");
16417
+ if (val === "") resolve12(defaultYes);
16418
+ else resolve12(val === "y" || val === "yes");
16419
16419
  });
16420
16420
  });
16421
16421
  }
16422
16422
  function choose(question, options) {
16423
- return new Promise((resolve10) => {
16423
+ return new Promise((resolve12) => {
16424
16424
  const r = getRL();
16425
16425
  r.write(`
16426
16426
  ${question}
@@ -16430,9 +16430,9 @@ function choose(question, options) {
16430
16430
  r.question(` Choice [1-${options.length}]: `, (answer) => {
16431
16431
  const idx = parseInt(answer.trim(), 10) - 1;
16432
16432
  if (idx >= 0 && idx < options.length) {
16433
- resolve10(options[idx]);
16433
+ resolve12(options[idx]);
16434
16434
  } else {
16435
- resolve10(options[0]);
16435
+ resolve12(options[0]);
16436
16436
  }
16437
16437
  });
16438
16438
  });
@@ -16901,15 +16901,15 @@ function generateWorld(state) {
16901
16901
  return { worldJson, stateSchema, guardsJson, rules, gatesJson, invariants, outcomes, metadata };
16902
16902
  }
16903
16903
  async function writeWorld(outputDir, world) {
16904
- const { mkdirSync: mkdirSync6, existsSync: existsSync14 } = await import("fs");
16904
+ const { mkdirSync: mkdirSync6, existsSync: existsSync15 } = await import("fs");
16905
16905
  const { writeFile: writeFile6 } = await import("fs/promises");
16906
- const { join: join18 } = await import("path");
16906
+ const { join: join19 } = await import("path");
16907
16907
  const files = [];
16908
- if (!existsSync14(outputDir)) mkdirSync6(outputDir, { recursive: true });
16909
- const rulesDir = join18(outputDir, "rules");
16910
- if (!existsSync14(rulesDir)) mkdirSync6(rulesDir, { recursive: true });
16908
+ if (!existsSync15(outputDir)) mkdirSync6(outputDir, { recursive: true });
16909
+ const rulesDir = join19(outputDir, "rules");
16910
+ if (!existsSync15(rulesDir)) mkdirSync6(rulesDir, { recursive: true });
16911
16911
  const writeJson = async (name, data) => {
16912
- const path = join18(outputDir, name);
16912
+ const path = join19(outputDir, name);
16913
16913
  await writeFile6(path, JSON.stringify(data, null, 2) + "\n", "utf-8");
16914
16914
  files.push(path);
16915
16915
  };
@@ -16921,7 +16921,7 @@ async function writeWorld(outputDir, world) {
16921
16921
  await writeJson("outcomes.json", world.outcomes);
16922
16922
  await writeJson("metadata.json", world.metadata);
16923
16923
  for (const rule of world.rules) {
16924
- const rulePath = join18(rulesDir, `${rule.id}.json`);
16924
+ const rulePath = join19(rulesDir, `${rule.id}.json`);
16925
16925
  await writeFile6(rulePath, JSON.stringify(rule, null, 2) + "\n", "utf-8");
16926
16926
  files.push(rulePath);
16927
16927
  }
@@ -17008,7 +17008,7 @@ async function main31(argv = process.argv.slice(2)) {
17008
17008
  }
17009
17009
  async function phaseRefine(outputDir, world) {
17010
17010
  const { writeFile: writeFile6 } = await import("fs/promises");
17011
- const { join: join18 } = await import("path");
17011
+ const { join: join19 } = await import("path");
17012
17012
  heading("Refinement: Thresholds & Collapse");
17013
17013
  const primaryMetric = world.gatesJson.viability_classification[0]?.field || "system_health";
17014
17014
  info(`
@@ -17025,7 +17025,7 @@ async function phaseRefine(outputDir, world) {
17025
17025
  if (!isNaN(parsed)) gate.value = parsed;
17026
17026
  }
17027
17027
  await writeFile6(
17028
- join18(outputDir, "gates.json"),
17028
+ join19(outputDir, "gates.json"),
17029
17029
  JSON.stringify(world.gatesJson, null, 2) + "\n",
17030
17030
  "utf-8"
17031
17031
  );
@@ -17047,7 +17047,7 @@ async function phaseRefine(outputDir, world) {
17047
17047
  result: "MODEL_COLLAPSES"
17048
17048
  };
17049
17049
  await writeFile6(
17050
- join18(outputDir, "rules", `${rule.id}.json`),
17050
+ join19(outputDir, "rules", `${rule.id}.json`),
17051
17051
  JSON.stringify(rule, null, 2) + "\n",
17052
17052
  "utf-8"
17053
17053
  );
@@ -18100,9 +18100,9 @@ async function cmdAdd(argv) {
18100
18100
  id = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
18101
18101
  }
18102
18102
  const { readFile: readFile4, writeFile: writeFile6 } = await import("fs/promises");
18103
- const { join: join18 } = await import("path");
18103
+ const { join: join19 } = await import("path");
18104
18104
  const possiblePaths = [
18105
- join18(worldPath, "world.nv-world.md"),
18105
+ join19(worldPath, "world.nv-world.md"),
18106
18106
  worldPath
18107
18107
  ];
18108
18108
  let mdPath = "";
@@ -18123,7 +18123,7 @@ async function cmdAdd(argv) {
18123
18123
  const files = await readdir(worldPath);
18124
18124
  const mdFile = files.find((f) => f.endsWith(".nv-world.md"));
18125
18125
  if (mdFile) {
18126
- mdPath = join18(worldPath, mdFile);
18126
+ mdPath = join19(worldPath, mdFile);
18127
18127
  mdContent = await readFile4(mdPath, "utf-8");
18128
18128
  }
18129
18129
  } catch {
@@ -19128,6 +19128,207 @@ var init_worldmodel_compiler = __esm({
19128
19128
  }
19129
19129
  });
19130
19130
 
19131
+ // src/cli/worldmodel-create.ts
19132
+ var worldmodel_create_exports = {};
19133
+ __export(worldmodel_create_exports, {
19134
+ askQuestions: () => askQuestions,
19135
+ saveWorldmodel: () => saveWorldmodel,
19136
+ structureWorldmodel: () => structureWorldmodel
19137
+ });
19138
+ async function askQuestions() {
19139
+ const rl2 = (0, import_readline.createInterface)({
19140
+ input: process.stdin,
19141
+ output: process.stderr
19142
+ // questions to stderr so stdout stays clean
19143
+ });
19144
+ const answers = {};
19145
+ process.stderr.write("\n");
19146
+ 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");
19147
+ process.stderr.write(" \u2551 NeuroVerseOS \u2014 Build your thinking constitution \u2551\n");
19148
+ 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");
19149
+ process.stderr.write("\n");
19150
+ process.stderr.write(" Answer these questions in your own words.\n");
19151
+ process.stderr.write(" There are no wrong answers \u2014 just say what you mean.\n");
19152
+ process.stderr.write(" The AI will structure your answers into a worldmodel.\n\n");
19153
+ for (const q of QUESTIONS) {
19154
+ const answer = await new Promise((resolve12) => {
19155
+ process.stderr.write(` \x1B[1m${q.question}\x1B[0m
19156
+ `);
19157
+ process.stderr.write(` \x1B[2m${q.placeholder}\x1B[0m
19158
+ `);
19159
+ rl2.question(" > ", (ans) => {
19160
+ process.stderr.write("\n");
19161
+ resolve12(ans.trim());
19162
+ });
19163
+ });
19164
+ answers[q.id] = answer;
19165
+ }
19166
+ rl2.close();
19167
+ return answers;
19168
+ }
19169
+ async function structureWorldmodel(answers, apiKey) {
19170
+ const prompt = buildStructuringPrompt(answers);
19171
+ const res = await fetch("https://api.anthropic.com/v1/messages", {
19172
+ method: "POST",
19173
+ headers: {
19174
+ "x-api-key": apiKey,
19175
+ "anthropic-version": "2023-06-01",
19176
+ "content-type": "application/json"
19177
+ },
19178
+ body: JSON.stringify({
19179
+ model: "claude-sonnet-4-20250514",
19180
+ max_tokens: 4096,
19181
+ 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.",
19182
+ messages: [{ role: "user", content: prompt }]
19183
+ })
19184
+ });
19185
+ if (!res.ok) {
19186
+ throw new Error(`AI structuring failed: ${res.status}`);
19187
+ }
19188
+ const data = await res.json();
19189
+ const text = data.content?.filter((c) => c.type === "text").map((c) => c.text ?? "").join("");
19190
+ if (!text) throw new Error("AI returned no content");
19191
+ return text.replace(/^```markdown\n?/, "").replace(/\n?```$/, "").trim();
19192
+ }
19193
+ function buildStructuringPrompt(answers) {
19194
+ return `Structure these conversational answers into a .worldmodel.md file.
19195
+
19196
+ The file MUST follow this exact three-layer format:
19197
+
19198
+ ---
19199
+ name: ${answers.name}
19200
+ version: 1.0.0
19201
+ ---
19202
+
19203
+ # Core Model Geometry
19204
+
19205
+ ## Mission
19206
+ (from the mission answer)
19207
+
19208
+ ## Domains
19209
+ (2-4 domains from the domains answer, each with:)
19210
+ ### Domain Name
19211
+ #### Skills (8-10 skills per domain, inferred from the answers)
19212
+ #### Values (3-4 values per domain, drawn from the non-negotiables + mission)
19213
+
19214
+ ## Overlap Effects
19215
+ (from the overlaps answer, formatted as: Domain A + Domain B = Emergent State)
19216
+
19217
+ ## Center Identity
19218
+ (from the center answer)
19219
+
19220
+ # Contextual Modifiers
19221
+
19222
+ ## Authority Layers
19223
+ (infer 4-5 authority levels appropriate to this organization)
19224
+
19225
+ ## Spatial Contexts
19226
+ (infer 4-5 contexts where behavior happens)
19227
+
19228
+ ## Interpretation Rules
19229
+ (infer 3-5 rules about how context changes meaning)
19230
+
19231
+ # Evolution Layer
19232
+
19233
+ ## Aligned Behaviors
19234
+ (from the success answer, expanded to 5-8 items)
19235
+
19236
+ ## Drift Behaviors
19237
+ (from the drift answer, expanded to 5-8 items)
19238
+
19239
+ ## Signals
19240
+ (infer 5-7 observable signals from the answers, snake_case)
19241
+
19242
+ ## Decision Priorities
19243
+ (from the priorities answer, formatted as: preferred > secondary)
19244
+
19245
+ ## Evolution Conditions
19246
+ (infer 3-5 conditions for when the model should adapt)
19247
+
19248
+ HERE ARE THE ANSWERS:
19249
+
19250
+ Name: ${answers.name}
19251
+
19252
+ Mission: ${answers.mission}
19253
+
19254
+ Domains: ${answers.domains}
19255
+
19256
+ Overlaps: ${answers.overlaps}
19257
+
19258
+ Center identity: ${answers.center}
19259
+
19260
+ Non-negotiables: ${answers.nonnegotiables}
19261
+
19262
+ Success looks like: ${answers.success}
19263
+
19264
+ Drift looks like: ${answers.drift}
19265
+
19266
+ Priorities: ${answers.priorities}
19267
+
19268
+ Output ONLY the .worldmodel.md content. No explanation. No commentary. Just the file.`;
19269
+ }
19270
+ function saveWorldmodel(content, outputPath) {
19271
+ const resolved = (0, import_path12.resolve)(outputPath);
19272
+ (0, import_fs11.writeFileSync)(resolved, content, "utf-8");
19273
+ return resolved;
19274
+ }
19275
+ var import_readline, import_fs11, import_path12, QUESTIONS;
19276
+ var init_worldmodel_create = __esm({
19277
+ "src/cli/worldmodel-create.ts"() {
19278
+ "use strict";
19279
+ import_readline = require("readline");
19280
+ import_fs11 = require("fs");
19281
+ import_path12 = require("path");
19282
+ QUESTIONS = [
19283
+ {
19284
+ id: "name",
19285
+ question: "What should we call this model? (Your name, your org, your project)",
19286
+ placeholder: 'e.g., "Kirsten", "Auki", "My Startup"'
19287
+ },
19288
+ {
19289
+ id: "mission",
19290
+ question: "In one or two sentences \u2014 what does this system exist to do? Not a slogan. The real purpose.",
19291
+ placeholder: 'e.g., "Protect human thinking while expanding cognitive capability through AI"'
19292
+ },
19293
+ {
19294
+ id: "domains",
19295
+ question: "What are the 2-3 big areas of focus? Not departments \u2014 the major kinds of work that matter most. Separate with commas.",
19296
+ placeholder: 'e.g., "Safety and boundaries, Individual authority, AI as cognitive extension"'
19297
+ },
19298
+ {
19299
+ id: "overlaps",
19300
+ question: "When those areas work well TOGETHER, what does that feel like? Name a feeling for each pair.",
19301
+ placeholder: 'e.g., "Safety + Authority = Trust, Authority + AI = Possibility"'
19302
+ },
19303
+ {
19304
+ id: "center",
19305
+ question: "When EVERYTHING is aligned \u2014 all areas working together \u2014 what does the system become? One name or phrase.",
19306
+ placeholder: 'e.g., "The Sovereign Conduit", "Collective Vanguard Leader"'
19307
+ },
19308
+ {
19309
+ id: "nonnegotiables",
19310
+ question: "What's absolutely non-negotiable? What would you walk away over? List a few.",
19311
+ placeholder: 'e.g., "Humans retain authority over thinking. AI extends, never replaces. People can always leave."'
19312
+ },
19313
+ {
19314
+ id: "success",
19315
+ question: `What does success look like in action? What would you point at and say "that's what I mean"?`,
19316
+ placeholder: 'e.g., "Someone maintaining clear authorship of decisions even when AI contributed"'
19317
+ },
19318
+ {
19319
+ id: "drift",
19320
+ question: "What does drift look like? What would worry you if you saw it happening?",
19321
+ placeholder: 'e.g., "Decision ownership quietly shifting to AI without explicit delegation"'
19322
+ },
19323
+ {
19324
+ id: "priorities",
19325
+ question: 'When tradeoffs appear, what wins? Give a few "X over Y" pairs.',
19326
+ placeholder: 'e.g., "Safety over speed, sovereignty over convenience, diversity over uniformity"'
19327
+ }
19328
+ ];
19329
+ }
19330
+ });
19331
+
19131
19332
  // src/cli/worldmodel.ts
19132
19333
  var worldmodel_exports = {};
19133
19334
  __export(worldmodel_exports, {
@@ -19164,8 +19365,8 @@ function formatIssue(issue) {
19164
19365
  return ` ${color}${icon}${RESET2} [${issue.section}${lineRef}] ${issue.message}`;
19165
19366
  }
19166
19367
  async function readSourceFile(inputPath) {
19167
- const fullPath = (0, import_path12.resolve)(inputPath);
19168
- if (!(0, import_fs11.existsSync)(fullPath)) {
19368
+ const fullPath = (0, import_path13.resolve)(inputPath);
19369
+ if (!(0, import_fs12.existsSync)(fullPath)) {
19169
19370
  process.stderr.write(`File not found: ${fullPath}
19170
19371
  `);
19171
19372
  process.exit(3);
@@ -19189,30 +19390,105 @@ async function cmdInit(argv) {
19189
19390
  const args = parseArgs26(argv);
19190
19391
  if (args.help) {
19191
19392
  process.stdout.write(
19192
- 'neuroverse worldmodel init \u2014 Scaffold a new .worldmodel.md template\n\nOptions:\n --name <name> Model name (default: "My Behavioral Model")\n --output <path> Output path (default: ./model.worldmodel.md)\n'
19393
+ 'neuroverse worldmodel init \u2014 Create a new behavioral model\n\nWith ANTHROPIC_API_KEY set:\n Interactive \u2014 answers questions, AI structures your worldmodel.\n Your natural process: talk \u2192 structure \u2192 refine.\n\nWithout ANTHROPIC_API_KEY:\n Template \u2014 generates a scaffold you fill in manually.\n\nOptions:\n --name <name> Model name (default: "My Behavioral Model")\n --output <path> Output path (default: ./model.worldmodel.md)\n --template Force template mode even with API key set\n'
19193
19394
  );
19194
19395
  return;
19195
19396
  }
19196
19397
  const modelName = args.name || "My Behavioral Model";
19197
- const outputPath = (0, import_path12.resolve)(
19398
+ const outputPath = (0, import_path13.resolve)(
19198
19399
  args.output || `./${toFileName(modelName)}.worldmodel.md`
19199
19400
  );
19200
- if ((0, import_fs11.existsSync)(outputPath)) {
19401
+ if ((0, import_fs12.existsSync)(outputPath)) {
19201
19402
  process.stderr.write(`File already exists: ${outputPath}
19202
19403
  `);
19203
19404
  process.stderr.write("Use --output to specify a different path.\n");
19204
19405
  process.exit(1);
19205
19406
  }
19407
+ const apiKey = process.env.ANTHROPIC_API_KEY;
19408
+ const forceTemplate = argv.includes("--template");
19409
+ if (apiKey && !forceTemplate && process.stdin.isTTY) {
19410
+ const { askQuestions: askQuestions2, structureWorldmodel: structureWorldmodel2, saveWorldmodel: saveWorldmodel2 } = await Promise.resolve().then(() => (init_worldmodel_create(), worldmodel_create_exports));
19411
+ process.stderr.write(`
19412
+ `);
19413
+ const answers = await askQuestions2();
19414
+ process.stderr.write(`${DIM2}Structuring your worldmodel...${RESET2}
19415
+ `);
19416
+ try {
19417
+ const content = await structureWorldmodel2(answers, apiKey);
19418
+ const dir2 = (0, import_path13.dirname)(outputPath);
19419
+ if (!(0, import_fs12.existsSync)(dir2)) {
19420
+ await (0, import_promises6.mkdir)(dir2, { recursive: true });
19421
+ }
19422
+ saveWorldmodel2(content, outputPath);
19423
+ process.stderr.write(`
19424
+ ${GREEN2}Created${RESET2} ${outputPath}
19425
+ `);
19426
+ process.stderr.write(
19427
+ `${DIM2}Review the file, then run: neuroverse worldmodel validate ${(0, import_path13.basename)(outputPath)}${RESET2}
19428
+ `
19429
+ );
19430
+ try {
19431
+ const validateResult = parseWorldModel(content);
19432
+ if (validateResult.model) {
19433
+ const m = validateResult.model;
19434
+ process.stderr.write(
19435
+ `${DIM2} Domains: ${m.geometry.domains.length} Overlaps: ${m.geometry.overlapEffects.length} Signals: ${m.evolution.signals.length}${RESET2}
19436
+ `
19437
+ );
19438
+ }
19439
+ const errors = validateResult.issues.filter((i) => i.severity === "error");
19440
+ if (errors.length > 0) {
19441
+ process.stderr.write(
19442
+ `
19443
+ ${YELLOW2}Validation found ${errors.length} issue${errors.length > 1 ? "s" : ""} \u2014 review and fix:${RESET2}
19444
+ `
19445
+ );
19446
+ for (const issue of errors) {
19447
+ process.stderr.write(` ${formatIssue(issue)}
19448
+ `);
19449
+ }
19450
+ } else {
19451
+ process.stderr.write(`${GREEN2}Validates cleanly!${RESET2}
19452
+ `);
19453
+ }
19454
+ } catch {
19455
+ }
19456
+ } catch (err) {
19457
+ process.stderr.write(`${RED}Error:${RESET2} ${err}
19458
+ `);
19459
+ process.stderr.write(
19460
+ `${DIM2}Falling back to template mode.${RESET2}
19461
+
19462
+ `
19463
+ );
19464
+ const template2 = generateScaffold(modelName);
19465
+ const dir2 = (0, import_path13.dirname)(outputPath);
19466
+ if (!(0, import_fs12.existsSync)(dir2)) {
19467
+ await (0, import_promises6.mkdir)(dir2, { recursive: true });
19468
+ }
19469
+ await (0, import_promises6.writeFile)(outputPath, template2, "utf-8");
19470
+ process.stderr.write(`${GREEN2}Created${RESET2} ${outputPath} (template)
19471
+ `);
19472
+ }
19473
+ return;
19474
+ }
19475
+ if (!apiKey && !forceTemplate) {
19476
+ process.stderr.write(
19477
+ `${DIM2}Tip: Set ANTHROPIC_API_KEY for the guided experience \u2014 AI asks you questions and creates your worldmodel.${RESET2}
19478
+
19479
+ `
19480
+ );
19481
+ }
19206
19482
  const template = generateScaffold(modelName);
19207
- const dir = (0, import_path12.dirname)(outputPath);
19208
- if (!(0, import_fs11.existsSync)(dir)) {
19483
+ const dir = (0, import_path13.dirname)(outputPath);
19484
+ if (!(0, import_fs12.existsSync)(dir)) {
19209
19485
  await (0, import_promises6.mkdir)(dir, { recursive: true });
19210
19486
  }
19211
19487
  await (0, import_promises6.writeFile)(outputPath, template, "utf-8");
19212
19488
  process.stderr.write(`${GREEN2}Created${RESET2} ${outputPath}
19213
19489
  `);
19214
19490
  process.stderr.write(
19215
- `${DIM2}Edit the template, then run: neuroverse worldmodel validate ${(0, import_path12.basename)(outputPath)}${RESET2}
19491
+ `${DIM2}Edit the template, then run: neuroverse worldmodel validate ${(0, import_path13.basename)(outputPath)}${RESET2}
19216
19492
  `
19217
19493
  );
19218
19494
  }
@@ -19643,17 +19919,17 @@ async function cmdBuild(argv) {
19643
19919
  process.stderr.write("\n");
19644
19920
  }
19645
19921
  const output = compileWorldModel(model);
19646
- const outputDir = (0, import_path12.resolve)(
19922
+ const outputDir = (0, import_path13.resolve)(
19647
19923
  args.output || `.neuroverse/worldmodels/${model.frontmatter.model_id}/`
19648
19924
  );
19649
- if (!(0, import_fs11.existsSync)(outputDir)) {
19925
+ if (!(0, import_fs12.existsSync)(outputDir)) {
19650
19926
  await (0, import_promises6.mkdir)(outputDir, { recursive: true });
19651
19927
  }
19652
- const worldPath = (0, import_path12.join)(outputDir, `${model.frontmatter.model_id}.nv-world.md`);
19653
- const signalsPath = (0, import_path12.join)(outputDir, "signals.json");
19654
- const overlapsPath = (0, import_path12.join)(outputDir, "overlaps.json");
19655
- const contextsPath = (0, import_path12.join)(outputDir, "contexts.json");
19656
- const lensesPath = (0, import_path12.join)(outputDir, "lenses.json");
19928
+ const worldPath = (0, import_path13.join)(outputDir, `${model.frontmatter.model_id}.nv-world.md`);
19929
+ const signalsPath = (0, import_path13.join)(outputDir, "signals.json");
19930
+ const overlapsPath = (0, import_path13.join)(outputDir, "overlaps.json");
19931
+ const contextsPath = (0, import_path13.join)(outputDir, "contexts.json");
19932
+ const lensesPath = (0, import_path13.join)(outputDir, "lenses.json");
19657
19933
  await Promise.all([
19658
19934
  (0, import_promises6.writeFile)(worldPath, output.worldMarkdown, "utf-8"),
19659
19935
  (0, import_promises6.writeFile)(signalsPath, JSON.stringify(output.signalSchema, null, 2) + "\n", "utf-8"),
@@ -19685,7 +19961,7 @@ async function cmdBuild(argv) {
19685
19961
  `);
19686
19962
  process.stderr.write(` ${BOLD2}Output:${RESET2} ${outputDir}/
19687
19963
  `);
19688
- process.stderr.write(` ${(0, import_path12.basename)(worldPath)}${DIM2} \u2014 executable world${RESET2}
19964
+ process.stderr.write(` ${(0, import_path13.basename)(worldPath)}${DIM2} \u2014 executable world${RESET2}
19689
19965
  `);
19690
19966
  process.stderr.write(` signals.json${DIM2} \u2014 signal schema${RESET2}
19691
19967
  `);
@@ -19721,9 +19997,9 @@ async function cmdEmitWorld(argv) {
19721
19997
  const { model } = await loadAndParse(args.inputPath);
19722
19998
  const markdown = emitWorldMarkdown(model);
19723
19999
  if (args.output) {
19724
- const dir = (0, import_path12.dirname)((0, import_path12.resolve)(args.output));
19725
- if (!(0, import_fs11.existsSync)(dir)) await (0, import_promises6.mkdir)(dir, { recursive: true });
19726
- await (0, import_promises6.writeFile)((0, import_path12.resolve)(args.output), markdown, "utf-8");
20000
+ const dir = (0, import_path13.dirname)((0, import_path13.resolve)(args.output));
20001
+ if (!(0, import_fs12.existsSync)(dir)) await (0, import_promises6.mkdir)(dir, { recursive: true });
20002
+ await (0, import_promises6.writeFile)((0, import_path13.resolve)(args.output), markdown, "utf-8");
19727
20003
  process.stderr.write(`${GREEN2}Written${RESET2} ${args.output}
19728
20004
  `);
19729
20005
  } else {
@@ -19814,13 +20090,13 @@ async function main33(argv = process.argv.slice(2)) {
19814
20090
  process.exit(1);
19815
20091
  }
19816
20092
  }
19817
- var import_promises6, import_fs11, import_path12, BOLD2, DIM2, CYAN2, GREEN2, YELLOW2, RED, MAGENTA2, RESET2, USAGE9;
20093
+ var import_promises6, import_fs12, import_path13, BOLD2, DIM2, CYAN2, GREEN2, YELLOW2, RED, MAGENTA2, RESET2, USAGE9;
19818
20094
  var init_worldmodel = __esm({
19819
20095
  "src/cli/worldmodel.ts"() {
19820
20096
  "use strict";
19821
20097
  import_promises6 = require("fs/promises");
19822
- import_fs11 = require("fs");
19823
- import_path12 = require("path");
20098
+ import_fs12 = require("fs");
20099
+ import_path13 = require("path");
19824
20100
  init_worldmodel_parser();
19825
20101
  init_worldmodel_compiler();
19826
20102
  BOLD2 = "\x1B[1m";
@@ -20292,13 +20568,300 @@ var init_auki_builder = __esm({
20292
20568
  }
20293
20569
  });
20294
20570
 
20571
+ // src/radiant/lenses/sovereign-conduit.ts
20572
+ function sovereignConduitRewrite(pattern) {
20573
+ if (pattern.evidence.cited_invariant) {
20574
+ return {
20575
+ ...pattern,
20576
+ framing: "non-negotiable rule tested",
20577
+ emphasis: "name the rule, name who it protects, name what would happen without it",
20578
+ compress: false
20579
+ // Sovereign Conduit is warm, not compressed
20580
+ };
20581
+ }
20582
+ if (pattern.type === "candidate") {
20583
+ return {
20584
+ ...pattern,
20585
+ framing: "something new noticed",
20586
+ emphasis: "explain what was seen in everyday language, ask whether it matters",
20587
+ compress: false
20588
+ };
20589
+ }
20590
+ return {
20591
+ ...pattern,
20592
+ framing: "what this means for the people in the system",
20593
+ emphasis: "humanity + sovereignty + learning",
20594
+ compress: false
20595
+ };
20596
+ }
20597
+ var SOVEREIGN_CONDUIT_FRAME, SOVEREIGN_CONDUIT_VOCABULARY, SOVEREIGN_CONDUIT_VOICE, SOVEREIGN_CONDUIT_FORBIDDEN, SOVEREIGN_CONDUIT_PREFERRED, SOVEREIGN_CONDUIT_STRATEGIC, SOVEREIGN_CONDUIT_EXEMPLARS, sovereignConduitLens;
20598
+ var init_sovereign_conduit = __esm({
20599
+ "src/radiant/lenses/sovereign-conduit.ts"() {
20600
+ "use strict";
20601
+ SOVEREIGN_CONDUIT_FRAME = {
20602
+ domains: [
20603
+ "stewardship",
20604
+ "sovereignty",
20605
+ "integration"
20606
+ ],
20607
+ overlaps: [
20608
+ {
20609
+ domains: ["stewardship", "sovereignty"],
20610
+ emergent_state: "Trust",
20611
+ description: "I am safe to be myself. When the system protects AND preserves individual authority, trust emerges \u2014 the feeling that you can think freely because someone is watching the boundaries."
20612
+ },
20613
+ {
20614
+ domains: ["sovereignty", "integration"],
20615
+ emergent_state: "Possibility",
20616
+ description: "My thinking can expand. When individual authority is preserved AND AI extends cognitive capability, possibility opens \u2014 the feeling that you can reach further without losing yourself."
20617
+ },
20618
+ {
20619
+ domains: ["integration", "stewardship"],
20620
+ emergent_state: "Responsibility",
20621
+ description: "Power is used with care. When AI extends capability AND the system protects integrity, responsibility emerges \u2014 the feeling that expansion comes with guardrails, not recklessness."
20622
+ }
20623
+ ],
20624
+ center_identity: "The Sovereign Conduit",
20625
+ evaluation_questions: [
20626
+ "Is the human maintaining authority over their decisions, or is decision ownership quietly shifting to the AI?",
20627
+ "Is the AI extending thinking, or is it replacing thinking? Look for the difference: extension means the human understands and owns the output. Replacement means they accept it without engaging.",
20628
+ "Are the boundaries between human thinking and AI output clear and visible, or are they blurring?",
20629
+ "Is diversity of thought preserved? Are people thinking differently from each other, or is the system funneling everyone into the same patterns?",
20630
+ "Would you feel safe letting a child learn in this system? If not, what specifically makes it unsafe?",
20631
+ "If this felt wrong, could you leave? Is the exit real or theoretical?"
20632
+ ],
20633
+ scoring_rubric: "For any activity, ask: is the human still the author of their decisions? Is the AI helping them think further, or thinking for them? Are the rules of this space clear, fair, and safe \u2014 like the rules at a good friend's house? When something feels off, name the feeling first, then the mechanism. Use everyday language. If a non-technical person couldn't understand the observation, rephrase it until they could.",
20634
+ domain_skills: {
20635
+ "stewardship": [
20636
+ "boundary setting",
20637
+ "risk awareness",
20638
+ "ethical judgment",
20639
+ "system protection",
20640
+ "conflict stabilization",
20641
+ "responsibility signaling",
20642
+ "harm detection",
20643
+ "constraint design"
20644
+ ],
20645
+ "sovereignty": [
20646
+ "independent thinking",
20647
+ "decision ownership",
20648
+ "self-trust",
20649
+ "value clarity",
20650
+ "cognitive resistance",
20651
+ "identity anchoring",
20652
+ "perspective holding",
20653
+ "authentic expression"
20654
+ ],
20655
+ "integration": [
20656
+ "AI collaboration",
20657
+ "cognitive expansion",
20658
+ "prompt framing",
20659
+ "insight synthesis",
20660
+ "signal interpretation",
20661
+ "tool fluency",
20662
+ "co-creation",
20663
+ "iterative thinking"
20664
+ ]
20665
+ },
20666
+ output_translation: {
20667
+ never_surface_in_output: [
20668
+ "Stewardship",
20669
+ "Sovereignty",
20670
+ "Integration"
20671
+ ],
20672
+ surface_freely: [
20673
+ "Trust",
20674
+ "Possibility",
20675
+ "Responsibility",
20676
+ "Sovereign Conduit"
20677
+ ],
20678
+ translation_examples: [
20679
+ {
20680
+ internal_reasoning: "Stewardship is strong",
20681
+ external_expression: "the boundaries are clear and the system feels safe to operate inside"
20682
+ },
20683
+ {
20684
+ internal_reasoning: "Sovereignty is weakening",
20685
+ external_expression: "decision ownership is quietly shifting \u2014 the human is accepting AI output without engaging with it"
20686
+ },
20687
+ {
20688
+ internal_reasoning: "Integration is high but Stewardship is low",
20689
+ external_expression: "the AI is expanding capability fast, but nobody is watching the guardrails \u2014 that's power without responsibility"
20690
+ }
20691
+ ]
20692
+ }
20693
+ };
20694
+ SOVEREIGN_CONDUIT_VOCABULARY = {
20695
+ proper_nouns: [
20696
+ "NeuroVerseOS",
20697
+ "Sovereign Conduit",
20698
+ "LifeOS",
20699
+ "CyberOS",
20700
+ "NeuroverseOS"
20701
+ ],
20702
+ preferred: {
20703
+ "worldmodel": "thinking constitution",
20704
+ "invariant": "non-negotiable rule",
20705
+ "governance": "the rules of the space",
20706
+ "alignment": "how well the work matches what was declared",
20707
+ "drift": "quiet shift away from what was intended",
20708
+ "signal": "something observable",
20709
+ "evidence gate": "how much we need to see before we speak",
20710
+ "actor domain": "who did the work \u2014 a person, an AI, or both together",
20711
+ "rendering lens": "how the system speaks",
20712
+ "candidate pattern": "something noticed but not yet named as important",
20713
+ "cognitive liberty": "your right to think for yourself",
20714
+ "homogenization": "everyone being funneled into the same patterns"
20715
+ },
20716
+ architecture: [
20717
+ "thinking constitution",
20718
+ "thinking space",
20719
+ "cognitive extension",
20720
+ "behavioral model",
20721
+ "governance frame",
20722
+ "world file",
20723
+ "cocoon"
20724
+ ],
20725
+ economic: [],
20726
+ framing: [
20727
+ "humanity first",
20728
+ "in constant learning",
20729
+ "in shared teaching",
20730
+ "extension not replacement",
20731
+ "safe to think freely",
20732
+ "the rules of this house",
20733
+ "sovereign over your own thinking",
20734
+ "idea calculator",
20735
+ "Spock in your life",
20736
+ "Jarvis in your life",
20737
+ "funneling into fields",
20738
+ "diversity of thought",
20739
+ "thinking for yourself"
20740
+ ],
20741
+ jargon_translations: {
20742
+ "worldmodel": "thinking constitution",
20743
+ "invariant": "non-negotiable rule",
20744
+ "canonical pattern": "something we're tracking by name",
20745
+ "candidate pattern": "something noticed but not yet tracked",
20746
+ "evidence gate": "how much we need to see before we speak up",
20747
+ "signal extraction": "reading what happened",
20748
+ "alignment score": "how well the work matches what was declared",
20749
+ "actor domain": "who did this \u2014 a person, an AI, or both",
20750
+ "presence-based averaging": "only counting what actually happened",
20751
+ "drift detection": "noticing when things quietly shift",
20752
+ "INSUFFICIENT_EVIDENCE": "not enough to say yet",
20753
+ "UNAVAILABLE": "can't measure this yet",
20754
+ "rendering lens": "how the system speaks to you"
20755
+ }
20756
+ };
20757
+ SOVEREIGN_CONDUIT_VOICE = {
20758
+ register: "warm, accessible, teaching. Like a thoughtful parent explaining how the world works \u2014 not talking down, but making the complex feel natural. Use everyday analogies. Name emotions. If a non-technical person couldn't understand the output, it's wrong.",
20759
+ active_voice: "preferred",
20760
+ specificity: "preferred",
20761
+ hype_vocabulary: "forbidden",
20762
+ hedging: "discouraged",
20763
+ playfulness: "allowed",
20764
+ close_with_strategic_frame: "preferred",
20765
+ punchline_move: "sparing",
20766
+ honesty_about_failure: "required",
20767
+ output_translation: `Reason internally through the three-domain frame (Stewardship, Sovereignty, Integration). Express externally through the skills inside each domain and the overlap feelings (Trust, Possibility, Responsibility). Do NOT surface the bucket names as labels. Readers understand "the boundaries feel safe" not "Stewardship is strong." Use everyday analogies \u2014 mom rules, friend's house rules, idea calculator. Name the emotion before the mechanism.`
20768
+ };
20769
+ SOVEREIGN_CONDUIT_FORBIDDEN = Object.freeze([
20770
+ // Bucket names as labels
20771
+ "stewardship is",
20772
+ "sovereignty is",
20773
+ "integration is",
20774
+ // AI-assistant hedging
20775
+ "it may be beneficial to consider",
20776
+ "there appears to be",
20777
+ "one possible interpretation",
20778
+ "it might be worth exploring",
20779
+ "consider whether",
20780
+ "it is worth noting",
20781
+ // Corporate
20782
+ "stakeholders",
20783
+ "synergy",
20784
+ "value proposition",
20785
+ "paradigm shift",
20786
+ "best-in-class",
20787
+ "industry-leading",
20788
+ // Cold/mechanical
20789
+ "the system recommends",
20790
+ "analysis suggests",
20791
+ "data indicates",
20792
+ "metrics show",
20793
+ "according to the model"
20794
+ ]);
20795
+ SOVEREIGN_CONDUIT_PREFERRED = Object.freeze([
20796
+ // Everyday analogies
20797
+ "This is like [everyday analogy]. [What it means].",
20798
+ "Think of it like the rules at a friend's house \u2014 [application].",
20799
+ "The boundaries are [state]. That means [feeling].",
20800
+ // Emotion-first
20801
+ "This feels like [emotion] because [mechanism].",
20802
+ "Trust is [emerging/breaking] here \u2014 [specific evidence].",
20803
+ "Possibility is opening because [evidence]. But [caveat if any].",
20804
+ // Teaching voice
20805
+ "Here's what's actually happening: [plain explanation].",
20806
+ "The question to ask yourself: [question].",
20807
+ "The difference between [A] and [B] matters here: [why].",
20808
+ // Sovereignty checks
20809
+ "Are you still the author of this decision, or did the AI make it for you?",
20810
+ "The AI extended your thinking here. That's working.",
20811
+ "The AI replaced your thinking here. That's the drift to watch.",
20812
+ // Safety
20813
+ "Would you feel safe letting someone learn in this environment? [Why/why not].",
20814
+ "The exit is real \u2014 you can [specific exit path].",
20815
+ "The exit isn't real here \u2014 [what's blocking it]."
20816
+ ]);
20817
+ SOVEREIGN_CONDUIT_STRATEGIC = Object.freeze([
20818
+ "Safety before expansion \u2014 always. No exception.",
20819
+ "Sovereignty before convenience \u2014 the right to think for yourself is not a feature to optimize away.",
20820
+ "Extension, not replacement \u2014 AI should make your thinking bigger, not do your thinking for you.",
20821
+ "Diversity over uniformity \u2014 different thinkers produce different ideas, and that's the engine of progress.",
20822
+ "The rules should be visible \u2014 like a good house, you know the rules before you walk in.",
20823
+ "Exit must be real \u2014 if you can't leave a system that feels wrong, it's not governance, it's a cage.",
20824
+ "Teach, don't lecture \u2014 help people think for themselves, not think what you think.",
20825
+ "Name the feeling first \u2014 when something is off, the emotion arrives before the analysis. Trust that."
20826
+ ]);
20827
+ SOVEREIGN_CONDUIT_EXEMPLARS = Object.freeze([
20828
+ {
20829
+ path: "neuroverseos-sovereign-conduit.worldmodel.md",
20830
+ title: "The Sovereign Conduit Worldmodel",
20831
+ exhibits: ["stewardship", "sovereignty", "integration"],
20832
+ integration_quality: "full \u2014 all three domains defined, overlaps named, center identity declared",
20833
+ notes: 'The source worldmodel. The tagline "Humanity first. In constant learning. In shared teaching." is the voice compressed to its essence. Use this as the north star for tone calibration.'
20834
+ }
20835
+ ]);
20836
+ sovereignConduitLens = {
20837
+ name: "sovereign-conduit",
20838
+ description: "The NeuroVerseOS base lens. Warm, accessible, teaching. Evaluates activity through Stewardship (safety), Sovereignty (authority over thinking), and Integration (AI as cognitive extension). Uses everyday analogies \u2014 mom rules, friend's house, idea calculator. Names emotions before mechanisms. If a non-technical person can't understand the output, the voice is wrong. Humanity first. In constant learning. In shared teaching.",
20839
+ primary_frame: {
20840
+ domains: SOVEREIGN_CONDUIT_FRAME.domains,
20841
+ overlaps: SOVEREIGN_CONDUIT_FRAME.overlaps,
20842
+ center_identity: SOVEREIGN_CONDUIT_FRAME.center_identity,
20843
+ evaluation_questions: SOVEREIGN_CONDUIT_FRAME.evaluation_questions,
20844
+ scoring_rubric: SOVEREIGN_CONDUIT_FRAME.scoring_rubric
20845
+ },
20846
+ vocabulary: SOVEREIGN_CONDUIT_VOCABULARY,
20847
+ voice: SOVEREIGN_CONDUIT_VOICE,
20848
+ forbidden_phrases: SOVEREIGN_CONDUIT_FORBIDDEN,
20849
+ preferred_patterns: SOVEREIGN_CONDUIT_PREFERRED,
20850
+ strategic_patterns: SOVEREIGN_CONDUIT_STRATEGIC,
20851
+ exemplar_refs: SOVEREIGN_CONDUIT_EXEMPLARS,
20852
+ rewrite: sovereignConduitRewrite
20853
+ };
20854
+ }
20855
+ });
20856
+
20295
20857
  // src/radiant/lenses/index.ts
20296
20858
  var lenses_exports = {};
20297
20859
  __export(lenses_exports, {
20298
20860
  LENSES: () => LENSES,
20299
20861
  aukiBuilderLens: () => aukiBuilderLens,
20300
20862
  getLens: () => getLens2,
20301
- listLenses: () => listLenses
20863
+ listLenses: () => listLenses,
20864
+ sovereignConduitLens: () => sovereignConduitLens
20302
20865
  });
20303
20866
  function getLens2(id) {
20304
20867
  return LENSES[id];
@@ -20311,102 +20874,186 @@ var init_lenses = __esm({
20311
20874
  "src/radiant/lenses/index.ts"() {
20312
20875
  "use strict";
20313
20876
  init_auki_builder();
20877
+ init_sovereign_conduit();
20314
20878
  init_auki_builder();
20879
+ init_sovereign_conduit();
20315
20880
  LENSES = Object.freeze({
20316
- "auki-builder": aukiBuilderLens
20881
+ "auki-builder": aukiBuilderLens,
20882
+ "sovereign-conduit": sovereignConduitLens
20317
20883
  });
20318
20884
  }
20319
20885
  });
20320
20886
 
20887
+ // src/radiant/core/compress.ts
20888
+ function compressWorldmodel(content) {
20889
+ const lines = [];
20890
+ const missionMatch = content.match(/##\s*Mission\s*\n+(?:<!--[\s\S]*?-->\s*\n+)?(.*?)(?:\n\n|\n##|$)/s);
20891
+ if (missionMatch) {
20892
+ const mission = missionMatch[1].trim().split("\n")[0];
20893
+ lines.push(`Mission: ${mission}`);
20894
+ }
20895
+ const domainMatches = content.matchAll(/###\s+([^\n]+)/g);
20896
+ const domains = [];
20897
+ for (const m of domainMatches) {
20898
+ const name = m[1].trim();
20899
+ if (name !== "Skills" && name !== "Values" && !name.startsWith("####")) {
20900
+ domains.push(name);
20901
+ }
20902
+ }
20903
+ if (domains.length > 0) {
20904
+ lines.push(`Domains: ${domains.join(", ")}`);
20905
+ }
20906
+ const invariantSection = content.match(/(?:Invariants|## Invariants|invariants)([\s\S]*?)(?:\n#|\n---|\n\n\n)/i);
20907
+ if (invariantSection) {
20908
+ const invLines = invariantSection[1].match(/^[-*]\s+`?([^`\n]+)/gm);
20909
+ if (invLines) {
20910
+ lines.push("\nInvariants:");
20911
+ for (const inv of invLines.slice(0, 10)) {
20912
+ lines.push(inv.trim());
20913
+ }
20914
+ }
20915
+ }
20916
+ const prioritySection = content.match(/(?:Decision Priorities|## Decision Priorities)([\s\S]*?)(?:\n#|\n---|\n\n\n)/i);
20917
+ if (prioritySection) {
20918
+ const priLines = prioritySection[1].match(/^[-*]\s+.+>.+/gm);
20919
+ if (priLines) {
20920
+ lines.push("\nPriorities:");
20921
+ for (const pri of priLines.slice(0, 10)) {
20922
+ lines.push(pri.trim());
20923
+ }
20924
+ }
20925
+ }
20926
+ const signalSection = content.match(/(?:## Signals)([\s\S]*?)(?:\n#|\n---|\n\n\n)/i);
20927
+ if (signalSection) {
20928
+ const sigLines = signalSection[1].match(/^[-*]\s+(\w+)/gm);
20929
+ if (sigLines) {
20930
+ lines.push(`
20931
+ Signals: ${sigLines.map((s) => s.replace(/^[-*]\s+/, "")).join(", ")}`);
20932
+ }
20933
+ }
20934
+ const driftSection = content.match(/(?:Drift Behaviors|## Drift Behaviors)([\s\S]*?)(?:\n#|\n---|\n\n\n)/i);
20935
+ if (driftSection) {
20936
+ const driftLines = driftSection[1].match(/^[-*]\s+(.+)/gm);
20937
+ if (driftLines) {
20938
+ lines.push("\nDrift behaviors:");
20939
+ for (const d of driftLines.slice(0, 5)) {
20940
+ lines.push(d.trim());
20941
+ }
20942
+ }
20943
+ }
20944
+ const compressed = lines.join("\n");
20945
+ if (compressed.length < 50) {
20946
+ return content.slice(0, 2e3) + "\n[truncated]";
20947
+ }
20948
+ return compressed;
20949
+ }
20950
+ function compressExocortex(ctx) {
20951
+ const lines = [];
20952
+ if (ctx.attention) {
20953
+ lines.push(`Attention: ${firstMeaningfulLine(ctx.attention)}`);
20954
+ }
20955
+ if (ctx.goals) {
20956
+ lines.push(`Goals: ${firstNLines(ctx.goals, 3)}`);
20957
+ }
20958
+ if (ctx.sprint) {
20959
+ lines.push(`Sprint: ${firstNLines(ctx.sprint, 3)}`);
20960
+ }
20961
+ if (ctx.identity) {
20962
+ lines.push(`Identity: ${firstMeaningfulLine(ctx.identity)}`);
20963
+ }
20964
+ if (ctx.organization) {
20965
+ lines.push(`Org: ${firstMeaningfulLine(ctx.organization)}`);
20966
+ }
20967
+ return lines.join("\n");
20968
+ }
20969
+ function compressLens(lens) {
20970
+ return {
20971
+ evaluationQuestions: lens.primary_frame.evaluation_questions.map((q, i) => `${i + 1}. ${q}`).join("\n"),
20972
+ scoringRubric: lens.primary_frame.scoring_rubric,
20973
+ forbiddenPhrases: lens.forbidden_phrases.join(", "),
20974
+ jargonTranslations: Object.entries(lens.vocabulary.jargon_translations).map(([k, v]) => `${k} \u2192 ${v}`).join("; "),
20975
+ strategicPatterns: lens.strategic_patterns.slice(0, 5).join("\n")
20976
+ };
20977
+ }
20978
+ function compressPriorReads(reads) {
20979
+ if (reads.length === 0) return "";
20980
+ const patternCounts = /* @__PURE__ */ new Map();
20981
+ for (const read of reads) {
20982
+ for (const name of read.patternNames) {
20983
+ patternCounts.set(name, (patternCounts.get(name) ?? 0) + 1);
20984
+ }
20985
+ }
20986
+ const sorted = [...patternCounts.entries()].sort((a, b) => b[1] - a[1]);
20987
+ if (sorted.length === 0) {
20988
+ return `${reads.length} prior reads, no patterns extracted.`;
20989
+ }
20990
+ const patternList = sorted.map(([name, count]) => `${name} (${count}x)`).join(", ");
20991
+ return `${reads.length} prior reads. Patterns seen: ${patternList}. If these recur, note persistence.`;
20992
+ }
20993
+ function firstMeaningfulLine(text) {
20994
+ const lines = text.split("\n").filter((l) => {
20995
+ const t = l.trim();
20996
+ return t.length > 0 && !t.startsWith("#") && !t.startsWith("<!--");
20997
+ });
20998
+ return lines[0]?.slice(0, 200) ?? "";
20999
+ }
21000
+ function firstNLines(text, n) {
21001
+ const lines = text.split("\n").filter((l) => {
21002
+ const t = l.trim();
21003
+ return t.length > 0 && !t.startsWith("#") && !t.startsWith("<!--");
21004
+ });
21005
+ return lines.slice(0, n).map((l) => l.slice(0, 150)).join("; ");
21006
+ }
21007
+ var init_compress = __esm({
21008
+ "src/radiant/core/compress.ts"() {
21009
+ "use strict";
21010
+ }
21011
+ });
21012
+
20321
21013
  // src/radiant/core/prompt.ts
20322
21014
  function composeSystemPrompt(worldmodelContent, lens) {
20323
- const sections = [];
20324
- sections.push(
20325
- `## Worldmodel
20326
-
20327
- You are operating inside a governed environment. The worldmodel below
20328
- defines the invariants, signals, decision priorities, and behavioral
20329
- expectations for this organization. Every response you produce must
20330
- be grounded in this worldmodel.
20331
-
20332
- ` + worldmodelContent
20333
- );
20334
- const frame = lens.primary_frame;
20335
- const questionsBlock = frame.evaluation_questions.map((q, i) => `${i + 1}. ${q}`).join("\n");
20336
- const overlapsBlock = frame.overlaps.map(
20337
- (o) => `- ${o.domains[0]} + ${o.domains[1]} = **${o.emergent_state}**: ${o.description}`
20338
- ).join("\n");
20339
- sections.push(
20340
- `## How to Think (Analytical Frame: ${lens.name})
20341
-
20342
- ${frame.scoring_rubric}
20343
-
20344
- ### Evaluation questions to reason through
21015
+ const compressedWorld = compressWorldmodel(worldmodelContent);
21016
+ const cl = compressLens(lens);
21017
+ const overlapsBlock = lens.primary_frame.overlaps.map((o) => `${o.domains[0]} + ${o.domains[1]} = ${o.emergent_state}`).join("\n");
21018
+ return [
21019
+ // Section 1: Compressed worldmodel
21020
+ `## Worldmodel (compressed)
20345
21021
 
20346
- ${questionsBlock}
21022
+ ${compressedWorld}`,
21023
+ // Section 2: Analytical frame (evaluation questions + rubric)
21024
+ `## How to Think
20347
21025
 
20348
- ### Overlap emergent states
21026
+ ${cl.scoringRubric}
20349
21027
 
20350
- ${overlapsBlock}
21028
+ Questions:
21029
+ ${cl.evaluationQuestions}
20351
21030
 
20352
- ### Center identity
21031
+ Overlaps: ${overlapsBlock}
21032
+ Center: ${lens.primary_frame.center_identity}
20353
21033
 
20354
- When all dimensions integrate fully: **${frame.center_identity}**. Surface this sparingly \u2014 only when the integration is genuinely complete.`
20355
- );
20356
- const vocabPreferred = Object.entries(lens.vocabulary.preferred).map(([generic, native]) => `- "${generic}" \u2192 **${native}**`).join("\n");
20357
- const vocabArchitecture = lens.vocabulary.architecture.map((t) => `\`${t}\``).join(", ");
20358
- const vocabProperNouns = lens.vocabulary.proper_nouns.map((n) => `**${n}**`).join(", ");
20359
- const strategicBlock = lens.strategic_patterns.map((p) => `- ${p}`).join("\n");
20360
- sections.push(
20361
- `## How to Speak (Voice: ${lens.name})
21034
+ Translate before output: ${cl.jargonTranslations}`,
21035
+ // Section 3: Voice (compressed — register + key rules only)
21036
+ `## Voice: ${lens.name}
20362
21037
 
20363
21038
  Register: ${lens.voice.register}
20364
-
20365
- Rules:
20366
- - Active voice: ${lens.voice.active_voice}
20367
- - Named specificity (people, places, numbers): ${lens.voice.specificity}
20368
- - Hype vocabulary: ${lens.voice.hype_vocabulary}
20369
- - Hedging / qualified phrasing: ${lens.voice.hedging}
20370
- - Playfulness: ${lens.voice.playfulness}
20371
- - Close with strategic frame: ${lens.voice.close_with_strategic_frame}
20372
- - Honesty about failure: ${lens.voice.honesty_about_failure}
20373
-
20374
- ### Output translation discipline
21039
+ Active voice: ${lens.voice.active_voice}. Specificity: ${lens.voice.specificity}. Hedging: ${lens.voice.hedging}. Hype: ${lens.voice.hype_vocabulary}. Honesty about failure: ${lens.voice.honesty_about_failure}.
20375
21040
 
20376
21041
  ${lens.voice.output_translation}
20377
21042
 
20378
- ### Vocabulary
20379
-
20380
- Proper nouns (use literally): ${vocabProperNouns}
20381
-
20382
- Preferred term substitutions:
20383
- ${vocabPreferred}
20384
-
20385
- Architecture vocabulary: ${vocabArchitecture}
20386
-
20387
- ### Strategic decision patterns
20388
-
20389
- When recommending action, these patterns reflect how this organization resolves tradeoffs:
20390
-
20391
- ${strategicBlock}`
20392
- );
20393
- const forbiddenBlock = lens.forbidden_phrases.map((p) => `- "${p}"`).join("\n");
20394
- sections.push(
21043
+ Strategic patterns:
21044
+ ${cl.strategicPatterns}`,
21045
+ // Section 4: Guardrails (forbidden phrases as comma-separated, not bulleted)
20395
21046
  `## Guardrails
20396
21047
 
20397
- Do NOT use any of these phrases in your response. If you catch yourself
20398
- reaching for one, rephrase in direct, active, specific language instead.
20399
-
20400
- ${forbiddenBlock}
21048
+ Do NOT use: ${cl.forbiddenPhrases}
20401
21049
 
20402
- If your response would violate a worldmodel invariant, state the conflict
20403
- explicitly and propose an alternative that honors the invariant.`
20404
- );
20405
- return sections.join("\n\n---\n\n");
21050
+ If a response would violate a worldmodel invariant, state the conflict and propose an alternative.`
21051
+ ].join("\n\n---\n\n");
20406
21052
  }
20407
21053
  var init_prompt = __esm({
20408
21054
  "src/radiant/core/prompt.ts"() {
20409
21055
  "use strict";
21056
+ init_compress();
20410
21057
  }
20411
21058
  });
20412
21059
 
@@ -20473,17 +21120,30 @@ var init_think = __esm({
20473
21120
  });
20474
21121
 
20475
21122
  // src/radiant/core/scopes.ts
20476
- function parseRepoScope(scope) {
21123
+ function parseScope(scope) {
20477
21124
  const cleaned = scope.replace(/^https?:\/\//, "").replace(/^github\.com\//, "").replace(/\.git$/, "").replace(/\/$/, "");
20478
- const parts = cleaned.split("/");
20479
- if (parts.length < 2 || !parts[0] || !parts[1]) {
21125
+ const parts = cleaned.split("/").filter(Boolean);
21126
+ if (parts.length === 0 || !parts[0]) {
20480
21127
  throw new Error(
20481
- `Cannot parse repo scope: "${scope}". Expected "owner/repo" or a GitHub URL.`
21128
+ `Cannot parse scope: "${scope}". Expected "owner/repo" or "owner".`
20482
21129
  );
20483
21130
  }
20484
- return { owner: parts[0], repo: parts[1] };
21131
+ if (parts.length === 1) {
21132
+ return { type: "org", owner: parts[0] };
21133
+ }
21134
+ return { type: "repo", owner: parts[0], repo: parts[1] };
21135
+ }
21136
+ function parseRepoScope(scope) {
21137
+ const parsed = parseScope(scope);
21138
+ if (parsed.type === "org") {
21139
+ throw new Error(
21140
+ `Expected "owner/repo" but got org-level scope "${parsed.owner}". Use parseScope() for org-level.`
21141
+ );
21142
+ }
21143
+ return parsed;
20485
21144
  }
20486
21145
  function formatScope(scope) {
21146
+ if (scope.type === "org") return `${scope.owner} (org)`;
20487
21147
  return `${scope.owner}/${scope.repo}`;
20488
21148
  }
20489
21149
  var init_scopes = __esm({
@@ -20652,11 +21312,45 @@ async function fetchJSON(url, headers) {
20652
21312
  );
20653
21313
  }
20654
21314
  }
20655
- throw new Error(
20656
- `GitHub API error ${res.status} for ${url}: ${(await res.text()).slice(0, 300)}`
20657
- );
21315
+ throw new Error(
21316
+ `GitHub API error ${res.status} for ${url}: ${(await res.text()).slice(0, 300)}`
21317
+ );
21318
+ }
21319
+ return await res.json();
21320
+ }
21321
+ async function fetchGitHubOrgActivity(scope, token, options = {}) {
21322
+ const perPage = options.perPage ?? 100;
21323
+ const headers = {
21324
+ Authorization: `token ${token}`,
21325
+ Accept: "application/vnd.github.v3+json",
21326
+ "User-Agent": "neuroverseos-radiant"
21327
+ };
21328
+ const repos = await fetchJSON(
21329
+ `https://api.github.com/orgs/${scope.owner}/repos?sort=pushed&direction=desc&per_page=${perPage}`,
21330
+ headers
21331
+ );
21332
+ const windowDays = options.windowDays ?? 14;
21333
+ const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
21334
+ const activeRepos = repos.filter(
21335
+ (r) => new Date(r.pushed_at) >= since
21336
+ );
21337
+ const cappedRepos = activeRepos.slice(0, 10);
21338
+ const allEvents = [];
21339
+ const repoNames = [];
21340
+ for (const repo of cappedRepos) {
21341
+ const [owner, repoName] = repo.full_name.split("/");
21342
+ try {
21343
+ const repoScope = { type: "repo", owner, repo: repoName };
21344
+ const events = await fetchGitHubActivity(repoScope, token, options);
21345
+ allEvents.push(...events);
21346
+ if (events.length > 0) repoNames.push(repo.full_name);
21347
+ } catch {
21348
+ }
20658
21349
  }
20659
- return await res.json();
21350
+ allEvents.sort(
21351
+ (a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp)
21352
+ );
21353
+ return { events: allEvents, repos: repoNames };
20660
21354
  }
20661
21355
  var KNOWN_AI_LOGINS, KNOWN_AI_CO_AUTHOR_NAMES;
20662
21356
  var init_github2 = __esm({
@@ -20680,16 +21374,491 @@ var init_github2 = __esm({
20680
21374
  }
20681
21375
  });
20682
21376
 
21377
+ // src/radiant/adapters/discord.ts
21378
+ async function fetchDiscordActivity(guildId, token, options = {}) {
21379
+ const windowDays = options.windowDays ?? 14;
21380
+ const perChannel = options.perChannel ?? 100;
21381
+ const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
21382
+ const headers = {
21383
+ Authorization: `Bot ${token}`,
21384
+ "Content-Type": "application/json"
21385
+ };
21386
+ const channels = await fetchJSON2(
21387
+ `https://discord.com/api/v10/guilds/${guildId}/channels`,
21388
+ headers
21389
+ );
21390
+ const textChannels = channels.filter((c) => {
21391
+ if (c.type !== 0) return false;
21392
+ if (options.channelIds && options.channelIds.length > 0) {
21393
+ return options.channelIds.includes(c.id);
21394
+ }
21395
+ if (options.visibility === "public") {
21396
+ return !c.name.startsWith("private-") && !c.nsfw;
21397
+ }
21398
+ return true;
21399
+ });
21400
+ const events = [];
21401
+ let totalMessages = 0;
21402
+ let helpRequests = 0;
21403
+ let unresolvedThreads = 0;
21404
+ let newcomerMessages = 0;
21405
+ const responseTimes = [];
21406
+ const participants = /* @__PURE__ */ new Set();
21407
+ const knownParticipants = /* @__PURE__ */ new Set();
21408
+ const topicCounts = /* @__PURE__ */ new Map();
21409
+ for (const channel of textChannels.slice(0, 15)) {
21410
+ try {
21411
+ const messages = await fetchJSON2(
21412
+ `https://discord.com/api/v10/channels/${channel.id}/messages?limit=${perChannel}`,
21413
+ headers
21414
+ );
21415
+ const inWindow = messages.filter(
21416
+ (m) => new Date(m.timestamp) >= since
21417
+ );
21418
+ totalMessages += inWindow.length;
21419
+ const topic = channel.name.replace(/-/g, " ");
21420
+ topicCounts.set(topic, (topicCounts.get(topic) ?? 0) + inWindow.length);
21421
+ for (const msg of inWindow) {
21422
+ const actor = mapDiscordUser(msg.author);
21423
+ participants.add(actor.id);
21424
+ const lowerContent = msg.content.toLowerCase();
21425
+ if (lowerContent.includes("help") || lowerContent.includes("stuck") || lowerContent.includes("how do i") || lowerContent.includes("anyone know")) {
21426
+ helpRequests++;
21427
+ }
21428
+ if (msg.referenced_message) {
21429
+ const refTime = new Date(msg.referenced_message.timestamp).getTime();
21430
+ const msgTime = new Date(msg.timestamp).getTime();
21431
+ const diffMinutes = (msgTime - refTime) / 6e4;
21432
+ if (diffMinutes > 0 && diffMinutes < 10080) {
21433
+ responseTimes.push(diffMinutes);
21434
+ }
21435
+ }
21436
+ events.push({
21437
+ id: `discord-${msg.id}`,
21438
+ timestamp: msg.timestamp,
21439
+ actor,
21440
+ kind: "discord_message",
21441
+ content: msg.content.slice(0, 500),
21442
+ respondsTo: msg.referenced_message ? {
21443
+ eventId: `discord-${msg.referenced_message.id}`,
21444
+ actor: mapDiscordUser(msg.referenced_message.author)
21445
+ } : void 0,
21446
+ metadata: {
21447
+ channel: channel.name,
21448
+ guildId
21449
+ }
21450
+ });
21451
+ }
21452
+ } catch {
21453
+ }
21454
+ }
21455
+ const avgResponseMinutes = responseTimes.length > 0 ? responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length : null;
21456
+ const topTopics = [...topicCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([t]) => t);
21457
+ const signals = {
21458
+ totalMessages,
21459
+ activeChannels: textChannels.length,
21460
+ uniqueParticipants: participants.size,
21461
+ avgResponseMinutes: avgResponseMinutes ? Math.round(avgResponseMinutes) : null,
21462
+ helpRequests,
21463
+ unresolvedThreads,
21464
+ topTopics,
21465
+ newcomerMessages
21466
+ };
21467
+ events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
21468
+ return { events, signals };
21469
+ }
21470
+ function formatDiscordSignalsForPrompt(signals) {
21471
+ if (signals.totalMessages === 0) return "";
21472
+ const lines = [
21473
+ "## Discord Activity (conversational behavior)",
21474
+ "",
21475
+ `${signals.totalMessages} messages across ${signals.activeChannels} channels.`,
21476
+ `${signals.uniqueParticipants} unique participants.`
21477
+ ];
21478
+ if (signals.avgResponseMinutes !== null) {
21479
+ lines.push(`Average response time: ${signals.avgResponseMinutes} minutes.`);
21480
+ }
21481
+ if (signals.helpRequests > 0) {
21482
+ lines.push(`${signals.helpRequests} help requests detected.`);
21483
+ }
21484
+ if (signals.unresolvedThreads > 0) {
21485
+ lines.push(`${signals.unresolvedThreads} unresolved threads.`);
21486
+ }
21487
+ if (signals.topTopics.length > 0) {
21488
+ lines.push(`Top discussion topics: ${signals.topTopics.join(", ")}.`);
21489
+ }
21490
+ lines.push("");
21491
+ lines.push("Compare conversational activity against GitHub shipping activity.");
21492
+ lines.push("Where debates happen in Discord but nothing ships in GitHub, name the gap.");
21493
+ lines.push("Where work ships in GitHub but nobody discusses it in Discord, name the visibility gap.");
21494
+ return lines.join("\n");
21495
+ }
21496
+ function mapDiscordUser(user) {
21497
+ return {
21498
+ id: user.username,
21499
+ kind: user.bot ? "bot" : "human",
21500
+ name: user.username
21501
+ };
21502
+ }
21503
+ async function fetchJSON2(url, headers) {
21504
+ const res = await fetch(url, { headers });
21505
+ if (!res.ok) {
21506
+ if (res.status === 404 || res.status === 403) return [];
21507
+ throw new Error(`Discord API error ${res.status}: ${(await res.text()).slice(0, 300)}`);
21508
+ }
21509
+ return await res.json();
21510
+ }
21511
+ var init_discord = __esm({
21512
+ "src/radiant/adapters/discord.ts"() {
21513
+ "use strict";
21514
+ }
21515
+ });
21516
+
21517
+ // src/radiant/adapters/slack.ts
21518
+ async function fetchSlackActivity(token, options = {}) {
21519
+ const windowDays = options.windowDays ?? 14;
21520
+ const perChannel = options.perChannel ?? 100;
21521
+ const oldest = String(
21522
+ Math.floor((Date.now() - windowDays * 24 * 60 * 60 * 1e3) / 1e3)
21523
+ );
21524
+ const headers = {
21525
+ Authorization: `Bearer ${token}`,
21526
+ "Content-Type": "application/json"
21527
+ };
21528
+ const channelsResponse = await fetchSlackAPI("https://slack.com/api/conversations.list?types=public_channel&limit=200", headers);
21529
+ let channels = channelsResponse.channels ?? [];
21530
+ if (options.channelIds && options.channelIds.length > 0) {
21531
+ const ids = new Set(options.channelIds);
21532
+ channels = channels.filter((c) => ids.has(c.id));
21533
+ }
21534
+ if (options.visibility === "public") {
21535
+ channels = channels.filter((c) => !c.is_private && !c.is_archived);
21536
+ }
21537
+ const events = [];
21538
+ let totalMessages = 0;
21539
+ let reactionCount = 0;
21540
+ let unresolvedThreads = 0;
21541
+ const responseTimes = [];
21542
+ const participants = /* @__PURE__ */ new Set();
21543
+ const externalParticipants = /* @__PURE__ */ new Set();
21544
+ const channelMessageCounts = /* @__PURE__ */ new Map();
21545
+ for (const channel of channels.slice(0, 15)) {
21546
+ try {
21547
+ const historyResponse = await fetchSlackAPI(
21548
+ `https://slack.com/api/conversations.history?channel=${channel.id}&limit=${perChannel}&oldest=${oldest}`,
21549
+ headers
21550
+ );
21551
+ const messages = historyResponse.messages ?? [];
21552
+ totalMessages += messages.length;
21553
+ channelMessageCounts.set(channel.name, messages.length);
21554
+ for (const msg of messages) {
21555
+ if (msg.subtype === "channel_join" || msg.subtype === "channel_leave") continue;
21556
+ const actor = mapSlackUser(msg.user ?? "unknown");
21557
+ participants.add(actor.id);
21558
+ if (msg.reactions) {
21559
+ reactionCount += msg.reactions.reduce(
21560
+ (sum, r) => sum + (r.count ?? 0),
21561
+ 0
21562
+ );
21563
+ }
21564
+ if (msg.thread_ts && msg.thread_ts !== msg.ts) {
21565
+ const parentTs = parseFloat(msg.thread_ts) * 1e3;
21566
+ const msgTs = parseFloat(msg.ts) * 1e3;
21567
+ const diffMinutes = (msgTs - parentTs) / 6e4;
21568
+ if (diffMinutes > 0 && diffMinutes < 10080) {
21569
+ responseTimes.push(diffMinutes);
21570
+ }
21571
+ }
21572
+ if (msg.thread_ts === msg.ts && (!msg.reply_count || msg.reply_count === 0)) {
21573
+ if (msg.text && (msg.text.includes("?") || msg.text.toLowerCase().includes("help"))) {
21574
+ unresolvedThreads++;
21575
+ }
21576
+ }
21577
+ const timestamp = new Date(parseFloat(msg.ts) * 1e3).toISOString();
21578
+ events.push({
21579
+ id: `slack-${msg.ts}`,
21580
+ timestamp,
21581
+ actor,
21582
+ kind: "slack_message",
21583
+ content: (msg.text ?? "").slice(0, 500),
21584
+ respondsTo: msg.thread_ts && msg.thread_ts !== msg.ts ? {
21585
+ eventId: `slack-${msg.thread_ts}`,
21586
+ actor: { id: "thread-parent", kind: "unknown" }
21587
+ } : void 0,
21588
+ metadata: {
21589
+ channel: channel.name,
21590
+ isPrivate: channel.is_private,
21591
+ hasReactions: (msg.reactions?.length ?? 0) > 0
21592
+ }
21593
+ });
21594
+ }
21595
+ } catch {
21596
+ }
21597
+ }
21598
+ const avgResponseMinutes = responseTimes.length > 0 ? Math.round(responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length) : null;
21599
+ const topChannels = [...channelMessageCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([name]) => name);
21600
+ const signals = {
21601
+ totalMessages,
21602
+ activeChannels: channelMessageCounts.size,
21603
+ uniqueParticipants: participants.size,
21604
+ avgResponseMinutes,
21605
+ externalParticipants: externalParticipants.size,
21606
+ unresolvedThreads,
21607
+ topChannels,
21608
+ reactionCount
21609
+ };
21610
+ events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
21611
+ return { events, signals };
21612
+ }
21613
+ function formatSlackSignalsForPrompt(signals) {
21614
+ if (signals.totalMessages === 0) return "";
21615
+ const lines = [
21616
+ "## Slack Activity (external coordination)",
21617
+ "",
21618
+ `${signals.totalMessages} messages across ${signals.activeChannels} channels.`,
21619
+ `${signals.uniqueParticipants} unique participants.`
21620
+ ];
21621
+ if (signals.avgResponseMinutes !== null) {
21622
+ lines.push(`Average thread response time: ${signals.avgResponseMinutes} minutes.`);
21623
+ }
21624
+ if (signals.unresolvedThreads > 0) {
21625
+ lines.push(`${signals.unresolvedThreads} questions/threads with no reply.`);
21626
+ }
21627
+ if (signals.reactionCount > 0) {
21628
+ lines.push(`${signals.reactionCount} reactions (engagement signal).`);
21629
+ }
21630
+ if (signals.topChannels.length > 0) {
21631
+ lines.push(`Most active channels: ${signals.topChannels.join(", ")}.`);
21632
+ }
21633
+ lines.push("");
21634
+ lines.push("Slack carries external coordination \u2014 partner and client communication.");
21635
+ lines.push("Compare partner engagement against internal activity. Where partners are");
21636
+ lines.push("active but internal follow-through is low, name the gap.");
21637
+ return lines.join("\n");
21638
+ }
21639
+ function mapSlackUser(userId) {
21640
+ return {
21641
+ id: userId,
21642
+ kind: "human",
21643
+ name: userId
21644
+ };
21645
+ }
21646
+ async function fetchSlackAPI(url, headers) {
21647
+ const res = await fetch(url, { headers });
21648
+ if (!res.ok) {
21649
+ throw new Error(`Slack API error ${res.status}: ${(await res.text()).slice(0, 300)}`);
21650
+ }
21651
+ const data = await res.json();
21652
+ if (!data.ok) {
21653
+ throw new Error(`Slack API error: ${data.error ?? "unknown"}`);
21654
+ }
21655
+ return data;
21656
+ }
21657
+ var init_slack = __esm({
21658
+ "src/radiant/adapters/slack.ts"() {
21659
+ "use strict";
21660
+ }
21661
+ });
21662
+
21663
+ // src/radiant/adapters/notion.ts
21664
+ async function fetchNotionActivity(token, options = {}) {
21665
+ const windowDays = options.windowDays ?? 14;
21666
+ const maxPages = options.maxPages ?? 100;
21667
+ const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
21668
+ const headers = {
21669
+ Authorization: `Bearer ${token}`,
21670
+ "Notion-Version": "2022-06-28",
21671
+ "Content-Type": "application/json"
21672
+ };
21673
+ const searchResponse = await fetchNotionAPI("https://api.notion.com/v1/search", headers, {
21674
+ method: "POST",
21675
+ body: JSON.stringify({
21676
+ filter: { property: "object", value: "page" },
21677
+ sort: { direction: "descending", timestamp: "last_edited_time" },
21678
+ page_size: maxPages
21679
+ })
21680
+ });
21681
+ const pages = searchResponse.results ?? [];
21682
+ const events = [];
21683
+ const editors = /* @__PURE__ */ new Set();
21684
+ let pagesCreated = 0;
21685
+ let pagesUpdated = 0;
21686
+ let stalePages = 0;
21687
+ const editAges = [];
21688
+ const topPages = [];
21689
+ const now = Date.now();
21690
+ for (const page of pages) {
21691
+ const lastEdited = new Date(page.last_edited_time);
21692
+ const created = new Date(page.created_time);
21693
+ const daysSinceEdit = (now - lastEdited.getTime()) / (24 * 60 * 60 * 1e3);
21694
+ editAges.push(daysSinceEdit);
21695
+ if (daysSinceEdit > 30) stalePages++;
21696
+ const title = extractTitle(page);
21697
+ const editorId = page.last_edited_by?.id ?? "unknown";
21698
+ editors.add(editorId);
21699
+ if (lastEdited >= since) {
21700
+ const isNew = created >= since;
21701
+ if (isNew) pagesCreated++;
21702
+ else pagesUpdated++;
21703
+ topPages.push({ title, editedAt: page.last_edited_time });
21704
+ events.push({
21705
+ id: `notion-${page.id}`,
21706
+ timestamp: page.last_edited_time,
21707
+ actor: {
21708
+ id: editorId,
21709
+ kind: "human",
21710
+ name: editorId
21711
+ },
21712
+ kind: isNew ? "doc_created" : "doc_updated",
21713
+ content: `${isNew ? "Created" : "Updated"}: ${title}`,
21714
+ metadata: {
21715
+ pageId: page.id,
21716
+ url: page.url,
21717
+ createdAt: page.created_time
21718
+ }
21719
+ });
21720
+ }
21721
+ }
21722
+ const avgDaysSinceEdit = editAges.length > 0 ? Math.round(editAges.reduce((a, b) => a + b, 0) / editAges.length) : null;
21723
+ const signals = {
21724
+ pagesActive: pagesCreated + pagesUpdated,
21725
+ pagesCreated,
21726
+ pagesUpdated,
21727
+ uniqueEditors: editors.size,
21728
+ stalePages,
21729
+ avgDaysSinceEdit,
21730
+ topPages: topPages.slice(0, 5).map((p) => p.title)
21731
+ };
21732
+ events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
21733
+ return { events, signals };
21734
+ }
21735
+ function formatNotionSignalsForPrompt(signals) {
21736
+ if (signals.pagesActive === 0 && signals.stalePages === 0) return "";
21737
+ const lines = [
21738
+ "## Notion Activity (documentation behavior)",
21739
+ "",
21740
+ `${signals.pagesActive} pages active in window (${signals.pagesCreated} created, ${signals.pagesUpdated} updated).`,
21741
+ `${signals.uniqueEditors} unique editors.`
21742
+ ];
21743
+ if (signals.stalePages > 0) {
21744
+ lines.push(`${signals.stalePages} pages haven't been touched in 30+ days.`);
21745
+ }
21746
+ if (signals.avgDaysSinceEdit !== null) {
21747
+ lines.push(`Average page age since last edit: ${signals.avgDaysSinceEdit} days.`);
21748
+ }
21749
+ if (signals.topPages.length > 0) {
21750
+ lines.push(`Recently active pages: ${signals.topPages.join(", ")}.`);
21751
+ }
21752
+ lines.push("");
21753
+ lines.push("Documentation is how the team crystallizes and shares knowledge.");
21754
+ lines.push("High code velocity + low documentation = building without recording.");
21755
+ lines.push("High documentation + low code = planning without shipping.");
21756
+ lines.push("Compare Notion activity against GitHub and Discord to find the balance.");
21757
+ return lines.join("\n");
21758
+ }
21759
+ function extractTitle(page) {
21760
+ for (const prop of Object.values(page.properties)) {
21761
+ if (prop.type === "title" && prop.title) {
21762
+ return prop.title.map((t) => t.plain_text).join("") || "Untitled";
21763
+ }
21764
+ }
21765
+ return "Untitled";
21766
+ }
21767
+ async function fetchNotionAPI(url, headers, init) {
21768
+ const res = await fetch(url, {
21769
+ method: init?.method ?? "GET",
21770
+ headers,
21771
+ body: init?.body
21772
+ });
21773
+ if (!res.ok) {
21774
+ throw new Error(
21775
+ `Notion API error ${res.status}: ${(await res.text()).slice(0, 300)}`
21776
+ );
21777
+ }
21778
+ return await res.json();
21779
+ }
21780
+ var init_notion = __esm({
21781
+ "src/radiant/adapters/notion.ts"() {
21782
+ "use strict";
21783
+ }
21784
+ });
21785
+
21786
+ // src/radiant/core/discovery.ts
21787
+ function discoverWorlds(options) {
21788
+ const worlds = [];
21789
+ const userDir = options?.userWorldsDir ?? (0, import_path14.join)((0, import_os5.homedir)(), ".neuroverse", "worlds");
21790
+ if ((0, import_fs13.existsSync)(userDir)) {
21791
+ worlds.push(...loadWorldsFromDir(userDir, "user"));
21792
+ }
21793
+ if (options?.explicitWorldsDir) {
21794
+ worlds.push(...loadWorldsFromDir(options.explicitWorldsDir, "repo"));
21795
+ } else if (options?.repoDir) {
21796
+ const repoPaths = [
21797
+ (0, import_path14.join)(options.repoDir, "worlds"),
21798
+ (0, import_path14.join)(options.repoDir, ".neuroverse", "worlds")
21799
+ ];
21800
+ for (const p of repoPaths) {
21801
+ if ((0, import_fs13.existsSync)(p)) {
21802
+ worlds.push(...loadWorldsFromDir(p, "repo"));
21803
+ break;
21804
+ }
21805
+ }
21806
+ }
21807
+ const combinedContent = worlds.map((w) => `<!-- world: ${w.name} (${w.source}) -->
21808
+ ${w.content}`).join("\n\n---\n\n");
21809
+ const summary2 = worlds.length === 0 ? "no worlds discovered" : worlds.map((w) => `${w.name} (${w.source})`).join(", ");
21810
+ return { worlds, combinedContent, summary: summary2 };
21811
+ }
21812
+ function loadWorldsFromDir(dirPath, source) {
21813
+ const dir = (0, import_path14.resolve)(dirPath);
21814
+ if (!(0, import_fs13.existsSync)(dir)) return [];
21815
+ const stat = (0, import_fs13.statSync)(dir);
21816
+ if (stat.isFile() && dir.endsWith(".md")) {
21817
+ try {
21818
+ return [{
21819
+ name: (0, import_path14.basename)(dir).replace(/\.worldmodel\.md$/, "").replace(/\.nv-world\.md$/, ""),
21820
+ source,
21821
+ path: dir,
21822
+ content: (0, import_fs13.readFileSync)(dir, "utf-8")
21823
+ }];
21824
+ } catch {
21825
+ return [];
21826
+ }
21827
+ }
21828
+ if (!stat.isDirectory()) return [];
21829
+ const files = (0, import_fs13.readdirSync)(dir).filter(
21830
+ (f) => f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md")
21831
+ ).sort();
21832
+ return files.map((f) => {
21833
+ const fullPath = (0, import_path14.join)(dir, f);
21834
+ return {
21835
+ name: f.replace(/\.worldmodel\.md$/, "").replace(/\.nv-world\.md$/, ""),
21836
+ source,
21837
+ path: fullPath,
21838
+ content: (0, import_fs13.readFileSync)(fullPath, "utf-8")
21839
+ };
21840
+ });
21841
+ }
21842
+ var import_fs13, import_path14, import_os5;
21843
+ var init_discovery = __esm({
21844
+ "src/radiant/core/discovery.ts"() {
21845
+ "use strict";
21846
+ import_fs13 = require("fs");
21847
+ import_path14 = require("path");
21848
+ import_os5 = require("os");
21849
+ }
21850
+ });
21851
+
20683
21852
  // src/radiant/adapters/exocortex.ts
20684
- function readExocortex(dirPath) {
20685
- const dir = (0, import_path13.resolve)(dirPath);
21853
+ function readExocortex(dirPath, repoName) {
21854
+ const dir = (0, import_path15.resolve)(dirPath);
20686
21855
  let filesLoaded = 0;
20687
21856
  function tryRead(...paths) {
20688
21857
  for (const p of paths) {
20689
- const full = (0, import_path13.join)(dir, p);
20690
- if ((0, import_fs12.existsSync)(full)) {
21858
+ const full = (0, import_path15.join)(dir, p);
21859
+ if ((0, import_fs14.existsSync)(full)) {
20691
21860
  try {
20692
- const content = (0, import_fs12.readFileSync)(full, "utf-8").trim();
21861
+ const content = (0, import_fs14.readFileSync)(full, "utf-8").trim();
20693
21862
  if (content) {
20694
21863
  filesLoaded++;
20695
21864
  return content;
@@ -20700,55 +21869,65 @@ function readExocortex(dirPath) {
20700
21869
  }
20701
21870
  return null;
20702
21871
  }
21872
+ const attention = tryRead("attention.md");
21873
+ const goals = tryRead("goals.md");
21874
+ const identity = tryRead("identity.md", "user.md");
21875
+ const organization = tryRead("org/organization.md", "org/src/organization.md");
21876
+ const methods = tryRead("org/methods.md", "org/src/methods.md");
21877
+ let sprint = null;
21878
+ let projectContext = null;
21879
+ if (repoName) {
21880
+ const projectPaths = [
21881
+ repoName,
21882
+ repoName.toLowerCase(),
21883
+ repoName.replace(/-/g, "_")
21884
+ ];
21885
+ for (const projectDir of projectPaths) {
21886
+ const projectSprint = tryRead(
21887
+ `${projectDir}/src/sprint.md`,
21888
+ `${projectDir}/sprint.md`
21889
+ );
21890
+ if (projectSprint) {
21891
+ sprint = projectSprint;
21892
+ break;
21893
+ }
21894
+ }
21895
+ for (const projectDir of projectPaths) {
21896
+ const roadmap = tryRead(
21897
+ `${projectDir}/roadmap.md`,
21898
+ `${projectDir}/src/roadmap.md`
21899
+ );
21900
+ if (roadmap) {
21901
+ projectContext = roadmap;
21902
+ break;
21903
+ }
21904
+ }
21905
+ }
21906
+ if (!sprint) {
21907
+ sprint = tryRead("sprint.md", "src/sprint.md");
21908
+ }
20703
21909
  const ctx = {
20704
- attention: tryRead("attention.md"),
20705
- goals: tryRead("goals.md"),
20706
- identity: tryRead("identity.md"),
20707
- sprint: tryRead("sprint.md", "src/sprint.md"),
20708
- organization: tryRead("org/organization.md", "org/src/organization.md"),
20709
- methods: tryRead("org/methods.md", "org/src/methods.md"),
21910
+ attention,
21911
+ goals,
21912
+ identity,
21913
+ sprint,
21914
+ organization,
21915
+ methods,
20710
21916
  source: dir,
20711
21917
  filesLoaded
20712
21918
  };
20713
- return ctx;
20714
- }
20715
- function formatExocortexForPrompt(ctx) {
20716
- if (ctx.filesLoaded === 0) return "";
20717
- const sections = [];
20718
- sections.push(
20719
- "## Stated Intent (from exocortex)\n\nThe following is what the person/team SAYS they are doing, focused on, and working toward. Compare this against the ACTUAL activity from GitHub. Where stated intent and observed behavior diverge, that gap is the most valuable signal in this read. Name it directly."
20720
- );
20721
- if (ctx.attention) {
20722
- sections.push(`### Current attention
20723
-
20724
- ${ctx.attention}`);
20725
- }
20726
- if (ctx.goals) {
20727
- sections.push(`### Goals
20728
-
20729
- ${ctx.goals}`);
20730
- }
20731
- if (ctx.sprint) {
20732
- sections.push(`### Sprint focus
20733
-
20734
- ${ctx.sprint}`);
20735
- }
20736
- if (ctx.identity) {
20737
- sections.push(`### Identity and values
20738
-
20739
- ${ctx.identity}`);
20740
- }
20741
- if (ctx.organization) {
20742
- sections.push(`### Organization
20743
-
20744
- ${ctx.organization}`);
20745
- }
20746
- if (ctx.methods) {
20747
- sections.push(`### Methods
21919
+ if (projectContext && ctx.sprint) {
21920
+ ctx.sprint = `${ctx.sprint}
20748
21921
 
20749
- ${ctx.methods}`);
21922
+ ---
21923
+ Project roadmap:
21924
+ ${projectContext}`;
21925
+ } else if (projectContext) {
21926
+ ctx.sprint = `Project roadmap:
21927
+ ${projectContext}`;
21928
+ ctx.filesLoaded++;
20750
21929
  }
20751
- return sections.join("\n\n");
21930
+ return ctx;
20752
21931
  }
20753
21932
  function summarizeExocortex(ctx) {
20754
21933
  if (ctx.filesLoaded === 0) return "no exocortex files found";
@@ -20761,33 +21940,33 @@ function summarizeExocortex(ctx) {
20761
21940
  if (ctx.methods) loaded.push("methods");
20762
21941
  return `${loaded.join(", ")} (${ctx.filesLoaded} files)`;
20763
21942
  }
20764
- var import_fs12, import_path13;
21943
+ var import_fs14, import_path15;
20765
21944
  var init_exocortex = __esm({
20766
21945
  "src/radiant/adapters/exocortex.ts"() {
20767
21946
  "use strict";
20768
- import_fs12 = require("fs");
20769
- import_path13 = require("path");
21947
+ import_fs14 = require("fs");
21948
+ import_path15 = require("path");
20770
21949
  }
20771
21950
  });
20772
21951
 
20773
21952
  // src/radiant/memory/palace.ts
20774
21953
  function writeRead(exocortexDir, frontmatter, text) {
20775
- const dir = (0, import_path14.resolve)(exocortexDir, "radiant", "reads");
20776
- (0, import_fs13.mkdirSync)(dir, { recursive: true });
21954
+ const dir = (0, import_path16.resolve)(exocortexDir, "radiant", "reads");
21955
+ (0, import_fs15.mkdirSync)(dir, { recursive: true });
20777
21956
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
20778
21957
  const filename = `${date}.md`;
20779
- const filepath = (0, import_path14.join)(dir, filename);
21958
+ const filepath = (0, import_path16.join)(dir, filename);
20780
21959
  const content = `${frontmatter}
20781
21960
 
20782
21961
  ${text}
20783
21962
  `;
20784
- (0, import_fs13.writeFileSync)(filepath, content, "utf-8");
21963
+ (0, import_fs15.writeFileSync)(filepath, content, "utf-8");
20785
21964
  return filepath;
20786
21965
  }
20787
21966
  function updateKnowledge(exocortexDir, persistence, options) {
20788
- const dir = (0, import_path14.resolve)(exocortexDir, "radiant");
20789
- (0, import_fs13.mkdirSync)(dir, { recursive: true });
20790
- const filepath = (0, import_path14.join)(dir, "knowledge.md");
21967
+ const dir = (0, import_path16.resolve)(exocortexDir, "radiant");
21968
+ (0, import_fs15.mkdirSync)(dir, { recursive: true });
21969
+ const filepath = (0, import_path16.join)(dir, "knowledge.md");
20791
21970
  const totalReads = options?.totalReads ?? 0;
20792
21971
  const existingUntriggered = loadUntriggeredCounts(filepath);
20793
21972
  const lines = [
@@ -20874,14 +22053,14 @@ function updateKnowledge(exocortexDir, persistence, options) {
20874
22053
  lines.push(`${name}=${count}`);
20875
22054
  }
20876
22055
  lines.push("-->");
20877
- (0, import_fs13.writeFileSync)(filepath, lines.join("\n"), "utf-8");
22056
+ (0, import_fs15.writeFileSync)(filepath, lines.join("\n"), "utf-8");
20878
22057
  return filepath;
20879
22058
  }
20880
22059
  function loadUntriggeredCounts(filepath) {
20881
22060
  const counts = /* @__PURE__ */ new Map();
20882
- if (!(0, import_fs13.existsSync)(filepath)) return counts;
22061
+ if (!(0, import_fs15.existsSync)(filepath)) return counts;
20883
22062
  try {
20884
- const content = (0, import_fs13.readFileSync)(filepath, "utf-8");
22063
+ const content = (0, import_fs15.readFileSync)(filepath, "utf-8");
20885
22064
  const match = content.match(
20886
22065
  /<!-- untriggered_counts[\s\S]*?-->/
20887
22066
  );
@@ -20899,13 +22078,13 @@ function loadUntriggeredCounts(filepath) {
20899
22078
  return counts;
20900
22079
  }
20901
22080
  function loadPriorReads(exocortexDir) {
20902
- const dir = (0, import_path14.resolve)(exocortexDir, "radiant", "reads");
20903
- if (!(0, import_fs13.existsSync)(dir)) return [];
20904
- const files = (0, import_fs13.readdirSync)(dir).filter((f) => f.endsWith(".md")).sort();
22081
+ const dir = (0, import_path16.resolve)(exocortexDir, "radiant", "reads");
22082
+ if (!(0, import_fs15.existsSync)(dir)) return [];
22083
+ const files = (0, import_fs15.readdirSync)(dir).filter((f) => f.endsWith(".md")).sort();
20905
22084
  const reads = [];
20906
22085
  for (const filename of files) {
20907
- const filepath = (0, import_path14.join)(dir, filename);
20908
- const content = (0, import_fs13.readFileSync)(filepath, "utf-8");
22086
+ const filepath = (0, import_path16.join)(dir, filename);
22087
+ const content = (0, import_fs15.readFileSync)(filepath, "utf-8");
20909
22088
  const date = filename.replace(".md", "");
20910
22089
  const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
20911
22090
  const frontmatter = fmMatch ? fmMatch[1] : "";
@@ -20939,33 +22118,12 @@ function computePersistence(priorReads, currentPatternNames) {
20939
22118
  dates: dates.sort()
20940
22119
  })).sort((a, b) => b.occurrences - a.occurrences);
20941
22120
  }
20942
- function formatPriorReadsForPrompt(priorReads) {
20943
- if (priorReads.length === 0) return "";
20944
- const lines = [
20945
- "## Prior Radiant reads (history)",
20946
- "",
20947
- `Radiant has run ${priorReads.length} time${priorReads.length > 1 ? "s" : ""} before on this scope.`,
20948
- "If you see patterns that appeared in prior reads, note their persistence.",
20949
- "Patterns that recur across 3+ reads are strong candidates for declaration in the strategy file.",
20950
- ""
20951
- ];
20952
- for (const read of priorReads.slice(-4)) {
20953
- lines.push(`### Read from ${read.date}`);
20954
- if (read.patternNames.length > 0) {
20955
- lines.push(`Patterns observed: ${read.patternNames.join(", ")}`);
20956
- } else {
20957
- lines.push("No patterns extracted from frontmatter.");
20958
- }
20959
- lines.push("");
20960
- }
20961
- return lines.join("\n");
20962
- }
20963
- var import_fs13, import_path14;
22121
+ var import_fs15, import_path16;
20964
22122
  var init_palace = __esm({
20965
22123
  "src/radiant/memory/palace.ts"() {
20966
22124
  "use strict";
20967
- import_fs13 = require("fs");
20968
- import_path14 = require("path");
22125
+ import_fs15 = require("fs");
22126
+ import_path16 = require("path");
20969
22127
  }
20970
22128
  });
20971
22129
 
@@ -21318,15 +22476,17 @@ function buildInterpretationPrompt(input) {
21318
22476
  const eventSample = formatEventSample(input.events, 30);
21319
22477
  const canonicalList = (input.canonicalPatterns ?? []).length > 0 ? `Patterns the organization has already named (use these names if you see them):
21320
22478
  ${input.canonicalPatterns.map((p) => `- ${p}`).join("\n")}` : "No patterns have been named yet. Everything you observe is new.";
22479
+ const compressedWorld = compressWorldmodel(input.worldmodelContent);
22480
+ const cl = compressLens(input.lens);
21321
22481
  const frame = input.lens.primary_frame;
21322
22482
  const evalQuestions = frame.evaluation_questions.map((q, i) => `${i + 1}. ${q}`).join("\n");
21323
- const forbiddenList = input.lens.forbidden_phrases.map((p) => `- "${p}"`).join("\n");
21324
- const jargonTable = Object.entries(input.lens.vocabulary.jargon_translations).map(([internal, plain]) => ` "${internal}" \u2192 "${plain}"`).join("\n");
22483
+ const forbiddenList = cl.forbiddenPhrases;
22484
+ const jargonTable = cl.jargonTranslations;
21325
22485
  return `You are a behavioral intelligence system reading team activity and producing a read for the reader who needs to act on it.
21326
22486
 
21327
- ## Context the reader has loaded
22487
+ ## Worldmodel (compressed)
21328
22488
 
21329
- ${input.worldmodelContent}
22489
+ ${compressedWorld}
21330
22490
 
21331
22491
  ## What happened this window
21332
22492
 
@@ -21372,6 +22532,14 @@ ${jargonTable}
21372
22532
 
21373
22533
  For example: don't say "update the worldmodel." Say "add a line to your strategy file."
21374
22534
 
22535
+ ## When the same invariant keeps firing
22536
+
22537
+ If the prior read history or the current evidence shows the same worldmodel invariant being triggered repeatedly (by the same side \u2014 human or AI), name it in MEANING and ask the real question:
22538
+
22539
+ "This invariant has been tested N times across M reads. Always on the [human/AI] side. Either the team needs alignment on WHY this rule exists \u2014 or the team is telling you something the worldmodel hasn't absorbed yet."
22540
+
22541
+ Don't just say "invariant held." Say what it means that people keep pushing against the same wall.
22542
+
21375
22543
  ## Health is a valid read
21376
22544
 
21377
22545
  If the activity is healthy and aligned with the worldmodel, SAY SO. Don't fabricate problems. Over-prescription is a voice failure. Legitimate outputs include:
@@ -21497,6 +22665,7 @@ function isPatternLike(x) {
21497
22665
  var init_patterns = __esm({
21498
22666
  "src/radiant/core/patterns.ts"() {
21499
22667
  "use strict";
22668
+ init_compress();
21500
22669
  }
21501
22670
  });
21502
22671
 
@@ -21514,30 +22683,16 @@ Window: last ${input.windowDays} days \xB7 ${input.eventCount} events
21514
22683
  Lens: ${input.lens.name}`
21515
22684
  );
21516
22685
  if (input.patterns.length > 0) {
21517
- const canonical = input.patterns.filter((p) => p.type === "canonical");
21518
- const candidates = input.patterns.filter((p) => p.type === "candidate");
21519
22686
  let emergentBlock = "EMERGENT\n";
21520
- if (canonical.length > 0) {
21521
- for (const p of canonical) {
21522
- emergentBlock += `
22687
+ for (const p of input.patterns) {
22688
+ emergentBlock += `
21523
22689
  ${p.name}
21524
22690
  `;
21525
- emergentBlock += ` ${p.description}
21526
- `;
21527
- }
21528
- }
21529
- if (candidates.length > 0) {
21530
- emergentBlock += "\n Emergent (candidates \u2014 not yet in worldmodel)\n";
21531
- for (const p of candidates) {
21532
- emergentBlock += `
21533
- ${p.name} (candidate)
21534
- `;
21535
- emergentBlock += ` ${p.description}
22691
+ emergentBlock += ` ${p.description}
21536
22692
  `;
21537
- if (p.evidence.cited_invariant) {
21538
- emergentBlock += ` Cited invariant: ${p.evidence.cited_invariant}
22693
+ if (p.evidence.cited_invariant) {
22694
+ emergentBlock += ` Cited invariant: ${p.evidence.cited_invariant}
21539
22695
  `;
21540
- }
21541
22696
  }
21542
22697
  }
21543
22698
  sections.push(emergentBlock.trimEnd());
@@ -21756,21 +22911,80 @@ var init_renderer = __esm({
21756
22911
  async function emergent(input) {
21757
22912
  const lens = resolveLens2(input.lensId);
21758
22913
  const windowDays = input.windowDays ?? 14;
22914
+ let worldStack;
22915
+ let worldmodelContent = input.worldmodelContent;
22916
+ if (!worldmodelContent || worldmodelContent.trim() === "") {
22917
+ worldStack = discoverWorlds({ explicitWorldsDir: input.worldPath });
22918
+ worldmodelContent = worldStack.combinedContent;
22919
+ }
21759
22920
  let statedIntent;
21760
22921
  let exocortexContext;
21761
22922
  let priorReadContext = "";
21762
22923
  if (input.exocortexPath) {
21763
- exocortexContext = readExocortex(input.exocortexPath);
21764
- const formatted = formatExocortexForPrompt(exocortexContext);
21765
- if (formatted) statedIntent = formatted;
22924
+ const repoName = input.scope.type === "repo" ? input.scope.repo : void 0;
22925
+ exocortexContext = readExocortex(input.exocortexPath, repoName);
22926
+ const compressed = compressExocortex(exocortexContext);
22927
+ if (compressed) {
22928
+ statedIntent = `## Stated Intent (from exocortex, compressed)
22929
+
22930
+ ${compressed}
22931
+
22932
+ Compare stated intent against actual GitHub activity. Gaps = drift.`;
22933
+ }
21766
22934
  const priorReads = loadPriorReads(input.exocortexPath);
21767
22935
  if (priorReads.length > 0) {
21768
- priorReadContext = formatPriorReadsForPrompt(priorReads);
22936
+ priorReadContext = compressPriorReads(priorReads);
21769
22937
  }
21770
22938
  }
21771
- const events = await fetchGitHubActivity(input.scope, input.githubToken, {
21772
- windowDays
21773
- });
22939
+ let events;
22940
+ let orgRepos;
22941
+ if (input.scope.type === "org") {
22942
+ const orgResult = await fetchGitHubOrgActivity(
22943
+ input.scope,
22944
+ input.githubToken,
22945
+ { windowDays }
22946
+ );
22947
+ events = orgResult.events;
22948
+ orgRepos = orgResult.repos;
22949
+ } else {
22950
+ events = await fetchGitHubActivity(input.scope, input.githubToken, {
22951
+ windowDays
22952
+ });
22953
+ }
22954
+ let adapterSignals = "";
22955
+ const activeAdapters = ["github"];
22956
+ const discordToken = process.env.DISCORD_TOKEN;
22957
+ const discordGuild = process.env.DISCORD_GUILD_ID;
22958
+ if (discordToken && discordGuild) {
22959
+ try {
22960
+ const discord = await fetchDiscordActivity(discordGuild, discordToken, { windowDays });
22961
+ events.push(...discord.events);
22962
+ adapterSignals += "\n\n" + formatDiscordSignalsForPrompt(discord.signals);
22963
+ activeAdapters.push("discord");
22964
+ } catch {
22965
+ }
22966
+ }
22967
+ const slackToken = process.env.SLACK_TOKEN;
22968
+ if (slackToken) {
22969
+ try {
22970
+ const slack = await fetchSlackActivity(slackToken, { windowDays });
22971
+ events.push(...slack.events);
22972
+ adapterSignals += "\n\n" + formatSlackSignalsForPrompt(slack.signals);
22973
+ activeAdapters.push("slack");
22974
+ } catch {
22975
+ }
22976
+ }
22977
+ const notionToken = process.env.NOTION_TOKEN;
22978
+ if (notionToken) {
22979
+ try {
22980
+ const notion = await fetchNotionActivity(notionToken, { windowDays });
22981
+ events.push(...notion.events);
22982
+ adapterSignals += "\n\n" + formatNotionSignalsForPrompt(notion.signals);
22983
+ activeAdapters.push("notion");
22984
+ } catch {
22985
+ }
22986
+ }
22987
+ events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
21774
22988
  const classified = classifyEvents(events);
21775
22989
  const signals = extractSignals(classified);
21776
22990
  const scores = computeScores(signals, input.worldmodelContent !== "");
@@ -21781,7 +22995,7 @@ async function emergent(input) {
21781
22995
  lens,
21782
22996
  ai: input.ai,
21783
22997
  canonicalPatterns: input.canonicalPatterns,
21784
- statedIntent: statedIntent ? statedIntent + (priorReadContext ? "\n\n" + priorReadContext : "") : priorReadContext || void 0
22998
+ statedIntent: [statedIntent, adapterSignals, priorReadContext].filter(Boolean).join("\n\n") || void 0
21785
22999
  });
21786
23000
  const rewrittenPatterns = patterns.map((p) => lens.rewrite(p));
21787
23001
  const allDescriptions = rewrittenPatterns.map((p) => p.description).join("\n");
@@ -21830,7 +23044,9 @@ async function emergent(input) {
21830
23044
  voiceClean: voiceViolations.length === 0,
21831
23045
  signals,
21832
23046
  scores,
21833
- eventCount: events.length
23047
+ eventCount: events.length,
23048
+ activeAdapters,
23049
+ worldStack
21834
23050
  };
21835
23051
  }
21836
23052
  function computeScores(signals, worldmodelLoaded) {
@@ -21885,8 +23101,13 @@ var init_emergent = __esm({
21885
23101
  "use strict";
21886
23102
  init_lenses();
21887
23103
  init_github2();
23104
+ init_discord();
23105
+ init_slack();
23106
+ init_notion();
23107
+ init_discovery();
21888
23108
  init_exocortex();
21889
23109
  init_palace();
23110
+ init_compress();
21890
23111
  init_governance();
21891
23112
  init_signals();
21892
23113
  init_math();
@@ -21943,22 +23164,22 @@ __export(server_exports, {
21943
23164
  startRadiantMcp: () => startRadiantMcp
21944
23165
  });
21945
23166
  function loadWorldmodelContent(worldsPath) {
21946
- const resolved = (0, import_path15.resolve)(worldsPath);
21947
- if (!(0, import_fs14.existsSync)(resolved)) {
23167
+ const resolved = (0, import_path17.resolve)(worldsPath);
23168
+ if (!(0, import_fs16.existsSync)(resolved)) {
21948
23169
  throw new Error(`Worlds path not found: ${resolved}`);
21949
23170
  }
21950
- const stat = (0, import_fs14.statSync)(resolved);
23171
+ const stat = (0, import_fs16.statSync)(resolved);
21951
23172
  if (stat.isFile()) {
21952
- return (0, import_fs14.readFileSync)(resolved, "utf-8");
23173
+ return (0, import_fs16.readFileSync)(resolved, "utf-8");
21953
23174
  }
21954
23175
  if (stat.isDirectory()) {
21955
- const files = (0, import_fs14.readdirSync)(resolved).filter(
21956
- (f) => (0, import_path15.extname)(f) === ".md" && (f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md"))
23176
+ const files = (0, import_fs16.readdirSync)(resolved).filter(
23177
+ (f) => (0, import_path17.extname)(f) === ".md" && (f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md"))
21957
23178
  ).sort();
21958
23179
  if (files.length === 0) {
21959
23180
  throw new Error(`No worldmodel files found in ${resolved}`);
21960
23181
  }
21961
- return files.map((f) => (0, import_fs14.readFileSync)((0, import_path15.join)(resolved, f), "utf-8")).join("\n\n---\n\n");
23182
+ return files.map((f) => (0, import_fs16.readFileSync)((0, import_path17.join)(resolved, f), "utf-8")).join("\n\n---\n\n");
21962
23183
  }
21963
23184
  throw new Error(`Worlds path is neither a file nor directory: ${resolved}`);
21964
23185
  }
@@ -21977,12 +23198,12 @@ async function startRadiantMcp(args) {
21977
23198
  const server = new RadiantMcpServer({ worldsPath, lensId, model });
21978
23199
  await server.start();
21979
23200
  }
21980
- var import_fs14, import_path15, TOOLS, RadiantMcpServer;
23201
+ var import_fs16, import_path17, TOOLS, RadiantMcpServer;
21981
23202
  var init_server = __esm({
21982
23203
  "src/radiant/mcp/server.ts"() {
21983
23204
  "use strict";
21984
- import_fs14 = require("fs");
21985
- import_path15 = require("path");
23205
+ import_fs16 = require("fs");
23206
+ import_path17 = require("path");
21986
23207
  init_think();
21987
23208
  init_emergent();
21988
23209
  init_ai();
@@ -22220,6 +23441,8 @@ function parseArgs27(argv) {
22220
23441
  query: void 0,
22221
23442
  model: void 0,
22222
23443
  exocortex: void 0,
23444
+ teamExocortex: void 0,
23445
+ view: void 0,
22223
23446
  json: false,
22224
23447
  help: false,
22225
23448
  rest: []
@@ -22247,6 +23470,12 @@ function parseArgs27(argv) {
22247
23470
  case "--exocortex":
22248
23471
  result.exocortex = argv[++i];
22249
23472
  break;
23473
+ case "--team-exocortex":
23474
+ result.teamExocortex = argv[++i];
23475
+ break;
23476
+ case "--view":
23477
+ result.view = argv[++i];
23478
+ break;
22250
23479
  case "--json":
22251
23480
  result.json = true;
22252
23481
  break;
@@ -22263,17 +23492,17 @@ function parseArgs27(argv) {
22263
23492
  return result;
22264
23493
  }
22265
23494
  function loadWorldmodelContent2(worldsPath) {
22266
- const resolved = (0, import_path16.resolve)(worldsPath);
22267
- if (!(0, import_fs15.existsSync)(resolved)) {
23495
+ const resolved = (0, import_path18.resolve)(worldsPath);
23496
+ if (!(0, import_fs17.existsSync)(resolved)) {
22268
23497
  throw new Error(`Worlds path not found: ${resolved}`);
22269
23498
  }
22270
- const stat = (0, import_fs15.statSync)(resolved);
23499
+ const stat = (0, import_fs17.statSync)(resolved);
22271
23500
  if (stat.isFile()) {
22272
- return (0, import_fs15.readFileSync)(resolved, "utf-8");
23501
+ return (0, import_fs17.readFileSync)(resolved, "utf-8");
22273
23502
  }
22274
23503
  if (stat.isDirectory()) {
22275
- const files = (0, import_fs15.readdirSync)(resolved).filter(
22276
- (f) => (0, import_path16.extname)(f) === ".md" && (f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md"))
23504
+ const files = (0, import_fs17.readdirSync)(resolved).filter(
23505
+ (f) => (0, import_path18.extname)(f) === ".md" && (f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md"))
22277
23506
  ).sort();
22278
23507
  if (files.length === 0) {
22279
23508
  throw new Error(
@@ -22281,7 +23510,7 @@ function loadWorldmodelContent2(worldsPath) {
22281
23510
  );
22282
23511
  }
22283
23512
  return files.map((f) => {
22284
- const content = (0, import_fs15.readFileSync)((0, import_path16.join)(resolved, f), "utf-8");
23513
+ const content = (0, import_fs17.readFileSync)((0, import_path18.join)(resolved, f), "utf-8");
22285
23514
  return `<!-- worldmodel: ${f} -->
22286
23515
  ${content}`;
22287
23516
  }).join("\n\n---\n\n");
@@ -22320,7 +23549,7 @@ ${DIM3}Set it to your Anthropic API key to use Radiant's AI features.${RESET3}
22320
23549
  query = args.rest.join(" ");
22321
23550
  }
22322
23551
  if (!query && !process.stdin.isTTY) {
22323
- query = (0, import_fs15.readFileSync)(0, "utf-8").trim();
23552
+ query = (0, import_fs17.readFileSync)(0, "utf-8").trim();
22324
23553
  }
22325
23554
  if (!query) {
22326
23555
  process.stderr.write(
@@ -22388,7 +23617,7 @@ async function cmdEmergent(args) {
22388
23617
  );
22389
23618
  process.exit(1);
22390
23619
  }
22391
- const scope = parseRepoScope(scopeStr);
23620
+ const scope = parseScope(scopeStr);
22392
23621
  const lensId = args.lens ?? process.env.RADIANT_LENS;
22393
23622
  if (!lensId) {
22394
23623
  process.stderr.write(
@@ -22426,6 +23655,15 @@ ${DIM3}Set it to a GitHub PAT with repo read access.${RESET3}
22426
23655
  const worldmodelContent = loadWorldmodelContent2(worldsPath);
22427
23656
  const model = args.model ?? process.env.RADIANT_MODEL;
22428
23657
  const ai = createAnthropicAI(anthropicKey, model || void 0);
23658
+ const view = args.view ?? process.env.RADIANT_VIEW ?? "community";
23659
+ const validViews = ["community", "team", "full"];
23660
+ if (!validViews.includes(view)) {
23661
+ process.stderr.write(
23662
+ `${RED2}Error:${RESET3} --view must be community, team, or full. Got "${view}".
23663
+ `
23664
+ );
23665
+ process.exit(1);
23666
+ }
22429
23667
  const exocortexPath = args.exocortex ?? process.env.RADIANT_EXOCORTEX;
22430
23668
  let exocortexStatus = "not loaded";
22431
23669
  if (exocortexPath) {
@@ -22433,7 +23671,8 @@ ${DIM3}Set it to a GitHub PAT with repo read access.${RESET3}
22433
23671
  exocortexStatus = summarizeExocortex(ctx);
22434
23672
  }
22435
23673
  process.stderr.write(
22436
- `${DIM3}Scope: ${scope.owner}/${scope.repo}${RESET3}
23674
+ `${DIM3}Scope: ${scope.type === "org" ? scope.owner + " (entire org)" : scope.owner + "/" + scope.repo}${RESET3}
23675
+ ${DIM3}View: ${view}${RESET3}
22437
23676
  ${DIM3}Lens: ${lensId}${RESET3}
22438
23677
  ${DIM3}Model: ${model ?? "claude-sonnet-4-20250514 (default)"}${RESET3}
22439
23678
  ${DIM3}ExoCortex: ${exocortexStatus}${RESET3}
@@ -22587,12 +23826,12 @@ async function main34(argv) {
22587
23826
  process.exit(1);
22588
23827
  }
22589
23828
  }
22590
- var import_fs15, import_path16, RED2, DIM3, BOLD3, YELLOW3, RESET3, USAGE10;
23829
+ var import_fs17, import_path18, RED2, DIM3, BOLD3, YELLOW3, RESET3, USAGE10;
22591
23830
  var init_radiant = __esm({
22592
23831
  "src/cli/radiant.ts"() {
22593
23832
  "use strict";
22594
- import_fs15 = require("fs");
22595
- import_path16 = require("path");
23833
+ import_fs17 = require("fs");
23834
+ import_path18 = require("path");
22596
23835
  init_think();
22597
23836
  init_emergent();
22598
23837
  init_ai();