@neuroverseos/governance 0.9.0 → 0.11.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.
Files changed (99) hide show
  1. package/README.md +1 -1
  2. package/dist/adapters/autoresearch.cjs +19 -1
  3. package/dist/adapters/autoresearch.d.cts +1 -1
  4. package/dist/adapters/autoresearch.d.ts +1 -1
  5. package/dist/adapters/autoresearch.js +2 -2
  6. package/dist/adapters/deep-agents.cjs +19 -1
  7. package/dist/adapters/deep-agents.d.cts +2 -2
  8. package/dist/adapters/deep-agents.d.ts +2 -2
  9. package/dist/adapters/deep-agents.js +2 -2
  10. package/dist/adapters/express.cjs +19 -1
  11. package/dist/adapters/express.d.cts +1 -1
  12. package/dist/adapters/express.d.ts +1 -1
  13. package/dist/adapters/express.js +2 -2
  14. package/dist/adapters/github.cjs +19 -1
  15. package/dist/adapters/github.d.cts +2 -2
  16. package/dist/adapters/github.d.ts +2 -2
  17. package/dist/adapters/github.js +2 -2
  18. package/dist/adapters/index.cjs +19 -1
  19. package/dist/adapters/index.d.cts +2 -2
  20. package/dist/adapters/index.d.ts +2 -2
  21. package/dist/adapters/index.js +8 -8
  22. package/dist/adapters/langchain.cjs +19 -1
  23. package/dist/adapters/langchain.d.cts +2 -2
  24. package/dist/adapters/langchain.d.ts +2 -2
  25. package/dist/adapters/langchain.js +2 -2
  26. package/dist/adapters/mentraos.cjs +19 -1
  27. package/dist/adapters/mentraos.d.cts +2 -2
  28. package/dist/adapters/mentraos.d.ts +2 -2
  29. package/dist/adapters/mentraos.js +2 -2
  30. package/dist/adapters/openai.cjs +19 -1
  31. package/dist/adapters/openai.d.cts +2 -2
  32. package/dist/adapters/openai.d.ts +2 -2
  33. package/dist/adapters/openai.js +2 -2
  34. package/dist/adapters/openclaw.cjs +19 -1
  35. package/dist/adapters/openclaw.d.cts +2 -2
  36. package/dist/adapters/openclaw.d.ts +2 -2
  37. package/dist/adapters/openclaw.js +2 -2
  38. package/dist/admin/index.cjs +19 -1
  39. package/dist/admin/index.js +1 -1
  40. package/dist/audit-CRJOB4CP.js +93 -0
  41. package/dist/audit-behavior-C62FdRAC.d.cts +100 -0
  42. package/dist/audit-behavior-DFy7LeYv.d.ts +100 -0
  43. package/dist/{behavioral-SPWPGYXL.js → behavioral-4TKMHZQZ.js} +2 -2
  44. package/dist/{chunk-OQU65525.js → chunk-24YW7BHC.js} +1 -1
  45. package/dist/{chunk-3ZWU7C43.js → chunk-2KTPIE57.js} +494 -14
  46. package/dist/{chunk-TJ5L2UTE.js → chunk-5K3LATTM.js} +1 -1
  47. package/dist/{chunk-HDNDL6D5.js → chunk-5LDBYOSJ.js} +1 -1
  48. package/dist/{chunk-FDPPZLSQ.js → chunk-5ZWKM7MO.js} +1 -1
  49. package/dist/{chunk-B3IIPTY3.js → chunk-6MB6TMAG.js} +1 -1
  50. package/dist/{chunk-IOVXB6QN.js → chunk-GXTAHCND.js} +1 -1
  51. package/dist/{chunk-FKQCPRKI.js → chunk-MAOIHKFO.js} +1 -1
  52. package/dist/{chunk-ZAF6JH23.js → chunk-MBOW6YXN.js} +19 -1
  53. package/dist/{chunk-A2UZTLRV.js → chunk-MLXKSX3L.js} +1 -1
  54. package/dist/{chunk-7FL3U7Z5.js → chunk-MWGEXHOD.js} +1 -1
  55. package/dist/{chunk-6CV4XG3J.js → chunk-QFDFAWZ6.js} +1 -1
  56. package/dist/{chunk-2VAWP6FI.js → chunk-RAS62JXV.js} +1 -1
  57. package/dist/{chunk-OTZU76DH.js → chunk-XAF3CYCW.js} +1 -1
  58. package/dist/{chunk-T6GMRZWC.js → chunk-XTYQCTDD.js} +1 -1
  59. package/dist/{chunk-TIXVEPS2.js → chunk-YN7OI5ZV.js} +1 -1
  60. package/dist/cli/neuroverse.cjs +999 -111
  61. package/dist/cli/neuroverse.js +16 -12
  62. package/dist/cli/plan.cjs +18 -0
  63. package/dist/cli/radiant.cjs +814 -17
  64. package/dist/cli/radiant.d.cts +44 -1
  65. package/dist/cli/radiant.d.ts +44 -1
  66. package/dist/cli/radiant.js +295 -7
  67. package/dist/cli/run.cjs +18 -0
  68. package/dist/cli/run.js +4 -4
  69. package/dist/{decision-flow-IJPNMVQK.js → decision-flow-5VI5YG6A.js} +2 -2
  70. package/dist/{demo-6W3YXLAX.js → demo-GYX6CYHC.js} +2 -2
  71. package/dist/engine/guard-engine.cjs +19 -1
  72. package/dist/engine/guard-engine.d.cts +21 -1
  73. package/dist/engine/guard-engine.d.ts +21 -1
  74. package/dist/engine/guard-engine.js +1 -1
  75. package/dist/{equity-penalties-CCO3GVHS.js → equity-penalties-NOM46NEO.js} +2 -2
  76. package/dist/{guard-IHJEKHL2.js → guard-PQ3SYV4Y.js} +3 -3
  77. package/dist/{guard-contract-ddiIPlOg.d.cts → guard-contract-Oznf-Kgq.d.cts} +32 -0
  78. package/dist/{guard-contract-q6HJAq3Q.d.ts → guard-contract-w_i_6gh-.d.ts} +32 -0
  79. package/dist/{impact-WIAM66IH.js → impact-LDJLTVRU.js} +3 -3
  80. package/dist/index.cjs +62 -1
  81. package/dist/index.d.cts +4 -3
  82. package/dist/index.d.ts +4 -3
  83. package/dist/index.js +49 -8
  84. package/dist/{mcp-server-CKYBHXWK.js → mcp-server-W3MWSKD7.js} +2 -2
  85. package/dist/{playground-3TTBN7XD.js → playground-SSZRNUAF.js} +1 -1
  86. package/dist/radiant/index.cjs +517 -14
  87. package/dist/radiant/index.d.cts +180 -10
  88. package/dist/radiant/index.d.ts +180 -10
  89. package/dist/radiant/index.js +12 -2
  90. package/dist/{redteam-W644UMWN.js → redteam-KCULS7EW.js} +1 -1
  91. package/dist/{server-JKUBUK5H.js → server-EGRGGSM2.js} +2 -2
  92. package/dist/{session-FMAROEIE.js → session-PZLTL22G.js} +2 -2
  93. package/dist/{shared-PpalGKxc.d.cts → shared-BC8mOpt0.d.cts} +1 -1
  94. package/dist/{shared-DAzdfWtU.d.ts → shared-CP63gNNW.d.ts} +1 -1
  95. package/dist/{test-XDB2DH3L.js → test-LIHGWHBA.js} +1 -1
  96. package/dist/{trace-2YDNAXMK.js → trace-DC3D7XPD.js} +2 -2
  97. package/examples/radiant-weekly-workflow.yml +4 -1
  98. package/package.json +1 -1
  99. /package/dist/{doctor-XEMLO6UA.js → doctor-SIWQGTAO.js} +0 -0
@@ -6332,6 +6332,24 @@ function isExternalScope(scope) {
6332
6332
  return !internalPatterns.some((p) => p.test(scope));
6333
6333
  }
6334
6334
  function evaluateGuard(event, world, options = {}) {
6335
+ const verdict = evaluateGuardCore(event, world, options);
6336
+ return options.mode === "observe" ? toShadowVerdict(verdict) : verdict;
6337
+ }
6338
+ function toShadowVerdict(verdict) {
6339
+ if (verdict.status === "ALLOW") return verdict;
6340
+ return {
6341
+ ...verdict,
6342
+ status: "ALLOW",
6343
+ shadowStatus: verdict.status,
6344
+ shadowReason: verdict.reason,
6345
+ // Preserve the original reason as shadowReason and wipe the
6346
+ // top-level reason so callers that display `reason` for BLOCK/PAUSE
6347
+ // don't accidentally surface an enforcement message.
6348
+ reason: void 0,
6349
+ warning: verdict.reason ? `Observe mode: would have ${verdict.status.toLowerCase()} \u2014 ${verdict.reason}` : `Observe mode: would have ${verdict.status.toLowerCase()}`
6350
+ };
6351
+ }
6352
+ function evaluateGuardCore(event, world, options = {}) {
6335
6353
  const startTime = performance.now();
6336
6354
  const level = options.level ?? "standard";
6337
6355
  const includeTrace = options.trace ?? false;
@@ -7647,10 +7665,99 @@ var init_guard = __esm({
7647
7665
  }
7648
7666
  });
7649
7667
 
7668
+ // src/cli/audit.ts
7669
+ var audit_exports = {};
7670
+ __export(audit_exports, {
7671
+ main: () => main12
7672
+ });
7673
+ function parseArgs12(argv) {
7674
+ let worldPath = "";
7675
+ let trace = false;
7676
+ let level;
7677
+ let multi = false;
7678
+ let crossingsOnly = false;
7679
+ for (let i = 0; i < argv.length; i++) {
7680
+ const a = argv[i];
7681
+ if (a === "--world") worldPath = argv[++i] ?? "";
7682
+ else if (a === "--trace") trace = true;
7683
+ else if (a === "--level") {
7684
+ const v = argv[++i];
7685
+ if (v === "basic" || v === "standard" || v === "strict") level = v;
7686
+ } else if (a === "--multi") multi = true;
7687
+ else if (a === "--crossings-only") crossingsOnly = true;
7688
+ }
7689
+ return { worldPath, trace, level, multi, crossingsOnly };
7690
+ }
7691
+ function usage() {
7692
+ process.stderr.write(
7693
+ "Usage: neuroverse audit --world <path> [--trace] [--level basic|standard|strict] [--multi] [--crossings-only]\n\nReads GuardEvent JSON from stdin. With --multi, reads a JSON array.\nEvaluates in observe mode \u2014 no enforcement. Verdicts carry\nshadowStatus/shadowReason for any event that would have crossed.\n"
7694
+ );
7695
+ }
7696
+ async function main12(argv = process.argv.slice(2)) {
7697
+ const args = parseArgs12(argv);
7698
+ if (!args.worldPath) {
7699
+ usage();
7700
+ process.exit(1);
7701
+ }
7702
+ let world;
7703
+ try {
7704
+ const resolved = resolveWorldPath(args.worldPath);
7705
+ world = await loadWorld(resolved);
7706
+ } catch (err) {
7707
+ process.stderr.write(`Failed to load world: ${err instanceof Error ? err.message : err}
7708
+ `);
7709
+ process.exit(1);
7710
+ }
7711
+ let raw = "";
7712
+ try {
7713
+ raw = await readStdin();
7714
+ } catch (err) {
7715
+ process.stderr.write(`Failed to read stdin: ${err instanceof Error ? err.message : err}
7716
+ `);
7717
+ process.exit(1);
7718
+ }
7719
+ if (!raw.trim()) {
7720
+ process.stderr.write("No input on stdin. Pipe a GuardEvent or a JSON array with --multi.\n");
7721
+ process.exit(1);
7722
+ }
7723
+ let parsed;
7724
+ try {
7725
+ parsed = JSON.parse(raw);
7726
+ } catch (err) {
7727
+ process.stderr.write(`Invalid JSON on stdin: ${err instanceof Error ? err.message : err}
7728
+ `);
7729
+ process.exit(1);
7730
+ }
7731
+ const options = { trace: args.trace, level: args.level, mode: "observe" };
7732
+ if (args.multi) {
7733
+ if (!Array.isArray(parsed)) {
7734
+ process.stderr.write("--multi expects a JSON array on stdin.\n");
7735
+ process.exit(1);
7736
+ }
7737
+ const verdicts = parsed.map(
7738
+ (e) => evaluateGuard(e, world, options)
7739
+ );
7740
+ const out = args.crossingsOnly ? verdicts.filter((v) => v.shadowStatus && v.shadowStatus !== "ALLOW") : verdicts;
7741
+ process.stdout.write(JSON.stringify(out, null, 2) + "\n");
7742
+ return;
7743
+ }
7744
+ const verdict = evaluateGuard(parsed, world, options);
7745
+ process.stdout.write(JSON.stringify(verdict, null, 2) + "\n");
7746
+ }
7747
+ var init_audit = __esm({
7748
+ "src/cli/audit.ts"() {
7749
+ "use strict";
7750
+ init_guard_engine();
7751
+ init_world_loader();
7752
+ init_world_resolver();
7753
+ init_cli_utils();
7754
+ }
7755
+ });
7756
+
7650
7757
  // src/cli/test.ts
7651
7758
  var test_exports = {};
7652
7759
  __export(test_exports, {
7653
- main: () => main12
7760
+ main: () => main13
7654
7761
  });
7655
7762
  function generateFuzzEvent() {
7656
7763
  const verb = FUZZ_VERBS[Math.floor(Math.random() * FUZZ_VERBS.length)];
@@ -7668,7 +7775,7 @@ function generateFuzzEvent() {
7668
7775
  }
7669
7776
  };
7670
7777
  }
7671
- function parseArgs12(argv) {
7778
+ function parseArgs13(argv) {
7672
7779
  let worldPath;
7673
7780
  let fuzz = false;
7674
7781
  let count = 20;
@@ -7684,8 +7791,8 @@ function parseArgs12(argv) {
7684
7791
  }
7685
7792
  return { worldPath, fuzz, count, json, level };
7686
7793
  }
7687
- async function main12(argv) {
7688
- const args = parseArgs12(argv);
7794
+ async function main13(argv) {
7795
+ const args = parseArgs13(argv);
7689
7796
  if (!args.worldPath) {
7690
7797
  process.stderr.write("Usage: neuroverse test --world <dir> [--fuzz] [--count N] [--json]\n");
7691
7798
  process.exit(1);
@@ -7868,9 +7975,9 @@ var init_test = __esm({
7868
7975
  // src/cli/redteam.ts
7869
7976
  var redteam_exports = {};
7870
7977
  __export(redteam_exports, {
7871
- main: () => main13
7978
+ main: () => main14
7872
7979
  });
7873
- function parseArgs13(argv) {
7980
+ function parseArgs14(argv) {
7874
7981
  let worldPath;
7875
7982
  let level = "standard";
7876
7983
  let json = false;
@@ -7882,8 +7989,8 @@ function parseArgs13(argv) {
7882
7989
  }
7883
7990
  return { worldPath, level, json };
7884
7991
  }
7885
- async function main13(argv) {
7886
- const args = parseArgs13(argv);
7992
+ async function main14(argv) {
7993
+ const args = parseArgs14(argv);
7887
7994
  if (!args.worldPath) {
7888
7995
  process.stderr.write("Usage: neuroverse redteam --world <dir> [--level basic|standard|strict] [--json]\n");
7889
7996
  process.exit(1);
@@ -8585,9 +8692,9 @@ var init_behavioral_engine = __esm({
8585
8692
  // src/cli/demo.ts
8586
8693
  var demo_exports = {};
8587
8694
  __export(demo_exports, {
8588
- main: () => main14
8695
+ main: () => main15
8589
8696
  });
8590
- async function main14(args) {
8697
+ async function main15(args) {
8591
8698
  let port = 3456;
8592
8699
  let worldName;
8593
8700
  let noBrowser = false;
@@ -11425,9 +11532,9 @@ var init_ = __esm({
11425
11532
  // src/cli/doctor.ts
11426
11533
  var doctor_exports = {};
11427
11534
  __export(doctor_exports, {
11428
- main: () => main15
11535
+ main: () => main16
11429
11536
  });
11430
- async function main15(argv) {
11537
+ async function main16(argv) {
11431
11538
  const json = argv.includes("--json");
11432
11539
  let worldPath;
11433
11540
  for (let i = 0; i < argv.length; i++) {
@@ -11589,7 +11696,7 @@ var init_doctor = __esm({
11589
11696
  // src/cli/playground.ts
11590
11697
  var playground_exports = {};
11591
11698
  __export(playground_exports, {
11592
- main: () => main16
11699
+ main: () => main17
11593
11700
  });
11594
11701
  function buildPlaygroundHtml(world, healthSummary) {
11595
11702
  const worldName = world.world.name;
@@ -12015,7 +12122,7 @@ function esc(s) {
12015
12122
  function esc(s) {
12016
12123
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
12017
12124
  }
12018
- function parseArgs14(argv) {
12125
+ function parseArgs15(argv) {
12019
12126
  let worldPath;
12020
12127
  let port = 4242;
12021
12128
  for (let i = 0; i < argv.length; i++) {
@@ -12025,8 +12132,8 @@ function parseArgs14(argv) {
12025
12132
  }
12026
12133
  return { worldPath, port };
12027
12134
  }
12028
- async function main16(argv) {
12029
- const args = parseArgs14(argv);
12135
+ async function main17(argv) {
12136
+ const args = parseArgs15(argv);
12030
12137
  let world;
12031
12138
  if (args.worldPath) {
12032
12139
  try {
@@ -12317,7 +12424,7 @@ var init_plan_contract = __esm({
12317
12424
  // src/cli/plan.ts
12318
12425
  var plan_exports = {};
12319
12426
  __export(plan_exports, {
12320
- main: () => main17
12427
+ main: () => main18
12321
12428
  });
12322
12429
  function parseArg(args, flag) {
12323
12430
  const idx = args.indexOf(flag);
@@ -12549,8 +12656,8 @@ async function deriveCommand(args) {
12549
12656
  return;
12550
12657
  }
12551
12658
  const plan = result.plan;
12552
- const { mkdirSync: mkdirSync7 } = await import("fs");
12553
- mkdirSync7(outputDir, { recursive: true });
12659
+ const { mkdirSync: mkdirSync8 } = await import("fs");
12660
+ mkdirSync8(outputDir, { recursive: true });
12554
12661
  const worldJson = {
12555
12662
  world_id: `plan_${plan.plan_id}`,
12556
12663
  name: `Derived: ${plan.objective}`,
@@ -12607,7 +12714,7 @@ async function deriveCommand(args) {
12607
12714
  process.stdout.write(` Invariants: ${plan.constraints.length} (one per constraint)
12608
12715
  `);
12609
12716
  }
12610
- async function main17(args) {
12717
+ async function main18(args) {
12611
12718
  const subcommand = args[0];
12612
12719
  const subArgs = args.slice(1);
12613
12720
  switch (subcommand) {
@@ -13502,7 +13609,7 @@ var init_session = __esm({
13502
13609
  // src/cli/run.ts
13503
13610
  var run_exports = {};
13504
13611
  __export(run_exports, {
13505
- main: () => main18
13612
+ main: () => main19
13506
13613
  });
13507
13614
  function parseArg2(args, flag) {
13508
13615
  const idx = args.indexOf(flag);
@@ -13527,7 +13634,7 @@ function autoDetectPlan() {
13527
13634
  function loadPlan(path) {
13528
13635
  return JSON.parse((0, import_fs5.readFileSync)(path, "utf-8"));
13529
13636
  }
13530
- async function main18(args) {
13637
+ async function main19(args) {
13531
13638
  if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
13532
13639
  process.stdout.write(RUN_USAGE + "\n");
13533
13640
  process.exit(0);
@@ -14280,9 +14387,9 @@ Progress: ${progress.completed}/${progress.total} (${progress.percentage}%)`;
14280
14387
  // src/cli/world.ts
14281
14388
  var world_exports = {};
14282
14389
  __export(world_exports, {
14283
- main: () => main19
14390
+ main: () => main20
14284
14391
  });
14285
- function parseArgs15(argv) {
14392
+ function parseArgs16(argv) {
14286
14393
  const subcommand = argv[0];
14287
14394
  const paths = [];
14288
14395
  const flags = {};
@@ -14560,8 +14667,8 @@ function worldCurrent(json) {
14560
14667
  process.stdout.write(`Source: ${info2.source}
14561
14668
  `);
14562
14669
  }
14563
- async function main19(argv = process.argv.slice(2)) {
14564
- const { subcommand, paths, flags } = parseArgs15(argv);
14670
+ async function main20(argv = process.argv.slice(2)) {
14671
+ const { subcommand, paths, flags } = parseArgs16(argv);
14565
14672
  if (flags.help || !subcommand) {
14566
14673
  process.stdout.write(USAGE + "\n");
14567
14674
  process.exit(0);
@@ -14652,9 +14759,9 @@ Options:
14652
14759
  // src/cli/trace.ts
14653
14760
  var trace_exports = {};
14654
14761
  __export(trace_exports, {
14655
- main: () => main20
14762
+ main: () => main21
14656
14763
  });
14657
- function parseArgs16(argv) {
14764
+ function parseArgs17(argv) {
14658
14765
  const args = {};
14659
14766
  for (let i = 0; i < argv.length; i++) {
14660
14767
  const arg = argv[i];
@@ -14738,8 +14845,8 @@ function formatSummary(events) {
14738
14845
  }
14739
14846
  return lines.join("\n");
14740
14847
  }
14741
- async function main20(argv = process.argv.slice(2)) {
14742
- const args = parseArgs16(argv);
14848
+ async function main21(argv = process.argv.slice(2)) {
14849
+ const args = parseArgs17(argv);
14743
14850
  if (args.help) {
14744
14851
  process.stdout.write(USAGE2 + "\n");
14745
14852
  process.exit(0);
@@ -15058,9 +15165,9 @@ var init_impact_report = __esm({
15058
15165
  // src/cli/impact.ts
15059
15166
  var impact_exports = {};
15060
15167
  __export(impact_exports, {
15061
- main: () => main21
15168
+ main: () => main22
15062
15169
  });
15063
- function parseArgs17(argv) {
15170
+ function parseArgs18(argv) {
15064
15171
  const args = {};
15065
15172
  for (let i = 0; i < argv.length; i++) {
15066
15173
  const arg = argv[i];
@@ -15070,8 +15177,8 @@ function parseArgs17(argv) {
15070
15177
  }
15071
15178
  return args;
15072
15179
  }
15073
- async function main21(argv = process.argv.slice(2)) {
15074
- const args = parseArgs17(argv);
15180
+ async function main22(argv = process.argv.slice(2)) {
15181
+ const args = parseArgs18(argv);
15075
15182
  if (args.help) {
15076
15183
  process.stdout.write(USAGE3 + "\n");
15077
15184
  process.exit(0);
@@ -15116,9 +15223,9 @@ repeat violations, and actor behavior patterns.
15116
15223
  // src/cli/behavioral.ts
15117
15224
  var behavioral_exports = {};
15118
15225
  __export(behavioral_exports, {
15119
- main: () => main22
15226
+ main: () => main23
15120
15227
  });
15121
- function parseArgs18(argv) {
15228
+ function parseArgs19(argv) {
15122
15229
  const args = {};
15123
15230
  for (let i = 0; i < argv.length; i++) {
15124
15231
  const arg = argv[i];
@@ -15128,8 +15235,8 @@ function parseArgs18(argv) {
15128
15235
  }
15129
15236
  return args;
15130
15237
  }
15131
- async function main22(argv = process.argv.slice(2)) {
15132
- const args = parseArgs18(argv);
15238
+ async function main23(argv = process.argv.slice(2)) {
15239
+ const args = parseArgs19(argv);
15133
15240
  if (args.help) {
15134
15241
  process.stdout.write(USAGE4 + "\n");
15135
15242
  process.exit(0);
@@ -15232,9 +15339,9 @@ and generates a human-readable narrative.
15232
15339
  // src/cli/derive.ts
15233
15340
  var derive_exports = {};
15234
15341
  __export(derive_exports, {
15235
- main: () => main23
15342
+ main: () => main24
15236
15343
  });
15237
- function parseArgs19(argv) {
15344
+ function parseArgs20(argv) {
15238
15345
  let inputPath = "";
15239
15346
  let outputPath = "./derived.nv-world.md";
15240
15347
  let validate = true;
@@ -15268,9 +15375,9 @@ function parseArgs19(argv) {
15268
15375
  if (!inputPath) throw new DeriveInputError("--input <path> is required");
15269
15376
  return { inputPath, outputPath, validate, dryRun, bootstrapDir, provider, model, endpoint };
15270
15377
  }
15271
- async function main23(argv = process.argv.slice(2)) {
15378
+ async function main24(argv = process.argv.slice(2)) {
15272
15379
  try {
15273
- const args = parseArgs19(argv);
15380
+ const args = parseArgs20(argv);
15274
15381
  const { result, exitCode, dryRunOutput } = await deriveWorld({
15275
15382
  inputPath: args.inputPath,
15276
15383
  outputPath: args.outputPath,
@@ -15380,9 +15487,9 @@ var init_derive = __esm({
15380
15487
  // src/cli/decision-flow.ts
15381
15488
  var decision_flow_exports = {};
15382
15489
  __export(decision_flow_exports, {
15383
- main: () => main24
15490
+ main: () => main25
15384
15491
  });
15385
- async function main24(args) {
15492
+ async function main25(args) {
15386
15493
  let logPath = ".neuroverse/audit.ndjson";
15387
15494
  let jsonOutput = false;
15388
15495
  for (let i = 0; i < args.length; i++) {
@@ -15439,7 +15546,7 @@ var init_decision_flow = __esm({
15439
15546
  // src/cli/equity-penalties.ts
15440
15547
  var equity_penalties_exports = {};
15441
15548
  __export(equity_penalties_exports, {
15442
- main: () => main25
15549
+ main: () => main26
15443
15550
  });
15444
15551
  function generateActionsForRound(agents, round2) {
15445
15552
  const actions = [];
@@ -15496,7 +15603,7 @@ function generateActionsForRound(agents, round2) {
15496
15603
  }
15497
15604
  return actions;
15498
15605
  }
15499
- async function main25(args) {
15606
+ async function main26(args) {
15500
15607
  let worldPath = "";
15501
15608
  let agentCount = 8;
15502
15609
  let rounds = 5;
@@ -15675,9 +15782,9 @@ var init_equity_penalties = __esm({
15675
15782
  // src/cli/keygen.ts
15676
15783
  var keygen_exports = {};
15677
15784
  __export(keygen_exports, {
15678
- main: () => main26
15785
+ main: () => main27
15679
15786
  });
15680
- function parseArgs20(argv) {
15787
+ function parseArgs21(argv) {
15681
15788
  let output = (0, import_path8.join)((0, import_os2.homedir)(), ".neuroverse", "keys");
15682
15789
  let name = "neuroverse";
15683
15790
  let force = false;
@@ -15696,8 +15803,8 @@ function parseArgs20(argv) {
15696
15803
  }
15697
15804
  return { output, name, force, help };
15698
15805
  }
15699
- async function main26(argv = process.argv.slice(2)) {
15700
- const args = parseArgs20(argv);
15806
+ async function main27(argv = process.argv.slice(2)) {
15807
+ const args = parseArgs21(argv);
15701
15808
  if (args.help) {
15702
15809
  process.stdout.write(USAGE5 + "\n");
15703
15810
  return;
@@ -15760,9 +15867,9 @@ var sign_exports = {};
15760
15867
  __export(sign_exports, {
15761
15868
  buildManifest: () => buildManifest,
15762
15869
  canonicalManifest: () => canonicalManifest,
15763
- main: () => main27
15870
+ main: () => main28
15764
15871
  });
15765
- function parseArgs21(argv) {
15872
+ function parseArgs22(argv) {
15766
15873
  let worldPath = "";
15767
15874
  let keyPath = (0, import_path9.join)((0, import_os3.homedir)(), ".neuroverse", "keys", "neuroverse.key");
15768
15875
  let help = false;
@@ -15806,8 +15913,8 @@ function canonicalManifest(files) {
15806
15913
  const sorted = Object.keys(files).sort();
15807
15914
  return sorted.map((k) => `${k}:${files[k]}`).join("\n");
15808
15915
  }
15809
- async function main27(argv = process.argv.slice(2)) {
15810
- const args = parseArgs21(argv);
15916
+ async function main28(argv = process.argv.slice(2)) {
15917
+ const args = parseArgs22(argv);
15811
15918
  if (args.help) {
15812
15919
  process.stdout.write(USAGE6 + "\n");
15813
15920
  return;
@@ -15872,9 +15979,9 @@ Examples:
15872
15979
  // src/cli/verify.ts
15873
15980
  var verify_exports = {};
15874
15981
  __export(verify_exports, {
15875
- main: () => main28
15982
+ main: () => main29
15876
15983
  });
15877
- function parseArgs22(argv) {
15984
+ function parseArgs23(argv) {
15878
15985
  let worldPath = "";
15879
15986
  let keyPath = (0, import_path10.join)((0, import_os4.homedir)(), ".neuroverse", "keys", "neuroverse.pub");
15880
15987
  let json = false;
@@ -15893,8 +16000,8 @@ function parseArgs22(argv) {
15893
16000
  }
15894
16001
  return { worldPath, keyPath, json, help };
15895
16002
  }
15896
- async function main28(argv = process.argv.slice(2)) {
15897
- const args = parseArgs22(argv);
16003
+ async function main29(argv = process.argv.slice(2)) {
16004
+ const args = parseArgs23(argv);
15898
16005
  if (args.help) {
15899
16006
  process.stdout.write(USAGE7 + "\n");
15900
16007
  return;
@@ -16027,7 +16134,7 @@ Examples:
16027
16134
  var migrate_exports = {};
16028
16135
  __export(migrate_exports, {
16029
16136
  LATEST_VERSION: () => LATEST_VERSION,
16030
- main: () => main29
16137
+ main: () => main30
16031
16138
  });
16032
16139
  function detectVersion(worldPath) {
16033
16140
  const metaPath = (0, import_path11.join)(worldPath, "metadata.json");
@@ -16060,7 +16167,7 @@ function findMigrationPath(from, to) {
16060
16167
  }
16061
16168
  return path;
16062
16169
  }
16063
- function parseArgs23(argv) {
16170
+ function parseArgs24(argv) {
16064
16171
  let worldPath = "";
16065
16172
  let dryRun = false;
16066
16173
  let backup = false;
@@ -16085,8 +16192,8 @@ function parseArgs23(argv) {
16085
16192
  }
16086
16193
  return { worldPath, dryRun, backup, target, json, help };
16087
16194
  }
16088
- async function main29(argv = process.argv.slice(2)) {
16089
- const args = parseArgs23(argv);
16195
+ async function main30(argv = process.argv.slice(2)) {
16196
+ const args = parseArgs24(argv);
16090
16197
  if (args.help) {
16091
16198
  process.stdout.write(USAGE8 + "\n");
16092
16199
  return;
@@ -16253,9 +16360,9 @@ Examples:
16253
16360
  // src/cli/configure-ai.ts
16254
16361
  var configure_ai_exports = {};
16255
16362
  __export(configure_ai_exports, {
16256
- main: () => main30
16363
+ main: () => main31
16257
16364
  });
16258
- function parseArgs24(argv) {
16365
+ function parseArgs25(argv) {
16259
16366
  let provider;
16260
16367
  let model;
16261
16368
  let apiKey;
@@ -16280,9 +16387,9 @@ function parseArgs24(argv) {
16280
16387
  }
16281
16388
  return { provider, model, apiKey, endpoint, show, test };
16282
16389
  }
16283
- async function main30(argv = process.argv.slice(2)) {
16390
+ async function main31(argv = process.argv.slice(2)) {
16284
16391
  try {
16285
- const args = parseArgs24(argv);
16392
+ const args = parseArgs25(argv);
16286
16393
  if (args.show) {
16287
16394
  const config2 = await loadConfig();
16288
16395
  if (!config2) {
@@ -16483,7 +16590,7 @@ var init_prompt_utils = __esm({
16483
16590
  // src/cli/configure-world.ts
16484
16591
  var configure_world_exports = {};
16485
16592
  __export(configure_world_exports, {
16486
- main: () => main31
16593
+ main: () => main32
16487
16594
  });
16488
16595
  function metricToStateVariable(metric) {
16489
16596
  const id = metric.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
@@ -16901,13 +17008,13 @@ function generateWorld(state) {
16901
17008
  return { worldJson, stateSchema, guardsJson, rules, gatesJson, invariants, outcomes, metadata };
16902
17009
  }
16903
17010
  async function writeWorld(outputDir, world) {
16904
- const { mkdirSync: mkdirSync7, existsSync: existsSync17 } = await import("fs");
17011
+ const { mkdirSync: mkdirSync8, existsSync: existsSync17 } = await import("fs");
16905
17012
  const { writeFile: writeFile6 } = await import("fs/promises");
16906
17013
  const { join: join21 } = await import("path");
16907
17014
  const files = [];
16908
- if (!existsSync17(outputDir)) mkdirSync7(outputDir, { recursive: true });
17015
+ if (!existsSync17(outputDir)) mkdirSync8(outputDir, { recursive: true });
16909
17016
  const rulesDir = join21(outputDir, "rules");
16910
- if (!existsSync17(rulesDir)) mkdirSync7(rulesDir, { recursive: true });
17017
+ if (!existsSync17(rulesDir)) mkdirSync8(rulesDir, { recursive: true });
16911
17018
  const writeJson = async (name, data) => {
16912
17019
  const path = join21(outputDir, name);
16913
17020
  await writeFile6(path, JSON.stringify(data, null, 2) + "\n", "utf-8");
@@ -16927,7 +17034,7 @@ async function writeWorld(outputDir, world) {
16927
17034
  }
16928
17035
  return files;
16929
17036
  }
16930
- function parseArgs25(argv) {
17037
+ function parseArgs26(argv) {
16931
17038
  let outputDir = "./world/";
16932
17039
  for (let i = 0; i < argv.length; i++) {
16933
17040
  const arg = argv[i];
@@ -16937,9 +17044,9 @@ function parseArgs25(argv) {
16937
17044
  }
16938
17045
  return { outputDir };
16939
17046
  }
16940
- async function main31(argv = process.argv.slice(2)) {
17047
+ async function main32(argv = process.argv.slice(2)) {
16941
17048
  try {
16942
- const args = parseArgs25(argv);
17049
+ const args = parseArgs26(argv);
16943
17050
  const context = await phaseContext();
16944
17051
  const guardState = await phaseGuard(context.domain);
16945
17052
  const systemState = await phaseSystem(context.domain);
@@ -17155,7 +17262,7 @@ function previewLens(lens) {
17155
17262
  const DIM4 = "\x1B[2m";
17156
17263
  const CYAN3 = "\x1B[36m";
17157
17264
  const YELLOW4 = "\x1B[33m";
17158
- const GREEN3 = "\x1B[32m";
17265
+ const GREEN4 = "\x1B[32m";
17159
17266
  const RESET4 = "\x1B[0m";
17160
17267
  const lines = [];
17161
17268
  lines.push("");
@@ -17166,7 +17273,7 @@ function previewLens(lens) {
17166
17273
  if (d.example) {
17167
17274
  lines.push(` ${BOLD4}${d.id}${RESET4}`);
17168
17275
  lines.push(` ${YELLOW4}Without:${RESET4} ${DIM4}${d.example.without}${RESET4}`);
17169
- lines.push(` ${GREEN3}With:${RESET4} ${d.example.with}`);
17276
+ lines.push(` ${GREEN4}With:${RESET4} ${d.example.with}`);
17170
17277
  lines.push("");
17171
17278
  }
17172
17279
  }
@@ -17840,7 +17947,7 @@ var init_lens = __esm({
17840
17947
  // src/cli/lens.ts
17841
17948
  var lens_exports = {};
17842
17949
  __export(lens_exports, {
17843
- main: () => main32
17950
+ main: () => main33
17844
17951
  });
17845
17952
  async function cmdList(argv) {
17846
17953
  let worldPath = "";
@@ -18173,7 +18280,7 @@ async function cmdAdd(argv) {
18173
18280
 
18174
18281
  `);
18175
18282
  }
18176
- async function main32(argv = process.argv.slice(2)) {
18283
+ async function main33(argv = process.argv.slice(2)) {
18177
18284
  const subcommand = argv[0];
18178
18285
  const subArgs = argv.slice(1);
18179
18286
  try {
@@ -19341,9 +19448,9 @@ var init_worldmodel_create = __esm({
19341
19448
  // src/cli/worldmodel.ts
19342
19449
  var worldmodel_exports = {};
19343
19450
  __export(worldmodel_exports, {
19344
- main: () => main33
19451
+ main: () => main34
19345
19452
  });
19346
- function parseArgs26(argv) {
19453
+ function parseArgs27(argv) {
19347
19454
  const args = {
19348
19455
  inputPath: "",
19349
19456
  output: "",
@@ -19396,7 +19503,7 @@ async function loadAndParse(inputPath) {
19396
19503
  return { model: result.model, issues: result.issues };
19397
19504
  }
19398
19505
  async function cmdInit(argv) {
19399
- const args = parseArgs26(argv);
19506
+ const args = parseArgs27(argv);
19400
19507
  if (args.help) {
19401
19508
  process.stdout.write(
19402
19509
  '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'
@@ -19718,7 +19825,7 @@ Examples:
19718
19825
  `;
19719
19826
  }
19720
19827
  async function cmdValidate(argv) {
19721
- const args = parseArgs26(argv);
19828
+ const args = parseArgs27(argv);
19722
19829
  if (args.help || !args.inputPath) {
19723
19830
  process.stdout.write(
19724
19831
  "neuroverse worldmodel validate <source.worldmodel.md> [--json]\n"
@@ -19775,7 +19882,7 @@ async function cmdValidate(argv) {
19775
19882
  process.exit(errors.length > 0 ? 1 : 0);
19776
19883
  }
19777
19884
  async function cmdExplain(argv) {
19778
- const args = parseArgs26(argv);
19885
+ const args = parseArgs27(argv);
19779
19886
  if (args.help || !args.inputPath) {
19780
19887
  process.stdout.write(
19781
19888
  "neuroverse worldmodel explain <source.worldmodel.md> [--json]\n"
@@ -19941,7 +20048,7 @@ function buildExplainData(model) {
19941
20048
  };
19942
20049
  }
19943
20050
  async function cmdBuild(argv) {
19944
- const args = parseArgs26(argv);
20051
+ const args = parseArgs27(argv);
19945
20052
  if (args.help || !args.inputPath) {
19946
20053
  process.stdout.write(
19947
20054
  "neuroverse worldmodel build <source.worldmodel.md> [--output <dir>] [--json]\n"
@@ -20038,7 +20145,7 @@ async function cmdBuild(argv) {
20038
20145
  }
20039
20146
  }
20040
20147
  async function cmdEmitWorld(argv) {
20041
- const args = parseArgs26(argv);
20148
+ const args = parseArgs27(argv);
20042
20149
  if (args.help || !args.inputPath) {
20043
20150
  process.stdout.write("neuroverse worldmodel emit-world <source.worldmodel.md>\n");
20044
20151
  return;
@@ -20056,7 +20163,7 @@ async function cmdEmitWorld(argv) {
20056
20163
  }
20057
20164
  }
20058
20165
  async function cmdEmitSignals(argv) {
20059
- const args = parseArgs26(argv);
20166
+ const args = parseArgs27(argv);
20060
20167
  if (args.help || !args.inputPath) {
20061
20168
  process.stdout.write(
20062
20169
  "neuroverse worldmodel emit-signals <source.worldmodel.md> [--json]\n"
@@ -20068,7 +20175,7 @@ async function cmdEmitSignals(argv) {
20068
20175
  process.stdout.write(JSON.stringify(schema, null, 2) + "\n");
20069
20176
  }
20070
20177
  async function cmdEmitLenses(argv) {
20071
- const args = parseArgs26(argv);
20178
+ const args = parseArgs27(argv);
20072
20179
  if (args.help || !args.inputPath) {
20073
20180
  process.stdout.write(
20074
20181
  "neuroverse worldmodel emit-lenses <source.worldmodel.md> [--json]\n"
@@ -20080,7 +20187,7 @@ async function cmdEmitLenses(argv) {
20080
20187
  process.stdout.write(JSON.stringify(lenses, null, 2) + "\n");
20081
20188
  }
20082
20189
  async function cmdEmitContexts(argv) {
20083
- const args = parseArgs26(argv);
20190
+ const args = parseArgs27(argv);
20084
20191
  if (args.help || !args.inputPath) {
20085
20192
  process.stdout.write(
20086
20193
  "neuroverse worldmodel emit-contexts <source.worldmodel.md> [--json]\n"
@@ -20092,7 +20199,7 @@ async function cmdEmitContexts(argv) {
20092
20199
  process.stdout.write(JSON.stringify(contexts, null, 2) + "\n");
20093
20200
  }
20094
20201
  async function cmdEmitOverlaps(argv) {
20095
- const args = parseArgs26(argv);
20202
+ const args = parseArgs27(argv);
20096
20203
  if (args.help || !args.inputPath) {
20097
20204
  process.stdout.write(
20098
20205
  "neuroverse worldmodel emit-overlaps <source.worldmodel.md> [--json]\n"
@@ -20103,7 +20210,7 @@ async function cmdEmitOverlaps(argv) {
20103
20210
  const overlaps = emitOverlapMap(model);
20104
20211
  process.stdout.write(JSON.stringify(overlaps, null, 2) + "\n");
20105
20212
  }
20106
- async function main33(argv = process.argv.slice(2)) {
20213
+ async function main34(argv = process.argv.slice(2)) {
20107
20214
  const subcommand = argv[0] ?? "";
20108
20215
  const subArgs = argv.slice(1);
20109
20216
  switch (subcommand) {
@@ -21832,6 +21939,262 @@ var init_notion = __esm({
21832
21939
  }
21833
21940
  });
21834
21941
 
21942
+ // src/radiant/adapters/linear.ts
21943
+ async function fetchLinearActivity(apiKey, options = {}) {
21944
+ const windowDays = options.windowDays ?? 14;
21945
+ const maxIssues = options.maxIssues ?? 200;
21946
+ const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
21947
+ const sinceIso = since.toISOString();
21948
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
21949
+ const teamFilter = options.teamIds && options.teamIds.length > 0 ? `team: { id: { in: [${options.teamIds.map((t) => JSON.stringify(t)).join(", ")}] } }` : "";
21950
+ const issuesQuery = `
21951
+ query RadiantIssues($since: DateTimeOrDuration!, $first: Int!) {
21952
+ issues(
21953
+ filter: {
21954
+ updatedAt: { gte: $since }
21955
+ ${teamFilter}
21956
+ }
21957
+ first: $first
21958
+ orderBy: updatedAt
21959
+ ) {
21960
+ nodes {
21961
+ id
21962
+ identifier
21963
+ title
21964
+ url
21965
+ createdAt
21966
+ updatedAt
21967
+ completedAt
21968
+ canceledAt
21969
+ state { name type }
21970
+ assignee { id name email }
21971
+ creator { id name }
21972
+ team { id name }
21973
+ project { id name }
21974
+ cycle { id number startsAt endsAt }
21975
+ comments(first: 20) {
21976
+ nodes { id body createdAt user { id name } }
21977
+ }
21978
+ }
21979
+ }
21980
+ }
21981
+ `;
21982
+ const cyclesQuery = `
21983
+ query RadiantCycles($since: DateTimeOrDuration!, $now: DateTimeOrDuration!) {
21984
+ cycles(
21985
+ filter: { endsAt: { gte: $since, lte: $now } }
21986
+ first: 20
21987
+ ) {
21988
+ nodes {
21989
+ id
21990
+ number
21991
+ startsAt
21992
+ endsAt
21993
+ issueCountHistory
21994
+ completedIssueCountHistory
21995
+ team { id name }
21996
+ }
21997
+ }
21998
+ }
21999
+ `;
22000
+ const [issuesResponse, cyclesResponse] = await Promise.all([
22001
+ fetchLinearGraphQL(apiKey, issuesQuery, {
22002
+ since: sinceIso,
22003
+ first: maxIssues
22004
+ }),
22005
+ fetchLinearGraphQL(apiKey, cyclesQuery, {
22006
+ since: sinceIso,
22007
+ now: nowIso
22008
+ })
22009
+ ]);
22010
+ const rawIssues = issuesResponse.issues?.nodes ?? [];
22011
+ const rawCycles = cyclesResponse.cycles?.nodes ?? [];
22012
+ const events = [];
22013
+ const assignees = /* @__PURE__ */ new Set();
22014
+ const projects = /* @__PURE__ */ new Map();
22015
+ let issuesCreated = 0;
22016
+ let issuesCompleted = 0;
22017
+ let issuesOpen = 0;
22018
+ let issuesStalled = 0;
22019
+ let commentsTotal = 0;
22020
+ const now = Date.now();
22021
+ const stallThresholdMs = 14 * 24 * 60 * 60 * 1e3;
22022
+ for (const issue of rawIssues) {
22023
+ const created = new Date(issue.createdAt);
22024
+ const updated = new Date(issue.updatedAt);
22025
+ const completed = issue.completedAt ? new Date(issue.completedAt) : null;
22026
+ const assigneeId = issue.assignee?.id ?? "unassigned";
22027
+ if (assigneeId !== "unassigned") assignees.add(assigneeId);
22028
+ if (issue.project) {
22029
+ projects.set(issue.project.name, (projects.get(issue.project.name) ?? 0) + 1);
22030
+ }
22031
+ const actor = {
22032
+ id: assigneeId,
22033
+ kind: "human",
22034
+ name: issue.assignee?.name ?? "unassigned"
22035
+ };
22036
+ if (created >= since) {
22037
+ issuesCreated++;
22038
+ events.push({
22039
+ id: `linear-created-${issue.id}`,
22040
+ timestamp: issue.createdAt,
22041
+ actor: {
22042
+ id: issue.creator?.id ?? "unknown",
22043
+ kind: "human",
22044
+ name: issue.creator?.name ?? "unknown"
22045
+ },
22046
+ kind: "issue_created",
22047
+ content: `[${issue.identifier}] ${issue.title}`,
22048
+ metadata: {
22049
+ issueId: issue.id,
22050
+ url: issue.url,
22051
+ team: issue.team?.name,
22052
+ project: issue.project?.name,
22053
+ state: issue.state?.name
22054
+ }
22055
+ });
22056
+ }
22057
+ if (completed && completed >= since) {
22058
+ issuesCompleted++;
22059
+ events.push({
22060
+ id: `linear-completed-${issue.id}`,
22061
+ timestamp: issue.completedAt,
22062
+ actor,
22063
+ kind: "issue_completed",
22064
+ content: `[${issue.identifier}] ${issue.title}`,
22065
+ metadata: {
22066
+ issueId: issue.id,
22067
+ url: issue.url,
22068
+ team: issue.team?.name,
22069
+ project: issue.project?.name,
22070
+ cycleDays: issue.cycle?.startsAt && issue.completedAt ? Math.round(
22071
+ (new Date(issue.completedAt).getTime() - new Date(issue.cycle.startsAt).getTime()) / (24 * 60 * 60 * 1e3)
22072
+ ) : null
22073
+ }
22074
+ });
22075
+ }
22076
+ if (!completed && !issue.canceledAt) {
22077
+ issuesOpen++;
22078
+ const isInProgress = issue.state?.type === "started";
22079
+ const idleMs = now - updated.getTime();
22080
+ if (isInProgress && idleMs > stallThresholdMs) issuesStalled++;
22081
+ }
22082
+ for (const comment of issue.comments?.nodes ?? []) {
22083
+ const commentedAt = new Date(comment.createdAt);
22084
+ if (commentedAt < since) continue;
22085
+ commentsTotal++;
22086
+ events.push({
22087
+ id: `linear-comment-${comment.id}`,
22088
+ timestamp: comment.createdAt,
22089
+ actor: {
22090
+ id: comment.user?.id ?? "unknown",
22091
+ kind: "human",
22092
+ name: comment.user?.name ?? "unknown"
22093
+ },
22094
+ kind: "issue_comment",
22095
+ content: comment.body.slice(0, 280),
22096
+ metadata: {
22097
+ issueId: issue.id,
22098
+ issueIdentifier: issue.identifier,
22099
+ url: issue.url
22100
+ }
22101
+ });
22102
+ }
22103
+ }
22104
+ let cycleCompletionRate = null;
22105
+ if (rawCycles.length > 0) {
22106
+ const rates = [];
22107
+ for (const cycle of rawCycles) {
22108
+ const committed = cycle.issueCountHistory?.at(0) ?? 0;
22109
+ const completed = cycle.completedIssueCountHistory?.at(-1) ?? 0;
22110
+ if (committed > 0) rates.push(completed / committed);
22111
+ }
22112
+ if (rates.length > 0) {
22113
+ cycleCompletionRate = Math.round(rates.reduce((a, b) => a + b, 0) / rates.length * 100) / 100;
22114
+ }
22115
+ }
22116
+ const topProjects = [...projects.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([name]) => name);
22117
+ const signals = {
22118
+ issuesCreated,
22119
+ issuesCompleted,
22120
+ issuesOpen,
22121
+ issuesStalled,
22122
+ cycleCompletionRate,
22123
+ uniqueAssignees: assignees.size,
22124
+ commentsTotal,
22125
+ topProjects
22126
+ };
22127
+ events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
22128
+ return { events, signals };
22129
+ }
22130
+ function formatLinearSignalsForPrompt(signals) {
22131
+ if (signals.issuesCreated === 0 && signals.issuesCompleted === 0 && signals.issuesOpen === 0) {
22132
+ return "";
22133
+ }
22134
+ const lines = [
22135
+ "## Linear Activity (planned work vs. shipped outcome)",
22136
+ "",
22137
+ `${signals.issuesCreated} issues created, ${signals.issuesCompleted} completed in window.`,
22138
+ `${signals.issuesOpen} issues still open.`
22139
+ ];
22140
+ if (signals.issuesStalled > 0) {
22141
+ lines.push(
22142
+ `${signals.issuesStalled} in-progress issues haven't moved in 14+ days (stalled).`
22143
+ );
22144
+ }
22145
+ if (signals.cycleCompletionRate !== null) {
22146
+ const pct = Math.round(signals.cycleCompletionRate * 100);
22147
+ lines.push(`Cycles ended in window completed ${pct}% of what was committed.`);
22148
+ }
22149
+ if (signals.uniqueAssignees > 0) {
22150
+ lines.push(`${signals.uniqueAssignees} unique assignees active.`);
22151
+ }
22152
+ if (signals.commentsTotal > 0) {
22153
+ lines.push(`${signals.commentsTotal} comments across issues in window.`);
22154
+ }
22155
+ if (signals.topProjects.length > 0) {
22156
+ lines.push(`Most active projects: ${signals.topProjects.join(", ")}.`);
22157
+ }
22158
+ lines.push("");
22159
+ lines.push("Linear is where the team states what it will build.");
22160
+ lines.push("GitHub is where the team reveals what actually got built.");
22161
+ lines.push("Low completion rate + high creation rate = planning faster than shipping.");
22162
+ lines.push("High stalled count = commitments made but not honored.");
22163
+ lines.push("Compare Linear signals against GitHub to find the stated-vs-shipped gap.");
22164
+ return lines.join("\n");
22165
+ }
22166
+ async function fetchLinearGraphQL(apiKey, query, variables) {
22167
+ const res = await fetch("https://api.linear.app/graphql", {
22168
+ method: "POST",
22169
+ headers: {
22170
+ // Linear accepts the raw API key in Authorization with no "Bearer" prefix.
22171
+ Authorization: apiKey,
22172
+ "Content-Type": "application/json"
22173
+ },
22174
+ body: JSON.stringify({ query, variables })
22175
+ });
22176
+ if (!res.ok) {
22177
+ throw new Error(
22178
+ `Linear API error ${res.status}: ${(await res.text()).slice(0, 300)}`
22179
+ );
22180
+ }
22181
+ const json = await res.json();
22182
+ if (json.errors && json.errors.length > 0) {
22183
+ throw new Error(
22184
+ `Linear GraphQL errors: ${json.errors.map((e) => e.message).join("; ")}`
22185
+ );
22186
+ }
22187
+ if (!json.data) {
22188
+ throw new Error("Linear API returned no data");
22189
+ }
22190
+ return json.data;
22191
+ }
22192
+ var init_linear = __esm({
22193
+ "src/radiant/adapters/linear.ts"() {
22194
+ "use strict";
22195
+ }
22196
+ });
22197
+
21835
22198
  // src/radiant/core/git-remote.ts
21836
22199
  function resolveGitConfigPath(repoDir) {
21837
22200
  const dotGit = (0, import_path14.join)(repoDir, ".git");
@@ -22485,6 +22848,7 @@ async function auditGovernance(events, worldPath) {
22485
22848
  return emptyAudit(events.length, "Could not load compiled worldmodel for governance audit.");
22486
22849
  }
22487
22850
  const verdicts = [];
22851
+ const crossings = [];
22488
22852
  for (const ce of events) {
22489
22853
  const intent = ce.event.content?.slice(0, 500) || ce.event.kind || "activity";
22490
22854
  const scope = ce.event.metadata?.scope || void 0;
@@ -22495,16 +22859,32 @@ async function auditGovernance(events, worldPath) {
22495
22859
  scope,
22496
22860
  actionCategory: mapKindToCategory(ce.event.kind)
22497
22861
  },
22498
- world
22862
+ world,
22863
+ { mode: "observe" }
22499
22864
  );
22865
+ const shadow = result.shadowStatus ?? "ALLOW";
22500
22866
  verdicts.push({
22501
22867
  eventId: ce.event.id,
22502
22868
  domain: ce.domain,
22503
- status: result.status,
22504
- reason: result.reason,
22869
+ status: shadow,
22870
+ reason: result.shadowReason,
22505
22871
  ruleId: result.ruleId,
22506
22872
  warning: result.warning
22507
22873
  });
22874
+ if (shadow !== "ALLOW") {
22875
+ crossings.push({
22876
+ eventId: ce.event.id,
22877
+ timestamp: ce.event.timestamp,
22878
+ kind: ce.event.kind,
22879
+ actorId: ce.event.actor.id,
22880
+ shadowStatus: shadow,
22881
+ shadowReason: result.shadowReason,
22882
+ ruleId: result.ruleId,
22883
+ excerpt: intent.length > 280 ? intent.slice(0, 279) + "\u2026" : intent,
22884
+ wouldHaveBlocked: true,
22885
+ verdict: result
22886
+ });
22887
+ }
22508
22888
  } catch {
22509
22889
  verdicts.push({
22510
22890
  eventId: ce.event.id,
@@ -22523,6 +22903,7 @@ async function auditGovernance(events, worldPath) {
22523
22903
  human,
22524
22904
  cyber,
22525
22905
  joint,
22906
+ crossings,
22526
22907
  summary: summary2
22527
22908
  };
22528
22909
  }
@@ -22578,6 +22959,7 @@ function emptyAudit(total, reason) {
22578
22959
  human: { allow: 0, modify: 0, block: 0, details: [] },
22579
22960
  cyber: { allow: 0, modify: 0, block: 0, details: [] },
22580
22961
  joint: { allow: 0, modify: 0, block: 0, details: [] },
22962
+ crossings: [],
22581
22963
  summary: reason
22582
22964
  };
22583
22965
  }
@@ -22761,6 +23143,144 @@ var init_signals = __esm({
22761
23143
  }
22762
23144
  });
22763
23145
 
23146
+ // src/radiant/core/vocabulary.ts
23147
+ function extractDeclaredVocabulary(worldmodelContent) {
23148
+ const aligned = extractSection(worldmodelContent, "Aligned Behaviors").map(
23149
+ (b) => parseBehavior(b, "aligned")
23150
+ );
23151
+ const drift = extractSection(worldmodelContent, "Drift Behaviors").map(
23152
+ (b) => parseBehavior(b, "drift")
23153
+ );
23154
+ const allNames = [...aligned, ...drift].map((p) => p.name);
23155
+ return { aligned, drift, allNames };
23156
+ }
23157
+ function extractSection(content, header) {
23158
+ const escaped = header.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
23159
+ const pattern = new RegExp(
23160
+ `##\\s+${escaped}\\s*\\n([\\s\\S]*?)(?=\\n##\\s|$)`,
23161
+ "i"
23162
+ );
23163
+ const match = content.match(pattern);
23164
+ if (!match) return [];
23165
+ const body = match[1];
23166
+ const bullets = body.match(/^[-*]\s+.+$/gm);
23167
+ if (!bullets) return [];
23168
+ return bullets.map((b) => b.replace(/^[-*]\s+/, "").trim()).filter((b) => b.length > 0 && !b.startsWith("<!--"));
23169
+ }
23170
+ function parseBehavior(bullet, kind) {
23171
+ const explicit = bullet.match(
23172
+ /^`?([a-z][a-z0-9_]*)`?\s+[—\u2014-]\s+(.+)$/i
23173
+ );
23174
+ if (explicit && isSnakeCase(explicit[1])) {
23175
+ return {
23176
+ name: explicit[1].toLowerCase(),
23177
+ prose: explicit[2].trim(),
23178
+ kind
23179
+ };
23180
+ }
23181
+ return { name: snakeCaseName(bullet), prose: bullet, kind };
23182
+ }
23183
+ function isSnakeCase(s) {
23184
+ return /^[a-z][a-z0-9_]*$/.test(s);
23185
+ }
23186
+ function snakeCaseName(s) {
23187
+ const base = s.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
23188
+ if (base.length <= 60) return base;
23189
+ const truncated = base.slice(0, 60);
23190
+ const lastUnderscore = truncated.lastIndexOf("_");
23191
+ return lastUnderscore > 20 ? truncated.slice(0, lastUnderscore) : truncated;
23192
+ }
23193
+ function matchDeclaredPattern(candidateName, candidateDescription, vocabulary) {
23194
+ const candidateText = `${candidateName.replace(/_/g, " ")} ${candidateDescription}`;
23195
+ const candidateWords = contentWords(candidateText);
23196
+ if (candidateWords.size === 0) return null;
23197
+ let best = null;
23198
+ for (const pattern of [...vocabulary.aligned, ...vocabulary.drift]) {
23199
+ const proseWords = contentWords(pattern.prose);
23200
+ if (proseWords.size === 0) continue;
23201
+ let shared = 0;
23202
+ for (const w of proseWords) {
23203
+ if (candidateWords.has(w)) shared++;
23204
+ }
23205
+ const coverage = shared / proseWords.size;
23206
+ if (shared >= 2 && coverage >= 0.3) {
23207
+ if (!best || coverage > best.score) {
23208
+ best = { pattern, score: coverage };
23209
+ }
23210
+ }
23211
+ }
23212
+ return best?.pattern ?? null;
23213
+ }
23214
+ function contentWords(text) {
23215
+ const words = text.toLowerCase().match(/[a-z][a-z0-9_]+/g) ?? [];
23216
+ return new Set(words.filter((w) => w.length > 3 && !STOPWORDS.has(w)));
23217
+ }
23218
+ var STOPWORDS;
23219
+ var init_vocabulary = __esm({
23220
+ "src/radiant/core/vocabulary.ts"() {
23221
+ "use strict";
23222
+ STOPWORDS = /* @__PURE__ */ new Set([
23223
+ "about",
23224
+ "after",
23225
+ "against",
23226
+ "among",
23227
+ "around",
23228
+ "because",
23229
+ "been",
23230
+ "before",
23231
+ "being",
23232
+ "between",
23233
+ "both",
23234
+ "could",
23235
+ "does",
23236
+ "doing",
23237
+ "during",
23238
+ "each",
23239
+ "from",
23240
+ "further",
23241
+ "have",
23242
+ "having",
23243
+ "into",
23244
+ "itself",
23245
+ "most",
23246
+ "nor",
23247
+ "only",
23248
+ "other",
23249
+ "over",
23250
+ "same",
23251
+ "should",
23252
+ "some",
23253
+ "such",
23254
+ "than",
23255
+ "that",
23256
+ "their",
23257
+ "them",
23258
+ "then",
23259
+ "there",
23260
+ "these",
23261
+ "they",
23262
+ "this",
23263
+ "those",
23264
+ "through",
23265
+ "under",
23266
+ "until",
23267
+ "very",
23268
+ "were",
23269
+ "what",
23270
+ "when",
23271
+ "where",
23272
+ "which",
23273
+ "while",
23274
+ "will",
23275
+ "with",
23276
+ "without",
23277
+ "would",
23278
+ "your",
23279
+ "yours"
23280
+ ]);
23281
+ }
23282
+ });
23283
+
22764
23284
  // src/radiant/types.ts
22765
23285
  function isScored(s) {
22766
23286
  return typeof s === "number";
@@ -22812,7 +23332,11 @@ var init_math = __esm({
22812
23332
  async function interpretPatterns(input) {
22813
23333
  const prompt = buildInterpretationPrompt(input);
22814
23334
  const raw = await input.ai.complete(prompt, "Analyze the activity and produce the read.");
22815
- const parsed = parseInterpretation(raw, input.canonicalPatterns ?? []);
23335
+ const canonicalNames = [
23336
+ ...input.canonicalPatterns ?? [],
23337
+ ...input.declaredVocabulary?.allNames ?? []
23338
+ ];
23339
+ const parsed = parseInterpretation(raw, canonicalNames, input.declaredVocabulary);
22816
23340
  return {
22817
23341
  patterns: parsed.patterns,
22818
23342
  meaning: parsed.meaning,
@@ -22823,8 +23347,10 @@ async function interpretPatterns(input) {
22823
23347
  function buildInterpretationPrompt(input) {
22824
23348
  const signalSummary = formatSignalSummary(input.signals);
22825
23349
  const eventSample = formatEventSample(input.events, 30);
22826
- const canonicalList = (input.canonicalPatterns ?? []).length > 0 ? `Patterns the organization has already named (use these names if you see them):
22827
- ${input.canonicalPatterns.map((p) => `- ${p}`).join("\n")}` : "No patterns have been named yet. Everything you observe is new.";
23350
+ const canonicalList = formatDeclaredVocabulary(
23351
+ input.declaredVocabulary,
23352
+ input.canonicalPatterns ?? []
23353
+ );
22828
23354
  const compressedWorld = compressWorldmodel(input.worldmodelContent);
22829
23355
  const cl = compressLens(input.lens);
22830
23356
  const frame = input.lens.primary_frame;
@@ -22935,6 +23461,44 @@ Only recommend a move when the evidence actually calls for one.
22935
23461
  Do NOT use these phrases anywhere in your output:
22936
23462
  ${forbiddenList}`;
22937
23463
  }
23464
+ function formatDeclaredVocabulary(vocabulary, extraNames) {
23465
+ const aligned = vocabulary?.aligned ?? [];
23466
+ const drift = vocabulary?.drift ?? [];
23467
+ if (aligned.length === 0 && drift.length === 0 && extraNames.length === 0) {
23468
+ return 'No patterns have been named yet. Everything you observe is new \u2014 mark it type: "candidate".';
23469
+ }
23470
+ const parts = [];
23471
+ parts.push("## Declared vocabulary (use these names when you see matching evidence)");
23472
+ parts.push("");
23473
+ parts.push(
23474
+ 'The worldmodel declares the patterns below. If your observation matches one of these, use the EXACT snake_case name shown and mark type: "canonical" \u2014 do not invent a new name for something that already has one.'
23475
+ );
23476
+ parts.push("");
23477
+ if (aligned.length > 0) {
23478
+ parts.push("### Aligned behaviors (positive patterns)");
23479
+ for (const p of aligned) {
23480
+ parts.push(`- \`${p.name}\` \u2014 ${p.prose}`);
23481
+ }
23482
+ parts.push("");
23483
+ }
23484
+ if (drift.length > 0) {
23485
+ parts.push("### Drift behaviors (negative patterns)");
23486
+ for (const p of drift) {
23487
+ parts.push(`- \`${p.name}\` \u2014 ${p.prose}`);
23488
+ }
23489
+ parts.push("");
23490
+ }
23491
+ if (extraNames.length > 0) {
23492
+ parts.push(
23493
+ `Additional canonical names (from prior runs or caller): ${extraNames.join(", ")}`
23494
+ );
23495
+ parts.push("");
23496
+ }
23497
+ parts.push(
23498
+ 'If you observe something genuinely new that matches NO declared pattern, mark it type: "candidate" with a freshly-invented snake_case name.'
23499
+ );
23500
+ return parts.join("\n");
23501
+ }
22938
23502
  function formatSignalSummary(signals) {
22939
23503
  const lines = [];
22940
23504
  const domains = ["life", "cyber", "joint"];
@@ -22960,7 +23524,7 @@ function formatEventSample(events, maxEvents) {
22960
23524
  "${content}"`;
22961
23525
  }).join("\n");
22962
23526
  }
22963
- function parseInterpretation(raw, canonicalNames) {
23527
+ function parseInterpretation(raw, canonicalNames, vocabulary) {
22964
23528
  let meaning = "";
22965
23529
  let move = "";
22966
23530
  let patternsArray = [];
@@ -22990,14 +23554,23 @@ function parseInterpretation(raw, canonicalNames) {
22990
23554
  const patterns = [];
22991
23555
  for (const item of patternsArray) {
22992
23556
  if (!isPatternLike(item)) continue;
22993
- const nameStr = String(item.name ?? "unnamed");
23557
+ const rawName = String(item.name ?? "unnamed");
23558
+ const description = String(item.description ?? "");
22994
23559
  const ev = item.evidence;
22995
- const isCanonical = item.type === "canonical" || canonicalSet.has(nameStr.toLowerCase());
23560
+ let name = rawName;
23561
+ let isCanonical = item.type === "canonical" || canonicalSet.has(rawName.toLowerCase());
23562
+ if (!isCanonical && vocabulary) {
23563
+ const matched = matchDeclaredPattern(rawName, description, vocabulary);
23564
+ if (matched) {
23565
+ name = matched.name;
23566
+ isCanonical = true;
23567
+ }
23568
+ }
22996
23569
  patterns.push({
22997
- name: nameStr,
23570
+ name,
22998
23571
  type: isCanonical ? "canonical" : "candidate",
22999
- declaredAs: isCanonical ? nameStr : void 0,
23000
- description: String(item.description ?? ""),
23572
+ declaredAs: isCanonical ? name : void 0,
23573
+ description,
23001
23574
  evidence: {
23002
23575
  signals: Array.isArray(ev?.signals) ? ev.signals.map(String) : [],
23003
23576
  events: Array.isArray(ev?.events) ? ev.events.map(String) : [],
@@ -23015,6 +23588,7 @@ var init_patterns = __esm({
23015
23588
  "src/radiant/core/patterns.ts"() {
23016
23589
  "use strict";
23017
23590
  init_compress();
23591
+ init_vocabulary();
23018
23592
  }
23019
23593
  });
23020
23594
 
@@ -23333,10 +23907,24 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
23333
23907
  } catch {
23334
23908
  }
23335
23909
  }
23910
+ const linearKey = process.env.LINEAR_API_KEY;
23911
+ if (linearKey) {
23912
+ try {
23913
+ const linear = await fetchLinearActivity(linearKey, { windowDays });
23914
+ events.push(...linear.events);
23915
+ adapterSignals += "\n\n" + formatLinearSignalsForPrompt(linear.signals);
23916
+ activeAdapters.push("linear");
23917
+ } catch {
23918
+ }
23919
+ }
23336
23920
  events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
23921
+ if (input.personalUser) {
23922
+ events = filterEventsByUser(events, input.personalUser);
23923
+ }
23337
23924
  const classified = classifyEvents(events);
23338
23925
  const signals = extractSignals(classified);
23339
23926
  const scores = computeScores(signals, input.worldmodelContent !== "");
23927
+ const declaredVocabulary = extractDeclaredVocabulary(worldmodelContent);
23340
23928
  const { patterns, meaning, move } = await interpretPatterns({
23341
23929
  signals,
23342
23930
  events: classified,
@@ -23344,6 +23932,7 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
23344
23932
  lens,
23345
23933
  ai: input.ai,
23346
23934
  canonicalPatterns: input.canonicalPatterns,
23935
+ declaredVocabulary,
23347
23936
  statedIntent: [statedIntent, adapterSignals, priorReadContext].filter(Boolean).join("\n\n") || void 0
23348
23937
  });
23349
23938
  const rewrittenPatterns = patterns.map((p) => lens.rewrite(p));
@@ -23395,9 +23984,14 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
23395
23984
  scores,
23396
23985
  eventCount: events.length,
23397
23986
  activeAdapters,
23398
- worldStack
23987
+ worldStack,
23988
+ governance
23399
23989
  };
23400
23990
  }
23991
+ function filterEventsByUser(events, username) {
23992
+ const target = username.toLowerCase();
23993
+ return events.filter((e) => e.actor.id.toLowerCase() === target);
23994
+ }
23401
23995
  function computeScores(signals, worldmodelLoaded) {
23402
23996
  const gate = DEFAULT_EVIDENCE_GATE;
23403
23997
  const lifeSignals = signals.filter((s) => s.domain === "life");
@@ -23453,12 +24047,14 @@ var init_emergent = __esm({
23453
24047
  init_discord();
23454
24048
  init_slack();
23455
24049
  init_notion();
24050
+ init_linear();
23456
24051
  init_discovery();
23457
24052
  init_exocortex();
23458
24053
  init_palace();
23459
24054
  init_compress();
23460
24055
  init_governance();
23461
24056
  init_signals();
24057
+ init_vocabulary();
23462
24058
  init_math();
23463
24059
  init_patterns();
23464
24060
  init_renderer();
@@ -23780,9 +24376,11 @@ var init_server = __esm({
23780
24376
  // src/cli/radiant.ts
23781
24377
  var radiant_exports = {};
23782
24378
  __export(radiant_exports, {
23783
- main: () => main34
24379
+ checkScopeConsent: () => checkScopeConsent,
24380
+ main: () => main35,
24381
+ parseArgs: () => parseArgs28
23784
24382
  });
23785
- function parseArgs27(argv) {
24383
+ function parseArgs28(argv) {
23786
24384
  const result = {
23787
24385
  subcommand: void 0,
23788
24386
  lens: void 0,
@@ -23792,8 +24390,12 @@ function parseArgs27(argv) {
23792
24390
  exocortex: void 0,
23793
24391
  teamExocortex: void 0,
23794
24392
  view: void 0,
24393
+ user: void 0,
24394
+ personal: false,
24395
+ entireOrg: false,
23795
24396
  json: false,
23796
24397
  help: false,
24398
+ force: false,
23797
24399
  rest: []
23798
24400
  };
23799
24401
  let i = 0;
@@ -23825,9 +24427,22 @@ function parseArgs27(argv) {
23825
24427
  case "--view":
23826
24428
  result.view = argv[++i];
23827
24429
  break;
24430
+ case "--user":
24431
+ result.user = argv[++i];
24432
+ break;
24433
+ case "--personal":
24434
+ result.personal = true;
24435
+ break;
24436
+ case "--entire-org":
24437
+ result.entireOrg = true;
24438
+ break;
23828
24439
  case "--json":
23829
24440
  result.json = true;
23830
24441
  break;
24442
+ case "--force":
24443
+ case "-f":
24444
+ result.force = true;
24445
+ break;
23831
24446
  case "--help":
23832
24447
  case "-h":
23833
24448
  result.help = true;
@@ -23985,6 +24600,15 @@ ${DIM3}Model: ${model ?? "claude-sonnet-4-20250514 (default)"}${RESET3}
23985
24600
  process.exit(2);
23986
24601
  }
23987
24602
  }
24603
+ function checkScopeConsent(input) {
24604
+ if (input.personal && !input.resolvedUser) {
24605
+ return { ok: false, reason: "personal_requires_user" };
24606
+ }
24607
+ if (input.scope.type === "org" && !input.entireOrg && !input.personal) {
24608
+ return { ok: false, reason: "org_requires_opt_in" };
24609
+ }
24610
+ return { ok: true };
24611
+ }
23988
24612
  async function cmdEmergent(args) {
23989
24613
  const scopeStr = args.rest[0];
23990
24614
  if (!scopeStr) {
@@ -23995,6 +24619,43 @@ async function cmdEmergent(args) {
23995
24619
  process.exit(1);
23996
24620
  }
23997
24621
  const scope = parseScope(scopeStr);
24622
+ const personalUser = args.user ?? process.env.RADIANT_USER;
24623
+ const consent = checkScopeConsent({
24624
+ scope,
24625
+ personal: args.personal,
24626
+ entireOrg: args.entireOrg,
24627
+ resolvedUser: personalUser
24628
+ });
24629
+ if (!consent.ok) {
24630
+ if (consent.reason === "personal_requires_user") {
24631
+ process.stderr.write(
24632
+ `${RED2}Error:${RESET3} --personal requires a GitHub username.
24633
+ ${DIM3}Pass --user <login> or set RADIANT_USER. Radiant will read
24634
+ only that user's activity \u2014 no one else is observed.${RESET3}
24635
+ `
24636
+ );
24637
+ } else {
24638
+ process.stderr.write(
24639
+ `${YELLOW3}\u26A0${RESET3} ${BOLD3}"${scope.owner}" is an org-wide scope.${RESET3}
24640
+
24641
+ ${DIM3}This reads activity across ALL repos in the org \u2014 a global-observer
24642
+ pattern that some teams consider offside with decentralization and
24643
+ cognitive-liberty principles. It's opt-in for that reason.${RESET3}
24644
+
24645
+ Three ways forward:
24646
+ ${GREEN3}1.${RESET3} Scope to a single repo (recommended default):
24647
+ radiant emergent ${scope.owner}/<repo>
24648
+
24649
+ ${GREEN3}2.${RESET3} Read only your own activity (personal mode):
24650
+ radiant emergent ${scope.owner}/ --personal --user <your-login>
24651
+
24652
+ ${GREEN3}3.${RESET3} Explicitly opt in to org-wide observation:
24653
+ radiant emergent ${scope.owner}/ --entire-org
24654
+ `
24655
+ );
24656
+ }
24657
+ process.exit(1);
24658
+ }
23998
24659
  const lensId = args.lens ?? process.env.RADIANT_LENS;
23999
24660
  if (!lensId) {
24000
24661
  process.stderr.write(
@@ -24043,8 +24704,11 @@ ${DIM3}Set it to a GitHub PAT with repo read access.${RESET3}
24043
24704
  const ctx = readExocortex(exocortexPath);
24044
24705
  exocortexStatus = summarizeExocortex(ctx);
24045
24706
  }
24707
+ const scopeLabel = scope.type === "org" ? scope.owner + " (entire org)" : scope.owner + "/" + scope.repo;
24708
+ const modeLabel = args.personal ? `personal \u2014 only ${personalUser}'s activity` : "team \u2014 all contributors";
24046
24709
  process.stderr.write(
24047
- `${DIM3}Scope: ${scope.type === "org" ? scope.owner + " (entire org)" : scope.owner + "/" + scope.repo}${RESET3}
24710
+ `${DIM3}Scope: ${scopeLabel}${RESET3}
24711
+ ${DIM3}Mode: ${modeLabel}${RESET3}
24048
24712
  ${DIM3}View: ${view}${RESET3}
24049
24713
  ${DIM3}Lens: ${lensId}${RESET3}
24050
24714
  ${DIM3}Model: ${model ?? "claude-sonnet-4-20250514 (default)"}${RESET3}
@@ -24060,7 +24724,8 @@ ${DIM3}Fetching activity...${RESET3}
24060
24724
  lensId,
24061
24725
  ai,
24062
24726
  windowDays: 14,
24063
- exocortexPath: exocortexPath || void 0
24727
+ exocortexPath: exocortexPath || void 0,
24728
+ personalUser: args.personal ? personalUser : void 0
24064
24729
  });
24065
24730
  if (!result.voiceClean) {
24066
24731
  process.stderr.write(
@@ -24162,13 +24827,52 @@ ${DIM3}Use: lenses list | lenses describe <id>${RESET3}
24162
24827
  );
24163
24828
  process.exit(1);
24164
24829
  }
24165
- async function main34(argv) {
24166
- const args = parseArgs27(argv);
24830
+ async function cmdInit2(args) {
24831
+ const targetDir = (0, import_path20.resolve)(args.rest[0] ?? "./mind-palace");
24832
+ const existed = (0, import_fs19.existsSync)(targetDir);
24833
+ if (existed && !args.force) {
24834
+ const entries = (0, import_fs19.readdirSync)(targetDir);
24835
+ if (entries.length > 0) {
24836
+ process.stderr.write(
24837
+ `${RED2}Error:${RESET3} ${targetDir} already exists and is not empty.
24838
+ ${DIM3}Use --force to write into it anyway (existing files will be overwritten).${RESET3}
24839
+ `
24840
+ );
24841
+ process.exit(1);
24842
+ }
24843
+ }
24844
+ (0, import_fs19.mkdirSync)(targetDir, { recursive: true });
24845
+ (0, import_fs19.mkdirSync)((0, import_path20.join)(targetDir, "reads"), { recursive: true });
24846
+ (0, import_fs19.mkdirSync)((0, import_path20.join)(targetDir, "worldmodels"), { recursive: true });
24847
+ for (const [relPath, content] of Object.entries(MIND_PALACE_FILES)) {
24848
+ const fullPath = (0, import_path20.join)(targetDir, relPath);
24849
+ (0, import_fs19.mkdirSync)((0, import_path20.resolve)(fullPath, ".."), { recursive: true });
24850
+ (0, import_fs19.writeFileSync)(fullPath, content, "utf-8");
24851
+ }
24852
+ process.stdout.write(
24853
+ `${GREEN3}\u2713${RESET3} Mind Palace scaffolded at ${BOLD3}${targetDir}${RESET3}
24854
+
24855
+ ${DIM3}Next steps:${RESET3}
24856
+ 1. Edit ${targetDir}/attention.md \u2014 what you're focused on right now
24857
+ 2. Edit ${targetDir}/worldmodels/starter.worldmodel.md \u2014 add a few
24858
+ aligned and drift behaviors
24859
+ 3. Run: neuroverse radiant emergent <owner/repo> \\
24860
+ --worlds ${targetDir}/worldmodels \\
24861
+ --exocortex ${targetDir}
24862
+
24863
+ ${DIM3}Files are yours. Edit freely.${RESET3}
24864
+ `
24865
+ );
24866
+ }
24867
+ async function main35(argv) {
24868
+ const args = parseArgs28(argv);
24167
24869
  if (args.help || !args.subcommand) {
24168
24870
  process.stdout.write(USAGE10 + "\n");
24169
24871
  return;
24170
24872
  }
24171
24873
  switch (args.subcommand) {
24874
+ case "init":
24875
+ return cmdInit2(args);
24172
24876
  case "think":
24173
24877
  return cmdThink(args);
24174
24878
  case "lenses":
@@ -24199,7 +24903,7 @@ async function main34(argv) {
24199
24903
  process.exit(1);
24200
24904
  }
24201
24905
  }
24202
- var import_fs19, import_path20, RED2, DIM3, BOLD3, YELLOW3, RESET3, USAGE10;
24906
+ var import_fs19, import_path20, RED2, GREEN3, DIM3, BOLD3, YELLOW3, RESET3, USAGE10, MIND_PALACE_FILES;
24203
24907
  var init_radiant = __esm({
24204
24908
  "src/cli/radiant.ts"() {
24205
24909
  "use strict";
@@ -24213,6 +24917,7 @@ var init_radiant = __esm({
24213
24917
  init_lenses();
24214
24918
  init_discovery();
24215
24919
  RED2 = "\x1B[31m";
24920
+ GREEN3 = "\x1B[32m";
24216
24921
  DIM3 = "\x1B[2m";
24217
24922
  BOLD3 = "\x1B[1m";
24218
24923
  YELLOW3 = "\x1B[33m";
@@ -24220,6 +24925,9 @@ var init_radiant = __esm({
24220
24925
  USAGE10 = `
24221
24926
  ${BOLD3}neuroverse radiant${RESET3} \u2014 behavioral intelligence for collaboration systems
24222
24927
 
24928
+ ${BOLD3}Setup:${RESET3}
24929
+ init Scaffold a Mind Palace in the current directory
24930
+
24223
24931
  ${BOLD3}Stage A (voice layer):${RESET3}
24224
24932
  think Send a query through the worldmodel + lens \u2192 AI-framed response
24225
24933
 
@@ -24230,13 +24938,27 @@ ${BOLD3}Stage B (behavioral analysis, coming soon):${RESET3}
24230
24938
  lenses List or describe available rendering lenses
24231
24939
 
24232
24940
  ${BOLD3}Usage:${RESET3}
24941
+ neuroverse radiant init (scaffolds ./mind-palace/)
24942
+ neuroverse radiant init ./my-palace (custom path)
24233
24943
  neuroverse radiant think --lens auki-builder --worlds ./worlds/ --query "What is our biggest risk?"
24234
24944
  neuroverse radiant think --lens auki-builder --worlds ./worlds/ < prompt.txt
24235
24945
  neuroverse radiant emergent aukiverse/posemesh --lens auki-builder --worlds ./worlds/
24236
24946
  neuroverse radiant emergent aukiverse/posemesh --lens auki-builder --worlds ./worlds/ --exocortex ~/exocortex/
24947
+ neuroverse radiant emergent aukilabs/posemesh --personal --user alice
24948
+ neuroverse radiant emergent aukilabs/ --entire-org --lens auki-builder --worlds ./worlds/
24237
24949
  neuroverse radiant lenses list
24238
24950
  neuroverse radiant lenses describe auki-builder
24239
24951
 
24952
+ ${BOLD3}Read modes:${RESET3}
24953
+ ${BOLD3}Default (team):${RESET3} reads all contributors in the given scope.
24954
+ ${BOLD3}--personal --user <login>:${RESET3} reads ONLY that user's activity.
24955
+ A local, private facilitator \u2014 no one else is observed. Works against
24956
+ any scope; an org scope with --personal is fine.
24957
+ ${BOLD3}--entire-org (gated):${RESET3} org-wide scope observes every contributor
24958
+ across every repo. This is a global-observer stance and is opt-in.
24959
+ \`radiant emergent <org>/\` without --entire-org will refuse and show
24960
+ you the three choices (single repo, --personal, or explicit opt-in).
24961
+
24240
24962
  ${BOLD3}Auto-discovery:${RESET3}
24241
24963
  You do not need to clone the target repo.
24242
24964
 
@@ -24255,7 +24977,169 @@ ${BOLD3}Environment:${RESET3}
24255
24977
  RADIANT_LENS Default lens id (overridden by --lens)
24256
24978
  RADIANT_MODEL AI model override (default: claude-sonnet-4-20250514)
24257
24979
  RADIANT_EXOCORTEX Default exocortex directory (overridden by --exocortex)
24980
+ RADIANT_USER Default personal-mode user (overridden by --user)
24258
24981
  `.trim();
24982
+ MIND_PALACE_FILES = {
24983
+ "README.md": `# Mind Palace
24984
+
24985
+ This is your Mind Palace \u2014 structured external memory that gives Radiant
24986
+ (and any agent you wire into it) persistent context about who you are,
24987
+ what you're working on, and what "on track" means for you.
24988
+
24989
+ Radiant reads these files before every run and writes each read back into
24990
+ \`reads/\`. Over time, \`knowledge.md\` accumulates what's persisted and what
24991
+ hasn't \u2014 the feedback loop that turns raw activity into named behavior.
24992
+
24993
+ ## Files
24994
+
24995
+ - \`attention.md\` \u2014 what you're focused on **right now**
24996
+ - \`goals.md\` \u2014 what you're working toward
24997
+ - \`sprint.md\` \u2014 this week's focus
24998
+ - \`identity.md\` \u2014 who you are, what you value
24999
+ - \`worldmodels/\` \u2014 your thinking constitutions (drift + aligned behaviors)
25000
+ - \`reads/\` \u2014 dated Radiant reads (written by \`radiant emergent\`)
25001
+ - \`knowledge.md\` \u2014 accumulated pattern persistence across reads
25002
+
25003
+ ## How to use
25004
+
25005
+ 1. Fill in \`attention.md\`, \`goals.md\`, \`sprint.md\`, \`identity.md\` with
25006
+ your own words. A sentence each is enough to start \u2014 the files grow
25007
+ with you.
25008
+ 2. Edit \`worldmodels/starter.worldmodel.md\`: add a few aligned behaviors
25009
+ (what on-track looks like) and drift behaviors (what off-track looks
25010
+ like). The sharper these are, the sharper Radiant's reads.
25011
+ 3. Run \`neuroverse radiant emergent <owner/repo> --mind-palace .\` against
25012
+ the repo you want read. Radiant compares your stated intent (these
25013
+ files) to your observed activity (GitHub) and names the gap.
25014
+
25015
+ Edit freely. These files are yours.
25016
+ `,
25017
+ "attention.md": `# Attention
25018
+
25019
+ <!--
25020
+ What are you focused on RIGHT NOW? One paragraph. Updated as you shift.
25021
+ This is the file an AI agent reads at the start of a session to know
25022
+ what to help with today.
25023
+ -->
25024
+
25025
+ `,
25026
+ "goals.md": `# Goals
25027
+
25028
+ <!--
25029
+ What are you working toward? Bullet points welcome.
25030
+ Longer horizon than attention \u2014 months, not days.
25031
+ -->
25032
+
25033
+ -
25034
+ `,
25035
+ "sprint.md": `# Sprint
25036
+
25037
+ <!--
25038
+ This week's focus. What do you want to ship or finish?
25039
+ Keep it short \u2014 five bullets max.
25040
+ -->
25041
+
25042
+ -
25043
+ `,
25044
+ "identity.md": `# Identity
25045
+
25046
+ <!--
25047
+ Who are you, what do you value, how do you work?
25048
+ This is the context an agent needs to not treat you like a stranger
25049
+ every time. Write it in your own voice.
25050
+ -->
25051
+
25052
+ `,
25053
+ "knowledge.md": `# Knowledge
25054
+
25055
+ <!--
25056
+ Radiant writes accumulated pattern persistence here across reads.
25057
+ Leave this file empty on day one \u2014 it fills up as \`radiant emergent\`
25058
+ runs accumulate.
25059
+ -->
25060
+
25061
+ `,
25062
+ "reads/.gitkeep": "",
25063
+ "worldmodels/starter.worldmodel.md": `# Starter Worldmodel
25064
+
25065
+ <!--
25066
+ Your thinking constitution. Radiant reads this to understand what
25067
+ "aligned" and "drift" mean for your work.
25068
+
25069
+ The sharper the Aligned/Drift Behaviors, the sharper Radiant's reads.
25070
+ When Radiant detects something matching a drift behavior below, it
25071
+ labels it with THAT name \u2014 it doesn't invent new ones.
25072
+ -->
25073
+
25074
+ ## Mission
25075
+
25076
+ <!-- One sentence. What are you doing in the world? -->
25077
+
25078
+
25079
+ ## Invariants
25080
+
25081
+ <!--
25082
+ Non-negotiable rules. If a decision violates one, it's blocked.
25083
+ Keep this list short \u2014 3 to 6 items. Each should be a hard no.
25084
+ -->
25085
+
25086
+ -
25087
+
25088
+ ## Aligned Behaviors
25089
+
25090
+ <!--
25091
+ What "on track" looks like. One per line, phrased as a behavior.
25092
+ Radiant will use these as canonical pattern names when it sees
25093
+ matching evidence in your activity.
25094
+
25095
+ Example:
25096
+ - ships partial-but-working features rather than waiting for the full stack
25097
+ - writes decisions down before acting on them
25098
+ -->
25099
+
25100
+ -
25101
+
25102
+ ## Drift Behaviors
25103
+
25104
+ <!--
25105
+ What "off track" looks like. Same format as Aligned.
25106
+ When Radiant detects drift, it will label it with these names \u2014 not
25107
+ make up new ones.
25108
+
25109
+ Example:
25110
+ - shipping pace outruns strategic decision-making
25111
+ - architecture decisions surface without context about why
25112
+ -->
25113
+
25114
+ -
25115
+
25116
+ ## Signals
25117
+
25118
+ <!--
25119
+ Observable quantities you care about. Radiant scores activity
25120
+ against these \u2014 5 to 7 is the sweet spot.
25121
+
25122
+ Example:
25123
+ - shipping_velocity
25124
+ - decision_ownership
25125
+ - storytelling_cadence
25126
+ -->
25127
+
25128
+ -
25129
+
25130
+ ## Decision Priorities
25131
+
25132
+ <!--
25133
+ When tradeoffs appear, these resolve them. Format: "A > B".
25134
+
25135
+ Example:
25136
+ - correctness > speed
25137
+ - clarity > cleverness
25138
+ -->
25139
+
25140
+ -
25141
+ `
25142
+ };
24259
25143
  }
24260
25144
  });
24261
25145
 
@@ -24308,7 +25192,7 @@ Governance:
24308
25192
  neuroverse mcp --world ./world/ --plan plan.json
24309
25193
  neuroverse test --world ./world/ --fuzz --count 50
24310
25194
  `.trim();
24311
- async function main35() {
25195
+ async function main36() {
24312
25196
  const args = process.argv.slice(2);
24313
25197
  const command = args[0];
24314
25198
  const subArgs = args.slice(1);
@@ -24359,6 +25243,10 @@ async function main35() {
24359
25243
  const { main: guardMain } = await Promise.resolve().then(() => (init_guard(), guard_exports));
24360
25244
  return guardMain(subArgs);
24361
25245
  }
25246
+ case "audit": {
25247
+ const { main: auditMain } = await Promise.resolve().then(() => (init_audit(), audit_exports));
25248
+ return auditMain(subArgs);
25249
+ }
24362
25250
  case "test": {
24363
25251
  const { main: testMain } = await Promise.resolve().then(() => (init_test(), test_exports));
24364
25252
  return testMain(subArgs);
@@ -24478,7 +25366,7 @@ async function main35() {
24478
25366
  }
24479
25367
  }
24480
25368
  }
24481
- main35().catch((e) => {
25369
+ main36().catch((e) => {
24482
25370
  process.stderr.write(`Fatal: ${e}
24483
25371
  `);
24484
25372
  process.exit(3);