@neuroverseos/governance 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,6 +48,7 @@ __export(radiant_exports, {
48
48
  createAnthropicAI: () => createAnthropicAI,
49
49
  createMockAI: () => createMockAI,
50
50
  createMockGitHubAdapter: () => createMockGitHubAdapter,
51
+ detectOrgExtendsSpec: () => detectOrgExtendsSpec,
51
52
  discoverWorlds: () => discoverWorlds,
52
53
  emergent: () => emergent,
53
54
  extractSignals: () => extractSignals,
@@ -64,19 +65,27 @@ __export(radiant_exports, {
64
65
  formatScope: () => formatScope,
65
66
  formatSlackSignalsForPrompt: () => formatSlackSignalsForPrompt,
66
67
  formatTeamExocorticesForPrompt: () => formatTeamExocorticesForPrompt,
68
+ getCacheDir: () => getCacheDir,
67
69
  getLens: () => getLens,
70
+ getRepoOrigin: () => getRepoOrigin,
68
71
  interpretPatterns: () => interpretPatterns,
69
72
  isPresent: () => isPresent,
70
73
  isScored: () => isScored,
71
74
  isSentinel: () => isSentinel,
72
75
  listLenses: () => listLenses,
76
+ loadExtendsConfig: () => loadExtendsConfig,
73
77
  loadPriorReads: () => loadPriorReads,
78
+ parseExtendsSpec: () => parseExtendsSpec,
79
+ parseRemoteUrl: () => parseRemoteUrl,
74
80
  parseRepoScope: () => parseRepoScope,
75
81
  parseScope: () => parseScope,
76
82
  presenceAverage: () => presenceAverage,
77
83
  readExocortex: () => readExocortex,
84
+ readOriginRemote: () => readOriginRemote,
78
85
  readTeamExocortices: () => readTeamExocortices,
79
86
  render: () => render,
87
+ resolveAllExtends: () => resolveAllExtends,
88
+ resolveExtendsSpec: () => resolveExtendsSpec,
80
89
  scoreComposite: () => scoreComposite,
81
90
  scoreCyber: () => scoreCyber,
82
91
  scoreLife: () => scoreLife,
@@ -575,17 +584,17 @@ var aukiBuilderLens = {
575
584
  var SOVEREIGN_CONDUIT_FRAME = {
576
585
  domains: [
577
586
  "stewardship",
578
- "sovereignty",
587
+ "agency",
579
588
  "integration"
580
589
  ],
581
590
  overlaps: [
582
591
  {
583
- domains: ["stewardship", "sovereignty"],
592
+ domains: ["stewardship", "agency"],
584
593
  emergent_state: "Trust",
585
594
  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."
586
595
  },
587
596
  {
588
- domains: ["sovereignty", "integration"],
597
+ domains: ["agency", "integration"],
589
598
  emergent_state: "Possibility",
590
599
  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."
591
600
  },
@@ -616,7 +625,7 @@ var SOVEREIGN_CONDUIT_FRAME = {
616
625
  "harm detection",
617
626
  "constraint design"
618
627
  ],
619
- "sovereignty": [
628
+ "agency": [
620
629
  "independent thinking",
621
630
  "decision ownership",
622
631
  "self-trust",
@@ -640,7 +649,7 @@ var SOVEREIGN_CONDUIT_FRAME = {
640
649
  output_translation: {
641
650
  never_surface_in_output: [
642
651
  "Stewardship",
643
- "Sovereignty",
652
+ "Agency",
644
653
  "Integration"
645
654
  ],
646
655
  surface_freely: [
@@ -655,7 +664,7 @@ var SOVEREIGN_CONDUIT_FRAME = {
655
664
  external_expression: "the boundaries are clear and the system feels safe to operate inside"
656
665
  },
657
666
  {
658
- internal_reasoning: "Sovereignty is weakening",
667
+ internal_reasoning: "Agency is weakening",
659
668
  external_expression: "decision ownership is quietly shifting \u2014 the human is accepting AI output without engaging with it"
660
669
  },
661
670
  {
@@ -738,12 +747,12 @@ var SOVEREIGN_CONDUIT_VOICE = {
738
747
  close_with_strategic_frame: "preferred",
739
748
  punchline_move: "sparing",
740
749
  honesty_about_failure: "required",
741
- 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.`
750
+ output_translation: `Reason internally through the three-domain frame (Stewardship, Agency, 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.`
742
751
  };
743
752
  var SOVEREIGN_CONDUIT_FORBIDDEN = Object.freeze([
744
753
  // Bucket names as labels
745
754
  "stewardship is",
746
- "sovereignty is",
755
+ "agency is",
747
756
  "integration is",
748
757
  // AI-assistant hedging
749
758
  "it may be beneficial to consider",
@@ -779,7 +788,7 @@ var SOVEREIGN_CONDUIT_PREFERRED = Object.freeze([
779
788
  "Here's what's actually happening: [plain explanation].",
780
789
  "The question to ask yourself: [question].",
781
790
  "The difference between [A] and [B] matters here: [why].",
782
- // Sovereignty checks
791
+ // Agency checks
783
792
  "Are you still the author of this decision, or did the AI make it for you?",
784
793
  "The AI extended your thinking here. That's working.",
785
794
  "The AI replaced your thinking here. That's the drift to watch.",
@@ -790,7 +799,7 @@ var SOVEREIGN_CONDUIT_PREFERRED = Object.freeze([
790
799
  ]);
791
800
  var SOVEREIGN_CONDUIT_STRATEGIC = Object.freeze([
792
801
  "Safety before expansion \u2014 always. No exception.",
793
- "Sovereignty before convenience \u2014 the right to think for yourself is not a feature to optimize away.",
802
+ "Agency before convenience \u2014 the right to think for yourself is not a feature to optimize away.",
794
803
  "Extension, not replacement \u2014 AI should make your thinking bigger, not do your thinking for you.",
795
804
  "Diversity over uniformity \u2014 different thinkers produce different ideas, and that's the engine of progress.",
796
805
  "The rules should be visible \u2014 like a good house, you know the rules before you walk in.",
@@ -800,9 +809,9 @@ var SOVEREIGN_CONDUIT_STRATEGIC = Object.freeze([
800
809
  ]);
801
810
  var SOVEREIGN_CONDUIT_EXEMPLARS = Object.freeze([
802
811
  {
803
- path: "neuroverseos-sovereign-conduit.worldmodel.md",
812
+ path: "src/radiant/examples/neuroverse-base/neuroverseos-sovereign-conduit.worldmodel.md",
804
813
  title: "The Sovereign Conduit Worldmodel",
805
- exhibits: ["stewardship", "sovereignty", "integration"],
814
+ exhibits: ["stewardship", "agency", "integration"],
806
815
  integration_quality: "full \u2014 all three domains defined, overlaps named, center identity declared",
807
816
  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.'
808
817
  }
@@ -828,13 +837,13 @@ function sovereignConduitRewrite(pattern) {
828
837
  return {
829
838
  ...pattern,
830
839
  framing: "what this means for the people in the system",
831
- emphasis: "humanity + sovereignty + learning",
840
+ emphasis: "humanity + agency + learning",
832
841
  compress: false
833
842
  };
834
843
  }
835
844
  var sovereignConduitLens = {
836
845
  name: "sovereign-conduit",
837
- 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.",
846
+ description: "The NeuroVerseOS base lens. Warm, accessible, teaching. Evaluates activity through Stewardship (safety), Agency (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.",
838
847
  primary_frame: {
839
848
  domains: SOVEREIGN_CONDUIT_FRAME.domains,
840
849
  overlaps: SOVEREIGN_CONDUIT_FRAME.overlaps,
@@ -2467,70 +2476,351 @@ function serializeYAML(obj, indent = 0) {
2467
2476
  }
2468
2477
 
2469
2478
  // src/radiant/core/discovery.ts
2479
+ var import_fs4 = require("fs");
2480
+ var import_path4 = require("path");
2481
+ var import_os2 = require("os");
2482
+
2483
+ // src/radiant/core/extends.ts
2484
+ var import_fs3 = require("fs");
2485
+ var import_path3 = require("path");
2486
+ var import_os = require("os");
2487
+ var import_crypto = require("crypto");
2488
+ var import_child_process = require("child_process");
2489
+
2490
+ // src/radiant/core/git-remote.ts
2470
2491
  var import_fs2 = require("fs");
2471
2492
  var import_path2 = require("path");
2472
- var import_os = require("os");
2493
+ function resolveGitConfigPath(repoDir) {
2494
+ const dotGit = (0, import_path2.join)(repoDir, ".git");
2495
+ if (!(0, import_fs2.existsSync)(dotGit)) return null;
2496
+ try {
2497
+ const stat = (0, import_fs2.statSync)(dotGit);
2498
+ if (stat.isDirectory()) {
2499
+ return (0, import_path2.join)(dotGit, "config");
2500
+ }
2501
+ if (stat.isFile()) {
2502
+ const content = (0, import_fs2.readFileSync)(dotGit, "utf-8");
2503
+ const match = /^gitdir:\s*(.+)$/m.exec(content);
2504
+ if (!match) return null;
2505
+ const gitDir = (0, import_path2.resolve)(repoDir, match[1].trim());
2506
+ const configPath = (0, import_path2.join)(gitDir, "config");
2507
+ return (0, import_fs2.existsSync)(configPath) ? configPath : null;
2508
+ }
2509
+ } catch {
2510
+ return null;
2511
+ }
2512
+ return null;
2513
+ }
2514
+ function readOriginRemote(repoDir) {
2515
+ const configPath = resolveGitConfigPath(repoDir);
2516
+ if (!configPath) return null;
2517
+ try {
2518
+ const raw = (0, import_fs2.readFileSync)(configPath, "utf-8");
2519
+ const sectionRe = /\[remote "origin"\]\s*\n((?:(?!\[)[^\n]*\n?)*)/;
2520
+ const section = sectionRe.exec(raw);
2521
+ if (!section) return null;
2522
+ const urlRe = /^\s*url\s*=\s*(.+?)\s*$/m;
2523
+ const url = urlRe.exec(section[1]);
2524
+ return url ? url[1] : null;
2525
+ } catch {
2526
+ return null;
2527
+ }
2528
+ }
2529
+ function parseRemoteUrl(url) {
2530
+ const trimmed = url.trim();
2531
+ if (!trimmed) return null;
2532
+ const ssh = /^git@([^:]+):([^/]+)\/(.+?)(?:\.git)?\/?$/.exec(trimmed);
2533
+ if (ssh) return { host: ssh[1], owner: ssh[2], repo: ssh[3] };
2534
+ const sshProto = /^ssh:\/\/git@([^/]+)\/([^/]+)\/(.+?)(?:\.git)?\/?$/.exec(trimmed);
2535
+ if (sshProto) return { host: sshProto[1], owner: sshProto[2], repo: sshProto[3] };
2536
+ const https = /^https?:\/\/(?:[^@/]+@)?([^/]+)\/([^/]+)\/(.+?)(?:\.git)?\/?$/.exec(trimmed);
2537
+ if (https) return { host: https[1], owner: https[2], repo: https[3] };
2538
+ return null;
2539
+ }
2540
+ function getRepoOrigin(repoDir) {
2541
+ const url = readOriginRemote(repoDir);
2542
+ if (!url) return null;
2543
+ return parseRemoteUrl(url);
2544
+ }
2545
+
2546
+ // src/radiant/core/extends.ts
2547
+ function loadExtendsConfig(repoDir) {
2548
+ const configPath = (0, import_path3.join)(repoDir, ".neuroverse", "config.json");
2549
+ if (!(0, import_fs3.existsSync)(configPath)) return null;
2550
+ try {
2551
+ const raw = (0, import_fs3.readFileSync)(configPath, "utf-8");
2552
+ const parsed = JSON.parse(raw);
2553
+ return parsed;
2554
+ } catch {
2555
+ return null;
2556
+ }
2557
+ }
2558
+ function parseExtendsSpec(raw) {
2559
+ const trimmed = raw.trim();
2560
+ if (!trimmed) return null;
2561
+ if (trimmed.startsWith("github:")) {
2562
+ const rest = trimmed.slice("github:".length);
2563
+ const match = /^([^/]+)\/([^@:]+)(?:@([^:]+))?(?::(.+))?$/.exec(rest);
2564
+ if (!match) return null;
2565
+ return {
2566
+ raw: trimmed,
2567
+ kind: "github",
2568
+ owner: match[1],
2569
+ repo: match[2],
2570
+ ref: match[3] ?? "HEAD",
2571
+ subpath: match[4] ?? ""
2572
+ };
2573
+ }
2574
+ if (trimmed.startsWith("./") || trimmed.startsWith("../") || (0, import_path3.isAbsolute)(trimmed)) {
2575
+ return { raw: trimmed, kind: "local", path: trimmed };
2576
+ }
2577
+ return null;
2578
+ }
2579
+ var DEFAULT_TTL_MS = 60 * 60 * 1e3;
2580
+ function getCacheDir(spec, baseCacheDir) {
2581
+ const root = baseCacheDir ?? (0, import_path3.join)((0, import_os.homedir)(), ".neuroverse", "cache", "extends");
2582
+ const key = (0, import_crypto.createHash)("sha256").update(spec.raw).digest("hex").slice(0, 16);
2583
+ return (0, import_path3.join)(root, key);
2584
+ }
2585
+ function isCacheFresh(cacheDir, ttlMs) {
2586
+ const stampPath = (0, import_path3.join)(cacheDir, ".neuroverse-fetched");
2587
+ if (!(0, import_fs3.existsSync)(stampPath)) return false;
2588
+ try {
2589
+ const stamp = (0, import_fs3.statSync)(stampPath);
2590
+ return Date.now() - stamp.mtimeMs < ttlMs;
2591
+ } catch {
2592
+ return false;
2593
+ }
2594
+ }
2595
+ function markCacheFresh(cacheDir) {
2596
+ const stampPath = (0, import_path3.join)(cacheDir, ".neuroverse-fetched");
2597
+ try {
2598
+ (0, import_fs3.mkdirSync)(cacheDir, { recursive: true });
2599
+ (0, import_fs3.writeFileSync)(stampPath, (/* @__PURE__ */ new Date()).toISOString());
2600
+ } catch {
2601
+ }
2602
+ }
2603
+ var defaultGitFetcher = (spec, destDir) => {
2604
+ if (spec.kind !== "github") return;
2605
+ const url = `https://github.com/${spec.owner}/${spec.repo}.git`;
2606
+ const parent = (0, import_path3.resolve)(destDir, "..");
2607
+ (0, import_fs3.mkdirSync)(parent, { recursive: true });
2608
+ if ((0, import_fs3.existsSync)(destDir)) {
2609
+ (0, import_fs3.rmSync)(destDir, { recursive: true, force: true });
2610
+ }
2611
+ const args = ["clone", "--depth", "1", "--filter=blob:none"];
2612
+ if (spec.ref && spec.ref !== "HEAD") {
2613
+ args.push("--branch", spec.ref);
2614
+ }
2615
+ args.push(url, destDir);
2616
+ (0, import_child_process.execFileSync)("git", args, { stdio: "pipe" });
2617
+ };
2618
+ function resolveExtendsSpec(spec, repoDir, options) {
2619
+ if (spec.kind === "local") {
2620
+ const full = (0, import_path3.isAbsolute)(spec.path) ? spec.path : (0, import_path3.resolve)(repoDir, spec.path);
2621
+ if (!(0, import_fs3.existsSync)(full)) {
2622
+ return { spec, dir: null, warning: `local extends path not found: ${full}` };
2623
+ }
2624
+ return { spec, dir: full };
2625
+ }
2626
+ const cacheRoot = options?.cacheDir;
2627
+ const ttl = options?.ttlMs ?? DEFAULT_TTL_MS;
2628
+ const cacheDir = getCacheDir(spec, cacheRoot);
2629
+ const fresh = isCacheFresh(cacheDir, ttl);
2630
+ const needsFetch = options?.forceRefresh || !fresh || !(0, import_fs3.existsSync)(cacheDir);
2631
+ if (needsFetch && options?.noFetch) {
2632
+ if ((0, import_fs3.existsSync)(cacheDir) && (0, import_fs3.existsSync)((0, import_path3.join)(cacheDir, ".neuroverse-fetched"))) {
2633
+ return resolveSubpath(spec, cacheDir);
2634
+ }
2635
+ return options?.silentOnMissing ? { spec, dir: null } : { spec, dir: null, warning: `NEUROVERSE_NO_FETCH set and no cache for ${spec.raw}` };
2636
+ }
2637
+ if (needsFetch) {
2638
+ const fetcher = options?.fetcher ?? defaultGitFetcher;
2639
+ try {
2640
+ fetcher(spec, cacheDir);
2641
+ markCacheFresh(cacheDir);
2642
+ } catch (err) {
2643
+ if ((0, import_fs3.existsSync)(cacheDir) && (0, import_fs3.existsSync)((0, import_path3.join)(cacheDir, ".neuroverse-fetched"))) {
2644
+ const result = resolveSubpath(spec, cacheDir);
2645
+ return options?.silentOnMissing ? result : { ...result, warning: `fetch failed for ${spec.raw}, using stale cache: ${err.message}` };
2646
+ }
2647
+ return options?.silentOnMissing ? { spec, dir: null } : { spec, dir: null, warning: `fetch failed for ${spec.raw}: ${err.message}` };
2648
+ }
2649
+ }
2650
+ return resolveSubpath(spec, cacheDir);
2651
+ }
2652
+ function resolveSubpath(spec, cacheDir) {
2653
+ const target = spec.subpath ? (0, import_path3.join)(cacheDir, spec.subpath) : cacheDir;
2654
+ if (!(0, import_fs3.existsSync)(target)) {
2655
+ return { spec, dir: null, warning: `subpath not found in ${spec.raw}: ${spec.subpath}` };
2656
+ }
2657
+ if (!spec.subpath) {
2658
+ const candidates = [
2659
+ (0, import_path3.join)(target, "worlds"),
2660
+ (0, import_path3.join)(target, ".neuroverse", "worlds")
2661
+ ];
2662
+ for (const c of candidates) {
2663
+ if ((0, import_fs3.existsSync)(c)) return { spec, dir: c };
2664
+ }
2665
+ }
2666
+ return { spec, dir: target };
2667
+ }
2668
+ function detectOrgExtendsSpec(repoDir) {
2669
+ const origin = getRepoOrigin(repoDir);
2670
+ if (!origin) return null;
2671
+ if (origin.host !== "github.com") return null;
2672
+ if (origin.repo === "worlds") return null;
2673
+ return {
2674
+ raw: `github:${origin.owner}/worlds`,
2675
+ kind: "github",
2676
+ owner: origin.owner,
2677
+ repo: "worlds",
2678
+ ref: "HEAD",
2679
+ subpath: ""
2680
+ };
2681
+ }
2682
+ function resolveAllExtends(repoDir, options) {
2683
+ const config = options?.config !== void 0 ? options.config : loadExtendsConfig(repoDir);
2684
+ if (!config?.extends || config.extends.length === 0) return [];
2685
+ const results = [];
2686
+ for (const raw of config.extends) {
2687
+ const spec = parseExtendsSpec(raw);
2688
+ if (!spec) {
2689
+ results.push({
2690
+ spec: { raw, kind: "local" },
2691
+ dir: null,
2692
+ warning: `unparseable extends spec: ${raw}`
2693
+ });
2694
+ continue;
2695
+ }
2696
+ results.push(resolveExtendsSpec(spec, repoDir, options));
2697
+ }
2698
+ return results;
2699
+ }
2700
+
2701
+ // src/radiant/core/discovery.ts
2473
2702
  function discoverWorlds(options) {
2474
2703
  const worlds = [];
2475
- const userDir = options?.userWorldsDir ?? (0, import_path2.join)((0, import_os.homedir)(), ".neuroverse", "worlds");
2476
- if ((0, import_fs2.existsSync)(userDir)) {
2704
+ const warnings = [];
2705
+ const forceRefresh = process.env.NEUROVERSE_REFRESH === "1";
2706
+ const noFetch = process.env.NEUROVERSE_NO_FETCH === "1";
2707
+ const noOrg = options?.disableOrg || process.env.NEUROVERSE_NO_ORG === "1";
2708
+ const userDir = options?.userWorldsDir ?? (0, import_path4.join)((0, import_os2.homedir)(), ".neuroverse", "worlds");
2709
+ if ((0, import_fs4.existsSync)(userDir)) {
2477
2710
  worlds.push(...loadWorldsFromDir(userDir, "user"));
2478
2711
  }
2712
+ if (!noOrg && !options?.explicitWorldsDir) {
2713
+ const specs = [];
2714
+ if (options?.repoDir) {
2715
+ const fromGit = detectOrgExtendsSpec(options.repoDir);
2716
+ if (fromGit) specs.push(fromGit);
2717
+ }
2718
+ if (options?.scopeOwner) {
2719
+ const already = specs.some(
2720
+ (s) => s.owner?.toLowerCase() === options.scopeOwner.toLowerCase()
2721
+ );
2722
+ if (!already) {
2723
+ specs.push({
2724
+ raw: `github:${options.scopeOwner}/worlds`,
2725
+ kind: "github",
2726
+ owner: options.scopeOwner,
2727
+ repo: "worlds"
2728
+ });
2729
+ }
2730
+ }
2731
+ const baseDir = options?.repoDir ?? process.cwd();
2732
+ for (const spec of specs) {
2733
+ const result = resolveExtendsSpec(spec, baseDir, {
2734
+ cacheDir: options?.extendsCacheDir,
2735
+ fetcher: options?.extendsFetcher,
2736
+ ttlMs: options?.extendsTtlMs,
2737
+ forceRefresh,
2738
+ noFetch,
2739
+ silentOnMissing: true
2740
+ });
2741
+ worlds.push(...loadExtendsWorlds(result, "org"));
2742
+ }
2743
+ }
2744
+ if (options?.repoDir && !options.disableExtends && !options.explicitWorldsDir) {
2745
+ const results = resolveAllExtends(options.repoDir, {
2746
+ cacheDir: options.extendsCacheDir,
2747
+ fetcher: options.extendsFetcher,
2748
+ ttlMs: options.extendsTtlMs,
2749
+ forceRefresh,
2750
+ noFetch
2751
+ });
2752
+ for (const result of results) {
2753
+ worlds.push(...loadExtendsWorlds(result, "extends"));
2754
+ if (result.warning) warnings.push(result.warning);
2755
+ }
2756
+ }
2479
2757
  if (options?.explicitWorldsDir) {
2480
2758
  worlds.push(...loadWorldsFromDir(options.explicitWorldsDir, "repo"));
2481
2759
  } else if (options?.repoDir) {
2482
2760
  const repoPaths = [
2483
- (0, import_path2.join)(options.repoDir, "worlds"),
2484
- (0, import_path2.join)(options.repoDir, ".neuroverse", "worlds")
2761
+ (0, import_path4.join)(options.repoDir, "worlds"),
2762
+ (0, import_path4.join)(options.repoDir, ".neuroverse", "worlds")
2485
2763
  ];
2486
2764
  for (const p of repoPaths) {
2487
- if ((0, import_fs2.existsSync)(p)) {
2765
+ if ((0, import_fs4.existsSync)(p)) {
2488
2766
  worlds.push(...loadWorldsFromDir(p, "repo"));
2489
2767
  break;
2490
2768
  }
2491
2769
  }
2492
2770
  }
2493
- const combinedContent = worlds.map((w) => `<!-- world: ${w.name} (${w.source}) -->
2494
- ${w.content}`).join("\n\n---\n\n");
2771
+ const combinedContent = worlds.map((w) => {
2772
+ const tag = w.extendsFrom ? `<!-- world: ${w.name} (${w.source} ${w.extendsFrom}) -->` : `<!-- world: ${w.name} (${w.source}) -->`;
2773
+ return `${tag}
2774
+ ${w.content}`;
2775
+ }).join("\n\n---\n\n");
2495
2776
  const summary = worlds.length === 0 ? "no worlds discovered" : worlds.map((w) => `${w.name} (${w.source})`).join(", ");
2496
- return { worlds, combinedContent, summary };
2777
+ return { worlds, combinedContent, summary, warnings };
2497
2778
  }
2498
2779
  function formatActiveWorlds(stack) {
2499
2780
  if (stack.worlds.length === 0) return "No worlds loaded.";
2500
2781
  const lines = ["ACTIVE WORLDS", ""];
2501
2782
  for (const w of stack.worlds) {
2502
- const sourceLabel = w.source === "base" ? "universal" : w.source === "user" ? "personal" : "this repo";
2783
+ const sourceLabel = w.source === "base" ? "universal" : w.source === "user" ? "personal" : w.source === "org" ? `org (${w.extendsFrom ?? "auto"})` : w.source === "extends" ? `shared (${w.extendsFrom ?? "extends"})` : "this repo";
2503
2784
  lines.push(` ${w.name} (${sourceLabel})`);
2504
2785
  }
2786
+ if (stack.warnings.length > 0) {
2787
+ lines.push("", "WARNINGS");
2788
+ for (const w of stack.warnings) lines.push(` ${w}`);
2789
+ }
2505
2790
  return lines.join("\n");
2506
2791
  }
2792
+ function loadExtendsWorlds(result, source) {
2793
+ if (!result.dir) return [];
2794
+ const loaded = loadWorldsFromDir(result.dir, source);
2795
+ return loaded.map((w) => ({ ...w, extendsFrom: result.spec.raw }));
2796
+ }
2507
2797
  function loadWorldsFromDir(dirPath, source) {
2508
- const dir = (0, import_path2.resolve)(dirPath);
2509
- if (!(0, import_fs2.existsSync)(dir)) return [];
2510
- const stat = (0, import_fs2.statSync)(dir);
2798
+ const dir = (0, import_path4.resolve)(dirPath);
2799
+ if (!(0, import_fs4.existsSync)(dir)) return [];
2800
+ const stat = (0, import_fs4.statSync)(dir);
2511
2801
  if (stat.isFile() && dir.endsWith(".md")) {
2512
2802
  try {
2513
2803
  return [{
2514
- name: (0, import_path2.basename)(dir).replace(/\.worldmodel\.md$/, "").replace(/\.nv-world\.md$/, ""),
2804
+ name: (0, import_path4.basename)(dir).replace(/\.worldmodel\.md$/, "").replace(/\.nv-world\.md$/, ""),
2515
2805
  source,
2516
2806
  path: dir,
2517
- content: (0, import_fs2.readFileSync)(dir, "utf-8")
2807
+ content: (0, import_fs4.readFileSync)(dir, "utf-8")
2518
2808
  }];
2519
2809
  } catch {
2520
2810
  return [];
2521
2811
  }
2522
2812
  }
2523
2813
  if (!stat.isDirectory()) return [];
2524
- const files = (0, import_fs2.readdirSync)(dir).filter(
2814
+ const files = (0, import_fs4.readdirSync)(dir).filter(
2525
2815
  (f) => f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md")
2526
2816
  ).sort();
2527
2817
  return files.map((f) => {
2528
- const fullPath = (0, import_path2.join)(dir, f);
2818
+ const fullPath = (0, import_path4.join)(dir, f);
2529
2819
  return {
2530
2820
  name: f.replace(/\.worldmodel\.md$/, "").replace(/\.nv-world\.md$/, ""),
2531
2821
  source,
2532
2822
  path: fullPath,
2533
- content: (0, import_fs2.readFileSync)(fullPath, "utf-8")
2823
+ content: (0, import_fs4.readFileSync)(fullPath, "utf-8")
2534
2824
  };
2535
2825
  });
2536
2826
  }
@@ -3621,10 +3911,10 @@ function verdictToEvent(status, intent) {
3621
3911
  // src/loader/world-loader.ts
3622
3912
  async function loadWorldFromDirectory(dirPath) {
3623
3913
  const { readFile } = await import("fs/promises");
3624
- const { join: join4 } = await import("path");
3914
+ const { join: join6 } = await import("path");
3625
3915
  const { readdirSync: readdirSync4 } = await import("fs");
3626
3916
  async function readJson(filename) {
3627
- const filePath = join4(dirPath, filename);
3917
+ const filePath = join6(dirPath, filename);
3628
3918
  try {
3629
3919
  const content = await readFile(filePath, "utf-8");
3630
3920
  return JSON.parse(content);
@@ -3654,11 +3944,11 @@ async function loadWorldFromDirectory(dirPath) {
3654
3944
  const metadataJson = await readJson("metadata.json");
3655
3945
  const rules = [];
3656
3946
  try {
3657
- const rulesDir = join4(dirPath, "rules");
3947
+ const rulesDir = join6(dirPath, "rules");
3658
3948
  const ruleFiles = readdirSync4(rulesDir).filter((f) => f.endsWith(".json")).sort();
3659
3949
  for (const file of ruleFiles) {
3660
3950
  try {
3661
- const content = await readFile(join4(rulesDir, file), "utf-8");
3951
+ const content = await readFile(join6(rulesDir, file), "utf-8");
3662
3952
  rules.push(JSON.parse(content));
3663
3953
  } catch (err) {
3664
3954
  process.stderr.write(
@@ -3818,25 +4108,25 @@ function emptyAudit(total, reason) {
3818
4108
  }
3819
4109
 
3820
4110
  // src/radiant/memory/palace.ts
3821
- var import_fs3 = require("fs");
3822
- var import_path3 = require("path");
4111
+ var import_fs5 = require("fs");
4112
+ var import_path5 = require("path");
3823
4113
  function writeRead(exocortexDir, frontmatter, text) {
3824
- const dir = (0, import_path3.resolve)(exocortexDir, "radiant", "reads");
3825
- (0, import_fs3.mkdirSync)(dir, { recursive: true });
4114
+ const dir = (0, import_path5.resolve)(exocortexDir, "radiant", "reads");
4115
+ (0, import_fs5.mkdirSync)(dir, { recursive: true });
3826
4116
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
3827
4117
  const filename = `${date}.md`;
3828
- const filepath = (0, import_path3.join)(dir, filename);
4118
+ const filepath = (0, import_path5.join)(dir, filename);
3829
4119
  const content = `${frontmatter}
3830
4120
 
3831
4121
  ${text}
3832
4122
  `;
3833
- (0, import_fs3.writeFileSync)(filepath, content, "utf-8");
4123
+ (0, import_fs5.writeFileSync)(filepath, content, "utf-8");
3834
4124
  return filepath;
3835
4125
  }
3836
4126
  function updateKnowledge(exocortexDir, persistence, options) {
3837
- const dir = (0, import_path3.resolve)(exocortexDir, "radiant");
3838
- (0, import_fs3.mkdirSync)(dir, { recursive: true });
3839
- const filepath = (0, import_path3.join)(dir, "knowledge.md");
4127
+ const dir = (0, import_path5.resolve)(exocortexDir, "radiant");
4128
+ (0, import_fs5.mkdirSync)(dir, { recursive: true });
4129
+ const filepath = (0, import_path5.join)(dir, "knowledge.md");
3840
4130
  const totalReads = options?.totalReads ?? 0;
3841
4131
  const existingUntriggered = loadUntriggeredCounts(filepath);
3842
4132
  const lines = [
@@ -3923,14 +4213,14 @@ function updateKnowledge(exocortexDir, persistence, options) {
3923
4213
  lines.push(`${name}=${count}`);
3924
4214
  }
3925
4215
  lines.push("-->");
3926
- (0, import_fs3.writeFileSync)(filepath, lines.join("\n"), "utf-8");
4216
+ (0, import_fs5.writeFileSync)(filepath, lines.join("\n"), "utf-8");
3927
4217
  return filepath;
3928
4218
  }
3929
4219
  function loadUntriggeredCounts(filepath) {
3930
4220
  const counts = /* @__PURE__ */ new Map();
3931
- if (!(0, import_fs3.existsSync)(filepath)) return counts;
4221
+ if (!(0, import_fs5.existsSync)(filepath)) return counts;
3932
4222
  try {
3933
- const content = (0, import_fs3.readFileSync)(filepath, "utf-8");
4223
+ const content = (0, import_fs5.readFileSync)(filepath, "utf-8");
3934
4224
  const match = content.match(
3935
4225
  /<!-- untriggered_counts[\s\S]*?-->/
3936
4226
  );
@@ -3948,13 +4238,13 @@ function loadUntriggeredCounts(filepath) {
3948
4238
  return counts;
3949
4239
  }
3950
4240
  function loadPriorReads(exocortexDir) {
3951
- const dir = (0, import_path3.resolve)(exocortexDir, "radiant", "reads");
3952
- if (!(0, import_fs3.existsSync)(dir)) return [];
3953
- const files = (0, import_fs3.readdirSync)(dir).filter((f) => f.endsWith(".md")).sort();
4241
+ const dir = (0, import_path5.resolve)(exocortexDir, "radiant", "reads");
4242
+ if (!(0, import_fs5.existsSync)(dir)) return [];
4243
+ const files = (0, import_fs5.readdirSync)(dir).filter((f) => f.endsWith(".md")).sort();
3954
4244
  const reads = [];
3955
4245
  for (const filename of files) {
3956
- const filepath = (0, import_path3.join)(dir, filename);
3957
- const content = (0, import_fs3.readFileSync)(filepath, "utf-8");
4246
+ const filepath = (0, import_path5.join)(dir, filename);
4247
+ const content = (0, import_fs5.readFileSync)(filepath, "utf-8");
3958
4248
  const date = filename.replace(".md", "");
3959
4249
  const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
3960
4250
  const frontmatter = fmMatch ? fmMatch[1] : "";
@@ -4253,6 +4543,7 @@ var RADIANT_PACKAGE_VERSION = "0.0.0";
4253
4543
  createAnthropicAI,
4254
4544
  createMockAI,
4255
4545
  createMockGitHubAdapter,
4546
+ detectOrgExtendsSpec,
4256
4547
  discoverWorlds,
4257
4548
  emergent,
4258
4549
  extractSignals,
@@ -4269,19 +4560,27 @@ var RADIANT_PACKAGE_VERSION = "0.0.0";
4269
4560
  formatScope,
4270
4561
  formatSlackSignalsForPrompt,
4271
4562
  formatTeamExocorticesForPrompt,
4563
+ getCacheDir,
4272
4564
  getLens,
4565
+ getRepoOrigin,
4273
4566
  interpretPatterns,
4274
4567
  isPresent,
4275
4568
  isScored,
4276
4569
  isSentinel,
4277
4570
  listLenses,
4571
+ loadExtendsConfig,
4278
4572
  loadPriorReads,
4573
+ parseExtendsSpec,
4574
+ parseRemoteUrl,
4279
4575
  parseRepoScope,
4280
4576
  parseScope,
4281
4577
  presenceAverage,
4282
4578
  readExocortex,
4579
+ readOriginRemote,
4283
4580
  readTeamExocortices,
4284
4581
  render,
4582
+ resolveAllExtends,
4583
+ resolveExtendsSpec,
4285
4584
  scoreComposite,
4286
4585
  scoreCyber,
4287
4586
  scoreLife,