@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.
- package/.well-known/ai-plugin.json +34 -9
- package/AGENTS.md +72 -24
- package/README.md +343 -248
- package/dist/adapters/autoresearch.cjs +1345 -0
- package/dist/adapters/autoresearch.d.cts +111 -0
- package/dist/adapters/autoresearch.d.ts +111 -0
- package/dist/adapters/autoresearch.js +12 -0
- package/dist/adapters/deep-agents.cjs +1528 -0
- package/dist/adapters/deep-agents.d.cts +181 -0
- package/dist/adapters/deep-agents.d.ts +181 -0
- package/dist/adapters/deep-agents.js +17 -0
- package/dist/adapters/express.cjs +1253 -0
- package/dist/adapters/express.d.cts +66 -0
- package/dist/adapters/express.d.ts +66 -0
- package/dist/adapters/express.js +12 -0
- package/dist/adapters/index.cjs +2112 -0
- package/dist/adapters/index.d.cts +8 -0
- package/dist/adapters/index.d.ts +8 -0
- package/dist/adapters/index.js +68 -0
- package/dist/adapters/langchain.cjs +1315 -0
- package/dist/adapters/langchain.d.cts +89 -0
- package/dist/adapters/langchain.d.ts +89 -0
- package/dist/adapters/langchain.js +17 -0
- package/dist/adapters/openai.cjs +1345 -0
- package/dist/adapters/openai.d.cts +99 -0
- package/dist/adapters/openai.d.ts +99 -0
- package/dist/adapters/openai.js +17 -0
- package/dist/adapters/openclaw.cjs +1337 -0
- package/dist/adapters/openclaw.d.cts +99 -0
- package/dist/adapters/openclaw.d.ts +99 -0
- package/dist/adapters/openclaw.js +17 -0
- package/dist/add-ROOZLU62.js +314 -0
- package/dist/behavioral-MJO34S6Q.js +118 -0
- package/dist/bootstrap-CQRZVOXK.js +116 -0
- package/dist/bootstrap-emitter-Q7UIJZ2O.js +7 -0
- package/dist/bootstrap-parser-EEF36XDU.js +7 -0
- package/dist/browser.global.js +941 -0
- package/dist/build-QKOBBC23.js +341 -0
- package/dist/chunk-3WQLXYTP.js +91 -0
- package/dist/chunk-4FLICVVA.js +119 -0
- package/dist/chunk-4NGDRRQH.js +10 -0
- package/dist/chunk-5TPFNWRU.js +215 -0
- package/dist/chunk-5U2MQO5P.js +57 -0
- package/dist/chunk-6CZSKEY5.js +164 -0
- package/dist/chunk-6S5CFQXY.js +624 -0
- package/dist/chunk-7P3S7MAY.js +1090 -0
- package/dist/chunk-A5W4GNQO.js +130 -0
- package/dist/chunk-A7GKPPU7.js +226 -0
- package/dist/chunk-AKW5YVCE.js +96 -0
- package/dist/chunk-B6OXJLJ5.js +622 -0
- package/dist/chunk-BNKJPUPQ.js +113 -0
- package/dist/chunk-BQZMOEML.js +43 -0
- package/dist/chunk-CNSO6XW5.js +207 -0
- package/dist/chunk-CTZHONLA.js +135 -0
- package/dist/chunk-D2UCV5AK.js +326 -0
- package/dist/chunk-EMQDLDAF.js +458 -0
- package/dist/chunk-F66BVUYB.js +340 -0
- package/dist/chunk-G7DJ6VOD.js +101 -0
- package/dist/chunk-I3RRAYK2.js +11 -0
- package/dist/chunk-IS4WUH6Y.js +363 -0
- package/dist/chunk-MH7BT4VH.js +15 -0
- package/dist/chunk-O5ABKEA7.js +304 -0
- package/dist/chunk-OT6PXH54.js +61 -0
- package/dist/chunk-PVTQQS3Y.js +186 -0
- package/dist/chunk-Q6O7ZLO2.js +62 -0
- package/dist/chunk-QLPTHTVB.js +253 -0
- package/dist/chunk-QWGCMQQD.js +16 -0
- package/dist/chunk-QXBFT7NI.js +201 -0
- package/dist/chunk-TG6SEF24.js +246 -0
- package/dist/chunk-U6U7EJZL.js +177 -0
- package/dist/chunk-W7LLXRGY.js +830 -0
- package/dist/chunk-ZJTDUCC2.js +194 -0
- package/dist/chunk-ZWI3NIXK.js +314 -0
- package/dist/cli/neuroverse.cjs +14191 -0
- package/dist/cli/neuroverse.d.cts +1 -0
- package/dist/cli/neuroverse.d.ts +1 -0
- package/dist/cli/neuroverse.js +227 -0
- package/dist/cli/plan.cjs +2439 -0
- package/dist/cli/plan.d.cts +20 -0
- package/dist/cli/plan.d.ts +20 -0
- package/dist/cli/plan.js +353 -0
- package/dist/cli/run.cjs +2001 -0
- package/dist/cli/run.d.cts +20 -0
- package/dist/cli/run.d.ts +20 -0
- package/dist/cli/run.js +143 -0
- package/dist/configure-ai-6TZ3MCSI.js +132 -0
- package/dist/decision-flow-M63D47LO.js +61 -0
- package/dist/demo-G43RLCPK.js +469 -0
- package/dist/derive-FJZVIPUZ.js +153 -0
- package/dist/doctor-6BC6X2VO.js +173 -0
- package/dist/equity-penalties-SG5IZQ7I.js +244 -0
- package/dist/explain-RHBU2GBR.js +51 -0
- package/dist/guard-AJCCGZMF.js +92 -0
- package/dist/guard-contract-DqFcTScd.d.cts +821 -0
- package/dist/guard-contract-DqFcTScd.d.ts +821 -0
- package/dist/guard-engine-PNR6MHCM.js +10 -0
- package/dist/impact-3XVDSCBU.js +59 -0
- package/dist/improve-TQP4ECSY.js +66 -0
- package/dist/index.cjs +7591 -0
- package/dist/index.d.cts +2195 -0
- package/dist/index.d.ts +2195 -0
- package/dist/index.js +472 -0
- package/dist/infer-world-IFXCACJ5.js +543 -0
- package/dist/init-FYPV4SST.js +144 -0
- package/dist/init-world-TI7ARHBT.js +223 -0
- package/dist/mcp-server-5Y3ZM7TV.js +13 -0
- package/dist/model-adapter-VXEKB4LS.js +11 -0
- package/dist/playground-VZBNPPBO.js +560 -0
- package/dist/redteam-MZPZD3EF.js +357 -0
- package/dist/session-JYOARW54.js +15 -0
- package/dist/shared-7RLUHNMU.js +16 -0
- package/dist/shared-B8dvUUD8.d.cts +60 -0
- package/dist/shared-Dr5Wiay8.d.ts +60 -0
- package/dist/simulate-LJXYBC6M.js +83 -0
- package/dist/test-BOOR4A5F.js +217 -0
- package/dist/trace-PKV4KX56.js +166 -0
- package/dist/validate-RALX7CZS.js +81 -0
- package/dist/validate-engine-7ZXFVGF2.js +7 -0
- package/dist/viz/assets/index-B8SaeJZZ.js +23 -0
- package/dist/viz/index.html +23 -0
- package/dist/world-BIP4GZBZ.js +376 -0
- package/dist/world-loader-Y6HMQH2D.js +13 -0
- package/dist/worlds/autoresearch.nv-world.md +230 -0
- package/dist/worlds/coding-agent.nv-world.md +211 -0
- package/dist/worlds/derivation-world.nv-world.md +278 -0
- package/dist/worlds/research-agent.nv-world.md +169 -0
- package/dist/worlds/social-media.nv-world.md +198 -0
- package/dist/worlds/trading-agent.nv-world.md +218 -0
- package/examples/social-media-sim/bridge.py +209 -0
- package/examples/social-media-sim/simulation.py +927 -0
- package/package.json +16 -3
- package/simulate.html +4 -336
|
@@ -0,0 +1,941 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var NeuroVerse = (() => {
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/browser.ts
|
|
22
|
+
var browser_exports = {};
|
|
23
|
+
__export(browser_exports, {
|
|
24
|
+
emitWorldDefinition: () => emitWorldDefinition,
|
|
25
|
+
parseAndEmitWorld: () => parseAndEmitWorld,
|
|
26
|
+
parseWorldMarkdown: () => parseWorldMarkdown,
|
|
27
|
+
simulateWorld: () => simulateWorld
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// src/engine/simulate-engine.ts
|
|
31
|
+
function simulateWorld(world, options = {}) {
|
|
32
|
+
if (!world || !world.world) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
'World definition required. simulateWorld() cannot run without a world.\nLoad one with: loadWorld("./world/") or parseWorldMarkdown(markdown)'
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
const steps = Math.max(1, Math.min(options.steps ?? 1, 50));
|
|
38
|
+
const profileName = options.profile ?? world.world.default_assumption_profile;
|
|
39
|
+
const state = buildInitialState(world.stateSchema, options.stateOverrides);
|
|
40
|
+
for (const outcome of world.outcomes?.computed_outcomes ?? []) {
|
|
41
|
+
if (!(outcome.id in state)) {
|
|
42
|
+
state[outcome.id] = outcome.primary ? 100 : 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const assumptions = resolveAssumptions(world.assumptions, profileName);
|
|
46
|
+
const initialState = { ...state };
|
|
47
|
+
const simulationSteps = [];
|
|
48
|
+
let collapsed = false;
|
|
49
|
+
let collapseStep;
|
|
50
|
+
let collapseRule;
|
|
51
|
+
const sortedRules = [...world.rules].sort((a, b) => a.order - b.order);
|
|
52
|
+
for (let stepNum = 1; stepNum <= steps; stepNum++) {
|
|
53
|
+
if (collapsed) break;
|
|
54
|
+
const stepResult = evaluateStep(
|
|
55
|
+
stepNum,
|
|
56
|
+
sortedRules,
|
|
57
|
+
state,
|
|
58
|
+
assumptions,
|
|
59
|
+
world
|
|
60
|
+
);
|
|
61
|
+
simulationSteps.push(stepResult);
|
|
62
|
+
if (stepResult.collapsed) {
|
|
63
|
+
collapsed = true;
|
|
64
|
+
collapseStep = stepNum;
|
|
65
|
+
collapseRule = stepResult.rulesEvaluated.find((r) => r.collapsed)?.ruleId;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const finalViability = classifyViability(state, world);
|
|
69
|
+
return {
|
|
70
|
+
worldId: world.world.world_id,
|
|
71
|
+
worldName: world.world.name,
|
|
72
|
+
profile: profileName,
|
|
73
|
+
initialState,
|
|
74
|
+
steps: simulationSteps,
|
|
75
|
+
finalState: { ...state },
|
|
76
|
+
finalViability,
|
|
77
|
+
collapsed,
|
|
78
|
+
collapseStep,
|
|
79
|
+
collapseRule
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function evaluateStep(stepNum, rules, state, assumptions, world) {
|
|
83
|
+
const evaluations = [];
|
|
84
|
+
let rulesFired = 0;
|
|
85
|
+
let collapsed = false;
|
|
86
|
+
const firedRuleIds = /* @__PURE__ */ new Set();
|
|
87
|
+
for (const rule of rules) {
|
|
88
|
+
if (collapsed) {
|
|
89
|
+
evaluations.push({
|
|
90
|
+
ruleId: rule.id,
|
|
91
|
+
label: rule.label,
|
|
92
|
+
triggered: false,
|
|
93
|
+
excluded: true,
|
|
94
|
+
effects: [],
|
|
95
|
+
collapsed: false
|
|
96
|
+
});
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const excluded = rule.exclusive_with ? firedRuleIds.has(rule.exclusive_with) : false;
|
|
100
|
+
if (excluded) {
|
|
101
|
+
evaluations.push({
|
|
102
|
+
ruleId: rule.id,
|
|
103
|
+
label: rule.label,
|
|
104
|
+
triggered: false,
|
|
105
|
+
excluded: true,
|
|
106
|
+
effects: [],
|
|
107
|
+
collapsed: false
|
|
108
|
+
});
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const triggered = evaluateTriggers(rule.triggers, state, assumptions);
|
|
112
|
+
if (!triggered) {
|
|
113
|
+
evaluations.push({
|
|
114
|
+
ruleId: rule.id,
|
|
115
|
+
label: rule.label,
|
|
116
|
+
triggered: false,
|
|
117
|
+
excluded: false,
|
|
118
|
+
effects: [],
|
|
119
|
+
collapsed: false
|
|
120
|
+
});
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
firedRuleIds.add(rule.id);
|
|
124
|
+
rulesFired++;
|
|
125
|
+
const appliedEffects = [];
|
|
126
|
+
for (const effect of rule.effects ?? []) {
|
|
127
|
+
const applied = applyEffect(effect, state);
|
|
128
|
+
if (applied) appliedEffects.push(applied);
|
|
129
|
+
}
|
|
130
|
+
for (const ce of rule.effects_conditional ?? []) {
|
|
131
|
+
const conditionMet = evaluateSingleTrigger(ce.condition, state, assumptions);
|
|
132
|
+
const andMet = ce.and ? evaluateSingleTrigger(ce.and, state, assumptions) : true;
|
|
133
|
+
const orMet = ce.or ? evaluateSingleTrigger(ce.or, state, assumptions) : false;
|
|
134
|
+
const anyMet = ce.condition_any ? ce.condition_any.some((c) => evaluateSingleTrigger(c, state, assumptions)) : false;
|
|
135
|
+
const shouldApply = conditionMet && andMet || ce.or && orMet || ce.condition_any && anyMet;
|
|
136
|
+
if (shouldApply) {
|
|
137
|
+
for (const effect of ce.effects) {
|
|
138
|
+
const applied = applyEffect(effect, state);
|
|
139
|
+
if (applied) appliedEffects.push(applied);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
let ruleCollapsed = false;
|
|
144
|
+
if (rule.collapse_check) {
|
|
145
|
+
const fieldVal = typeof state[rule.collapse_check.field] === "number" ? state[rule.collapse_check.field] : 0;
|
|
146
|
+
if (evaluateOperator(fieldVal, rule.collapse_check.operator, rule.collapse_check.value)) {
|
|
147
|
+
ruleCollapsed = true;
|
|
148
|
+
collapsed = true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (!ruleCollapsed && rule.secondary_check) {
|
|
152
|
+
const fieldVal = typeof state[rule.secondary_check.field] === "number" ? state[rule.secondary_check.field] : 0;
|
|
153
|
+
if (evaluateOperator(fieldVal, rule.secondary_check.operator, rule.secondary_check.value)) {
|
|
154
|
+
ruleCollapsed = true;
|
|
155
|
+
collapsed = true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
evaluations.push({
|
|
159
|
+
ruleId: rule.id,
|
|
160
|
+
label: rule.label,
|
|
161
|
+
triggered: true,
|
|
162
|
+
excluded: false,
|
|
163
|
+
effects: appliedEffects,
|
|
164
|
+
collapsed: ruleCollapsed,
|
|
165
|
+
collapseField: ruleCollapsed ? rule.collapse_check?.field ?? rule.secondary_check?.field : void 0
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
const viability = classifyViability(state, world);
|
|
169
|
+
return {
|
|
170
|
+
step: stepNum,
|
|
171
|
+
rulesEvaluated: evaluations,
|
|
172
|
+
rulesFired,
|
|
173
|
+
stateAfter: { ...state },
|
|
174
|
+
viability,
|
|
175
|
+
collapsed
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function evaluateTriggers(triggers, state, assumptions) {
|
|
179
|
+
if (!triggers || triggers.length === 0) return true;
|
|
180
|
+
return triggers.every((t) => evaluateSingleTrigger(t, state, assumptions));
|
|
181
|
+
}
|
|
182
|
+
function evaluateSingleTrigger(trigger, state, assumptions) {
|
|
183
|
+
const source = trigger.source === "assumption" ? assumptions : state;
|
|
184
|
+
const fieldValue = source[trigger.field];
|
|
185
|
+
if (fieldValue === void 0) return false;
|
|
186
|
+
return evaluateOperator(fieldValue, trigger.operator, trigger.value);
|
|
187
|
+
}
|
|
188
|
+
function evaluateOperator(fieldValue, operator, conditionValue) {
|
|
189
|
+
switch (operator) {
|
|
190
|
+
case "==":
|
|
191
|
+
return fieldValue === conditionValue;
|
|
192
|
+
case "!=":
|
|
193
|
+
return fieldValue !== conditionValue;
|
|
194
|
+
case ">":
|
|
195
|
+
return typeof fieldValue === "number" && typeof conditionValue === "number" && fieldValue > conditionValue;
|
|
196
|
+
case "<":
|
|
197
|
+
return typeof fieldValue === "number" && typeof conditionValue === "number" && fieldValue < conditionValue;
|
|
198
|
+
case ">=":
|
|
199
|
+
return typeof fieldValue === "number" && typeof conditionValue === "number" && fieldValue >= conditionValue;
|
|
200
|
+
case "<=":
|
|
201
|
+
return typeof fieldValue === "number" && typeof conditionValue === "number" && fieldValue <= conditionValue;
|
|
202
|
+
case "in":
|
|
203
|
+
return Array.isArray(conditionValue) && conditionValue.includes(String(fieldValue));
|
|
204
|
+
default:
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function applyEffect(effect, state) {
|
|
209
|
+
const before = state[effect.target];
|
|
210
|
+
let after;
|
|
211
|
+
switch (effect.operation) {
|
|
212
|
+
case "multiply":
|
|
213
|
+
case "multiply_dynamic": {
|
|
214
|
+
const current = typeof before === "number" ? before : 0;
|
|
215
|
+
const factor = typeof effect.value === "number" ? effect.value : 1;
|
|
216
|
+
after = current * factor;
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
case "add":
|
|
220
|
+
case "add_dynamic": {
|
|
221
|
+
const current = typeof before === "number" ? before : 0;
|
|
222
|
+
const addend = typeof effect.value === "number" ? effect.value : 0;
|
|
223
|
+
after = current + addend;
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
case "subtract":
|
|
227
|
+
case "subtract_dynamic": {
|
|
228
|
+
const current = typeof before === "number" ? before : 0;
|
|
229
|
+
const subtrahend = typeof effect.value === "number" ? effect.value : 0;
|
|
230
|
+
after = current - subtrahend;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
case "set":
|
|
234
|
+
case "set_dynamic":
|
|
235
|
+
after = effect.value;
|
|
236
|
+
break;
|
|
237
|
+
case "set_boolean":
|
|
238
|
+
after = !!effect.value;
|
|
239
|
+
break;
|
|
240
|
+
default:
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
state[effect.target] = after;
|
|
244
|
+
return {
|
|
245
|
+
target: effect.target,
|
|
246
|
+
operation: effect.operation,
|
|
247
|
+
value: effect.value,
|
|
248
|
+
before: before ?? 0,
|
|
249
|
+
after
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
function buildInitialState(schema, overrides) {
|
|
253
|
+
const state = {};
|
|
254
|
+
for (const [name, variable] of Object.entries(schema.variables ?? {})) {
|
|
255
|
+
state[name] = variable.default;
|
|
256
|
+
}
|
|
257
|
+
if (overrides) {
|
|
258
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
259
|
+
state[key] = value;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return state;
|
|
263
|
+
}
|
|
264
|
+
function resolveAssumptions(config, profileName) {
|
|
265
|
+
const profile = config.profiles?.[profileName];
|
|
266
|
+
return profile?.parameters ?? {};
|
|
267
|
+
}
|
|
268
|
+
function classifyViability(state, world) {
|
|
269
|
+
const gates = world.gates?.viability_classification ?? [];
|
|
270
|
+
for (const gate of gates) {
|
|
271
|
+
const fieldValue = state[gate.field];
|
|
272
|
+
if (typeof fieldValue !== "number") continue;
|
|
273
|
+
if (evaluateOperator(fieldValue, gate.operator, gate.value)) {
|
|
274
|
+
return gate.status;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return "MODEL_COLLAPSES";
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/engine/bootstrap-parser.ts
|
|
281
|
+
function splitSections(markdown) {
|
|
282
|
+
const lines = markdown.split("\n");
|
|
283
|
+
let frontmatter = "";
|
|
284
|
+
let bodyStart = 0;
|
|
285
|
+
if (lines[0]?.trim() === "---") {
|
|
286
|
+
const endIdx = lines.indexOf("---", 1);
|
|
287
|
+
if (endIdx > 0) {
|
|
288
|
+
frontmatter = lines.slice(1, endIdx).join("\n");
|
|
289
|
+
bodyStart = endIdx + 1;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const sections = [];
|
|
293
|
+
let currentSection = null;
|
|
294
|
+
const contentLines = [];
|
|
295
|
+
for (let i = bodyStart; i < lines.length; i++) {
|
|
296
|
+
const line = lines[i];
|
|
297
|
+
if (line.startsWith("# ")) {
|
|
298
|
+
if (currentSection) {
|
|
299
|
+
currentSection.content = contentLines.join("\n").trim();
|
|
300
|
+
sections.push(currentSection);
|
|
301
|
+
contentLines.length = 0;
|
|
302
|
+
}
|
|
303
|
+
currentSection = {
|
|
304
|
+
name: line.replace(/^#\s+/, "").trim(),
|
|
305
|
+
content: "",
|
|
306
|
+
startLine: i + 1
|
|
307
|
+
// 1-based
|
|
308
|
+
};
|
|
309
|
+
} else if (currentSection) {
|
|
310
|
+
contentLines.push(line);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (currentSection) {
|
|
314
|
+
currentSection.content = contentLines.join("\n").trim();
|
|
315
|
+
sections.push(currentSection);
|
|
316
|
+
}
|
|
317
|
+
return { frontmatter, sections };
|
|
318
|
+
}
|
|
319
|
+
function parseFrontmatter(yaml, issues) {
|
|
320
|
+
const result = {};
|
|
321
|
+
for (const line of yaml.split("\n")) {
|
|
322
|
+
const trimmed = line.trim();
|
|
323
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
324
|
+
const colonIdx = trimmed.indexOf(":");
|
|
325
|
+
if (colonIdx === -1) continue;
|
|
326
|
+
const key = trimmed.slice(0, colonIdx).trim();
|
|
327
|
+
const value = trimmed.slice(colonIdx + 1).trim();
|
|
328
|
+
result[key] = value;
|
|
329
|
+
}
|
|
330
|
+
if (!result.world_id) {
|
|
331
|
+
issues.push({ line: 1, section: "frontmatter", message: "Missing world_id in frontmatter", severity: "error" });
|
|
332
|
+
}
|
|
333
|
+
if (!result.name) {
|
|
334
|
+
issues.push({ line: 1, section: "frontmatter", message: "Missing name in frontmatter", severity: "error" });
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
world_id: result.world_id ?? "",
|
|
338
|
+
name: result.name ?? "",
|
|
339
|
+
version: result.version,
|
|
340
|
+
runtime_mode: result.runtime_mode,
|
|
341
|
+
default_profile: result.default_profile,
|
|
342
|
+
alternative_profile: result.alternative_profile
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function parseThesis(content, startLine, issues) {
|
|
346
|
+
const thesis = content.trim();
|
|
347
|
+
if (!thesis) {
|
|
348
|
+
issues.push({ line: startLine, section: "Thesis", message: "Thesis section is empty", severity: "error" });
|
|
349
|
+
}
|
|
350
|
+
return thesis;
|
|
351
|
+
}
|
|
352
|
+
function parseInvariants(content, startLine, issues) {
|
|
353
|
+
const invariants = [];
|
|
354
|
+
const lines = content.split("\n");
|
|
355
|
+
for (let i = 0; i < lines.length; i++) {
|
|
356
|
+
const line = lines[i].trim();
|
|
357
|
+
if (!line.startsWith("- ")) continue;
|
|
358
|
+
const lineNum = startLine + i + 1;
|
|
359
|
+
const match = line.match(
|
|
360
|
+
/^-\s+`([^`]+)`\s*[—–-]\s*(.+?)(?:\s*\(([^)]+)\))?\s*$/
|
|
361
|
+
);
|
|
362
|
+
if (match) {
|
|
363
|
+
const id = match[1];
|
|
364
|
+
const label = match[2].trim();
|
|
365
|
+
const parens = match[3] ?? "structural, immutable";
|
|
366
|
+
const enforcement = parens.includes("prompt") ? "prompt" : parens.includes("operational") ? "operational" : "structural";
|
|
367
|
+
const mutable = parens.includes("mutable") && !parens.includes("immutable");
|
|
368
|
+
invariants.push({ id, label, enforcement, mutable, line: lineNum });
|
|
369
|
+
} else {
|
|
370
|
+
const fallback = line.match(/^-\s+\*\*([^*]+)\*\*\s*[—–-]\s*(.+)/);
|
|
371
|
+
if (fallback) {
|
|
372
|
+
const id = fallback[1].toLowerCase().replace(/\s+/g, "_");
|
|
373
|
+
const label = fallback[2].trim();
|
|
374
|
+
invariants.push({ id, label, enforcement: "structural", mutable: false, line: lineNum });
|
|
375
|
+
} else {
|
|
376
|
+
issues.push({ line: lineNum, section: "Invariants", message: `Could not parse invariant: "${line}"`, severity: "warning" });
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (invariants.length === 0) {
|
|
381
|
+
issues.push({ line: startLine, section: "Invariants", message: "No invariants found", severity: "error" });
|
|
382
|
+
}
|
|
383
|
+
return invariants;
|
|
384
|
+
}
|
|
385
|
+
function parseStateVariables(content, startLine, issues) {
|
|
386
|
+
const variables = [];
|
|
387
|
+
const subSections = splitH2Sections(content, startLine);
|
|
388
|
+
for (const sub of subSections) {
|
|
389
|
+
const props = parseKeyValueBullets(sub.content);
|
|
390
|
+
const lineNum = sub.startLine;
|
|
391
|
+
const type = props.type;
|
|
392
|
+
if (!type) {
|
|
393
|
+
issues.push({ line: lineNum, section: "State", message: `Variable "${sub.name}" missing type`, severity: "error" });
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
let defaultVal = props.default ?? "";
|
|
397
|
+
if (type === "number") {
|
|
398
|
+
defaultVal = parseFloat(String(defaultVal)) || 0;
|
|
399
|
+
} else if (type === "boolean") {
|
|
400
|
+
defaultVal = String(defaultVal).toLowerCase() === "true";
|
|
401
|
+
}
|
|
402
|
+
const variable = {
|
|
403
|
+
id: sub.name,
|
|
404
|
+
type,
|
|
405
|
+
default: defaultVal,
|
|
406
|
+
label: props.label ?? sub.name,
|
|
407
|
+
description: props.description ?? "",
|
|
408
|
+
line: lineNum
|
|
409
|
+
};
|
|
410
|
+
if (type === "number") {
|
|
411
|
+
if (props.min !== void 0) variable.min = parseFloat(props.min);
|
|
412
|
+
if (props.max !== void 0) variable.max = parseFloat(props.max);
|
|
413
|
+
if (props.step !== void 0) variable.step = parseFloat(props.step);
|
|
414
|
+
}
|
|
415
|
+
if (type === "enum" && props.options) {
|
|
416
|
+
variable.options = props.options.split(",").map((s) => s.trim());
|
|
417
|
+
}
|
|
418
|
+
variables.push(variable);
|
|
419
|
+
}
|
|
420
|
+
return variables;
|
|
421
|
+
}
|
|
422
|
+
function parseAssumptions(content, startLine, issues) {
|
|
423
|
+
const profiles = [];
|
|
424
|
+
const subSections = splitH2Sections(content, startLine);
|
|
425
|
+
for (const sub of subSections) {
|
|
426
|
+
const props = parseKeyValueBullets(sub.content);
|
|
427
|
+
const name = props.name ?? sub.name;
|
|
428
|
+
const description = props.description ?? "";
|
|
429
|
+
const parameters = {};
|
|
430
|
+
for (const [key, val] of Object.entries(props)) {
|
|
431
|
+
if (key === "name" || key === "description") continue;
|
|
432
|
+
if (val === "true") parameters[key] = true;
|
|
433
|
+
else if (val === "false") parameters[key] = false;
|
|
434
|
+
else if (!isNaN(Number(val)) && val.trim() !== "") parameters[key] = Number(val);
|
|
435
|
+
else parameters[key] = val;
|
|
436
|
+
}
|
|
437
|
+
profiles.push({
|
|
438
|
+
id: sub.name,
|
|
439
|
+
name,
|
|
440
|
+
description,
|
|
441
|
+
parameters,
|
|
442
|
+
line: sub.startLine
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
return profiles;
|
|
446
|
+
}
|
|
447
|
+
function parseRules(content, startLine, issues) {
|
|
448
|
+
const rules = [];
|
|
449
|
+
const subSections = splitH2Sections(content, startLine);
|
|
450
|
+
for (let ruleIdx = 0; ruleIdx < subSections.length; ruleIdx++) {
|
|
451
|
+
const sub = subSections[ruleIdx];
|
|
452
|
+
const lineNum = sub.startLine;
|
|
453
|
+
const headingMatch = sub.name.match(/^([^:]+):\s*(.+?)(?:\s*\(([^)]+)\))?\s*$/);
|
|
454
|
+
const id = headingMatch ? headingMatch[1].trim() : `rule-${String(ruleIdx + 1).padStart(3, "0")}`;
|
|
455
|
+
const label = headingMatch ? headingMatch[2].trim() : sub.name;
|
|
456
|
+
const severity = headingMatch?.[3]?.trim() ?? "degradation";
|
|
457
|
+
const lines = sub.content.split("\n");
|
|
458
|
+
let description = "";
|
|
459
|
+
const triggers = [];
|
|
460
|
+
const effects = [];
|
|
461
|
+
let collapseCheck;
|
|
462
|
+
const causalParts = {};
|
|
463
|
+
for (let i = 0; i < lines.length; i++) {
|
|
464
|
+
const line = lines[i].trim();
|
|
465
|
+
if (line.startsWith("When ")) {
|
|
466
|
+
const triggerStr = line.slice(5);
|
|
467
|
+
const parts = triggerStr.split(/\s+AND\s+/i);
|
|
468
|
+
for (const part of parts) {
|
|
469
|
+
const trigger = parseTriggerExpression(part.trim());
|
|
470
|
+
if (trigger) triggers.push(trigger);
|
|
471
|
+
else issues.push({ line: lineNum + i, section: "Rules", message: `Could not parse trigger: "${part}"`, severity: "warning" });
|
|
472
|
+
}
|
|
473
|
+
} else if (line.startsWith("Then ")) {
|
|
474
|
+
const effectStr = line.slice(5);
|
|
475
|
+
const parts = effectStr.split(",");
|
|
476
|
+
for (const part of parts) {
|
|
477
|
+
const effect = parseEffectExpression(part.trim());
|
|
478
|
+
if (effect) effects.push(effect);
|
|
479
|
+
else issues.push({ line: lineNum + i, section: "Rules", message: `Could not parse effect: "${part}"`, severity: "warning" });
|
|
480
|
+
}
|
|
481
|
+
} else if (line.startsWith("Collapse:")) {
|
|
482
|
+
const collapseStr = line.slice(9).trim();
|
|
483
|
+
const collapse = parseCollapseExpression(collapseStr);
|
|
484
|
+
if (collapse) collapseCheck = collapse;
|
|
485
|
+
else issues.push({ line: lineNum + i, section: "Rules", message: `Could not parse collapse: "${collapseStr}"`, severity: "warning" });
|
|
486
|
+
} else if (line.startsWith("> ")) {
|
|
487
|
+
const causalMatch = line.match(/^>\s*(trigger|rule|shift|effect):\s*(.+)/i);
|
|
488
|
+
if (causalMatch) {
|
|
489
|
+
causalParts[causalMatch[1].toLowerCase()] = causalMatch[2].trim();
|
|
490
|
+
}
|
|
491
|
+
} else if (line && !line.startsWith("-") && !line.startsWith("#")) {
|
|
492
|
+
if (!description) description = line;
|
|
493
|
+
else description += " " + line;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
if (triggers.length === 0) {
|
|
497
|
+
issues.push({ line: lineNum, section: "Rules", message: `Rule "${id}" has no triggers (missing "When" line)`, severity: "warning" });
|
|
498
|
+
}
|
|
499
|
+
if (effects.length === 0) {
|
|
500
|
+
issues.push({ line: lineNum, section: "Rules", message: `Rule "${id}" has no effects (missing "Then" line)`, severity: "warning" });
|
|
501
|
+
}
|
|
502
|
+
const causal_translation = Object.keys(causalParts).length > 0 ? {
|
|
503
|
+
trigger_text: causalParts.trigger ?? "",
|
|
504
|
+
rule_text: causalParts.rule ?? "",
|
|
505
|
+
shift_text: causalParts.shift ?? "",
|
|
506
|
+
effect_text: causalParts.effect ?? ""
|
|
507
|
+
} : void 0;
|
|
508
|
+
rules.push({
|
|
509
|
+
id,
|
|
510
|
+
label,
|
|
511
|
+
severity,
|
|
512
|
+
description: description || void 0,
|
|
513
|
+
order: ruleIdx + 1,
|
|
514
|
+
triggers,
|
|
515
|
+
effects,
|
|
516
|
+
collapse_check: collapseCheck,
|
|
517
|
+
causal_translation,
|
|
518
|
+
line: lineNum
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
return rules;
|
|
522
|
+
}
|
|
523
|
+
function parseTriggerExpression(expr) {
|
|
524
|
+
const match = expr.match(
|
|
525
|
+
/^(\w+)\s*(==|!=|>=|<=|>|<|in)\s*(.+?)\s*\[(state|assumption)\]\s*$/
|
|
526
|
+
);
|
|
527
|
+
if (!match) return null;
|
|
528
|
+
const field = match[1];
|
|
529
|
+
const operator = match[2];
|
|
530
|
+
let value = match[3].trim();
|
|
531
|
+
const source = match[4];
|
|
532
|
+
value = parseValueLiteral(value);
|
|
533
|
+
return { field, operator, value, source };
|
|
534
|
+
}
|
|
535
|
+
function parseEffectExpression(expr) {
|
|
536
|
+
const compound = expr.match(/^(\w+)\s*(\*=|\+=|-=)\s*(.+)$/);
|
|
537
|
+
if (compound) {
|
|
538
|
+
const target = compound[1];
|
|
539
|
+
const op = compound[2];
|
|
540
|
+
const value = parseValueLiteral(compound[3].trim());
|
|
541
|
+
const operationMap = {
|
|
542
|
+
"*=": "multiply",
|
|
543
|
+
"+=": "add",
|
|
544
|
+
"-=": "subtract"
|
|
545
|
+
};
|
|
546
|
+
return { target, operation: operationMap[op], value };
|
|
547
|
+
}
|
|
548
|
+
const assignment = expr.match(/^(\w+)\s*=\s*(.+)$/);
|
|
549
|
+
if (assignment) {
|
|
550
|
+
const target = assignment[1];
|
|
551
|
+
const value = parseValueLiteral(assignment[2].trim());
|
|
552
|
+
const operation = typeof value === "boolean" ? "set_boolean" : "set";
|
|
553
|
+
return { target, operation, value };
|
|
554
|
+
}
|
|
555
|
+
return null;
|
|
556
|
+
}
|
|
557
|
+
function parseCollapseExpression(expr) {
|
|
558
|
+
const cleaned = expr.replace(/\s*→.*$/, "").trim();
|
|
559
|
+
const match = cleaned.match(/^(\w+)\s*(==|!=|>=|<=|>|<)\s*([\d.]+)$/);
|
|
560
|
+
if (!match) return null;
|
|
561
|
+
return {
|
|
562
|
+
field: match[1],
|
|
563
|
+
operator: match[2],
|
|
564
|
+
value: parseFloat(match[3])
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
function parseGates(content, startLine, issues) {
|
|
568
|
+
const gates = [];
|
|
569
|
+
const lines = content.split("\n");
|
|
570
|
+
for (let i = 0; i < lines.length; i++) {
|
|
571
|
+
const line = lines[i].trim();
|
|
572
|
+
if (!line.startsWith("- ")) continue;
|
|
573
|
+
const lineNum = startLine + i + 1;
|
|
574
|
+
const match = line.match(/^-\s+(\w+):\s*(\w+)\s*(==|!=|>=|<=|>|<)\s*([\d.]+)/);
|
|
575
|
+
if (match) {
|
|
576
|
+
gates.push({
|
|
577
|
+
status: match[1],
|
|
578
|
+
field: match[2],
|
|
579
|
+
operator: match[3],
|
|
580
|
+
value: parseFloat(match[4]),
|
|
581
|
+
line: lineNum
|
|
582
|
+
});
|
|
583
|
+
} else {
|
|
584
|
+
issues.push({ line: lineNum, section: "Gates", message: `Could not parse gate: "${line}"`, severity: "warning" });
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
if (gates.length === 0) {
|
|
588
|
+
issues.push({ line: startLine, section: "Gates", message: "No gates found", severity: "error" });
|
|
589
|
+
}
|
|
590
|
+
return gates;
|
|
591
|
+
}
|
|
592
|
+
function parseOutcomes(content, startLine, issues) {
|
|
593
|
+
const outcomes = [];
|
|
594
|
+
const subSections = splitH2Sections(content, startLine);
|
|
595
|
+
for (const sub of subSections) {
|
|
596
|
+
const props = parseKeyValueBullets(sub.content);
|
|
597
|
+
const outcome = {
|
|
598
|
+
id: sub.name,
|
|
599
|
+
type: props.type ?? "number",
|
|
600
|
+
label: props.label ?? sub.name,
|
|
601
|
+
line: sub.startLine
|
|
602
|
+
};
|
|
603
|
+
if (props.range) {
|
|
604
|
+
const rangeParts = props.range.split("-").map(Number);
|
|
605
|
+
if (rangeParts.length === 2 && !isNaN(rangeParts[0]) && !isNaN(rangeParts[1])) {
|
|
606
|
+
outcome.range = [rangeParts[0], rangeParts[1]];
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
if (props.display) outcome.display = props.display;
|
|
610
|
+
if (props.primary) outcome.primary = props.primary === "true";
|
|
611
|
+
if (props.assignment) outcome.assignment = props.assignment;
|
|
612
|
+
outcomes.push(outcome);
|
|
613
|
+
}
|
|
614
|
+
return outcomes;
|
|
615
|
+
}
|
|
616
|
+
function splitH2Sections(content, baseStartLine) {
|
|
617
|
+
const lines = content.split("\n");
|
|
618
|
+
const sections = [];
|
|
619
|
+
let current = null;
|
|
620
|
+
const contentLines = [];
|
|
621
|
+
for (let i = 0; i < lines.length; i++) {
|
|
622
|
+
const line = lines[i];
|
|
623
|
+
if (line.startsWith("## ")) {
|
|
624
|
+
if (current) {
|
|
625
|
+
current.content = contentLines.join("\n").trim();
|
|
626
|
+
sections.push(current);
|
|
627
|
+
contentLines.length = 0;
|
|
628
|
+
}
|
|
629
|
+
current = {
|
|
630
|
+
name: line.replace(/^##\s+/, "").trim(),
|
|
631
|
+
content: "",
|
|
632
|
+
startLine: baseStartLine + i + 1
|
|
633
|
+
};
|
|
634
|
+
} else if (current) {
|
|
635
|
+
contentLines.push(line);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (current) {
|
|
639
|
+
current.content = contentLines.join("\n").trim();
|
|
640
|
+
sections.push(current);
|
|
641
|
+
}
|
|
642
|
+
return sections;
|
|
643
|
+
}
|
|
644
|
+
function parseKeyValueBullets(content) {
|
|
645
|
+
const result = {};
|
|
646
|
+
for (const line of content.split("\n")) {
|
|
647
|
+
const trimmed = line.trim();
|
|
648
|
+
const match = trimmed.match(/^-\s+(\w[\w\s]*?):\s*(.+)$/);
|
|
649
|
+
if (match) {
|
|
650
|
+
result[match[1].trim().toLowerCase().replace(/\s+/g, "_")] = match[2].trim();
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return result;
|
|
654
|
+
}
|
|
655
|
+
function parseValueLiteral(raw) {
|
|
656
|
+
if (raw === "true") return true;
|
|
657
|
+
if (raw === "false") return false;
|
|
658
|
+
if (raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("'") && raw.endsWith("'")) {
|
|
659
|
+
return raw.slice(1, -1);
|
|
660
|
+
}
|
|
661
|
+
const num = Number(raw);
|
|
662
|
+
if (!isNaN(num) && raw.trim() !== "") return num;
|
|
663
|
+
return raw;
|
|
664
|
+
}
|
|
665
|
+
function parseWorldMarkdown(markdown) {
|
|
666
|
+
const issues = [];
|
|
667
|
+
const { frontmatter: fmRaw, sections } = splitSections(markdown);
|
|
668
|
+
const frontmatter = parseFrontmatter(fmRaw, issues);
|
|
669
|
+
const findSection = (name) => sections.find((s) => s.name.toLowerCase() === name.toLowerCase());
|
|
670
|
+
const thesisSection = findSection("Thesis");
|
|
671
|
+
const thesis = thesisSection ? parseThesis(thesisSection.content, thesisSection.startLine, issues) : "";
|
|
672
|
+
if (!thesisSection) {
|
|
673
|
+
issues.push({ line: 0, section: "Thesis", message: "Missing # Thesis section", severity: "error" });
|
|
674
|
+
}
|
|
675
|
+
const invariantsSection = findSection("Invariants");
|
|
676
|
+
const invariants = invariantsSection ? parseInvariants(invariantsSection.content, invariantsSection.startLine, issues) : [];
|
|
677
|
+
if (!invariantsSection) {
|
|
678
|
+
issues.push({ line: 0, section: "Invariants", message: "Missing # Invariants section", severity: "error" });
|
|
679
|
+
}
|
|
680
|
+
const stateSection = findSection("State");
|
|
681
|
+
const stateVariables = stateSection ? parseStateVariables(stateSection.content, stateSection.startLine, issues) : [];
|
|
682
|
+
if (!stateSection) {
|
|
683
|
+
issues.push({ line: 0, section: "State", message: "Missing # State section", severity: "warning" });
|
|
684
|
+
}
|
|
685
|
+
const assumptionsSection = findSection("Assumptions");
|
|
686
|
+
const assumptions = assumptionsSection ? parseAssumptions(assumptionsSection.content, assumptionsSection.startLine, issues) : [];
|
|
687
|
+
if (!assumptionsSection) {
|
|
688
|
+
issues.push({ line: 0, section: "Assumptions", message: "Missing # Assumptions section", severity: "warning" });
|
|
689
|
+
}
|
|
690
|
+
const rulesSection = findSection("Rules");
|
|
691
|
+
const rules = rulesSection ? parseRules(rulesSection.content, rulesSection.startLine, issues) : [];
|
|
692
|
+
if (!rulesSection) {
|
|
693
|
+
issues.push({ line: 0, section: "Rules", message: "Missing # Rules section", severity: "warning" });
|
|
694
|
+
}
|
|
695
|
+
const gatesSection = findSection("Gates");
|
|
696
|
+
const gates = gatesSection ? parseGates(gatesSection.content, gatesSection.startLine, issues) : [];
|
|
697
|
+
if (!gatesSection) {
|
|
698
|
+
issues.push({ line: 0, section: "Gates", message: "Missing # Gates section", severity: "warning" });
|
|
699
|
+
}
|
|
700
|
+
const outcomesSection = findSection("Outcomes");
|
|
701
|
+
const outcomes = outcomesSection ? parseOutcomes(outcomesSection.content, outcomesSection.startLine, issues) : [];
|
|
702
|
+
const parsedSections = sections.map((s) => s.name);
|
|
703
|
+
const knownSections = /* @__PURE__ */ new Set(["thesis", "invariants", "state", "assumptions", "rules", "gates", "outcomes"]);
|
|
704
|
+
for (const section of sections) {
|
|
705
|
+
if (!knownSections.has(section.name.toLowerCase())) {
|
|
706
|
+
issues.push({
|
|
707
|
+
line: section.startLine,
|
|
708
|
+
section: section.name,
|
|
709
|
+
message: `Unrecognized section "${section.name}" \u2014 will be ignored`,
|
|
710
|
+
severity: "info"
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
715
|
+
if (!frontmatter.world_id || !thesis) {
|
|
716
|
+
if (hasErrors) {
|
|
717
|
+
return { world: null, issues };
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return {
|
|
721
|
+
world: {
|
|
722
|
+
frontmatter,
|
|
723
|
+
thesis,
|
|
724
|
+
invariants,
|
|
725
|
+
stateVariables,
|
|
726
|
+
assumptions,
|
|
727
|
+
rules,
|
|
728
|
+
gates,
|
|
729
|
+
outcomes
|
|
730
|
+
},
|
|
731
|
+
issues
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// src/engine/bootstrap-emitter.ts
|
|
736
|
+
var GATE_DEFAULTS = {
|
|
737
|
+
THRIVING: { color: "#0f6b3a", icon: "\u2726" },
|
|
738
|
+
STABLE: { color: "#1856b8", icon: "\u25CF" },
|
|
739
|
+
COMPRESSED: { color: "#a16207", icon: "\u25B2" },
|
|
740
|
+
CRITICAL: { color: "#b91c1c", icon: "\u26A0" },
|
|
741
|
+
MODEL_COLLAPSES: { color: "#7f1d1d", icon: "\u2715" }
|
|
742
|
+
};
|
|
743
|
+
function emitWorldDefinition(parsed) {
|
|
744
|
+
const issues = [];
|
|
745
|
+
const fm = parsed.frontmatter;
|
|
746
|
+
const defaultProfile = fm.default_profile ?? parsed.assumptions[0]?.id ?? "baseline";
|
|
747
|
+
const altProfile = fm.alternative_profile ?? parsed.assumptions[1]?.id ?? "alternative";
|
|
748
|
+
const world = {
|
|
749
|
+
world_id: fm.world_id,
|
|
750
|
+
name: fm.name,
|
|
751
|
+
thesis: parsed.thesis,
|
|
752
|
+
version: fm.version ?? "1.0.0",
|
|
753
|
+
runtime_mode: fm.runtime_mode ?? "SIMULATION",
|
|
754
|
+
default_assumption_profile: defaultProfile,
|
|
755
|
+
default_alternative_profile: altProfile,
|
|
756
|
+
modules: parsed.rules.map((r) => r.id),
|
|
757
|
+
players: {
|
|
758
|
+
thinking_space: true,
|
|
759
|
+
experience_space: true,
|
|
760
|
+
action_space: true
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
const invariants = parsed.invariants.map((inv) => ({
|
|
764
|
+
id: inv.id,
|
|
765
|
+
label: inv.label,
|
|
766
|
+
enforcement: inv.enforcement === "prompt" ? "prompt" : "structural",
|
|
767
|
+
mutable: false
|
|
768
|
+
}));
|
|
769
|
+
const profiles = {};
|
|
770
|
+
const parameterDefinitions = {};
|
|
771
|
+
for (let i = 0; i < parsed.assumptions.length; i++) {
|
|
772
|
+
const profile = parsed.assumptions[i];
|
|
773
|
+
const params = {};
|
|
774
|
+
for (const [key, val] of Object.entries(profile.parameters)) {
|
|
775
|
+
params[key] = String(val);
|
|
776
|
+
if (!parameterDefinitions[key]) {
|
|
777
|
+
parameterDefinitions[key] = {
|
|
778
|
+
type: typeof val === "boolean" ? "boolean" : typeof val === "number" ? "number" : "enum",
|
|
779
|
+
label: key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
780
|
+
description: `Parameter: ${key}`
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
profiles[profile.id] = {
|
|
785
|
+
name: profile.name,
|
|
786
|
+
description: profile.description,
|
|
787
|
+
is_default_baseline: i === 0 || profile.id === defaultProfile,
|
|
788
|
+
is_default_alternative: i === 1 || profile.id === altProfile,
|
|
789
|
+
parameters: params
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
const assumptions = { profiles, parameter_definitions: parameterDefinitions };
|
|
793
|
+
const variables = {};
|
|
794
|
+
for (const v of parsed.stateVariables) {
|
|
795
|
+
const stateVar = {
|
|
796
|
+
type: v.type,
|
|
797
|
+
default: v.default,
|
|
798
|
+
mutable: true,
|
|
799
|
+
label: v.label,
|
|
800
|
+
description: v.description
|
|
801
|
+
};
|
|
802
|
+
if (v.type === "number") {
|
|
803
|
+
if (v.min !== void 0) stateVar.min = v.min;
|
|
804
|
+
if (v.max !== void 0) stateVar.max = v.max;
|
|
805
|
+
if (v.step !== void 0) stateVar.step = v.step;
|
|
806
|
+
}
|
|
807
|
+
if (v.type === "enum" && v.options) {
|
|
808
|
+
stateVar.options = v.options;
|
|
809
|
+
}
|
|
810
|
+
variables[v.id] = stateVar;
|
|
811
|
+
}
|
|
812
|
+
const stateSchema = { variables, presets: {} };
|
|
813
|
+
const rules = parsed.rules.map((r) => {
|
|
814
|
+
const triggers = r.triggers.map((t) => ({
|
|
815
|
+
field: t.field,
|
|
816
|
+
operator: t.operator,
|
|
817
|
+
value: t.value,
|
|
818
|
+
source: t.source
|
|
819
|
+
}));
|
|
820
|
+
const effects = r.effects.map((e) => ({
|
|
821
|
+
target: e.target,
|
|
822
|
+
operation: e.operation,
|
|
823
|
+
value: e.value
|
|
824
|
+
}));
|
|
825
|
+
let collapse_check;
|
|
826
|
+
if (r.collapse_check) {
|
|
827
|
+
collapse_check = {
|
|
828
|
+
field: r.collapse_check.field,
|
|
829
|
+
operator: r.collapse_check.operator,
|
|
830
|
+
value: r.collapse_check.value,
|
|
831
|
+
result: "MODEL_COLLAPSES"
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
const causal_translation = r.causal_translation ?? {
|
|
835
|
+
trigger_text: "",
|
|
836
|
+
rule_text: "",
|
|
837
|
+
shift_text: "",
|
|
838
|
+
effect_text: ""
|
|
839
|
+
};
|
|
840
|
+
const rule = {
|
|
841
|
+
id: r.id,
|
|
842
|
+
severity: r.severity,
|
|
843
|
+
label: r.label,
|
|
844
|
+
description: r.description ?? r.label,
|
|
845
|
+
order: r.order,
|
|
846
|
+
triggers,
|
|
847
|
+
effects: effects.length > 0 ? effects : void 0,
|
|
848
|
+
collapse_check,
|
|
849
|
+
causal_translation
|
|
850
|
+
};
|
|
851
|
+
return rule;
|
|
852
|
+
});
|
|
853
|
+
const viabilityClassification = parsed.gates.map((g) => {
|
|
854
|
+
const defaults = GATE_DEFAULTS[g.status] ?? { color: "#5c5a52", icon: "\u25CF" };
|
|
855
|
+
return {
|
|
856
|
+
status: g.status,
|
|
857
|
+
field: g.field,
|
|
858
|
+
operator: g.operator,
|
|
859
|
+
value: g.value,
|
|
860
|
+
color: defaults.color,
|
|
861
|
+
icon: defaults.icon
|
|
862
|
+
};
|
|
863
|
+
});
|
|
864
|
+
const gates = {
|
|
865
|
+
viability_classification: viabilityClassification,
|
|
866
|
+
structural_override: {
|
|
867
|
+
description: "Rules with severity=structural and triggered collapse_check force MODEL_COLLAPSES regardless of final margin.",
|
|
868
|
+
enforcement: "mandatory"
|
|
869
|
+
},
|
|
870
|
+
sustainability_threshold: 0.1,
|
|
871
|
+
collapse_visual: {
|
|
872
|
+
background: "#1c1917",
|
|
873
|
+
text: "#fef2f2",
|
|
874
|
+
border: "#b91c1c",
|
|
875
|
+
label: "Structural Failure"
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
const computedOutcomes = parsed.outcomes.map((o) => {
|
|
879
|
+
const outcome = {
|
|
880
|
+
id: o.id,
|
|
881
|
+
type: o.type,
|
|
882
|
+
label: o.label,
|
|
883
|
+
show_in_comparison: true
|
|
884
|
+
};
|
|
885
|
+
if (o.range) outcome.range = o.range;
|
|
886
|
+
if (o.display) outcome.display_as = o.display;
|
|
887
|
+
if (o.primary) outcome.primary = o.primary;
|
|
888
|
+
if (o.assignment) outcome.assignment = o.assignment;
|
|
889
|
+
return outcome;
|
|
890
|
+
});
|
|
891
|
+
const outcomes = {
|
|
892
|
+
computed_outcomes: computedOutcomes,
|
|
893
|
+
comparison_layout: {
|
|
894
|
+
primary_card: computedOutcomes.find((o) => o.primary)?.id ?? computedOutcomes[0]?.id ?? "",
|
|
895
|
+
status_badge: "viability_status",
|
|
896
|
+
structural_indicators: rules.filter((r) => r.severity === "structural").map((r) => r.id)
|
|
897
|
+
}
|
|
898
|
+
};
|
|
899
|
+
const metadata = {
|
|
900
|
+
format_version: "1.0.0",
|
|
901
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
902
|
+
last_modified: (/* @__PURE__ */ new Date()).toISOString(),
|
|
903
|
+
authoring_method: "manual-authoring"
|
|
904
|
+
};
|
|
905
|
+
const worldDefinition = {
|
|
906
|
+
world,
|
|
907
|
+
invariants,
|
|
908
|
+
assumptions,
|
|
909
|
+
stateSchema,
|
|
910
|
+
rules,
|
|
911
|
+
gates,
|
|
912
|
+
outcomes,
|
|
913
|
+
metadata
|
|
914
|
+
};
|
|
915
|
+
return { world: worldDefinition, issues };
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
// src/browser.ts
|
|
919
|
+
function parseAndEmitWorld(markdown) {
|
|
920
|
+
const parseResult = parseWorldMarkdown(markdown);
|
|
921
|
+
if (!parseResult.world) {
|
|
922
|
+
throw new Error("Failed to parse world markdown");
|
|
923
|
+
}
|
|
924
|
+
const { world, issues } = emitWorldDefinition(parseResult.world);
|
|
925
|
+
for (const issue of issues) {
|
|
926
|
+
if (issue.severity === "error") {
|
|
927
|
+
console.warn(`[NeuroVerse] Parse issue: ${issue.message}`);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
return world;
|
|
931
|
+
}
|
|
932
|
+
var NeuroVerse = {
|
|
933
|
+
simulateWorld,
|
|
934
|
+
parseWorldMarkdown: parseAndEmitWorld,
|
|
935
|
+
// Also expose raw pipeline for advanced use
|
|
936
|
+
_parseWorldMarkdownRaw: parseWorldMarkdown,
|
|
937
|
+
_emitWorldDefinition: emitWorldDefinition
|
|
938
|
+
};
|
|
939
|
+
globalThis.NeuroVerse = NeuroVerse;
|
|
940
|
+
return __toCommonJS(browser_exports);
|
|
941
|
+
})();
|