@neuroverseos/governance 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +8 -0
- package/README.md +119 -1
- package/dist/{chunk-ETDIEVAX.js → chunk-3ZWU7C43.js} +331 -45
- package/dist/{chunk-F2LWMOM5.js → chunk-TCGGED4G.js} +14 -14
- package/dist/cli/neuroverse.cjs +591 -205
- package/dist/cli/radiant.cjs +440 -103
- package/dist/cli/radiant.js +62 -24
- package/dist/cli/worldmodel.cjs +1055 -1000
- package/dist/cli/worldmodel.js +40 -0
- package/dist/{lenses-YDMKSXDL.js → lenses-XDWK6ZKI.js} +1 -1
- package/dist/radiant/index.cjs +352 -53
- package/dist/radiant/index.d.cts +145 -10
- package/dist/radiant/index.d.ts +145 -10
- package/dist/radiant/index.js +20 -2
- package/dist/{server-ZSQ6DRSN.js → server-JKUBUK5H.js} +2 -2
- package/examples/radiant-weekly-workflow.yml +81 -0
- package/package.json +2 -1
package/dist/cli/worldmodel.cjs
CHANGED
|
@@ -20,1086 +20,1101 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
20
|
};
|
|
21
21
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
22
|
|
|
23
|
-
// src/
|
|
24
|
-
var
|
|
25
|
-
__export(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
// src/engine/worldmodel-compiler.ts
|
|
24
|
+
var worldmodel_compiler_exports = {};
|
|
25
|
+
__export(worldmodel_compiler_exports, {
|
|
26
|
+
compileWorldModel: () => compileWorldModel,
|
|
27
|
+
emitContextsConfig: () => emitContextsConfig,
|
|
28
|
+
emitLensSuggestions: () => emitLensSuggestions,
|
|
29
|
+
emitOverlapMap: () => emitOverlapMap,
|
|
30
|
+
emitSignalSchema: () => emitSignalSchema,
|
|
31
|
+
emitWorldMarkdown: () => emitWorldMarkdown
|
|
29
32
|
});
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
input: process.stdin,
|
|
33
|
-
output: process.stderr
|
|
34
|
-
// questions to stderr so stdout stays clean
|
|
35
|
-
});
|
|
36
|
-
const answers = {};
|
|
37
|
-
process.stderr.write("\n");
|
|
38
|
-
process.stderr.write(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n");
|
|
39
|
-
process.stderr.write(" \u2551 NeuroVerseOS \u2014 Build your thinking constitution \u2551\n");
|
|
40
|
-
process.stderr.write(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
|
|
41
|
-
process.stderr.write("\n");
|
|
42
|
-
process.stderr.write(" Answer these questions in your own words.\n");
|
|
43
|
-
process.stderr.write(" There are no wrong answers \u2014 just say what you mean.\n");
|
|
44
|
-
process.stderr.write(" The AI will structure your answers into a worldmodel.\n\n");
|
|
45
|
-
for (const q of QUESTIONS) {
|
|
46
|
-
const answer = await new Promise((resolve3) => {
|
|
47
|
-
process.stderr.write(` \x1B[1m${q.question}\x1B[0m
|
|
48
|
-
`);
|
|
49
|
-
process.stderr.write(` \x1B[2m${q.placeholder}\x1B[0m
|
|
50
|
-
`);
|
|
51
|
-
rl.question(" > ", (ans) => {
|
|
52
|
-
process.stderr.write("\n");
|
|
53
|
-
resolve3(ans.trim());
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
answers[q.id] = answer;
|
|
57
|
-
}
|
|
58
|
-
rl.close();
|
|
59
|
-
return answers;
|
|
60
|
-
}
|
|
61
|
-
async function structureWorldmodel(answers, apiKey) {
|
|
62
|
-
const prompt = buildStructuringPrompt(answers);
|
|
63
|
-
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
64
|
-
method: "POST",
|
|
65
|
-
headers: {
|
|
66
|
-
"x-api-key": apiKey,
|
|
67
|
-
"anthropic-version": "2023-06-01",
|
|
68
|
-
"content-type": "application/json"
|
|
69
|
-
},
|
|
70
|
-
body: JSON.stringify({
|
|
71
|
-
model: "claude-sonnet-4-20250514",
|
|
72
|
-
max_tokens: 4096,
|
|
73
|
-
system: "You are a behavioral model architect. You take conversational answers about an organization's values, purpose, and priorities, and structure them into a precise .worldmodel.md file that follows the NeuroVerseOS three-layer format. Output ONLY the markdown file content, nothing else.",
|
|
74
|
-
messages: [{ role: "user", content: prompt }]
|
|
75
|
-
})
|
|
76
|
-
});
|
|
77
|
-
if (!res.ok) {
|
|
78
|
-
throw new Error(`AI structuring failed: ${res.status}`);
|
|
79
|
-
}
|
|
80
|
-
const data = await res.json();
|
|
81
|
-
const text = data.content?.filter((c) => c.type === "text").map((c) => c.text ?? "").join("");
|
|
82
|
-
if (!text) throw new Error("AI returned no content");
|
|
83
|
-
return text.replace(/^```markdown\n?/, "").replace(/\n?```$/, "").trim();
|
|
33
|
+
function toSnakeCase(text) {
|
|
34
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
|
|
84
35
|
}
|
|
85
|
-
function
|
|
86
|
-
return
|
|
87
|
-
|
|
88
|
-
The file MUST follow this exact three-layer format:
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
name: ${answers.name}
|
|
92
|
-
version: 1.0.0
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
# Core Model Geometry
|
|
96
|
-
|
|
97
|
-
## Mission
|
|
98
|
-
(from the mission answer)
|
|
99
|
-
|
|
100
|
-
## Domains
|
|
101
|
-
(2-4 domains from the domains answer, each with:)
|
|
102
|
-
### Domain Name
|
|
103
|
-
#### Skills (8-10 skills per domain, inferred from the answers)
|
|
104
|
-
#### Values (3-4 values per domain, drawn from the non-negotiables + mission)
|
|
105
|
-
|
|
106
|
-
## Overlap Effects
|
|
107
|
-
(from the overlaps answer, formatted as: Domain A + Domain B = Emergent State)
|
|
108
|
-
|
|
109
|
-
## Center Identity
|
|
110
|
-
(from the center answer)
|
|
111
|
-
|
|
112
|
-
# Contextual Modifiers
|
|
113
|
-
|
|
114
|
-
## Authority Layers
|
|
115
|
-
(infer 4-5 authority levels appropriate to this organization)
|
|
116
|
-
|
|
117
|
-
## Spatial Contexts
|
|
118
|
-
(infer 4-5 contexts where behavior happens)
|
|
119
|
-
|
|
120
|
-
## Interpretation Rules
|
|
121
|
-
(infer 3-5 rules about how context changes meaning)
|
|
122
|
-
|
|
123
|
-
# Evolution Layer
|
|
124
|
-
|
|
125
|
-
## Aligned Behaviors
|
|
126
|
-
(from the success answer, expanded to 5-8 items)
|
|
127
|
-
|
|
128
|
-
## Drift Behaviors
|
|
129
|
-
(from the drift answer, expanded to 5-8 items)
|
|
130
|
-
|
|
131
|
-
## Signals
|
|
132
|
-
(infer 5-7 observable signals from the answers, snake_case)
|
|
133
|
-
|
|
134
|
-
## Decision Priorities
|
|
135
|
-
(from the priorities answer, formatted as: preferred > secondary)
|
|
136
|
-
|
|
137
|
-
## Evolution Conditions
|
|
138
|
-
(infer 3-5 conditions for when the model should adapt)
|
|
139
|
-
|
|
140
|
-
HERE ARE THE ANSWERS:
|
|
141
|
-
|
|
142
|
-
Name: ${answers.name}
|
|
143
|
-
|
|
144
|
-
Mission: ${answers.mission}
|
|
145
|
-
|
|
146
|
-
Domains: ${answers.domains}
|
|
147
|
-
|
|
148
|
-
Overlaps: ${answers.overlaps}
|
|
149
|
-
|
|
150
|
-
Center identity: ${answers.center}
|
|
151
|
-
|
|
152
|
-
Non-negotiables: ${answers.nonnegotiables}
|
|
153
|
-
|
|
154
|
-
Success looks like: ${answers.success}
|
|
155
|
-
|
|
156
|
-
Drift looks like: ${answers.drift}
|
|
157
|
-
|
|
158
|
-
Priorities: ${answers.priorities}
|
|
159
|
-
|
|
160
|
-
Output ONLY the .worldmodel.md content. No explanation. No commentary. Just the file.`;
|
|
36
|
+
function toKebabCase2(text) {
|
|
37
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
161
38
|
}
|
|
162
|
-
function
|
|
163
|
-
|
|
164
|
-
(0, import_fs.writeFileSync)(resolved, content, "utf-8");
|
|
165
|
-
return resolved;
|
|
39
|
+
function titleCase(text) {
|
|
40
|
+
return text.split(/[\s_-]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
|
|
166
41
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
import_path = require("path");
|
|
174
|
-
QUESTIONS = [
|
|
175
|
-
{
|
|
176
|
-
id: "name",
|
|
177
|
-
question: "What should we call this model? (Your name, your org, your project)",
|
|
178
|
-
placeholder: 'e.g., "Kirsten", "Auki", "My Startup"'
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
id: "mission",
|
|
182
|
-
question: "In one or two sentences \u2014 what does this system exist to do? Not a slogan. The real purpose.",
|
|
183
|
-
placeholder: 'e.g., "Protect human thinking while expanding cognitive capability through AI"'
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
id: "domains",
|
|
187
|
-
question: "What are the 2-3 big areas of focus? Not departments \u2014 the major kinds of work that matter most. Separate with commas.",
|
|
188
|
-
placeholder: 'e.g., "Safety and boundaries, Individual authority, AI as cognitive extension"'
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
id: "overlaps",
|
|
192
|
-
question: "When those areas work well TOGETHER, what does that feel like? Name a feeling for each pair.",
|
|
193
|
-
placeholder: 'e.g., "Safety + Authority = Trust, Authority + AI = Possibility"'
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
id: "center",
|
|
197
|
-
question: "When EVERYTHING is aligned \u2014 all areas working together \u2014 what does the system become? One name or phrase.",
|
|
198
|
-
placeholder: 'e.g., "The Sovereign Conduit", "Collective Vanguard Leader"'
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
id: "nonnegotiables",
|
|
202
|
-
question: "What's absolutely non-negotiable? What would you walk away over? List a few.",
|
|
203
|
-
placeholder: 'e.g., "Humans retain authority over thinking. AI extends, never replaces. People can always leave."'
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
id: "success",
|
|
207
|
-
question: `What does success look like in action? What would you point at and say "that's what I mean"?`,
|
|
208
|
-
placeholder: 'e.g., "Someone maintaining clear authorship of decisions even when AI contributed"'
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
id: "drift",
|
|
212
|
-
question: "What does drift look like? What would worry you if you saw it happening?",
|
|
213
|
-
placeholder: 'e.g., "Decision ownership quietly shifting to AI without explicit delegation"'
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
id: "priorities",
|
|
217
|
-
question: 'When tradeoffs appear, what wins? Give a few "X over Y" pairs.',
|
|
218
|
-
placeholder: 'e.g., "Safety over speed, sovereignty over convenience, diversity over uniformity"'
|
|
219
|
-
}
|
|
220
|
-
];
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
// src/cli/worldmodel.ts
|
|
225
|
-
var worldmodel_exports = {};
|
|
226
|
-
__export(worldmodel_exports, {
|
|
227
|
-
main: () => main
|
|
228
|
-
});
|
|
229
|
-
module.exports = __toCommonJS(worldmodel_exports);
|
|
230
|
-
var import_promises = require("fs/promises");
|
|
231
|
-
var import_fs2 = require("fs");
|
|
232
|
-
var import_path2 = require("path");
|
|
233
|
-
|
|
234
|
-
// src/engine/worldmodel-parser.ts
|
|
235
|
-
function splitSections(markdown) {
|
|
236
|
-
const lines = markdown.split("\n");
|
|
237
|
-
let frontmatter = "";
|
|
238
|
-
let bodyStart = 0;
|
|
239
|
-
if (lines[0]?.trim() === "---") {
|
|
240
|
-
const endIdx = lines.indexOf("---", 1);
|
|
241
|
-
if (endIdx > 0) {
|
|
242
|
-
frontmatter = lines.slice(1, endIdx).join("\n");
|
|
243
|
-
bodyStart = endIdx + 1;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
const sections = [];
|
|
247
|
-
let currentSection = null;
|
|
248
|
-
const contentLines = [];
|
|
249
|
-
for (let i = bodyStart; i < lines.length; i++) {
|
|
250
|
-
const line = lines[i];
|
|
251
|
-
if (line.startsWith("# ")) {
|
|
252
|
-
if (currentSection) {
|
|
253
|
-
currentSection.content = contentLines.join("\n").trim();
|
|
254
|
-
sections.push(currentSection);
|
|
255
|
-
contentLines.length = 0;
|
|
256
|
-
}
|
|
257
|
-
currentSection = {
|
|
258
|
-
name: line.replace(/^#\s+/, "").trim(),
|
|
259
|
-
content: "",
|
|
260
|
-
startLine: i + 1
|
|
261
|
-
// 1-based
|
|
262
|
-
};
|
|
263
|
-
} else if (currentSection) {
|
|
264
|
-
contentLines.push(line);
|
|
42
|
+
function matchSignal(behaviorText, signals) {
|
|
43
|
+
const lowerText = behaviorText.toLowerCase();
|
|
44
|
+
for (const signal of signals) {
|
|
45
|
+
const signalWords = signal.toLowerCase().split("_");
|
|
46
|
+
if (signalWords.some((w) => w.length > 3 && lowerText.includes(w))) {
|
|
47
|
+
return signal;
|
|
265
48
|
}
|
|
266
49
|
}
|
|
267
|
-
|
|
268
|
-
currentSection.content = contentLines.join("\n").trim();
|
|
269
|
-
sections.push(currentSection);
|
|
270
|
-
}
|
|
271
|
-
return { frontmatter, sections };
|
|
50
|
+
return "alignment_score";
|
|
272
51
|
}
|
|
273
|
-
function
|
|
274
|
-
const lines =
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
52
|
+
function emitWorldMarkdown(model) {
|
|
53
|
+
const lines = [];
|
|
54
|
+
const worldId = model.frontmatter.model_id;
|
|
55
|
+
const worldName = model.frontmatter.name;
|
|
56
|
+
const version = model.frontmatter.version;
|
|
57
|
+
lines.push("---");
|
|
58
|
+
lines.push(`world_id: ${worldId}`);
|
|
59
|
+
lines.push(`name: ${worldName}`);
|
|
60
|
+
lines.push(`version: ${version}`);
|
|
61
|
+
lines.push("runtime_mode: COMPLIANCE");
|
|
62
|
+
lines.push("default_profile: aligned");
|
|
63
|
+
lines.push("alternative_profile: drifting");
|
|
64
|
+
lines.push("---");
|
|
65
|
+
lines.push("");
|
|
66
|
+
lines.push("# Thesis");
|
|
67
|
+
lines.push("");
|
|
68
|
+
lines.push(model.geometry.mission);
|
|
69
|
+
if (model.geometry.centerIdentity) {
|
|
70
|
+
lines.push(
|
|
71
|
+
`When all domains are aligned, the system operates as: ${model.geometry.centerIdentity}.`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
lines.push("");
|
|
75
|
+
lines.push("# Invariants");
|
|
76
|
+
lines.push("");
|
|
77
|
+
let invariantIdx = 0;
|
|
78
|
+
for (const domain of model.geometry.domains) {
|
|
79
|
+
for (const value of domain.values) {
|
|
80
|
+
invariantIdx++;
|
|
81
|
+
const invId = `${toSnakeCase(domain.name)}_value_${String(invariantIdx).padStart(2, "0")}`;
|
|
82
|
+
lines.push(
|
|
83
|
+
`- \`${invId}\` \u2014 ${value} [${domain.name}] (structural, immutable)`
|
|
84
|
+
);
|
|
293
85
|
}
|
|
294
86
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
87
|
+
lines.push("");
|
|
88
|
+
lines.push("# State");
|
|
89
|
+
lines.push("");
|
|
90
|
+
lines.push("## alignment_score");
|
|
91
|
+
lines.push("- type: number");
|
|
92
|
+
lines.push("- min: 0");
|
|
93
|
+
lines.push("- max: 100");
|
|
94
|
+
lines.push("- step: 5");
|
|
95
|
+
lines.push("- default: 70");
|
|
96
|
+
lines.push("- label: Alignment Score");
|
|
97
|
+
lines.push(
|
|
98
|
+
"- description: Composite behavioral alignment metric derived from all signals"
|
|
99
|
+
);
|
|
100
|
+
lines.push("");
|
|
101
|
+
for (const signal of model.evolution.signals) {
|
|
102
|
+
const signalId = toSnakeCase(signal);
|
|
103
|
+
const signalLabel = titleCase(signal);
|
|
104
|
+
lines.push(`## ${signalId}`);
|
|
105
|
+
lines.push("- type: number");
|
|
106
|
+
lines.push("- min: 0");
|
|
107
|
+
lines.push("- max: 100");
|
|
108
|
+
lines.push("- step: 5");
|
|
109
|
+
lines.push("- default: 70");
|
|
110
|
+
lines.push(`- label: ${signalLabel}`);
|
|
111
|
+
lines.push(`- description: Behavioral signal measuring ${signal.replace(/_/g, " ")}`);
|
|
112
|
+
lines.push("");
|
|
298
113
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
|
|
114
|
+
lines.push("# Assumptions");
|
|
115
|
+
lines.push("");
|
|
116
|
+
lines.push("## aligned");
|
|
117
|
+
lines.push("- name: Aligned");
|
|
118
|
+
lines.push("- description: All behavioral signals at healthy levels");
|
|
119
|
+
lines.push("- pressure_level: low");
|
|
120
|
+
lines.push("");
|
|
121
|
+
lines.push("## drifting");
|
|
122
|
+
lines.push("- name: Drifting");
|
|
123
|
+
lines.push("- description: Behavioral signals under pressure with drift risk");
|
|
124
|
+
lines.push("- pressure_level: high");
|
|
125
|
+
lines.push("");
|
|
126
|
+
lines.push("# Rules");
|
|
127
|
+
lines.push("");
|
|
128
|
+
let ruleIdx = 0;
|
|
129
|
+
for (const drift of model.evolution.driftBehaviors) {
|
|
130
|
+
ruleIdx++;
|
|
131
|
+
const ruleId = `rule-${String(ruleIdx).padStart(3, "0")}`;
|
|
132
|
+
const matchedSignal = matchSignal(drift, model.evolution.signals);
|
|
133
|
+
const signalId = toSnakeCase(matchedSignal);
|
|
134
|
+
lines.push(`## ${ruleId}: ${drift} (degradation)`);
|
|
135
|
+
lines.push(`Drift behavior detected: ${drift}`);
|
|
136
|
+
lines.push("");
|
|
137
|
+
lines.push(`When ${signalId} < 50 [state]`);
|
|
138
|
+
lines.push("Then alignment_score *= 0.80");
|
|
139
|
+
lines.push("");
|
|
140
|
+
lines.push(`> trigger: ${signalId} drops below threshold`);
|
|
141
|
+
lines.push(`> rule: Drift behavior weakens alignment`);
|
|
142
|
+
lines.push(`> shift: Behavioral alignment decreases`);
|
|
143
|
+
lines.push(`> effect: Alignment score reduced by 20%`);
|
|
144
|
+
lines.push("");
|
|
322
145
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
146
|
+
for (const aligned of model.evolution.alignedBehaviors) {
|
|
147
|
+
ruleIdx++;
|
|
148
|
+
const ruleId = `rule-${String(ruleIdx).padStart(3, "0")}`;
|
|
149
|
+
const matchedSignal = matchSignal(aligned, model.evolution.signals);
|
|
150
|
+
const signalId = toSnakeCase(matchedSignal);
|
|
151
|
+
lines.push(`## ${ruleId}: ${aligned} (advantage)`);
|
|
152
|
+
lines.push(`Aligned behavior reinforced: ${aligned}`);
|
|
153
|
+
lines.push("");
|
|
154
|
+
lines.push(`When ${signalId} >= 70 [state]`);
|
|
155
|
+
lines.push("Then alignment_score *= 1.10");
|
|
156
|
+
lines.push("");
|
|
157
|
+
lines.push(`> trigger: ${signalId} above healthy threshold`);
|
|
158
|
+
lines.push(`> rule: Aligned behavior strengthens system`);
|
|
159
|
+
lines.push(`> shift: Behavioral alignment increases`);
|
|
160
|
+
lines.push(`> effect: Alignment score boosted by 10%`);
|
|
161
|
+
lines.push("");
|
|
326
162
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
163
|
+
for (let i = 0; i < model.evolution.decisionPriorities.length; i++) {
|
|
164
|
+
ruleIdx++;
|
|
165
|
+
const priority = model.evolution.decisionPriorities[i];
|
|
166
|
+
const ruleId = `rule-${String(ruleIdx).padStart(3, "0")}`;
|
|
167
|
+
lines.push(
|
|
168
|
+
`## ${ruleId}: ${priority.preferred} over ${priority.over} (structural)`
|
|
169
|
+
);
|
|
170
|
+
lines.push(
|
|
171
|
+
`Priority: ${priority.preferred} takes precedence over ${priority.over} in tradeoff situations.`
|
|
172
|
+
);
|
|
173
|
+
lines.push("");
|
|
174
|
+
lines.push("When alignment_score < 40 [state]");
|
|
175
|
+
lines.push("Then alignment_score *= 0.70");
|
|
176
|
+
lines.push("Collapse: alignment_score < 10");
|
|
177
|
+
lines.push("");
|
|
178
|
+
lines.push(`> trigger: Alignment score critically low`);
|
|
179
|
+
lines.push(
|
|
180
|
+
`> rule: Priority violation \u2014 ${priority.preferred} must outweigh ${priority.over}`
|
|
181
|
+
);
|
|
182
|
+
lines.push(`> shift: System enters structural enforcement`);
|
|
183
|
+
lines.push(`> effect: Alignment sharply reduced; collapse if critical`);
|
|
184
|
+
lines.push("");
|
|
185
|
+
}
|
|
186
|
+
lines.push("# Gates");
|
|
187
|
+
lines.push("");
|
|
188
|
+
lines.push("- STRONG: alignment_score >= 85");
|
|
189
|
+
lines.push("- STABLE: alignment_score >= 65");
|
|
190
|
+
lines.push("- WATCHING: alignment_score >= 45");
|
|
191
|
+
lines.push("- FRAGILE: alignment_score > 30");
|
|
192
|
+
lines.push("- MISALIGNED: alignment_score <= 30");
|
|
193
|
+
lines.push("");
|
|
194
|
+
lines.push("# Outcomes");
|
|
195
|
+
lines.push("");
|
|
196
|
+
lines.push("## alignment_score");
|
|
197
|
+
lines.push("- type: number");
|
|
198
|
+
lines.push("- range: 0-100");
|
|
199
|
+
lines.push("- display: percentage");
|
|
200
|
+
lines.push("- label: Alignment Score");
|
|
201
|
+
lines.push("- primary: true");
|
|
202
|
+
lines.push("");
|
|
203
|
+
for (const signal of model.evolution.signals) {
|
|
204
|
+
const signalId = toSnakeCase(signal);
|
|
205
|
+
const signalLabel = titleCase(signal);
|
|
206
|
+
lines.push(`## ${signalId}`);
|
|
207
|
+
lines.push("- type: number");
|
|
208
|
+
lines.push("- range: 0-100");
|
|
209
|
+
lines.push("- display: percentage");
|
|
210
|
+
lines.push(`- label: ${signalLabel}`);
|
|
211
|
+
lines.push("");
|
|
212
|
+
}
|
|
213
|
+
const lensSuggestions = buildLensSuggestions(model);
|
|
214
|
+
if (lensSuggestions.length > 0) {
|
|
215
|
+
lines.push("# Lenses");
|
|
216
|
+
lines.push("- policy: role_default");
|
|
217
|
+
lines.push("");
|
|
218
|
+
for (const lens of lensSuggestions) {
|
|
219
|
+
lines.push(`## ${lens.id}`);
|
|
220
|
+
lines.push(`- tagline: ${lens.tagline}`);
|
|
221
|
+
lines.push(
|
|
222
|
+
`- description: Lens derived from ${lens.derived_from.domainA} and ${lens.derived_from.domainB} interaction, producing ${lens.derived_from.effect}.`
|
|
223
|
+
);
|
|
224
|
+
lines.push(`- formality: ${lens.tone.formality}`);
|
|
225
|
+
lines.push(`- verbosity: ${lens.tone.verbosity}`);
|
|
226
|
+
lines.push(`- emotion: ${lens.tone.emotion}`);
|
|
227
|
+
lines.push(`- confidence: ${lens.tone.confidence}`);
|
|
228
|
+
lines.push("- tags: behavioral, worldmodel, overlap");
|
|
229
|
+
lines.push("- default_for_roles: all");
|
|
230
|
+
lines.push("- priority: 50");
|
|
231
|
+
lines.push("- stackable: true");
|
|
232
|
+
lines.push("");
|
|
233
|
+
for (const directive of lens.directives) {
|
|
234
|
+
lines.push(`> ${directive.scope}: ${directive.instruction}`);
|
|
341
235
|
}
|
|
342
|
-
|
|
343
|
-
name: line.replace(/^####\s+/, "").trim(),
|
|
344
|
-
content: "",
|
|
345
|
-
startLine: baseLine + i
|
|
346
|
-
};
|
|
347
|
-
} else if (currentSection) {
|
|
348
|
-
contentLines.push(line);
|
|
236
|
+
lines.push("");
|
|
349
237
|
}
|
|
350
238
|
}
|
|
351
|
-
|
|
352
|
-
currentSection.content = contentLines.join("\n").trim();
|
|
353
|
-
sections.push(currentSection);
|
|
354
|
-
}
|
|
355
|
-
return sections;
|
|
239
|
+
return lines.join("\n");
|
|
356
240
|
}
|
|
357
|
-
function
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
continue;
|
|
370
|
-
}
|
|
371
|
-
if (trimmed.startsWith("- ")) {
|
|
372
|
-
items.push(trimmed.slice(2).trim());
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
return items;
|
|
241
|
+
function emitSignalSchema(model) {
|
|
242
|
+
const signals = model.evolution.signals.map((signal) => ({
|
|
243
|
+
id: toSnakeCase(signal),
|
|
244
|
+
name: titleCase(signal),
|
|
245
|
+
type: "number",
|
|
246
|
+
default: 70
|
|
247
|
+
}));
|
|
248
|
+
return {
|
|
249
|
+
model_id: model.frontmatter.model_id,
|
|
250
|
+
signals
|
|
251
|
+
};
|
|
376
252
|
}
|
|
377
|
-
function
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
390
|
-
continue;
|
|
391
|
-
}
|
|
392
|
-
if (trimmed && !trimmed.startsWith("#")) {
|
|
393
|
-
textLines.push(trimmed);
|
|
394
|
-
}
|
|
253
|
+
function emitOverlapMap(model) {
|
|
254
|
+
const pairings = model.geometry.overlapEffects.map((o) => ({
|
|
255
|
+
domainA: o.domainA,
|
|
256
|
+
domainB: o.domainB,
|
|
257
|
+
effect: o.effect
|
|
258
|
+
}));
|
|
259
|
+
const matrix = {};
|
|
260
|
+
for (const overlap of model.geometry.overlapEffects) {
|
|
261
|
+
const keyA = toKebabCase2(overlap.domainA);
|
|
262
|
+
const keyB = toKebabCase2(overlap.domainB);
|
|
263
|
+
if (!matrix[keyA]) matrix[keyA] = {};
|
|
264
|
+
matrix[keyA][keyB] = overlap.effect;
|
|
395
265
|
}
|
|
396
|
-
return
|
|
266
|
+
return {
|
|
267
|
+
model_id: model.frontmatter.model_id,
|
|
268
|
+
pairings,
|
|
269
|
+
matrix
|
|
270
|
+
};
|
|
397
271
|
}
|
|
398
|
-
function
|
|
399
|
-
return
|
|
272
|
+
function emitContextsConfig(model) {
|
|
273
|
+
return {
|
|
274
|
+
model_id: model.frontmatter.model_id,
|
|
275
|
+
authority_layers: model.modifiers.authorityLayers,
|
|
276
|
+
spatial_contexts: model.modifiers.spatialContexts,
|
|
277
|
+
interpretation_rules: model.modifiers.interpretationRules
|
|
278
|
+
};
|
|
400
279
|
}
|
|
401
|
-
function
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
const key = trimmed.slice(0, colonIdx).trim();
|
|
409
|
-
const value = trimmed.slice(colonIdx + 1).trim();
|
|
410
|
-
result[key] = value;
|
|
280
|
+
function deriveTone(domainA, domainB) {
|
|
281
|
+
const combined = `${domainA} ${domainB}`.toLowerCase();
|
|
282
|
+
let formality = "neutral";
|
|
283
|
+
if (/strateg|technic|analytic|research|engineer/.test(combined)) {
|
|
284
|
+
formality = "professional";
|
|
285
|
+
} else if (/narrat|story|communi|creative/.test(combined)) {
|
|
286
|
+
formality = "casual";
|
|
411
287
|
}
|
|
412
|
-
|
|
413
|
-
if (
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
288
|
+
let verbosity = "balanced";
|
|
289
|
+
if (/foresight|scenario|plan|design/.test(combined)) {
|
|
290
|
+
verbosity = "detailed";
|
|
291
|
+
} else if (/prosper|negotiat|stakeholder/.test(combined)) {
|
|
292
|
+
verbosity = "concise";
|
|
293
|
+
}
|
|
294
|
+
let emotion = "neutral";
|
|
295
|
+
if (/empath|emoti|care|safe|trust/.test(combined)) {
|
|
296
|
+
emotion = "warm";
|
|
297
|
+
} else if (/analytic|system|data/.test(combined)) {
|
|
298
|
+
emotion = "clinical";
|
|
299
|
+
}
|
|
300
|
+
let confidence = "balanced";
|
|
301
|
+
if (/lead|command|decis|strateg/.test(combined)) {
|
|
302
|
+
confidence = "authoritative";
|
|
303
|
+
} else if (/explor|experiment|creat/.test(combined)) {
|
|
304
|
+
confidence = "exploratory";
|
|
305
|
+
}
|
|
306
|
+
return { formality, verbosity, emotion, confidence };
|
|
307
|
+
}
|
|
308
|
+
function buildLensSuggestions(model) {
|
|
309
|
+
const lenses = [];
|
|
310
|
+
const domainMap = new Map(model.geometry.domains.map((d) => [d.name.toLowerCase(), d]));
|
|
311
|
+
for (const overlap of model.geometry.overlapEffects) {
|
|
312
|
+
const lensId = toKebabCase2(overlap.effect);
|
|
313
|
+
const tone = deriveTone(overlap.domainA, overlap.domainB);
|
|
314
|
+
const domainAData = domainMap.get(overlap.domainA.toLowerCase());
|
|
315
|
+
const domainBData = domainMap.get(overlap.domainB.toLowerCase());
|
|
316
|
+
const directives = [];
|
|
317
|
+
if (domainAData && domainAData.skills.length > 0) {
|
|
318
|
+
directives.push({
|
|
319
|
+
scope: "response_framing",
|
|
320
|
+
instruction: `Approach through the lens of ${domainAData.skills.join(", ").toLowerCase()}.`
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
if (domainBData && domainBData.values.length > 0) {
|
|
324
|
+
directives.push({
|
|
325
|
+
scope: "behavior_shaping",
|
|
326
|
+
instruction: `Maintain ${domainBData.values.join(", ").toLowerCase()} in all responses.`
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
directives.push({
|
|
330
|
+
scope: "value_emphasis",
|
|
331
|
+
instruction: `Emphasize ${overlap.effect.toLowerCase()} as the emergent state of aligned behavior.`
|
|
332
|
+
});
|
|
333
|
+
lenses.push({
|
|
334
|
+
id: lensId,
|
|
335
|
+
name: titleCase(overlap.effect),
|
|
336
|
+
tagline: `${overlap.effect} through ${overlap.domainA} and ${overlap.domainB}.`,
|
|
337
|
+
derived_from: {
|
|
338
|
+
domainA: overlap.domainA,
|
|
339
|
+
domainB: overlap.domainB,
|
|
340
|
+
effect: overlap.effect
|
|
341
|
+
},
|
|
342
|
+
tone,
|
|
343
|
+
directives
|
|
419
344
|
});
|
|
420
345
|
}
|
|
421
|
-
|
|
346
|
+
return lenses;
|
|
347
|
+
}
|
|
348
|
+
function emitLensSuggestions(model) {
|
|
349
|
+
return buildLensSuggestions(model);
|
|
350
|
+
}
|
|
351
|
+
function compileWorldModel(model) {
|
|
422
352
|
return {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
353
|
+
worldMarkdown: emitWorldMarkdown(model),
|
|
354
|
+
signalSchema: emitSignalSchema(model),
|
|
355
|
+
overlapMap: emitOverlapMap(model),
|
|
356
|
+
contextsConfig: emitContextsConfig(model),
|
|
357
|
+
lensSuggestions: emitLensSuggestions(model)
|
|
426
358
|
};
|
|
427
359
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
domains: [],
|
|
432
|
-
overlapEffects: [],
|
|
433
|
-
centerIdentity: ""
|
|
434
|
-
};
|
|
435
|
-
if (!section) {
|
|
436
|
-
issues.push({
|
|
437
|
-
line: 0,
|
|
438
|
-
section: "Core Model Geometry",
|
|
439
|
-
message: "Missing # Core Model Geometry section. Define the structural model: mission, domains with embedded skills and values, overlaps, and center identity.",
|
|
440
|
-
severity: "error"
|
|
441
|
-
});
|
|
442
|
-
return geometry;
|
|
443
|
-
}
|
|
444
|
-
const h2Sections = splitH2Sections(section.content, section.startLine);
|
|
445
|
-
const missionSection = h2Sections.find((s) => s.name.toLowerCase() === "mission");
|
|
446
|
-
if (missionSection) {
|
|
447
|
-
geometry.mission = extractTextContent(missionSection.content);
|
|
360
|
+
var init_worldmodel_compiler = __esm({
|
|
361
|
+
"src/engine/worldmodel-compiler.ts"() {
|
|
362
|
+
"use strict";
|
|
448
363
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// src/cli/worldmodel-create.ts
|
|
367
|
+
var worldmodel_create_exports = {};
|
|
368
|
+
__export(worldmodel_create_exports, {
|
|
369
|
+
askQuestions: () => askQuestions,
|
|
370
|
+
saveWorldmodel: () => saveWorldmodel,
|
|
371
|
+
structureWorldmodel: () => structureWorldmodel
|
|
372
|
+
});
|
|
373
|
+
async function askQuestions() {
|
|
374
|
+
const rl = (0, import_readline.createInterface)({
|
|
375
|
+
input: process.stdin,
|
|
376
|
+
output: process.stderr
|
|
377
|
+
// questions to stderr so stdout stays clean
|
|
378
|
+
});
|
|
379
|
+
const answers = {};
|
|
380
|
+
process.stderr.write("\n");
|
|
381
|
+
process.stderr.write(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n");
|
|
382
|
+
process.stderr.write(" \u2551 NeuroVerseOS \u2014 Build your thinking constitution \u2551\n");
|
|
383
|
+
process.stderr.write(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
|
|
384
|
+
process.stderr.write("\n");
|
|
385
|
+
process.stderr.write(" Answer these questions in your own words.\n");
|
|
386
|
+
process.stderr.write(" There are no wrong answers \u2014 just say what you mean.\n");
|
|
387
|
+
process.stderr.write(" The AI will structure your answers into a worldmodel.\n\n");
|
|
388
|
+
for (const q of QUESTIONS) {
|
|
389
|
+
const answer = await new Promise((resolve3) => {
|
|
390
|
+
process.stderr.write(` \x1B[1m${q.question}\x1B[0m
|
|
391
|
+
`);
|
|
392
|
+
process.stderr.write(` \x1B[2m${q.placeholder}\x1B[0m
|
|
393
|
+
`);
|
|
394
|
+
rl.question(" > ", (ans) => {
|
|
395
|
+
process.stderr.write("\n");
|
|
396
|
+
resolve3(ans.trim());
|
|
397
|
+
});
|
|
455
398
|
});
|
|
399
|
+
answers[q.id] = answer;
|
|
456
400
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
issues.push({
|
|
479
|
-
line: ds.startLine,
|
|
480
|
-
section: "Domains",
|
|
481
|
-
message: `Domain '${ds.name}' has no skills defined. Skills are the capabilities within this domain.`,
|
|
482
|
-
severity: "warning"
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
if (domain.values.length === 0) {
|
|
486
|
-
issues.push({
|
|
487
|
-
line: ds.startLine,
|
|
488
|
-
section: "Domains",
|
|
489
|
-
message: `Domain '${ds.name}' has no values defined. Behavior has no constraints without values.`,
|
|
490
|
-
severity: "warning"
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
geometry.domains.push(domain);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
if (geometry.domains.length < 2) {
|
|
497
|
-
issues.push({
|
|
498
|
-
line: domainsSection?.startLine ?? section.startLine,
|
|
499
|
-
section: "Domains",
|
|
500
|
-
message: "At least 2 domains required. Domains are the major operating modes of the system, each carrying skills and values.",
|
|
501
|
-
severity: "error"
|
|
502
|
-
});
|
|
401
|
+
rl.close();
|
|
402
|
+
return answers;
|
|
403
|
+
}
|
|
404
|
+
async function structureWorldmodel(answers, apiKey) {
|
|
405
|
+
const prompt = buildStructuringPrompt(answers);
|
|
406
|
+
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
407
|
+
method: "POST",
|
|
408
|
+
headers: {
|
|
409
|
+
"x-api-key": apiKey,
|
|
410
|
+
"anthropic-version": "2023-06-01",
|
|
411
|
+
"content-type": "application/json"
|
|
412
|
+
},
|
|
413
|
+
body: JSON.stringify({
|
|
414
|
+
model: "claude-sonnet-4-20250514",
|
|
415
|
+
max_tokens: 4096,
|
|
416
|
+
system: "You are a behavioral model architect. You take conversational answers about an organization's values, purpose, and priorities, and structure them into a precise .worldmodel.md file that follows the NeuroVerseOS three-layer format. Output ONLY the markdown file content, nothing else.",
|
|
417
|
+
messages: [{ role: "user", content: prompt }]
|
|
418
|
+
})
|
|
419
|
+
});
|
|
420
|
+
if (!res.ok) {
|
|
421
|
+
throw new Error(`AI structuring failed: ${res.status}`);
|
|
503
422
|
}
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
);
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
423
|
+
const data = await res.json();
|
|
424
|
+
const text = data.content?.filter((c) => c.type === "text").map((c) => c.text ?? "").join("");
|
|
425
|
+
if (!text) throw new Error("AI returned no content");
|
|
426
|
+
return text.replace(/^```markdown\n?/, "").replace(/\n?```$/, "").trim();
|
|
427
|
+
}
|
|
428
|
+
function buildStructuringPrompt(answers) {
|
|
429
|
+
return `Structure these conversational answers into a .worldmodel.md file.
|
|
430
|
+
|
|
431
|
+
The file MUST follow this exact three-layer format:
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
name: ${answers.name}
|
|
435
|
+
version: 1.0.0
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
# Core Model Geometry
|
|
439
|
+
|
|
440
|
+
## Mission
|
|
441
|
+
(from the mission answer)
|
|
442
|
+
|
|
443
|
+
## Domains
|
|
444
|
+
(2-4 domains from the domains answer, each with:)
|
|
445
|
+
### Domain Name
|
|
446
|
+
#### Skills (8-10 skills per domain, inferred from the answers)
|
|
447
|
+
#### Values (3-4 values per domain, drawn from the non-negotiables + mission)
|
|
448
|
+
|
|
449
|
+
## Overlap Effects
|
|
450
|
+
(from the overlaps answer, formatted as: Domain A + Domain B = Emergent State)
|
|
451
|
+
|
|
452
|
+
## Center Identity
|
|
453
|
+
(from the center answer)
|
|
454
|
+
|
|
455
|
+
# Contextual Modifiers
|
|
456
|
+
|
|
457
|
+
## Authority Layers
|
|
458
|
+
(infer 4-5 authority levels appropriate to this organization)
|
|
459
|
+
|
|
460
|
+
## Spatial Contexts
|
|
461
|
+
(infer 4-5 contexts where behavior happens)
|
|
462
|
+
|
|
463
|
+
## Interpretation Rules
|
|
464
|
+
(infer 3-5 rules about how context changes meaning)
|
|
465
|
+
|
|
466
|
+
# Evolution Layer
|
|
467
|
+
|
|
468
|
+
## Aligned Behaviors
|
|
469
|
+
(from the success answer, expanded to 5-8 items)
|
|
470
|
+
|
|
471
|
+
## Drift Behaviors
|
|
472
|
+
(from the drift answer, expanded to 5-8 items)
|
|
473
|
+
|
|
474
|
+
## Signals
|
|
475
|
+
(infer 5-7 observable signals from the answers, snake_case)
|
|
476
|
+
|
|
477
|
+
## Decision Priorities
|
|
478
|
+
(from the priorities answer, formatted as: preferred > secondary)
|
|
479
|
+
|
|
480
|
+
## Evolution Conditions
|
|
481
|
+
(infer 3-5 conditions for when the model should adapt)
|
|
482
|
+
|
|
483
|
+
HERE ARE THE ANSWERS:
|
|
484
|
+
|
|
485
|
+
Name: ${answers.name}
|
|
486
|
+
|
|
487
|
+
Mission: ${answers.mission}
|
|
488
|
+
|
|
489
|
+
Domains: ${answers.domains}
|
|
490
|
+
|
|
491
|
+
Overlaps: ${answers.overlaps}
|
|
492
|
+
|
|
493
|
+
Center identity: ${answers.center}
|
|
494
|
+
|
|
495
|
+
Non-negotiables: ${answers.nonnegotiables}
|
|
496
|
+
|
|
497
|
+
Success looks like: ${answers.success}
|
|
498
|
+
|
|
499
|
+
Drift looks like: ${answers.drift}
|
|
500
|
+
|
|
501
|
+
Priorities: ${answers.priorities}
|
|
502
|
+
|
|
503
|
+
Output ONLY the .worldmodel.md content. No explanation. No commentary. Just the file.`;
|
|
504
|
+
}
|
|
505
|
+
function saveWorldmodel(content, outputPath) {
|
|
506
|
+
const resolved = (0, import_path.resolve)(outputPath);
|
|
507
|
+
(0, import_fs.writeFileSync)(resolved, content, "utf-8");
|
|
508
|
+
return resolved;
|
|
509
|
+
}
|
|
510
|
+
var import_readline, import_fs, import_path, QUESTIONS;
|
|
511
|
+
var init_worldmodel_create = __esm({
|
|
512
|
+
"src/cli/worldmodel-create.ts"() {
|
|
513
|
+
"use strict";
|
|
514
|
+
import_readline = require("readline");
|
|
515
|
+
import_fs = require("fs");
|
|
516
|
+
import_path = require("path");
|
|
517
|
+
QUESTIONS = [
|
|
518
|
+
{
|
|
519
|
+
id: "name",
|
|
520
|
+
question: "What should we call this model? (Your name, your org, your project)",
|
|
521
|
+
placeholder: 'e.g., "Kirsten", "Auki", "My Startup"'
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
id: "mission",
|
|
525
|
+
question: "In one or two sentences \u2014 what does this system exist to do? Not a slogan. The real purpose.",
|
|
526
|
+
placeholder: 'e.g., "Protect human thinking while expanding cognitive capability through AI"'
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
id: "domains",
|
|
530
|
+
question: "What are the 2-3 big areas of focus? Not departments \u2014 the major kinds of work that matter most. Separate with commas.",
|
|
531
|
+
placeholder: 'e.g., "Safety and boundaries, Individual authority, AI as cognitive extension"'
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
id: "overlaps",
|
|
535
|
+
question: "When those areas work well TOGETHER, what does that feel like? Name a feeling for each pair.",
|
|
536
|
+
placeholder: 'e.g., "Safety + Authority = Trust, Authority + AI = Possibility"'
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
id: "center",
|
|
540
|
+
question: "When EVERYTHING is aligned \u2014 all areas working together \u2014 what does the system become? One name or phrase.",
|
|
541
|
+
placeholder: 'e.g., "The Sovereign Conduit", "Collective Vanguard Leader"'
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
id: "nonnegotiables",
|
|
545
|
+
question: "What's absolutely non-negotiable? What would you walk away over? List a few.",
|
|
546
|
+
placeholder: 'e.g., "Humans retain authority over thinking. AI extends, never replaces. People can always leave."'
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
id: "success",
|
|
550
|
+
question: `What does success look like in action? What would you point at and say "that's what I mean"?`,
|
|
551
|
+
placeholder: 'e.g., "Someone maintaining clear authorship of decisions even when AI contributed"'
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
id: "drift",
|
|
555
|
+
question: "What does drift look like? What would worry you if you saw it happening?",
|
|
556
|
+
placeholder: 'e.g., "Decision ownership quietly shifting to AI without explicit delegation"'
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
id: "priorities",
|
|
560
|
+
question: 'When tradeoffs appear, what wins? Give a few "X over Y" pairs.',
|
|
561
|
+
placeholder: 'e.g., "Safety over speed, sovereignty over convenience, diversity over uniformity"'
|
|
546
562
|
}
|
|
547
|
-
|
|
563
|
+
];
|
|
548
564
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
// src/cli/worldmodel.ts
|
|
568
|
+
var worldmodel_exports = {};
|
|
569
|
+
__export(worldmodel_exports, {
|
|
570
|
+
main: () => main
|
|
571
|
+
});
|
|
572
|
+
module.exports = __toCommonJS(worldmodel_exports);
|
|
573
|
+
var import_promises = require("fs/promises");
|
|
574
|
+
var import_fs2 = require("fs");
|
|
575
|
+
var import_path2 = require("path");
|
|
576
|
+
|
|
577
|
+
// src/engine/worldmodel-parser.ts
|
|
578
|
+
function splitSections(markdown) {
|
|
579
|
+
const lines = markdown.split("\n");
|
|
580
|
+
let frontmatter = "";
|
|
581
|
+
let bodyStart = 0;
|
|
582
|
+
if (lines[0]?.trim() === "---") {
|
|
583
|
+
const endIdx = lines.indexOf("---", 1);
|
|
584
|
+
if (endIdx > 0) {
|
|
585
|
+
frontmatter = lines.slice(1, endIdx).join("\n");
|
|
586
|
+
bodyStart = endIdx + 1;
|
|
587
|
+
}
|
|
556
588
|
}
|
|
557
|
-
const
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
589
|
+
const sections = [];
|
|
590
|
+
let currentSection = null;
|
|
591
|
+
const contentLines = [];
|
|
592
|
+
for (let i = bodyStart; i < lines.length; i++) {
|
|
593
|
+
const line = lines[i];
|
|
594
|
+
if (line.startsWith("# ")) {
|
|
595
|
+
if (currentSection) {
|
|
596
|
+
currentSection.content = contentLines.join("\n").trim();
|
|
597
|
+
sections.push(currentSection);
|
|
598
|
+
contentLines.length = 0;
|
|
599
|
+
}
|
|
600
|
+
currentSection = {
|
|
601
|
+
name: line.replace(/^#\s+/, "").trim(),
|
|
602
|
+
content: "",
|
|
603
|
+
startLine: i + 1
|
|
604
|
+
// 1-based
|
|
605
|
+
};
|
|
606
|
+
} else if (currentSection) {
|
|
607
|
+
contentLines.push(line);
|
|
608
|
+
}
|
|
562
609
|
}
|
|
563
|
-
if (
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
section: "Center Identity",
|
|
567
|
-
message: "No center identity defined. Define what the system becomes when all domains are aligned \u2014 the core identity.",
|
|
568
|
-
severity: "warning"
|
|
569
|
-
});
|
|
610
|
+
if (currentSection) {
|
|
611
|
+
currentSection.content = contentLines.join("\n").trim();
|
|
612
|
+
sections.push(currentSection);
|
|
570
613
|
}
|
|
571
|
-
return
|
|
614
|
+
return { frontmatter, sections };
|
|
572
615
|
}
|
|
573
|
-
function
|
|
574
|
-
const
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
}
|
|
595
|
-
const spatialSection = h2Sections.find(
|
|
596
|
-
(s) => s.name.toLowerCase() === "spatial contexts"
|
|
597
|
-
);
|
|
598
|
-
if (spatialSection) {
|
|
599
|
-
modifiers.spatialContexts = parseBulletList(spatialSection.content);
|
|
616
|
+
function splitH2Sections(content, baseLine) {
|
|
617
|
+
const lines = content.split("\n");
|
|
618
|
+
const sections = [];
|
|
619
|
+
let currentSection = null;
|
|
620
|
+
const contentLines = [];
|
|
621
|
+
for (let i = 0; i < lines.length; i++) {
|
|
622
|
+
const line = lines[i];
|
|
623
|
+
if (line.startsWith("## ")) {
|
|
624
|
+
if (currentSection) {
|
|
625
|
+
currentSection.content = contentLines.join("\n").trim();
|
|
626
|
+
sections.push(currentSection);
|
|
627
|
+
contentLines.length = 0;
|
|
628
|
+
}
|
|
629
|
+
currentSection = {
|
|
630
|
+
name: line.replace(/^##\s+/, "").trim(),
|
|
631
|
+
content: "",
|
|
632
|
+
startLine: baseLine + i
|
|
633
|
+
};
|
|
634
|
+
} else if (currentSection) {
|
|
635
|
+
contentLines.push(line);
|
|
636
|
+
}
|
|
600
637
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
if (rulesSection) {
|
|
605
|
-
modifiers.interpretationRules = parseBulletList(rulesSection.content);
|
|
638
|
+
if (currentSection) {
|
|
639
|
+
currentSection.content = contentLines.join("\n").trim();
|
|
640
|
+
sections.push(currentSection);
|
|
606
641
|
}
|
|
607
|
-
return
|
|
642
|
+
return sections;
|
|
608
643
|
}
|
|
609
|
-
function
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
if (alignedSection) {
|
|
631
|
-
evolution.alignedBehaviors = parseBulletList(alignedSection.content);
|
|
632
|
-
}
|
|
633
|
-
if (evolution.alignedBehaviors.length === 0) {
|
|
634
|
-
issues.push({
|
|
635
|
-
line: alignedSection?.startLine ?? section.startLine,
|
|
636
|
-
section: "Aligned Behaviors",
|
|
637
|
-
message: "No aligned behaviors defined. Define what success looks like in action.",
|
|
638
|
-
severity: "warning"
|
|
639
|
-
});
|
|
640
|
-
}
|
|
641
|
-
const driftSection = h2Sections.find(
|
|
642
|
-
(s) => s.name.toLowerCase() === "drift behaviors"
|
|
643
|
-
);
|
|
644
|
-
if (driftSection) {
|
|
645
|
-
evolution.driftBehaviors = parseBulletList(driftSection.content);
|
|
646
|
-
}
|
|
647
|
-
if (evolution.driftBehaviors.length === 0) {
|
|
648
|
-
issues.push({
|
|
649
|
-
line: driftSection?.startLine ?? section.startLine,
|
|
650
|
-
section: "Drift Behaviors",
|
|
651
|
-
message: "No drift behaviors defined. Define what misalignment looks like so the system can detect behavioral drift over time.",
|
|
652
|
-
severity: "warning"
|
|
653
|
-
});
|
|
644
|
+
function splitH3Sections(content, baseLine) {
|
|
645
|
+
const lines = content.split("\n");
|
|
646
|
+
const sections = [];
|
|
647
|
+
let currentSection = null;
|
|
648
|
+
const contentLines = [];
|
|
649
|
+
for (let i = 0; i < lines.length; i++) {
|
|
650
|
+
const line = lines[i];
|
|
651
|
+
if (line.startsWith("### ")) {
|
|
652
|
+
if (currentSection) {
|
|
653
|
+
currentSection.content = contentLines.join("\n").trim();
|
|
654
|
+
sections.push(currentSection);
|
|
655
|
+
contentLines.length = 0;
|
|
656
|
+
}
|
|
657
|
+
currentSection = {
|
|
658
|
+
name: line.replace(/^###\s+/, "").trim(),
|
|
659
|
+
content: "",
|
|
660
|
+
startLine: baseLine + i
|
|
661
|
+
};
|
|
662
|
+
} else if (currentSection) {
|
|
663
|
+
contentLines.push(line);
|
|
664
|
+
}
|
|
654
665
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
if (signalsSection) {
|
|
659
|
-
evolution.signals = parseBulletList(signalsSection.content);
|
|
666
|
+
if (currentSection) {
|
|
667
|
+
currentSection.content = contentLines.join("\n").trim();
|
|
668
|
+
sections.push(currentSection);
|
|
660
669
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
670
|
+
return sections;
|
|
671
|
+
}
|
|
672
|
+
function splitH4Sections(content, baseLine) {
|
|
673
|
+
const lines = content.split("\n");
|
|
674
|
+
const sections = [];
|
|
675
|
+
let currentSection = null;
|
|
676
|
+
const contentLines = [];
|
|
677
|
+
for (let i = 0; i < lines.length; i++) {
|
|
678
|
+
const line = lines[i];
|
|
679
|
+
if (line.startsWith("#### ")) {
|
|
680
|
+
if (currentSection) {
|
|
681
|
+
currentSection.content = contentLines.join("\n").trim();
|
|
682
|
+
sections.push(currentSection);
|
|
683
|
+
contentLines.length = 0;
|
|
684
|
+
}
|
|
685
|
+
currentSection = {
|
|
686
|
+
name: line.replace(/^####\s+/, "").trim(),
|
|
687
|
+
content: "",
|
|
688
|
+
startLine: baseLine + i
|
|
689
|
+
};
|
|
690
|
+
} else if (currentSection) {
|
|
691
|
+
contentLines.push(line);
|
|
692
|
+
}
|
|
668
693
|
}
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
section: "Decision Priorities",
|
|
687
|
-
message: `Cannot parse priority: '${bullet}'. Expected format: 'preferred > over'.`,
|
|
688
|
-
severity: "warning"
|
|
689
|
-
});
|
|
694
|
+
if (currentSection) {
|
|
695
|
+
currentSection.content = contentLines.join("\n").trim();
|
|
696
|
+
sections.push(currentSection);
|
|
697
|
+
}
|
|
698
|
+
return sections;
|
|
699
|
+
}
|
|
700
|
+
function parseBulletList(content) {
|
|
701
|
+
const items = [];
|
|
702
|
+
let inComment = false;
|
|
703
|
+
for (const line of content.split("\n")) {
|
|
704
|
+
const trimmed = line.trim();
|
|
705
|
+
if (trimmed.startsWith("<!--")) {
|
|
706
|
+
inComment = true;
|
|
707
|
+
}
|
|
708
|
+
if (inComment) {
|
|
709
|
+
if (trimmed.includes("-->")) {
|
|
710
|
+
inComment = false;
|
|
690
711
|
}
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
if (trimmed.startsWith("- ")) {
|
|
715
|
+
items.push(trimmed.slice(2).trim());
|
|
691
716
|
}
|
|
692
717
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
});
|
|
718
|
+
return items;
|
|
719
|
+
}
|
|
720
|
+
function extractTextContent(content) {
|
|
721
|
+
const lines = content.split("\n");
|
|
722
|
+
const textLines = [];
|
|
723
|
+
let inComment = false;
|
|
724
|
+
for (const line of lines) {
|
|
725
|
+
const trimmed = line.trim();
|
|
726
|
+
if (trimmed.startsWith("<!--")) {
|
|
727
|
+
inComment = true;
|
|
728
|
+
}
|
|
729
|
+
if (inComment) {
|
|
730
|
+
if (trimmed.includes("-->")) {
|
|
731
|
+
inComment = false;
|
|
732
|
+
}
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
if (trimmed && !trimmed.startsWith("#")) {
|
|
736
|
+
textLines.push(trimmed);
|
|
737
|
+
}
|
|
714
738
|
}
|
|
715
|
-
return
|
|
739
|
+
return textLines.join("\n").trim();
|
|
716
740
|
}
|
|
717
|
-
function
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
741
|
+
function toKebabCase(name) {
|
|
742
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
743
|
+
}
|
|
744
|
+
function parseFrontmatter(yaml, issues) {
|
|
745
|
+
const result = {};
|
|
746
|
+
for (const line of yaml.split("\n")) {
|
|
747
|
+
const trimmed = line.trim();
|
|
748
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
749
|
+
const colonIdx = trimmed.indexOf(":");
|
|
750
|
+
if (colonIdx === -1) continue;
|
|
751
|
+
const key = trimmed.slice(0, colonIdx).trim();
|
|
752
|
+
const value = trimmed.slice(colonIdx + 1).trim();
|
|
753
|
+
result[key] = value;
|
|
727
754
|
}
|
|
728
|
-
const
|
|
729
|
-
|
|
730
|
-
const geometrySection = sections.find(
|
|
731
|
-
(s) => s.name.toLowerCase() === "core model geometry"
|
|
732
|
-
);
|
|
733
|
-
const modifiersSection = sections.find(
|
|
734
|
-
(s) => s.name.toLowerCase() === "contextual modifiers"
|
|
735
|
-
);
|
|
736
|
-
const evolutionSection = sections.find(
|
|
737
|
-
(s) => s.name.toLowerCase() === "evolution layer"
|
|
738
|
-
);
|
|
739
|
-
const geometry = parseGeometry(geometrySection, issues);
|
|
740
|
-
const modifiers = parseModifiers(modifiersSection, issues);
|
|
741
|
-
const evolution = parseEvolution(evolutionSection, issues);
|
|
742
|
-
if (geometry.overlapEffects.length > 0 && !geometry.centerIdentity) {
|
|
755
|
+
const name = result.name || "";
|
|
756
|
+
if (!name) {
|
|
743
757
|
issues.push({
|
|
744
|
-
line:
|
|
745
|
-
section: "
|
|
746
|
-
message: "
|
|
747
|
-
severity: "
|
|
758
|
+
line: 1,
|
|
759
|
+
section: "frontmatter",
|
|
760
|
+
message: "Missing name in frontmatter. Provide a human-readable model name.",
|
|
761
|
+
severity: "error"
|
|
748
762
|
});
|
|
749
763
|
}
|
|
750
|
-
const
|
|
751
|
-
if (hasErrors) {
|
|
752
|
-
return {
|
|
753
|
-
model: {
|
|
754
|
-
frontmatter,
|
|
755
|
-
geometry,
|
|
756
|
-
modifiers,
|
|
757
|
-
evolution
|
|
758
|
-
},
|
|
759
|
-
issues
|
|
760
|
-
};
|
|
761
|
-
}
|
|
764
|
+
const model_id = result.model_id || toKebabCase(name);
|
|
762
765
|
return {
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
modifiers,
|
|
767
|
-
evolution
|
|
768
|
-
},
|
|
769
|
-
issues
|
|
766
|
+
model_id,
|
|
767
|
+
name,
|
|
768
|
+
version: result.version || "1.0.0"
|
|
770
769
|
};
|
|
771
770
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
if (signalWords.some((w) => w.length > 3 && lowerText.includes(w))) {
|
|
788
|
-
return signal;
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
return "alignment_score";
|
|
792
|
-
}
|
|
793
|
-
function emitWorldMarkdown(model) {
|
|
794
|
-
const lines = [];
|
|
795
|
-
const worldId = model.frontmatter.model_id;
|
|
796
|
-
const worldName = model.frontmatter.name;
|
|
797
|
-
const version = model.frontmatter.version;
|
|
798
|
-
lines.push("---");
|
|
799
|
-
lines.push(`world_id: ${worldId}`);
|
|
800
|
-
lines.push(`name: ${worldName}`);
|
|
801
|
-
lines.push(`version: ${version}`);
|
|
802
|
-
lines.push("runtime_mode: COMPLIANCE");
|
|
803
|
-
lines.push("default_profile: aligned");
|
|
804
|
-
lines.push("alternative_profile: drifting");
|
|
805
|
-
lines.push("---");
|
|
806
|
-
lines.push("");
|
|
807
|
-
lines.push("# Thesis");
|
|
808
|
-
lines.push("");
|
|
809
|
-
lines.push(model.geometry.mission);
|
|
810
|
-
if (model.geometry.centerIdentity) {
|
|
811
|
-
lines.push(
|
|
812
|
-
`When all domains are aligned, the system operates as: ${model.geometry.centerIdentity}.`
|
|
813
|
-
);
|
|
814
|
-
}
|
|
815
|
-
lines.push("");
|
|
816
|
-
lines.push("# Invariants");
|
|
817
|
-
lines.push("");
|
|
818
|
-
let invariantIdx = 0;
|
|
819
|
-
for (const domain of model.geometry.domains) {
|
|
820
|
-
for (const value of domain.values) {
|
|
821
|
-
invariantIdx++;
|
|
822
|
-
const invId = `${toSnakeCase(domain.name)}_value_${String(invariantIdx).padStart(2, "0")}`;
|
|
823
|
-
lines.push(
|
|
824
|
-
`- \`${invId}\` \u2014 ${value} [${domain.name}] (structural, immutable)`
|
|
825
|
-
);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
lines.push("");
|
|
829
|
-
lines.push("# State");
|
|
830
|
-
lines.push("");
|
|
831
|
-
lines.push("## alignment_score");
|
|
832
|
-
lines.push("- type: number");
|
|
833
|
-
lines.push("- min: 0");
|
|
834
|
-
lines.push("- max: 100");
|
|
835
|
-
lines.push("- step: 5");
|
|
836
|
-
lines.push("- default: 70");
|
|
837
|
-
lines.push("- label: Alignment Score");
|
|
838
|
-
lines.push(
|
|
839
|
-
"- description: Composite behavioral alignment metric derived from all signals"
|
|
840
|
-
);
|
|
841
|
-
lines.push("");
|
|
842
|
-
for (const signal of model.evolution.signals) {
|
|
843
|
-
const signalId = toSnakeCase(signal);
|
|
844
|
-
const signalLabel = titleCase(signal);
|
|
845
|
-
lines.push(`## ${signalId}`);
|
|
846
|
-
lines.push("- type: number");
|
|
847
|
-
lines.push("- min: 0");
|
|
848
|
-
lines.push("- max: 100");
|
|
849
|
-
lines.push("- step: 5");
|
|
850
|
-
lines.push("- default: 70");
|
|
851
|
-
lines.push(`- label: ${signalLabel}`);
|
|
852
|
-
lines.push(`- description: Behavioral signal measuring ${signal.replace(/_/g, " ")}`);
|
|
853
|
-
lines.push("");
|
|
854
|
-
}
|
|
855
|
-
lines.push("# Assumptions");
|
|
856
|
-
lines.push("");
|
|
857
|
-
lines.push("## aligned");
|
|
858
|
-
lines.push("- name: Aligned");
|
|
859
|
-
lines.push("- description: All behavioral signals at healthy levels");
|
|
860
|
-
lines.push("- pressure_level: low");
|
|
861
|
-
lines.push("");
|
|
862
|
-
lines.push("## drifting");
|
|
863
|
-
lines.push("- name: Drifting");
|
|
864
|
-
lines.push("- description: Behavioral signals under pressure with drift risk");
|
|
865
|
-
lines.push("- pressure_level: high");
|
|
866
|
-
lines.push("");
|
|
867
|
-
lines.push("# Rules");
|
|
868
|
-
lines.push("");
|
|
869
|
-
let ruleIdx = 0;
|
|
870
|
-
for (const drift of model.evolution.driftBehaviors) {
|
|
871
|
-
ruleIdx++;
|
|
872
|
-
const ruleId = `rule-${String(ruleIdx).padStart(3, "0")}`;
|
|
873
|
-
const matchedSignal = matchSignal(drift, model.evolution.signals);
|
|
874
|
-
const signalId = toSnakeCase(matchedSignal);
|
|
875
|
-
lines.push(`## ${ruleId}: ${drift} (degradation)`);
|
|
876
|
-
lines.push(`Drift behavior detected: ${drift}`);
|
|
877
|
-
lines.push("");
|
|
878
|
-
lines.push(`When ${signalId} < 50 [state]`);
|
|
879
|
-
lines.push("Then alignment_score *= 0.80");
|
|
880
|
-
lines.push("");
|
|
881
|
-
lines.push(`> trigger: ${signalId} drops below threshold`);
|
|
882
|
-
lines.push(`> rule: Drift behavior weakens alignment`);
|
|
883
|
-
lines.push(`> shift: Behavioral alignment decreases`);
|
|
884
|
-
lines.push(`> effect: Alignment score reduced by 20%`);
|
|
885
|
-
lines.push("");
|
|
771
|
+
function parseGeometry(section, issues) {
|
|
772
|
+
const geometry = {
|
|
773
|
+
mission: "",
|
|
774
|
+
domains: [],
|
|
775
|
+
overlapEffects: [],
|
|
776
|
+
centerIdentity: ""
|
|
777
|
+
};
|
|
778
|
+
if (!section) {
|
|
779
|
+
issues.push({
|
|
780
|
+
line: 0,
|
|
781
|
+
section: "Core Model Geometry",
|
|
782
|
+
message: "Missing # Core Model Geometry section. Define the structural model: mission, domains with embedded skills and values, overlaps, and center identity.",
|
|
783
|
+
severity: "error"
|
|
784
|
+
});
|
|
785
|
+
return geometry;
|
|
886
786
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
const signalId = toSnakeCase(matchedSignal);
|
|
892
|
-
lines.push(`## ${ruleId}: ${aligned} (advantage)`);
|
|
893
|
-
lines.push(`Aligned behavior reinforced: ${aligned}`);
|
|
894
|
-
lines.push("");
|
|
895
|
-
lines.push(`When ${signalId} >= 70 [state]`);
|
|
896
|
-
lines.push("Then alignment_score *= 1.10");
|
|
897
|
-
lines.push("");
|
|
898
|
-
lines.push(`> trigger: ${signalId} above healthy threshold`);
|
|
899
|
-
lines.push(`> rule: Aligned behavior strengthens system`);
|
|
900
|
-
lines.push(`> shift: Behavioral alignment increases`);
|
|
901
|
-
lines.push(`> effect: Alignment score boosted by 10%`);
|
|
902
|
-
lines.push("");
|
|
787
|
+
const h2Sections = splitH2Sections(section.content, section.startLine);
|
|
788
|
+
const missionSection = h2Sections.find((s) => s.name.toLowerCase() === "mission");
|
|
789
|
+
if (missionSection) {
|
|
790
|
+
geometry.mission = extractTextContent(missionSection.content);
|
|
903
791
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
);
|
|
911
|
-
lines.push(
|
|
912
|
-
`Priority: ${priority.preferred} takes precedence over ${priority.over} in tradeoff situations.`
|
|
913
|
-
);
|
|
914
|
-
lines.push("");
|
|
915
|
-
lines.push("When alignment_score < 40 [state]");
|
|
916
|
-
lines.push("Then alignment_score *= 0.70");
|
|
917
|
-
lines.push("Collapse: alignment_score < 10");
|
|
918
|
-
lines.push("");
|
|
919
|
-
lines.push(`> trigger: Alignment score critically low`);
|
|
920
|
-
lines.push(
|
|
921
|
-
`> rule: Priority violation \u2014 ${priority.preferred} must outweigh ${priority.over}`
|
|
922
|
-
);
|
|
923
|
-
lines.push(`> shift: System enters structural enforcement`);
|
|
924
|
-
lines.push(`> effect: Alignment sharply reduced; collapse if critical`);
|
|
925
|
-
lines.push("");
|
|
792
|
+
if (!geometry.mission) {
|
|
793
|
+
issues.push({
|
|
794
|
+
line: missionSection?.startLine ?? section.startLine,
|
|
795
|
+
section: "Mission",
|
|
796
|
+
message: "Missing ## Mission. Define what this system is trying to achieve \u2014 the core aim, not a slogan.",
|
|
797
|
+
severity: "error"
|
|
798
|
+
});
|
|
926
799
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
800
|
+
const domainsSection = h2Sections.find((s) => s.name.toLowerCase() === "domains");
|
|
801
|
+
if (domainsSection) {
|
|
802
|
+
const domainSections = splitH3Sections(domainsSection.content, domainsSection.startLine);
|
|
803
|
+
for (const ds of domainSections) {
|
|
804
|
+
const domain = {
|
|
805
|
+
id: toKebabCase(ds.name),
|
|
806
|
+
name: ds.name,
|
|
807
|
+
skills: [],
|
|
808
|
+
values: [],
|
|
809
|
+
line: ds.startLine
|
|
810
|
+
};
|
|
811
|
+
const h4Sections = splitH4Sections(ds.content, ds.startLine);
|
|
812
|
+
const skillsH4 = h4Sections.find((s) => s.name.toLowerCase() === "skills");
|
|
813
|
+
if (skillsH4) {
|
|
814
|
+
domain.skills = parseBulletList(skillsH4.content);
|
|
815
|
+
}
|
|
816
|
+
const valuesH4 = h4Sections.find((s) => s.name.toLowerCase() === "values");
|
|
817
|
+
if (valuesH4) {
|
|
818
|
+
domain.values = parseBulletList(valuesH4.content);
|
|
819
|
+
}
|
|
820
|
+
if (domain.skills.length === 0) {
|
|
821
|
+
issues.push({
|
|
822
|
+
line: ds.startLine,
|
|
823
|
+
section: "Domains",
|
|
824
|
+
message: `Domain '${ds.name}' has no skills defined. Skills are the capabilities within this domain.`,
|
|
825
|
+
severity: "warning"
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
if (domain.values.length === 0) {
|
|
829
|
+
issues.push({
|
|
830
|
+
line: ds.startLine,
|
|
831
|
+
section: "Domains",
|
|
832
|
+
message: `Domain '${ds.name}' has no values defined. Behavior has no constraints without values.`,
|
|
833
|
+
severity: "warning"
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
geometry.domains.push(domain);
|
|
837
|
+
}
|
|
953
838
|
}
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
839
|
+
if (geometry.domains.length < 2) {
|
|
840
|
+
issues.push({
|
|
841
|
+
line: domainsSection?.startLine ?? section.startLine,
|
|
842
|
+
section: "Domains",
|
|
843
|
+
message: "At least 2 domains required. Domains are the major operating modes of the system, each carrying skills and values.",
|
|
844
|
+
severity: "error"
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
const overlapsSection = h2Sections.find(
|
|
848
|
+
(s) => s.name.toLowerCase() === "overlap effects"
|
|
849
|
+
);
|
|
850
|
+
if (overlapsSection) {
|
|
851
|
+
const bullets = parseBulletList(overlapsSection.content);
|
|
852
|
+
const domainNames = new Set(geometry.domains.map((d) => d.name.toLowerCase()));
|
|
853
|
+
for (let i = 0; i < bullets.length; i++) {
|
|
854
|
+
const bullet = bullets[i];
|
|
855
|
+
const match = bullet.match(/^(.+?)\s*\+\s*(.+?)\s*=\s*(.+)$/);
|
|
856
|
+
if (match) {
|
|
857
|
+
const domainA = match[1].trim();
|
|
858
|
+
const domainB = match[2].trim();
|
|
859
|
+
const effect = match[3].trim();
|
|
860
|
+
if (!domainNames.has(domainA.toLowerCase())) {
|
|
861
|
+
issues.push({
|
|
862
|
+
line: overlapsSection.startLine + i,
|
|
863
|
+
section: "Overlap Effects",
|
|
864
|
+
message: `Overlap references unknown domain '${domainA}'. Must reference a declared domain.`,
|
|
865
|
+
severity: "warning"
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
if (!domainNames.has(domainB.toLowerCase())) {
|
|
869
|
+
issues.push({
|
|
870
|
+
line: overlapsSection.startLine + i,
|
|
871
|
+
section: "Overlap Effects",
|
|
872
|
+
message: `Overlap references unknown domain '${domainB}'. Must reference a declared domain.`,
|
|
873
|
+
severity: "warning"
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
geometry.overlapEffects.push({
|
|
877
|
+
domainA,
|
|
878
|
+
domainB,
|
|
879
|
+
effect,
|
|
880
|
+
line: overlapsSection.startLine + i
|
|
881
|
+
});
|
|
882
|
+
} else {
|
|
883
|
+
issues.push({
|
|
884
|
+
line: overlapsSection.startLine + i,
|
|
885
|
+
section: "Overlap Effects",
|
|
886
|
+
message: `Cannot parse overlap: '${bullet}'. Expected format: 'Domain A + Domain B = Emergent State'.`,
|
|
887
|
+
severity: "warning"
|
|
888
|
+
});
|
|
976
889
|
}
|
|
977
|
-
lines.push("");
|
|
978
890
|
}
|
|
979
891
|
}
|
|
980
|
-
|
|
892
|
+
if (geometry.overlapEffects.length === 0) {
|
|
893
|
+
issues.push({
|
|
894
|
+
line: overlapsSection?.startLine ?? section.startLine,
|
|
895
|
+
section: "Overlap Effects",
|
|
896
|
+
message: 'No overlap effects defined. Define what emerges when two domains interact well (e.g., "Domain A + Domain B = Inspiration").',
|
|
897
|
+
severity: "warning"
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
const identitySection = h2Sections.find(
|
|
901
|
+
(s) => s.name.toLowerCase() === "center identity"
|
|
902
|
+
);
|
|
903
|
+
if (identitySection) {
|
|
904
|
+
geometry.centerIdentity = extractTextContent(identitySection.content);
|
|
905
|
+
}
|
|
906
|
+
if (!geometry.centerIdentity) {
|
|
907
|
+
issues.push({
|
|
908
|
+
line: identitySection?.startLine ?? section.startLine,
|
|
909
|
+
section: "Center Identity",
|
|
910
|
+
message: "No center identity defined. Define what the system becomes when all domains are aligned \u2014 the core identity.",
|
|
911
|
+
severity: "warning"
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
return geometry;
|
|
981
915
|
}
|
|
982
|
-
function
|
|
983
|
-
const
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
default: 70
|
|
988
|
-
}));
|
|
989
|
-
return {
|
|
990
|
-
model_id: model.frontmatter.model_id,
|
|
991
|
-
signals
|
|
916
|
+
function parseModifiers(section, issues) {
|
|
917
|
+
const modifiers = {
|
|
918
|
+
authorityLayers: [],
|
|
919
|
+
spatialContexts: [],
|
|
920
|
+
interpretationRules: []
|
|
992
921
|
};
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
922
|
+
if (!section) {
|
|
923
|
+
issues.push({
|
|
924
|
+
line: 0,
|
|
925
|
+
section: "Contextual Modifiers",
|
|
926
|
+
message: "Missing # Contextual Modifiers section. Define how authority, role, and spatial context change how behavior is interpreted.",
|
|
927
|
+
severity: "warning"
|
|
928
|
+
});
|
|
929
|
+
return modifiers;
|
|
930
|
+
}
|
|
931
|
+
const h2Sections = splitH2Sections(section.content, section.startLine);
|
|
932
|
+
const authoritySection = h2Sections.find(
|
|
933
|
+
(s) => s.name.toLowerCase() === "authority layers"
|
|
934
|
+
);
|
|
935
|
+
if (authoritySection) {
|
|
936
|
+
modifiers.authorityLayers = parseBulletList(authoritySection.content);
|
|
1006
937
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
938
|
+
const spatialSection = h2Sections.find(
|
|
939
|
+
(s) => s.name.toLowerCase() === "spatial contexts"
|
|
940
|
+
);
|
|
941
|
+
if (spatialSection) {
|
|
942
|
+
modifiers.spatialContexts = parseBulletList(spatialSection.content);
|
|
943
|
+
}
|
|
944
|
+
const rulesSection = h2Sections.find(
|
|
945
|
+
(s) => s.name.toLowerCase() === "interpretation rules"
|
|
946
|
+
);
|
|
947
|
+
if (rulesSection) {
|
|
948
|
+
modifiers.interpretationRules = parseBulletList(rulesSection.content);
|
|
949
|
+
}
|
|
950
|
+
return modifiers;
|
|
1012
951
|
}
|
|
1013
|
-
function
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
952
|
+
function parseEvolution(section, issues) {
|
|
953
|
+
const evolution = {
|
|
954
|
+
alignedBehaviors: [],
|
|
955
|
+
driftBehaviors: [],
|
|
956
|
+
signals: [],
|
|
957
|
+
decisionPriorities: [],
|
|
958
|
+
evolutionConditions: []
|
|
1019
959
|
};
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
960
|
+
if (!section) {
|
|
961
|
+
issues.push({
|
|
962
|
+
line: 0,
|
|
963
|
+
section: "Evolution Layer",
|
|
964
|
+
message: "Missing # Evolution Layer section. Define observable behaviors, signals, decision priorities, and adaptation conditions.",
|
|
965
|
+
severity: "error"
|
|
966
|
+
});
|
|
967
|
+
return evolution;
|
|
1028
968
|
}
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
969
|
+
const h2Sections = splitH2Sections(section.content, section.startLine);
|
|
970
|
+
const alignedSection = h2Sections.find(
|
|
971
|
+
(s) => s.name.toLowerCase() === "aligned behaviors"
|
|
972
|
+
);
|
|
973
|
+
if (alignedSection) {
|
|
974
|
+
evolution.alignedBehaviors = parseBulletList(alignedSection.content);
|
|
1034
975
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
976
|
+
if (evolution.alignedBehaviors.length === 0) {
|
|
977
|
+
issues.push({
|
|
978
|
+
line: alignedSection?.startLine ?? section.startLine,
|
|
979
|
+
section: "Aligned Behaviors",
|
|
980
|
+
message: "No aligned behaviors defined. Define what success looks like in action.",
|
|
981
|
+
severity: "warning"
|
|
982
|
+
});
|
|
1040
983
|
}
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
984
|
+
const driftSection = h2Sections.find(
|
|
985
|
+
(s) => s.name.toLowerCase() === "drift behaviors"
|
|
986
|
+
);
|
|
987
|
+
if (driftSection) {
|
|
988
|
+
evolution.driftBehaviors = parseBulletList(driftSection.content);
|
|
1046
989
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
990
|
+
if (evolution.driftBehaviors.length === 0) {
|
|
991
|
+
issues.push({
|
|
992
|
+
line: driftSection?.startLine ?? section.startLine,
|
|
993
|
+
section: "Drift Behaviors",
|
|
994
|
+
message: "No drift behaviors defined. Define what misalignment looks like so the system can detect behavioral drift over time.",
|
|
995
|
+
severity: "warning"
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
const signalsSection = h2Sections.find(
|
|
999
|
+
(s) => s.name.toLowerCase() === "signals"
|
|
1000
|
+
);
|
|
1001
|
+
if (signalsSection) {
|
|
1002
|
+
evolution.signals = parseBulletList(signalsSection.content);
|
|
1003
|
+
}
|
|
1004
|
+
if (evolution.signals.length < 2) {
|
|
1005
|
+
issues.push({
|
|
1006
|
+
line: signalsSection?.startLine ?? section.startLine,
|
|
1007
|
+
section: "Signals",
|
|
1008
|
+
message: "At least 2 signals required. Signals are the observable metrics for detecting alignment or drift.",
|
|
1009
|
+
severity: "error"
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
const prioritiesSection = h2Sections.find(
|
|
1013
|
+
(s) => s.name.toLowerCase() === "decision priorities"
|
|
1014
|
+
);
|
|
1015
|
+
if (prioritiesSection) {
|
|
1016
|
+
const bullets = parseBulletList(prioritiesSection.content);
|
|
1017
|
+
for (let i = 0; i < bullets.length; i++) {
|
|
1018
|
+
const bullet = bullets[i];
|
|
1019
|
+
const match = bullet.match(/^(.+?)\s*>\s*(.+)$/);
|
|
1020
|
+
if (match) {
|
|
1021
|
+
evolution.decisionPriorities.push({
|
|
1022
|
+
preferred: match[1].trim(),
|
|
1023
|
+
over: match[2].trim(),
|
|
1024
|
+
line: prioritiesSection.startLine + i
|
|
1025
|
+
});
|
|
1026
|
+
} else {
|
|
1027
|
+
issues.push({
|
|
1028
|
+
line: prioritiesSection.startLine + i,
|
|
1029
|
+
section: "Decision Priorities",
|
|
1030
|
+
message: `Cannot parse priority: '${bullet}'. Expected format: 'preferred > over'.`,
|
|
1031
|
+
severity: "warning"
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1069
1034
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1035
|
+
}
|
|
1036
|
+
if (evolution.decisionPriorities.length === 0) {
|
|
1037
|
+
issues.push({
|
|
1038
|
+
line: prioritiesSection?.startLine ?? section.startLine,
|
|
1039
|
+
section: "Decision Priorities",
|
|
1040
|
+
message: "No decision priorities defined. Define what wins when tradeoffs appear.",
|
|
1041
|
+
severity: "warning"
|
|
1073
1042
|
});
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1043
|
+
}
|
|
1044
|
+
const evoSection = h2Sections.find(
|
|
1045
|
+
(s) => s.name.toLowerCase() === "evolution conditions"
|
|
1046
|
+
);
|
|
1047
|
+
if (evoSection) {
|
|
1048
|
+
evolution.evolutionConditions = parseBulletList(evoSection.content);
|
|
1049
|
+
}
|
|
1050
|
+
if (evolution.signals.length > 0 && evolution.driftBehaviors.length === 0) {
|
|
1051
|
+
issues.push({
|
|
1052
|
+
line: signalsSection?.startLine ?? section.startLine,
|
|
1053
|
+
section: "Evolution Layer",
|
|
1054
|
+
message: "Signals defined but no drift behaviors. System cannot detect failure without drift definitions.",
|
|
1055
|
+
severity: "warning"
|
|
1085
1056
|
});
|
|
1086
1057
|
}
|
|
1087
|
-
return
|
|
1088
|
-
}
|
|
1089
|
-
function emitLensSuggestions(model) {
|
|
1090
|
-
return buildLensSuggestions(model);
|
|
1058
|
+
return evolution;
|
|
1091
1059
|
}
|
|
1092
|
-
function
|
|
1060
|
+
function parseWorldModel(markdown) {
|
|
1061
|
+
const issues = [];
|
|
1062
|
+
if (!markdown || !markdown.trim()) {
|
|
1063
|
+
issues.push({
|
|
1064
|
+
line: 0,
|
|
1065
|
+
section: "file",
|
|
1066
|
+
message: "Empty input. Provide a .worldmodel.md file with three layers: Core Model Geometry, Contextual Modifiers, Evolution Layer.",
|
|
1067
|
+
severity: "error"
|
|
1068
|
+
});
|
|
1069
|
+
return { model: null, issues };
|
|
1070
|
+
}
|
|
1071
|
+
const { frontmatter: fmRaw, sections } = splitSections(markdown);
|
|
1072
|
+
const frontmatter = parseFrontmatter(fmRaw, issues);
|
|
1073
|
+
const geometrySection = sections.find(
|
|
1074
|
+
(s) => s.name.toLowerCase() === "core model geometry"
|
|
1075
|
+
);
|
|
1076
|
+
const modifiersSection = sections.find(
|
|
1077
|
+
(s) => s.name.toLowerCase() === "contextual modifiers"
|
|
1078
|
+
);
|
|
1079
|
+
const evolutionSection = sections.find(
|
|
1080
|
+
(s) => s.name.toLowerCase() === "evolution layer"
|
|
1081
|
+
);
|
|
1082
|
+
const geometry = parseGeometry(geometrySection, issues);
|
|
1083
|
+
const modifiers = parseModifiers(modifiersSection, issues);
|
|
1084
|
+
const evolution = parseEvolution(evolutionSection, issues);
|
|
1085
|
+
if (geometry.overlapEffects.length > 0 && !geometry.centerIdentity) {
|
|
1086
|
+
issues.push({
|
|
1087
|
+
line: 0,
|
|
1088
|
+
section: "Core Model Geometry",
|
|
1089
|
+
message: "Overlaps defined but no center identity. System lacks coherence without an aligned identity.",
|
|
1090
|
+
severity: "warning"
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
1094
|
+
if (hasErrors) {
|
|
1095
|
+
return {
|
|
1096
|
+
model: {
|
|
1097
|
+
frontmatter,
|
|
1098
|
+
geometry,
|
|
1099
|
+
modifiers,
|
|
1100
|
+
evolution
|
|
1101
|
+
},
|
|
1102
|
+
issues
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1093
1105
|
return {
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1106
|
+
model: {
|
|
1107
|
+
frontmatter,
|
|
1108
|
+
geometry,
|
|
1109
|
+
modifiers,
|
|
1110
|
+
evolution
|
|
1111
|
+
},
|
|
1112
|
+
issues
|
|
1099
1113
|
};
|
|
1100
1114
|
}
|
|
1101
1115
|
|
|
1102
1116
|
// src/cli/worldmodel.ts
|
|
1117
|
+
init_worldmodel_compiler();
|
|
1103
1118
|
var BOLD = "\x1B[1m";
|
|
1104
1119
|
var DIM = "\x1B[2m";
|
|
1105
1120
|
var CYAN = "\x1B[36m";
|
|
@@ -1257,6 +1272,46 @@ ${YELLOW}Validation found ${errors.length} issue${errors.length > 1 ? "s" : ""}
|
|
|
1257
1272
|
} else {
|
|
1258
1273
|
process.stderr.write(`${GREEN}Validates cleanly!${RESET}
|
|
1259
1274
|
`);
|
|
1275
|
+
try {
|
|
1276
|
+
if (!validateResult.model) throw new Error("no model");
|
|
1277
|
+
const { compileWorldModel: compileWorldModel2 } = await Promise.resolve().then(() => (init_worldmodel_compiler(), worldmodel_compiler_exports));
|
|
1278
|
+
const compiled = compileWorldModel2(validateResult.model);
|
|
1279
|
+
const outDir = (0, import_path2.dirname)(outputPath);
|
|
1280
|
+
const baseName = (0, import_path2.basename)(outputPath).replace(/\.worldmodel\.md$/, "");
|
|
1281
|
+
const worldPath = (0, import_path2.join)(outDir, `${baseName}.nv-world.md`);
|
|
1282
|
+
await (0, import_promises.writeFile)(worldPath, compiled.worldMarkdown, "utf-8");
|
|
1283
|
+
const signalsPath = (0, import_path2.join)(outDir, "signals.json");
|
|
1284
|
+
await (0, import_promises.writeFile)(signalsPath, JSON.stringify(compiled.signalSchema, null, 2), "utf-8");
|
|
1285
|
+
const overlapsPath = (0, import_path2.join)(outDir, "overlaps.json");
|
|
1286
|
+
await (0, import_promises.writeFile)(overlapsPath, JSON.stringify(compiled.overlapMap, null, 2), "utf-8");
|
|
1287
|
+
const contextsPath = (0, import_path2.join)(outDir, "contexts.json");
|
|
1288
|
+
await (0, import_promises.writeFile)(contextsPath, JSON.stringify(compiled.contextsConfig, null, 2), "utf-8");
|
|
1289
|
+
const lensesPath = (0, import_path2.join)(outDir, "lenses.json");
|
|
1290
|
+
await (0, import_promises.writeFile)(lensesPath, JSON.stringify(compiled.lensSuggestions, null, 2), "utf-8");
|
|
1291
|
+
process.stderr.write(`
|
|
1292
|
+
${GREEN}Compiled!${RESET} Token-optimized artifacts:
|
|
1293
|
+
`);
|
|
1294
|
+
process.stderr.write(`${DIM} ${worldPath}${RESET}
|
|
1295
|
+
`);
|
|
1296
|
+
process.stderr.write(`${DIM} ${signalsPath}${RESET}
|
|
1297
|
+
`);
|
|
1298
|
+
process.stderr.write(`${DIM} ${overlapsPath}${RESET}
|
|
1299
|
+
`);
|
|
1300
|
+
process.stderr.write(`${DIM} ${contextsPath}${RESET}
|
|
1301
|
+
`);
|
|
1302
|
+
process.stderr.write(`${DIM} ${lensesPath}${RESET}
|
|
1303
|
+
`);
|
|
1304
|
+
process.stderr.write(`
|
|
1305
|
+
${DIM}Source: ${outputPath} (readable, editable)${RESET}
|
|
1306
|
+
`);
|
|
1307
|
+
process.stderr.write(`${DIM}Compiled: ready for Radiant \u2014 token-optimized, no prose overhead.${RESET}
|
|
1308
|
+
`);
|
|
1309
|
+
} catch {
|
|
1310
|
+
process.stderr.write(
|
|
1311
|
+
`${DIM}Auto-compile skipped \u2014 run 'neuroverse worldmodel build ${(0, import_path2.basename)(outputPath)}' manually.${RESET}
|
|
1312
|
+
`
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1260
1315
|
}
|
|
1261
1316
|
} catch {
|
|
1262
1317
|
}
|