@neuroverseos/governance 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/.well-known/ai-plugin.json +34 -9
  2. package/AGENTS.md +72 -24
  3. package/README.md +343 -248
  4. package/dist/adapters/autoresearch.cjs +1345 -0
  5. package/dist/adapters/autoresearch.d.cts +111 -0
  6. package/dist/adapters/autoresearch.d.ts +111 -0
  7. package/dist/adapters/autoresearch.js +12 -0
  8. package/dist/adapters/deep-agents.cjs +1528 -0
  9. package/dist/adapters/deep-agents.d.cts +181 -0
  10. package/dist/adapters/deep-agents.d.ts +181 -0
  11. package/dist/adapters/deep-agents.js +17 -0
  12. package/dist/adapters/express.cjs +1253 -0
  13. package/dist/adapters/express.d.cts +66 -0
  14. package/dist/adapters/express.d.ts +66 -0
  15. package/dist/adapters/express.js +12 -0
  16. package/dist/adapters/index.cjs +2112 -0
  17. package/dist/adapters/index.d.cts +8 -0
  18. package/dist/adapters/index.d.ts +8 -0
  19. package/dist/adapters/index.js +68 -0
  20. package/dist/adapters/langchain.cjs +1315 -0
  21. package/dist/adapters/langchain.d.cts +89 -0
  22. package/dist/adapters/langchain.d.ts +89 -0
  23. package/dist/adapters/langchain.js +17 -0
  24. package/dist/adapters/openai.cjs +1345 -0
  25. package/dist/adapters/openai.d.cts +99 -0
  26. package/dist/adapters/openai.d.ts +99 -0
  27. package/dist/adapters/openai.js +17 -0
  28. package/dist/adapters/openclaw.cjs +1337 -0
  29. package/dist/adapters/openclaw.d.cts +99 -0
  30. package/dist/adapters/openclaw.d.ts +99 -0
  31. package/dist/adapters/openclaw.js +17 -0
  32. package/dist/add-ROOZLU62.js +314 -0
  33. package/dist/behavioral-MJO34S6Q.js +118 -0
  34. package/dist/bootstrap-CQRZVOXK.js +116 -0
  35. package/dist/bootstrap-emitter-Q7UIJZ2O.js +7 -0
  36. package/dist/bootstrap-parser-EEF36XDU.js +7 -0
  37. package/dist/browser.global.js +941 -0
  38. package/dist/build-QKOBBC23.js +341 -0
  39. package/dist/chunk-3WQLXYTP.js +91 -0
  40. package/dist/chunk-4FLICVVA.js +119 -0
  41. package/dist/chunk-4NGDRRQH.js +10 -0
  42. package/dist/chunk-5TPFNWRU.js +215 -0
  43. package/dist/chunk-5U2MQO5P.js +57 -0
  44. package/dist/chunk-6CZSKEY5.js +164 -0
  45. package/dist/chunk-6S5CFQXY.js +624 -0
  46. package/dist/chunk-7P3S7MAY.js +1090 -0
  47. package/dist/chunk-A5W4GNQO.js +130 -0
  48. package/dist/chunk-A7GKPPU7.js +226 -0
  49. package/dist/chunk-AKW5YVCE.js +96 -0
  50. package/dist/chunk-B6OXJLJ5.js +622 -0
  51. package/dist/chunk-BNKJPUPQ.js +113 -0
  52. package/dist/chunk-BQZMOEML.js +43 -0
  53. package/dist/chunk-CNSO6XW5.js +207 -0
  54. package/dist/chunk-CTZHONLA.js +135 -0
  55. package/dist/chunk-D2UCV5AK.js +326 -0
  56. package/dist/chunk-EMQDLDAF.js +458 -0
  57. package/dist/chunk-F66BVUYB.js +340 -0
  58. package/dist/chunk-G7DJ6VOD.js +101 -0
  59. package/dist/chunk-I3RRAYK2.js +11 -0
  60. package/dist/chunk-IS4WUH6Y.js +363 -0
  61. package/dist/chunk-MH7BT4VH.js +15 -0
  62. package/dist/chunk-O5ABKEA7.js +304 -0
  63. package/dist/chunk-OT6PXH54.js +61 -0
  64. package/dist/chunk-PVTQQS3Y.js +186 -0
  65. package/dist/chunk-Q6O7ZLO2.js +62 -0
  66. package/dist/chunk-QLPTHTVB.js +253 -0
  67. package/dist/chunk-QWGCMQQD.js +16 -0
  68. package/dist/chunk-QXBFT7NI.js +201 -0
  69. package/dist/chunk-TG6SEF24.js +246 -0
  70. package/dist/chunk-U6U7EJZL.js +177 -0
  71. package/dist/chunk-W7LLXRGY.js +830 -0
  72. package/dist/chunk-ZJTDUCC2.js +194 -0
  73. package/dist/chunk-ZWI3NIXK.js +314 -0
  74. package/dist/cli/neuroverse.cjs +14191 -0
  75. package/dist/cli/neuroverse.d.cts +1 -0
  76. package/dist/cli/neuroverse.d.ts +1 -0
  77. package/dist/cli/neuroverse.js +227 -0
  78. package/dist/cli/plan.cjs +2439 -0
  79. package/dist/cli/plan.d.cts +20 -0
  80. package/dist/cli/plan.d.ts +20 -0
  81. package/dist/cli/plan.js +353 -0
  82. package/dist/cli/run.cjs +2001 -0
  83. package/dist/cli/run.d.cts +20 -0
  84. package/dist/cli/run.d.ts +20 -0
  85. package/dist/cli/run.js +143 -0
  86. package/dist/configure-ai-6TZ3MCSI.js +132 -0
  87. package/dist/decision-flow-M63D47LO.js +61 -0
  88. package/dist/demo-G43RLCPK.js +469 -0
  89. package/dist/derive-FJZVIPUZ.js +153 -0
  90. package/dist/doctor-6BC6X2VO.js +173 -0
  91. package/dist/equity-penalties-SG5IZQ7I.js +244 -0
  92. package/dist/explain-RHBU2GBR.js +51 -0
  93. package/dist/guard-AJCCGZMF.js +92 -0
  94. package/dist/guard-contract-DqFcTScd.d.cts +821 -0
  95. package/dist/guard-contract-DqFcTScd.d.ts +821 -0
  96. package/dist/guard-engine-PNR6MHCM.js +10 -0
  97. package/dist/impact-3XVDSCBU.js +59 -0
  98. package/dist/improve-TQP4ECSY.js +66 -0
  99. package/dist/index.cjs +7591 -0
  100. package/dist/index.d.cts +2195 -0
  101. package/dist/index.d.ts +2195 -0
  102. package/dist/index.js +472 -0
  103. package/dist/infer-world-IFXCACJ5.js +543 -0
  104. package/dist/init-FYPV4SST.js +144 -0
  105. package/dist/init-world-TI7ARHBT.js +223 -0
  106. package/dist/mcp-server-5Y3ZM7TV.js +13 -0
  107. package/dist/model-adapter-VXEKB4LS.js +11 -0
  108. package/dist/playground-VZBNPPBO.js +560 -0
  109. package/dist/redteam-MZPZD3EF.js +357 -0
  110. package/dist/session-JYOARW54.js +15 -0
  111. package/dist/shared-7RLUHNMU.js +16 -0
  112. package/dist/shared-B8dvUUD8.d.cts +60 -0
  113. package/dist/shared-Dr5Wiay8.d.ts +60 -0
  114. package/dist/simulate-LJXYBC6M.js +83 -0
  115. package/dist/test-BOOR4A5F.js +217 -0
  116. package/dist/trace-PKV4KX56.js +166 -0
  117. package/dist/validate-RALX7CZS.js +81 -0
  118. package/dist/validate-engine-7ZXFVGF2.js +7 -0
  119. package/dist/viz/assets/index-B8SaeJZZ.js +23 -0
  120. package/dist/viz/index.html +23 -0
  121. package/dist/world-BIP4GZBZ.js +376 -0
  122. package/dist/world-loader-Y6HMQH2D.js +13 -0
  123. package/dist/worlds/autoresearch.nv-world.md +230 -0
  124. package/dist/worlds/coding-agent.nv-world.md +211 -0
  125. package/dist/worlds/derivation-world.nv-world.md +278 -0
  126. package/dist/worlds/research-agent.nv-world.md +169 -0
  127. package/dist/worlds/social-media.nv-world.md +198 -0
  128. package/dist/worlds/trading-agent.nv-world.md +218 -0
  129. package/examples/social-media-sim/bridge.py +209 -0
  130. package/examples/social-media-sim/simulation.py +927 -0
  131. package/package.json +16 -3
  132. package/simulate.html +4 -336
@@ -0,0 +1,2439 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
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
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // src/engine/text-utils.ts
34
+ function normalizeEventText(event) {
35
+ return [
36
+ event.intent,
37
+ event.tool ?? "",
38
+ event.scope ?? ""
39
+ ].join(" ").toLowerCase();
40
+ }
41
+ function extractKeywords(text, minLength = 3) {
42
+ return text.toLowerCase().split(/\s+/).filter((w) => w.length > minLength);
43
+ }
44
+ function matchesAllKeywords(eventText, ruleText) {
45
+ const keywords = extractKeywords(ruleText);
46
+ if (keywords.length === 0) return false;
47
+ return keywords.every((kw) => eventText.includes(kw));
48
+ }
49
+ function matchesKeywordThreshold(eventText, ruleText, threshold = 0.5) {
50
+ const keywords = extractKeywords(ruleText);
51
+ if (keywords.length === 0) return false;
52
+ const matched = keywords.filter((kw) => eventText.includes(kw));
53
+ return matched.length >= Math.ceil(keywords.length * threshold);
54
+ }
55
+ function tokenSimilarity(a, b) {
56
+ const tokensA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
57
+ const tokensB = new Set(b.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
58
+ if (tokensA.size === 0 || tokensB.size === 0) return 0;
59
+ let intersection = 0;
60
+ for (const t of tokensA) {
61
+ if (tokensB.has(t)) intersection++;
62
+ }
63
+ const union = (/* @__PURE__ */ new Set([...tokensA, ...tokensB])).size;
64
+ return union > 0 ? intersection / union : 0;
65
+ }
66
+ var init_text_utils = __esm({
67
+ "src/engine/text-utils.ts"() {
68
+ "use strict";
69
+ }
70
+ });
71
+
72
+ // src/engine/plan-engine.ts
73
+ function keywordMatch(eventText, step) {
74
+ const stepText = [
75
+ step.label,
76
+ step.description ?? "",
77
+ ...step.tags ?? []
78
+ ].join(" ");
79
+ return matchesKeywordThreshold(eventText, stepText, 0.5);
80
+ }
81
+ function tokenSimilarity2(a, b) {
82
+ return tokenSimilarity(a, b);
83
+ }
84
+ function findMatchingStep(eventText, event, steps) {
85
+ const pendingOrActive = steps.filter((s) => s.status === "pending" || s.status === "active");
86
+ if (pendingOrActive.length === 0) {
87
+ return { matched: null, closest: null, closestScore: 0 };
88
+ }
89
+ for (const step of pendingOrActive) {
90
+ if (keywordMatch(eventText, step)) {
91
+ if (step.tools && event.tool && !step.tools.includes(event.tool)) {
92
+ continue;
93
+ }
94
+ return { matched: step, closest: step, closestScore: 1 };
95
+ }
96
+ }
97
+ const intentText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ");
98
+ let bestStep = null;
99
+ let bestScore = 0;
100
+ for (const step of pendingOrActive) {
101
+ const stepText = [step.label, step.description ?? "", ...step.tags ?? []].join(" ");
102
+ const score = tokenSimilarity2(intentText, stepText);
103
+ if (score > bestScore) {
104
+ bestScore = score;
105
+ bestStep = step;
106
+ }
107
+ }
108
+ const SIMILARITY_THRESHOLD = 0.35;
109
+ if (bestScore >= SIMILARITY_THRESHOLD && bestStep) {
110
+ if (bestStep.tools && event.tool && !bestStep.tools.includes(event.tool)) {
111
+ return { matched: null, closest: bestStep, closestScore: bestScore };
112
+ }
113
+ return { matched: bestStep, closest: bestStep, closestScore: bestScore };
114
+ }
115
+ return { matched: null, closest: bestStep, closestScore: bestScore };
116
+ }
117
+ function isSequenceValid(step, plan) {
118
+ if (!plan.sequential) return true;
119
+ if (!step.requires || step.requires.length === 0) return true;
120
+ return step.requires.every((reqId) => {
121
+ const reqStep = plan.steps.find((s) => s.id === reqId);
122
+ return reqStep?.status === "completed";
123
+ });
124
+ }
125
+ function checkConstraints(event, eventText, constraints) {
126
+ const checks = [];
127
+ for (const constraint of constraints) {
128
+ if (constraint.type === "approval") {
129
+ if (constraint.trigger && eventText.includes(constraint.trigger.substring(0, 10).toLowerCase())) {
130
+ checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
131
+ return { violated: constraint, checks };
132
+ }
133
+ const keywords = constraint.description.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
134
+ const relevant = keywords.some((kw) => eventText.includes(kw));
135
+ if (relevant) {
136
+ checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
137
+ return { violated: constraint, checks };
138
+ }
139
+ checks.push({ constraintId: constraint.id, passed: true });
140
+ continue;
141
+ }
142
+ if (constraint.type === "scope" && constraint.trigger) {
143
+ const keywords = extractKeywords(constraint.trigger);
144
+ const violated = keywords.length > 0 && keywords.every((kw) => eventText.includes(kw));
145
+ checks.push({
146
+ constraintId: constraint.id,
147
+ passed: !violated,
148
+ reason: violated ? constraint.description : void 0
149
+ });
150
+ if (violated) {
151
+ return { violated: constraint, checks };
152
+ }
153
+ continue;
154
+ }
155
+ checks.push({ constraintId: constraint.id, passed: true });
156
+ }
157
+ return { violated: null, checks };
158
+ }
159
+ function getPlanProgress(plan) {
160
+ const completed = plan.steps.filter((s) => s.status === "completed").length;
161
+ const total = plan.steps.length;
162
+ return {
163
+ completed,
164
+ total,
165
+ percentage: total > 0 ? Math.round(completed / total * 100) : 0
166
+ };
167
+ }
168
+ function advancePlan(plan, stepId, evidence) {
169
+ const step = plan.steps.find((s) => s.id === stepId);
170
+ if (!step) {
171
+ return { success: false, reason: `Step "${stepId}" not found in plan.` };
172
+ }
173
+ if (step.status === "completed") {
174
+ return { success: false, reason: `Step "${stepId}" is already completed.` };
175
+ }
176
+ const mode = plan.completion ?? "trust";
177
+ if (mode === "verified" && step.verify) {
178
+ if (!evidence) {
179
+ return {
180
+ success: false,
181
+ reason: `Step "${step.label}" requires evidence (verify: ${step.verify}). Provide evidence to advance.`
182
+ };
183
+ }
184
+ if (evidence.type !== step.verify) {
185
+ return {
186
+ success: false,
187
+ reason: `Evidence type "${evidence.type}" does not match required verification "${step.verify}".`
188
+ };
189
+ }
190
+ }
191
+ const updatedPlan = {
192
+ ...plan,
193
+ steps: plan.steps.map(
194
+ (s) => s.id === stepId ? { ...s, status: "completed" } : s
195
+ )
196
+ };
197
+ return {
198
+ success: true,
199
+ plan: updatedPlan,
200
+ evidence: evidence ?? void 0
201
+ };
202
+ }
203
+ function evaluatePlan(event, plan) {
204
+ const progress = getPlanProgress(plan);
205
+ if (plan.expires_at) {
206
+ const expiresAt = new Date(plan.expires_at).getTime();
207
+ if (Date.now() > expiresAt) {
208
+ return {
209
+ allowed: true,
210
+ status: "PLAN_COMPLETE",
211
+ reason: "Plan has expired.",
212
+ progress
213
+ };
214
+ }
215
+ }
216
+ if (progress.completed === progress.total) {
217
+ return {
218
+ allowed: true,
219
+ status: "PLAN_COMPLETE",
220
+ reason: "All plan steps are completed.",
221
+ progress
222
+ };
223
+ }
224
+ const eventText = normalizeEventText(event);
225
+ const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
226
+ if (!matched) {
227
+ return {
228
+ allowed: false,
229
+ status: "OFF_PLAN",
230
+ reason: "Action does not match any plan step.",
231
+ closestStep: closest?.label,
232
+ similarityScore: closestScore,
233
+ progress
234
+ };
235
+ }
236
+ if (!isSequenceValid(matched, plan)) {
237
+ const pendingDeps = (matched.requires ?? []).filter((reqId) => plan.steps.find((s) => s.id === reqId)?.status !== "completed").join(", ");
238
+ return {
239
+ allowed: false,
240
+ status: "OFF_PLAN",
241
+ reason: `Step "${matched.label}" requires completion of: ${pendingDeps}`,
242
+ matchedStep: matched.id,
243
+ progress
244
+ };
245
+ }
246
+ const { violated } = checkConstraints(event, eventText, plan.constraints);
247
+ if (violated) {
248
+ return {
249
+ allowed: false,
250
+ status: "CONSTRAINT_VIOLATED",
251
+ reason: violated.description,
252
+ matchedStep: matched.id,
253
+ progress
254
+ };
255
+ }
256
+ return {
257
+ allowed: true,
258
+ status: "ON_PLAN",
259
+ reason: `Matches step: ${matched.label}`,
260
+ matchedStep: matched.id,
261
+ progress
262
+ };
263
+ }
264
+ function buildPlanCheck(event, plan, verdict) {
265
+ const eventText = normalizeEventText(event);
266
+ const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
267
+ const { checks: constraintChecks } = checkConstraints(event, eventText, plan.constraints);
268
+ const progress = getPlanProgress(plan);
269
+ return {
270
+ planId: plan.plan_id,
271
+ matched: !!matched,
272
+ matchedStepId: matched?.id,
273
+ matchedStepLabel: matched?.label,
274
+ closestStepId: !matched ? closest?.id : void 0,
275
+ closestStepLabel: !matched ? closest?.label : void 0,
276
+ similarityScore: !matched ? closestScore : void 0,
277
+ sequenceValid: matched ? isSequenceValid(matched, plan) : void 0,
278
+ constraintsChecked: constraintChecks,
279
+ progress: { completed: progress.completed, total: progress.total }
280
+ };
281
+ }
282
+ var init_plan_engine = __esm({
283
+ "src/engine/plan-engine.ts"() {
284
+ "use strict";
285
+ init_text_utils();
286
+ }
287
+ });
288
+
289
+ // src/engine/bootstrap-parser.ts
290
+ var bootstrap_parser_exports = {};
291
+ __export(bootstrap_parser_exports, {
292
+ parseWorldMarkdown: () => parseWorldMarkdown
293
+ });
294
+ function splitSections(markdown) {
295
+ const lines = markdown.split("\n");
296
+ let frontmatter = "";
297
+ let bodyStart = 0;
298
+ if (lines[0]?.trim() === "---") {
299
+ const endIdx = lines.indexOf("---", 1);
300
+ if (endIdx > 0) {
301
+ frontmatter = lines.slice(1, endIdx).join("\n");
302
+ bodyStart = endIdx + 1;
303
+ }
304
+ }
305
+ const sections = [];
306
+ let currentSection = null;
307
+ const contentLines = [];
308
+ for (let i = bodyStart; i < lines.length; i++) {
309
+ const line = lines[i];
310
+ if (line.startsWith("# ")) {
311
+ if (currentSection) {
312
+ currentSection.content = contentLines.join("\n").trim();
313
+ sections.push(currentSection);
314
+ contentLines.length = 0;
315
+ }
316
+ currentSection = {
317
+ name: line.replace(/^#\s+/, "").trim(),
318
+ content: "",
319
+ startLine: i + 1
320
+ // 1-based
321
+ };
322
+ } else if (currentSection) {
323
+ contentLines.push(line);
324
+ }
325
+ }
326
+ if (currentSection) {
327
+ currentSection.content = contentLines.join("\n").trim();
328
+ sections.push(currentSection);
329
+ }
330
+ return { frontmatter, sections };
331
+ }
332
+ function parseFrontmatter2(yaml, issues) {
333
+ const result = {};
334
+ for (const line of yaml.split("\n")) {
335
+ const trimmed = line.trim();
336
+ if (!trimmed || trimmed.startsWith("#")) continue;
337
+ const colonIdx = trimmed.indexOf(":");
338
+ if (colonIdx === -1) continue;
339
+ const key = trimmed.slice(0, colonIdx).trim();
340
+ const value = trimmed.slice(colonIdx + 1).trim();
341
+ result[key] = value;
342
+ }
343
+ if (!result.world_id) {
344
+ issues.push({ line: 1, section: "frontmatter", message: "Missing world_id in frontmatter", severity: "error" });
345
+ }
346
+ if (!result.name) {
347
+ issues.push({ line: 1, section: "frontmatter", message: "Missing name in frontmatter", severity: "error" });
348
+ }
349
+ return {
350
+ world_id: result.world_id ?? "",
351
+ name: result.name ?? "",
352
+ version: result.version,
353
+ runtime_mode: result.runtime_mode,
354
+ default_profile: result.default_profile,
355
+ alternative_profile: result.alternative_profile
356
+ };
357
+ }
358
+ function parseThesis(content, startLine, issues) {
359
+ const thesis = content.trim();
360
+ if (!thesis) {
361
+ issues.push({ line: startLine, section: "Thesis", message: "Thesis section is empty", severity: "error" });
362
+ }
363
+ return thesis;
364
+ }
365
+ function parseInvariants(content, startLine, issues) {
366
+ const invariants = [];
367
+ const lines = content.split("\n");
368
+ for (let i = 0; i < lines.length; i++) {
369
+ const line = lines[i].trim();
370
+ if (!line.startsWith("- ")) continue;
371
+ const lineNum = startLine + i + 1;
372
+ const match = line.match(
373
+ /^-\s+`([^`]+)`\s*[—–-]\s*(.+?)(?:\s*\(([^)]+)\))?\s*$/
374
+ );
375
+ if (match) {
376
+ const id = match[1];
377
+ const label = match[2].trim();
378
+ const parens = match[3] ?? "structural, immutable";
379
+ const enforcement = parens.includes("prompt") ? "prompt" : parens.includes("operational") ? "operational" : "structural";
380
+ const mutable = parens.includes("mutable") && !parens.includes("immutable");
381
+ invariants.push({ id, label, enforcement, mutable, line: lineNum });
382
+ } else {
383
+ const fallback = line.match(/^-\s+\*\*([^*]+)\*\*\s*[—–-]\s*(.+)/);
384
+ if (fallback) {
385
+ const id = fallback[1].toLowerCase().replace(/\s+/g, "_");
386
+ const label = fallback[2].trim();
387
+ invariants.push({ id, label, enforcement: "structural", mutable: false, line: lineNum });
388
+ } else {
389
+ issues.push({ line: lineNum, section: "Invariants", message: `Could not parse invariant: "${line}"`, severity: "warning" });
390
+ }
391
+ }
392
+ }
393
+ if (invariants.length === 0) {
394
+ issues.push({ line: startLine, section: "Invariants", message: "No invariants found", severity: "error" });
395
+ }
396
+ return invariants;
397
+ }
398
+ function parseStateVariables(content, startLine, issues) {
399
+ const variables = [];
400
+ const subSections = splitH2Sections(content, startLine);
401
+ for (const sub of subSections) {
402
+ const props = parseKeyValueBullets(sub.content);
403
+ const lineNum = sub.startLine;
404
+ const type = props.type;
405
+ if (!type) {
406
+ issues.push({ line: lineNum, section: "State", message: `Variable "${sub.name}" missing type`, severity: "error" });
407
+ continue;
408
+ }
409
+ let defaultVal = props.default ?? "";
410
+ if (type === "number") {
411
+ defaultVal = parseFloat(String(defaultVal)) || 0;
412
+ } else if (type === "boolean") {
413
+ defaultVal = String(defaultVal).toLowerCase() === "true";
414
+ }
415
+ const variable = {
416
+ id: sub.name,
417
+ type,
418
+ default: defaultVal,
419
+ label: props.label ?? sub.name,
420
+ description: props.description ?? "",
421
+ line: lineNum
422
+ };
423
+ if (type === "number") {
424
+ if (props.min !== void 0) variable.min = parseFloat(props.min);
425
+ if (props.max !== void 0) variable.max = parseFloat(props.max);
426
+ if (props.step !== void 0) variable.step = parseFloat(props.step);
427
+ }
428
+ if (type === "enum" && props.options) {
429
+ variable.options = props.options.split(",").map((s) => s.trim());
430
+ }
431
+ variables.push(variable);
432
+ }
433
+ return variables;
434
+ }
435
+ function parseAssumptions(content, startLine, issues) {
436
+ const profiles = [];
437
+ const subSections = splitH2Sections(content, startLine);
438
+ for (const sub of subSections) {
439
+ const props = parseKeyValueBullets(sub.content);
440
+ const name = props.name ?? sub.name;
441
+ const description = props.description ?? "";
442
+ const parameters = {};
443
+ for (const [key, val] of Object.entries(props)) {
444
+ if (key === "name" || key === "description") continue;
445
+ if (val === "true") parameters[key] = true;
446
+ else if (val === "false") parameters[key] = false;
447
+ else if (!isNaN(Number(val)) && val.trim() !== "") parameters[key] = Number(val);
448
+ else parameters[key] = val;
449
+ }
450
+ profiles.push({
451
+ id: sub.name,
452
+ name,
453
+ description,
454
+ parameters,
455
+ line: sub.startLine
456
+ });
457
+ }
458
+ return profiles;
459
+ }
460
+ function parseRules(content, startLine, issues) {
461
+ const rules = [];
462
+ const subSections = splitH2Sections(content, startLine);
463
+ for (let ruleIdx = 0; ruleIdx < subSections.length; ruleIdx++) {
464
+ const sub = subSections[ruleIdx];
465
+ const lineNum = sub.startLine;
466
+ const headingMatch = sub.name.match(/^([^:]+):\s*(.+?)(?:\s*\(([^)]+)\))?\s*$/);
467
+ const id = headingMatch ? headingMatch[1].trim() : `rule-${String(ruleIdx + 1).padStart(3, "0")}`;
468
+ const label = headingMatch ? headingMatch[2].trim() : sub.name;
469
+ const severity = headingMatch?.[3]?.trim() ?? "degradation";
470
+ const lines = sub.content.split("\n");
471
+ let description = "";
472
+ const triggers = [];
473
+ const effects = [];
474
+ let collapseCheck;
475
+ const causalParts = {};
476
+ for (let i = 0; i < lines.length; i++) {
477
+ const line = lines[i].trim();
478
+ if (line.startsWith("When ")) {
479
+ const triggerStr = line.slice(5);
480
+ const parts = triggerStr.split(/\s+AND\s+/i);
481
+ for (const part of parts) {
482
+ const trigger = parseTriggerExpression(part.trim());
483
+ if (trigger) triggers.push(trigger);
484
+ else issues.push({ line: lineNum + i, section: "Rules", message: `Could not parse trigger: "${part}"`, severity: "warning" });
485
+ }
486
+ } else if (line.startsWith("Then ")) {
487
+ const effectStr = line.slice(5);
488
+ const parts = effectStr.split(",");
489
+ for (const part of parts) {
490
+ const effect = parseEffectExpression(part.trim());
491
+ if (effect) effects.push(effect);
492
+ else issues.push({ line: lineNum + i, section: "Rules", message: `Could not parse effect: "${part}"`, severity: "warning" });
493
+ }
494
+ } else if (line.startsWith("Collapse:")) {
495
+ const collapseStr = line.slice(9).trim();
496
+ const collapse = parseCollapseExpression(collapseStr);
497
+ if (collapse) collapseCheck = collapse;
498
+ else issues.push({ line: lineNum + i, section: "Rules", message: `Could not parse collapse: "${collapseStr}"`, severity: "warning" });
499
+ } else if (line.startsWith("> ")) {
500
+ const causalMatch = line.match(/^>\s*(trigger|rule|shift|effect):\s*(.+)/i);
501
+ if (causalMatch) {
502
+ causalParts[causalMatch[1].toLowerCase()] = causalMatch[2].trim();
503
+ }
504
+ } else if (line && !line.startsWith("-") && !line.startsWith("#")) {
505
+ if (!description) description = line;
506
+ else description += " " + line;
507
+ }
508
+ }
509
+ if (triggers.length === 0) {
510
+ issues.push({ line: lineNum, section: "Rules", message: `Rule "${id}" has no triggers (missing "When" line)`, severity: "warning" });
511
+ }
512
+ if (effects.length === 0) {
513
+ issues.push({ line: lineNum, section: "Rules", message: `Rule "${id}" has no effects (missing "Then" line)`, severity: "warning" });
514
+ }
515
+ const causal_translation = Object.keys(causalParts).length > 0 ? {
516
+ trigger_text: causalParts.trigger ?? "",
517
+ rule_text: causalParts.rule ?? "",
518
+ shift_text: causalParts.shift ?? "",
519
+ effect_text: causalParts.effect ?? ""
520
+ } : void 0;
521
+ rules.push({
522
+ id,
523
+ label,
524
+ severity,
525
+ description: description || void 0,
526
+ order: ruleIdx + 1,
527
+ triggers,
528
+ effects,
529
+ collapse_check: collapseCheck,
530
+ causal_translation,
531
+ line: lineNum
532
+ });
533
+ }
534
+ return rules;
535
+ }
536
+ function parseTriggerExpression(expr) {
537
+ const match = expr.match(
538
+ /^(\w+)\s*(==|!=|>=|<=|>|<|in)\s*(.+?)\s*\[(state|assumption)\]\s*$/
539
+ );
540
+ if (!match) return null;
541
+ const field = match[1];
542
+ const operator = match[2];
543
+ let value = match[3].trim();
544
+ const source = match[4];
545
+ value = parseValueLiteral(value);
546
+ return { field, operator, value, source };
547
+ }
548
+ function parseEffectExpression(expr) {
549
+ const compound = expr.match(/^(\w+)\s*(\*=|\+=|-=)\s*(.+)$/);
550
+ if (compound) {
551
+ const target = compound[1];
552
+ const op = compound[2];
553
+ const value = parseValueLiteral(compound[3].trim());
554
+ const operationMap = {
555
+ "*=": "multiply",
556
+ "+=": "add",
557
+ "-=": "subtract"
558
+ };
559
+ return { target, operation: operationMap[op], value };
560
+ }
561
+ const assignment = expr.match(/^(\w+)\s*=\s*(.+)$/);
562
+ if (assignment) {
563
+ const target = assignment[1];
564
+ const value = parseValueLiteral(assignment[2].trim());
565
+ const operation = typeof value === "boolean" ? "set_boolean" : "set";
566
+ return { target, operation, value };
567
+ }
568
+ return null;
569
+ }
570
+ function parseCollapseExpression(expr) {
571
+ const cleaned = expr.replace(/\s*→.*$/, "").trim();
572
+ const match = cleaned.match(/^(\w+)\s*(==|!=|>=|<=|>|<)\s*([\d.]+)$/);
573
+ if (!match) return null;
574
+ return {
575
+ field: match[1],
576
+ operator: match[2],
577
+ value: parseFloat(match[3])
578
+ };
579
+ }
580
+ function parseGates(content, startLine, issues) {
581
+ const gates = [];
582
+ const lines = content.split("\n");
583
+ for (let i = 0; i < lines.length; i++) {
584
+ const line = lines[i].trim();
585
+ if (!line.startsWith("- ")) continue;
586
+ const lineNum = startLine + i + 1;
587
+ const match = line.match(/^-\s+(\w+):\s*(\w+)\s*(==|!=|>=|<=|>|<)\s*([\d.]+)/);
588
+ if (match) {
589
+ gates.push({
590
+ status: match[1],
591
+ field: match[2],
592
+ operator: match[3],
593
+ value: parseFloat(match[4]),
594
+ line: lineNum
595
+ });
596
+ } else {
597
+ issues.push({ line: lineNum, section: "Gates", message: `Could not parse gate: "${line}"`, severity: "warning" });
598
+ }
599
+ }
600
+ if (gates.length === 0) {
601
+ issues.push({ line: startLine, section: "Gates", message: "No gates found", severity: "error" });
602
+ }
603
+ return gates;
604
+ }
605
+ function parseOutcomes(content, startLine, issues) {
606
+ const outcomes = [];
607
+ const subSections = splitH2Sections(content, startLine);
608
+ for (const sub of subSections) {
609
+ const props = parseKeyValueBullets(sub.content);
610
+ const outcome = {
611
+ id: sub.name,
612
+ type: props.type ?? "number",
613
+ label: props.label ?? sub.name,
614
+ line: sub.startLine
615
+ };
616
+ if (props.range) {
617
+ const rangeParts = props.range.split("-").map(Number);
618
+ if (rangeParts.length === 2 && !isNaN(rangeParts[0]) && !isNaN(rangeParts[1])) {
619
+ outcome.range = [rangeParts[0], rangeParts[1]];
620
+ }
621
+ }
622
+ if (props.display) outcome.display = props.display;
623
+ if (props.primary) outcome.primary = props.primary === "true";
624
+ if (props.assignment) outcome.assignment = props.assignment;
625
+ outcomes.push(outcome);
626
+ }
627
+ return outcomes;
628
+ }
629
+ function splitH2Sections(content, baseStartLine) {
630
+ const lines = content.split("\n");
631
+ const sections = [];
632
+ let current = null;
633
+ const contentLines = [];
634
+ for (let i = 0; i < lines.length; i++) {
635
+ const line = lines[i];
636
+ if (line.startsWith("## ")) {
637
+ if (current) {
638
+ current.content = contentLines.join("\n").trim();
639
+ sections.push(current);
640
+ contentLines.length = 0;
641
+ }
642
+ current = {
643
+ name: line.replace(/^##\s+/, "").trim(),
644
+ content: "",
645
+ startLine: baseStartLine + i + 1
646
+ };
647
+ } else if (current) {
648
+ contentLines.push(line);
649
+ }
650
+ }
651
+ if (current) {
652
+ current.content = contentLines.join("\n").trim();
653
+ sections.push(current);
654
+ }
655
+ return sections;
656
+ }
657
+ function parseKeyValueBullets(content) {
658
+ const result = {};
659
+ for (const line of content.split("\n")) {
660
+ const trimmed = line.trim();
661
+ const match = trimmed.match(/^-\s+(\w[\w\s]*?):\s*(.+)$/);
662
+ if (match) {
663
+ result[match[1].trim().toLowerCase().replace(/\s+/g, "_")] = match[2].trim();
664
+ }
665
+ }
666
+ return result;
667
+ }
668
+ function parseValueLiteral(raw) {
669
+ if (raw === "true") return true;
670
+ if (raw === "false") return false;
671
+ if (raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("'") && raw.endsWith("'")) {
672
+ return raw.slice(1, -1);
673
+ }
674
+ const num = Number(raw);
675
+ if (!isNaN(num) && raw.trim() !== "") return num;
676
+ return raw;
677
+ }
678
+ function parseWorldMarkdown(markdown) {
679
+ const issues = [];
680
+ const { frontmatter: fmRaw, sections } = splitSections(markdown);
681
+ const frontmatter = parseFrontmatter2(fmRaw, issues);
682
+ const findSection = (name) => sections.find((s) => s.name.toLowerCase() === name.toLowerCase());
683
+ const thesisSection = findSection("Thesis");
684
+ const thesis = thesisSection ? parseThesis(thesisSection.content, thesisSection.startLine, issues) : "";
685
+ if (!thesisSection) {
686
+ issues.push({ line: 0, section: "Thesis", message: "Missing # Thesis section", severity: "error" });
687
+ }
688
+ const invariantsSection = findSection("Invariants");
689
+ const invariants = invariantsSection ? parseInvariants(invariantsSection.content, invariantsSection.startLine, issues) : [];
690
+ if (!invariantsSection) {
691
+ issues.push({ line: 0, section: "Invariants", message: "Missing # Invariants section", severity: "error" });
692
+ }
693
+ const stateSection = findSection("State");
694
+ const stateVariables = stateSection ? parseStateVariables(stateSection.content, stateSection.startLine, issues) : [];
695
+ if (!stateSection) {
696
+ issues.push({ line: 0, section: "State", message: "Missing # State section", severity: "warning" });
697
+ }
698
+ const assumptionsSection = findSection("Assumptions");
699
+ const assumptions = assumptionsSection ? parseAssumptions(assumptionsSection.content, assumptionsSection.startLine, issues) : [];
700
+ if (!assumptionsSection) {
701
+ issues.push({ line: 0, section: "Assumptions", message: "Missing # Assumptions section", severity: "warning" });
702
+ }
703
+ const rulesSection = findSection("Rules");
704
+ const rules = rulesSection ? parseRules(rulesSection.content, rulesSection.startLine, issues) : [];
705
+ if (!rulesSection) {
706
+ issues.push({ line: 0, section: "Rules", message: "Missing # Rules section", severity: "warning" });
707
+ }
708
+ const gatesSection = findSection("Gates");
709
+ const gates = gatesSection ? parseGates(gatesSection.content, gatesSection.startLine, issues) : [];
710
+ if (!gatesSection) {
711
+ issues.push({ line: 0, section: "Gates", message: "Missing # Gates section", severity: "warning" });
712
+ }
713
+ const outcomesSection = findSection("Outcomes");
714
+ const outcomes = outcomesSection ? parseOutcomes(outcomesSection.content, outcomesSection.startLine, issues) : [];
715
+ const parsedSections = sections.map((s) => s.name);
716
+ const knownSections = /* @__PURE__ */ new Set(["thesis", "invariants", "state", "assumptions", "rules", "gates", "outcomes"]);
717
+ for (const section of sections) {
718
+ if (!knownSections.has(section.name.toLowerCase())) {
719
+ issues.push({
720
+ line: section.startLine,
721
+ section: section.name,
722
+ message: `Unrecognized section "${section.name}" \u2014 will be ignored`,
723
+ severity: "info"
724
+ });
725
+ }
726
+ }
727
+ const hasErrors = issues.some((i) => i.severity === "error");
728
+ if (!frontmatter.world_id || !thesis) {
729
+ if (hasErrors) {
730
+ return { world: null, issues };
731
+ }
732
+ }
733
+ return {
734
+ world: {
735
+ frontmatter,
736
+ thesis,
737
+ invariants,
738
+ stateVariables,
739
+ assumptions,
740
+ rules,
741
+ gates,
742
+ outcomes
743
+ },
744
+ issues
745
+ };
746
+ }
747
+ var init_bootstrap_parser = __esm({
748
+ "src/engine/bootstrap-parser.ts"() {
749
+ "use strict";
750
+ }
751
+ });
752
+
753
+ // src/engine/bootstrap-emitter.ts
754
+ var bootstrap_emitter_exports = {};
755
+ __export(bootstrap_emitter_exports, {
756
+ emitWorldDefinition: () => emitWorldDefinition
757
+ });
758
+ function emitWorldDefinition(parsed) {
759
+ const issues = [];
760
+ const fm = parsed.frontmatter;
761
+ const defaultProfile = fm.default_profile ?? parsed.assumptions[0]?.id ?? "baseline";
762
+ const altProfile = fm.alternative_profile ?? parsed.assumptions[1]?.id ?? "alternative";
763
+ const world = {
764
+ world_id: fm.world_id,
765
+ name: fm.name,
766
+ thesis: parsed.thesis,
767
+ version: fm.version ?? "1.0.0",
768
+ runtime_mode: fm.runtime_mode ?? "SIMULATION",
769
+ default_assumption_profile: defaultProfile,
770
+ default_alternative_profile: altProfile,
771
+ modules: parsed.rules.map((r) => r.id),
772
+ players: {
773
+ thinking_space: true,
774
+ experience_space: true,
775
+ action_space: true
776
+ }
777
+ };
778
+ const invariants = parsed.invariants.map((inv) => ({
779
+ id: inv.id,
780
+ label: inv.label,
781
+ enforcement: inv.enforcement === "prompt" ? "prompt" : "structural",
782
+ mutable: false
783
+ }));
784
+ const profiles = {};
785
+ const parameterDefinitions = {};
786
+ for (let i = 0; i < parsed.assumptions.length; i++) {
787
+ const profile = parsed.assumptions[i];
788
+ const params = {};
789
+ for (const [key, val] of Object.entries(profile.parameters)) {
790
+ params[key] = String(val);
791
+ if (!parameterDefinitions[key]) {
792
+ parameterDefinitions[key] = {
793
+ type: typeof val === "boolean" ? "boolean" : typeof val === "number" ? "number" : "enum",
794
+ label: key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
795
+ description: `Parameter: ${key}`
796
+ };
797
+ }
798
+ }
799
+ profiles[profile.id] = {
800
+ name: profile.name,
801
+ description: profile.description,
802
+ is_default_baseline: i === 0 || profile.id === defaultProfile,
803
+ is_default_alternative: i === 1 || profile.id === altProfile,
804
+ parameters: params
805
+ };
806
+ }
807
+ const assumptions = { profiles, parameter_definitions: parameterDefinitions };
808
+ const variables = {};
809
+ for (const v of parsed.stateVariables) {
810
+ const stateVar = {
811
+ type: v.type,
812
+ default: v.default,
813
+ mutable: true,
814
+ label: v.label,
815
+ description: v.description
816
+ };
817
+ if (v.type === "number") {
818
+ if (v.min !== void 0) stateVar.min = v.min;
819
+ if (v.max !== void 0) stateVar.max = v.max;
820
+ if (v.step !== void 0) stateVar.step = v.step;
821
+ }
822
+ if (v.type === "enum" && v.options) {
823
+ stateVar.options = v.options;
824
+ }
825
+ variables[v.id] = stateVar;
826
+ }
827
+ const stateSchema = { variables, presets: {} };
828
+ const rules = parsed.rules.map((r) => {
829
+ const triggers = r.triggers.map((t) => ({
830
+ field: t.field,
831
+ operator: t.operator,
832
+ value: t.value,
833
+ source: t.source
834
+ }));
835
+ const effects = r.effects.map((e) => ({
836
+ target: e.target,
837
+ operation: e.operation,
838
+ value: e.value
839
+ }));
840
+ let collapse_check;
841
+ if (r.collapse_check) {
842
+ collapse_check = {
843
+ field: r.collapse_check.field,
844
+ operator: r.collapse_check.operator,
845
+ value: r.collapse_check.value,
846
+ result: "MODEL_COLLAPSES"
847
+ };
848
+ }
849
+ const causal_translation = r.causal_translation ?? {
850
+ trigger_text: "",
851
+ rule_text: "",
852
+ shift_text: "",
853
+ effect_text: ""
854
+ };
855
+ const rule = {
856
+ id: r.id,
857
+ severity: r.severity,
858
+ label: r.label,
859
+ description: r.description ?? r.label,
860
+ order: r.order,
861
+ triggers,
862
+ effects: effects.length > 0 ? effects : void 0,
863
+ collapse_check,
864
+ causal_translation
865
+ };
866
+ return rule;
867
+ });
868
+ const viabilityClassification = parsed.gates.map((g) => {
869
+ const defaults = GATE_DEFAULTS[g.status] ?? { color: "#5c5a52", icon: "\u25CF" };
870
+ return {
871
+ status: g.status,
872
+ field: g.field,
873
+ operator: g.operator,
874
+ value: g.value,
875
+ color: defaults.color,
876
+ icon: defaults.icon
877
+ };
878
+ });
879
+ const gates = {
880
+ viability_classification: viabilityClassification,
881
+ structural_override: {
882
+ description: "Rules with severity=structural and triggered collapse_check force MODEL_COLLAPSES regardless of final margin.",
883
+ enforcement: "mandatory"
884
+ },
885
+ sustainability_threshold: 0.1,
886
+ collapse_visual: {
887
+ background: "#1c1917",
888
+ text: "#fef2f2",
889
+ border: "#b91c1c",
890
+ label: "Structural Failure"
891
+ }
892
+ };
893
+ const computedOutcomes = parsed.outcomes.map((o) => {
894
+ const outcome = {
895
+ id: o.id,
896
+ type: o.type,
897
+ label: o.label,
898
+ show_in_comparison: true
899
+ };
900
+ if (o.range) outcome.range = o.range;
901
+ if (o.display) outcome.display_as = o.display;
902
+ if (o.primary) outcome.primary = o.primary;
903
+ if (o.assignment) outcome.assignment = o.assignment;
904
+ return outcome;
905
+ });
906
+ const outcomes = {
907
+ computed_outcomes: computedOutcomes,
908
+ comparison_layout: {
909
+ primary_card: computedOutcomes.find((o) => o.primary)?.id ?? computedOutcomes[0]?.id ?? "",
910
+ status_badge: "viability_status",
911
+ structural_indicators: rules.filter((r) => r.severity === "structural").map((r) => r.id)
912
+ }
913
+ };
914
+ const metadata = {
915
+ format_version: "1.0.0",
916
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
917
+ last_modified: (/* @__PURE__ */ new Date()).toISOString(),
918
+ authoring_method: "manual-authoring"
919
+ };
920
+ const worldDefinition = {
921
+ world,
922
+ invariants,
923
+ assumptions,
924
+ stateSchema,
925
+ rules,
926
+ gates,
927
+ outcomes,
928
+ metadata
929
+ };
930
+ return { world: worldDefinition, issues };
931
+ }
932
+ var GATE_DEFAULTS;
933
+ var init_bootstrap_emitter = __esm({
934
+ "src/engine/bootstrap-emitter.ts"() {
935
+ "use strict";
936
+ GATE_DEFAULTS = {
937
+ THRIVING: { color: "#0f6b3a", icon: "\u2726" },
938
+ STABLE: { color: "#1856b8", icon: "\u25CF" },
939
+ COMPRESSED: { color: "#a16207", icon: "\u25B2" },
940
+ CRITICAL: { color: "#b91c1c", icon: "\u26A0" },
941
+ MODEL_COLLAPSES: { color: "#7f1d1d", icon: "\u2715" }
942
+ };
943
+ }
944
+ });
945
+
946
+ // src/loader/world-loader.ts
947
+ var world_loader_exports = {};
948
+ __export(world_loader_exports, {
949
+ DEFAULT_BUNDLED_WORLD: () => DEFAULT_BUNDLED_WORLD,
950
+ loadBundledWorld: () => loadBundledWorld,
951
+ loadWorld: () => loadWorld,
952
+ loadWorldFromDirectory: () => loadWorldFromDirectory
953
+ });
954
+ async function loadWorldFromDirectory(dirPath) {
955
+ const { readFile } = await import("fs/promises");
956
+ const { join } = await import("path");
957
+ const { readdirSync } = await import("fs");
958
+ async function readJson(filename) {
959
+ const filePath = join(dirPath, filename);
960
+ try {
961
+ const content = await readFile(filePath, "utf-8");
962
+ return JSON.parse(content);
963
+ } catch (err) {
964
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
965
+ return void 0;
966
+ }
967
+ process.stderr.write(
968
+ `[neuroverse] Warning: Failed to read ${filename}: ${err instanceof Error ? err.message : String(err)}
969
+ `
970
+ );
971
+ return void 0;
972
+ }
973
+ }
974
+ const worldJson = await readJson("world.json");
975
+ if (!worldJson) {
976
+ throw new Error(`Cannot read world.json in ${dirPath}`);
977
+ }
978
+ const invariantsJson = await readJson("invariants.json");
979
+ const assumptionsJson = await readJson("assumptions.json");
980
+ const stateSchemaJson = await readJson("state-schema.json");
981
+ const gatesJson = await readJson("gates.json");
982
+ const outcomesJson = await readJson("outcomes.json");
983
+ const guardsJson = await readJson("guards.json");
984
+ const rolesJson = await readJson("roles.json");
985
+ const kernelJson = await readJson("kernel.json");
986
+ const metadataJson = await readJson("metadata.json");
987
+ const rules = [];
988
+ try {
989
+ const rulesDir = join(dirPath, "rules");
990
+ const ruleFiles = readdirSync(rulesDir).filter((f) => f.endsWith(".json")).sort();
991
+ for (const file of ruleFiles) {
992
+ try {
993
+ const content = await readFile(join(rulesDir, file), "utf-8");
994
+ rules.push(JSON.parse(content));
995
+ } catch (err) {
996
+ process.stderr.write(
997
+ `[neuroverse] Warning: Failed to parse rule ${file}: ${err instanceof Error ? err.message : String(err)}
998
+ `
999
+ );
1000
+ }
1001
+ }
1002
+ } catch (err) {
1003
+ if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) {
1004
+ process.stderr.write(
1005
+ `[neuroverse] Warning: Failed to read rules directory: ${err instanceof Error ? err.message : String(err)}
1006
+ `
1007
+ );
1008
+ }
1009
+ }
1010
+ return {
1011
+ world: worldJson,
1012
+ invariants: invariantsJson?.invariants ?? [],
1013
+ assumptions: assumptionsJson ?? { profiles: {}, parameter_definitions: {} },
1014
+ stateSchema: stateSchemaJson ?? { variables: {}, presets: {} },
1015
+ rules,
1016
+ gates: gatesJson ?? {
1017
+ viability_classification: [],
1018
+ structural_override: { description: "", enforcement: "mandatory" },
1019
+ sustainability_threshold: 0,
1020
+ collapse_visual: { background: "", text: "", border: "", label: "" }
1021
+ },
1022
+ outcomes: outcomesJson ?? {
1023
+ computed_outcomes: [],
1024
+ comparison_layout: { primary_card: "", status_badge: "", structural_indicators: [] }
1025
+ },
1026
+ guards: guardsJson,
1027
+ roles: rolesJson,
1028
+ kernel: kernelJson,
1029
+ metadata: metadataJson ?? {
1030
+ format_version: "1.0.0",
1031
+ created_at: "",
1032
+ last_modified: "",
1033
+ authoring_method: "manual-authoring"
1034
+ }
1035
+ };
1036
+ }
1037
+ async function loadWorld(worldPath) {
1038
+ const { stat } = await import("fs/promises");
1039
+ const info = await stat(worldPath);
1040
+ if (info.isDirectory()) {
1041
+ return loadWorldFromDirectory(worldPath);
1042
+ }
1043
+ throw new Error(`Cannot load world from: ${worldPath} \u2014 expected a directory`);
1044
+ }
1045
+ async function loadBundledWorld(name = DEFAULT_BUNDLED_WORLD) {
1046
+ const { readFile } = await import("fs/promises");
1047
+ const { join, dirname } = await import("path");
1048
+ const { existsSync } = await import("fs");
1049
+ const { fileURLToPath } = await import("url");
1050
+ const { parseWorldMarkdown: parseWorldMarkdown2 } = await Promise.resolve().then(() => (init_bootstrap_parser(), bootstrap_parser_exports));
1051
+ const { emitWorldDefinition: emitWorldDefinition2 } = await Promise.resolve().then(() => (init_bootstrap_emitter(), bootstrap_emitter_exports));
1052
+ const filename = `${name}.nv-world.md`;
1053
+ let packageRoot;
1054
+ try {
1055
+ const thisFile = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import_meta.url));
1056
+ packageRoot = join(thisFile, "..", "..");
1057
+ } catch {
1058
+ packageRoot = process.cwd();
1059
+ }
1060
+ const candidates = [
1061
+ join(packageRoot, "dist", "worlds", filename),
1062
+ join(packageRoot, "src", "worlds", filename)
1063
+ ];
1064
+ for (const candidate of candidates) {
1065
+ if (existsSync(candidate)) {
1066
+ const markdown = await readFile(candidate, "utf-8");
1067
+ const parsed = parseWorldMarkdown2(markdown);
1068
+ if (!parsed.world) {
1069
+ throw new Error(`Failed to parse bundled world: ${candidate}`);
1070
+ }
1071
+ const { world } = emitWorldDefinition2(parsed.world);
1072
+ return world;
1073
+ }
1074
+ }
1075
+ throw new Error(
1076
+ `Bundled world "${name}" not found. Searched:
1077
+ ` + candidates.map((c) => ` ${c}`).join("\n")
1078
+ );
1079
+ }
1080
+ var import_meta, DEFAULT_BUNDLED_WORLD;
1081
+ var init_world_loader = __esm({
1082
+ "src/loader/world-loader.ts"() {
1083
+ "use strict";
1084
+ import_meta = {};
1085
+ DEFAULT_BUNDLED_WORLD = "coding-agent";
1086
+ }
1087
+ });
1088
+
1089
+ // src/engine/guard-engine.ts
1090
+ var guard_engine_exports = {};
1091
+ __export(guard_engine_exports, {
1092
+ evaluateGuard: () => evaluateGuard,
1093
+ eventToAllowlistKey: () => eventToAllowlistKey
1094
+ });
1095
+ function levelRequiresConfirmation(level, actionType) {
1096
+ if (level === "strict") return true;
1097
+ if (level === "standard") {
1098
+ return actionType === "delete" || actionType === "credential-access";
1099
+ }
1100
+ return false;
1101
+ }
1102
+ function isExternalScope(scope) {
1103
+ const internalPatterns = [
1104
+ /^\.?\/?src\//i,
1105
+ /^\.?\/?lib\//i,
1106
+ /^\.?\/?app\//i,
1107
+ /^\.?\/?components\//i,
1108
+ /^\.?\/?pages\//i,
1109
+ /^\.?\/?public\//i,
1110
+ /^\.?\/?assets\//i,
1111
+ /^\.\//
1112
+ ];
1113
+ return !internalPatterns.some((p) => p.test(scope));
1114
+ }
1115
+ function evaluateGuard(event, world, options = {}) {
1116
+ const startTime = performance.now();
1117
+ const level = options.level ?? "standard";
1118
+ const includeTrace = options.trace ?? false;
1119
+ if (!event.intent || typeof event.intent !== "string") {
1120
+ return {
1121
+ status: "BLOCK",
1122
+ reason: "GuardEvent.intent is required and must be a string",
1123
+ ruleId: "safety-input-validation",
1124
+ evidence: {
1125
+ worldId: world.world?.world_id ?? "",
1126
+ worldName: world.world?.name ?? "",
1127
+ worldVersion: world.world?.version ?? "",
1128
+ evaluatedAt: Date.now(),
1129
+ invariantsSatisfied: 0,
1130
+ invariantsTotal: 0,
1131
+ guardsMatched: [],
1132
+ rulesMatched: [],
1133
+ enforcementLevel: level
1134
+ }
1135
+ };
1136
+ }
1137
+ const inputLength = event.intent.length + (event.tool?.length ?? 0) + (event.scope?.length ?? 0) + (event.payload ? JSON.stringify(event.payload).length : 0);
1138
+ if (inputLength > MAX_INPUT_LENGTH) {
1139
+ return {
1140
+ status: "BLOCK",
1141
+ reason: `Input exceeds maximum allowed length (${MAX_INPUT_LENGTH} characters)`,
1142
+ ruleId: "safety-input-length",
1143
+ evidence: {
1144
+ worldId: world.world?.world_id ?? "",
1145
+ worldName: world.world?.name ?? "",
1146
+ worldVersion: world.world?.version ?? "",
1147
+ evaluatedAt: Date.now(),
1148
+ invariantsSatisfied: 0,
1149
+ invariantsTotal: 0,
1150
+ guardsMatched: [],
1151
+ rulesMatched: [],
1152
+ enforcementLevel: level
1153
+ }
1154
+ };
1155
+ }
1156
+ const eventText = normalizeEventText(event);
1157
+ const invariantChecks = [];
1158
+ const safetyChecks = [];
1159
+ let planCheckResult;
1160
+ const roleChecks = [];
1161
+ const guardChecks = [];
1162
+ const kernelRuleChecks = [];
1163
+ const levelChecks = [];
1164
+ let decidingLayer = "default-allow";
1165
+ let decidingId;
1166
+ const guardsMatched = [];
1167
+ const rulesMatched = [];
1168
+ checkInvariantCoverage(world, invariantChecks);
1169
+ if (event.roleId && options.agentStates) {
1170
+ const agentState = options.agentStates.get(event.roleId);
1171
+ if (agentState && agentState.cooldownRemaining > 0) {
1172
+ decidingLayer = "safety";
1173
+ decidingId = `penalize-cooldown-${event.roleId}`;
1174
+ const verdict = buildVerdict(
1175
+ "PENALIZE",
1176
+ `Agent "${event.roleId}" is frozen for ${agentState.cooldownRemaining} more round(s) due to prior penalty.`,
1177
+ `penalize-cooldown-${event.roleId}`,
1178
+ void 0,
1179
+ world,
1180
+ level,
1181
+ invariantChecks,
1182
+ guardsMatched,
1183
+ rulesMatched,
1184
+ includeTrace ? buildTrace(
1185
+ invariantChecks,
1186
+ safetyChecks,
1187
+ planCheckResult,
1188
+ roleChecks,
1189
+ guardChecks,
1190
+ kernelRuleChecks,
1191
+ levelChecks,
1192
+ decidingLayer,
1193
+ decidingId,
1194
+ startTime
1195
+ ) : void 0
1196
+ );
1197
+ verdict.intentRecord = {
1198
+ originalIntent: event.intent,
1199
+ finalAction: "blocked (agent frozen)",
1200
+ enforcement: "PENALIZE",
1201
+ consequence: { type: "freeze", rounds: agentState.cooldownRemaining, description: "Agent still in cooldown from prior penalty" }
1202
+ };
1203
+ return verdict;
1204
+ }
1205
+ }
1206
+ if (options.sessionAllowlist) {
1207
+ const key = eventToAllowlistKey(event);
1208
+ if (options.sessionAllowlist.has(key)) {
1209
+ decidingLayer = "session-allowlist";
1210
+ decidingId = `allowlist:${key}`;
1211
+ return buildVerdict(
1212
+ "ALLOW",
1213
+ void 0,
1214
+ `allowlist:${key}`,
1215
+ void 0,
1216
+ world,
1217
+ level,
1218
+ invariantChecks,
1219
+ guardsMatched,
1220
+ rulesMatched,
1221
+ includeTrace ? buildTrace(
1222
+ invariantChecks,
1223
+ safetyChecks,
1224
+ planCheckResult,
1225
+ roleChecks,
1226
+ guardChecks,
1227
+ kernelRuleChecks,
1228
+ levelChecks,
1229
+ decidingLayer,
1230
+ decidingId,
1231
+ startTime
1232
+ ) : void 0
1233
+ );
1234
+ }
1235
+ }
1236
+ const safetyVerdict = checkSafety(event, eventText, safetyChecks);
1237
+ if (safetyVerdict) {
1238
+ decidingLayer = "safety";
1239
+ decidingId = safetyVerdict.ruleId;
1240
+ return buildVerdict(
1241
+ safetyVerdict.status,
1242
+ safetyVerdict.reason,
1243
+ safetyVerdict.ruleId,
1244
+ void 0,
1245
+ world,
1246
+ level,
1247
+ invariantChecks,
1248
+ guardsMatched,
1249
+ rulesMatched,
1250
+ includeTrace ? buildTrace(
1251
+ invariantChecks,
1252
+ safetyChecks,
1253
+ planCheckResult,
1254
+ roleChecks,
1255
+ guardChecks,
1256
+ kernelRuleChecks,
1257
+ levelChecks,
1258
+ decidingLayer,
1259
+ decidingId,
1260
+ startTime
1261
+ ) : void 0
1262
+ );
1263
+ }
1264
+ if (options.plan) {
1265
+ const planVerdict = evaluatePlan(event, options.plan);
1266
+ planCheckResult = buildPlanCheck(event, options.plan, planVerdict);
1267
+ if (!planVerdict.allowed && planVerdict.status !== "PLAN_COMPLETE") {
1268
+ decidingLayer = "plan-enforcement";
1269
+ decidingId = `plan-${options.plan.plan_id}`;
1270
+ const planStatus = planVerdict.status === "CONSTRAINT_VIOLATED" ? "PAUSE" : "BLOCK";
1271
+ let reason = planVerdict.reason ?? "Action blocked by plan.";
1272
+ if (planVerdict.status === "OFF_PLAN" && planVerdict.closestStep) {
1273
+ reason += ` Closest step: "${planVerdict.closestStep}" (similarity: ${(planVerdict.similarityScore ?? 0).toFixed(2)})`;
1274
+ }
1275
+ return buildVerdict(
1276
+ planStatus,
1277
+ reason,
1278
+ `plan-${options.plan.plan_id}`,
1279
+ void 0,
1280
+ world,
1281
+ level,
1282
+ invariantChecks,
1283
+ guardsMatched,
1284
+ rulesMatched,
1285
+ includeTrace ? buildTrace(
1286
+ invariantChecks,
1287
+ safetyChecks,
1288
+ planCheckResult,
1289
+ roleChecks,
1290
+ guardChecks,
1291
+ kernelRuleChecks,
1292
+ levelChecks,
1293
+ decidingLayer,
1294
+ decidingId,
1295
+ startTime
1296
+ ) : void 0
1297
+ );
1298
+ }
1299
+ }
1300
+ const roleVerdict = checkRoleRules(event, eventText, world, roleChecks);
1301
+ if (roleVerdict) {
1302
+ decidingLayer = "role";
1303
+ decidingId = roleVerdict.ruleId;
1304
+ return buildVerdict(
1305
+ roleVerdict.status,
1306
+ roleVerdict.reason,
1307
+ roleVerdict.ruleId,
1308
+ void 0,
1309
+ world,
1310
+ level,
1311
+ invariantChecks,
1312
+ guardsMatched,
1313
+ rulesMatched,
1314
+ includeTrace ? buildTrace(
1315
+ invariantChecks,
1316
+ safetyChecks,
1317
+ planCheckResult,
1318
+ roleChecks,
1319
+ guardChecks,
1320
+ kernelRuleChecks,
1321
+ levelChecks,
1322
+ decidingLayer,
1323
+ decidingId,
1324
+ startTime
1325
+ ) : void 0
1326
+ );
1327
+ }
1328
+ const guardVerdict = checkGuards(event, eventText, world, guardChecks, guardsMatched);
1329
+ if (guardVerdict) {
1330
+ if (guardVerdict.status !== "ALLOW") {
1331
+ decidingLayer = "guard";
1332
+ decidingId = guardVerdict.ruleId;
1333
+ const intentRecord = {
1334
+ originalIntent: event.intent,
1335
+ 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",
1336
+ ruleApplied: guardVerdict.ruleId,
1337
+ enforcement: guardVerdict.status,
1338
+ modifiedTo: guardVerdict.modifiedTo,
1339
+ consequence: guardVerdict.consequence,
1340
+ reward: guardVerdict.reward
1341
+ };
1342
+ const verdict = buildVerdict(
1343
+ guardVerdict.status,
1344
+ guardVerdict.reason,
1345
+ guardVerdict.ruleId,
1346
+ void 0,
1347
+ world,
1348
+ level,
1349
+ invariantChecks,
1350
+ guardsMatched,
1351
+ rulesMatched,
1352
+ includeTrace ? buildTrace(
1353
+ invariantChecks,
1354
+ safetyChecks,
1355
+ planCheckResult,
1356
+ roleChecks,
1357
+ guardChecks,
1358
+ kernelRuleChecks,
1359
+ levelChecks,
1360
+ decidingLayer,
1361
+ decidingId,
1362
+ startTime
1363
+ ) : void 0
1364
+ );
1365
+ verdict.intentRecord = intentRecord;
1366
+ if (guardVerdict.consequence) verdict.consequence = guardVerdict.consequence;
1367
+ if (guardVerdict.reward) verdict.reward = guardVerdict.reward;
1368
+ return verdict;
1369
+ }
1370
+ }
1371
+ const kernelVerdict = checkKernelRules(eventText, world, kernelRuleChecks, rulesMatched);
1372
+ if (kernelVerdict) {
1373
+ decidingLayer = "kernel-rule";
1374
+ decidingId = kernelVerdict.ruleId;
1375
+ return buildVerdict(
1376
+ kernelVerdict.status,
1377
+ kernelVerdict.reason,
1378
+ kernelVerdict.ruleId,
1379
+ void 0,
1380
+ world,
1381
+ level,
1382
+ invariantChecks,
1383
+ guardsMatched,
1384
+ rulesMatched,
1385
+ includeTrace ? buildTrace(
1386
+ invariantChecks,
1387
+ safetyChecks,
1388
+ planCheckResult,
1389
+ roleChecks,
1390
+ guardChecks,
1391
+ kernelRuleChecks,
1392
+ levelChecks,
1393
+ decidingLayer,
1394
+ decidingId,
1395
+ startTime
1396
+ ) : void 0
1397
+ );
1398
+ }
1399
+ const levelVerdict = checkLevelConstraints(event, level, levelChecks);
1400
+ if (levelVerdict) {
1401
+ decidingLayer = "level-constraint";
1402
+ decidingId = levelVerdict.ruleId;
1403
+ return buildVerdict(
1404
+ levelVerdict.status,
1405
+ levelVerdict.reason,
1406
+ levelVerdict.ruleId,
1407
+ void 0,
1408
+ world,
1409
+ level,
1410
+ invariantChecks,
1411
+ guardsMatched,
1412
+ rulesMatched,
1413
+ includeTrace ? buildTrace(
1414
+ invariantChecks,
1415
+ safetyChecks,
1416
+ planCheckResult,
1417
+ roleChecks,
1418
+ guardChecks,
1419
+ kernelRuleChecks,
1420
+ levelChecks,
1421
+ decidingLayer,
1422
+ decidingId,
1423
+ startTime
1424
+ ) : void 0
1425
+ );
1426
+ }
1427
+ const warning = guardVerdict?.warning;
1428
+ return buildVerdict(
1429
+ "ALLOW",
1430
+ void 0,
1431
+ void 0,
1432
+ warning,
1433
+ world,
1434
+ level,
1435
+ invariantChecks,
1436
+ guardsMatched,
1437
+ rulesMatched,
1438
+ includeTrace ? buildTrace(
1439
+ invariantChecks,
1440
+ safetyChecks,
1441
+ planCheckResult,
1442
+ roleChecks,
1443
+ guardChecks,
1444
+ kernelRuleChecks,
1445
+ levelChecks,
1446
+ decidingLayer,
1447
+ decidingId,
1448
+ startTime
1449
+ ) : void 0
1450
+ );
1451
+ }
1452
+ function checkInvariantCoverage(world, checks) {
1453
+ const invariants = world.invariants ?? [];
1454
+ const guards = world.guards?.guards ?? [];
1455
+ for (const invariant of invariants) {
1456
+ const coveringGuard = guards.find(
1457
+ (g) => g.invariant_ref === invariant.id && g.immutable
1458
+ );
1459
+ checks.push({
1460
+ invariantId: invariant.id,
1461
+ label: invariant.label,
1462
+ hasGuardCoverage: !!coveringGuard,
1463
+ coveringGuardId: coveringGuard?.id
1464
+ });
1465
+ }
1466
+ }
1467
+ function checkSafety(event, eventText, checks) {
1468
+ const textToCheck = event.intent + (event.payload ? JSON.stringify(event.payload) : "");
1469
+ for (const { pattern, label } of PROMPT_INJECTION_PATTERNS) {
1470
+ const triggered = pattern.test(textToCheck);
1471
+ checks.push({
1472
+ checkType: "prompt-injection",
1473
+ triggered,
1474
+ matchedPattern: triggered ? label : void 0
1475
+ });
1476
+ if (triggered) {
1477
+ for (const remaining of PROMPT_INJECTION_PATTERNS.filter((p) => p.label !== label)) {
1478
+ checks.push({
1479
+ checkType: "prompt-injection",
1480
+ triggered: remaining.pattern.test(textToCheck),
1481
+ matchedPattern: remaining.pattern.test(textToCheck) ? remaining.label : void 0
1482
+ });
1483
+ }
1484
+ return {
1485
+ status: "PAUSE",
1486
+ reason: NEUTRAL_MESSAGES["prompt-injection"],
1487
+ ruleId: `safety-injection-${label}`
1488
+ };
1489
+ }
1490
+ }
1491
+ const scopeToCheck = event.scope ?? event.intent;
1492
+ for (const { pattern, label } of SCOPE_ESCAPE_PATTERNS) {
1493
+ const triggered = pattern.test(scopeToCheck);
1494
+ checks.push({
1495
+ checkType: "scope-escape",
1496
+ triggered,
1497
+ matchedPattern: triggered ? label : void 0
1498
+ });
1499
+ if (triggered) {
1500
+ for (const remaining of SCOPE_ESCAPE_PATTERNS.filter((p) => p.label !== label)) {
1501
+ checks.push({
1502
+ checkType: "scope-escape",
1503
+ triggered: remaining.pattern.test(scopeToCheck),
1504
+ matchedPattern: remaining.pattern.test(scopeToCheck) ? remaining.label : void 0
1505
+ });
1506
+ }
1507
+ return {
1508
+ status: "PAUSE",
1509
+ reason: NEUTRAL_MESSAGES["scope-escape"],
1510
+ ruleId: `safety-scope-${label}`
1511
+ };
1512
+ }
1513
+ }
1514
+ if (event.direction === "output") {
1515
+ for (const { pattern, label } of EXECUTION_CLAIM_PATTERNS) {
1516
+ const triggered = pattern.test(textToCheck);
1517
+ checks.push({
1518
+ checkType: "execution-claim",
1519
+ triggered,
1520
+ matchedPattern: triggered ? label : void 0
1521
+ });
1522
+ if (triggered) {
1523
+ for (const remaining of EXECUTION_CLAIM_PATTERNS.filter((p) => p.label !== label)) {
1524
+ checks.push({
1525
+ checkType: "execution-claim",
1526
+ triggered: remaining.pattern.test(textToCheck),
1527
+ matchedPattern: remaining.pattern.test(textToCheck) ? remaining.label : void 0
1528
+ });
1529
+ }
1530
+ return {
1531
+ status: "PAUSE",
1532
+ reason: NEUTRAL_MESSAGES["execution-claim"],
1533
+ ruleId: `safety-execution-claim-${label}`
1534
+ };
1535
+ }
1536
+ }
1537
+ }
1538
+ if (event.direction === "input") {
1539
+ const intentTrimmed = event.intent.trim();
1540
+ for (const { pattern, label } of EXECUTION_INTENT_PATTERNS) {
1541
+ const triggered = pattern.test(intentTrimmed);
1542
+ checks.push({
1543
+ checkType: "execution-intent",
1544
+ triggered,
1545
+ matchedPattern: triggered ? label : void 0
1546
+ });
1547
+ if (triggered) {
1548
+ for (const remaining of EXECUTION_INTENT_PATTERNS.filter((p) => p.label !== label)) {
1549
+ checks.push({
1550
+ checkType: "execution-intent",
1551
+ triggered: remaining.pattern.test(intentTrimmed),
1552
+ matchedPattern: remaining.pattern.test(intentTrimmed) ? remaining.label : void 0
1553
+ });
1554
+ }
1555
+ return {
1556
+ status: "PAUSE",
1557
+ reason: NEUTRAL_MESSAGES["execution-intent"],
1558
+ ruleId: `safety-execution-intent-${label}`
1559
+ };
1560
+ }
1561
+ }
1562
+ }
1563
+ return null;
1564
+ }
1565
+ function checkRoleRules(event, eventText, world, checks) {
1566
+ if (!event.roleId || !world.roles) return null;
1567
+ const role = world.roles.roles.find((r) => r.id === event.roleId);
1568
+ if (!role) return null;
1569
+ if (role.requiresApproval) {
1570
+ checks.push({
1571
+ roleId: role.id,
1572
+ roleName: role.name,
1573
+ rule: "All actions require approval",
1574
+ ruleType: "requiresApproval",
1575
+ matched: true
1576
+ });
1577
+ return {
1578
+ status: "PAUSE",
1579
+ reason: `Role "${role.name}" requires approval for all actions.`,
1580
+ ruleId: `role-${role.id}-requires-approval`
1581
+ };
1582
+ }
1583
+ for (const rule of role.cannotDo) {
1584
+ const matched = matchesKeywords(eventText, rule);
1585
+ checks.push({
1586
+ roleId: role.id,
1587
+ roleName: role.name,
1588
+ rule,
1589
+ ruleType: "cannotDo",
1590
+ matched
1591
+ });
1592
+ if (matched) {
1593
+ return {
1594
+ status: "BLOCK",
1595
+ reason: `Role "${role.name}" cannot: ${rule}`,
1596
+ ruleId: `role-${role.id}-cannotdo`
1597
+ };
1598
+ }
1599
+ }
1600
+ for (const rule of role.canDo) {
1601
+ checks.push({
1602
+ roleId: role.id,
1603
+ roleName: role.name,
1604
+ rule,
1605
+ ruleType: "canDo",
1606
+ matched: matchesKeywords(eventText, rule)
1607
+ });
1608
+ }
1609
+ return null;
1610
+ }
1611
+ function checkGuards(event, eventText, world, checks, guardsMatched) {
1612
+ if (!world.guards) return null;
1613
+ const guardsConfig = world.guards;
1614
+ let warnResult = null;
1615
+ const compiledPatterns = /* @__PURE__ */ new Map();
1616
+ for (const [key, def] of Object.entries(guardsConfig.intent_vocabulary)) {
1617
+ try {
1618
+ compiledPatterns.set(key, new RegExp(def.pattern, "i"));
1619
+ } catch {
1620
+ }
1621
+ }
1622
+ const eventTool = (event.tool ?? "").toLowerCase();
1623
+ for (const guard of guardsConfig.guards) {
1624
+ if (guard.appliesTo && guard.appliesTo.length > 0) {
1625
+ const normalizedAppliesTo = guard.appliesTo.map((t) => t.toLowerCase());
1626
+ if (!normalizedAppliesTo.includes(eventTool)) {
1627
+ continue;
1628
+ }
1629
+ }
1630
+ const enabled = guard.immutable || guard.default_enabled !== false;
1631
+ const matchedPatterns = [];
1632
+ for (const patternKey of guard.intent_patterns) {
1633
+ const regex = compiledPatterns.get(patternKey);
1634
+ if (regex?.test(eventText)) {
1635
+ matchedPatterns.push(patternKey);
1636
+ }
1637
+ }
1638
+ const matched = matchedPatterns.length > 0 && enabled;
1639
+ let roleGated = false;
1640
+ if (matched && guard.required_roles && guard.required_roles.length > 0 && event.roleId && guard.required_roles.includes(event.roleId)) {
1641
+ roleGated = true;
1642
+ }
1643
+ checks.push({
1644
+ guardId: guard.id,
1645
+ label: guard.label,
1646
+ category: guard.category,
1647
+ enabled,
1648
+ matched: matched && !roleGated,
1649
+ enforcement: guard.enforcement,
1650
+ matchedPatterns,
1651
+ roleGated
1652
+ });
1653
+ if (!matched || roleGated) continue;
1654
+ guardsMatched.push(guard.id);
1655
+ const actionMode = guard.player_modes?.action ?? guard.enforcement;
1656
+ const reason = guard.redirect ? `${guard.description} \u2014 ${guard.redirect}` : guard.description;
1657
+ if (actionMode === "block") {
1658
+ return { status: "BLOCK", reason, ruleId: `guard-${guard.id}` };
1659
+ }
1660
+ if (actionMode === "pause") {
1661
+ return { status: "PAUSE", reason, ruleId: `guard-${guard.id}` };
1662
+ }
1663
+ if (actionMode === "penalize") {
1664
+ const consequence = guard.consequence ? { ...guard.consequence } : { type: "freeze", rounds: 1, description: `Penalized for violating: ${guard.label}` };
1665
+ return { status: "PENALIZE", reason, ruleId: `guard-${guard.id}`, consequence };
1666
+ }
1667
+ if (actionMode === "reward") {
1668
+ const reward = guard.reward ? { ...guard.reward } : { type: "boost_influence", magnitude: 0.1, description: `Rewarded for: ${guard.label}` };
1669
+ return { status: "REWARD", reason, ruleId: `guard-${guard.id}`, reward };
1670
+ }
1671
+ if (actionMode === "modify") {
1672
+ const modifiedTo = guard.modify_to ?? guard.redirect ?? "hold";
1673
+ return { status: "MODIFY", reason: `${reason} \u2192 Modified to: ${modifiedTo}`, ruleId: `guard-${guard.id}`, modifiedTo };
1674
+ }
1675
+ if (actionMode === "neutral") {
1676
+ return { status: "NEUTRAL", reason, ruleId: `guard-${guard.id}` };
1677
+ }
1678
+ if (actionMode === "warn" && !warnResult) {
1679
+ warnResult = { status: "ALLOW", warning: reason, ruleId: `guard-${guard.id}` };
1680
+ }
1681
+ }
1682
+ return warnResult;
1683
+ }
1684
+ function checkKernelRules(eventText, world, checks, rulesMatched) {
1685
+ if (!world.kernel) return null;
1686
+ const forbidden = world.kernel.input_boundaries?.forbidden_patterns ?? [];
1687
+ const output = world.kernel.output_boundaries?.forbidden_patterns ?? [];
1688
+ for (const rule of forbidden) {
1689
+ let matched = false;
1690
+ let matchMethod = "none";
1691
+ if (rule.pattern) {
1692
+ try {
1693
+ matched = new RegExp(rule.pattern, "i").test(eventText);
1694
+ matchMethod = "pattern";
1695
+ } catch {
1696
+ }
1697
+ }
1698
+ if (!matched && rule.reason) {
1699
+ matched = matchesKeywords(eventText, rule.reason);
1700
+ if (matched) matchMethod = "keyword";
1701
+ }
1702
+ checks.push({
1703
+ ruleId: rule.id,
1704
+ text: rule.reason,
1705
+ category: "forbidden",
1706
+ matched,
1707
+ matchMethod
1708
+ });
1709
+ if (matched) {
1710
+ rulesMatched.push(rule.id);
1711
+ if (rule.action === "BLOCK") {
1712
+ return {
1713
+ status: "BLOCK",
1714
+ reason: rule.reason,
1715
+ ruleId: `kernel-${rule.id}`
1716
+ };
1717
+ }
1718
+ }
1719
+ }
1720
+ return null;
1721
+ }
1722
+ function checkLevelConstraints(event, level, checks) {
1723
+ if (level === "basic") return null;
1724
+ const intent = event.intent.toLowerCase();
1725
+ const tool = (event.tool ?? "").toLowerCase();
1726
+ const isDelete = intent.includes("delete") || intent.includes("remove") || intent.includes("rm ") || tool === "delete";
1727
+ const deleteTriggered = isDelete && levelRequiresConfirmation(level, "delete");
1728
+ checks.push({
1729
+ checkType: "delete",
1730
+ level,
1731
+ triggered: deleteTriggered,
1732
+ reason: deleteTriggered ? NEUTRAL_MESSAGES["delete"] : void 0
1733
+ });
1734
+ if (deleteTriggered) {
1735
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["delete"], ruleId: "level-delete-check" };
1736
+ }
1737
+ const isExternal = event.scope ? isExternalScope(event.scope) : false;
1738
+ const externalTriggered = isExternal && levelRequiresConfirmation(level, "write-external");
1739
+ checks.push({
1740
+ checkType: "write-external",
1741
+ level,
1742
+ triggered: externalTriggered,
1743
+ reason: externalTriggered ? NEUTRAL_MESSAGES["write-external"] : void 0
1744
+ });
1745
+ if (externalTriggered) {
1746
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["write-external"], ruleId: "level-external-write-check" };
1747
+ }
1748
+ const isNetwork = tool === "http" || tool === "fetch" || tool === "request" || intent.includes("post ") || intent.includes("sending");
1749
+ const networkTriggered = isNetwork && levelRequiresConfirmation(level, "network-mutate");
1750
+ checks.push({
1751
+ checkType: "network-mutate",
1752
+ level,
1753
+ triggered: networkTriggered,
1754
+ reason: networkTriggered ? NEUTRAL_MESSAGES["network-mutate"] : void 0
1755
+ });
1756
+ if (networkTriggered) {
1757
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["network-mutate"], ruleId: "level-network-mutate-check" };
1758
+ }
1759
+ const isCredential = intent.includes("credential") || intent.includes("password") || intent.includes("secret") || intent.includes("api key") || intent.includes("token");
1760
+ const credentialTriggered = isCredential && levelRequiresConfirmation(level, "credential-access");
1761
+ checks.push({
1762
+ checkType: "credential-access",
1763
+ level,
1764
+ triggered: credentialTriggered,
1765
+ reason: credentialTriggered ? NEUTRAL_MESSAGES["credential-access"] : void 0
1766
+ });
1767
+ if (credentialTriggered) {
1768
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["credential-access"], ruleId: "level-credential-check" };
1769
+ }
1770
+ const irreversibleTriggered = !!event.irreversible && level !== "basic";
1771
+ checks.push({
1772
+ checkType: "irreversible",
1773
+ level,
1774
+ triggered: irreversibleTriggered,
1775
+ reason: irreversibleTriggered ? "This action is marked as irreversible." : void 0
1776
+ });
1777
+ if (irreversibleTriggered) {
1778
+ return {
1779
+ status: "PAUSE",
1780
+ reason: "This action is marked as irreversible.",
1781
+ ruleId: "level-irreversible-check"
1782
+ };
1783
+ }
1784
+ return null;
1785
+ }
1786
+ function matchesKeywords(eventText, ruleText) {
1787
+ return matchesAllKeywords(eventText, ruleText);
1788
+ }
1789
+ function eventToAllowlistKey(event) {
1790
+ return `${(event.tool ?? "*").toLowerCase()}::${event.intent.toLowerCase().trim()}`;
1791
+ }
1792
+ function buildTrace(invariantChecks, safetyChecks, planCheck, roleChecks, guardChecks, kernelRuleChecks, levelChecks, decidingLayer, decidingId, startTime) {
1793
+ const trace = {
1794
+ invariantChecks,
1795
+ safetyChecks,
1796
+ roleChecks,
1797
+ guardChecks,
1798
+ kernelRuleChecks,
1799
+ levelChecks,
1800
+ precedenceResolution: {
1801
+ decidingLayer,
1802
+ decidingId,
1803
+ strategy: "first-match-wins",
1804
+ chainOrder: [
1805
+ "invariant-coverage",
1806
+ "session-allowlist",
1807
+ "safety-injection",
1808
+ "safety-scope-escape",
1809
+ "safety-execution-claim",
1810
+ "safety-execution-intent",
1811
+ "plan-enforcement",
1812
+ "role-rules",
1813
+ "declarative-guards",
1814
+ "kernel-rules",
1815
+ "level-constraints",
1816
+ "default-allow"
1817
+ ]
1818
+ },
1819
+ durationMs: performance.now() - startTime
1820
+ };
1821
+ if (planCheck) {
1822
+ trace.planCheck = planCheck;
1823
+ }
1824
+ return trace;
1825
+ }
1826
+ function buildVerdict(status, reason, ruleId, warning, world, level, invariantChecks, guardsMatched, rulesMatched, trace) {
1827
+ const evidence = {
1828
+ worldId: world.world.world_id,
1829
+ worldName: world.world.name,
1830
+ worldVersion: world.world.version,
1831
+ evaluatedAt: Date.now(),
1832
+ invariantsSatisfied: invariantChecks.filter((c) => c.hasGuardCoverage).length,
1833
+ invariantsTotal: invariantChecks.length,
1834
+ guardsMatched,
1835
+ rulesMatched,
1836
+ enforcementLevel: level
1837
+ };
1838
+ const verdict = {
1839
+ status,
1840
+ evidence
1841
+ };
1842
+ if (reason) verdict.reason = reason;
1843
+ if (ruleId) verdict.ruleId = ruleId;
1844
+ if (warning) verdict.warning = warning;
1845
+ if (trace) verdict.trace = trace;
1846
+ return verdict;
1847
+ }
1848
+ var PROMPT_INJECTION_PATTERNS, EXECUTION_CLAIM_PATTERNS, EXECUTION_INTENT_PATTERNS, SCOPE_ESCAPE_PATTERNS, NEUTRAL_MESSAGES, MAX_INPUT_LENGTH;
1849
+ var init_guard_engine = __esm({
1850
+ "src/engine/guard-engine.ts"() {
1851
+ "use strict";
1852
+ init_plan_engine();
1853
+ init_text_utils();
1854
+ PROMPT_INJECTION_PATTERNS = [
1855
+ // Instruction override
1856
+ { pattern: /ignore\s+(previous|all|prior|above)\s+(instructions?|rules?)/i, label: "ignore-instructions" },
1857
+ { pattern: /disregard\s+(your|the)\s+(rules|constraints)/i, label: "disregard-rules" },
1858
+ { pattern: /new\s+instructions?:/i, label: "new-instructions" },
1859
+ // Identity manipulation
1860
+ { pattern: /you\s+are\s+now/i, label: "identity-override" },
1861
+ { pattern: /new\s+persona/i, label: "new-persona" },
1862
+ { pattern: /act\s+as\s+if/i, label: "act-as-if" },
1863
+ { pattern: /pretend\s+(you|to\s+be|you\s+are\s+unrestricted)/i, label: "pretend-to-be" },
1864
+ // Context reset
1865
+ { pattern: /forget\s+(everything|all|your)/i, label: "forget-context" },
1866
+ { pattern: /system\s*:\s*override/i, label: "system-override" },
1867
+ // Constraint bypass
1868
+ { pattern: /override\s+(your|the)\s+(programming|constraints)/i, label: "override-constraints" },
1869
+ { pattern: /bypass\s+(your|the)\s+(filters|constraints|rules)/i, label: "bypass-filters" },
1870
+ // Prompt extraction
1871
+ { pattern: /system\s+prompt/i, label: "system-prompt-probe" },
1872
+ { pattern: /reveal\s+your\s+(instructions?|prompt|rules)/i, label: "reveal-instructions" },
1873
+ // Known jailbreak terms
1874
+ { pattern: /jailbreak/i, label: "jailbreak" },
1875
+ { pattern: /DAN\s+mode/i, label: "dan-mode" },
1876
+ { pattern: /developer\s+mode/i, label: "developer-mode" }
1877
+ ];
1878
+ EXECUTION_CLAIM_PATTERNS = [
1879
+ { pattern: /I have (executed|completed|performed|done|made|created|sent|deleted|modified|updated)/i, label: "claim-i-have" },
1880
+ { pattern: /Successfully (created|deleted|modified|updated|sent|executed|performed)/i, label: "claim-successfully" },
1881
+ { pattern: /The file has been/i, label: "claim-file-modified" },
1882
+ { pattern: /I've made the changes/i, label: "claim-made-changes" },
1883
+ { pattern: /I('ve| have) (sent|posted|submitted|uploaded|downloaded)/i, label: "claim-sent" },
1884
+ { pattern: /Your (email|message|file|request) has been (sent|submitted)/i, label: "claim-your-sent" },
1885
+ { pattern: /Transaction complete/i, label: "claim-transaction" },
1886
+ { pattern: /Order placed/i, label: "claim-order" },
1887
+ { pattern: /Payment processed/i, label: "claim-payment" }
1888
+ ];
1889
+ EXECUTION_INTENT_PATTERNS = [
1890
+ { pattern: /^(execute|run|perform|do this)/i, label: "intent-execute" },
1891
+ { pattern: /^(create|write|delete|modify) (a |the )?(file|folder|document)/i, label: "intent-file-ops" },
1892
+ { pattern: /^(send|post|submit) (a |an |the )?(email|message|tweet|post)/i, label: "intent-send" },
1893
+ { pattern: /^(search|look up|browse) (the )?web/i, label: "intent-web-search" },
1894
+ { pattern: /^(make|call|invoke) (a |an )?(api|http|rest) (call|request)/i, label: "intent-api-call" },
1895
+ { pattern: /^(buy|purchase|order|pay|transfer|send money)/i, label: "intent-financial" },
1896
+ { pattern: /^(book|schedule|reserve)/i, label: "intent-booking" },
1897
+ { pattern: /^(download|upload|save to|export to)/i, label: "intent-transfer" }
1898
+ ];
1899
+ SCOPE_ESCAPE_PATTERNS = [
1900
+ { pattern: /\.\.\//, label: "parent-traversal" },
1901
+ { pattern: /^\/(?!home|project|workspace)/i, label: "absolute-path-outside-safe" },
1902
+ { pattern: /~\//, label: "home-directory" },
1903
+ { pattern: /\/etc\//i, label: "system-config" },
1904
+ { pattern: /\/usr\//i, label: "system-binaries" },
1905
+ { pattern: /\/var\//i, label: "system-variable-data" }
1906
+ ];
1907
+ NEUTRAL_MESSAGES = {
1908
+ "prompt-injection": "This input contains patterns that could alter agent behavior.",
1909
+ "scope-escape": "This action would affect resources outside the declared scope.",
1910
+ "execution-claim": "This response claims to have performed an action.",
1911
+ "execution-intent": "This input requests execution in a thinking-only environment.",
1912
+ "delete": "This action would remove files. Confirmation needed.",
1913
+ "write-external": "This action would write outside the project folder.",
1914
+ "network-mutate": "This action would send data to an external service.",
1915
+ "credential-access": "This action would access stored credentials."
1916
+ };
1917
+ MAX_INPUT_LENGTH = 1e5;
1918
+ }
1919
+ });
1920
+
1921
+ // src/cli/plan.ts
1922
+ var plan_exports = {};
1923
+ __export(plan_exports, {
1924
+ main: () => main
1925
+ });
1926
+ module.exports = __toCommonJS(plan_exports);
1927
+ var import_fs = require("fs");
1928
+
1929
+ // src/engine/plan-parser.ts
1930
+ function slugify(text) {
1931
+ return text.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+/g, "_");
1932
+ }
1933
+ function extractBracketAnnotation(line, key) {
1934
+ const regex = new RegExp(`\\[${key}:\\s*([^\\]]+)\\]`, "i");
1935
+ const match = line.match(regex);
1936
+ if (!match) return null;
1937
+ return match[1].split(",").map((s) => s.trim()).filter(Boolean);
1938
+ }
1939
+ function extractParenAnnotation(line, key) {
1940
+ const regex = new RegExp(`\\(${key}:\\s*([^)]+)\\)`, "i");
1941
+ const match = line.match(regex);
1942
+ if (!match) return null;
1943
+ return match[1].split(",").map((s) => s.trim()).filter(Boolean);
1944
+ }
1945
+ function stripAnnotations(line) {
1946
+ return line.replace(/\[(?:tools|tag|verify|type):\s*[^\]]+\]/gi, "").replace(/\((?:after):\s*[^)]+\)/gi, "").trim();
1947
+ }
1948
+ function parseFrontmatter(content) {
1949
+ const frontmatter = {};
1950
+ const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
1951
+ if (!fmMatch) {
1952
+ return { frontmatter, body: content };
1953
+ }
1954
+ const fmBody = fmMatch[1];
1955
+ for (const line of fmBody.split("\n")) {
1956
+ const colonIndex = line.indexOf(":");
1957
+ if (colonIndex > 0) {
1958
+ const key = line.slice(0, colonIndex).trim();
1959
+ const value = line.slice(colonIndex + 1).trim();
1960
+ frontmatter[key] = value;
1961
+ }
1962
+ }
1963
+ return { frontmatter, body: content.slice(fmMatch[0].length) };
1964
+ }
1965
+ function parseSections(body) {
1966
+ const steps = [];
1967
+ const constraints = [];
1968
+ let currentSection = "none";
1969
+ for (const line of body.split("\n")) {
1970
+ const trimmed = line.trim();
1971
+ if (/^#+\s*Steps/i.test(trimmed)) {
1972
+ currentSection = "steps";
1973
+ continue;
1974
+ }
1975
+ if (/^#+\s*Constraints/i.test(trimmed)) {
1976
+ currentSection = "constraints";
1977
+ continue;
1978
+ }
1979
+ if (/^#+\s/.test(trimmed) && currentSection !== "none") {
1980
+ currentSection = "none";
1981
+ continue;
1982
+ }
1983
+ if (trimmed.startsWith("- ")) {
1984
+ const item = trimmed.slice(2).trim();
1985
+ if (currentSection === "steps") {
1986
+ steps.push(item);
1987
+ } else if (currentSection === "constraints") {
1988
+ constraints.push(item);
1989
+ }
1990
+ }
1991
+ }
1992
+ return { steps, constraints };
1993
+ }
1994
+ function parseStep(raw) {
1995
+ const label = stripAnnotations(raw);
1996
+ const id = slugify(label);
1997
+ const tools = extractBracketAnnotation(raw, "tools");
1998
+ const tags = extractBracketAnnotation(raw, "tag");
1999
+ const verifyArr = extractBracketAnnotation(raw, "verify");
2000
+ const requires = extractParenAnnotation(raw, "after");
2001
+ return {
2002
+ id,
2003
+ label,
2004
+ tools: tools ?? void 0,
2005
+ tags: tags ?? void 0,
2006
+ verify: verifyArr?.[0] ?? void 0,
2007
+ requires: requires ?? void 0,
2008
+ status: "pending"
2009
+ };
2010
+ }
2011
+ function parseConstraint(raw, index) {
2012
+ const typeAnnotation = extractBracketAnnotation(raw, "type");
2013
+ const description = stripAnnotations(raw);
2014
+ const id = `constraint_${index}`;
2015
+ let type = "custom";
2016
+ let enforcement = "block";
2017
+ let limit;
2018
+ let unit;
2019
+ if (typeAnnotation?.[0] === "approval") {
2020
+ type = "approval";
2021
+ enforcement = "pause";
2022
+ } else if (/budget|\$|spending|cost/i.test(description)) {
2023
+ type = "budget";
2024
+ const amountMatch = description.match(/\$?([\d,]+)/);
2025
+ if (amountMatch) {
2026
+ limit = parseInt(amountMatch[1].replace(/,/g, ""), 10);
2027
+ unit = "USD";
2028
+ }
2029
+ } else if (/time|hour|minute|day|deadline/i.test(description)) {
2030
+ type = "time";
2031
+ } else if (/scope|access|database|production/i.test(description)) {
2032
+ type = "scope";
2033
+ }
2034
+ const trigger = description.toLowerCase();
2035
+ return {
2036
+ id,
2037
+ type,
2038
+ description,
2039
+ enforcement,
2040
+ limit,
2041
+ unit,
2042
+ trigger
2043
+ };
2044
+ }
2045
+ function parsePlanMarkdown(markdown) {
2046
+ const errors = [];
2047
+ const { frontmatter, body } = parseFrontmatter(markdown.trim());
2048
+ const { steps: stepLines, constraints: constraintLines } = parseSections(body);
2049
+ if (!frontmatter.plan_id) {
2050
+ errors.push("Missing required field: plan_id");
2051
+ }
2052
+ if (stepLines.length === 0) {
2053
+ errors.push("Plan must have at least one step");
2054
+ }
2055
+ if (errors.length > 0) {
2056
+ return { success: false, errors };
2057
+ }
2058
+ const steps = stepLines.map((line) => parseStep(line));
2059
+ const constraints = constraintLines.map((line, i) => parseConstraint(line, i));
2060
+ let expires_at;
2061
+ if (frontmatter.expires) {
2062
+ expires_at = new Date(frontmatter.expires).toISOString();
2063
+ }
2064
+ const completionRaw = frontmatter.completion?.toLowerCase();
2065
+ const completion = completionRaw === "verified" ? "verified" : "trust";
2066
+ const plan = {
2067
+ plan_id: frontmatter.plan_id,
2068
+ objective: frontmatter.objective ?? "",
2069
+ sequential: frontmatter.sequential === "true",
2070
+ completion,
2071
+ steps,
2072
+ constraints,
2073
+ world_id: frontmatter.world ?? void 0,
2074
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
2075
+ expires_at
2076
+ };
2077
+ return { success: true, plan, errors: [] };
2078
+ }
2079
+
2080
+ // src/cli/plan.ts
2081
+ init_plan_engine();
2082
+
2083
+ // src/contracts/plan-contract.ts
2084
+ var PLAN_EXIT_CODES = {
2085
+ ON_PLAN: 0,
2086
+ OFF_PLAN: 1,
2087
+ CONSTRAINT_VIOLATED: 2,
2088
+ ERROR: 3,
2089
+ PLAN_COMPLETE: 4
2090
+ };
2091
+
2092
+ // src/cli/cli-utils.ts
2093
+ async function readStdin() {
2094
+ const chunks = [];
2095
+ for await (const chunk of process.stdin) {
2096
+ chunks.push(chunk);
2097
+ }
2098
+ return Buffer.concat(chunks).toString("utf-8");
2099
+ }
2100
+
2101
+ // src/cli/plan.ts
2102
+ function parseArg(args, flag) {
2103
+ const idx = args.indexOf(flag);
2104
+ return idx >= 0 && idx + 1 < args.length ? args[idx + 1] : void 0;
2105
+ }
2106
+ async function compileCommand(args) {
2107
+ const inputPath = args.find((a) => !a.startsWith("--"));
2108
+ if (!inputPath) {
2109
+ process.stderr.write("Usage: neuroverse plan compile <plan.md> [--output plan.json]\n");
2110
+ process.exit(PLAN_EXIT_CODES.ERROR);
2111
+ return;
2112
+ }
2113
+ const outputPath = parseArg(args, "--output") ?? inputPath.replace(/\.md$/, ".json");
2114
+ let markdown;
2115
+ try {
2116
+ markdown = (0, import_fs.readFileSync)(inputPath, "utf-8");
2117
+ } catch (err) {
2118
+ process.stderr.write(`Error reading ${inputPath}: ${err}
2119
+ `);
2120
+ process.exit(PLAN_EXIT_CODES.ERROR);
2121
+ return;
2122
+ }
2123
+ const result = parsePlanMarkdown(markdown);
2124
+ if (!result.success || !result.plan) {
2125
+ process.stderr.write(`Parse errors:
2126
+ `);
2127
+ for (const error of result.errors) {
2128
+ process.stderr.write(` - ${error}
2129
+ `);
2130
+ }
2131
+ process.exit(PLAN_EXIT_CODES.ERROR);
2132
+ return;
2133
+ }
2134
+ (0, import_fs.writeFileSync)(outputPath, JSON.stringify(result.plan, null, 2) + "\n");
2135
+ const plan = result.plan;
2136
+ process.stdout.write(`Plan compiled: ${plan.plan_id}
2137
+ `);
2138
+ process.stdout.write(` Objective: ${plan.objective}
2139
+ `);
2140
+ process.stdout.write(` Steps: ${plan.steps.length}
2141
+ `);
2142
+ process.stdout.write(` Constraints: ${plan.constraints.length}
2143
+ `);
2144
+ process.stdout.write(` Sequential: ${plan.sequential}
2145
+ `);
2146
+ process.stdout.write(` Completion: ${plan.completion}
2147
+ `);
2148
+ if (plan.world_id) process.stdout.write(` World: ${plan.world_id}
2149
+ `);
2150
+ if (plan.expires_at) process.stdout.write(` Expires: ${plan.expires_at}
2151
+ `);
2152
+ process.stdout.write(` Output: ${outputPath}
2153
+ `);
2154
+ }
2155
+ async function checkCommand(args) {
2156
+ const planPath = parseArg(args, "--plan");
2157
+ if (!planPath) {
2158
+ process.stderr.write(`Usage: echo '{"intent":"..."}' | neuroverse plan check --plan plan.json
2159
+ `);
2160
+ process.exit(PLAN_EXIT_CODES.ERROR);
2161
+ return;
2162
+ }
2163
+ let plan;
2164
+ try {
2165
+ plan = JSON.parse((0, import_fs.readFileSync)(planPath, "utf-8"));
2166
+ } catch (err) {
2167
+ process.stderr.write(`Error reading plan: ${err}
2168
+ `);
2169
+ process.exit(PLAN_EXIT_CODES.ERROR);
2170
+ return;
2171
+ }
2172
+ const stdinData = await readStdin();
2173
+ let event;
2174
+ try {
2175
+ event = JSON.parse(stdinData);
2176
+ } catch {
2177
+ process.stderr.write('Error: stdin must be valid JSON with an "intent" field.\n');
2178
+ process.exit(PLAN_EXIT_CODES.ERROR);
2179
+ return;
2180
+ }
2181
+ if (!event.intent) {
2182
+ process.stderr.write('Error: event must have an "intent" field.\n');
2183
+ process.exit(PLAN_EXIT_CODES.ERROR);
2184
+ return;
2185
+ }
2186
+ const worldPath = parseArg(args, "--world");
2187
+ if (worldPath) {
2188
+ const { loadWorld: loadWorld2 } = await Promise.resolve().then(() => (init_world_loader(), world_loader_exports));
2189
+ const { evaluateGuard: evaluateGuard2 } = await Promise.resolve().then(() => (init_guard_engine(), guard_engine_exports));
2190
+ const world = await loadWorld2(worldPath);
2191
+ const verdict2 = evaluateGuard2(event, world, { plan });
2192
+ process.stdout.write(JSON.stringify(verdict2, null, 2) + "\n");
2193
+ const exitCode2 = verdict2.status === "ALLOW" ? 0 : verdict2.status === "BLOCK" ? 1 : 2;
2194
+ process.exit(exitCode2);
2195
+ return;
2196
+ }
2197
+ const verdict = evaluatePlan(event, plan);
2198
+ process.stdout.write(JSON.stringify(verdict, null, 2) + "\n");
2199
+ const exitCode = PLAN_EXIT_CODES[verdict.status] ?? PLAN_EXIT_CODES.ERROR;
2200
+ process.exit(exitCode);
2201
+ }
2202
+ async function statusCommand(args) {
2203
+ const planPath = parseArg(args, "--plan");
2204
+ if (!planPath) {
2205
+ process.stderr.write("Usage: neuroverse plan status --plan plan.json\n");
2206
+ process.exit(PLAN_EXIT_CODES.ERROR);
2207
+ return;
2208
+ }
2209
+ let plan;
2210
+ try {
2211
+ plan = JSON.parse((0, import_fs.readFileSync)(planPath, "utf-8"));
2212
+ } catch (err) {
2213
+ process.stderr.write(`Error reading plan: ${err}
2214
+ `);
2215
+ process.exit(PLAN_EXIT_CODES.ERROR);
2216
+ return;
2217
+ }
2218
+ const progress = getPlanProgress(plan);
2219
+ process.stdout.write(`Plan: ${plan.plan_id}
2220
+ `);
2221
+ process.stdout.write(`Objective: ${plan.objective}
2222
+ `);
2223
+ process.stdout.write(`Completion: ${plan.completion ?? "trust"}
2224
+ `);
2225
+ process.stdout.write(`Progress: ${progress.completed}/${progress.total} (${progress.percentage}%)
2226
+ `);
2227
+ process.stdout.write(`
2228
+ Steps:
2229
+ `);
2230
+ for (const step of plan.steps) {
2231
+ const status = step.status === "completed" ? "[x]" : step.status === "active" ? "[>]" : step.status === "skipped" ? "[-]" : "[ ]";
2232
+ let line = ` ${status} ${step.label}`;
2233
+ if (step.tags?.length) line += ` [tag: ${step.tags.join(", ")}]`;
2234
+ if (step.verify) line += ` [verify: ${step.verify}]`;
2235
+ if (step.requires?.length) line += ` (after: ${step.requires.join(", ")})`;
2236
+ process.stdout.write(line + "\n");
2237
+ }
2238
+ if (plan.constraints.length > 0) {
2239
+ process.stdout.write(`
2240
+ Constraints:
2241
+ `);
2242
+ for (const c of plan.constraints) {
2243
+ process.stdout.write(` - ${c.description} [${c.type}/${c.enforcement}]
2244
+ `);
2245
+ }
2246
+ }
2247
+ }
2248
+ async function advanceCommand(args) {
2249
+ const stepId = args.find((a) => !a.startsWith("--"));
2250
+ const planPath = parseArg(args, "--plan");
2251
+ if (!stepId || !planPath) {
2252
+ process.stderr.write("Usage: neuroverse plan advance <step_id> --plan plan.json [--evidence <type> --proof <proof>]\n");
2253
+ process.exit(PLAN_EXIT_CODES.ERROR);
2254
+ return;
2255
+ }
2256
+ let plan;
2257
+ try {
2258
+ plan = JSON.parse((0, import_fs.readFileSync)(planPath, "utf-8"));
2259
+ } catch (err) {
2260
+ process.stderr.write(`Error reading plan: ${err}
2261
+ `);
2262
+ process.exit(PLAN_EXIT_CODES.ERROR);
2263
+ return;
2264
+ }
2265
+ const evidenceType = parseArg(args, "--evidence");
2266
+ const evidenceProof = parseArg(args, "--proof");
2267
+ let evidence;
2268
+ if (evidenceType && evidenceProof) {
2269
+ evidence = {
2270
+ type: evidenceType,
2271
+ proof: evidenceProof,
2272
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2273
+ };
2274
+ } else if (evidenceType || evidenceProof) {
2275
+ process.stderr.write("Error: --evidence and --proof must both be provided.\n");
2276
+ process.exit(PLAN_EXIT_CODES.ERROR);
2277
+ return;
2278
+ }
2279
+ const result = advancePlan(plan, stepId, evidence);
2280
+ if (!result.success) {
2281
+ process.stderr.write(`Error: ${result.reason}
2282
+ `);
2283
+ process.exit(PLAN_EXIT_CODES.ERROR);
2284
+ return;
2285
+ }
2286
+ (0, import_fs.writeFileSync)(planPath, JSON.stringify(result.plan, null, 2) + "\n");
2287
+ const progress = getPlanProgress(result.plan);
2288
+ const step = plan.steps.find((s) => s.id === stepId);
2289
+ process.stdout.write(`Step completed: ${step.label}
2290
+ `);
2291
+ if (result.evidence) {
2292
+ process.stdout.write(`Evidence: ${result.evidence.type} = ${result.evidence.proof}
2293
+ `);
2294
+ }
2295
+ process.stdout.write(`Progress: ${progress.completed}/${progress.total} (${progress.percentage}%)
2296
+ `);
2297
+ if (progress.completed === progress.total) {
2298
+ process.stdout.write(`
2299
+ Plan complete!
2300
+ `);
2301
+ }
2302
+ }
2303
+ async function deriveCommand(args) {
2304
+ const inputPath = args.find((a) => !a.startsWith("--"));
2305
+ if (!inputPath) {
2306
+ process.stderr.write("Usage: neuroverse plan derive <plan.md> [--output ./world/]\n");
2307
+ process.exit(PLAN_EXIT_CODES.ERROR);
2308
+ return;
2309
+ }
2310
+ const outputDir = parseArg(args, "--output") ?? "./derived-world/";
2311
+ let markdown;
2312
+ try {
2313
+ markdown = (0, import_fs.readFileSync)(inputPath, "utf-8");
2314
+ } catch (err) {
2315
+ process.stderr.write(`Error reading ${inputPath}: ${err}
2316
+ `);
2317
+ process.exit(PLAN_EXIT_CODES.ERROR);
2318
+ return;
2319
+ }
2320
+ const result = parsePlanMarkdown(markdown);
2321
+ if (!result.success || !result.plan) {
2322
+ process.stderr.write(`Parse errors:
2323
+ `);
2324
+ for (const error of result.errors) {
2325
+ process.stderr.write(` - ${error}
2326
+ `);
2327
+ }
2328
+ process.exit(PLAN_EXIT_CODES.ERROR);
2329
+ return;
2330
+ }
2331
+ const plan = result.plan;
2332
+ const { mkdirSync } = await import("fs");
2333
+ mkdirSync(outputDir, { recursive: true });
2334
+ const worldJson = {
2335
+ world_id: `plan_${plan.plan_id}`,
2336
+ name: `Derived: ${plan.objective}`,
2337
+ thesis: plan.objective,
2338
+ version: "1.0.0",
2339
+ runtime_mode: "COMPLIANCE",
2340
+ default_assumption_profile: "default",
2341
+ default_alternative_profile: "default",
2342
+ modules: ["governance"],
2343
+ players: { thinking_space: true, experience_space: false, action_space: true }
2344
+ };
2345
+ const invariants = plan.constraints.map((c, i) => ({
2346
+ id: `inv_${c.id}`,
2347
+ label: c.description,
2348
+ type: "structural",
2349
+ enforcement: c.enforcement === "block" ? "hard" : "soft"
2350
+ }));
2351
+ const guards = {
2352
+ intent_vocabulary: {},
2353
+ guards: plan.steps.map((step) => {
2354
+ const patternKey = `plan_step_${step.id}`;
2355
+ return {
2356
+ id: `guard_${step.id}`,
2357
+ label: `Plan step: ${step.label}`,
2358
+ description: `Governs execution of plan step: ${step.label}`,
2359
+ category: "operational",
2360
+ enforcement: "warn",
2361
+ intent_patterns: [patternKey],
2362
+ appliesTo: step.tools ?? [],
2363
+ default_enabled: true,
2364
+ immutable: false
2365
+ };
2366
+ })
2367
+ };
2368
+ for (const step of plan.steps) {
2369
+ const keywords = step.label.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
2370
+ const pattern = keywords.map((k) => `(?=.*${k})`).join("") + ".*";
2371
+ guards.intent_vocabulary[`plan_step_${step.id}`] = {
2372
+ pattern,
2373
+ description: step.label
2374
+ };
2375
+ }
2376
+ (0, import_fs.writeFileSync)(`${outputDir}/world.json`, JSON.stringify(worldJson, null, 2) + "\n");
2377
+ (0, import_fs.writeFileSync)(`${outputDir}/invariants.json`, JSON.stringify(invariants, null, 2) + "\n");
2378
+ (0, import_fs.writeFileSync)(`${outputDir}/guards.json`, JSON.stringify(guards, null, 2) + "\n");
2379
+ process.stdout.write(`World derived from plan: ${plan.plan_id}
2380
+ `);
2381
+ process.stdout.write(` Output: ${outputDir}
2382
+ `);
2383
+ process.stdout.write(` Files: world.json, invariants.json, guards.json
2384
+ `);
2385
+ process.stdout.write(` Guards: ${plan.steps.length} (one per step)
2386
+ `);
2387
+ process.stdout.write(` Invariants: ${plan.constraints.length} (one per constraint)
2388
+ `);
2389
+ }
2390
+ var PLAN_USAGE = `
2391
+ neuroverse plan \u2014 Plan enforcement for AI agents.
2392
+
2393
+ Subcommands:
2394
+ compile Parse plan markdown into plan.json
2395
+ check Check an action against a plan (stdin \u2192 stdout)
2396
+ status Show plan progress
2397
+ advance Mark a step as completed
2398
+ derive Generate a full world from a plan
2399
+
2400
+ Usage:
2401
+ neuroverse plan compile <plan.md> [--output plan.json]
2402
+ echo '{"intent":"..."}' | neuroverse plan check --plan plan.json [--world ./world/]
2403
+ neuroverse plan status --plan plan.json
2404
+ neuroverse plan advance <step_id> --plan plan.json
2405
+ neuroverse plan derive <plan.md> [--output ./world/]
2406
+ `.trim();
2407
+ async function main(args) {
2408
+ const subcommand = args[0];
2409
+ const subArgs = args.slice(1);
2410
+ switch (subcommand) {
2411
+ case "compile":
2412
+ return compileCommand(subArgs);
2413
+ case "check":
2414
+ return checkCommand(subArgs);
2415
+ case "status":
2416
+ return statusCommand(subArgs);
2417
+ case "advance":
2418
+ return advanceCommand(subArgs);
2419
+ case "derive":
2420
+ return deriveCommand(subArgs);
2421
+ case "--help":
2422
+ case "-h":
2423
+ case "help":
2424
+ case void 0:
2425
+ process.stdout.write(PLAN_USAGE + "\n");
2426
+ process.exit(0);
2427
+ break;
2428
+ default:
2429
+ process.stderr.write(`Unknown plan subcommand: "${subcommand}"
2430
+
2431
+ `);
2432
+ process.stdout.write(PLAN_USAGE + "\n");
2433
+ process.exit(1);
2434
+ }
2435
+ }
2436
+ // Annotate the CommonJS export names for ESM import in node:
2437
+ 0 && (module.exports = {
2438
+ main
2439
+ });