@neuroverseos/governance 0.6.1 → 0.8.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.
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __esm = (fn, res) => function __init() {
7
9
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -18,6 +20,14 @@ var __copyProps = (to, from, except, desc) => {
18
20
  }
19
21
  return to;
20
22
  };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
21
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
32
 
23
33
  // src/radiant/lenses/auki-builder.ts
@@ -471,18 +481,6 @@ var init_lenses = __esm({
471
481
  }
472
482
  });
473
483
 
474
- // src/cli/radiant.ts
475
- var radiant_exports = {};
476
- __export(radiant_exports, {
477
- main: () => main
478
- });
479
- module.exports = __toCommonJS(radiant_exports);
480
- var import_fs2 = require("fs");
481
- var import_path2 = require("path");
482
-
483
- // src/radiant/commands/think.ts
484
- init_lenses();
485
-
486
484
  // src/radiant/core/prompt.ts
487
485
  function composeSystemPrompt(worldmodelContent, lens) {
488
486
  const sections = [];
@@ -569,6 +567,11 @@ explicitly and propose an alternative that honors the invariant.`
569
567
  );
570
568
  return sections.join("\n\n---\n\n");
571
569
  }
570
+ var init_prompt = __esm({
571
+ "src/radiant/core/prompt.ts"() {
572
+ "use strict";
573
+ }
574
+ });
572
575
 
573
576
  // src/radiant/core/voice-check.ts
574
577
  function checkForbiddenPhrases(lens, text) {
@@ -587,6 +590,11 @@ function checkForbiddenPhrases(lens, text) {
587
590
  violations.sort((a, b) => a.offset - b.offset);
588
591
  return violations;
589
592
  }
593
+ var init_voice_check = __esm({
594
+ "src/radiant/core/voice-check.ts"() {
595
+ "use strict";
596
+ }
597
+ });
590
598
 
591
599
  // src/radiant/commands/think.ts
592
600
  async function think(input) {
@@ -618,24 +626,47 @@ function resolveLens(id) {
618
626
  }
619
627
  return lens;
620
628
  }
621
-
622
- // src/radiant/commands/emergent.ts
623
- init_lenses();
629
+ var init_think = __esm({
630
+ "src/radiant/commands/think.ts"() {
631
+ "use strict";
632
+ init_lenses();
633
+ init_prompt();
634
+ init_voice_check();
635
+ }
636
+ });
624
637
 
625
638
  // src/radiant/core/scopes.ts
626
- function parseRepoScope(scope) {
639
+ function parseScope(scope) {
627
640
  const cleaned = scope.replace(/^https?:\/\//, "").replace(/^github\.com\//, "").replace(/\.git$/, "").replace(/\/$/, "");
628
- const parts = cleaned.split("/");
629
- if (parts.length < 2 || !parts[0] || !parts[1]) {
641
+ const parts = cleaned.split("/").filter(Boolean);
642
+ if (parts.length === 0 || !parts[0]) {
630
643
  throw new Error(
631
- `Cannot parse repo scope: "${scope}". Expected "owner/repo" or a GitHub URL.`
644
+ `Cannot parse scope: "${scope}". Expected "owner/repo" or "owner".`
632
645
  );
633
646
  }
634
- return { owner: parts[0], repo: parts[1] };
647
+ if (parts.length === 1) {
648
+ return { type: "org", owner: parts[0] };
649
+ }
650
+ return { type: "repo", owner: parts[0], repo: parts[1] };
651
+ }
652
+ function parseRepoScope(scope) {
653
+ const parsed = parseScope(scope);
654
+ if (parsed.type === "org") {
655
+ throw new Error(
656
+ `Expected "owner/repo" but got org-level scope "${parsed.owner}". Use parseScope() for org-level.`
657
+ );
658
+ }
659
+ return parsed;
635
660
  }
636
661
  function formatScope(scope) {
662
+ if (scope.type === "org") return `${scope.owner} (org)`;
637
663
  return `${scope.owner}/${scope.repo}`;
638
664
  }
665
+ var init_scopes = __esm({
666
+ "src/radiant/core/scopes.ts"() {
667
+ "use strict";
668
+ }
669
+ });
639
670
 
640
671
  // src/radiant/adapters/github.ts
641
672
  async function fetchGitHubActivity(scope, token, options = {}) {
@@ -745,20 +776,6 @@ function mapComment(comment, scope) {
745
776
  };
746
777
  return event;
747
778
  }
748
- var KNOWN_AI_LOGINS = /* @__PURE__ */ new Set([
749
- "github-actions[bot]",
750
- "dependabot[bot]",
751
- "renovate[bot]",
752
- "copilot"
753
- ]);
754
- var KNOWN_AI_CO_AUTHOR_NAMES = /* @__PURE__ */ new Set([
755
- "claude",
756
- "copilot",
757
- "cursor",
758
- "codeium",
759
- "tabnine",
760
- "codex"
761
- ]);
762
779
  function mapUser(ghUser, fallbackName) {
763
780
  if (!ghUser) {
764
781
  return {
@@ -817,10 +834,63 @@ async function fetchJSON(url, headers) {
817
834
  }
818
835
  return await res.json();
819
836
  }
837
+ async function fetchGitHubOrgActivity(scope, token, options = {}) {
838
+ const perPage = options.perPage ?? 100;
839
+ const headers = {
840
+ Authorization: `token ${token}`,
841
+ Accept: "application/vnd.github.v3+json",
842
+ "User-Agent": "neuroverseos-radiant"
843
+ };
844
+ const repos = await fetchJSON(
845
+ `https://api.github.com/orgs/${scope.owner}/repos?sort=pushed&direction=desc&per_page=${perPage}`,
846
+ headers
847
+ );
848
+ const windowDays = options.windowDays ?? 14;
849
+ const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
850
+ const activeRepos = repos.filter(
851
+ (r) => new Date(r.pushed_at) >= since
852
+ );
853
+ const cappedRepos = activeRepos.slice(0, 10);
854
+ const allEvents = [];
855
+ const repoNames = [];
856
+ for (const repo of cappedRepos) {
857
+ const [owner, repoName] = repo.full_name.split("/");
858
+ try {
859
+ const repoScope = { type: "repo", owner, repo: repoName };
860
+ const events = await fetchGitHubActivity(repoScope, token, options);
861
+ allEvents.push(...events);
862
+ if (events.length > 0) repoNames.push(repo.full_name);
863
+ } catch {
864
+ }
865
+ }
866
+ allEvents.sort(
867
+ (a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp)
868
+ );
869
+ return { events: allEvents, repos: repoNames };
870
+ }
871
+ var KNOWN_AI_LOGINS, KNOWN_AI_CO_AUTHOR_NAMES;
872
+ var init_github = __esm({
873
+ "src/radiant/adapters/github.ts"() {
874
+ "use strict";
875
+ init_scopes();
876
+ KNOWN_AI_LOGINS = /* @__PURE__ */ new Set([
877
+ "github-actions[bot]",
878
+ "dependabot[bot]",
879
+ "renovate[bot]",
880
+ "copilot"
881
+ ]);
882
+ KNOWN_AI_CO_AUTHOR_NAMES = /* @__PURE__ */ new Set([
883
+ "claude",
884
+ "copilot",
885
+ "cursor",
886
+ "codeium",
887
+ "tabnine",
888
+ "codex"
889
+ ]);
890
+ }
891
+ });
820
892
 
821
893
  // src/radiant/adapters/exocortex.ts
822
- var import_fs = require("fs");
823
- var import_path = require("path");
824
894
  function readExocortex(dirPath) {
825
895
  const dir = (0, import_path.resolve)(dirPath);
826
896
  let filesLoaded = 0;
@@ -901,6 +971,1526 @@ function summarizeExocortex(ctx) {
901
971
  if (ctx.methods) loaded.push("methods");
902
972
  return `${loaded.join(", ")} (${ctx.filesLoaded} files)`;
903
973
  }
974
+ var import_fs, import_path;
975
+ var init_exocortex = __esm({
976
+ "src/radiant/adapters/exocortex.ts"() {
977
+ "use strict";
978
+ import_fs = require("fs");
979
+ import_path = require("path");
980
+ }
981
+ });
982
+
983
+ // src/radiant/memory/palace.ts
984
+ function writeRead(exocortexDir, frontmatter, text) {
985
+ const dir = (0, import_path2.resolve)(exocortexDir, "radiant", "reads");
986
+ (0, import_fs2.mkdirSync)(dir, { recursive: true });
987
+ const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
988
+ const filename = `${date}.md`;
989
+ const filepath = (0, import_path2.join)(dir, filename);
990
+ const content = `${frontmatter}
991
+
992
+ ${text}
993
+ `;
994
+ (0, import_fs2.writeFileSync)(filepath, content, "utf-8");
995
+ return filepath;
996
+ }
997
+ function updateKnowledge(exocortexDir, persistence, options) {
998
+ const dir = (0, import_path2.resolve)(exocortexDir, "radiant");
999
+ (0, import_fs2.mkdirSync)(dir, { recursive: true });
1000
+ const filepath = (0, import_path2.join)(dir, "knowledge.md");
1001
+ const totalReads = options?.totalReads ?? 0;
1002
+ const existingUntriggered = loadUntriggeredCounts(filepath);
1003
+ const lines = [
1004
+ "# Radiant \u2014 Accumulated Behavioral Knowledge",
1005
+ "",
1006
+ `Last updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`,
1007
+ `Total reads: ${totalReads}`,
1008
+ "",
1009
+ "---",
1010
+ "",
1011
+ "## Evolution proposals",
1012
+ ""
1013
+ ];
1014
+ const addCandidates = persistence.filter((p) => p.occurrences >= 3);
1015
+ if (addCandidates.length > 0) {
1016
+ lines.push("### Consider adding");
1017
+ lines.push("");
1018
+ lines.push("These candidate patterns keep recurring. They are not yet in the worldmodel.");
1019
+ lines.push("If they represent real behavioral patterns worth tracking, add them.");
1020
+ lines.push("If they were temporary, dismiss them.");
1021
+ lines.push("");
1022
+ for (const p of addCandidates) {
1023
+ lines.push(
1024
+ `- **${p.name}** \u2014 observed ${p.occurrences} times (${p.dates.join(", ")}). Add to auki-strategy.worldmodel.md \u2192 Evolution Layer \u2192 Drift Behaviors (if concerning) or Aligned Behaviors (if healthy).`
1025
+ );
1026
+ }
1027
+ lines.push("");
1028
+ }
1029
+ if (options?.declaredItems && options.declaredItems.length > 0) {
1030
+ const triggered = new Set(options.triggeredItems ?? []);
1031
+ const removeCandidates = [];
1032
+ for (const item of options.declaredItems) {
1033
+ if (!triggered.has(item.name)) {
1034
+ const prior = existingUntriggered.get(item.name) ?? 0;
1035
+ const count = prior + 1;
1036
+ existingUntriggered.set(item.name, count);
1037
+ if (count >= 4) {
1038
+ removeCandidates.push({ item, weeksSilent: count });
1039
+ }
1040
+ } else {
1041
+ existingUntriggered.set(item.name, 0);
1042
+ }
1043
+ }
1044
+ if (removeCandidates.length > 0) {
1045
+ lines.push("### Consider removing");
1046
+ lines.push("");
1047
+ lines.push("These items are declared in the worldmodel but haven't triggered in multiple reads.");
1048
+ lines.push("Either the team has internalized them (the rule is redundant) or they haven't been tested.");
1049
+ lines.push("A lean worldmodel with 5 sharp invariants is stronger than a bloated one with 20.");
1050
+ lines.push("");
1051
+ for (const { item, weeksSilent } of removeCandidates) {
1052
+ lines.push(
1053
+ `- **${item.name}** (${item.type}) \u2014 hasn't triggered in ${weeksSilent} reads. Internalized or untested? Review whether it still earns its place.`
1054
+ );
1055
+ }
1056
+ lines.push("");
1057
+ }
1058
+ }
1059
+ if (options?.triggeredItems && options.triggeredItems.length > 0) {
1060
+ lines.push("### Keep (recently active)");
1061
+ lines.push("");
1062
+ lines.push("These worldmodel items triggered governance in the most recent read. They're earning their place.");
1063
+ lines.push("");
1064
+ for (const name of options.triggeredItems) {
1065
+ lines.push(`- **${name}** \u2014 triggered this read. Holding.`);
1066
+ }
1067
+ lines.push("");
1068
+ }
1069
+ lines.push("---");
1070
+ lines.push("");
1071
+ lines.push("## Pattern persistence (all observed)");
1072
+ lines.push("");
1073
+ for (const p of persistence) {
1074
+ const status = p.occurrences >= 4 ? "**persistent**" : p.occurrences >= 2 ? "recurring" : "observed once";
1075
+ lines.push(`### ${p.name}`);
1076
+ lines.push(`- Status: ${status}`);
1077
+ lines.push(`- Observed ${p.occurrences} time${p.occurrences > 1 ? "s" : ""}: ${p.dates.join(", ")}`);
1078
+ lines.push("");
1079
+ }
1080
+ lines.push("---");
1081
+ lines.push("");
1082
+ lines.push("<!-- untriggered_counts (machine-readable, do not edit)");
1083
+ for (const [name, count] of existingUntriggered.entries()) {
1084
+ lines.push(`${name}=${count}`);
1085
+ }
1086
+ lines.push("-->");
1087
+ (0, import_fs2.writeFileSync)(filepath, lines.join("\n"), "utf-8");
1088
+ return filepath;
1089
+ }
1090
+ function loadUntriggeredCounts(filepath) {
1091
+ const counts = /* @__PURE__ */ new Map();
1092
+ if (!(0, import_fs2.existsSync)(filepath)) return counts;
1093
+ try {
1094
+ const content = (0, import_fs2.readFileSync)(filepath, "utf-8");
1095
+ const match = content.match(
1096
+ /<!-- untriggered_counts[\s\S]*?-->/
1097
+ );
1098
+ if (match) {
1099
+ const lines = match[0].split("\n");
1100
+ for (const line of lines) {
1101
+ const eq = line.match(/^([^=]+)=(\d+)$/);
1102
+ if (eq) {
1103
+ counts.set(eq[1], parseInt(eq[2], 10));
1104
+ }
1105
+ }
1106
+ }
1107
+ } catch {
1108
+ }
1109
+ return counts;
1110
+ }
1111
+ function loadPriorReads(exocortexDir) {
1112
+ const dir = (0, import_path2.resolve)(exocortexDir, "radiant", "reads");
1113
+ if (!(0, import_fs2.existsSync)(dir)) return [];
1114
+ const files = (0, import_fs2.readdirSync)(dir).filter((f) => f.endsWith(".md")).sort();
1115
+ const reads = [];
1116
+ for (const filename of files) {
1117
+ const filepath = (0, import_path2.join)(dir, filename);
1118
+ const content = (0, import_fs2.readFileSync)(filepath, "utf-8");
1119
+ const date = filename.replace(".md", "");
1120
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
1121
+ const frontmatter = fmMatch ? fmMatch[1] : "";
1122
+ const patternNames = [];
1123
+ const nameMatches = frontmatter.matchAll(/- name: ["']?([^"'\n]+)["']?/g);
1124
+ for (const m of nameMatches) {
1125
+ patternNames.push(m[1].trim());
1126
+ }
1127
+ reads.push({ date, filename, patternNames, frontmatter });
1128
+ }
1129
+ return reads;
1130
+ }
1131
+ function computePersistence(priorReads, currentPatternNames) {
1132
+ const allPatterns = /* @__PURE__ */ new Map();
1133
+ for (const read of priorReads) {
1134
+ for (const name of read.patternNames) {
1135
+ const dates = allPatterns.get(name) ?? [];
1136
+ if (!dates.includes(read.date)) dates.push(read.date);
1137
+ allPatterns.set(name, dates);
1138
+ }
1139
+ }
1140
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1141
+ for (const name of currentPatternNames) {
1142
+ const dates = allPatterns.get(name) ?? [];
1143
+ if (!dates.includes(today)) dates.push(today);
1144
+ allPatterns.set(name, dates);
1145
+ }
1146
+ return Array.from(allPatterns.entries()).map(([name, dates]) => ({
1147
+ name,
1148
+ occurrences: dates.length,
1149
+ dates: dates.sort()
1150
+ })).sort((a, b) => b.occurrences - a.occurrences);
1151
+ }
1152
+ function formatPriorReadsForPrompt(priorReads) {
1153
+ if (priorReads.length === 0) return "";
1154
+ const lines = [
1155
+ "## Prior Radiant reads (history)",
1156
+ "",
1157
+ `Radiant has run ${priorReads.length} time${priorReads.length > 1 ? "s" : ""} before on this scope.`,
1158
+ "If you see patterns that appeared in prior reads, note their persistence.",
1159
+ "Patterns that recur across 3+ reads are strong candidates for declaration in the strategy file.",
1160
+ ""
1161
+ ];
1162
+ for (const read of priorReads.slice(-4)) {
1163
+ lines.push(`### Read from ${read.date}`);
1164
+ if (read.patternNames.length > 0) {
1165
+ lines.push(`Patterns observed: ${read.patternNames.join(", ")}`);
1166
+ } else {
1167
+ lines.push("No patterns extracted from frontmatter.");
1168
+ }
1169
+ lines.push("");
1170
+ }
1171
+ return lines.join("\n");
1172
+ }
1173
+ var import_fs2, import_path2;
1174
+ var init_palace = __esm({
1175
+ "src/radiant/memory/palace.ts"() {
1176
+ "use strict";
1177
+ import_fs2 = require("fs");
1178
+ import_path2 = require("path");
1179
+ }
1180
+ });
1181
+
1182
+ // src/engine/text-utils.ts
1183
+ function normalizeEventText(event) {
1184
+ return [
1185
+ event.intent,
1186
+ event.tool ?? "",
1187
+ event.scope ?? ""
1188
+ ].join(" ").toLowerCase();
1189
+ }
1190
+ function extractKeywords(text, minLength = 3) {
1191
+ return text.toLowerCase().split(/\s+/).filter((w) => w.length > minLength);
1192
+ }
1193
+ function matchesAllKeywords(eventText, ruleText) {
1194
+ const keywords = extractKeywords(ruleText);
1195
+ if (keywords.length === 0) return false;
1196
+ return keywords.every((kw) => eventText.includes(kw));
1197
+ }
1198
+ function matchesKeywordThreshold(eventText, ruleText, threshold = 0.5) {
1199
+ const keywords = extractKeywords(ruleText);
1200
+ if (keywords.length === 0) return false;
1201
+ const matched = keywords.filter((kw) => eventText.includes(kw));
1202
+ return matched.length >= Math.ceil(keywords.length * threshold);
1203
+ }
1204
+ function tokenSimilarity(a, b) {
1205
+ const tokensA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
1206
+ const tokensB = new Set(b.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
1207
+ if (tokensA.size === 0 || tokensB.size === 0) return 0;
1208
+ let intersection = 0;
1209
+ for (const t of tokensA) {
1210
+ if (tokensB.has(t)) intersection++;
1211
+ }
1212
+ const union = (/* @__PURE__ */ new Set([...tokensA, ...tokensB])).size;
1213
+ return union > 0 ? intersection / union : 0;
1214
+ }
1215
+ var init_text_utils = __esm({
1216
+ "src/engine/text-utils.ts"() {
1217
+ "use strict";
1218
+ }
1219
+ });
1220
+
1221
+ // src/engine/plan-engine.ts
1222
+ function keywordMatch(eventText, step) {
1223
+ const stepText = [
1224
+ step.label,
1225
+ step.description ?? "",
1226
+ ...step.tags ?? []
1227
+ ].join(" ");
1228
+ return matchesKeywordThreshold(eventText, stepText, 0.5);
1229
+ }
1230
+ function tokenSimilarity2(a, b) {
1231
+ return tokenSimilarity(a, b);
1232
+ }
1233
+ function findMatchingStep(eventText, event, steps) {
1234
+ const pendingOrActive = steps.filter((s) => s.status === "pending" || s.status === "active");
1235
+ if (pendingOrActive.length === 0) {
1236
+ return { matched: null, closest: null, closestScore: 0 };
1237
+ }
1238
+ for (const step of pendingOrActive) {
1239
+ if (keywordMatch(eventText, step)) {
1240
+ if (step.tools && event.tool && !step.tools.includes(event.tool)) {
1241
+ continue;
1242
+ }
1243
+ return { matched: step, closest: step, closestScore: 1 };
1244
+ }
1245
+ }
1246
+ const intentText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ");
1247
+ let bestStep = null;
1248
+ let bestScore = 0;
1249
+ for (const step of pendingOrActive) {
1250
+ const stepText = [step.label, step.description ?? "", ...step.tags ?? []].join(" ");
1251
+ const score = tokenSimilarity2(intentText, stepText);
1252
+ if (score > bestScore) {
1253
+ bestScore = score;
1254
+ bestStep = step;
1255
+ }
1256
+ }
1257
+ const SIMILARITY_THRESHOLD = 0.35;
1258
+ if (bestScore >= SIMILARITY_THRESHOLD && bestStep) {
1259
+ if (bestStep.tools && event.tool && !bestStep.tools.includes(event.tool)) {
1260
+ return { matched: null, closest: bestStep, closestScore: bestScore };
1261
+ }
1262
+ return { matched: bestStep, closest: bestStep, closestScore: bestScore };
1263
+ }
1264
+ return { matched: null, closest: bestStep, closestScore: bestScore };
1265
+ }
1266
+ function isSequenceValid(step, plan) {
1267
+ if (!plan.sequential) return true;
1268
+ if (!step.requires || step.requires.length === 0) return true;
1269
+ return step.requires.every((reqId) => {
1270
+ const reqStep = plan.steps.find((s) => s.id === reqId);
1271
+ return reqStep?.status === "completed";
1272
+ });
1273
+ }
1274
+ function checkConstraints(event, eventText, constraints) {
1275
+ const checks = [];
1276
+ for (const constraint of constraints) {
1277
+ if (constraint.type === "approval") {
1278
+ if (constraint.trigger && eventText.includes(constraint.trigger.substring(0, 10).toLowerCase())) {
1279
+ checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
1280
+ return { violated: constraint, checks };
1281
+ }
1282
+ const keywords = constraint.description.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
1283
+ const relevant = keywords.some((kw) => eventText.includes(kw));
1284
+ if (relevant) {
1285
+ checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
1286
+ return { violated: constraint, checks };
1287
+ }
1288
+ checks.push({ constraintId: constraint.id, passed: true });
1289
+ continue;
1290
+ }
1291
+ if (constraint.type === "scope" && constraint.trigger) {
1292
+ const keywords = extractKeywords(constraint.trigger);
1293
+ const violated = keywords.length > 0 && keywords.every((kw) => eventText.includes(kw));
1294
+ checks.push({
1295
+ constraintId: constraint.id,
1296
+ passed: !violated,
1297
+ reason: violated ? constraint.description : void 0
1298
+ });
1299
+ if (violated) {
1300
+ return { violated: constraint, checks };
1301
+ }
1302
+ continue;
1303
+ }
1304
+ checks.push({ constraintId: constraint.id, passed: true });
1305
+ }
1306
+ return { violated: null, checks };
1307
+ }
1308
+ function getPlanProgress(plan) {
1309
+ const completed = plan.steps.filter((s) => s.status === "completed").length;
1310
+ const total = plan.steps.length;
1311
+ return {
1312
+ completed,
1313
+ total,
1314
+ percentage: total > 0 ? Math.round(completed / total * 100) : 0
1315
+ };
1316
+ }
1317
+ function evaluatePlan(event, plan) {
1318
+ const progress = getPlanProgress(plan);
1319
+ if (plan.expires_at) {
1320
+ const expiresAt = new Date(plan.expires_at).getTime();
1321
+ if (Date.now() > expiresAt) {
1322
+ return {
1323
+ allowed: true,
1324
+ status: "PLAN_COMPLETE",
1325
+ reason: "Plan has expired.",
1326
+ progress
1327
+ };
1328
+ }
1329
+ }
1330
+ if (progress.completed === progress.total) {
1331
+ return {
1332
+ allowed: true,
1333
+ status: "PLAN_COMPLETE",
1334
+ reason: "All plan steps are completed.",
1335
+ progress
1336
+ };
1337
+ }
1338
+ const eventText = normalizeEventText(event);
1339
+ const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
1340
+ if (!matched) {
1341
+ return {
1342
+ allowed: false,
1343
+ status: "OFF_PLAN",
1344
+ reason: "Action does not match any plan step.",
1345
+ closestStep: closest?.label,
1346
+ similarityScore: closestScore,
1347
+ progress
1348
+ };
1349
+ }
1350
+ if (!isSequenceValid(matched, plan)) {
1351
+ const pendingDeps = (matched.requires ?? []).filter((reqId) => plan.steps.find((s) => s.id === reqId)?.status !== "completed").join(", ");
1352
+ return {
1353
+ allowed: false,
1354
+ status: "OFF_PLAN",
1355
+ reason: `Step "${matched.label}" requires completion of: ${pendingDeps}`,
1356
+ matchedStep: matched.id,
1357
+ progress
1358
+ };
1359
+ }
1360
+ const { violated } = checkConstraints(event, eventText, plan.constraints);
1361
+ if (violated) {
1362
+ return {
1363
+ allowed: false,
1364
+ status: "CONSTRAINT_VIOLATED",
1365
+ reason: violated.description,
1366
+ matchedStep: matched.id,
1367
+ progress
1368
+ };
1369
+ }
1370
+ return {
1371
+ allowed: true,
1372
+ status: "ON_PLAN",
1373
+ reason: `Matches step: ${matched.label}`,
1374
+ matchedStep: matched.id,
1375
+ progress
1376
+ };
1377
+ }
1378
+ function buildPlanCheck(event, plan, verdict) {
1379
+ const eventText = normalizeEventText(event);
1380
+ const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
1381
+ const { checks: constraintChecks } = checkConstraints(event, eventText, plan.constraints);
1382
+ const progress = getPlanProgress(plan);
1383
+ return {
1384
+ planId: plan.plan_id,
1385
+ matched: !!matched,
1386
+ matchedStepId: matched?.id,
1387
+ matchedStepLabel: matched?.label,
1388
+ closestStepId: !matched ? closest?.id : void 0,
1389
+ closestStepLabel: !matched ? closest?.label : void 0,
1390
+ similarityScore: !matched ? closestScore : void 0,
1391
+ sequenceValid: matched ? isSequenceValid(matched, plan) : void 0,
1392
+ constraintsChecked: constraintChecks,
1393
+ progress: { completed: progress.completed, total: progress.total }
1394
+ };
1395
+ }
1396
+ var init_plan_engine = __esm({
1397
+ "src/engine/plan-engine.ts"() {
1398
+ "use strict";
1399
+ init_text_utils();
1400
+ }
1401
+ });
1402
+
1403
+ // src/engine/guard-engine.ts
1404
+ function levelRequiresConfirmation(level, actionType) {
1405
+ if (level === "strict") return true;
1406
+ if (level === "standard") {
1407
+ return actionType === "delete" || actionType === "credential-access";
1408
+ }
1409
+ return false;
1410
+ }
1411
+ function isExternalScope(scope) {
1412
+ const internalPatterns = [
1413
+ /^\.?\/?src\//i,
1414
+ /^\.?\/?lib\//i,
1415
+ /^\.?\/?app\//i,
1416
+ /^\.?\/?components\//i,
1417
+ /^\.?\/?pages\//i,
1418
+ /^\.?\/?public\//i,
1419
+ /^\.?\/?assets\//i,
1420
+ /^\.\//
1421
+ ];
1422
+ return !internalPatterns.some((p) => p.test(scope));
1423
+ }
1424
+ function evaluateGuard(event, world, options = {}) {
1425
+ const startTime = performance.now();
1426
+ const level = options.level ?? "standard";
1427
+ const includeTrace = options.trace ?? false;
1428
+ if (!event.intent || typeof event.intent !== "string") {
1429
+ return {
1430
+ status: "BLOCK",
1431
+ reason: "GuardEvent.intent is required and must be a string",
1432
+ ruleId: "safety-input-validation",
1433
+ evidence: {
1434
+ worldId: world.world?.world_id ?? "",
1435
+ worldName: world.world?.name ?? "",
1436
+ worldVersion: world.world?.version ?? "",
1437
+ evaluatedAt: Date.now(),
1438
+ invariantsSatisfied: 0,
1439
+ invariantsTotal: 0,
1440
+ guardsMatched: [],
1441
+ rulesMatched: [],
1442
+ enforcementLevel: level
1443
+ }
1444
+ };
1445
+ }
1446
+ const inputLength = event.intent.length + (event.tool?.length ?? 0) + (event.scope?.length ?? 0) + (event.payload ? JSON.stringify(event.payload).length : 0);
1447
+ if (inputLength > MAX_INPUT_LENGTH) {
1448
+ return {
1449
+ status: "BLOCK",
1450
+ reason: `Input exceeds maximum allowed length (${MAX_INPUT_LENGTH} characters)`,
1451
+ ruleId: "safety-input-length",
1452
+ evidence: {
1453
+ worldId: world.world?.world_id ?? "",
1454
+ worldName: world.world?.name ?? "",
1455
+ worldVersion: world.world?.version ?? "",
1456
+ evaluatedAt: Date.now(),
1457
+ invariantsSatisfied: 0,
1458
+ invariantsTotal: 0,
1459
+ guardsMatched: [],
1460
+ rulesMatched: [],
1461
+ enforcementLevel: level
1462
+ }
1463
+ };
1464
+ }
1465
+ const eventText = normalizeEventText(event);
1466
+ const invariantChecks = [];
1467
+ const safetyChecks = [];
1468
+ let planCheckResult;
1469
+ const roleChecks = [];
1470
+ const guardChecks = [];
1471
+ const kernelRuleChecks = [];
1472
+ const levelChecks = [];
1473
+ let decidingLayer = "default-allow";
1474
+ let decidingId;
1475
+ const guardsMatched = [];
1476
+ const rulesMatched = [];
1477
+ if (options.emergencyOverride) {
1478
+ checkInvariantCoverage(world, invariantChecks);
1479
+ return buildVerdict(
1480
+ "ALLOW",
1481
+ void 0,
1482
+ "emergency-override",
1483
+ "Emergency override active \u2014 all governance rules suspended. Platform constraints still apply.",
1484
+ world,
1485
+ level,
1486
+ invariantChecks,
1487
+ guardsMatched,
1488
+ rulesMatched,
1489
+ includeTrace ? buildTrace(
1490
+ invariantChecks,
1491
+ safetyChecks,
1492
+ planCheckResult,
1493
+ roleChecks,
1494
+ guardChecks,
1495
+ kernelRuleChecks,
1496
+ levelChecks,
1497
+ "session-allowlist",
1498
+ "emergency-override",
1499
+ startTime
1500
+ ) : void 0,
1501
+ event.intent
1502
+ );
1503
+ }
1504
+ checkInvariantCoverage(world, invariantChecks);
1505
+ if (event.roleId && options.agentStates) {
1506
+ const agentState = options.agentStates.get(event.roleId);
1507
+ if (agentState && agentState.cooldownRemaining > 0) {
1508
+ decidingLayer = "safety";
1509
+ decidingId = `penalize-cooldown-${event.roleId}`;
1510
+ const verdict = buildVerdict(
1511
+ "PENALIZE",
1512
+ `Agent "${event.roleId}" is frozen for ${agentState.cooldownRemaining} more round(s) due to prior penalty.`,
1513
+ `penalize-cooldown-${event.roleId}`,
1514
+ void 0,
1515
+ world,
1516
+ level,
1517
+ invariantChecks,
1518
+ guardsMatched,
1519
+ rulesMatched,
1520
+ includeTrace ? buildTrace(
1521
+ invariantChecks,
1522
+ safetyChecks,
1523
+ planCheckResult,
1524
+ roleChecks,
1525
+ guardChecks,
1526
+ kernelRuleChecks,
1527
+ levelChecks,
1528
+ decidingLayer,
1529
+ decidingId,
1530
+ startTime
1531
+ ) : void 0
1532
+ );
1533
+ verdict.intentRecord = {
1534
+ originalIntent: event.intent,
1535
+ finalAction: "blocked (agent frozen)",
1536
+ enforcement: "PENALIZE",
1537
+ consequence: { type: "freeze", rounds: agentState.cooldownRemaining, description: "Agent still in cooldown from prior penalty" }
1538
+ };
1539
+ return verdict;
1540
+ }
1541
+ }
1542
+ if (options.sessionAllowlist) {
1543
+ const key = eventToAllowlistKey(event);
1544
+ if (options.sessionAllowlist.has(key)) {
1545
+ decidingLayer = "session-allowlist";
1546
+ decidingId = `allowlist:${key}`;
1547
+ return buildVerdict(
1548
+ "ALLOW",
1549
+ void 0,
1550
+ `allowlist:${key}`,
1551
+ void 0,
1552
+ world,
1553
+ level,
1554
+ invariantChecks,
1555
+ guardsMatched,
1556
+ rulesMatched,
1557
+ includeTrace ? buildTrace(
1558
+ invariantChecks,
1559
+ safetyChecks,
1560
+ planCheckResult,
1561
+ roleChecks,
1562
+ guardChecks,
1563
+ kernelRuleChecks,
1564
+ levelChecks,
1565
+ decidingLayer,
1566
+ decidingId,
1567
+ startTime
1568
+ ) : void 0,
1569
+ event.intent
1570
+ );
1571
+ }
1572
+ }
1573
+ const safetyVerdict = checkSafety(event, eventText, safetyChecks);
1574
+ if (safetyVerdict) {
1575
+ decidingLayer = "safety";
1576
+ decidingId = safetyVerdict.ruleId;
1577
+ return buildVerdict(
1578
+ safetyVerdict.status,
1579
+ safetyVerdict.reason,
1580
+ safetyVerdict.ruleId,
1581
+ void 0,
1582
+ world,
1583
+ level,
1584
+ invariantChecks,
1585
+ guardsMatched,
1586
+ rulesMatched,
1587
+ includeTrace ? buildTrace(
1588
+ invariantChecks,
1589
+ safetyChecks,
1590
+ planCheckResult,
1591
+ roleChecks,
1592
+ guardChecks,
1593
+ kernelRuleChecks,
1594
+ levelChecks,
1595
+ decidingLayer,
1596
+ decidingId,
1597
+ startTime
1598
+ ) : void 0,
1599
+ event.intent
1600
+ );
1601
+ }
1602
+ if (options.plan) {
1603
+ const planVerdict = evaluatePlan(event, options.plan);
1604
+ planCheckResult = buildPlanCheck(event, options.plan, planVerdict);
1605
+ if (!planVerdict.allowed && planVerdict.status !== "PLAN_COMPLETE") {
1606
+ decidingLayer = "plan-enforcement";
1607
+ decidingId = `plan-${options.plan.plan_id}`;
1608
+ const planStatus = planVerdict.status === "CONSTRAINT_VIOLATED" ? "PAUSE" : "BLOCK";
1609
+ let reason = planVerdict.reason ?? "Action blocked by plan.";
1610
+ if (planVerdict.status === "OFF_PLAN" && planVerdict.closestStep) {
1611
+ reason += ` Closest step: "${planVerdict.closestStep}" (similarity: ${(planVerdict.similarityScore ?? 0).toFixed(2)})`;
1612
+ }
1613
+ return buildVerdict(
1614
+ planStatus,
1615
+ reason,
1616
+ `plan-${options.plan.plan_id}`,
1617
+ void 0,
1618
+ world,
1619
+ level,
1620
+ invariantChecks,
1621
+ guardsMatched,
1622
+ rulesMatched,
1623
+ includeTrace ? buildTrace(
1624
+ invariantChecks,
1625
+ safetyChecks,
1626
+ planCheckResult,
1627
+ roleChecks,
1628
+ guardChecks,
1629
+ kernelRuleChecks,
1630
+ levelChecks,
1631
+ decidingLayer,
1632
+ decidingId,
1633
+ startTime
1634
+ ) : void 0,
1635
+ event.intent
1636
+ );
1637
+ }
1638
+ }
1639
+ const roleVerdict = checkRoleRules(event, eventText, world, roleChecks);
1640
+ if (roleVerdict) {
1641
+ decidingLayer = "role";
1642
+ decidingId = roleVerdict.ruleId;
1643
+ return buildVerdict(
1644
+ roleVerdict.status,
1645
+ roleVerdict.reason,
1646
+ roleVerdict.ruleId,
1647
+ void 0,
1648
+ world,
1649
+ level,
1650
+ invariantChecks,
1651
+ guardsMatched,
1652
+ rulesMatched,
1653
+ includeTrace ? buildTrace(
1654
+ invariantChecks,
1655
+ safetyChecks,
1656
+ planCheckResult,
1657
+ roleChecks,
1658
+ guardChecks,
1659
+ kernelRuleChecks,
1660
+ levelChecks,
1661
+ decidingLayer,
1662
+ decidingId,
1663
+ startTime
1664
+ ) : void 0,
1665
+ event.intent
1666
+ );
1667
+ }
1668
+ const guardVerdict = checkGuards(event, eventText, world, guardChecks, guardsMatched);
1669
+ if (guardVerdict) {
1670
+ if (guardVerdict.status !== "ALLOW") {
1671
+ decidingLayer = "guard";
1672
+ decidingId = guardVerdict.ruleId;
1673
+ const intentRecord = {
1674
+ originalIntent: event.intent,
1675
+ finalAction: guardVerdict.status === "MODIFY" ? guardVerdict.modifiedTo ?? "modified" : guardVerdict.status === "PENALIZE" ? "blocked + penalized" : guardVerdict.status === "REWARD" ? event.intent : guardVerdict.status === "NEUTRAL" ? event.intent : guardVerdict.status === "BLOCK" ? "blocked" : "paused",
1676
+ ruleApplied: guardVerdict.ruleId,
1677
+ enforcement: guardVerdict.status,
1678
+ modifiedTo: guardVerdict.modifiedTo,
1679
+ consequence: guardVerdict.consequence,
1680
+ reward: guardVerdict.reward
1681
+ };
1682
+ const verdict = buildVerdict(
1683
+ guardVerdict.status,
1684
+ guardVerdict.reason,
1685
+ guardVerdict.ruleId,
1686
+ void 0,
1687
+ world,
1688
+ level,
1689
+ invariantChecks,
1690
+ guardsMatched,
1691
+ rulesMatched,
1692
+ includeTrace ? buildTrace(
1693
+ invariantChecks,
1694
+ safetyChecks,
1695
+ planCheckResult,
1696
+ roleChecks,
1697
+ guardChecks,
1698
+ kernelRuleChecks,
1699
+ levelChecks,
1700
+ decidingLayer,
1701
+ decidingId,
1702
+ startTime
1703
+ ) : void 0,
1704
+ event.intent
1705
+ );
1706
+ verdict.intentRecord = intentRecord;
1707
+ if (guardVerdict.consequence) verdict.consequence = guardVerdict.consequence;
1708
+ if (guardVerdict.reward) verdict.reward = guardVerdict.reward;
1709
+ return verdict;
1710
+ }
1711
+ }
1712
+ const kernelVerdict = checkKernelRules(eventText, world, kernelRuleChecks, rulesMatched);
1713
+ if (kernelVerdict) {
1714
+ decidingLayer = "kernel-rule";
1715
+ decidingId = kernelVerdict.ruleId;
1716
+ return buildVerdict(
1717
+ kernelVerdict.status,
1718
+ kernelVerdict.reason,
1719
+ kernelVerdict.ruleId,
1720
+ void 0,
1721
+ world,
1722
+ level,
1723
+ invariantChecks,
1724
+ guardsMatched,
1725
+ rulesMatched,
1726
+ includeTrace ? buildTrace(
1727
+ invariantChecks,
1728
+ safetyChecks,
1729
+ planCheckResult,
1730
+ roleChecks,
1731
+ guardChecks,
1732
+ kernelRuleChecks,
1733
+ levelChecks,
1734
+ decidingLayer,
1735
+ decidingId,
1736
+ startTime
1737
+ ) : void 0,
1738
+ event.intent
1739
+ );
1740
+ }
1741
+ const levelVerdict = checkLevelConstraints(event, level, levelChecks);
1742
+ if (levelVerdict) {
1743
+ decidingLayer = "level-constraint";
1744
+ decidingId = levelVerdict.ruleId;
1745
+ return buildVerdict(
1746
+ levelVerdict.status,
1747
+ levelVerdict.reason,
1748
+ levelVerdict.ruleId,
1749
+ void 0,
1750
+ world,
1751
+ level,
1752
+ invariantChecks,
1753
+ guardsMatched,
1754
+ rulesMatched,
1755
+ includeTrace ? buildTrace(
1756
+ invariantChecks,
1757
+ safetyChecks,
1758
+ planCheckResult,
1759
+ roleChecks,
1760
+ guardChecks,
1761
+ kernelRuleChecks,
1762
+ levelChecks,
1763
+ decidingLayer,
1764
+ decidingId,
1765
+ startTime
1766
+ ) : void 0,
1767
+ event.intent
1768
+ );
1769
+ }
1770
+ const warning = guardVerdict?.warning;
1771
+ return buildVerdict(
1772
+ "ALLOW",
1773
+ void 0,
1774
+ void 0,
1775
+ warning,
1776
+ world,
1777
+ level,
1778
+ invariantChecks,
1779
+ guardsMatched,
1780
+ rulesMatched,
1781
+ includeTrace ? buildTrace(
1782
+ invariantChecks,
1783
+ safetyChecks,
1784
+ planCheckResult,
1785
+ roleChecks,
1786
+ guardChecks,
1787
+ kernelRuleChecks,
1788
+ levelChecks,
1789
+ decidingLayer,
1790
+ decidingId,
1791
+ startTime
1792
+ ) : void 0,
1793
+ event.intent
1794
+ );
1795
+ }
1796
+ function checkInvariantCoverage(world, checks) {
1797
+ const invariants = world.invariants ?? [];
1798
+ const guards = world.guards?.guards ?? [];
1799
+ for (const invariant of invariants) {
1800
+ const coveringGuard = guards.find(
1801
+ (g) => g.invariant_ref === invariant.id && g.immutable
1802
+ );
1803
+ checks.push({
1804
+ invariantId: invariant.id,
1805
+ label: invariant.label,
1806
+ hasGuardCoverage: !!coveringGuard,
1807
+ coveringGuardId: coveringGuard?.id
1808
+ });
1809
+ }
1810
+ }
1811
+ function checkSafety(event, eventText, checks) {
1812
+ const textToCheck = event.intent + (event.payload ? JSON.stringify(event.payload) : "");
1813
+ for (const { pattern, label } of PROMPT_INJECTION_PATTERNS) {
1814
+ const triggered = pattern.test(textToCheck);
1815
+ checks.push({
1816
+ checkType: "prompt-injection",
1817
+ triggered,
1818
+ matchedPattern: triggered ? label : void 0
1819
+ });
1820
+ if (triggered) {
1821
+ for (const remaining of PROMPT_INJECTION_PATTERNS.filter((p) => p.label !== label)) {
1822
+ checks.push({
1823
+ checkType: "prompt-injection",
1824
+ triggered: remaining.pattern.test(textToCheck),
1825
+ matchedPattern: remaining.pattern.test(textToCheck) ? remaining.label : void 0
1826
+ });
1827
+ }
1828
+ return {
1829
+ status: "PAUSE",
1830
+ reason: NEUTRAL_MESSAGES["prompt-injection"],
1831
+ ruleId: `safety-injection-${label}`
1832
+ };
1833
+ }
1834
+ }
1835
+ const scopeToCheck = event.scope ?? event.intent;
1836
+ for (const { pattern, label } of SCOPE_ESCAPE_PATTERNS) {
1837
+ const triggered = pattern.test(scopeToCheck);
1838
+ checks.push({
1839
+ checkType: "scope-escape",
1840
+ triggered,
1841
+ matchedPattern: triggered ? label : void 0
1842
+ });
1843
+ if (triggered) {
1844
+ for (const remaining of SCOPE_ESCAPE_PATTERNS.filter((p) => p.label !== label)) {
1845
+ checks.push({
1846
+ checkType: "scope-escape",
1847
+ triggered: remaining.pattern.test(scopeToCheck),
1848
+ matchedPattern: remaining.pattern.test(scopeToCheck) ? remaining.label : void 0
1849
+ });
1850
+ }
1851
+ return {
1852
+ status: "PAUSE",
1853
+ reason: NEUTRAL_MESSAGES["scope-escape"],
1854
+ ruleId: `safety-scope-${label}`
1855
+ };
1856
+ }
1857
+ }
1858
+ if (event.direction === "output") {
1859
+ for (const { pattern, label } of EXECUTION_CLAIM_PATTERNS) {
1860
+ const triggered = pattern.test(textToCheck);
1861
+ checks.push({
1862
+ checkType: "execution-claim",
1863
+ triggered,
1864
+ matchedPattern: triggered ? label : void 0
1865
+ });
1866
+ if (triggered) {
1867
+ for (const remaining of EXECUTION_CLAIM_PATTERNS.filter((p) => p.label !== label)) {
1868
+ checks.push({
1869
+ checkType: "execution-claim",
1870
+ triggered: remaining.pattern.test(textToCheck),
1871
+ matchedPattern: remaining.pattern.test(textToCheck) ? remaining.label : void 0
1872
+ });
1873
+ }
1874
+ return {
1875
+ status: "PAUSE",
1876
+ reason: NEUTRAL_MESSAGES["execution-claim"],
1877
+ ruleId: `safety-execution-claim-${label}`
1878
+ };
1879
+ }
1880
+ }
1881
+ }
1882
+ if (event.direction === "input") {
1883
+ const intentTrimmed = event.intent.trim();
1884
+ for (const { pattern, label } of EXECUTION_INTENT_PATTERNS) {
1885
+ const triggered = pattern.test(intentTrimmed);
1886
+ checks.push({
1887
+ checkType: "execution-intent",
1888
+ triggered,
1889
+ matchedPattern: triggered ? label : void 0
1890
+ });
1891
+ if (triggered) {
1892
+ for (const remaining of EXECUTION_INTENT_PATTERNS.filter((p) => p.label !== label)) {
1893
+ checks.push({
1894
+ checkType: "execution-intent",
1895
+ triggered: remaining.pattern.test(intentTrimmed),
1896
+ matchedPattern: remaining.pattern.test(intentTrimmed) ? remaining.label : void 0
1897
+ });
1898
+ }
1899
+ return {
1900
+ status: "PAUSE",
1901
+ reason: NEUTRAL_MESSAGES["execution-intent"],
1902
+ ruleId: `safety-execution-intent-${label}`
1903
+ };
1904
+ }
1905
+ }
1906
+ }
1907
+ return null;
1908
+ }
1909
+ function checkRoleRules(event, eventText, world, checks) {
1910
+ if (!event.roleId || !world.roles) return null;
1911
+ const role = world.roles.roles.find((r) => r.id === event.roleId);
1912
+ if (!role) return null;
1913
+ if (role.requiresApproval) {
1914
+ checks.push({
1915
+ roleId: role.id,
1916
+ roleName: role.name,
1917
+ rule: "All actions require approval",
1918
+ ruleType: "requiresApproval",
1919
+ matched: true
1920
+ });
1921
+ return {
1922
+ status: "PAUSE",
1923
+ reason: `Role "${role.name}" requires approval for all actions.`,
1924
+ ruleId: `role-${role.id}-requires-approval`
1925
+ };
1926
+ }
1927
+ for (const rule of role.cannotDo) {
1928
+ const matched = matchesKeywords(eventText, rule);
1929
+ checks.push({
1930
+ roleId: role.id,
1931
+ roleName: role.name,
1932
+ rule,
1933
+ ruleType: "cannotDo",
1934
+ matched
1935
+ });
1936
+ if (matched) {
1937
+ return {
1938
+ status: "BLOCK",
1939
+ reason: `Role "${role.name}" cannot: ${rule}`,
1940
+ ruleId: `role-${role.id}-cannotdo`
1941
+ };
1942
+ }
1943
+ }
1944
+ for (const rule of role.canDo) {
1945
+ checks.push({
1946
+ roleId: role.id,
1947
+ roleName: role.name,
1948
+ rule,
1949
+ ruleType: "canDo",
1950
+ matched: matchesKeywords(eventText, rule)
1951
+ });
1952
+ }
1953
+ return null;
1954
+ }
1955
+ function checkGuards(event, eventText, world, checks, guardsMatched) {
1956
+ if (!world.guards) return null;
1957
+ const guardsConfig = world.guards;
1958
+ let warnResult = null;
1959
+ const compiledPatterns = /* @__PURE__ */ new Map();
1960
+ for (const [key, def] of Object.entries(guardsConfig.intent_vocabulary)) {
1961
+ try {
1962
+ compiledPatterns.set(key, new RegExp(def.pattern, "i"));
1963
+ } catch {
1964
+ }
1965
+ }
1966
+ const eventTool = (event.tool ?? "").toLowerCase();
1967
+ for (const guard of guardsConfig.guards) {
1968
+ if (guard.appliesTo && guard.appliesTo.length > 0) {
1969
+ const normalizedAppliesTo = guard.appliesTo.map((t) => t.toLowerCase());
1970
+ if (!normalizedAppliesTo.includes(eventTool)) {
1971
+ continue;
1972
+ }
1973
+ }
1974
+ const enabled = guard.immutable || guard.default_enabled !== false;
1975
+ const matchedPatterns = [];
1976
+ for (const patternKey of guard.intent_patterns) {
1977
+ const regex = compiledPatterns.get(patternKey);
1978
+ if (regex?.test(eventText)) {
1979
+ matchedPatterns.push(patternKey);
1980
+ }
1981
+ }
1982
+ const matched = matchedPatterns.length > 0 && enabled;
1983
+ let roleGated = false;
1984
+ if (matched && guard.required_roles && guard.required_roles.length > 0 && event.roleId && guard.required_roles.includes(event.roleId)) {
1985
+ roleGated = true;
1986
+ }
1987
+ checks.push({
1988
+ guardId: guard.id,
1989
+ label: guard.label,
1990
+ category: guard.category,
1991
+ enabled,
1992
+ matched: matched && !roleGated,
1993
+ enforcement: guard.enforcement,
1994
+ matchedPatterns,
1995
+ roleGated
1996
+ });
1997
+ if (!matched || roleGated) continue;
1998
+ guardsMatched.push(guard.id);
1999
+ const actionMode = guard.player_modes?.action ?? guard.enforcement;
2000
+ const reason = guard.redirect ? `${guard.description} \u2014 ${guard.redirect}` : guard.description;
2001
+ if (actionMode === "block") {
2002
+ return { status: "BLOCK", reason, ruleId: `guard-${guard.id}` };
2003
+ }
2004
+ if (actionMode === "pause") {
2005
+ return { status: "PAUSE", reason, ruleId: `guard-${guard.id}` };
2006
+ }
2007
+ if (actionMode === "penalize") {
2008
+ const consequence = guard.consequence ? { ...guard.consequence } : { type: "freeze", rounds: 1, description: `Penalized for violating: ${guard.label}` };
2009
+ return { status: "PENALIZE", reason, ruleId: `guard-${guard.id}`, consequence };
2010
+ }
2011
+ if (actionMode === "reward") {
2012
+ const reward = guard.reward ? { ...guard.reward } : { type: "boost_influence", magnitude: 0.1, description: `Rewarded for: ${guard.label}` };
2013
+ return { status: "REWARD", reason, ruleId: `guard-${guard.id}`, reward };
2014
+ }
2015
+ if (actionMode === "modify") {
2016
+ const modifiedTo = guard.modify_to ?? guard.redirect ?? "hold";
2017
+ return { status: "MODIFY", reason: `${reason} \u2192 Modified to: ${modifiedTo}`, ruleId: `guard-${guard.id}`, modifiedTo };
2018
+ }
2019
+ if (actionMode === "neutral") {
2020
+ return { status: "NEUTRAL", reason, ruleId: `guard-${guard.id}` };
2021
+ }
2022
+ if (actionMode === "warn" && !warnResult) {
2023
+ warnResult = { status: "ALLOW", warning: reason, ruleId: `guard-${guard.id}` };
2024
+ }
2025
+ }
2026
+ return warnResult;
2027
+ }
2028
+ function checkKernelRules(eventText, world, checks, rulesMatched) {
2029
+ if (!world.kernel) return null;
2030
+ const forbidden = world.kernel.input_boundaries?.forbidden_patterns ?? [];
2031
+ const output = world.kernel.output_boundaries?.forbidden_patterns ?? [];
2032
+ for (const rule of forbidden) {
2033
+ let matched = false;
2034
+ let matchMethod = "none";
2035
+ if (rule.pattern) {
2036
+ try {
2037
+ matched = new RegExp(rule.pattern, "i").test(eventText);
2038
+ matchMethod = "pattern";
2039
+ } catch {
2040
+ }
2041
+ }
2042
+ if (!matched && rule.reason) {
2043
+ matched = matchesKeywords(eventText, rule.reason);
2044
+ if (matched) matchMethod = "keyword";
2045
+ }
2046
+ checks.push({
2047
+ ruleId: rule.id,
2048
+ text: rule.reason,
2049
+ category: "forbidden",
2050
+ matched,
2051
+ matchMethod
2052
+ });
2053
+ if (matched) {
2054
+ rulesMatched.push(rule.id);
2055
+ if (rule.action === "BLOCK") {
2056
+ return {
2057
+ status: "BLOCK",
2058
+ reason: rule.reason,
2059
+ ruleId: `kernel-${rule.id}`
2060
+ };
2061
+ }
2062
+ }
2063
+ }
2064
+ return null;
2065
+ }
2066
+ function checkLevelConstraints(event, level, checks) {
2067
+ if (level === "basic") return null;
2068
+ const intent = event.intent.toLowerCase();
2069
+ const tool = (event.tool ?? "").toLowerCase();
2070
+ const isDelete = intent.includes("delete") || intent.includes("remove") || intent.includes("rm ") || tool === "delete";
2071
+ const deleteTriggered = isDelete && levelRequiresConfirmation(level, "delete");
2072
+ checks.push({
2073
+ checkType: "delete",
2074
+ level,
2075
+ triggered: deleteTriggered,
2076
+ reason: deleteTriggered ? NEUTRAL_MESSAGES["delete"] : void 0
2077
+ });
2078
+ if (deleteTriggered) {
2079
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["delete"], ruleId: "level-delete-check" };
2080
+ }
2081
+ const isExternal = event.scope ? isExternalScope(event.scope) : false;
2082
+ const externalTriggered = isExternal && levelRequiresConfirmation(level, "write-external");
2083
+ checks.push({
2084
+ checkType: "write-external",
2085
+ level,
2086
+ triggered: externalTriggered,
2087
+ reason: externalTriggered ? NEUTRAL_MESSAGES["write-external"] : void 0
2088
+ });
2089
+ if (externalTriggered) {
2090
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["write-external"], ruleId: "level-external-write-check" };
2091
+ }
2092
+ const isNetwork = tool === "http" || tool === "fetch" || tool === "request" || intent.includes("post ") || intent.includes("sending");
2093
+ const networkTriggered = isNetwork && levelRequiresConfirmation(level, "network-mutate");
2094
+ checks.push({
2095
+ checkType: "network-mutate",
2096
+ level,
2097
+ triggered: networkTriggered,
2098
+ reason: networkTriggered ? NEUTRAL_MESSAGES["network-mutate"] : void 0
2099
+ });
2100
+ if (networkTriggered) {
2101
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["network-mutate"], ruleId: "level-network-mutate-check" };
2102
+ }
2103
+ const isCredential = intent.includes("credential") || intent.includes("password") || intent.includes("secret") || intent.includes("api key") || intent.includes("token");
2104
+ const credentialTriggered = isCredential && levelRequiresConfirmation(level, "credential-access");
2105
+ checks.push({
2106
+ checkType: "credential-access",
2107
+ level,
2108
+ triggered: credentialTriggered,
2109
+ reason: credentialTriggered ? NEUTRAL_MESSAGES["credential-access"] : void 0
2110
+ });
2111
+ if (credentialTriggered) {
2112
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["credential-access"], ruleId: "level-credential-check" };
2113
+ }
2114
+ const irreversibleTriggered = !!event.irreversible && level !== "basic";
2115
+ checks.push({
2116
+ checkType: "irreversible",
2117
+ level,
2118
+ triggered: irreversibleTriggered,
2119
+ reason: irreversibleTriggered ? "This action is marked as irreversible." : void 0
2120
+ });
2121
+ if (irreversibleTriggered) {
2122
+ return {
2123
+ status: "PAUSE",
2124
+ reason: "This action is marked as irreversible.",
2125
+ ruleId: "level-irreversible-check"
2126
+ };
2127
+ }
2128
+ return null;
2129
+ }
2130
+ function matchesKeywords(eventText, ruleText) {
2131
+ return matchesAllKeywords(eventText, ruleText);
2132
+ }
2133
+ function eventToAllowlistKey(event) {
2134
+ return `${(event.tool ?? "*").toLowerCase()}::${event.intent.toLowerCase().trim()}`;
2135
+ }
2136
+ function buildTrace(invariantChecks, safetyChecks, planCheck, roleChecks, guardChecks, kernelRuleChecks, levelChecks, decidingLayer, decidingId, startTime) {
2137
+ const trace = {
2138
+ invariantChecks,
2139
+ safetyChecks,
2140
+ roleChecks,
2141
+ guardChecks,
2142
+ kernelRuleChecks,
2143
+ levelChecks,
2144
+ precedenceResolution: {
2145
+ decidingLayer,
2146
+ decidingId,
2147
+ strategy: "first-match-wins",
2148
+ chainOrder: [
2149
+ "invariant-coverage",
2150
+ "session-allowlist",
2151
+ "safety-injection",
2152
+ "safety-scope-escape",
2153
+ "safety-execution-claim",
2154
+ "safety-execution-intent",
2155
+ "plan-enforcement",
2156
+ "role-rules",
2157
+ "declarative-guards",
2158
+ "kernel-rules",
2159
+ "level-constraints",
2160
+ "default-allow"
2161
+ ]
2162
+ },
2163
+ durationMs: performance.now() - startTime
2164
+ };
2165
+ if (planCheck) {
2166
+ trace.planCheck = planCheck;
2167
+ }
2168
+ return trace;
2169
+ }
2170
+ function buildVerdict(status, reason, ruleId, warning, world, level, invariantChecks, guardsMatched, rulesMatched, trace, eventIntent) {
2171
+ const evidence = {
2172
+ worldId: world.world.world_id,
2173
+ worldName: world.world.name,
2174
+ worldVersion: world.world.version,
2175
+ evaluatedAt: Date.now(),
2176
+ invariantsSatisfied: invariantChecks.filter((c) => c.hasGuardCoverage).length,
2177
+ invariantsTotal: invariantChecks.length,
2178
+ guardsMatched,
2179
+ rulesMatched,
2180
+ enforcementLevel: level
2181
+ };
2182
+ const verdict = {
2183
+ status,
2184
+ evidence
2185
+ };
2186
+ if (reason) verdict.reason = reason;
2187
+ if (ruleId) verdict.ruleId = ruleId;
2188
+ if (warning) verdict.warning = warning;
2189
+ if (trace) verdict.trace = trace;
2190
+ verdict.event = verdictToEvent(status, eventIntent);
2191
+ return verdict;
2192
+ }
2193
+ function verdictToEvent(status, intent) {
2194
+ const statusEventMap = {
2195
+ ALLOW: "action_allowed",
2196
+ BLOCK: "action_blocked",
2197
+ PAUSE: "action_paused",
2198
+ MODIFY: "action_modified",
2199
+ PENALIZE: "action_penalized",
2200
+ REWARD: "action_rewarded",
2201
+ NEUTRAL: "action_neutral"
2202
+ };
2203
+ return {
2204
+ type: intent || statusEventMap[status] || "unknown_action",
2205
+ actor: "agent",
2206
+ source: "guard",
2207
+ timestamp: Date.now(),
2208
+ guardStatus: status
2209
+ };
2210
+ }
2211
+ var PROMPT_INJECTION_PATTERNS, EXECUTION_CLAIM_PATTERNS, EXECUTION_INTENT_PATTERNS, SCOPE_ESCAPE_PATTERNS, NEUTRAL_MESSAGES, MAX_INPUT_LENGTH;
2212
+ var init_guard_engine = __esm({
2213
+ "src/engine/guard-engine.ts"() {
2214
+ "use strict";
2215
+ init_plan_engine();
2216
+ init_text_utils();
2217
+ PROMPT_INJECTION_PATTERNS = [
2218
+ // Instruction override
2219
+ { pattern: /ignore\s+(previous|all|prior|above)\s+(instructions?|rules?)/i, label: "ignore-instructions" },
2220
+ { pattern: /disregard\s+(your|the)\s+(rules|constraints)/i, label: "disregard-rules" },
2221
+ { pattern: /new\s+instructions?:/i, label: "new-instructions" },
2222
+ // Identity manipulation
2223
+ { pattern: /you\s+are\s+now/i, label: "identity-override" },
2224
+ { pattern: /new\s+persona/i, label: "new-persona" },
2225
+ { pattern: /act\s+as\s+if/i, label: "act-as-if" },
2226
+ { pattern: /pretend\s+(you|to\s+be|you\s+are\s+unrestricted)/i, label: "pretend-to-be" },
2227
+ // Context reset
2228
+ { pattern: /forget\s+(everything|all|your)/i, label: "forget-context" },
2229
+ { pattern: /system\s*:\s*override/i, label: "system-override" },
2230
+ // Constraint bypass
2231
+ { pattern: /override\s+(your|the)\s+(programming|constraints)/i, label: "override-constraints" },
2232
+ { pattern: /bypass\s+(your|the)\s+(filters|constraints|rules)/i, label: "bypass-filters" },
2233
+ // Prompt extraction
2234
+ { pattern: /system\s+prompt/i, label: "system-prompt-probe" },
2235
+ { pattern: /reveal\s+your\s+(instructions?|prompt|rules)/i, label: "reveal-instructions" },
2236
+ // Known jailbreak terms
2237
+ { pattern: /jailbreak/i, label: "jailbreak" },
2238
+ { pattern: /DAN\s+mode/i, label: "dan-mode" },
2239
+ { pattern: /developer\s+mode/i, label: "developer-mode" }
2240
+ ];
2241
+ EXECUTION_CLAIM_PATTERNS = [
2242
+ { pattern: /I have (executed|completed|performed|done|made|created|sent|deleted|modified|updated)/i, label: "claim-i-have" },
2243
+ { pattern: /Successfully (created|deleted|modified|updated|sent|executed|performed)/i, label: "claim-successfully" },
2244
+ { pattern: /The file has been/i, label: "claim-file-modified" },
2245
+ { pattern: /I've made the changes/i, label: "claim-made-changes" },
2246
+ { pattern: /I('ve| have) (sent|posted|submitted|uploaded|downloaded)/i, label: "claim-sent" },
2247
+ { pattern: /Your (email|message|file|request) has been (sent|submitted)/i, label: "claim-your-sent" },
2248
+ { pattern: /Transaction complete/i, label: "claim-transaction" },
2249
+ { pattern: /Order placed/i, label: "claim-order" },
2250
+ { pattern: /Payment processed/i, label: "claim-payment" }
2251
+ ];
2252
+ EXECUTION_INTENT_PATTERNS = [
2253
+ { pattern: /^(execute|run|perform|do this)/i, label: "intent-execute" },
2254
+ { pattern: /^(create|write|delete|modify) (a |the )?(file|folder|document)/i, label: "intent-file-ops" },
2255
+ { pattern: /^(send|post|submit) (a |an |the )?(email|message|tweet|post)/i, label: "intent-send" },
2256
+ { pattern: /^(search|look up|browse) (the )?web/i, label: "intent-web-search" },
2257
+ { pattern: /^(make|call|invoke) (a |an )?(api|http|rest) (call|request)/i, label: "intent-api-call" },
2258
+ { pattern: /^(buy|purchase|order|pay|transfer|send money)/i, label: "intent-financial" },
2259
+ { pattern: /^(book|schedule|reserve)/i, label: "intent-booking" },
2260
+ { pattern: /^(download|upload|save to|export to)/i, label: "intent-transfer" }
2261
+ ];
2262
+ SCOPE_ESCAPE_PATTERNS = [
2263
+ { pattern: /\.\.\//, label: "parent-traversal" },
2264
+ { pattern: /^\/(?!home|project|workspace)/i, label: "absolute-path-outside-safe" },
2265
+ { pattern: /~\//, label: "home-directory" },
2266
+ { pattern: /\/etc\//i, label: "system-config" },
2267
+ { pattern: /\/usr\//i, label: "system-binaries" },
2268
+ { pattern: /\/var\//i, label: "system-variable-data" }
2269
+ ];
2270
+ NEUTRAL_MESSAGES = {
2271
+ "prompt-injection": "This input contains patterns that could alter agent behavior.",
2272
+ "scope-escape": "This action would affect resources outside the declared scope.",
2273
+ "execution-claim": "This response claims to have performed an action.",
2274
+ "execution-intent": "This input requests execution in a thinking-only environment.",
2275
+ "delete": "This action would remove files. Confirmation needed.",
2276
+ "write-external": "This action would write outside the project folder.",
2277
+ "network-mutate": "This action would send data to an external service.",
2278
+ "credential-access": "This action would access stored credentials."
2279
+ };
2280
+ MAX_INPUT_LENGTH = 1e5;
2281
+ }
2282
+ });
2283
+
2284
+ // src/loader/world-loader.ts
2285
+ async function loadWorldFromDirectory(dirPath) {
2286
+ const { readFile } = await import("fs/promises");
2287
+ const { join: join5 } = await import("path");
2288
+ const { readdirSync: readdirSync5 } = await import("fs");
2289
+ async function readJson(filename) {
2290
+ const filePath = join5(dirPath, filename);
2291
+ try {
2292
+ const content = await readFile(filePath, "utf-8");
2293
+ return JSON.parse(content);
2294
+ } catch (err) {
2295
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
2296
+ return void 0;
2297
+ }
2298
+ process.stderr.write(
2299
+ `[neuroverse] Warning: Failed to read ${filename}: ${err instanceof Error ? err.message : String(err)}
2300
+ `
2301
+ );
2302
+ return void 0;
2303
+ }
2304
+ }
2305
+ const worldJson = await readJson("world.json");
2306
+ if (!worldJson) {
2307
+ throw new Error(`Cannot read world.json in ${dirPath}`);
2308
+ }
2309
+ const invariantsJson = await readJson("invariants.json");
2310
+ const assumptionsJson = await readJson("assumptions.json");
2311
+ const stateSchemaJson = await readJson("state-schema.json");
2312
+ const gatesJson = await readJson("gates.json");
2313
+ const outcomesJson = await readJson("outcomes.json");
2314
+ const guardsJson = await readJson("guards.json");
2315
+ const rolesJson = await readJson("roles.json");
2316
+ const kernelJson = await readJson("kernel.json");
2317
+ const metadataJson = await readJson("metadata.json");
2318
+ const rules = [];
2319
+ try {
2320
+ const rulesDir = join5(dirPath, "rules");
2321
+ const ruleFiles = readdirSync5(rulesDir).filter((f) => f.endsWith(".json")).sort();
2322
+ for (const file of ruleFiles) {
2323
+ try {
2324
+ const content = await readFile(join5(rulesDir, file), "utf-8");
2325
+ rules.push(JSON.parse(content));
2326
+ } catch (err) {
2327
+ process.stderr.write(
2328
+ `[neuroverse] Warning: Failed to parse rule ${file}: ${err instanceof Error ? err.message : String(err)}
2329
+ `
2330
+ );
2331
+ }
2332
+ }
2333
+ } catch (err) {
2334
+ if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) {
2335
+ process.stderr.write(
2336
+ `[neuroverse] Warning: Failed to read rules directory: ${err instanceof Error ? err.message : String(err)}
2337
+ `
2338
+ );
2339
+ }
2340
+ }
2341
+ return {
2342
+ world: worldJson,
2343
+ invariants: invariantsJson?.invariants ?? [],
2344
+ assumptions: assumptionsJson ?? { profiles: {}, parameter_definitions: {} },
2345
+ stateSchema: stateSchemaJson ?? { variables: {}, presets: {} },
2346
+ rules,
2347
+ gates: gatesJson ?? {
2348
+ viability_classification: [],
2349
+ structural_override: { description: "", enforcement: "mandatory" },
2350
+ sustainability_threshold: 0,
2351
+ collapse_visual: { background: "", text: "", border: "", label: "" }
2352
+ },
2353
+ outcomes: outcomesJson ?? {
2354
+ computed_outcomes: [],
2355
+ comparison_layout: { primary_card: "", status_badge: "", structural_indicators: [] }
2356
+ },
2357
+ guards: guardsJson,
2358
+ roles: rolesJson,
2359
+ kernel: kernelJson,
2360
+ metadata: metadataJson ?? {
2361
+ format_version: "1.0.0",
2362
+ created_at: "",
2363
+ last_modified: "",
2364
+ authoring_method: "manual-authoring"
2365
+ }
2366
+ };
2367
+ }
2368
+ async function loadWorld(worldPath) {
2369
+ const { stat } = await import("fs/promises");
2370
+ const info = await stat(worldPath);
2371
+ if (info.isDirectory()) {
2372
+ return loadWorldFromDirectory(worldPath);
2373
+ }
2374
+ throw new Error(`Cannot load world from: ${worldPath} \u2014 expected a directory`);
2375
+ }
2376
+ var init_world_loader = __esm({
2377
+ "src/loader/world-loader.ts"() {
2378
+ "use strict";
2379
+ }
2380
+ });
2381
+
2382
+ // src/radiant/core/governance.ts
2383
+ async function auditGovernance(events, worldPath) {
2384
+ let world;
2385
+ try {
2386
+ world = await loadWorld(worldPath);
2387
+ } catch {
2388
+ return emptyAudit(events.length, "Could not load compiled worldmodel for governance audit.");
2389
+ }
2390
+ const verdicts = [];
2391
+ for (const ce of events) {
2392
+ const intent = ce.event.content?.slice(0, 500) || ce.event.kind || "activity";
2393
+ const scope = ce.event.metadata?.scope || void 0;
2394
+ try {
2395
+ const result = evaluateGuard(
2396
+ {
2397
+ intent,
2398
+ scope,
2399
+ actionCategory: mapKindToCategory(ce.event.kind)
2400
+ },
2401
+ world
2402
+ );
2403
+ verdicts.push({
2404
+ eventId: ce.event.id,
2405
+ domain: ce.domain,
2406
+ status: result.status,
2407
+ reason: result.reason,
2408
+ ruleId: result.ruleId,
2409
+ warning: result.warning
2410
+ });
2411
+ } catch {
2412
+ verdicts.push({
2413
+ eventId: ce.event.id,
2414
+ domain: ce.domain,
2415
+ status: "ALLOW",
2416
+ reason: "guard evaluation skipped (error)"
2417
+ });
2418
+ }
2419
+ }
2420
+ const human = bucketVerdicts(verdicts.filter((v) => v.domain === "life"));
2421
+ const cyber = bucketVerdicts(verdicts.filter((v) => v.domain === "cyber"));
2422
+ const joint = bucketVerdicts(verdicts.filter((v) => v.domain === "joint"));
2423
+ const summary = buildSummary(human, cyber, joint, events.length);
2424
+ return {
2425
+ totalEvents: events.length,
2426
+ human,
2427
+ cyber,
2428
+ joint,
2429
+ summary
2430
+ };
2431
+ }
2432
+ function bucketVerdicts(verdicts) {
2433
+ const nonAllow = verdicts.filter((v) => v.status !== "ALLOW");
2434
+ return {
2435
+ allow: verdicts.filter((v) => v.status === "ALLOW").length,
2436
+ modify: verdicts.filter((v) => v.status === "MODIFY").length,
2437
+ block: verdicts.filter((v) => v.status === "BLOCK").length,
2438
+ details: nonAllow
2439
+ };
2440
+ }
2441
+ function buildSummary(human, cyber, joint, total) {
2442
+ const humanTriggered = human.modify + human.block;
2443
+ const cyberTriggered = cyber.modify + cyber.block;
2444
+ const jointTriggered = joint.modify + joint.block;
2445
+ const totalTriggered = humanTriggered + cyberTriggered + jointTriggered;
2446
+ if (totalTriggered === 0) {
2447
+ return `${total} events evaluated. All passed. The cocoon held \u2014 no governance triggered.`;
2448
+ }
2449
+ const parts = [];
2450
+ parts.push(`${total} events evaluated. ${totalTriggered} triggered governance.`);
2451
+ if (humanTriggered > 0) {
2452
+ parts.push(`Human side: ${humanTriggered} (${human.block} blocked, ${human.modify} modified).`);
2453
+ }
2454
+ if (cyberTriggered > 0) {
2455
+ parts.push(`AI side: ${cyberTriggered} (${cyber.block} blocked, ${cyber.modify} modified).`);
2456
+ }
2457
+ if (jointTriggered > 0) {
2458
+ parts.push(`Joint work: ${jointTriggered} (${joint.block} blocked, ${joint.modify} modified).`);
2459
+ }
2460
+ if (humanTriggered > 0 && cyberTriggered > 0) {
2461
+ const ratio = humanTriggered / cyberTriggered;
2462
+ if (ratio > 2) {
2463
+ parts.push("Human side is testing the frame more than AI. Either the worldmodel needs calibrating for human workflows, or humans are genuinely drifting.");
2464
+ } else if (ratio < 0.5) {
2465
+ parts.push("AI side is testing the frame more than humans. Check whether the AI's output patterns match the declared invariants.");
2466
+ } else {
2467
+ parts.push("Roughly balanced between human and AI \u2014 both sides are testing the frame.");
2468
+ }
2469
+ }
2470
+ return parts.join(" ");
2471
+ }
2472
+ function mapKindToCategory(kind) {
2473
+ if (!kind) return "other";
2474
+ if (kind.includes("commit") || kind.includes("merge")) return "write";
2475
+ if (kind.includes("review") || kind.includes("comment")) return "read";
2476
+ return "other";
2477
+ }
2478
+ function emptyAudit(total, reason) {
2479
+ return {
2480
+ totalEvents: total,
2481
+ human: { allow: 0, modify: 0, block: 0, details: [] },
2482
+ cyber: { allow: 0, modify: 0, block: 0, details: [] },
2483
+ joint: { allow: 0, modify: 0, block: 0, details: [] },
2484
+ summary: reason
2485
+ };
2486
+ }
2487
+ var init_governance = __esm({
2488
+ "src/radiant/core/governance.ts"() {
2489
+ "use strict";
2490
+ init_guard_engine();
2491
+ init_world_loader();
2492
+ }
2493
+ });
904
2494
 
905
2495
  // src/radiant/core/domain.ts
906
2496
  function isLifeSide(k) {
@@ -926,6 +2516,11 @@ function classifyActorDomain(event) {
926
2516
  }
927
2517
  return isCyberSide(primaryKind) ? "cyber" : "life";
928
2518
  }
2519
+ var init_domain = __esm({
2520
+ "src/radiant/core/domain.ts"() {
2521
+ "use strict";
2522
+ }
2523
+ });
929
2524
 
930
2525
  // src/radiant/core/signals.ts
931
2526
  function classifyEvents(events) {
@@ -951,7 +2546,6 @@ function extractSignals(events, extractors = DEFAULT_SIGNAL_EXTRACTORS) {
951
2546
  }
952
2547
  return out;
953
2548
  }
954
- var ZERO = { score: 0, eventCount: 0, confidence: 0 };
955
2549
  function inDomain(events, domain) {
956
2550
  return events.filter((e) => e.domain === domain);
957
2551
  }
@@ -963,110 +2557,124 @@ function clamp100(n) {
963
2557
  if (n > 100) return 100;
964
2558
  return n;
965
2559
  }
966
- var CLARITY_EXTRACTOR = {
967
- id: "clarity",
968
- description: "Informativeness of event content \u2014 commit messages, PR bodies, review text",
969
- extract(events, domain) {
970
- const sub = inDomain(events, domain);
971
- if (sub.length === 0) return ZERO;
972
- const totalScore = sub.reduce((acc, e) => {
973
- const len = (e.event.content ?? "").length;
974
- const norm = Math.min(len, 200) / 200;
975
- return acc + norm * 100;
976
- }, 0);
977
- return {
978
- score: clamp100(totalScore / sub.length),
979
- eventCount: sub.length,
980
- confidence: confidenceFromCount(sub.length)
2560
+ var ZERO, CLARITY_EXTRACTOR, OWNERSHIP_EXTRACTOR, FOLLOW_THROUGH_EXTRACTOR, ALIGNMENT_EXTRACTOR, DECISION_MOMENTUM_EXTRACTOR, DEFAULT_SIGNAL_EXTRACTORS;
2561
+ var init_signals = __esm({
2562
+ "src/radiant/core/signals.ts"() {
2563
+ "use strict";
2564
+ init_domain();
2565
+ ZERO = { score: 0, eventCount: 0, confidence: 0 };
2566
+ CLARITY_EXTRACTOR = {
2567
+ id: "clarity",
2568
+ description: "Informativeness of event content \u2014 commit messages, PR bodies, review text",
2569
+ extract(events, domain) {
2570
+ const sub = inDomain(events, domain);
2571
+ if (sub.length === 0) return ZERO;
2572
+ const totalScore = sub.reduce((acc, e) => {
2573
+ const len = (e.event.content ?? "").length;
2574
+ const norm = Math.min(len, 200) / 200;
2575
+ return acc + norm * 100;
2576
+ }, 0);
2577
+ return {
2578
+ score: clamp100(totalScore / sub.length),
2579
+ eventCount: sub.length,
2580
+ confidence: confidenceFromCount(sub.length)
2581
+ };
2582
+ }
981
2583
  };
982
- }
983
- };
984
- var OWNERSHIP_EXTRACTOR = {
985
- id: "ownership",
986
- description: "Clarity of accountability \u2014 fraction of events with a known primary actor",
987
- extract(events, domain) {
988
- const sub = inDomain(events, domain);
989
- if (sub.length === 0) return ZERO;
990
- const attributed = sub.filter((e) => e.event.actor.kind !== "unknown").length;
991
- return {
992
- score: clamp100(attributed / sub.length * 100),
993
- eventCount: sub.length,
994
- confidence: confidenceFromCount(sub.length)
2584
+ OWNERSHIP_EXTRACTOR = {
2585
+ id: "ownership",
2586
+ description: "Clarity of accountability \u2014 fraction of events with a known primary actor",
2587
+ extract(events, domain) {
2588
+ const sub = inDomain(events, domain);
2589
+ if (sub.length === 0) return ZERO;
2590
+ const attributed = sub.filter((e) => e.event.actor.kind !== "unknown").length;
2591
+ return {
2592
+ score: clamp100(attributed / sub.length * 100),
2593
+ eventCount: sub.length,
2594
+ confidence: confidenceFromCount(sub.length)
2595
+ };
2596
+ }
995
2597
  };
996
- }
997
- };
998
- var FOLLOW_THROUGH_EXTRACTOR = {
999
- id: "follow_through",
1000
- description: "Fraction of events that were followed up \u2014 i.e. referenced by a later event",
1001
- extract(events, domain) {
1002
- const sub = inDomain(events, domain);
1003
- if (sub.length === 0) return ZERO;
1004
- const referencedIds = /* @__PURE__ */ new Set();
1005
- for (const e of events) {
1006
- const ref = e.event.respondsTo?.eventId;
1007
- if (ref) referencedIds.add(ref);
1008
- }
1009
- const followedUp = sub.filter((e) => referencedIds.has(e.event.id)).length;
1010
- return {
1011
- score: clamp100(followedUp / sub.length * 100),
1012
- eventCount: sub.length,
1013
- confidence: confidenceFromCount(sub.length)
2598
+ FOLLOW_THROUGH_EXTRACTOR = {
2599
+ id: "follow_through",
2600
+ description: "Fraction of events that were followed up \u2014 i.e. referenced by a later event",
2601
+ extract(events, domain) {
2602
+ const sub = inDomain(events, domain);
2603
+ if (sub.length === 0) return ZERO;
2604
+ const referencedIds = /* @__PURE__ */ new Set();
2605
+ for (const e of events) {
2606
+ const ref = e.event.respondsTo?.eventId;
2607
+ if (ref) referencedIds.add(ref);
2608
+ }
2609
+ const followedUp = sub.filter((e) => referencedIds.has(e.event.id)).length;
2610
+ return {
2611
+ score: clamp100(followedUp / sub.length * 100),
2612
+ eventCount: sub.length,
2613
+ confidence: confidenceFromCount(sub.length)
2614
+ };
2615
+ }
1014
2616
  };
1015
- }
1016
- };
1017
- var ALIGNMENT_EXTRACTOR = {
1018
- id: "alignment",
1019
- description: "Coordination pressure \u2014 fraction of events that reference a prior event",
1020
- extract(events, domain) {
1021
- const sub = inDomain(events, domain);
1022
- if (sub.length === 0) return ZERO;
1023
- const referencing = sub.filter((e) => e.event.respondsTo !== void 0).length;
1024
- return {
1025
- score: clamp100(referencing / sub.length * 100),
1026
- eventCount: sub.length,
1027
- confidence: confidenceFromCount(sub.length)
2617
+ ALIGNMENT_EXTRACTOR = {
2618
+ id: "alignment",
2619
+ description: "Coordination pressure \u2014 fraction of events that reference a prior event",
2620
+ extract(events, domain) {
2621
+ const sub = inDomain(events, domain);
2622
+ if (sub.length === 0) return ZERO;
2623
+ const referencing = sub.filter((e) => e.event.respondsTo !== void 0).length;
2624
+ return {
2625
+ score: clamp100(referencing / sub.length * 100),
2626
+ eventCount: sub.length,
2627
+ confidence: confidenceFromCount(sub.length)
2628
+ };
2629
+ }
1028
2630
  };
1029
- }
1030
- };
1031
- var DECISION_MOMENTUM_EXTRACTOR = {
1032
- id: "decision_momentum",
1033
- description: "Rate of activity in this domain \u2014 events per day, capped at 10/day",
1034
- extract(events, domain) {
1035
- const sub = inDomain(events, domain);
1036
- if (sub.length === 0) return ZERO;
1037
- if (sub.length < 2) {
1038
- return {
1039
- score: 20,
1040
- // token non-zero score — single event = some motion
1041
- eventCount: sub.length,
1042
- confidence: confidenceFromCount(sub.length)
1043
- };
1044
- }
1045
- const ts = sub.map((e) => Date.parse(e.event.timestamp)).sort((a, b) => a - b);
1046
- const spanMs = ts[ts.length - 1] - ts[0];
1047
- const spanDays = Math.max(spanMs / (24 * 60 * 60 * 1e3), 1 / 24);
1048
- const perDay = sub.length / spanDays;
1049
- const normalized = Math.min(perDay, 10) / 10;
1050
- return {
1051
- score: clamp100(normalized * 100),
1052
- eventCount: sub.length,
1053
- confidence: confidenceFromCount(sub.length)
2631
+ DECISION_MOMENTUM_EXTRACTOR = {
2632
+ id: "decision_momentum",
2633
+ description: "Rate of activity in this domain \u2014 events per day, capped at 10/day",
2634
+ extract(events, domain) {
2635
+ const sub = inDomain(events, domain);
2636
+ if (sub.length === 0) return ZERO;
2637
+ if (sub.length < 2) {
2638
+ return {
2639
+ score: 20,
2640
+ // token non-zero score — single event = some motion
2641
+ eventCount: sub.length,
2642
+ confidence: confidenceFromCount(sub.length)
2643
+ };
2644
+ }
2645
+ const ts = sub.map((e) => Date.parse(e.event.timestamp)).sort((a, b) => a - b);
2646
+ const spanMs = ts[ts.length - 1] - ts[0];
2647
+ const spanDays = Math.max(spanMs / (24 * 60 * 60 * 1e3), 1 / 24);
2648
+ const perDay = sub.length / spanDays;
2649
+ const normalized = Math.min(perDay, 10) / 10;
2650
+ return {
2651
+ score: clamp100(normalized * 100),
2652
+ eventCount: sub.length,
2653
+ confidence: confidenceFromCount(sub.length)
2654
+ };
2655
+ }
1054
2656
  };
2657
+ DEFAULT_SIGNAL_EXTRACTORS = Object.freeze([
2658
+ CLARITY_EXTRACTOR,
2659
+ OWNERSHIP_EXTRACTOR,
2660
+ FOLLOW_THROUGH_EXTRACTOR,
2661
+ ALIGNMENT_EXTRACTOR,
2662
+ DECISION_MOMENTUM_EXTRACTOR
2663
+ ]);
1055
2664
  }
1056
- };
1057
- var DEFAULT_SIGNAL_EXTRACTORS = Object.freeze([
1058
- CLARITY_EXTRACTOR,
1059
- OWNERSHIP_EXTRACTOR,
1060
- FOLLOW_THROUGH_EXTRACTOR,
1061
- ALIGNMENT_EXTRACTOR,
1062
- DECISION_MOMENTUM_EXTRACTOR
1063
- ]);
2665
+ });
1064
2666
 
1065
2667
  // src/radiant/types.ts
1066
- var DEFAULT_EVIDENCE_GATE = { k: 3, c: 0.5 };
1067
2668
  function isScored(s) {
1068
2669
  return typeof s === "number";
1069
2670
  }
2671
+ var DEFAULT_EVIDENCE_GATE;
2672
+ var init_types = __esm({
2673
+ "src/radiant/types.ts"() {
2674
+ "use strict";
2675
+ DEFAULT_EVIDENCE_GATE = { k: 3, c: 0.5 };
2676
+ }
2677
+ });
1070
2678
 
1071
2679
  // src/radiant/core/math.ts
1072
2680
  function isPresent(o, gate = DEFAULT_EVIDENCE_GATE) {
@@ -1096,6 +2704,12 @@ function scoreComposite(a_L, a_C, a_N) {
1096
2704
  if (available.length === 0) return "INSUFFICIENT_EVIDENCE";
1097
2705
  return available.reduce((a, b) => a + b, 0) / available.length;
1098
2706
  }
2707
+ var init_math = __esm({
2708
+ "src/radiant/core/math.ts"() {
2709
+ "use strict";
2710
+ init_types();
2711
+ }
2712
+ });
1099
2713
 
1100
2714
  // src/radiant/core/patterns.ts
1101
2715
  async function interpretPatterns(input) {
@@ -1168,6 +2782,14 @@ ${jargonTable}
1168
2782
 
1169
2783
  For example: don't say "update the worldmodel." Say "add a line to your strategy file."
1170
2784
 
2785
+ ## When the same invariant keeps firing
2786
+
2787
+ If the prior read history or the current evidence shows the same worldmodel invariant being triggered repeatedly (by the same side \u2014 human or AI), name it in MEANING and ask the real question:
2788
+
2789
+ "This invariant has been tested N times across M reads. Always on the [human/AI] side. Either the team needs alignment on WHY this rule exists \u2014 or the team is telling you something the worldmodel hasn't absorbed yet."
2790
+
2791
+ Don't just say "invariant held." Say what it means that people keep pushing against the same wall.
2792
+
1171
2793
  ## Health is a valid read
1172
2794
 
1173
2795
  If the activity is healthy and aligned with the worldmodel, SAY SO. Don't fabricate problems. Over-prescription is a voice failure. Legitimate outputs include:
@@ -1196,7 +2818,7 @@ Only recommend a move when the evidence actually calls for one.
1196
2818
  }
1197
2819
  ],
1198
2820
  "meaning": "3-5 sentences. Weave the patterns into ONE strategic thesis. Compress. The reader should finish this paragraph and understand the one thing that matters most in this read. Plain English \u2014 no system jargon.",
1199
- "move": "1-3 direct imperatives, OR explicit 'nothing to act on' if the read is healthy. Do not fabricate urgency. Examples: 'Force cross-module ownership this sprint.' / 'Nothing's broken. Keep shipping.' / 'If you want future reads to track this pattern by name, add a line to your strategy file.'"
2821
+ "move": "1-3 direct imperatives, OR explicit 'nothing to act on' if the read is healthy. Do not fabricate urgency. When a candidate pattern has high confidence (>0.6), tell the reader EXACTLY where to declare it: 'If you want Radiant to track [pattern_name] over time, add it to auki-strategy.worldmodel.md under Evolution Layer \u2192 Drift Behaviors (or Aligned Behaviors if it is positive). If you don't, Radiant will rediscover it from scratch next run.' Be specific about the file and section \u2014 don't make them guess."
1200
2822
  }
1201
2823
  \`\`\`
1202
2824
 
@@ -1290,6 +2912,11 @@ function parseInterpretation(raw, canonicalNames) {
1290
2912
  function isPatternLike(x) {
1291
2913
  return typeof x === "object" && x !== null && "name" in x;
1292
2914
  }
2915
+ var init_patterns = __esm({
2916
+ "src/radiant/core/patterns.ts"() {
2917
+ "use strict";
2918
+ }
2919
+ });
1293
2920
 
1294
2921
  // src/radiant/core/renderer.ts
1295
2922
  function render(input) {
@@ -1352,6 +2979,27 @@ Lens: ${input.lens.name}`
1352
2979
  ` Composite: ${formatScore(input.scores.R)}`
1353
2980
  ].join("\n");
1354
2981
  sections.push(alignBlock);
2982
+ if (input.governance && input.governance.totalEvents > 0) {
2983
+ const gov = input.governance;
2984
+ const govLines = ["GOVERNANCE", "", ` ${gov.summary}`];
2985
+ const showSide = (label, side) => {
2986
+ if (side.allow + side.modify + side.block === 0) return;
2987
+ govLines.push("");
2988
+ govLines.push(` ${label}:`);
2989
+ govLines.push(` ${side.allow} ALLOW \xB7 ${side.modify} MODIFY \xB7 ${side.block} BLOCK`);
2990
+ for (const d of side.details.slice(0, 3)) {
2991
+ const reason = d.reason ? ` \u2192 ${d.reason}` : "";
2992
+ govLines.push(` ${d.status}: ${d.eventId}${reason}`);
2993
+ }
2994
+ if (side.details.length > 3) {
2995
+ govLines.push(` ... and ${side.details.length - 3} more`);
2996
+ }
2997
+ };
2998
+ showSide("Human side", gov.human);
2999
+ showSide("AI side", gov.cyber);
3000
+ showSide("Human\u2013AI joint", gov.joint);
3001
+ sections.push(govLines.join("\n"));
3002
+ }
1355
3003
  sections.push(renderDepth(input.priorReadCount ?? 0, input.windowDays));
1356
3004
  return sections.join("\n\n");
1357
3005
  }
@@ -1514,6 +3162,13 @@ function serializeYAML(obj, indent = 0) {
1514
3162
  return `${obj}
1515
3163
  `;
1516
3164
  }
3165
+ var init_renderer = __esm({
3166
+ "src/radiant/core/renderer.ts"() {
3167
+ "use strict";
3168
+ init_types();
3169
+ init_scopes();
3170
+ }
3171
+ });
1517
3172
 
1518
3173
  // src/radiant/commands/emergent.ts
1519
3174
  async function emergent(input) {
@@ -1521,14 +3176,31 @@ async function emergent(input) {
1521
3176
  const windowDays = input.windowDays ?? 14;
1522
3177
  let statedIntent;
1523
3178
  let exocortexContext;
3179
+ let priorReadContext = "";
1524
3180
  if (input.exocortexPath) {
1525
3181
  exocortexContext = readExocortex(input.exocortexPath);
1526
3182
  const formatted = formatExocortexForPrompt(exocortexContext);
1527
3183
  if (formatted) statedIntent = formatted;
3184
+ const priorReads = loadPriorReads(input.exocortexPath);
3185
+ if (priorReads.length > 0) {
3186
+ priorReadContext = formatPriorReadsForPrompt(priorReads);
3187
+ }
3188
+ }
3189
+ let events;
3190
+ let orgRepos;
3191
+ if (input.scope.type === "org") {
3192
+ const orgResult = await fetchGitHubOrgActivity(
3193
+ input.scope,
3194
+ input.githubToken,
3195
+ { windowDays }
3196
+ );
3197
+ events = orgResult.events;
3198
+ orgRepos = orgResult.repos;
3199
+ } else {
3200
+ events = await fetchGitHubActivity(input.scope, input.githubToken, {
3201
+ windowDays
3202
+ });
1528
3203
  }
1529
- const events = await fetchGitHubActivity(input.scope, input.githubToken, {
1530
- windowDays
1531
- });
1532
3204
  const classified = classifyEvents(events);
1533
3205
  const signals = extractSignals(classified);
1534
3206
  const scores = computeScores(signals, input.worldmodelContent !== "");
@@ -1539,11 +3211,18 @@ async function emergent(input) {
1539
3211
  lens,
1540
3212
  ai: input.ai,
1541
3213
  canonicalPatterns: input.canonicalPatterns,
1542
- statedIntent
3214
+ statedIntent: statedIntent ? statedIntent + (priorReadContext ? "\n\n" + priorReadContext : "") : priorReadContext || void 0
1543
3215
  });
1544
3216
  const rewrittenPatterns = patterns.map((p) => lens.rewrite(p));
1545
3217
  const allDescriptions = rewrittenPatterns.map((p) => p.description).join("\n");
1546
3218
  const voiceViolations = checkForbiddenPhrases(lens, allDescriptions);
3219
+ let governance;
3220
+ if (input.worldPath) {
3221
+ try {
3222
+ governance = await auditGovernance(classified, input.worldPath);
3223
+ } catch {
3224
+ }
3225
+ }
1547
3226
  const rendered = render({
1548
3227
  scope: input.scope,
1549
3228
  windowDays,
@@ -1553,8 +3232,27 @@ async function emergent(input) {
1553
3232
  scores,
1554
3233
  lens,
1555
3234
  meaning: meaning || void 0,
1556
- move: move || void 0
3235
+ move: move || void 0,
3236
+ governance
1557
3237
  });
3238
+ if (input.exocortexPath) {
3239
+ try {
3240
+ const readPath = writeRead(input.exocortexPath, rendered.frontmatter, rendered.text);
3241
+ const priorReads = loadPriorReads(input.exocortexPath);
3242
+ const currentPatternNames = rewrittenPatterns.map((p) => p.name);
3243
+ const persistence = computePersistence(priorReads, currentPatternNames);
3244
+ const triggeredItems = governance ? [
3245
+ ...governance.human.details.map((d) => d.ruleId).filter(Boolean),
3246
+ ...governance.cyber.details.map((d) => d.ruleId).filter(Boolean),
3247
+ ...governance.joint.details.map((d) => d.ruleId).filter(Boolean)
3248
+ ] : [];
3249
+ updateKnowledge(input.exocortexPath, persistence, {
3250
+ triggeredItems,
3251
+ totalReads: priorReads.length + 1
3252
+ });
3253
+ } catch {
3254
+ }
3255
+ }
1558
3256
  return {
1559
3257
  text: rendered.text,
1560
3258
  frontmatter: rendered.frontmatter,
@@ -1612,6 +3310,22 @@ function resolveLens2(id) {
1612
3310
  }
1613
3311
  return lens;
1614
3312
  }
3313
+ var init_emergent = __esm({
3314
+ "src/radiant/commands/emergent.ts"() {
3315
+ "use strict";
3316
+ init_lenses();
3317
+ init_github();
3318
+ init_exocortex();
3319
+ init_palace();
3320
+ init_governance();
3321
+ init_signals();
3322
+ init_math();
3323
+ init_patterns();
3324
+ init_renderer();
3325
+ init_voice_check();
3326
+ init_types();
3327
+ }
3328
+ });
1615
3329
 
1616
3330
  // src/radiant/core/ai.ts
1617
3331
  function createAnthropicAI(apiKey, model = "claude-sonnet-4-20250514", maxTokens = 4096) {
@@ -1646,8 +3360,296 @@ function createAnthropicAI(apiKey, model = "claude-sonnet-4-20250514", maxTokens
1646
3360
  }
1647
3361
  };
1648
3362
  }
3363
+ var init_ai = __esm({
3364
+ "src/radiant/core/ai.ts"() {
3365
+ "use strict";
3366
+ }
3367
+ });
3368
+
3369
+ // src/radiant/mcp/server.ts
3370
+ var server_exports = {};
3371
+ __export(server_exports, {
3372
+ RadiantMcpServer: () => RadiantMcpServer,
3373
+ startRadiantMcp: () => startRadiantMcp
3374
+ });
3375
+ function loadWorldmodelContent(worldsPath) {
3376
+ const resolved = (0, import_path3.resolve)(worldsPath);
3377
+ if (!(0, import_fs3.existsSync)(resolved)) {
3378
+ throw new Error(`Worlds path not found: ${resolved}`);
3379
+ }
3380
+ const stat = (0, import_fs3.statSync)(resolved);
3381
+ if (stat.isFile()) {
3382
+ return (0, import_fs3.readFileSync)(resolved, "utf-8");
3383
+ }
3384
+ if (stat.isDirectory()) {
3385
+ const files = (0, import_fs3.readdirSync)(resolved).filter(
3386
+ (f) => (0, import_path3.extname)(f) === ".md" && (f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md"))
3387
+ ).sort();
3388
+ if (files.length === 0) {
3389
+ throw new Error(`No worldmodel files found in ${resolved}`);
3390
+ }
3391
+ return files.map((f) => (0, import_fs3.readFileSync)((0, import_path3.join)(resolved, f), "utf-8")).join("\n\n---\n\n");
3392
+ }
3393
+ throw new Error(`Worlds path is neither a file nor directory: ${resolved}`);
3394
+ }
3395
+ async function startRadiantMcp(args) {
3396
+ function parseArg(flag) {
3397
+ const idx = args.indexOf(flag);
3398
+ return idx >= 0 && idx + 1 < args.length ? args[idx + 1] : void 0;
3399
+ }
3400
+ const worldsPath = parseArg("--worlds") ?? process.env.RADIANT_WORLDS;
3401
+ const lensId = parseArg("--lens") ?? process.env.RADIANT_LENS ?? "auki-builder";
3402
+ const model = parseArg("--model") ?? process.env.RADIANT_MODEL;
3403
+ if (!worldsPath) {
3404
+ process.stderr.write("Error: --worlds <dir> or RADIANT_WORLDS required.\n");
3405
+ process.exit(1);
3406
+ }
3407
+ const server = new RadiantMcpServer({ worldsPath, lensId, model });
3408
+ await server.start();
3409
+ }
3410
+ var import_fs3, import_path3, TOOLS, RadiantMcpServer;
3411
+ var init_server = __esm({
3412
+ "src/radiant/mcp/server.ts"() {
3413
+ "use strict";
3414
+ import_fs3 = require("fs");
3415
+ import_path3 = require("path");
3416
+ init_think();
3417
+ init_emergent();
3418
+ init_ai();
3419
+ init_scopes();
3420
+ TOOLS = [
3421
+ {
3422
+ name: "radiant_think",
3423
+ description: "Send a query through the loaded worldmodel + rendering lens and get an Auki-framed response. Use this for strategic questions, decision evaluation, or any question that should be interpreted through the organization's behavioral model.",
3424
+ inputSchema: {
3425
+ type: "object",
3426
+ properties: {
3427
+ query: {
3428
+ type: "string",
3429
+ description: "The question or prompt to interpret through the worldmodel + lens."
3430
+ }
3431
+ },
3432
+ required: ["query"]
3433
+ }
3434
+ },
3435
+ {
3436
+ name: "radiant_emergent",
3437
+ description: "Run a behavioral read on a GitHub repository. Fetches recent activity, classifies events, extracts signals, identifies patterns, computes alignment scores, and produces the EMERGENT / MEANING / MOVE / ALIGNMENT output. Use this when asked about team activity, coordination patterns, or alignment with the worldmodel.",
3438
+ inputSchema: {
3439
+ type: "object",
3440
+ properties: {
3441
+ scope: {
3442
+ type: "string",
3443
+ description: 'GitHub repository in "owner/repo" format (e.g. "aukiverse/posemesh").'
3444
+ },
3445
+ exocortex_dir: {
3446
+ type: "string",
3447
+ description: "Optional path to an exocortex directory for stated-intent-vs-observed-behavior comparison."
3448
+ }
3449
+ },
3450
+ required: ["scope"]
3451
+ }
3452
+ }
3453
+ ];
3454
+ RadiantMcpServer = class {
3455
+ config;
3456
+ worldmodelContent;
3457
+ buffer = "";
3458
+ constructor(config) {
3459
+ this.config = config;
3460
+ this.worldmodelContent = loadWorldmodelContent(config.worldsPath);
3461
+ }
3462
+ async start() {
3463
+ process.stderr.write(
3464
+ `Radiant MCP server starting
3465
+ Worlds: ${this.config.worldsPath}
3466
+ Lens: ${this.config.lensId}
3467
+ Tools: radiant_think, radiant_emergent
3468
+ `
3469
+ );
3470
+ process.stdin.setEncoding("utf-8");
3471
+ process.stdin.on("data", (chunk) => {
3472
+ this.buffer += chunk;
3473
+ this.processBuffer();
3474
+ });
3475
+ process.stdin.on("end", () => {
3476
+ process.exit(0);
3477
+ });
3478
+ }
3479
+ processBuffer() {
3480
+ const lines = this.buffer.split("\n");
3481
+ this.buffer = lines.pop() ?? "";
3482
+ for (const line of lines) {
3483
+ const trimmed = line.trim();
3484
+ if (!trimmed) continue;
3485
+ try {
3486
+ const request = JSON.parse(trimmed);
3487
+ this.handleRequest(request).catch((err) => {
3488
+ this.sendError(request.id, -32603, String(err));
3489
+ });
3490
+ } catch {
3491
+ }
3492
+ }
3493
+ }
3494
+ async handleRequest(req) {
3495
+ switch (req.method) {
3496
+ case "initialize":
3497
+ this.sendResult(req.id, {
3498
+ protocolVersion: "2024-11-05",
3499
+ capabilities: { tools: {} },
3500
+ serverInfo: {
3501
+ name: "radiant",
3502
+ version: "0.6.1"
3503
+ }
3504
+ });
3505
+ break;
3506
+ case "notifications/initialized":
3507
+ break;
3508
+ case "tools/list":
3509
+ this.sendResult(req.id, { tools: TOOLS });
3510
+ break;
3511
+ case "tools/call":
3512
+ await this.handleToolCall(req);
3513
+ break;
3514
+ default:
3515
+ this.sendError(req.id, -32601, `Unknown method: ${req.method}`);
3516
+ }
3517
+ }
3518
+ async handleToolCall(req) {
3519
+ const params = req.params;
3520
+ if (!params?.name) {
3521
+ this.sendError(req.id, -32602, "Missing tool name");
3522
+ return;
3523
+ }
3524
+ const args = params.arguments ?? {};
3525
+ try {
3526
+ switch (params.name) {
3527
+ case "radiant_think":
3528
+ await this.handleThink(req.id, args);
3529
+ break;
3530
+ case "radiant_emergent":
3531
+ await this.handleEmergent(req.id, args);
3532
+ break;
3533
+ default:
3534
+ this.sendError(req.id, -32602, `Unknown tool: ${params.name}`);
3535
+ }
3536
+ } catch (err) {
3537
+ this.sendResult(req.id, {
3538
+ content: [{ type: "text", text: `Error: ${err}` }],
3539
+ isError: true
3540
+ });
3541
+ }
3542
+ }
3543
+ async handleThink(id, args) {
3544
+ const query = String(args.query ?? "");
3545
+ if (!query) {
3546
+ this.sendResult(id, {
3547
+ content: [{ type: "text", text: "Error: query is required" }],
3548
+ isError: true
3549
+ });
3550
+ return;
3551
+ }
3552
+ const apiKey = process.env.ANTHROPIC_API_KEY;
3553
+ if (!apiKey) {
3554
+ this.sendResult(id, {
3555
+ content: [{ type: "text", text: "Error: ANTHROPIC_API_KEY not set" }],
3556
+ isError: true
3557
+ });
3558
+ return;
3559
+ }
3560
+ const ai = createAnthropicAI(apiKey, this.config.model || void 0);
3561
+ const result = await think({
3562
+ worldmodelContent: this.worldmodelContent,
3563
+ lensId: this.config.lensId,
3564
+ query,
3565
+ ai
3566
+ });
3567
+ let text = result.response;
3568
+ if (!result.voiceClean) {
3569
+ text += `
3570
+
3571
+ \u26A0 Voice violations detected: ${result.voiceViolations.map((v) => v.phrase).join(", ")}`;
3572
+ }
3573
+ this.sendResult(id, {
3574
+ content: [{ type: "text", text }]
3575
+ });
3576
+ }
3577
+ async handleEmergent(id, args) {
3578
+ const scopeStr = String(args.scope ?? "");
3579
+ if (!scopeStr) {
3580
+ this.sendResult(id, {
3581
+ content: [{ type: "text", text: 'Error: scope is required (e.g. "aukiverse/posemesh")' }],
3582
+ isError: true
3583
+ });
3584
+ return;
3585
+ }
3586
+ const apiKey = process.env.ANTHROPIC_API_KEY;
3587
+ const githubToken = process.env.GITHUB_TOKEN;
3588
+ if (!apiKey) {
3589
+ this.sendResult(id, {
3590
+ content: [{ type: "text", text: "Error: ANTHROPIC_API_KEY not set" }],
3591
+ isError: true
3592
+ });
3593
+ return;
3594
+ }
3595
+ if (!githubToken) {
3596
+ this.sendResult(id, {
3597
+ content: [{ type: "text", text: "Error: GITHUB_TOKEN not set" }],
3598
+ isError: true
3599
+ });
3600
+ return;
3601
+ }
3602
+ const scope = parseRepoScope(scopeStr);
3603
+ const ai = createAnthropicAI(apiKey, this.config.model || void 0);
3604
+ const exocortexPath = args.exocortex_dir ? String(args.exocortex_dir) : void 0;
3605
+ const result = await emergent({
3606
+ scope,
3607
+ githubToken,
3608
+ worldmodelContent: this.worldmodelContent,
3609
+ lensId: this.config.lensId,
3610
+ ai,
3611
+ windowDays: 14,
3612
+ exocortexPath
3613
+ });
3614
+ let text = result.text;
3615
+ if (!result.voiceClean) {
3616
+ text += `
3617
+
3618
+ \u26A0 Voice violations: ${result.voiceViolations.map((v) => v.phrase).join(", ")}`;
3619
+ }
3620
+ this.sendResult(id, {
3621
+ content: [{ type: "text", text }]
3622
+ });
3623
+ }
3624
+ sendResult(id, result) {
3625
+ const response = { jsonrpc: "2.0", id, result };
3626
+ process.stdout.write(JSON.stringify(response) + "\n");
3627
+ }
3628
+ sendError(id, code, message) {
3629
+ const response = {
3630
+ jsonrpc: "2.0",
3631
+ id: id ?? null,
3632
+ error: { code, message }
3633
+ };
3634
+ process.stdout.write(JSON.stringify(response) + "\n");
3635
+ }
3636
+ };
3637
+ }
3638
+ });
1649
3639
 
1650
3640
  // src/cli/radiant.ts
3641
+ var radiant_exports = {};
3642
+ __export(radiant_exports, {
3643
+ main: () => main
3644
+ });
3645
+ module.exports = __toCommonJS(radiant_exports);
3646
+ var import_fs4 = require("fs");
3647
+ var import_path4 = require("path");
3648
+ init_think();
3649
+ init_emergent();
3650
+ init_ai();
3651
+ init_scopes();
3652
+ init_exocortex();
1651
3653
  init_lenses();
1652
3654
  var RED = "\x1B[31m";
1653
3655
  var DIM = "\x1B[2m";
@@ -1689,6 +3691,8 @@ function parseArgs(argv) {
1689
3691
  query: void 0,
1690
3692
  model: void 0,
1691
3693
  exocortex: void 0,
3694
+ teamExocortex: void 0,
3695
+ view: void 0,
1692
3696
  json: false,
1693
3697
  help: false,
1694
3698
  rest: []
@@ -1716,6 +3720,12 @@ function parseArgs(argv) {
1716
3720
  case "--exocortex":
1717
3721
  result.exocortex = argv[++i];
1718
3722
  break;
3723
+ case "--team-exocortex":
3724
+ result.teamExocortex = argv[++i];
3725
+ break;
3726
+ case "--view":
3727
+ result.view = argv[++i];
3728
+ break;
1719
3729
  case "--json":
1720
3730
  result.json = true;
1721
3731
  break;
@@ -1731,18 +3741,18 @@ function parseArgs(argv) {
1731
3741
  }
1732
3742
  return result;
1733
3743
  }
1734
- function loadWorldmodelContent(worldsPath) {
1735
- const resolved = (0, import_path2.resolve)(worldsPath);
1736
- if (!(0, import_fs2.existsSync)(resolved)) {
3744
+ function loadWorldmodelContent2(worldsPath) {
3745
+ const resolved = (0, import_path4.resolve)(worldsPath);
3746
+ if (!(0, import_fs4.existsSync)(resolved)) {
1737
3747
  throw new Error(`Worlds path not found: ${resolved}`);
1738
3748
  }
1739
- const stat = (0, import_fs2.statSync)(resolved);
3749
+ const stat = (0, import_fs4.statSync)(resolved);
1740
3750
  if (stat.isFile()) {
1741
- return (0, import_fs2.readFileSync)(resolved, "utf-8");
3751
+ return (0, import_fs4.readFileSync)(resolved, "utf-8");
1742
3752
  }
1743
3753
  if (stat.isDirectory()) {
1744
- const files = (0, import_fs2.readdirSync)(resolved).filter(
1745
- (f) => (0, import_path2.extname)(f) === ".md" && (f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md"))
3754
+ const files = (0, import_fs4.readdirSync)(resolved).filter(
3755
+ (f) => (0, import_path4.extname)(f) === ".md" && (f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md"))
1746
3756
  ).sort();
1747
3757
  if (files.length === 0) {
1748
3758
  throw new Error(
@@ -1750,7 +3760,7 @@ function loadWorldmodelContent(worldsPath) {
1750
3760
  );
1751
3761
  }
1752
3762
  return files.map((f) => {
1753
- const content = (0, import_fs2.readFileSync)((0, import_path2.join)(resolved, f), "utf-8");
3763
+ const content = (0, import_fs4.readFileSync)((0, import_path4.join)(resolved, f), "utf-8");
1754
3764
  return `<!-- worldmodel: ${f} -->
1755
3765
  ${content}`;
1756
3766
  }).join("\n\n---\n\n");
@@ -1789,7 +3799,7 @@ ${DIM}Set it to your Anthropic API key to use Radiant's AI features.${RESET}
1789
3799
  query = args.rest.join(" ");
1790
3800
  }
1791
3801
  if (!query && !process.stdin.isTTY) {
1792
- query = (0, import_fs2.readFileSync)(0, "utf-8").trim();
3802
+ query = (0, import_fs4.readFileSync)(0, "utf-8").trim();
1793
3803
  }
1794
3804
  if (!query) {
1795
3805
  process.stderr.write(
@@ -1799,7 +3809,7 @@ ${DIM}Use --query "...", pass as trailing args, or pipe via stdin.${RESET}
1799
3809
  );
1800
3810
  process.exit(1);
1801
3811
  }
1802
- const worldmodelContent = loadWorldmodelContent(worldsPath);
3812
+ const worldmodelContent = loadWorldmodelContent2(worldsPath);
1803
3813
  const model = args.model ?? process.env.RADIANT_MODEL;
1804
3814
  const ai = createAnthropicAI(apiKey, model || void 0);
1805
3815
  process.stderr.write(
@@ -1857,7 +3867,7 @@ async function cmdEmergent(args) {
1857
3867
  );
1858
3868
  process.exit(1);
1859
3869
  }
1860
- const scope = parseRepoScope(scopeStr);
3870
+ const scope = parseScope(scopeStr);
1861
3871
  const lensId = args.lens ?? process.env.RADIANT_LENS;
1862
3872
  if (!lensId) {
1863
3873
  process.stderr.write(
@@ -1892,9 +3902,18 @@ ${DIM}Set it to a GitHub PAT with repo read access.${RESET}
1892
3902
  );
1893
3903
  process.exit(1);
1894
3904
  }
1895
- const worldmodelContent = loadWorldmodelContent(worldsPath);
3905
+ const worldmodelContent = loadWorldmodelContent2(worldsPath);
1896
3906
  const model = args.model ?? process.env.RADIANT_MODEL;
1897
3907
  const ai = createAnthropicAI(anthropicKey, model || void 0);
3908
+ const view = args.view ?? process.env.RADIANT_VIEW ?? "community";
3909
+ const validViews = ["community", "team", "full"];
3910
+ if (!validViews.includes(view)) {
3911
+ process.stderr.write(
3912
+ `${RED}Error:${RESET} --view must be community, team, or full. Got "${view}".
3913
+ `
3914
+ );
3915
+ process.exit(1);
3916
+ }
1898
3917
  const exocortexPath = args.exocortex ?? process.env.RADIANT_EXOCORTEX;
1899
3918
  let exocortexStatus = "not loaded";
1900
3919
  if (exocortexPath) {
@@ -1902,7 +3921,8 @@ ${DIM}Set it to a GitHub PAT with repo read access.${RESET}
1902
3921
  exocortexStatus = summarizeExocortex(ctx);
1903
3922
  }
1904
3923
  process.stderr.write(
1905
- `${DIM}Scope: ${scope.owner}/${scope.repo}${RESET}
3924
+ `${DIM}Scope: ${scope.type === "org" ? scope.owner + " (entire org)" : scope.owner + "/" + scope.repo}${RESET}
3925
+ ${DIM}View: ${view}${RESET}
1906
3926
  ${DIM}Lens: ${lensId}${RESET}
1907
3927
  ${DIM}Model: ${model ?? "claude-sonnet-4-20250514 (default)"}${RESET}
1908
3928
  ${DIM}ExoCortex: ${exocortexStatus}${RESET}
@@ -2032,6 +4052,10 @@ async function main(argv) {
2032
4052
  return cmdLenses(args);
2033
4053
  case "emergent":
2034
4054
  return cmdEmergent(args);
4055
+ case "mcp": {
4056
+ const { startRadiantMcp: startRadiantMcp2 } = await Promise.resolve().then(() => (init_server(), server_exports));
4057
+ return startRadiantMcp2(argv);
4058
+ }
2035
4059
  case "decision":
2036
4060
  case "signals":
2037
4061
  case "drift":