@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,194 @@
1
+ // src/engine/rule-utils.ts
2
+ function collectAllEffects(rule) {
3
+ const effects = [...rule.effects ?? []];
4
+ for (const ce of rule.effects_conditional ?? []) {
5
+ effects.push(...ce.effects);
6
+ }
7
+ return effects;
8
+ }
9
+
10
+ // src/engine/explain-engine.ts
11
+ function detectTensions(rules) {
12
+ const increases = /* @__PURE__ */ new Map();
13
+ const decreases = /* @__PURE__ */ new Map();
14
+ for (const rule of rules) {
15
+ const allEffects = collectAllEffects(rule);
16
+ for (const effect of allEffects) {
17
+ const target = effect.target;
18
+ const isIncrease = effect.operation === "add" || effect.operation === "multiply" && typeof effect.value === "number" && effect.value > 1;
19
+ const isDecrease = effect.operation === "subtract" || effect.operation === "multiply" && typeof effect.value === "number" && effect.value < 1;
20
+ if (isIncrease) {
21
+ if (!increases.has(target)) increases.set(target, []);
22
+ increases.get(target).push(rule.label);
23
+ }
24
+ if (isDecrease) {
25
+ if (!decreases.has(target)) decreases.set(target, []);
26
+ decreases.get(target).push(rule.label);
27
+ }
28
+ }
29
+ }
30
+ const tensions = [];
31
+ for (const [variable, incRules] of increases) {
32
+ const decRules = decreases.get(variable);
33
+ if (decRules && decRules.length > 0) {
34
+ tensions.push({
35
+ variable,
36
+ increasedBy: incRules,
37
+ decreasedBy: decRules
38
+ });
39
+ }
40
+ }
41
+ return tensions;
42
+ }
43
+ function explainWorld(world) {
44
+ const dynamics = [...world.rules].sort((a, b) => a.order - b.order).map((rule) => {
45
+ const allEffects = collectAllEffects(rule);
46
+ return {
47
+ ruleId: rule.id,
48
+ label: rule.label,
49
+ severity: rule.severity,
50
+ triggerDescription: rule.causal_translation?.trigger_text ?? describeTriggers(rule),
51
+ effectDescription: rule.causal_translation?.effect_text ?? describeEffects(allEffects),
52
+ targets: [...new Set(allEffects.map((e) => e.target))]
53
+ };
54
+ });
55
+ const stateVariables = Object.entries(world.stateSchema.variables ?? {}).map(
56
+ ([name, v]) => ({
57
+ name,
58
+ label: v.label || name,
59
+ type: v.type,
60
+ defaultValue: v.default,
61
+ range: v.type === "number" && v.min !== void 0 && v.max !== void 0 ? `${v.min}\u2013${v.max}` : v.type === "enum" && v.options ? v.options.join(", ") : void 0
62
+ })
63
+ );
64
+ const invariants = world.invariants.map((inv) => ({
65
+ id: inv.id,
66
+ label: inv.label,
67
+ enforcement: inv.enforcement
68
+ }));
69
+ const gates = (world.gates.viability_classification ?? []).map((g) => ({
70
+ status: g.status,
71
+ field: g.field,
72
+ threshold: `${g.operator} ${g.value}`
73
+ }));
74
+ const tensions = detectTensions(world.rules);
75
+ const outcomes = (world.outcomes.computed_outcomes ?? []).map((o) => ({
76
+ id: o.id,
77
+ label: o.label,
78
+ type: o.type,
79
+ primary: o.primary ?? false
80
+ }));
81
+ const stats = {
82
+ invariants: world.invariants.length,
83
+ stateVariables: Object.keys(world.stateSchema.variables ?? {}).length,
84
+ rules: world.rules.length,
85
+ gates: (world.gates.viability_classification ?? []).length,
86
+ outcomes: (world.outcomes.computed_outcomes ?? []).length,
87
+ assumptions: Object.keys(world.assumptions.profiles ?? {}).length
88
+ };
89
+ return {
90
+ worldName: world.world.name,
91
+ worldId: world.world.world_id,
92
+ thesis: world.world.thesis,
93
+ dynamics,
94
+ stateVariables,
95
+ invariants,
96
+ gates,
97
+ tensions,
98
+ outcomes,
99
+ stats
100
+ };
101
+ }
102
+ function describeTriggers(rule) {
103
+ if (!rule.triggers || rule.triggers.length === 0) return "Always active";
104
+ return rule.triggers.map((t) => `${t.field} ${t.operator} ${t.value}`).join(" AND ");
105
+ }
106
+ function describeEffects(effects) {
107
+ if (effects.length === 0) return "No direct effects";
108
+ return effects.map((e) => {
109
+ switch (e.operation) {
110
+ case "multiply":
111
+ return `${e.target} scaled by ${e.value}`;
112
+ case "add":
113
+ return `${e.target} increased by ${e.value}`;
114
+ case "subtract":
115
+ return `${e.target} decreased by ${e.value}`;
116
+ case "set":
117
+ return `${e.target} set to ${e.value}`;
118
+ case "set_boolean":
119
+ return `${e.target} set to ${e.value}`;
120
+ default:
121
+ return `${e.target} ${e.operation} ${e.value}`;
122
+ }
123
+ }).join("; ");
124
+ }
125
+ function renderExplainText(output) {
126
+ const lines = [];
127
+ lines.push(`WORLD: ${output.worldName}`);
128
+ lines.push(`ID: ${output.worldId}`);
129
+ lines.push("");
130
+ if (output.thesis) {
131
+ lines.push("THESIS");
132
+ lines.push(` ${output.thesis}`);
133
+ lines.push("");
134
+ }
135
+ lines.push("STRUCTURE");
136
+ lines.push(` ${output.stats.invariants} invariants, ${output.stats.stateVariables} state variables, ${output.stats.rules} rules`);
137
+ lines.push(` ${output.stats.gates} viability gates, ${output.stats.outcomes} outcomes, ${output.stats.assumptions} assumption profiles`);
138
+ lines.push("");
139
+ if (output.dynamics.length > 0) {
140
+ lines.push("KEY DYNAMICS");
141
+ for (const d of output.dynamics) {
142
+ const severity = d.severity === "structural" ? "[structural]" : d.severity === "advantage" ? "[advantage]" : "[degradation]";
143
+ lines.push(` ${d.label} ${severity}`);
144
+ lines.push(` When: ${d.triggerDescription}`);
145
+ lines.push(` Then: ${d.effectDescription}`);
146
+ }
147
+ lines.push("");
148
+ }
149
+ if (output.tensions.length > 0) {
150
+ lines.push("DRAMATIC TENSIONS");
151
+ for (const t of output.tensions) {
152
+ lines.push(` ${t.variable}:`);
153
+ lines.push(` Increased by: ${t.increasedBy.join(", ")}`);
154
+ lines.push(` Decreased by: ${t.decreasedBy.join(", ")}`);
155
+ }
156
+ lines.push("");
157
+ }
158
+ if (output.stateVariables.length > 0) {
159
+ lines.push("STATE VARIABLES");
160
+ for (const v of output.stateVariables) {
161
+ const range = v.range ? ` (${v.range})` : "";
162
+ lines.push(` ${v.label}: ${v.type}, default ${v.defaultValue}${range}`);
163
+ }
164
+ lines.push("");
165
+ }
166
+ if (output.invariants.length > 0) {
167
+ lines.push("INVARIANTS (cannot change)");
168
+ for (const inv of output.invariants) {
169
+ lines.push(` ${inv.label} [${inv.enforcement}]`);
170
+ }
171
+ lines.push("");
172
+ }
173
+ if (output.gates.length > 0) {
174
+ lines.push("VIABILITY GATES");
175
+ for (const g of output.gates) {
176
+ lines.push(` ${g.status}: ${g.field} ${g.threshold}`);
177
+ }
178
+ lines.push("");
179
+ }
180
+ if (output.outcomes.length > 0) {
181
+ lines.push("OUTCOMES");
182
+ for (const o of output.outcomes) {
183
+ const primary = o.primary ? " [primary]" : "";
184
+ lines.push(` ${o.label} (${o.type})${primary}`);
185
+ }
186
+ lines.push("");
187
+ }
188
+ return lines.join("\n");
189
+ }
190
+
191
+ export {
192
+ explainWorld,
193
+ renderExplainText
194
+ };
@@ -0,0 +1,314 @@
1
+ // src/engine/simulate-engine.ts
2
+ function simulateWorld(world, options = {}) {
3
+ if (!world || !world.world) {
4
+ throw new Error(
5
+ 'World definition required. simulateWorld() cannot run without a world.\nLoad one with: loadWorld("./world/") or parseWorldMarkdown(markdown)'
6
+ );
7
+ }
8
+ const steps = Math.max(1, Math.min(options.steps ?? 1, 50));
9
+ const profileName = options.profile ?? world.world.default_assumption_profile;
10
+ const state = buildInitialState(world.stateSchema, options.stateOverrides);
11
+ for (const outcome of world.outcomes?.computed_outcomes ?? []) {
12
+ if (!(outcome.id in state)) {
13
+ state[outcome.id] = outcome.primary ? 100 : 0;
14
+ }
15
+ }
16
+ const assumptions = resolveAssumptions(world.assumptions, profileName);
17
+ const initialState = { ...state };
18
+ const simulationSteps = [];
19
+ let collapsed = false;
20
+ let collapseStep;
21
+ let collapseRule;
22
+ const sortedRules = [...world.rules].sort((a, b) => a.order - b.order);
23
+ for (let stepNum = 1; stepNum <= steps; stepNum++) {
24
+ if (collapsed) break;
25
+ const stepResult = evaluateStep(
26
+ stepNum,
27
+ sortedRules,
28
+ state,
29
+ assumptions,
30
+ world
31
+ );
32
+ simulationSteps.push(stepResult);
33
+ if (stepResult.collapsed) {
34
+ collapsed = true;
35
+ collapseStep = stepNum;
36
+ collapseRule = stepResult.rulesEvaluated.find((r) => r.collapsed)?.ruleId;
37
+ }
38
+ }
39
+ const finalViability = classifyViability(state, world);
40
+ return {
41
+ worldId: world.world.world_id,
42
+ worldName: world.world.name,
43
+ profile: profileName,
44
+ initialState,
45
+ steps: simulationSteps,
46
+ finalState: { ...state },
47
+ finalViability,
48
+ collapsed,
49
+ collapseStep,
50
+ collapseRule
51
+ };
52
+ }
53
+ function evaluateStep(stepNum, rules, state, assumptions, world) {
54
+ const evaluations = [];
55
+ let rulesFired = 0;
56
+ let collapsed = false;
57
+ const firedRuleIds = /* @__PURE__ */ new Set();
58
+ for (const rule of rules) {
59
+ if (collapsed) {
60
+ evaluations.push({
61
+ ruleId: rule.id,
62
+ label: rule.label,
63
+ triggered: false,
64
+ excluded: true,
65
+ effects: [],
66
+ collapsed: false
67
+ });
68
+ continue;
69
+ }
70
+ const excluded = rule.exclusive_with ? firedRuleIds.has(rule.exclusive_with) : false;
71
+ if (excluded) {
72
+ evaluations.push({
73
+ ruleId: rule.id,
74
+ label: rule.label,
75
+ triggered: false,
76
+ excluded: true,
77
+ effects: [],
78
+ collapsed: false
79
+ });
80
+ continue;
81
+ }
82
+ const triggered = evaluateTriggers(rule.triggers, state, assumptions);
83
+ if (!triggered) {
84
+ evaluations.push({
85
+ ruleId: rule.id,
86
+ label: rule.label,
87
+ triggered: false,
88
+ excluded: false,
89
+ effects: [],
90
+ collapsed: false
91
+ });
92
+ continue;
93
+ }
94
+ firedRuleIds.add(rule.id);
95
+ rulesFired++;
96
+ const appliedEffects = [];
97
+ for (const effect of rule.effects ?? []) {
98
+ const applied = applyEffect(effect, state);
99
+ if (applied) appliedEffects.push(applied);
100
+ }
101
+ for (const ce of rule.effects_conditional ?? []) {
102
+ const conditionMet = evaluateSingleTrigger(ce.condition, state, assumptions);
103
+ const andMet = ce.and ? evaluateSingleTrigger(ce.and, state, assumptions) : true;
104
+ const orMet = ce.or ? evaluateSingleTrigger(ce.or, state, assumptions) : false;
105
+ const anyMet = ce.condition_any ? ce.condition_any.some((c) => evaluateSingleTrigger(c, state, assumptions)) : false;
106
+ const shouldApply = conditionMet && andMet || ce.or && orMet || ce.condition_any && anyMet;
107
+ if (shouldApply) {
108
+ for (const effect of ce.effects) {
109
+ const applied = applyEffect(effect, state);
110
+ if (applied) appliedEffects.push(applied);
111
+ }
112
+ }
113
+ }
114
+ let ruleCollapsed = false;
115
+ if (rule.collapse_check) {
116
+ const fieldVal = typeof state[rule.collapse_check.field] === "number" ? state[rule.collapse_check.field] : 0;
117
+ if (evaluateOperator(fieldVal, rule.collapse_check.operator, rule.collapse_check.value)) {
118
+ ruleCollapsed = true;
119
+ collapsed = true;
120
+ }
121
+ }
122
+ if (!ruleCollapsed && rule.secondary_check) {
123
+ const fieldVal = typeof state[rule.secondary_check.field] === "number" ? state[rule.secondary_check.field] : 0;
124
+ if (evaluateOperator(fieldVal, rule.secondary_check.operator, rule.secondary_check.value)) {
125
+ ruleCollapsed = true;
126
+ collapsed = true;
127
+ }
128
+ }
129
+ evaluations.push({
130
+ ruleId: rule.id,
131
+ label: rule.label,
132
+ triggered: true,
133
+ excluded: false,
134
+ effects: appliedEffects,
135
+ collapsed: ruleCollapsed,
136
+ collapseField: ruleCollapsed ? rule.collapse_check?.field ?? rule.secondary_check?.field : void 0
137
+ });
138
+ }
139
+ const viability = classifyViability(state, world);
140
+ return {
141
+ step: stepNum,
142
+ rulesEvaluated: evaluations,
143
+ rulesFired,
144
+ stateAfter: { ...state },
145
+ viability,
146
+ collapsed
147
+ };
148
+ }
149
+ function evaluateTriggers(triggers, state, assumptions) {
150
+ if (!triggers || triggers.length === 0) return true;
151
+ return triggers.every((t) => evaluateSingleTrigger(t, state, assumptions));
152
+ }
153
+ function evaluateSingleTrigger(trigger, state, assumptions) {
154
+ const source = trigger.source === "assumption" ? assumptions : state;
155
+ const fieldValue = source[trigger.field];
156
+ if (fieldValue === void 0) return false;
157
+ return evaluateOperator(fieldValue, trigger.operator, trigger.value);
158
+ }
159
+ function evaluateOperator(fieldValue, operator, conditionValue) {
160
+ switch (operator) {
161
+ case "==":
162
+ return fieldValue === conditionValue;
163
+ case "!=":
164
+ return fieldValue !== conditionValue;
165
+ case ">":
166
+ return typeof fieldValue === "number" && typeof conditionValue === "number" && fieldValue > conditionValue;
167
+ case "<":
168
+ return typeof fieldValue === "number" && typeof conditionValue === "number" && fieldValue < conditionValue;
169
+ case ">=":
170
+ return typeof fieldValue === "number" && typeof conditionValue === "number" && fieldValue >= conditionValue;
171
+ case "<=":
172
+ return typeof fieldValue === "number" && typeof conditionValue === "number" && fieldValue <= conditionValue;
173
+ case "in":
174
+ return Array.isArray(conditionValue) && conditionValue.includes(String(fieldValue));
175
+ default:
176
+ return false;
177
+ }
178
+ }
179
+ function applyEffect(effect, state) {
180
+ const before = state[effect.target];
181
+ let after;
182
+ switch (effect.operation) {
183
+ case "multiply":
184
+ case "multiply_dynamic": {
185
+ const current = typeof before === "number" ? before : 0;
186
+ const factor = typeof effect.value === "number" ? effect.value : 1;
187
+ after = current * factor;
188
+ break;
189
+ }
190
+ case "add":
191
+ case "add_dynamic": {
192
+ const current = typeof before === "number" ? before : 0;
193
+ const addend = typeof effect.value === "number" ? effect.value : 0;
194
+ after = current + addend;
195
+ break;
196
+ }
197
+ case "subtract":
198
+ case "subtract_dynamic": {
199
+ const current = typeof before === "number" ? before : 0;
200
+ const subtrahend = typeof effect.value === "number" ? effect.value : 0;
201
+ after = current - subtrahend;
202
+ break;
203
+ }
204
+ case "set":
205
+ case "set_dynamic":
206
+ after = effect.value;
207
+ break;
208
+ case "set_boolean":
209
+ after = !!effect.value;
210
+ break;
211
+ default:
212
+ return null;
213
+ }
214
+ state[effect.target] = after;
215
+ return {
216
+ target: effect.target,
217
+ operation: effect.operation,
218
+ value: effect.value,
219
+ before: before ?? 0,
220
+ after
221
+ };
222
+ }
223
+ function buildInitialState(schema, overrides) {
224
+ const state = {};
225
+ for (const [name, variable] of Object.entries(schema.variables ?? {})) {
226
+ state[name] = variable.default;
227
+ }
228
+ if (overrides) {
229
+ for (const [key, value] of Object.entries(overrides)) {
230
+ state[key] = value;
231
+ }
232
+ }
233
+ return state;
234
+ }
235
+ function resolveAssumptions(config, profileName) {
236
+ const profile = config.profiles?.[profileName];
237
+ return profile?.parameters ?? {};
238
+ }
239
+ function classifyViability(state, world) {
240
+ const gates = world.gates?.viability_classification ?? [];
241
+ for (const gate of gates) {
242
+ const fieldValue = state[gate.field];
243
+ if (typeof fieldValue !== "number") continue;
244
+ if (evaluateOperator(fieldValue, gate.operator, gate.value)) {
245
+ return gate.status;
246
+ }
247
+ }
248
+ return "MODEL_COLLAPSES";
249
+ }
250
+ function renderSimulateText(result) {
251
+ const lines = [];
252
+ lines.push(`SIMULATION: ${result.worldName}`);
253
+ lines.push(`Profile: ${result.profile}`);
254
+ lines.push(`Steps: ${result.steps.length}`);
255
+ lines.push("");
256
+ lines.push("INITIAL STATE");
257
+ for (const [key, value] of Object.entries(result.initialState)) {
258
+ lines.push(` ${key}: ${value}`);
259
+ }
260
+ lines.push("");
261
+ for (const step of result.steps) {
262
+ lines.push(`STEP ${step.step}`);
263
+ const fired = step.rulesEvaluated.filter((r) => r.triggered);
264
+ const skipped = step.rulesEvaluated.filter((r) => !r.triggered && !r.excluded);
265
+ const excluded = step.rulesEvaluated.filter((r) => r.excluded);
266
+ if (fired.length === 0) {
267
+ lines.push(" No rules fired (state unchanged)");
268
+ } else {
269
+ for (const rule of fired) {
270
+ lines.push(` FIRED: ${rule.label}`);
271
+ for (const effect of rule.effects) {
272
+ const beforeStr = formatValue(effect.before);
273
+ const afterStr = formatValue(effect.after);
274
+ lines.push(` ${effect.target}: ${beforeStr} -> ${afterStr}`);
275
+ }
276
+ if (rule.collapsed) {
277
+ lines.push(` COLLAPSE on ${rule.collapseField}`);
278
+ }
279
+ }
280
+ }
281
+ if (excluded.length > 0) {
282
+ lines.push(` Excluded: ${excluded.map((r) => r.label).join(", ")}`);
283
+ }
284
+ lines.push(` Viability: ${step.viability}`);
285
+ if (step.collapsed) {
286
+ lines.push(" ** MODEL COLLAPSED **");
287
+ }
288
+ lines.push("");
289
+ }
290
+ lines.push("FINAL STATE");
291
+ for (const [key, value] of Object.entries(result.finalState)) {
292
+ const initial = result.initialState[key];
293
+ const changed = initial !== value;
294
+ const marker = changed ? " (changed)" : "";
295
+ lines.push(` ${key}: ${formatValue(value)}${marker}`);
296
+ }
297
+ lines.push("");
298
+ lines.push(`VIABILITY: ${result.finalViability}`);
299
+ if (result.collapsed) {
300
+ lines.push(`COLLAPSED at step ${result.collapseStep} (rule: ${result.collapseRule})`);
301
+ }
302
+ return lines.join("\n");
303
+ }
304
+ function formatValue(v) {
305
+ if (typeof v === "number") {
306
+ return Number.isInteger(v) ? String(v) : v.toFixed(2);
307
+ }
308
+ return String(v);
309
+ }
310
+
311
+ export {
312
+ simulateWorld,
313
+ renderSimulateText
314
+ };