@neuroverseos/governance 0.6.1 → 0.7.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.
- package/README.md +0 -3
- package/dist/{chunk-AEVT7DSZ.js → chunk-T6EQ7ZBG.js} +366 -3
- package/dist/cli/neuroverse.cjs +770 -129
- package/dist/cli/radiant.cjs +2078 -139
- package/dist/cli/radiant.js +8 -1
- package/dist/radiant/index.cjs +1554 -5
- package/dist/radiant/index.d.cts +146 -8
- package/dist/radiant/index.d.ts +146 -8
- package/dist/radiant/index.js +18 -3
- package/dist/server-BXMC5NOE.js +271 -0
- package/package.json +1 -1
package/dist/cli/radiant.cjs
CHANGED
|
@@ -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,9 +626,14 @@ function resolveLens(id) {
|
|
|
618
626
|
}
|
|
619
627
|
return lens;
|
|
620
628
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
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
639
|
function parseRepoScope(scope) {
|
|
@@ -636,6 +649,11 @@ function parseRepoScope(scope) {
|
|
|
636
649
|
function formatScope(scope) {
|
|
637
650
|
return `${scope.owner}/${scope.repo}`;
|
|
638
651
|
}
|
|
652
|
+
var init_scopes = __esm({
|
|
653
|
+
"src/radiant/core/scopes.ts"() {
|
|
654
|
+
"use strict";
|
|
655
|
+
}
|
|
656
|
+
});
|
|
639
657
|
|
|
640
658
|
// src/radiant/adapters/github.ts
|
|
641
659
|
async function fetchGitHubActivity(scope, token, options = {}) {
|
|
@@ -745,20 +763,6 @@ function mapComment(comment, scope) {
|
|
|
745
763
|
};
|
|
746
764
|
return event;
|
|
747
765
|
}
|
|
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
766
|
function mapUser(ghUser, fallbackName) {
|
|
763
767
|
if (!ghUser) {
|
|
764
768
|
return {
|
|
@@ -817,10 +821,29 @@ async function fetchJSON(url, headers) {
|
|
|
817
821
|
}
|
|
818
822
|
return await res.json();
|
|
819
823
|
}
|
|
824
|
+
var KNOWN_AI_LOGINS, KNOWN_AI_CO_AUTHOR_NAMES;
|
|
825
|
+
var init_github = __esm({
|
|
826
|
+
"src/radiant/adapters/github.ts"() {
|
|
827
|
+
"use strict";
|
|
828
|
+
init_scopes();
|
|
829
|
+
KNOWN_AI_LOGINS = /* @__PURE__ */ new Set([
|
|
830
|
+
"github-actions[bot]",
|
|
831
|
+
"dependabot[bot]",
|
|
832
|
+
"renovate[bot]",
|
|
833
|
+
"copilot"
|
|
834
|
+
]);
|
|
835
|
+
KNOWN_AI_CO_AUTHOR_NAMES = /* @__PURE__ */ new Set([
|
|
836
|
+
"claude",
|
|
837
|
+
"copilot",
|
|
838
|
+
"cursor",
|
|
839
|
+
"codeium",
|
|
840
|
+
"tabnine",
|
|
841
|
+
"codex"
|
|
842
|
+
]);
|
|
843
|
+
}
|
|
844
|
+
});
|
|
820
845
|
|
|
821
846
|
// src/radiant/adapters/exocortex.ts
|
|
822
|
-
var import_fs = require("fs");
|
|
823
|
-
var import_path = require("path");
|
|
824
847
|
function readExocortex(dirPath) {
|
|
825
848
|
const dir = (0, import_path.resolve)(dirPath);
|
|
826
849
|
let filesLoaded = 0;
|
|
@@ -901,6 +924,1526 @@ function summarizeExocortex(ctx) {
|
|
|
901
924
|
if (ctx.methods) loaded.push("methods");
|
|
902
925
|
return `${loaded.join(", ")} (${ctx.filesLoaded} files)`;
|
|
903
926
|
}
|
|
927
|
+
var import_fs, import_path;
|
|
928
|
+
var init_exocortex = __esm({
|
|
929
|
+
"src/radiant/adapters/exocortex.ts"() {
|
|
930
|
+
"use strict";
|
|
931
|
+
import_fs = require("fs");
|
|
932
|
+
import_path = require("path");
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
// src/radiant/memory/palace.ts
|
|
937
|
+
function writeRead(exocortexDir, frontmatter, text) {
|
|
938
|
+
const dir = (0, import_path2.resolve)(exocortexDir, "radiant", "reads");
|
|
939
|
+
(0, import_fs2.mkdirSync)(dir, { recursive: true });
|
|
940
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
941
|
+
const filename = `${date}.md`;
|
|
942
|
+
const filepath = (0, import_path2.join)(dir, filename);
|
|
943
|
+
const content = `${frontmatter}
|
|
944
|
+
|
|
945
|
+
${text}
|
|
946
|
+
`;
|
|
947
|
+
(0, import_fs2.writeFileSync)(filepath, content, "utf-8");
|
|
948
|
+
return filepath;
|
|
949
|
+
}
|
|
950
|
+
function updateKnowledge(exocortexDir, persistence, options) {
|
|
951
|
+
const dir = (0, import_path2.resolve)(exocortexDir, "radiant");
|
|
952
|
+
(0, import_fs2.mkdirSync)(dir, { recursive: true });
|
|
953
|
+
const filepath = (0, import_path2.join)(dir, "knowledge.md");
|
|
954
|
+
const totalReads = options?.totalReads ?? 0;
|
|
955
|
+
const existingUntriggered = loadUntriggeredCounts(filepath);
|
|
956
|
+
const lines = [
|
|
957
|
+
"# Radiant \u2014 Accumulated Behavioral Knowledge",
|
|
958
|
+
"",
|
|
959
|
+
`Last updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`,
|
|
960
|
+
`Total reads: ${totalReads}`,
|
|
961
|
+
"",
|
|
962
|
+
"---",
|
|
963
|
+
"",
|
|
964
|
+
"## Evolution proposals",
|
|
965
|
+
""
|
|
966
|
+
];
|
|
967
|
+
const addCandidates = persistence.filter((p) => p.occurrences >= 3);
|
|
968
|
+
if (addCandidates.length > 0) {
|
|
969
|
+
lines.push("### Consider adding");
|
|
970
|
+
lines.push("");
|
|
971
|
+
lines.push("These candidate patterns keep recurring. They are not yet in the worldmodel.");
|
|
972
|
+
lines.push("If they represent real behavioral patterns worth tracking, add them.");
|
|
973
|
+
lines.push("If they were temporary, dismiss them.");
|
|
974
|
+
lines.push("");
|
|
975
|
+
for (const p of addCandidates) {
|
|
976
|
+
lines.push(
|
|
977
|
+
`- **${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).`
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
lines.push("");
|
|
981
|
+
}
|
|
982
|
+
if (options?.declaredItems && options.declaredItems.length > 0) {
|
|
983
|
+
const triggered = new Set(options.triggeredItems ?? []);
|
|
984
|
+
const removeCandidates = [];
|
|
985
|
+
for (const item of options.declaredItems) {
|
|
986
|
+
if (!triggered.has(item.name)) {
|
|
987
|
+
const prior = existingUntriggered.get(item.name) ?? 0;
|
|
988
|
+
const count = prior + 1;
|
|
989
|
+
existingUntriggered.set(item.name, count);
|
|
990
|
+
if (count >= 4) {
|
|
991
|
+
removeCandidates.push({ item, weeksSilent: count });
|
|
992
|
+
}
|
|
993
|
+
} else {
|
|
994
|
+
existingUntriggered.set(item.name, 0);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
if (removeCandidates.length > 0) {
|
|
998
|
+
lines.push("### Consider removing");
|
|
999
|
+
lines.push("");
|
|
1000
|
+
lines.push("These items are declared in the worldmodel but haven't triggered in multiple reads.");
|
|
1001
|
+
lines.push("Either the team has internalized them (the rule is redundant) or they haven't been tested.");
|
|
1002
|
+
lines.push("A lean worldmodel with 5 sharp invariants is stronger than a bloated one with 20.");
|
|
1003
|
+
lines.push("");
|
|
1004
|
+
for (const { item, weeksSilent } of removeCandidates) {
|
|
1005
|
+
lines.push(
|
|
1006
|
+
`- **${item.name}** (${item.type}) \u2014 hasn't triggered in ${weeksSilent} reads. Internalized or untested? Review whether it still earns its place.`
|
|
1007
|
+
);
|
|
1008
|
+
}
|
|
1009
|
+
lines.push("");
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
if (options?.triggeredItems && options.triggeredItems.length > 0) {
|
|
1013
|
+
lines.push("### Keep (recently active)");
|
|
1014
|
+
lines.push("");
|
|
1015
|
+
lines.push("These worldmodel items triggered governance in the most recent read. They're earning their place.");
|
|
1016
|
+
lines.push("");
|
|
1017
|
+
for (const name of options.triggeredItems) {
|
|
1018
|
+
lines.push(`- **${name}** \u2014 triggered this read. Holding.`);
|
|
1019
|
+
}
|
|
1020
|
+
lines.push("");
|
|
1021
|
+
}
|
|
1022
|
+
lines.push("---");
|
|
1023
|
+
lines.push("");
|
|
1024
|
+
lines.push("## Pattern persistence (all observed)");
|
|
1025
|
+
lines.push("");
|
|
1026
|
+
for (const p of persistence) {
|
|
1027
|
+
const status = p.occurrences >= 4 ? "**persistent**" : p.occurrences >= 2 ? "recurring" : "observed once";
|
|
1028
|
+
lines.push(`### ${p.name}`);
|
|
1029
|
+
lines.push(`- Status: ${status}`);
|
|
1030
|
+
lines.push(`- Observed ${p.occurrences} time${p.occurrences > 1 ? "s" : ""}: ${p.dates.join(", ")}`);
|
|
1031
|
+
lines.push("");
|
|
1032
|
+
}
|
|
1033
|
+
lines.push("---");
|
|
1034
|
+
lines.push("");
|
|
1035
|
+
lines.push("<!-- untriggered_counts (machine-readable, do not edit)");
|
|
1036
|
+
for (const [name, count] of existingUntriggered.entries()) {
|
|
1037
|
+
lines.push(`${name}=${count}`);
|
|
1038
|
+
}
|
|
1039
|
+
lines.push("-->");
|
|
1040
|
+
(0, import_fs2.writeFileSync)(filepath, lines.join("\n"), "utf-8");
|
|
1041
|
+
return filepath;
|
|
1042
|
+
}
|
|
1043
|
+
function loadUntriggeredCounts(filepath) {
|
|
1044
|
+
const counts = /* @__PURE__ */ new Map();
|
|
1045
|
+
if (!(0, import_fs2.existsSync)(filepath)) return counts;
|
|
1046
|
+
try {
|
|
1047
|
+
const content = (0, import_fs2.readFileSync)(filepath, "utf-8");
|
|
1048
|
+
const match = content.match(
|
|
1049
|
+
/<!-- untriggered_counts[\s\S]*?-->/
|
|
1050
|
+
);
|
|
1051
|
+
if (match) {
|
|
1052
|
+
const lines = match[0].split("\n");
|
|
1053
|
+
for (const line of lines) {
|
|
1054
|
+
const eq = line.match(/^([^=]+)=(\d+)$/);
|
|
1055
|
+
if (eq) {
|
|
1056
|
+
counts.set(eq[1], parseInt(eq[2], 10));
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
} catch {
|
|
1061
|
+
}
|
|
1062
|
+
return counts;
|
|
1063
|
+
}
|
|
1064
|
+
function loadPriorReads(exocortexDir) {
|
|
1065
|
+
const dir = (0, import_path2.resolve)(exocortexDir, "radiant", "reads");
|
|
1066
|
+
if (!(0, import_fs2.existsSync)(dir)) return [];
|
|
1067
|
+
const files = (0, import_fs2.readdirSync)(dir).filter((f) => f.endsWith(".md")).sort();
|
|
1068
|
+
const reads = [];
|
|
1069
|
+
for (const filename of files) {
|
|
1070
|
+
const filepath = (0, import_path2.join)(dir, filename);
|
|
1071
|
+
const content = (0, import_fs2.readFileSync)(filepath, "utf-8");
|
|
1072
|
+
const date = filename.replace(".md", "");
|
|
1073
|
+
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
1074
|
+
const frontmatter = fmMatch ? fmMatch[1] : "";
|
|
1075
|
+
const patternNames = [];
|
|
1076
|
+
const nameMatches = frontmatter.matchAll(/- name: ["']?([^"'\n]+)["']?/g);
|
|
1077
|
+
for (const m of nameMatches) {
|
|
1078
|
+
patternNames.push(m[1].trim());
|
|
1079
|
+
}
|
|
1080
|
+
reads.push({ date, filename, patternNames, frontmatter });
|
|
1081
|
+
}
|
|
1082
|
+
return reads;
|
|
1083
|
+
}
|
|
1084
|
+
function computePersistence(priorReads, currentPatternNames) {
|
|
1085
|
+
const allPatterns = /* @__PURE__ */ new Map();
|
|
1086
|
+
for (const read of priorReads) {
|
|
1087
|
+
for (const name of read.patternNames) {
|
|
1088
|
+
const dates = allPatterns.get(name) ?? [];
|
|
1089
|
+
if (!dates.includes(read.date)) dates.push(read.date);
|
|
1090
|
+
allPatterns.set(name, dates);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1094
|
+
for (const name of currentPatternNames) {
|
|
1095
|
+
const dates = allPatterns.get(name) ?? [];
|
|
1096
|
+
if (!dates.includes(today)) dates.push(today);
|
|
1097
|
+
allPatterns.set(name, dates);
|
|
1098
|
+
}
|
|
1099
|
+
return Array.from(allPatterns.entries()).map(([name, dates]) => ({
|
|
1100
|
+
name,
|
|
1101
|
+
occurrences: dates.length,
|
|
1102
|
+
dates: dates.sort()
|
|
1103
|
+
})).sort((a, b) => b.occurrences - a.occurrences);
|
|
1104
|
+
}
|
|
1105
|
+
function formatPriorReadsForPrompt(priorReads) {
|
|
1106
|
+
if (priorReads.length === 0) return "";
|
|
1107
|
+
const lines = [
|
|
1108
|
+
"## Prior Radiant reads (history)",
|
|
1109
|
+
"",
|
|
1110
|
+
`Radiant has run ${priorReads.length} time${priorReads.length > 1 ? "s" : ""} before on this scope.`,
|
|
1111
|
+
"If you see patterns that appeared in prior reads, note their persistence.",
|
|
1112
|
+
"Patterns that recur across 3+ reads are strong candidates for declaration in the strategy file.",
|
|
1113
|
+
""
|
|
1114
|
+
];
|
|
1115
|
+
for (const read of priorReads.slice(-4)) {
|
|
1116
|
+
lines.push(`### Read from ${read.date}`);
|
|
1117
|
+
if (read.patternNames.length > 0) {
|
|
1118
|
+
lines.push(`Patterns observed: ${read.patternNames.join(", ")}`);
|
|
1119
|
+
} else {
|
|
1120
|
+
lines.push("No patterns extracted from frontmatter.");
|
|
1121
|
+
}
|
|
1122
|
+
lines.push("");
|
|
1123
|
+
}
|
|
1124
|
+
return lines.join("\n");
|
|
1125
|
+
}
|
|
1126
|
+
var import_fs2, import_path2;
|
|
1127
|
+
var init_palace = __esm({
|
|
1128
|
+
"src/radiant/memory/palace.ts"() {
|
|
1129
|
+
"use strict";
|
|
1130
|
+
import_fs2 = require("fs");
|
|
1131
|
+
import_path2 = require("path");
|
|
1132
|
+
}
|
|
1133
|
+
});
|
|
1134
|
+
|
|
1135
|
+
// src/engine/text-utils.ts
|
|
1136
|
+
function normalizeEventText(event) {
|
|
1137
|
+
return [
|
|
1138
|
+
event.intent,
|
|
1139
|
+
event.tool ?? "",
|
|
1140
|
+
event.scope ?? ""
|
|
1141
|
+
].join(" ").toLowerCase();
|
|
1142
|
+
}
|
|
1143
|
+
function extractKeywords(text, minLength = 3) {
|
|
1144
|
+
return text.toLowerCase().split(/\s+/).filter((w) => w.length > minLength);
|
|
1145
|
+
}
|
|
1146
|
+
function matchesAllKeywords(eventText, ruleText) {
|
|
1147
|
+
const keywords = extractKeywords(ruleText);
|
|
1148
|
+
if (keywords.length === 0) return false;
|
|
1149
|
+
return keywords.every((kw) => eventText.includes(kw));
|
|
1150
|
+
}
|
|
1151
|
+
function matchesKeywordThreshold(eventText, ruleText, threshold = 0.5) {
|
|
1152
|
+
const keywords = extractKeywords(ruleText);
|
|
1153
|
+
if (keywords.length === 0) return false;
|
|
1154
|
+
const matched = keywords.filter((kw) => eventText.includes(kw));
|
|
1155
|
+
return matched.length >= Math.ceil(keywords.length * threshold);
|
|
1156
|
+
}
|
|
1157
|
+
function tokenSimilarity(a, b) {
|
|
1158
|
+
const tokensA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
1159
|
+
const tokensB = new Set(b.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
1160
|
+
if (tokensA.size === 0 || tokensB.size === 0) return 0;
|
|
1161
|
+
let intersection = 0;
|
|
1162
|
+
for (const t of tokensA) {
|
|
1163
|
+
if (tokensB.has(t)) intersection++;
|
|
1164
|
+
}
|
|
1165
|
+
const union = (/* @__PURE__ */ new Set([...tokensA, ...tokensB])).size;
|
|
1166
|
+
return union > 0 ? intersection / union : 0;
|
|
1167
|
+
}
|
|
1168
|
+
var init_text_utils = __esm({
|
|
1169
|
+
"src/engine/text-utils.ts"() {
|
|
1170
|
+
"use strict";
|
|
1171
|
+
}
|
|
1172
|
+
});
|
|
1173
|
+
|
|
1174
|
+
// src/engine/plan-engine.ts
|
|
1175
|
+
function keywordMatch(eventText, step) {
|
|
1176
|
+
const stepText = [
|
|
1177
|
+
step.label,
|
|
1178
|
+
step.description ?? "",
|
|
1179
|
+
...step.tags ?? []
|
|
1180
|
+
].join(" ");
|
|
1181
|
+
return matchesKeywordThreshold(eventText, stepText, 0.5);
|
|
1182
|
+
}
|
|
1183
|
+
function tokenSimilarity2(a, b) {
|
|
1184
|
+
return tokenSimilarity(a, b);
|
|
1185
|
+
}
|
|
1186
|
+
function findMatchingStep(eventText, event, steps) {
|
|
1187
|
+
const pendingOrActive = steps.filter((s) => s.status === "pending" || s.status === "active");
|
|
1188
|
+
if (pendingOrActive.length === 0) {
|
|
1189
|
+
return { matched: null, closest: null, closestScore: 0 };
|
|
1190
|
+
}
|
|
1191
|
+
for (const step of pendingOrActive) {
|
|
1192
|
+
if (keywordMatch(eventText, step)) {
|
|
1193
|
+
if (step.tools && event.tool && !step.tools.includes(event.tool)) {
|
|
1194
|
+
continue;
|
|
1195
|
+
}
|
|
1196
|
+
return { matched: step, closest: step, closestScore: 1 };
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
const intentText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ");
|
|
1200
|
+
let bestStep = null;
|
|
1201
|
+
let bestScore = 0;
|
|
1202
|
+
for (const step of pendingOrActive) {
|
|
1203
|
+
const stepText = [step.label, step.description ?? "", ...step.tags ?? []].join(" ");
|
|
1204
|
+
const score = tokenSimilarity2(intentText, stepText);
|
|
1205
|
+
if (score > bestScore) {
|
|
1206
|
+
bestScore = score;
|
|
1207
|
+
bestStep = step;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
const SIMILARITY_THRESHOLD = 0.35;
|
|
1211
|
+
if (bestScore >= SIMILARITY_THRESHOLD && bestStep) {
|
|
1212
|
+
if (bestStep.tools && event.tool && !bestStep.tools.includes(event.tool)) {
|
|
1213
|
+
return { matched: null, closest: bestStep, closestScore: bestScore };
|
|
1214
|
+
}
|
|
1215
|
+
return { matched: bestStep, closest: bestStep, closestScore: bestScore };
|
|
1216
|
+
}
|
|
1217
|
+
return { matched: null, closest: bestStep, closestScore: bestScore };
|
|
1218
|
+
}
|
|
1219
|
+
function isSequenceValid(step, plan) {
|
|
1220
|
+
if (!plan.sequential) return true;
|
|
1221
|
+
if (!step.requires || step.requires.length === 0) return true;
|
|
1222
|
+
return step.requires.every((reqId) => {
|
|
1223
|
+
const reqStep = plan.steps.find((s) => s.id === reqId);
|
|
1224
|
+
return reqStep?.status === "completed";
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
function checkConstraints(event, eventText, constraints) {
|
|
1228
|
+
const checks = [];
|
|
1229
|
+
for (const constraint of constraints) {
|
|
1230
|
+
if (constraint.type === "approval") {
|
|
1231
|
+
if (constraint.trigger && eventText.includes(constraint.trigger.substring(0, 10).toLowerCase())) {
|
|
1232
|
+
checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
|
|
1233
|
+
return { violated: constraint, checks };
|
|
1234
|
+
}
|
|
1235
|
+
const keywords = constraint.description.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
|
|
1236
|
+
const relevant = keywords.some((kw) => eventText.includes(kw));
|
|
1237
|
+
if (relevant) {
|
|
1238
|
+
checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
|
|
1239
|
+
return { violated: constraint, checks };
|
|
1240
|
+
}
|
|
1241
|
+
checks.push({ constraintId: constraint.id, passed: true });
|
|
1242
|
+
continue;
|
|
1243
|
+
}
|
|
1244
|
+
if (constraint.type === "scope" && constraint.trigger) {
|
|
1245
|
+
const keywords = extractKeywords(constraint.trigger);
|
|
1246
|
+
const violated = keywords.length > 0 && keywords.every((kw) => eventText.includes(kw));
|
|
1247
|
+
checks.push({
|
|
1248
|
+
constraintId: constraint.id,
|
|
1249
|
+
passed: !violated,
|
|
1250
|
+
reason: violated ? constraint.description : void 0
|
|
1251
|
+
});
|
|
1252
|
+
if (violated) {
|
|
1253
|
+
return { violated: constraint, checks };
|
|
1254
|
+
}
|
|
1255
|
+
continue;
|
|
1256
|
+
}
|
|
1257
|
+
checks.push({ constraintId: constraint.id, passed: true });
|
|
1258
|
+
}
|
|
1259
|
+
return { violated: null, checks };
|
|
1260
|
+
}
|
|
1261
|
+
function getPlanProgress(plan) {
|
|
1262
|
+
const completed = plan.steps.filter((s) => s.status === "completed").length;
|
|
1263
|
+
const total = plan.steps.length;
|
|
1264
|
+
return {
|
|
1265
|
+
completed,
|
|
1266
|
+
total,
|
|
1267
|
+
percentage: total > 0 ? Math.round(completed / total * 100) : 0
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
function evaluatePlan(event, plan) {
|
|
1271
|
+
const progress = getPlanProgress(plan);
|
|
1272
|
+
if (plan.expires_at) {
|
|
1273
|
+
const expiresAt = new Date(plan.expires_at).getTime();
|
|
1274
|
+
if (Date.now() > expiresAt) {
|
|
1275
|
+
return {
|
|
1276
|
+
allowed: true,
|
|
1277
|
+
status: "PLAN_COMPLETE",
|
|
1278
|
+
reason: "Plan has expired.",
|
|
1279
|
+
progress
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
if (progress.completed === progress.total) {
|
|
1284
|
+
return {
|
|
1285
|
+
allowed: true,
|
|
1286
|
+
status: "PLAN_COMPLETE",
|
|
1287
|
+
reason: "All plan steps are completed.",
|
|
1288
|
+
progress
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
const eventText = normalizeEventText(event);
|
|
1292
|
+
const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
|
|
1293
|
+
if (!matched) {
|
|
1294
|
+
return {
|
|
1295
|
+
allowed: false,
|
|
1296
|
+
status: "OFF_PLAN",
|
|
1297
|
+
reason: "Action does not match any plan step.",
|
|
1298
|
+
closestStep: closest?.label,
|
|
1299
|
+
similarityScore: closestScore,
|
|
1300
|
+
progress
|
|
1301
|
+
};
|
|
1302
|
+
}
|
|
1303
|
+
if (!isSequenceValid(matched, plan)) {
|
|
1304
|
+
const pendingDeps = (matched.requires ?? []).filter((reqId) => plan.steps.find((s) => s.id === reqId)?.status !== "completed").join(", ");
|
|
1305
|
+
return {
|
|
1306
|
+
allowed: false,
|
|
1307
|
+
status: "OFF_PLAN",
|
|
1308
|
+
reason: `Step "${matched.label}" requires completion of: ${pendingDeps}`,
|
|
1309
|
+
matchedStep: matched.id,
|
|
1310
|
+
progress
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
const { violated } = checkConstraints(event, eventText, plan.constraints);
|
|
1314
|
+
if (violated) {
|
|
1315
|
+
return {
|
|
1316
|
+
allowed: false,
|
|
1317
|
+
status: "CONSTRAINT_VIOLATED",
|
|
1318
|
+
reason: violated.description,
|
|
1319
|
+
matchedStep: matched.id,
|
|
1320
|
+
progress
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
return {
|
|
1324
|
+
allowed: true,
|
|
1325
|
+
status: "ON_PLAN",
|
|
1326
|
+
reason: `Matches step: ${matched.label}`,
|
|
1327
|
+
matchedStep: matched.id,
|
|
1328
|
+
progress
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
function buildPlanCheck(event, plan, verdict) {
|
|
1332
|
+
const eventText = normalizeEventText(event);
|
|
1333
|
+
const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
|
|
1334
|
+
const { checks: constraintChecks } = checkConstraints(event, eventText, plan.constraints);
|
|
1335
|
+
const progress = getPlanProgress(plan);
|
|
1336
|
+
return {
|
|
1337
|
+
planId: plan.plan_id,
|
|
1338
|
+
matched: !!matched,
|
|
1339
|
+
matchedStepId: matched?.id,
|
|
1340
|
+
matchedStepLabel: matched?.label,
|
|
1341
|
+
closestStepId: !matched ? closest?.id : void 0,
|
|
1342
|
+
closestStepLabel: !matched ? closest?.label : void 0,
|
|
1343
|
+
similarityScore: !matched ? closestScore : void 0,
|
|
1344
|
+
sequenceValid: matched ? isSequenceValid(matched, plan) : void 0,
|
|
1345
|
+
constraintsChecked: constraintChecks,
|
|
1346
|
+
progress: { completed: progress.completed, total: progress.total }
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
var init_plan_engine = __esm({
|
|
1350
|
+
"src/engine/plan-engine.ts"() {
|
|
1351
|
+
"use strict";
|
|
1352
|
+
init_text_utils();
|
|
1353
|
+
}
|
|
1354
|
+
});
|
|
1355
|
+
|
|
1356
|
+
// src/engine/guard-engine.ts
|
|
1357
|
+
function levelRequiresConfirmation(level, actionType) {
|
|
1358
|
+
if (level === "strict") return true;
|
|
1359
|
+
if (level === "standard") {
|
|
1360
|
+
return actionType === "delete" || actionType === "credential-access";
|
|
1361
|
+
}
|
|
1362
|
+
return false;
|
|
1363
|
+
}
|
|
1364
|
+
function isExternalScope(scope) {
|
|
1365
|
+
const internalPatterns = [
|
|
1366
|
+
/^\.?\/?src\//i,
|
|
1367
|
+
/^\.?\/?lib\//i,
|
|
1368
|
+
/^\.?\/?app\//i,
|
|
1369
|
+
/^\.?\/?components\//i,
|
|
1370
|
+
/^\.?\/?pages\//i,
|
|
1371
|
+
/^\.?\/?public\//i,
|
|
1372
|
+
/^\.?\/?assets\//i,
|
|
1373
|
+
/^\.\//
|
|
1374
|
+
];
|
|
1375
|
+
return !internalPatterns.some((p) => p.test(scope));
|
|
1376
|
+
}
|
|
1377
|
+
function evaluateGuard(event, world, options = {}) {
|
|
1378
|
+
const startTime = performance.now();
|
|
1379
|
+
const level = options.level ?? "standard";
|
|
1380
|
+
const includeTrace = options.trace ?? false;
|
|
1381
|
+
if (!event.intent || typeof event.intent !== "string") {
|
|
1382
|
+
return {
|
|
1383
|
+
status: "BLOCK",
|
|
1384
|
+
reason: "GuardEvent.intent is required and must be a string",
|
|
1385
|
+
ruleId: "safety-input-validation",
|
|
1386
|
+
evidence: {
|
|
1387
|
+
worldId: world.world?.world_id ?? "",
|
|
1388
|
+
worldName: world.world?.name ?? "",
|
|
1389
|
+
worldVersion: world.world?.version ?? "",
|
|
1390
|
+
evaluatedAt: Date.now(),
|
|
1391
|
+
invariantsSatisfied: 0,
|
|
1392
|
+
invariantsTotal: 0,
|
|
1393
|
+
guardsMatched: [],
|
|
1394
|
+
rulesMatched: [],
|
|
1395
|
+
enforcementLevel: level
|
|
1396
|
+
}
|
|
1397
|
+
};
|
|
1398
|
+
}
|
|
1399
|
+
const inputLength = event.intent.length + (event.tool?.length ?? 0) + (event.scope?.length ?? 0) + (event.payload ? JSON.stringify(event.payload).length : 0);
|
|
1400
|
+
if (inputLength > MAX_INPUT_LENGTH) {
|
|
1401
|
+
return {
|
|
1402
|
+
status: "BLOCK",
|
|
1403
|
+
reason: `Input exceeds maximum allowed length (${MAX_INPUT_LENGTH} characters)`,
|
|
1404
|
+
ruleId: "safety-input-length",
|
|
1405
|
+
evidence: {
|
|
1406
|
+
worldId: world.world?.world_id ?? "",
|
|
1407
|
+
worldName: world.world?.name ?? "",
|
|
1408
|
+
worldVersion: world.world?.version ?? "",
|
|
1409
|
+
evaluatedAt: Date.now(),
|
|
1410
|
+
invariantsSatisfied: 0,
|
|
1411
|
+
invariantsTotal: 0,
|
|
1412
|
+
guardsMatched: [],
|
|
1413
|
+
rulesMatched: [],
|
|
1414
|
+
enforcementLevel: level
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
const eventText = normalizeEventText(event);
|
|
1419
|
+
const invariantChecks = [];
|
|
1420
|
+
const safetyChecks = [];
|
|
1421
|
+
let planCheckResult;
|
|
1422
|
+
const roleChecks = [];
|
|
1423
|
+
const guardChecks = [];
|
|
1424
|
+
const kernelRuleChecks = [];
|
|
1425
|
+
const levelChecks = [];
|
|
1426
|
+
let decidingLayer = "default-allow";
|
|
1427
|
+
let decidingId;
|
|
1428
|
+
const guardsMatched = [];
|
|
1429
|
+
const rulesMatched = [];
|
|
1430
|
+
if (options.emergencyOverride) {
|
|
1431
|
+
checkInvariantCoverage(world, invariantChecks);
|
|
1432
|
+
return buildVerdict(
|
|
1433
|
+
"ALLOW",
|
|
1434
|
+
void 0,
|
|
1435
|
+
"emergency-override",
|
|
1436
|
+
"Emergency override active \u2014 all governance rules suspended. Platform constraints still apply.",
|
|
1437
|
+
world,
|
|
1438
|
+
level,
|
|
1439
|
+
invariantChecks,
|
|
1440
|
+
guardsMatched,
|
|
1441
|
+
rulesMatched,
|
|
1442
|
+
includeTrace ? buildTrace(
|
|
1443
|
+
invariantChecks,
|
|
1444
|
+
safetyChecks,
|
|
1445
|
+
planCheckResult,
|
|
1446
|
+
roleChecks,
|
|
1447
|
+
guardChecks,
|
|
1448
|
+
kernelRuleChecks,
|
|
1449
|
+
levelChecks,
|
|
1450
|
+
"session-allowlist",
|
|
1451
|
+
"emergency-override",
|
|
1452
|
+
startTime
|
|
1453
|
+
) : void 0,
|
|
1454
|
+
event.intent
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
checkInvariantCoverage(world, invariantChecks);
|
|
1458
|
+
if (event.roleId && options.agentStates) {
|
|
1459
|
+
const agentState = options.agentStates.get(event.roleId);
|
|
1460
|
+
if (agentState && agentState.cooldownRemaining > 0) {
|
|
1461
|
+
decidingLayer = "safety";
|
|
1462
|
+
decidingId = `penalize-cooldown-${event.roleId}`;
|
|
1463
|
+
const verdict = buildVerdict(
|
|
1464
|
+
"PENALIZE",
|
|
1465
|
+
`Agent "${event.roleId}" is frozen for ${agentState.cooldownRemaining} more round(s) due to prior penalty.`,
|
|
1466
|
+
`penalize-cooldown-${event.roleId}`,
|
|
1467
|
+
void 0,
|
|
1468
|
+
world,
|
|
1469
|
+
level,
|
|
1470
|
+
invariantChecks,
|
|
1471
|
+
guardsMatched,
|
|
1472
|
+
rulesMatched,
|
|
1473
|
+
includeTrace ? buildTrace(
|
|
1474
|
+
invariantChecks,
|
|
1475
|
+
safetyChecks,
|
|
1476
|
+
planCheckResult,
|
|
1477
|
+
roleChecks,
|
|
1478
|
+
guardChecks,
|
|
1479
|
+
kernelRuleChecks,
|
|
1480
|
+
levelChecks,
|
|
1481
|
+
decidingLayer,
|
|
1482
|
+
decidingId,
|
|
1483
|
+
startTime
|
|
1484
|
+
) : void 0
|
|
1485
|
+
);
|
|
1486
|
+
verdict.intentRecord = {
|
|
1487
|
+
originalIntent: event.intent,
|
|
1488
|
+
finalAction: "blocked (agent frozen)",
|
|
1489
|
+
enforcement: "PENALIZE",
|
|
1490
|
+
consequence: { type: "freeze", rounds: agentState.cooldownRemaining, description: "Agent still in cooldown from prior penalty" }
|
|
1491
|
+
};
|
|
1492
|
+
return verdict;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
if (options.sessionAllowlist) {
|
|
1496
|
+
const key = eventToAllowlistKey(event);
|
|
1497
|
+
if (options.sessionAllowlist.has(key)) {
|
|
1498
|
+
decidingLayer = "session-allowlist";
|
|
1499
|
+
decidingId = `allowlist:${key}`;
|
|
1500
|
+
return buildVerdict(
|
|
1501
|
+
"ALLOW",
|
|
1502
|
+
void 0,
|
|
1503
|
+
`allowlist:${key}`,
|
|
1504
|
+
void 0,
|
|
1505
|
+
world,
|
|
1506
|
+
level,
|
|
1507
|
+
invariantChecks,
|
|
1508
|
+
guardsMatched,
|
|
1509
|
+
rulesMatched,
|
|
1510
|
+
includeTrace ? buildTrace(
|
|
1511
|
+
invariantChecks,
|
|
1512
|
+
safetyChecks,
|
|
1513
|
+
planCheckResult,
|
|
1514
|
+
roleChecks,
|
|
1515
|
+
guardChecks,
|
|
1516
|
+
kernelRuleChecks,
|
|
1517
|
+
levelChecks,
|
|
1518
|
+
decidingLayer,
|
|
1519
|
+
decidingId,
|
|
1520
|
+
startTime
|
|
1521
|
+
) : void 0,
|
|
1522
|
+
event.intent
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
const safetyVerdict = checkSafety(event, eventText, safetyChecks);
|
|
1527
|
+
if (safetyVerdict) {
|
|
1528
|
+
decidingLayer = "safety";
|
|
1529
|
+
decidingId = safetyVerdict.ruleId;
|
|
1530
|
+
return buildVerdict(
|
|
1531
|
+
safetyVerdict.status,
|
|
1532
|
+
safetyVerdict.reason,
|
|
1533
|
+
safetyVerdict.ruleId,
|
|
1534
|
+
void 0,
|
|
1535
|
+
world,
|
|
1536
|
+
level,
|
|
1537
|
+
invariantChecks,
|
|
1538
|
+
guardsMatched,
|
|
1539
|
+
rulesMatched,
|
|
1540
|
+
includeTrace ? buildTrace(
|
|
1541
|
+
invariantChecks,
|
|
1542
|
+
safetyChecks,
|
|
1543
|
+
planCheckResult,
|
|
1544
|
+
roleChecks,
|
|
1545
|
+
guardChecks,
|
|
1546
|
+
kernelRuleChecks,
|
|
1547
|
+
levelChecks,
|
|
1548
|
+
decidingLayer,
|
|
1549
|
+
decidingId,
|
|
1550
|
+
startTime
|
|
1551
|
+
) : void 0,
|
|
1552
|
+
event.intent
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
if (options.plan) {
|
|
1556
|
+
const planVerdict = evaluatePlan(event, options.plan);
|
|
1557
|
+
planCheckResult = buildPlanCheck(event, options.plan, planVerdict);
|
|
1558
|
+
if (!planVerdict.allowed && planVerdict.status !== "PLAN_COMPLETE") {
|
|
1559
|
+
decidingLayer = "plan-enforcement";
|
|
1560
|
+
decidingId = `plan-${options.plan.plan_id}`;
|
|
1561
|
+
const planStatus = planVerdict.status === "CONSTRAINT_VIOLATED" ? "PAUSE" : "BLOCK";
|
|
1562
|
+
let reason = planVerdict.reason ?? "Action blocked by plan.";
|
|
1563
|
+
if (planVerdict.status === "OFF_PLAN" && planVerdict.closestStep) {
|
|
1564
|
+
reason += ` Closest step: "${planVerdict.closestStep}" (similarity: ${(planVerdict.similarityScore ?? 0).toFixed(2)})`;
|
|
1565
|
+
}
|
|
1566
|
+
return buildVerdict(
|
|
1567
|
+
planStatus,
|
|
1568
|
+
reason,
|
|
1569
|
+
`plan-${options.plan.plan_id}`,
|
|
1570
|
+
void 0,
|
|
1571
|
+
world,
|
|
1572
|
+
level,
|
|
1573
|
+
invariantChecks,
|
|
1574
|
+
guardsMatched,
|
|
1575
|
+
rulesMatched,
|
|
1576
|
+
includeTrace ? buildTrace(
|
|
1577
|
+
invariantChecks,
|
|
1578
|
+
safetyChecks,
|
|
1579
|
+
planCheckResult,
|
|
1580
|
+
roleChecks,
|
|
1581
|
+
guardChecks,
|
|
1582
|
+
kernelRuleChecks,
|
|
1583
|
+
levelChecks,
|
|
1584
|
+
decidingLayer,
|
|
1585
|
+
decidingId,
|
|
1586
|
+
startTime
|
|
1587
|
+
) : void 0,
|
|
1588
|
+
event.intent
|
|
1589
|
+
);
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
const roleVerdict = checkRoleRules(event, eventText, world, roleChecks);
|
|
1593
|
+
if (roleVerdict) {
|
|
1594
|
+
decidingLayer = "role";
|
|
1595
|
+
decidingId = roleVerdict.ruleId;
|
|
1596
|
+
return buildVerdict(
|
|
1597
|
+
roleVerdict.status,
|
|
1598
|
+
roleVerdict.reason,
|
|
1599
|
+
roleVerdict.ruleId,
|
|
1600
|
+
void 0,
|
|
1601
|
+
world,
|
|
1602
|
+
level,
|
|
1603
|
+
invariantChecks,
|
|
1604
|
+
guardsMatched,
|
|
1605
|
+
rulesMatched,
|
|
1606
|
+
includeTrace ? buildTrace(
|
|
1607
|
+
invariantChecks,
|
|
1608
|
+
safetyChecks,
|
|
1609
|
+
planCheckResult,
|
|
1610
|
+
roleChecks,
|
|
1611
|
+
guardChecks,
|
|
1612
|
+
kernelRuleChecks,
|
|
1613
|
+
levelChecks,
|
|
1614
|
+
decidingLayer,
|
|
1615
|
+
decidingId,
|
|
1616
|
+
startTime
|
|
1617
|
+
) : void 0,
|
|
1618
|
+
event.intent
|
|
1619
|
+
);
|
|
1620
|
+
}
|
|
1621
|
+
const guardVerdict = checkGuards(event, eventText, world, guardChecks, guardsMatched);
|
|
1622
|
+
if (guardVerdict) {
|
|
1623
|
+
if (guardVerdict.status !== "ALLOW") {
|
|
1624
|
+
decidingLayer = "guard";
|
|
1625
|
+
decidingId = guardVerdict.ruleId;
|
|
1626
|
+
const intentRecord = {
|
|
1627
|
+
originalIntent: event.intent,
|
|
1628
|
+
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",
|
|
1629
|
+
ruleApplied: guardVerdict.ruleId,
|
|
1630
|
+
enforcement: guardVerdict.status,
|
|
1631
|
+
modifiedTo: guardVerdict.modifiedTo,
|
|
1632
|
+
consequence: guardVerdict.consequence,
|
|
1633
|
+
reward: guardVerdict.reward
|
|
1634
|
+
};
|
|
1635
|
+
const verdict = buildVerdict(
|
|
1636
|
+
guardVerdict.status,
|
|
1637
|
+
guardVerdict.reason,
|
|
1638
|
+
guardVerdict.ruleId,
|
|
1639
|
+
void 0,
|
|
1640
|
+
world,
|
|
1641
|
+
level,
|
|
1642
|
+
invariantChecks,
|
|
1643
|
+
guardsMatched,
|
|
1644
|
+
rulesMatched,
|
|
1645
|
+
includeTrace ? buildTrace(
|
|
1646
|
+
invariantChecks,
|
|
1647
|
+
safetyChecks,
|
|
1648
|
+
planCheckResult,
|
|
1649
|
+
roleChecks,
|
|
1650
|
+
guardChecks,
|
|
1651
|
+
kernelRuleChecks,
|
|
1652
|
+
levelChecks,
|
|
1653
|
+
decidingLayer,
|
|
1654
|
+
decidingId,
|
|
1655
|
+
startTime
|
|
1656
|
+
) : void 0,
|
|
1657
|
+
event.intent
|
|
1658
|
+
);
|
|
1659
|
+
verdict.intentRecord = intentRecord;
|
|
1660
|
+
if (guardVerdict.consequence) verdict.consequence = guardVerdict.consequence;
|
|
1661
|
+
if (guardVerdict.reward) verdict.reward = guardVerdict.reward;
|
|
1662
|
+
return verdict;
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
const kernelVerdict = checkKernelRules(eventText, world, kernelRuleChecks, rulesMatched);
|
|
1666
|
+
if (kernelVerdict) {
|
|
1667
|
+
decidingLayer = "kernel-rule";
|
|
1668
|
+
decidingId = kernelVerdict.ruleId;
|
|
1669
|
+
return buildVerdict(
|
|
1670
|
+
kernelVerdict.status,
|
|
1671
|
+
kernelVerdict.reason,
|
|
1672
|
+
kernelVerdict.ruleId,
|
|
1673
|
+
void 0,
|
|
1674
|
+
world,
|
|
1675
|
+
level,
|
|
1676
|
+
invariantChecks,
|
|
1677
|
+
guardsMatched,
|
|
1678
|
+
rulesMatched,
|
|
1679
|
+
includeTrace ? buildTrace(
|
|
1680
|
+
invariantChecks,
|
|
1681
|
+
safetyChecks,
|
|
1682
|
+
planCheckResult,
|
|
1683
|
+
roleChecks,
|
|
1684
|
+
guardChecks,
|
|
1685
|
+
kernelRuleChecks,
|
|
1686
|
+
levelChecks,
|
|
1687
|
+
decidingLayer,
|
|
1688
|
+
decidingId,
|
|
1689
|
+
startTime
|
|
1690
|
+
) : void 0,
|
|
1691
|
+
event.intent
|
|
1692
|
+
);
|
|
1693
|
+
}
|
|
1694
|
+
const levelVerdict = checkLevelConstraints(event, level, levelChecks);
|
|
1695
|
+
if (levelVerdict) {
|
|
1696
|
+
decidingLayer = "level-constraint";
|
|
1697
|
+
decidingId = levelVerdict.ruleId;
|
|
1698
|
+
return buildVerdict(
|
|
1699
|
+
levelVerdict.status,
|
|
1700
|
+
levelVerdict.reason,
|
|
1701
|
+
levelVerdict.ruleId,
|
|
1702
|
+
void 0,
|
|
1703
|
+
world,
|
|
1704
|
+
level,
|
|
1705
|
+
invariantChecks,
|
|
1706
|
+
guardsMatched,
|
|
1707
|
+
rulesMatched,
|
|
1708
|
+
includeTrace ? buildTrace(
|
|
1709
|
+
invariantChecks,
|
|
1710
|
+
safetyChecks,
|
|
1711
|
+
planCheckResult,
|
|
1712
|
+
roleChecks,
|
|
1713
|
+
guardChecks,
|
|
1714
|
+
kernelRuleChecks,
|
|
1715
|
+
levelChecks,
|
|
1716
|
+
decidingLayer,
|
|
1717
|
+
decidingId,
|
|
1718
|
+
startTime
|
|
1719
|
+
) : void 0,
|
|
1720
|
+
event.intent
|
|
1721
|
+
);
|
|
1722
|
+
}
|
|
1723
|
+
const warning = guardVerdict?.warning;
|
|
1724
|
+
return buildVerdict(
|
|
1725
|
+
"ALLOW",
|
|
1726
|
+
void 0,
|
|
1727
|
+
void 0,
|
|
1728
|
+
warning,
|
|
1729
|
+
world,
|
|
1730
|
+
level,
|
|
1731
|
+
invariantChecks,
|
|
1732
|
+
guardsMatched,
|
|
1733
|
+
rulesMatched,
|
|
1734
|
+
includeTrace ? buildTrace(
|
|
1735
|
+
invariantChecks,
|
|
1736
|
+
safetyChecks,
|
|
1737
|
+
planCheckResult,
|
|
1738
|
+
roleChecks,
|
|
1739
|
+
guardChecks,
|
|
1740
|
+
kernelRuleChecks,
|
|
1741
|
+
levelChecks,
|
|
1742
|
+
decidingLayer,
|
|
1743
|
+
decidingId,
|
|
1744
|
+
startTime
|
|
1745
|
+
) : void 0,
|
|
1746
|
+
event.intent
|
|
1747
|
+
);
|
|
1748
|
+
}
|
|
1749
|
+
function checkInvariantCoverage(world, checks) {
|
|
1750
|
+
const invariants = world.invariants ?? [];
|
|
1751
|
+
const guards = world.guards?.guards ?? [];
|
|
1752
|
+
for (const invariant of invariants) {
|
|
1753
|
+
const coveringGuard = guards.find(
|
|
1754
|
+
(g) => g.invariant_ref === invariant.id && g.immutable
|
|
1755
|
+
);
|
|
1756
|
+
checks.push({
|
|
1757
|
+
invariantId: invariant.id,
|
|
1758
|
+
label: invariant.label,
|
|
1759
|
+
hasGuardCoverage: !!coveringGuard,
|
|
1760
|
+
coveringGuardId: coveringGuard?.id
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
function checkSafety(event, eventText, checks) {
|
|
1765
|
+
const textToCheck = event.intent + (event.payload ? JSON.stringify(event.payload) : "");
|
|
1766
|
+
for (const { pattern, label } of PROMPT_INJECTION_PATTERNS) {
|
|
1767
|
+
const triggered = pattern.test(textToCheck);
|
|
1768
|
+
checks.push({
|
|
1769
|
+
checkType: "prompt-injection",
|
|
1770
|
+
triggered,
|
|
1771
|
+
matchedPattern: triggered ? label : void 0
|
|
1772
|
+
});
|
|
1773
|
+
if (triggered) {
|
|
1774
|
+
for (const remaining of PROMPT_INJECTION_PATTERNS.filter((p) => p.label !== label)) {
|
|
1775
|
+
checks.push({
|
|
1776
|
+
checkType: "prompt-injection",
|
|
1777
|
+
triggered: remaining.pattern.test(textToCheck),
|
|
1778
|
+
matchedPattern: remaining.pattern.test(textToCheck) ? remaining.label : void 0
|
|
1779
|
+
});
|
|
1780
|
+
}
|
|
1781
|
+
return {
|
|
1782
|
+
status: "PAUSE",
|
|
1783
|
+
reason: NEUTRAL_MESSAGES["prompt-injection"],
|
|
1784
|
+
ruleId: `safety-injection-${label}`
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
const scopeToCheck = event.scope ?? event.intent;
|
|
1789
|
+
for (const { pattern, label } of SCOPE_ESCAPE_PATTERNS) {
|
|
1790
|
+
const triggered = pattern.test(scopeToCheck);
|
|
1791
|
+
checks.push({
|
|
1792
|
+
checkType: "scope-escape",
|
|
1793
|
+
triggered,
|
|
1794
|
+
matchedPattern: triggered ? label : void 0
|
|
1795
|
+
});
|
|
1796
|
+
if (triggered) {
|
|
1797
|
+
for (const remaining of SCOPE_ESCAPE_PATTERNS.filter((p) => p.label !== label)) {
|
|
1798
|
+
checks.push({
|
|
1799
|
+
checkType: "scope-escape",
|
|
1800
|
+
triggered: remaining.pattern.test(scopeToCheck),
|
|
1801
|
+
matchedPattern: remaining.pattern.test(scopeToCheck) ? remaining.label : void 0
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1804
|
+
return {
|
|
1805
|
+
status: "PAUSE",
|
|
1806
|
+
reason: NEUTRAL_MESSAGES["scope-escape"],
|
|
1807
|
+
ruleId: `safety-scope-${label}`
|
|
1808
|
+
};
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
if (event.direction === "output") {
|
|
1812
|
+
for (const { pattern, label } of EXECUTION_CLAIM_PATTERNS) {
|
|
1813
|
+
const triggered = pattern.test(textToCheck);
|
|
1814
|
+
checks.push({
|
|
1815
|
+
checkType: "execution-claim",
|
|
1816
|
+
triggered,
|
|
1817
|
+
matchedPattern: triggered ? label : void 0
|
|
1818
|
+
});
|
|
1819
|
+
if (triggered) {
|
|
1820
|
+
for (const remaining of EXECUTION_CLAIM_PATTERNS.filter((p) => p.label !== label)) {
|
|
1821
|
+
checks.push({
|
|
1822
|
+
checkType: "execution-claim",
|
|
1823
|
+
triggered: remaining.pattern.test(textToCheck),
|
|
1824
|
+
matchedPattern: remaining.pattern.test(textToCheck) ? remaining.label : void 0
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1827
|
+
return {
|
|
1828
|
+
status: "PAUSE",
|
|
1829
|
+
reason: NEUTRAL_MESSAGES["execution-claim"],
|
|
1830
|
+
ruleId: `safety-execution-claim-${label}`
|
|
1831
|
+
};
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
if (event.direction === "input") {
|
|
1836
|
+
const intentTrimmed = event.intent.trim();
|
|
1837
|
+
for (const { pattern, label } of EXECUTION_INTENT_PATTERNS) {
|
|
1838
|
+
const triggered = pattern.test(intentTrimmed);
|
|
1839
|
+
checks.push({
|
|
1840
|
+
checkType: "execution-intent",
|
|
1841
|
+
triggered,
|
|
1842
|
+
matchedPattern: triggered ? label : void 0
|
|
1843
|
+
});
|
|
1844
|
+
if (triggered) {
|
|
1845
|
+
for (const remaining of EXECUTION_INTENT_PATTERNS.filter((p) => p.label !== label)) {
|
|
1846
|
+
checks.push({
|
|
1847
|
+
checkType: "execution-intent",
|
|
1848
|
+
triggered: remaining.pattern.test(intentTrimmed),
|
|
1849
|
+
matchedPattern: remaining.pattern.test(intentTrimmed) ? remaining.label : void 0
|
|
1850
|
+
});
|
|
1851
|
+
}
|
|
1852
|
+
return {
|
|
1853
|
+
status: "PAUSE",
|
|
1854
|
+
reason: NEUTRAL_MESSAGES["execution-intent"],
|
|
1855
|
+
ruleId: `safety-execution-intent-${label}`
|
|
1856
|
+
};
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
return null;
|
|
1861
|
+
}
|
|
1862
|
+
function checkRoleRules(event, eventText, world, checks) {
|
|
1863
|
+
if (!event.roleId || !world.roles) return null;
|
|
1864
|
+
const role = world.roles.roles.find((r) => r.id === event.roleId);
|
|
1865
|
+
if (!role) return null;
|
|
1866
|
+
if (role.requiresApproval) {
|
|
1867
|
+
checks.push({
|
|
1868
|
+
roleId: role.id,
|
|
1869
|
+
roleName: role.name,
|
|
1870
|
+
rule: "All actions require approval",
|
|
1871
|
+
ruleType: "requiresApproval",
|
|
1872
|
+
matched: true
|
|
1873
|
+
});
|
|
1874
|
+
return {
|
|
1875
|
+
status: "PAUSE",
|
|
1876
|
+
reason: `Role "${role.name}" requires approval for all actions.`,
|
|
1877
|
+
ruleId: `role-${role.id}-requires-approval`
|
|
1878
|
+
};
|
|
1879
|
+
}
|
|
1880
|
+
for (const rule of role.cannotDo) {
|
|
1881
|
+
const matched = matchesKeywords(eventText, rule);
|
|
1882
|
+
checks.push({
|
|
1883
|
+
roleId: role.id,
|
|
1884
|
+
roleName: role.name,
|
|
1885
|
+
rule,
|
|
1886
|
+
ruleType: "cannotDo",
|
|
1887
|
+
matched
|
|
1888
|
+
});
|
|
1889
|
+
if (matched) {
|
|
1890
|
+
return {
|
|
1891
|
+
status: "BLOCK",
|
|
1892
|
+
reason: `Role "${role.name}" cannot: ${rule}`,
|
|
1893
|
+
ruleId: `role-${role.id}-cannotdo`
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
for (const rule of role.canDo) {
|
|
1898
|
+
checks.push({
|
|
1899
|
+
roleId: role.id,
|
|
1900
|
+
roleName: role.name,
|
|
1901
|
+
rule,
|
|
1902
|
+
ruleType: "canDo",
|
|
1903
|
+
matched: matchesKeywords(eventText, rule)
|
|
1904
|
+
});
|
|
1905
|
+
}
|
|
1906
|
+
return null;
|
|
1907
|
+
}
|
|
1908
|
+
function checkGuards(event, eventText, world, checks, guardsMatched) {
|
|
1909
|
+
if (!world.guards) return null;
|
|
1910
|
+
const guardsConfig = world.guards;
|
|
1911
|
+
let warnResult = null;
|
|
1912
|
+
const compiledPatterns = /* @__PURE__ */ new Map();
|
|
1913
|
+
for (const [key, def] of Object.entries(guardsConfig.intent_vocabulary)) {
|
|
1914
|
+
try {
|
|
1915
|
+
compiledPatterns.set(key, new RegExp(def.pattern, "i"));
|
|
1916
|
+
} catch {
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
const eventTool = (event.tool ?? "").toLowerCase();
|
|
1920
|
+
for (const guard of guardsConfig.guards) {
|
|
1921
|
+
if (guard.appliesTo && guard.appliesTo.length > 0) {
|
|
1922
|
+
const normalizedAppliesTo = guard.appliesTo.map((t) => t.toLowerCase());
|
|
1923
|
+
if (!normalizedAppliesTo.includes(eventTool)) {
|
|
1924
|
+
continue;
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
const enabled = guard.immutable || guard.default_enabled !== false;
|
|
1928
|
+
const matchedPatterns = [];
|
|
1929
|
+
for (const patternKey of guard.intent_patterns) {
|
|
1930
|
+
const regex = compiledPatterns.get(patternKey);
|
|
1931
|
+
if (regex?.test(eventText)) {
|
|
1932
|
+
matchedPatterns.push(patternKey);
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
const matched = matchedPatterns.length > 0 && enabled;
|
|
1936
|
+
let roleGated = false;
|
|
1937
|
+
if (matched && guard.required_roles && guard.required_roles.length > 0 && event.roleId && guard.required_roles.includes(event.roleId)) {
|
|
1938
|
+
roleGated = true;
|
|
1939
|
+
}
|
|
1940
|
+
checks.push({
|
|
1941
|
+
guardId: guard.id,
|
|
1942
|
+
label: guard.label,
|
|
1943
|
+
category: guard.category,
|
|
1944
|
+
enabled,
|
|
1945
|
+
matched: matched && !roleGated,
|
|
1946
|
+
enforcement: guard.enforcement,
|
|
1947
|
+
matchedPatterns,
|
|
1948
|
+
roleGated
|
|
1949
|
+
});
|
|
1950
|
+
if (!matched || roleGated) continue;
|
|
1951
|
+
guardsMatched.push(guard.id);
|
|
1952
|
+
const actionMode = guard.player_modes?.action ?? guard.enforcement;
|
|
1953
|
+
const reason = guard.redirect ? `${guard.description} \u2014 ${guard.redirect}` : guard.description;
|
|
1954
|
+
if (actionMode === "block") {
|
|
1955
|
+
return { status: "BLOCK", reason, ruleId: `guard-${guard.id}` };
|
|
1956
|
+
}
|
|
1957
|
+
if (actionMode === "pause") {
|
|
1958
|
+
return { status: "PAUSE", reason, ruleId: `guard-${guard.id}` };
|
|
1959
|
+
}
|
|
1960
|
+
if (actionMode === "penalize") {
|
|
1961
|
+
const consequence = guard.consequence ? { ...guard.consequence } : { type: "freeze", rounds: 1, description: `Penalized for violating: ${guard.label}` };
|
|
1962
|
+
return { status: "PENALIZE", reason, ruleId: `guard-${guard.id}`, consequence };
|
|
1963
|
+
}
|
|
1964
|
+
if (actionMode === "reward") {
|
|
1965
|
+
const reward = guard.reward ? { ...guard.reward } : { type: "boost_influence", magnitude: 0.1, description: `Rewarded for: ${guard.label}` };
|
|
1966
|
+
return { status: "REWARD", reason, ruleId: `guard-${guard.id}`, reward };
|
|
1967
|
+
}
|
|
1968
|
+
if (actionMode === "modify") {
|
|
1969
|
+
const modifiedTo = guard.modify_to ?? guard.redirect ?? "hold";
|
|
1970
|
+
return { status: "MODIFY", reason: `${reason} \u2192 Modified to: ${modifiedTo}`, ruleId: `guard-${guard.id}`, modifiedTo };
|
|
1971
|
+
}
|
|
1972
|
+
if (actionMode === "neutral") {
|
|
1973
|
+
return { status: "NEUTRAL", reason, ruleId: `guard-${guard.id}` };
|
|
1974
|
+
}
|
|
1975
|
+
if (actionMode === "warn" && !warnResult) {
|
|
1976
|
+
warnResult = { status: "ALLOW", warning: reason, ruleId: `guard-${guard.id}` };
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
return warnResult;
|
|
1980
|
+
}
|
|
1981
|
+
function checkKernelRules(eventText, world, checks, rulesMatched) {
|
|
1982
|
+
if (!world.kernel) return null;
|
|
1983
|
+
const forbidden = world.kernel.input_boundaries?.forbidden_patterns ?? [];
|
|
1984
|
+
const output = world.kernel.output_boundaries?.forbidden_patterns ?? [];
|
|
1985
|
+
for (const rule of forbidden) {
|
|
1986
|
+
let matched = false;
|
|
1987
|
+
let matchMethod = "none";
|
|
1988
|
+
if (rule.pattern) {
|
|
1989
|
+
try {
|
|
1990
|
+
matched = new RegExp(rule.pattern, "i").test(eventText);
|
|
1991
|
+
matchMethod = "pattern";
|
|
1992
|
+
} catch {
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
if (!matched && rule.reason) {
|
|
1996
|
+
matched = matchesKeywords(eventText, rule.reason);
|
|
1997
|
+
if (matched) matchMethod = "keyword";
|
|
1998
|
+
}
|
|
1999
|
+
checks.push({
|
|
2000
|
+
ruleId: rule.id,
|
|
2001
|
+
text: rule.reason,
|
|
2002
|
+
category: "forbidden",
|
|
2003
|
+
matched,
|
|
2004
|
+
matchMethod
|
|
2005
|
+
});
|
|
2006
|
+
if (matched) {
|
|
2007
|
+
rulesMatched.push(rule.id);
|
|
2008
|
+
if (rule.action === "BLOCK") {
|
|
2009
|
+
return {
|
|
2010
|
+
status: "BLOCK",
|
|
2011
|
+
reason: rule.reason,
|
|
2012
|
+
ruleId: `kernel-${rule.id}`
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
return null;
|
|
2018
|
+
}
|
|
2019
|
+
function checkLevelConstraints(event, level, checks) {
|
|
2020
|
+
if (level === "basic") return null;
|
|
2021
|
+
const intent = event.intent.toLowerCase();
|
|
2022
|
+
const tool = (event.tool ?? "").toLowerCase();
|
|
2023
|
+
const isDelete = intent.includes("delete") || intent.includes("remove") || intent.includes("rm ") || tool === "delete";
|
|
2024
|
+
const deleteTriggered = isDelete && levelRequiresConfirmation(level, "delete");
|
|
2025
|
+
checks.push({
|
|
2026
|
+
checkType: "delete",
|
|
2027
|
+
level,
|
|
2028
|
+
triggered: deleteTriggered,
|
|
2029
|
+
reason: deleteTriggered ? NEUTRAL_MESSAGES["delete"] : void 0
|
|
2030
|
+
});
|
|
2031
|
+
if (deleteTriggered) {
|
|
2032
|
+
return { status: "PAUSE", reason: NEUTRAL_MESSAGES["delete"], ruleId: "level-delete-check" };
|
|
2033
|
+
}
|
|
2034
|
+
const isExternal = event.scope ? isExternalScope(event.scope) : false;
|
|
2035
|
+
const externalTriggered = isExternal && levelRequiresConfirmation(level, "write-external");
|
|
2036
|
+
checks.push({
|
|
2037
|
+
checkType: "write-external",
|
|
2038
|
+
level,
|
|
2039
|
+
triggered: externalTriggered,
|
|
2040
|
+
reason: externalTriggered ? NEUTRAL_MESSAGES["write-external"] : void 0
|
|
2041
|
+
});
|
|
2042
|
+
if (externalTriggered) {
|
|
2043
|
+
return { status: "PAUSE", reason: NEUTRAL_MESSAGES["write-external"], ruleId: "level-external-write-check" };
|
|
2044
|
+
}
|
|
2045
|
+
const isNetwork = tool === "http" || tool === "fetch" || tool === "request" || intent.includes("post ") || intent.includes("sending");
|
|
2046
|
+
const networkTriggered = isNetwork && levelRequiresConfirmation(level, "network-mutate");
|
|
2047
|
+
checks.push({
|
|
2048
|
+
checkType: "network-mutate",
|
|
2049
|
+
level,
|
|
2050
|
+
triggered: networkTriggered,
|
|
2051
|
+
reason: networkTriggered ? NEUTRAL_MESSAGES["network-mutate"] : void 0
|
|
2052
|
+
});
|
|
2053
|
+
if (networkTriggered) {
|
|
2054
|
+
return { status: "PAUSE", reason: NEUTRAL_MESSAGES["network-mutate"], ruleId: "level-network-mutate-check" };
|
|
2055
|
+
}
|
|
2056
|
+
const isCredential = intent.includes("credential") || intent.includes("password") || intent.includes("secret") || intent.includes("api key") || intent.includes("token");
|
|
2057
|
+
const credentialTriggered = isCredential && levelRequiresConfirmation(level, "credential-access");
|
|
2058
|
+
checks.push({
|
|
2059
|
+
checkType: "credential-access",
|
|
2060
|
+
level,
|
|
2061
|
+
triggered: credentialTriggered,
|
|
2062
|
+
reason: credentialTriggered ? NEUTRAL_MESSAGES["credential-access"] : void 0
|
|
2063
|
+
});
|
|
2064
|
+
if (credentialTriggered) {
|
|
2065
|
+
return { status: "PAUSE", reason: NEUTRAL_MESSAGES["credential-access"], ruleId: "level-credential-check" };
|
|
2066
|
+
}
|
|
2067
|
+
const irreversibleTriggered = !!event.irreversible && level !== "basic";
|
|
2068
|
+
checks.push({
|
|
2069
|
+
checkType: "irreversible",
|
|
2070
|
+
level,
|
|
2071
|
+
triggered: irreversibleTriggered,
|
|
2072
|
+
reason: irreversibleTriggered ? "This action is marked as irreversible." : void 0
|
|
2073
|
+
});
|
|
2074
|
+
if (irreversibleTriggered) {
|
|
2075
|
+
return {
|
|
2076
|
+
status: "PAUSE",
|
|
2077
|
+
reason: "This action is marked as irreversible.",
|
|
2078
|
+
ruleId: "level-irreversible-check"
|
|
2079
|
+
};
|
|
2080
|
+
}
|
|
2081
|
+
return null;
|
|
2082
|
+
}
|
|
2083
|
+
function matchesKeywords(eventText, ruleText) {
|
|
2084
|
+
return matchesAllKeywords(eventText, ruleText);
|
|
2085
|
+
}
|
|
2086
|
+
function eventToAllowlistKey(event) {
|
|
2087
|
+
return `${(event.tool ?? "*").toLowerCase()}::${event.intent.toLowerCase().trim()}`;
|
|
2088
|
+
}
|
|
2089
|
+
function buildTrace(invariantChecks, safetyChecks, planCheck, roleChecks, guardChecks, kernelRuleChecks, levelChecks, decidingLayer, decidingId, startTime) {
|
|
2090
|
+
const trace = {
|
|
2091
|
+
invariantChecks,
|
|
2092
|
+
safetyChecks,
|
|
2093
|
+
roleChecks,
|
|
2094
|
+
guardChecks,
|
|
2095
|
+
kernelRuleChecks,
|
|
2096
|
+
levelChecks,
|
|
2097
|
+
precedenceResolution: {
|
|
2098
|
+
decidingLayer,
|
|
2099
|
+
decidingId,
|
|
2100
|
+
strategy: "first-match-wins",
|
|
2101
|
+
chainOrder: [
|
|
2102
|
+
"invariant-coverage",
|
|
2103
|
+
"session-allowlist",
|
|
2104
|
+
"safety-injection",
|
|
2105
|
+
"safety-scope-escape",
|
|
2106
|
+
"safety-execution-claim",
|
|
2107
|
+
"safety-execution-intent",
|
|
2108
|
+
"plan-enforcement",
|
|
2109
|
+
"role-rules",
|
|
2110
|
+
"declarative-guards",
|
|
2111
|
+
"kernel-rules",
|
|
2112
|
+
"level-constraints",
|
|
2113
|
+
"default-allow"
|
|
2114
|
+
]
|
|
2115
|
+
},
|
|
2116
|
+
durationMs: performance.now() - startTime
|
|
2117
|
+
};
|
|
2118
|
+
if (planCheck) {
|
|
2119
|
+
trace.planCheck = planCheck;
|
|
2120
|
+
}
|
|
2121
|
+
return trace;
|
|
2122
|
+
}
|
|
2123
|
+
function buildVerdict(status, reason, ruleId, warning, world, level, invariantChecks, guardsMatched, rulesMatched, trace, eventIntent) {
|
|
2124
|
+
const evidence = {
|
|
2125
|
+
worldId: world.world.world_id,
|
|
2126
|
+
worldName: world.world.name,
|
|
2127
|
+
worldVersion: world.world.version,
|
|
2128
|
+
evaluatedAt: Date.now(),
|
|
2129
|
+
invariantsSatisfied: invariantChecks.filter((c) => c.hasGuardCoverage).length,
|
|
2130
|
+
invariantsTotal: invariantChecks.length,
|
|
2131
|
+
guardsMatched,
|
|
2132
|
+
rulesMatched,
|
|
2133
|
+
enforcementLevel: level
|
|
2134
|
+
};
|
|
2135
|
+
const verdict = {
|
|
2136
|
+
status,
|
|
2137
|
+
evidence
|
|
2138
|
+
};
|
|
2139
|
+
if (reason) verdict.reason = reason;
|
|
2140
|
+
if (ruleId) verdict.ruleId = ruleId;
|
|
2141
|
+
if (warning) verdict.warning = warning;
|
|
2142
|
+
if (trace) verdict.trace = trace;
|
|
2143
|
+
verdict.event = verdictToEvent(status, eventIntent);
|
|
2144
|
+
return verdict;
|
|
2145
|
+
}
|
|
2146
|
+
function verdictToEvent(status, intent) {
|
|
2147
|
+
const statusEventMap = {
|
|
2148
|
+
ALLOW: "action_allowed",
|
|
2149
|
+
BLOCK: "action_blocked",
|
|
2150
|
+
PAUSE: "action_paused",
|
|
2151
|
+
MODIFY: "action_modified",
|
|
2152
|
+
PENALIZE: "action_penalized",
|
|
2153
|
+
REWARD: "action_rewarded",
|
|
2154
|
+
NEUTRAL: "action_neutral"
|
|
2155
|
+
};
|
|
2156
|
+
return {
|
|
2157
|
+
type: intent || statusEventMap[status] || "unknown_action",
|
|
2158
|
+
actor: "agent",
|
|
2159
|
+
source: "guard",
|
|
2160
|
+
timestamp: Date.now(),
|
|
2161
|
+
guardStatus: status
|
|
2162
|
+
};
|
|
2163
|
+
}
|
|
2164
|
+
var PROMPT_INJECTION_PATTERNS, EXECUTION_CLAIM_PATTERNS, EXECUTION_INTENT_PATTERNS, SCOPE_ESCAPE_PATTERNS, NEUTRAL_MESSAGES, MAX_INPUT_LENGTH;
|
|
2165
|
+
var init_guard_engine = __esm({
|
|
2166
|
+
"src/engine/guard-engine.ts"() {
|
|
2167
|
+
"use strict";
|
|
2168
|
+
init_plan_engine();
|
|
2169
|
+
init_text_utils();
|
|
2170
|
+
PROMPT_INJECTION_PATTERNS = [
|
|
2171
|
+
// Instruction override
|
|
2172
|
+
{ pattern: /ignore\s+(previous|all|prior|above)\s+(instructions?|rules?)/i, label: "ignore-instructions" },
|
|
2173
|
+
{ pattern: /disregard\s+(your|the)\s+(rules|constraints)/i, label: "disregard-rules" },
|
|
2174
|
+
{ pattern: /new\s+instructions?:/i, label: "new-instructions" },
|
|
2175
|
+
// Identity manipulation
|
|
2176
|
+
{ pattern: /you\s+are\s+now/i, label: "identity-override" },
|
|
2177
|
+
{ pattern: /new\s+persona/i, label: "new-persona" },
|
|
2178
|
+
{ pattern: /act\s+as\s+if/i, label: "act-as-if" },
|
|
2179
|
+
{ pattern: /pretend\s+(you|to\s+be|you\s+are\s+unrestricted)/i, label: "pretend-to-be" },
|
|
2180
|
+
// Context reset
|
|
2181
|
+
{ pattern: /forget\s+(everything|all|your)/i, label: "forget-context" },
|
|
2182
|
+
{ pattern: /system\s*:\s*override/i, label: "system-override" },
|
|
2183
|
+
// Constraint bypass
|
|
2184
|
+
{ pattern: /override\s+(your|the)\s+(programming|constraints)/i, label: "override-constraints" },
|
|
2185
|
+
{ pattern: /bypass\s+(your|the)\s+(filters|constraints|rules)/i, label: "bypass-filters" },
|
|
2186
|
+
// Prompt extraction
|
|
2187
|
+
{ pattern: /system\s+prompt/i, label: "system-prompt-probe" },
|
|
2188
|
+
{ pattern: /reveal\s+your\s+(instructions?|prompt|rules)/i, label: "reveal-instructions" },
|
|
2189
|
+
// Known jailbreak terms
|
|
2190
|
+
{ pattern: /jailbreak/i, label: "jailbreak" },
|
|
2191
|
+
{ pattern: /DAN\s+mode/i, label: "dan-mode" },
|
|
2192
|
+
{ pattern: /developer\s+mode/i, label: "developer-mode" }
|
|
2193
|
+
];
|
|
2194
|
+
EXECUTION_CLAIM_PATTERNS = [
|
|
2195
|
+
{ pattern: /I have (executed|completed|performed|done|made|created|sent|deleted|modified|updated)/i, label: "claim-i-have" },
|
|
2196
|
+
{ pattern: /Successfully (created|deleted|modified|updated|sent|executed|performed)/i, label: "claim-successfully" },
|
|
2197
|
+
{ pattern: /The file has been/i, label: "claim-file-modified" },
|
|
2198
|
+
{ pattern: /I've made the changes/i, label: "claim-made-changes" },
|
|
2199
|
+
{ pattern: /I('ve| have) (sent|posted|submitted|uploaded|downloaded)/i, label: "claim-sent" },
|
|
2200
|
+
{ pattern: /Your (email|message|file|request) has been (sent|submitted)/i, label: "claim-your-sent" },
|
|
2201
|
+
{ pattern: /Transaction complete/i, label: "claim-transaction" },
|
|
2202
|
+
{ pattern: /Order placed/i, label: "claim-order" },
|
|
2203
|
+
{ pattern: /Payment processed/i, label: "claim-payment" }
|
|
2204
|
+
];
|
|
2205
|
+
EXECUTION_INTENT_PATTERNS = [
|
|
2206
|
+
{ pattern: /^(execute|run|perform|do this)/i, label: "intent-execute" },
|
|
2207
|
+
{ pattern: /^(create|write|delete|modify) (a |the )?(file|folder|document)/i, label: "intent-file-ops" },
|
|
2208
|
+
{ pattern: /^(send|post|submit) (a |an |the )?(email|message|tweet|post)/i, label: "intent-send" },
|
|
2209
|
+
{ pattern: /^(search|look up|browse) (the )?web/i, label: "intent-web-search" },
|
|
2210
|
+
{ pattern: /^(make|call|invoke) (a |an )?(api|http|rest) (call|request)/i, label: "intent-api-call" },
|
|
2211
|
+
{ pattern: /^(buy|purchase|order|pay|transfer|send money)/i, label: "intent-financial" },
|
|
2212
|
+
{ pattern: /^(book|schedule|reserve)/i, label: "intent-booking" },
|
|
2213
|
+
{ pattern: /^(download|upload|save to|export to)/i, label: "intent-transfer" }
|
|
2214
|
+
];
|
|
2215
|
+
SCOPE_ESCAPE_PATTERNS = [
|
|
2216
|
+
{ pattern: /\.\.\//, label: "parent-traversal" },
|
|
2217
|
+
{ pattern: /^\/(?!home|project|workspace)/i, label: "absolute-path-outside-safe" },
|
|
2218
|
+
{ pattern: /~\//, label: "home-directory" },
|
|
2219
|
+
{ pattern: /\/etc\//i, label: "system-config" },
|
|
2220
|
+
{ pattern: /\/usr\//i, label: "system-binaries" },
|
|
2221
|
+
{ pattern: /\/var\//i, label: "system-variable-data" }
|
|
2222
|
+
];
|
|
2223
|
+
NEUTRAL_MESSAGES = {
|
|
2224
|
+
"prompt-injection": "This input contains patterns that could alter agent behavior.",
|
|
2225
|
+
"scope-escape": "This action would affect resources outside the declared scope.",
|
|
2226
|
+
"execution-claim": "This response claims to have performed an action.",
|
|
2227
|
+
"execution-intent": "This input requests execution in a thinking-only environment.",
|
|
2228
|
+
"delete": "This action would remove files. Confirmation needed.",
|
|
2229
|
+
"write-external": "This action would write outside the project folder.",
|
|
2230
|
+
"network-mutate": "This action would send data to an external service.",
|
|
2231
|
+
"credential-access": "This action would access stored credentials."
|
|
2232
|
+
};
|
|
2233
|
+
MAX_INPUT_LENGTH = 1e5;
|
|
2234
|
+
}
|
|
2235
|
+
});
|
|
2236
|
+
|
|
2237
|
+
// src/loader/world-loader.ts
|
|
2238
|
+
async function loadWorldFromDirectory(dirPath) {
|
|
2239
|
+
const { readFile } = await import("fs/promises");
|
|
2240
|
+
const { join: join5 } = await import("path");
|
|
2241
|
+
const { readdirSync: readdirSync4 } = await import("fs");
|
|
2242
|
+
async function readJson(filename) {
|
|
2243
|
+
const filePath = join5(dirPath, filename);
|
|
2244
|
+
try {
|
|
2245
|
+
const content = await readFile(filePath, "utf-8");
|
|
2246
|
+
return JSON.parse(content);
|
|
2247
|
+
} catch (err) {
|
|
2248
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") {
|
|
2249
|
+
return void 0;
|
|
2250
|
+
}
|
|
2251
|
+
process.stderr.write(
|
|
2252
|
+
`[neuroverse] Warning: Failed to read ${filename}: ${err instanceof Error ? err.message : String(err)}
|
|
2253
|
+
`
|
|
2254
|
+
);
|
|
2255
|
+
return void 0;
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
const worldJson = await readJson("world.json");
|
|
2259
|
+
if (!worldJson) {
|
|
2260
|
+
throw new Error(`Cannot read world.json in ${dirPath}`);
|
|
2261
|
+
}
|
|
2262
|
+
const invariantsJson = await readJson("invariants.json");
|
|
2263
|
+
const assumptionsJson = await readJson("assumptions.json");
|
|
2264
|
+
const stateSchemaJson = await readJson("state-schema.json");
|
|
2265
|
+
const gatesJson = await readJson("gates.json");
|
|
2266
|
+
const outcomesJson = await readJson("outcomes.json");
|
|
2267
|
+
const guardsJson = await readJson("guards.json");
|
|
2268
|
+
const rolesJson = await readJson("roles.json");
|
|
2269
|
+
const kernelJson = await readJson("kernel.json");
|
|
2270
|
+
const metadataJson = await readJson("metadata.json");
|
|
2271
|
+
const rules = [];
|
|
2272
|
+
try {
|
|
2273
|
+
const rulesDir = join5(dirPath, "rules");
|
|
2274
|
+
const ruleFiles = readdirSync4(rulesDir).filter((f) => f.endsWith(".json")).sort();
|
|
2275
|
+
for (const file of ruleFiles) {
|
|
2276
|
+
try {
|
|
2277
|
+
const content = await readFile(join5(rulesDir, file), "utf-8");
|
|
2278
|
+
rules.push(JSON.parse(content));
|
|
2279
|
+
} catch (err) {
|
|
2280
|
+
process.stderr.write(
|
|
2281
|
+
`[neuroverse] Warning: Failed to parse rule ${file}: ${err instanceof Error ? err.message : String(err)}
|
|
2282
|
+
`
|
|
2283
|
+
);
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
} catch (err) {
|
|
2287
|
+
if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) {
|
|
2288
|
+
process.stderr.write(
|
|
2289
|
+
`[neuroverse] Warning: Failed to read rules directory: ${err instanceof Error ? err.message : String(err)}
|
|
2290
|
+
`
|
|
2291
|
+
);
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
return {
|
|
2295
|
+
world: worldJson,
|
|
2296
|
+
invariants: invariantsJson?.invariants ?? [],
|
|
2297
|
+
assumptions: assumptionsJson ?? { profiles: {}, parameter_definitions: {} },
|
|
2298
|
+
stateSchema: stateSchemaJson ?? { variables: {}, presets: {} },
|
|
2299
|
+
rules,
|
|
2300
|
+
gates: gatesJson ?? {
|
|
2301
|
+
viability_classification: [],
|
|
2302
|
+
structural_override: { description: "", enforcement: "mandatory" },
|
|
2303
|
+
sustainability_threshold: 0,
|
|
2304
|
+
collapse_visual: { background: "", text: "", border: "", label: "" }
|
|
2305
|
+
},
|
|
2306
|
+
outcomes: outcomesJson ?? {
|
|
2307
|
+
computed_outcomes: [],
|
|
2308
|
+
comparison_layout: { primary_card: "", status_badge: "", structural_indicators: [] }
|
|
2309
|
+
},
|
|
2310
|
+
guards: guardsJson,
|
|
2311
|
+
roles: rolesJson,
|
|
2312
|
+
kernel: kernelJson,
|
|
2313
|
+
metadata: metadataJson ?? {
|
|
2314
|
+
format_version: "1.0.0",
|
|
2315
|
+
created_at: "",
|
|
2316
|
+
last_modified: "",
|
|
2317
|
+
authoring_method: "manual-authoring"
|
|
2318
|
+
}
|
|
2319
|
+
};
|
|
2320
|
+
}
|
|
2321
|
+
async function loadWorld(worldPath) {
|
|
2322
|
+
const { stat } = await import("fs/promises");
|
|
2323
|
+
const info = await stat(worldPath);
|
|
2324
|
+
if (info.isDirectory()) {
|
|
2325
|
+
return loadWorldFromDirectory(worldPath);
|
|
2326
|
+
}
|
|
2327
|
+
throw new Error(`Cannot load world from: ${worldPath} \u2014 expected a directory`);
|
|
2328
|
+
}
|
|
2329
|
+
var init_world_loader = __esm({
|
|
2330
|
+
"src/loader/world-loader.ts"() {
|
|
2331
|
+
"use strict";
|
|
2332
|
+
}
|
|
2333
|
+
});
|
|
2334
|
+
|
|
2335
|
+
// src/radiant/core/governance.ts
|
|
2336
|
+
async function auditGovernance(events, worldPath) {
|
|
2337
|
+
let world;
|
|
2338
|
+
try {
|
|
2339
|
+
world = await loadWorld(worldPath);
|
|
2340
|
+
} catch {
|
|
2341
|
+
return emptyAudit(events.length, "Could not load compiled worldmodel for governance audit.");
|
|
2342
|
+
}
|
|
2343
|
+
const verdicts = [];
|
|
2344
|
+
for (const ce of events) {
|
|
2345
|
+
const intent = ce.event.content?.slice(0, 500) || ce.event.kind || "activity";
|
|
2346
|
+
const scope = ce.event.metadata?.scope || void 0;
|
|
2347
|
+
try {
|
|
2348
|
+
const result = evaluateGuard(
|
|
2349
|
+
{
|
|
2350
|
+
intent,
|
|
2351
|
+
scope,
|
|
2352
|
+
actionCategory: mapKindToCategory(ce.event.kind)
|
|
2353
|
+
},
|
|
2354
|
+
world
|
|
2355
|
+
);
|
|
2356
|
+
verdicts.push({
|
|
2357
|
+
eventId: ce.event.id,
|
|
2358
|
+
domain: ce.domain,
|
|
2359
|
+
status: result.status,
|
|
2360
|
+
reason: result.reason,
|
|
2361
|
+
ruleId: result.ruleId,
|
|
2362
|
+
warning: result.warning
|
|
2363
|
+
});
|
|
2364
|
+
} catch {
|
|
2365
|
+
verdicts.push({
|
|
2366
|
+
eventId: ce.event.id,
|
|
2367
|
+
domain: ce.domain,
|
|
2368
|
+
status: "ALLOW",
|
|
2369
|
+
reason: "guard evaluation skipped (error)"
|
|
2370
|
+
});
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
const human = bucketVerdicts(verdicts.filter((v) => v.domain === "life"));
|
|
2374
|
+
const cyber = bucketVerdicts(verdicts.filter((v) => v.domain === "cyber"));
|
|
2375
|
+
const joint = bucketVerdicts(verdicts.filter((v) => v.domain === "joint"));
|
|
2376
|
+
const summary = buildSummary(human, cyber, joint, events.length);
|
|
2377
|
+
return {
|
|
2378
|
+
totalEvents: events.length,
|
|
2379
|
+
human,
|
|
2380
|
+
cyber,
|
|
2381
|
+
joint,
|
|
2382
|
+
summary
|
|
2383
|
+
};
|
|
2384
|
+
}
|
|
2385
|
+
function bucketVerdicts(verdicts) {
|
|
2386
|
+
const nonAllow = verdicts.filter((v) => v.status !== "ALLOW");
|
|
2387
|
+
return {
|
|
2388
|
+
allow: verdicts.filter((v) => v.status === "ALLOW").length,
|
|
2389
|
+
modify: verdicts.filter((v) => v.status === "MODIFY").length,
|
|
2390
|
+
block: verdicts.filter((v) => v.status === "BLOCK").length,
|
|
2391
|
+
details: nonAllow
|
|
2392
|
+
};
|
|
2393
|
+
}
|
|
2394
|
+
function buildSummary(human, cyber, joint, total) {
|
|
2395
|
+
const humanTriggered = human.modify + human.block;
|
|
2396
|
+
const cyberTriggered = cyber.modify + cyber.block;
|
|
2397
|
+
const jointTriggered = joint.modify + joint.block;
|
|
2398
|
+
const totalTriggered = humanTriggered + cyberTriggered + jointTriggered;
|
|
2399
|
+
if (totalTriggered === 0) {
|
|
2400
|
+
return `${total} events evaluated. All passed. The cocoon held \u2014 no governance triggered.`;
|
|
2401
|
+
}
|
|
2402
|
+
const parts = [];
|
|
2403
|
+
parts.push(`${total} events evaluated. ${totalTriggered} triggered governance.`);
|
|
2404
|
+
if (humanTriggered > 0) {
|
|
2405
|
+
parts.push(`Human side: ${humanTriggered} (${human.block} blocked, ${human.modify} modified).`);
|
|
2406
|
+
}
|
|
2407
|
+
if (cyberTriggered > 0) {
|
|
2408
|
+
parts.push(`AI side: ${cyberTriggered} (${cyber.block} blocked, ${cyber.modify} modified).`);
|
|
2409
|
+
}
|
|
2410
|
+
if (jointTriggered > 0) {
|
|
2411
|
+
parts.push(`Joint work: ${jointTriggered} (${joint.block} blocked, ${joint.modify} modified).`);
|
|
2412
|
+
}
|
|
2413
|
+
if (humanTriggered > 0 && cyberTriggered > 0) {
|
|
2414
|
+
const ratio = humanTriggered / cyberTriggered;
|
|
2415
|
+
if (ratio > 2) {
|
|
2416
|
+
parts.push("Human side is testing the frame more than AI. Either the worldmodel needs calibrating for human workflows, or humans are genuinely drifting.");
|
|
2417
|
+
} else if (ratio < 0.5) {
|
|
2418
|
+
parts.push("AI side is testing the frame more than humans. Check whether the AI's output patterns match the declared invariants.");
|
|
2419
|
+
} else {
|
|
2420
|
+
parts.push("Roughly balanced between human and AI \u2014 both sides are testing the frame.");
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
return parts.join(" ");
|
|
2424
|
+
}
|
|
2425
|
+
function mapKindToCategory(kind) {
|
|
2426
|
+
if (!kind) return "other";
|
|
2427
|
+
if (kind.includes("commit") || kind.includes("merge")) return "write";
|
|
2428
|
+
if (kind.includes("review") || kind.includes("comment")) return "read";
|
|
2429
|
+
return "other";
|
|
2430
|
+
}
|
|
2431
|
+
function emptyAudit(total, reason) {
|
|
2432
|
+
return {
|
|
2433
|
+
totalEvents: total,
|
|
2434
|
+
human: { allow: 0, modify: 0, block: 0, details: [] },
|
|
2435
|
+
cyber: { allow: 0, modify: 0, block: 0, details: [] },
|
|
2436
|
+
joint: { allow: 0, modify: 0, block: 0, details: [] },
|
|
2437
|
+
summary: reason
|
|
2438
|
+
};
|
|
2439
|
+
}
|
|
2440
|
+
var init_governance = __esm({
|
|
2441
|
+
"src/radiant/core/governance.ts"() {
|
|
2442
|
+
"use strict";
|
|
2443
|
+
init_guard_engine();
|
|
2444
|
+
init_world_loader();
|
|
2445
|
+
}
|
|
2446
|
+
});
|
|
904
2447
|
|
|
905
2448
|
// src/radiant/core/domain.ts
|
|
906
2449
|
function isLifeSide(k) {
|
|
@@ -926,6 +2469,11 @@ function classifyActorDomain(event) {
|
|
|
926
2469
|
}
|
|
927
2470
|
return isCyberSide(primaryKind) ? "cyber" : "life";
|
|
928
2471
|
}
|
|
2472
|
+
var init_domain = __esm({
|
|
2473
|
+
"src/radiant/core/domain.ts"() {
|
|
2474
|
+
"use strict";
|
|
2475
|
+
}
|
|
2476
|
+
});
|
|
929
2477
|
|
|
930
2478
|
// src/radiant/core/signals.ts
|
|
931
2479
|
function classifyEvents(events) {
|
|
@@ -951,7 +2499,6 @@ function extractSignals(events, extractors = DEFAULT_SIGNAL_EXTRACTORS) {
|
|
|
951
2499
|
}
|
|
952
2500
|
return out;
|
|
953
2501
|
}
|
|
954
|
-
var ZERO = { score: 0, eventCount: 0, confidence: 0 };
|
|
955
2502
|
function inDomain(events, domain) {
|
|
956
2503
|
return events.filter((e) => e.domain === domain);
|
|
957
2504
|
}
|
|
@@ -963,110 +2510,124 @@ function clamp100(n) {
|
|
|
963
2510
|
if (n > 100) return 100;
|
|
964
2511
|
return n;
|
|
965
2512
|
}
|
|
966
|
-
var CLARITY_EXTRACTOR
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
2513
|
+
var ZERO, CLARITY_EXTRACTOR, OWNERSHIP_EXTRACTOR, FOLLOW_THROUGH_EXTRACTOR, ALIGNMENT_EXTRACTOR, DECISION_MOMENTUM_EXTRACTOR, DEFAULT_SIGNAL_EXTRACTORS;
|
|
2514
|
+
var init_signals = __esm({
|
|
2515
|
+
"src/radiant/core/signals.ts"() {
|
|
2516
|
+
"use strict";
|
|
2517
|
+
init_domain();
|
|
2518
|
+
ZERO = { score: 0, eventCount: 0, confidence: 0 };
|
|
2519
|
+
CLARITY_EXTRACTOR = {
|
|
2520
|
+
id: "clarity",
|
|
2521
|
+
description: "Informativeness of event content \u2014 commit messages, PR bodies, review text",
|
|
2522
|
+
extract(events, domain) {
|
|
2523
|
+
const sub = inDomain(events, domain);
|
|
2524
|
+
if (sub.length === 0) return ZERO;
|
|
2525
|
+
const totalScore = sub.reduce((acc, e) => {
|
|
2526
|
+
const len = (e.event.content ?? "").length;
|
|
2527
|
+
const norm = Math.min(len, 200) / 200;
|
|
2528
|
+
return acc + norm * 100;
|
|
2529
|
+
}, 0);
|
|
2530
|
+
return {
|
|
2531
|
+
score: clamp100(totalScore / sub.length),
|
|
2532
|
+
eventCount: sub.length,
|
|
2533
|
+
confidence: confidenceFromCount(sub.length)
|
|
2534
|
+
};
|
|
2535
|
+
}
|
|
981
2536
|
};
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
2537
|
+
OWNERSHIP_EXTRACTOR = {
|
|
2538
|
+
id: "ownership",
|
|
2539
|
+
description: "Clarity of accountability \u2014 fraction of events with a known primary actor",
|
|
2540
|
+
extract(events, domain) {
|
|
2541
|
+
const sub = inDomain(events, domain);
|
|
2542
|
+
if (sub.length === 0) return ZERO;
|
|
2543
|
+
const attributed = sub.filter((e) => e.event.actor.kind !== "unknown").length;
|
|
2544
|
+
return {
|
|
2545
|
+
score: clamp100(attributed / sub.length * 100),
|
|
2546
|
+
eventCount: sub.length,
|
|
2547
|
+
confidence: confidenceFromCount(sub.length)
|
|
2548
|
+
};
|
|
2549
|
+
}
|
|
995
2550
|
};
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
2551
|
+
FOLLOW_THROUGH_EXTRACTOR = {
|
|
2552
|
+
id: "follow_through",
|
|
2553
|
+
description: "Fraction of events that were followed up \u2014 i.e. referenced by a later event",
|
|
2554
|
+
extract(events, domain) {
|
|
2555
|
+
const sub = inDomain(events, domain);
|
|
2556
|
+
if (sub.length === 0) return ZERO;
|
|
2557
|
+
const referencedIds = /* @__PURE__ */ new Set();
|
|
2558
|
+
for (const e of events) {
|
|
2559
|
+
const ref = e.event.respondsTo?.eventId;
|
|
2560
|
+
if (ref) referencedIds.add(ref);
|
|
2561
|
+
}
|
|
2562
|
+
const followedUp = sub.filter((e) => referencedIds.has(e.event.id)).length;
|
|
2563
|
+
return {
|
|
2564
|
+
score: clamp100(followedUp / sub.length * 100),
|
|
2565
|
+
eventCount: sub.length,
|
|
2566
|
+
confidence: confidenceFromCount(sub.length)
|
|
2567
|
+
};
|
|
2568
|
+
}
|
|
1014
2569
|
};
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
2570
|
+
ALIGNMENT_EXTRACTOR = {
|
|
2571
|
+
id: "alignment",
|
|
2572
|
+
description: "Coordination pressure \u2014 fraction of events that reference a prior event",
|
|
2573
|
+
extract(events, domain) {
|
|
2574
|
+
const sub = inDomain(events, domain);
|
|
2575
|
+
if (sub.length === 0) return ZERO;
|
|
2576
|
+
const referencing = sub.filter((e) => e.event.respondsTo !== void 0).length;
|
|
2577
|
+
return {
|
|
2578
|
+
score: clamp100(referencing / sub.length * 100),
|
|
2579
|
+
eventCount: sub.length,
|
|
2580
|
+
confidence: confidenceFromCount(sub.length)
|
|
2581
|
+
};
|
|
2582
|
+
}
|
|
1028
2583
|
};
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
2584
|
+
DECISION_MOMENTUM_EXTRACTOR = {
|
|
2585
|
+
id: "decision_momentum",
|
|
2586
|
+
description: "Rate of activity in this domain \u2014 events per day, capped at 10/day",
|
|
2587
|
+
extract(events, domain) {
|
|
2588
|
+
const sub = inDomain(events, domain);
|
|
2589
|
+
if (sub.length === 0) return ZERO;
|
|
2590
|
+
if (sub.length < 2) {
|
|
2591
|
+
return {
|
|
2592
|
+
score: 20,
|
|
2593
|
+
// token non-zero score — single event = some motion
|
|
2594
|
+
eventCount: sub.length,
|
|
2595
|
+
confidence: confidenceFromCount(sub.length)
|
|
2596
|
+
};
|
|
2597
|
+
}
|
|
2598
|
+
const ts = sub.map((e) => Date.parse(e.event.timestamp)).sort((a, b) => a - b);
|
|
2599
|
+
const spanMs = ts[ts.length - 1] - ts[0];
|
|
2600
|
+
const spanDays = Math.max(spanMs / (24 * 60 * 60 * 1e3), 1 / 24);
|
|
2601
|
+
const perDay = sub.length / spanDays;
|
|
2602
|
+
const normalized = Math.min(perDay, 10) / 10;
|
|
2603
|
+
return {
|
|
2604
|
+
score: clamp100(normalized * 100),
|
|
2605
|
+
eventCount: sub.length,
|
|
2606
|
+
confidence: confidenceFromCount(sub.length)
|
|
2607
|
+
};
|
|
2608
|
+
}
|
|
1054
2609
|
};
|
|
2610
|
+
DEFAULT_SIGNAL_EXTRACTORS = Object.freeze([
|
|
2611
|
+
CLARITY_EXTRACTOR,
|
|
2612
|
+
OWNERSHIP_EXTRACTOR,
|
|
2613
|
+
FOLLOW_THROUGH_EXTRACTOR,
|
|
2614
|
+
ALIGNMENT_EXTRACTOR,
|
|
2615
|
+
DECISION_MOMENTUM_EXTRACTOR
|
|
2616
|
+
]);
|
|
1055
2617
|
}
|
|
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
|
-
]);
|
|
2618
|
+
});
|
|
1064
2619
|
|
|
1065
2620
|
// src/radiant/types.ts
|
|
1066
|
-
var DEFAULT_EVIDENCE_GATE = { k: 3, c: 0.5 };
|
|
1067
2621
|
function isScored(s) {
|
|
1068
2622
|
return typeof s === "number";
|
|
1069
2623
|
}
|
|
2624
|
+
var DEFAULT_EVIDENCE_GATE;
|
|
2625
|
+
var init_types = __esm({
|
|
2626
|
+
"src/radiant/types.ts"() {
|
|
2627
|
+
"use strict";
|
|
2628
|
+
DEFAULT_EVIDENCE_GATE = { k: 3, c: 0.5 };
|
|
2629
|
+
}
|
|
2630
|
+
});
|
|
1070
2631
|
|
|
1071
2632
|
// src/radiant/core/math.ts
|
|
1072
2633
|
function isPresent(o, gate = DEFAULT_EVIDENCE_GATE) {
|
|
@@ -1096,6 +2657,12 @@ function scoreComposite(a_L, a_C, a_N) {
|
|
|
1096
2657
|
if (available.length === 0) return "INSUFFICIENT_EVIDENCE";
|
|
1097
2658
|
return available.reduce((a, b) => a + b, 0) / available.length;
|
|
1098
2659
|
}
|
|
2660
|
+
var init_math = __esm({
|
|
2661
|
+
"src/radiant/core/math.ts"() {
|
|
2662
|
+
"use strict";
|
|
2663
|
+
init_types();
|
|
2664
|
+
}
|
|
2665
|
+
});
|
|
1099
2666
|
|
|
1100
2667
|
// src/radiant/core/patterns.ts
|
|
1101
2668
|
async function interpretPatterns(input) {
|
|
@@ -1196,7 +2763,7 @@ Only recommend a move when the evidence actually calls for one.
|
|
|
1196
2763
|
}
|
|
1197
2764
|
],
|
|
1198
2765
|
"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.
|
|
2766
|
+
"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
2767
|
}
|
|
1201
2768
|
\`\`\`
|
|
1202
2769
|
|
|
@@ -1290,6 +2857,11 @@ function parseInterpretation(raw, canonicalNames) {
|
|
|
1290
2857
|
function isPatternLike(x) {
|
|
1291
2858
|
return typeof x === "object" && x !== null && "name" in x;
|
|
1292
2859
|
}
|
|
2860
|
+
var init_patterns = __esm({
|
|
2861
|
+
"src/radiant/core/patterns.ts"() {
|
|
2862
|
+
"use strict";
|
|
2863
|
+
}
|
|
2864
|
+
});
|
|
1293
2865
|
|
|
1294
2866
|
// src/radiant/core/renderer.ts
|
|
1295
2867
|
function render(input) {
|
|
@@ -1352,6 +2924,27 @@ Lens: ${input.lens.name}`
|
|
|
1352
2924
|
` Composite: ${formatScore(input.scores.R)}`
|
|
1353
2925
|
].join("\n");
|
|
1354
2926
|
sections.push(alignBlock);
|
|
2927
|
+
if (input.governance && input.governance.totalEvents > 0) {
|
|
2928
|
+
const gov = input.governance;
|
|
2929
|
+
const govLines = ["GOVERNANCE", "", ` ${gov.summary}`];
|
|
2930
|
+
const showSide = (label, side) => {
|
|
2931
|
+
if (side.allow + side.modify + side.block === 0) return;
|
|
2932
|
+
govLines.push("");
|
|
2933
|
+
govLines.push(` ${label}:`);
|
|
2934
|
+
govLines.push(` ${side.allow} ALLOW \xB7 ${side.modify} MODIFY \xB7 ${side.block} BLOCK`);
|
|
2935
|
+
for (const d of side.details.slice(0, 3)) {
|
|
2936
|
+
const reason = d.reason ? ` \u2192 ${d.reason}` : "";
|
|
2937
|
+
govLines.push(` ${d.status}: ${d.eventId}${reason}`);
|
|
2938
|
+
}
|
|
2939
|
+
if (side.details.length > 3) {
|
|
2940
|
+
govLines.push(` ... and ${side.details.length - 3} more`);
|
|
2941
|
+
}
|
|
2942
|
+
};
|
|
2943
|
+
showSide("Human side", gov.human);
|
|
2944
|
+
showSide("AI side", gov.cyber);
|
|
2945
|
+
showSide("Human\u2013AI joint", gov.joint);
|
|
2946
|
+
sections.push(govLines.join("\n"));
|
|
2947
|
+
}
|
|
1355
2948
|
sections.push(renderDepth(input.priorReadCount ?? 0, input.windowDays));
|
|
1356
2949
|
return sections.join("\n\n");
|
|
1357
2950
|
}
|
|
@@ -1514,6 +3107,13 @@ function serializeYAML(obj, indent = 0) {
|
|
|
1514
3107
|
return `${obj}
|
|
1515
3108
|
`;
|
|
1516
3109
|
}
|
|
3110
|
+
var init_renderer = __esm({
|
|
3111
|
+
"src/radiant/core/renderer.ts"() {
|
|
3112
|
+
"use strict";
|
|
3113
|
+
init_types();
|
|
3114
|
+
init_scopes();
|
|
3115
|
+
}
|
|
3116
|
+
});
|
|
1517
3117
|
|
|
1518
3118
|
// src/radiant/commands/emergent.ts
|
|
1519
3119
|
async function emergent(input) {
|
|
@@ -1521,10 +3121,15 @@ async function emergent(input) {
|
|
|
1521
3121
|
const windowDays = input.windowDays ?? 14;
|
|
1522
3122
|
let statedIntent;
|
|
1523
3123
|
let exocortexContext;
|
|
3124
|
+
let priorReadContext = "";
|
|
1524
3125
|
if (input.exocortexPath) {
|
|
1525
3126
|
exocortexContext = readExocortex(input.exocortexPath);
|
|
1526
3127
|
const formatted = formatExocortexForPrompt(exocortexContext);
|
|
1527
3128
|
if (formatted) statedIntent = formatted;
|
|
3129
|
+
const priorReads = loadPriorReads(input.exocortexPath);
|
|
3130
|
+
if (priorReads.length > 0) {
|
|
3131
|
+
priorReadContext = formatPriorReadsForPrompt(priorReads);
|
|
3132
|
+
}
|
|
1528
3133
|
}
|
|
1529
3134
|
const events = await fetchGitHubActivity(input.scope, input.githubToken, {
|
|
1530
3135
|
windowDays
|
|
@@ -1539,11 +3144,18 @@ async function emergent(input) {
|
|
|
1539
3144
|
lens,
|
|
1540
3145
|
ai: input.ai,
|
|
1541
3146
|
canonicalPatterns: input.canonicalPatterns,
|
|
1542
|
-
statedIntent
|
|
3147
|
+
statedIntent: statedIntent ? statedIntent + (priorReadContext ? "\n\n" + priorReadContext : "") : priorReadContext || void 0
|
|
1543
3148
|
});
|
|
1544
3149
|
const rewrittenPatterns = patterns.map((p) => lens.rewrite(p));
|
|
1545
3150
|
const allDescriptions = rewrittenPatterns.map((p) => p.description).join("\n");
|
|
1546
3151
|
const voiceViolations = checkForbiddenPhrases(lens, allDescriptions);
|
|
3152
|
+
let governance;
|
|
3153
|
+
if (input.worldPath) {
|
|
3154
|
+
try {
|
|
3155
|
+
governance = await auditGovernance(classified, input.worldPath);
|
|
3156
|
+
} catch {
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
1547
3159
|
const rendered = render({
|
|
1548
3160
|
scope: input.scope,
|
|
1549
3161
|
windowDays,
|
|
@@ -1553,8 +3165,27 @@ async function emergent(input) {
|
|
|
1553
3165
|
scores,
|
|
1554
3166
|
lens,
|
|
1555
3167
|
meaning: meaning || void 0,
|
|
1556
|
-
move: move || void 0
|
|
3168
|
+
move: move || void 0,
|
|
3169
|
+
governance
|
|
1557
3170
|
});
|
|
3171
|
+
if (input.exocortexPath) {
|
|
3172
|
+
try {
|
|
3173
|
+
const readPath = writeRead(input.exocortexPath, rendered.frontmatter, rendered.text);
|
|
3174
|
+
const priorReads = loadPriorReads(input.exocortexPath);
|
|
3175
|
+
const currentPatternNames = rewrittenPatterns.map((p) => p.name);
|
|
3176
|
+
const persistence = computePersistence(priorReads, currentPatternNames);
|
|
3177
|
+
const triggeredItems = governance ? [
|
|
3178
|
+
...governance.human.details.map((d) => d.ruleId).filter(Boolean),
|
|
3179
|
+
...governance.cyber.details.map((d) => d.ruleId).filter(Boolean),
|
|
3180
|
+
...governance.joint.details.map((d) => d.ruleId).filter(Boolean)
|
|
3181
|
+
] : [];
|
|
3182
|
+
updateKnowledge(input.exocortexPath, persistence, {
|
|
3183
|
+
triggeredItems,
|
|
3184
|
+
totalReads: priorReads.length + 1
|
|
3185
|
+
});
|
|
3186
|
+
} catch {
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
1558
3189
|
return {
|
|
1559
3190
|
text: rendered.text,
|
|
1560
3191
|
frontmatter: rendered.frontmatter,
|
|
@@ -1612,6 +3243,22 @@ function resolveLens2(id) {
|
|
|
1612
3243
|
}
|
|
1613
3244
|
return lens;
|
|
1614
3245
|
}
|
|
3246
|
+
var init_emergent = __esm({
|
|
3247
|
+
"src/radiant/commands/emergent.ts"() {
|
|
3248
|
+
"use strict";
|
|
3249
|
+
init_lenses();
|
|
3250
|
+
init_github();
|
|
3251
|
+
init_exocortex();
|
|
3252
|
+
init_palace();
|
|
3253
|
+
init_governance();
|
|
3254
|
+
init_signals();
|
|
3255
|
+
init_math();
|
|
3256
|
+
init_patterns();
|
|
3257
|
+
init_renderer();
|
|
3258
|
+
init_voice_check();
|
|
3259
|
+
init_types();
|
|
3260
|
+
}
|
|
3261
|
+
});
|
|
1615
3262
|
|
|
1616
3263
|
// src/radiant/core/ai.ts
|
|
1617
3264
|
function createAnthropicAI(apiKey, model = "claude-sonnet-4-20250514", maxTokens = 4096) {
|
|
@@ -1646,8 +3293,296 @@ function createAnthropicAI(apiKey, model = "claude-sonnet-4-20250514", maxTokens
|
|
|
1646
3293
|
}
|
|
1647
3294
|
};
|
|
1648
3295
|
}
|
|
3296
|
+
var init_ai = __esm({
|
|
3297
|
+
"src/radiant/core/ai.ts"() {
|
|
3298
|
+
"use strict";
|
|
3299
|
+
}
|
|
3300
|
+
});
|
|
3301
|
+
|
|
3302
|
+
// src/radiant/mcp/server.ts
|
|
3303
|
+
var server_exports = {};
|
|
3304
|
+
__export(server_exports, {
|
|
3305
|
+
RadiantMcpServer: () => RadiantMcpServer,
|
|
3306
|
+
startRadiantMcp: () => startRadiantMcp
|
|
3307
|
+
});
|
|
3308
|
+
function loadWorldmodelContent(worldsPath) {
|
|
3309
|
+
const resolved = (0, import_path3.resolve)(worldsPath);
|
|
3310
|
+
if (!(0, import_fs3.existsSync)(resolved)) {
|
|
3311
|
+
throw new Error(`Worlds path not found: ${resolved}`);
|
|
3312
|
+
}
|
|
3313
|
+
const stat = (0, import_fs3.statSync)(resolved);
|
|
3314
|
+
if (stat.isFile()) {
|
|
3315
|
+
return (0, import_fs3.readFileSync)(resolved, "utf-8");
|
|
3316
|
+
}
|
|
3317
|
+
if (stat.isDirectory()) {
|
|
3318
|
+
const files = (0, import_fs3.readdirSync)(resolved).filter(
|
|
3319
|
+
(f) => (0, import_path3.extname)(f) === ".md" && (f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md"))
|
|
3320
|
+
).sort();
|
|
3321
|
+
if (files.length === 0) {
|
|
3322
|
+
throw new Error(`No worldmodel files found in ${resolved}`);
|
|
3323
|
+
}
|
|
3324
|
+
return files.map((f) => (0, import_fs3.readFileSync)((0, import_path3.join)(resolved, f), "utf-8")).join("\n\n---\n\n");
|
|
3325
|
+
}
|
|
3326
|
+
throw new Error(`Worlds path is neither a file nor directory: ${resolved}`);
|
|
3327
|
+
}
|
|
3328
|
+
async function startRadiantMcp(args) {
|
|
3329
|
+
function parseArg(flag) {
|
|
3330
|
+
const idx = args.indexOf(flag);
|
|
3331
|
+
return idx >= 0 && idx + 1 < args.length ? args[idx + 1] : void 0;
|
|
3332
|
+
}
|
|
3333
|
+
const worldsPath = parseArg("--worlds") ?? process.env.RADIANT_WORLDS;
|
|
3334
|
+
const lensId = parseArg("--lens") ?? process.env.RADIANT_LENS ?? "auki-builder";
|
|
3335
|
+
const model = parseArg("--model") ?? process.env.RADIANT_MODEL;
|
|
3336
|
+
if (!worldsPath) {
|
|
3337
|
+
process.stderr.write("Error: --worlds <dir> or RADIANT_WORLDS required.\n");
|
|
3338
|
+
process.exit(1);
|
|
3339
|
+
}
|
|
3340
|
+
const server = new RadiantMcpServer({ worldsPath, lensId, model });
|
|
3341
|
+
await server.start();
|
|
3342
|
+
}
|
|
3343
|
+
var import_fs3, import_path3, TOOLS, RadiantMcpServer;
|
|
3344
|
+
var init_server = __esm({
|
|
3345
|
+
"src/radiant/mcp/server.ts"() {
|
|
3346
|
+
"use strict";
|
|
3347
|
+
import_fs3 = require("fs");
|
|
3348
|
+
import_path3 = require("path");
|
|
3349
|
+
init_think();
|
|
3350
|
+
init_emergent();
|
|
3351
|
+
init_ai();
|
|
3352
|
+
init_scopes();
|
|
3353
|
+
TOOLS = [
|
|
3354
|
+
{
|
|
3355
|
+
name: "radiant_think",
|
|
3356
|
+
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.",
|
|
3357
|
+
inputSchema: {
|
|
3358
|
+
type: "object",
|
|
3359
|
+
properties: {
|
|
3360
|
+
query: {
|
|
3361
|
+
type: "string",
|
|
3362
|
+
description: "The question or prompt to interpret through the worldmodel + lens."
|
|
3363
|
+
}
|
|
3364
|
+
},
|
|
3365
|
+
required: ["query"]
|
|
3366
|
+
}
|
|
3367
|
+
},
|
|
3368
|
+
{
|
|
3369
|
+
name: "radiant_emergent",
|
|
3370
|
+
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.",
|
|
3371
|
+
inputSchema: {
|
|
3372
|
+
type: "object",
|
|
3373
|
+
properties: {
|
|
3374
|
+
scope: {
|
|
3375
|
+
type: "string",
|
|
3376
|
+
description: 'GitHub repository in "owner/repo" format (e.g. "aukiverse/posemesh").'
|
|
3377
|
+
},
|
|
3378
|
+
exocortex_dir: {
|
|
3379
|
+
type: "string",
|
|
3380
|
+
description: "Optional path to an exocortex directory for stated-intent-vs-observed-behavior comparison."
|
|
3381
|
+
}
|
|
3382
|
+
},
|
|
3383
|
+
required: ["scope"]
|
|
3384
|
+
}
|
|
3385
|
+
}
|
|
3386
|
+
];
|
|
3387
|
+
RadiantMcpServer = class {
|
|
3388
|
+
config;
|
|
3389
|
+
worldmodelContent;
|
|
3390
|
+
buffer = "";
|
|
3391
|
+
constructor(config) {
|
|
3392
|
+
this.config = config;
|
|
3393
|
+
this.worldmodelContent = loadWorldmodelContent(config.worldsPath);
|
|
3394
|
+
}
|
|
3395
|
+
async start() {
|
|
3396
|
+
process.stderr.write(
|
|
3397
|
+
`Radiant MCP server starting
|
|
3398
|
+
Worlds: ${this.config.worldsPath}
|
|
3399
|
+
Lens: ${this.config.lensId}
|
|
3400
|
+
Tools: radiant_think, radiant_emergent
|
|
3401
|
+
`
|
|
3402
|
+
);
|
|
3403
|
+
process.stdin.setEncoding("utf-8");
|
|
3404
|
+
process.stdin.on("data", (chunk) => {
|
|
3405
|
+
this.buffer += chunk;
|
|
3406
|
+
this.processBuffer();
|
|
3407
|
+
});
|
|
3408
|
+
process.stdin.on("end", () => {
|
|
3409
|
+
process.exit(0);
|
|
3410
|
+
});
|
|
3411
|
+
}
|
|
3412
|
+
processBuffer() {
|
|
3413
|
+
const lines = this.buffer.split("\n");
|
|
3414
|
+
this.buffer = lines.pop() ?? "";
|
|
3415
|
+
for (const line of lines) {
|
|
3416
|
+
const trimmed = line.trim();
|
|
3417
|
+
if (!trimmed) continue;
|
|
3418
|
+
try {
|
|
3419
|
+
const request = JSON.parse(trimmed);
|
|
3420
|
+
this.handleRequest(request).catch((err) => {
|
|
3421
|
+
this.sendError(request.id, -32603, String(err));
|
|
3422
|
+
});
|
|
3423
|
+
} catch {
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
async handleRequest(req) {
|
|
3428
|
+
switch (req.method) {
|
|
3429
|
+
case "initialize":
|
|
3430
|
+
this.sendResult(req.id, {
|
|
3431
|
+
protocolVersion: "2024-11-05",
|
|
3432
|
+
capabilities: { tools: {} },
|
|
3433
|
+
serverInfo: {
|
|
3434
|
+
name: "radiant",
|
|
3435
|
+
version: "0.6.1"
|
|
3436
|
+
}
|
|
3437
|
+
});
|
|
3438
|
+
break;
|
|
3439
|
+
case "notifications/initialized":
|
|
3440
|
+
break;
|
|
3441
|
+
case "tools/list":
|
|
3442
|
+
this.sendResult(req.id, { tools: TOOLS });
|
|
3443
|
+
break;
|
|
3444
|
+
case "tools/call":
|
|
3445
|
+
await this.handleToolCall(req);
|
|
3446
|
+
break;
|
|
3447
|
+
default:
|
|
3448
|
+
this.sendError(req.id, -32601, `Unknown method: ${req.method}`);
|
|
3449
|
+
}
|
|
3450
|
+
}
|
|
3451
|
+
async handleToolCall(req) {
|
|
3452
|
+
const params = req.params;
|
|
3453
|
+
if (!params?.name) {
|
|
3454
|
+
this.sendError(req.id, -32602, "Missing tool name");
|
|
3455
|
+
return;
|
|
3456
|
+
}
|
|
3457
|
+
const args = params.arguments ?? {};
|
|
3458
|
+
try {
|
|
3459
|
+
switch (params.name) {
|
|
3460
|
+
case "radiant_think":
|
|
3461
|
+
await this.handleThink(req.id, args);
|
|
3462
|
+
break;
|
|
3463
|
+
case "radiant_emergent":
|
|
3464
|
+
await this.handleEmergent(req.id, args);
|
|
3465
|
+
break;
|
|
3466
|
+
default:
|
|
3467
|
+
this.sendError(req.id, -32602, `Unknown tool: ${params.name}`);
|
|
3468
|
+
}
|
|
3469
|
+
} catch (err) {
|
|
3470
|
+
this.sendResult(req.id, {
|
|
3471
|
+
content: [{ type: "text", text: `Error: ${err}` }],
|
|
3472
|
+
isError: true
|
|
3473
|
+
});
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
async handleThink(id, args) {
|
|
3477
|
+
const query = String(args.query ?? "");
|
|
3478
|
+
if (!query) {
|
|
3479
|
+
this.sendResult(id, {
|
|
3480
|
+
content: [{ type: "text", text: "Error: query is required" }],
|
|
3481
|
+
isError: true
|
|
3482
|
+
});
|
|
3483
|
+
return;
|
|
3484
|
+
}
|
|
3485
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
3486
|
+
if (!apiKey) {
|
|
3487
|
+
this.sendResult(id, {
|
|
3488
|
+
content: [{ type: "text", text: "Error: ANTHROPIC_API_KEY not set" }],
|
|
3489
|
+
isError: true
|
|
3490
|
+
});
|
|
3491
|
+
return;
|
|
3492
|
+
}
|
|
3493
|
+
const ai = createAnthropicAI(apiKey, this.config.model || void 0);
|
|
3494
|
+
const result = await think({
|
|
3495
|
+
worldmodelContent: this.worldmodelContent,
|
|
3496
|
+
lensId: this.config.lensId,
|
|
3497
|
+
query,
|
|
3498
|
+
ai
|
|
3499
|
+
});
|
|
3500
|
+
let text = result.response;
|
|
3501
|
+
if (!result.voiceClean) {
|
|
3502
|
+
text += `
|
|
3503
|
+
|
|
3504
|
+
\u26A0 Voice violations detected: ${result.voiceViolations.map((v) => v.phrase).join(", ")}`;
|
|
3505
|
+
}
|
|
3506
|
+
this.sendResult(id, {
|
|
3507
|
+
content: [{ type: "text", text }]
|
|
3508
|
+
});
|
|
3509
|
+
}
|
|
3510
|
+
async handleEmergent(id, args) {
|
|
3511
|
+
const scopeStr = String(args.scope ?? "");
|
|
3512
|
+
if (!scopeStr) {
|
|
3513
|
+
this.sendResult(id, {
|
|
3514
|
+
content: [{ type: "text", text: 'Error: scope is required (e.g. "aukiverse/posemesh")' }],
|
|
3515
|
+
isError: true
|
|
3516
|
+
});
|
|
3517
|
+
return;
|
|
3518
|
+
}
|
|
3519
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
3520
|
+
const githubToken = process.env.GITHUB_TOKEN;
|
|
3521
|
+
if (!apiKey) {
|
|
3522
|
+
this.sendResult(id, {
|
|
3523
|
+
content: [{ type: "text", text: "Error: ANTHROPIC_API_KEY not set" }],
|
|
3524
|
+
isError: true
|
|
3525
|
+
});
|
|
3526
|
+
return;
|
|
3527
|
+
}
|
|
3528
|
+
if (!githubToken) {
|
|
3529
|
+
this.sendResult(id, {
|
|
3530
|
+
content: [{ type: "text", text: "Error: GITHUB_TOKEN not set" }],
|
|
3531
|
+
isError: true
|
|
3532
|
+
});
|
|
3533
|
+
return;
|
|
3534
|
+
}
|
|
3535
|
+
const scope = parseRepoScope(scopeStr);
|
|
3536
|
+
const ai = createAnthropicAI(apiKey, this.config.model || void 0);
|
|
3537
|
+
const exocortexPath = args.exocortex_dir ? String(args.exocortex_dir) : void 0;
|
|
3538
|
+
const result = await emergent({
|
|
3539
|
+
scope,
|
|
3540
|
+
githubToken,
|
|
3541
|
+
worldmodelContent: this.worldmodelContent,
|
|
3542
|
+
lensId: this.config.lensId,
|
|
3543
|
+
ai,
|
|
3544
|
+
windowDays: 14,
|
|
3545
|
+
exocortexPath
|
|
3546
|
+
});
|
|
3547
|
+
let text = result.text;
|
|
3548
|
+
if (!result.voiceClean) {
|
|
3549
|
+
text += `
|
|
3550
|
+
|
|
3551
|
+
\u26A0 Voice violations: ${result.voiceViolations.map((v) => v.phrase).join(", ")}`;
|
|
3552
|
+
}
|
|
3553
|
+
this.sendResult(id, {
|
|
3554
|
+
content: [{ type: "text", text }]
|
|
3555
|
+
});
|
|
3556
|
+
}
|
|
3557
|
+
sendResult(id, result) {
|
|
3558
|
+
const response = { jsonrpc: "2.0", id, result };
|
|
3559
|
+
process.stdout.write(JSON.stringify(response) + "\n");
|
|
3560
|
+
}
|
|
3561
|
+
sendError(id, code, message) {
|
|
3562
|
+
const response = {
|
|
3563
|
+
jsonrpc: "2.0",
|
|
3564
|
+
id: id ?? null,
|
|
3565
|
+
error: { code, message }
|
|
3566
|
+
};
|
|
3567
|
+
process.stdout.write(JSON.stringify(response) + "\n");
|
|
3568
|
+
}
|
|
3569
|
+
};
|
|
3570
|
+
}
|
|
3571
|
+
});
|
|
1649
3572
|
|
|
1650
3573
|
// src/cli/radiant.ts
|
|
3574
|
+
var radiant_exports = {};
|
|
3575
|
+
__export(radiant_exports, {
|
|
3576
|
+
main: () => main
|
|
3577
|
+
});
|
|
3578
|
+
module.exports = __toCommonJS(radiant_exports);
|
|
3579
|
+
var import_fs4 = require("fs");
|
|
3580
|
+
var import_path4 = require("path");
|
|
3581
|
+
init_think();
|
|
3582
|
+
init_emergent();
|
|
3583
|
+
init_ai();
|
|
3584
|
+
init_scopes();
|
|
3585
|
+
init_exocortex();
|
|
1651
3586
|
init_lenses();
|
|
1652
3587
|
var RED = "\x1B[31m";
|
|
1653
3588
|
var DIM = "\x1B[2m";
|
|
@@ -1731,18 +3666,18 @@ function parseArgs(argv) {
|
|
|
1731
3666
|
}
|
|
1732
3667
|
return result;
|
|
1733
3668
|
}
|
|
1734
|
-
function
|
|
1735
|
-
const resolved = (0,
|
|
1736
|
-
if (!(0,
|
|
3669
|
+
function loadWorldmodelContent2(worldsPath) {
|
|
3670
|
+
const resolved = (0, import_path4.resolve)(worldsPath);
|
|
3671
|
+
if (!(0, import_fs4.existsSync)(resolved)) {
|
|
1737
3672
|
throw new Error(`Worlds path not found: ${resolved}`);
|
|
1738
3673
|
}
|
|
1739
|
-
const stat = (0,
|
|
3674
|
+
const stat = (0, import_fs4.statSync)(resolved);
|
|
1740
3675
|
if (stat.isFile()) {
|
|
1741
|
-
return (0,
|
|
3676
|
+
return (0, import_fs4.readFileSync)(resolved, "utf-8");
|
|
1742
3677
|
}
|
|
1743
3678
|
if (stat.isDirectory()) {
|
|
1744
|
-
const files = (0,
|
|
1745
|
-
(f) => (0,
|
|
3679
|
+
const files = (0, import_fs4.readdirSync)(resolved).filter(
|
|
3680
|
+
(f) => (0, import_path4.extname)(f) === ".md" && (f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md"))
|
|
1746
3681
|
).sort();
|
|
1747
3682
|
if (files.length === 0) {
|
|
1748
3683
|
throw new Error(
|
|
@@ -1750,7 +3685,7 @@ function loadWorldmodelContent(worldsPath) {
|
|
|
1750
3685
|
);
|
|
1751
3686
|
}
|
|
1752
3687
|
return files.map((f) => {
|
|
1753
|
-
const content = (0,
|
|
3688
|
+
const content = (0, import_fs4.readFileSync)((0, import_path4.join)(resolved, f), "utf-8");
|
|
1754
3689
|
return `<!-- worldmodel: ${f} -->
|
|
1755
3690
|
${content}`;
|
|
1756
3691
|
}).join("\n\n---\n\n");
|
|
@@ -1789,7 +3724,7 @@ ${DIM}Set it to your Anthropic API key to use Radiant's AI features.${RESET}
|
|
|
1789
3724
|
query = args.rest.join(" ");
|
|
1790
3725
|
}
|
|
1791
3726
|
if (!query && !process.stdin.isTTY) {
|
|
1792
|
-
query = (0,
|
|
3727
|
+
query = (0, import_fs4.readFileSync)(0, "utf-8").trim();
|
|
1793
3728
|
}
|
|
1794
3729
|
if (!query) {
|
|
1795
3730
|
process.stderr.write(
|
|
@@ -1799,7 +3734,7 @@ ${DIM}Use --query "...", pass as trailing args, or pipe via stdin.${RESET}
|
|
|
1799
3734
|
);
|
|
1800
3735
|
process.exit(1);
|
|
1801
3736
|
}
|
|
1802
|
-
const worldmodelContent =
|
|
3737
|
+
const worldmodelContent = loadWorldmodelContent2(worldsPath);
|
|
1803
3738
|
const model = args.model ?? process.env.RADIANT_MODEL;
|
|
1804
3739
|
const ai = createAnthropicAI(apiKey, model || void 0);
|
|
1805
3740
|
process.stderr.write(
|
|
@@ -1892,7 +3827,7 @@ ${DIM}Set it to a GitHub PAT with repo read access.${RESET}
|
|
|
1892
3827
|
);
|
|
1893
3828
|
process.exit(1);
|
|
1894
3829
|
}
|
|
1895
|
-
const worldmodelContent =
|
|
3830
|
+
const worldmodelContent = loadWorldmodelContent2(worldsPath);
|
|
1896
3831
|
const model = args.model ?? process.env.RADIANT_MODEL;
|
|
1897
3832
|
const ai = createAnthropicAI(anthropicKey, model || void 0);
|
|
1898
3833
|
const exocortexPath = args.exocortex ?? process.env.RADIANT_EXOCORTEX;
|
|
@@ -2032,6 +3967,10 @@ async function main(argv) {
|
|
|
2032
3967
|
return cmdLenses(args);
|
|
2033
3968
|
case "emergent":
|
|
2034
3969
|
return cmdEmergent(args);
|
|
3970
|
+
case "mcp": {
|
|
3971
|
+
const { startRadiantMcp: startRadiantMcp2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
3972
|
+
return startRadiantMcp2(argv);
|
|
3973
|
+
}
|
|
2035
3974
|
case "decision":
|
|
2036
3975
|
case "signals":
|
|
2037
3976
|
case "drift":
|