@sdotwinter/openclaw-deterministic 0.8.0 → 0.10.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/bin/doctor.js +167 -46
- package/package.json +1 -1
package/bin/doctor.js
CHANGED
|
@@ -5,10 +5,16 @@ const path = require("path");
|
|
|
5
5
|
|
|
6
6
|
const pkg = require("../package.json");
|
|
7
7
|
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
const JSON_MODE = args.includes("--json");
|
|
10
|
+
|
|
8
11
|
const HOME = process.env.HOME;
|
|
9
12
|
const openclawRoot = path.join(HOME, ".openclaw");
|
|
10
13
|
const workspace = path.join(openclawRoot, "workspace");
|
|
11
14
|
|
|
15
|
+
const DEFAULT_HARD_LIMIT = 1200;
|
|
16
|
+
const DEFAULT_RISK_THRESHOLD = 1020;
|
|
17
|
+
|
|
12
18
|
const files = {
|
|
13
19
|
operating: path.join(workspace, "OPERATING_RULES.md"),
|
|
14
20
|
detSoul: path.join(workspace, "SOUL.deterministic.md"),
|
|
@@ -34,27 +40,6 @@ function versionFromFile(content) {
|
|
|
34
40
|
return match ? match[1] : null;
|
|
35
41
|
}
|
|
36
42
|
|
|
37
|
-
function checkVersion(filePath, label) {
|
|
38
|
-
if (!exists(filePath)) {
|
|
39
|
-
console.log(`❌ ${label} missing.`);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const content = read(filePath);
|
|
44
|
-
const version = versionFromFile(content);
|
|
45
|
-
|
|
46
|
-
if (!version) {
|
|
47
|
-
console.log(`⚠ ${label} version stamp missing.`);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (version === pkg.version) {
|
|
52
|
-
console.log(`✅ ${label} version matches CLI (${version})`);
|
|
53
|
-
} else {
|
|
54
|
-
console.log(`⚠ ${label} version mismatch (installed ${version}, CLI ${pkg.version})`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
43
|
function overlayEnabled() {
|
|
59
44
|
if (!exists(files.soul)) return false;
|
|
60
45
|
const content = read(files.soul);
|
|
@@ -76,43 +61,179 @@ function estimateSemanticTokens() {
|
|
|
76
61
|
return Math.ceil(content.length / 4);
|
|
77
62
|
}
|
|
78
63
|
|
|
79
|
-
|
|
64
|
+
function evaluateVersion(filePath) {
|
|
65
|
+
if (!exists(filePath)) {
|
|
66
|
+
return { status: "missing", version: null };
|
|
67
|
+
}
|
|
80
68
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
69
|
+
const content = read(filePath);
|
|
70
|
+
const version = versionFromFile(content);
|
|
71
|
+
|
|
72
|
+
if (!version) {
|
|
73
|
+
return { status: "no-stamp", version: null };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (version === pkg.version) {
|
|
77
|
+
return { status: "match", version };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return { status: "mismatch", version };
|
|
84
81
|
}
|
|
85
82
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
function parseHardLimit() {
|
|
84
|
+
if (!exists(files.compactor)) return null;
|
|
85
|
+
|
|
86
|
+
const content = read(files.compactor);
|
|
87
|
+
|
|
88
|
+
const match = content.match(/HARD_LIMIT[^0-9]*([0-9]+)/);
|
|
89
|
+
if (!match) return null;
|
|
90
|
+
|
|
91
|
+
return parseInt(match[1], 10);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
function parseRiskThreshold() {
|
|
95
|
+
if (!exists(files.compactor)) return null;
|
|
96
|
+
|
|
97
|
+
const content = read(files.compactor);
|
|
98
|
+
|
|
99
|
+
const match = content.match(/RISK_THRESHOLD[^0-9]*([0-9]+)/);
|
|
100
|
+
if (!match) return null;
|
|
101
|
+
|
|
102
|
+
return parseInt(match[1], 10);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function evaluate() {
|
|
106
|
+
const result = {
|
|
107
|
+
cliVersion: pkg.version,
|
|
108
|
+
openclawDetected: exists(openclawRoot),
|
|
109
|
+
workspaceDetected: exists(workspace),
|
|
110
|
+
files: {},
|
|
111
|
+
overlayEnabled: false,
|
|
112
|
+
semanticTokens: 0,
|
|
113
|
+
semanticStatus: "safe",
|
|
114
|
+
limits: {
|
|
115
|
+
hardLimitConfigured: null,
|
|
116
|
+
riskThresholdConfigured: null,
|
|
117
|
+
hardLimitDefault: DEFAULT_HARD_LIMIT,
|
|
118
|
+
riskThresholdDefault: DEFAULT_RISK_THRESHOLD,
|
|
119
|
+
coherent: true,
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
if (!result.openclawDetected || !result.workspaceDetected) {
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
result.files.operating = evaluateVersion(files.operating);
|
|
128
|
+
result.files.detSoul = evaluateVersion(files.detSoul);
|
|
129
|
+
result.files.compactor = evaluateVersion(files.compactor);
|
|
130
|
+
|
|
131
|
+
result.overlayEnabled = overlayEnabled();
|
|
132
|
+
|
|
133
|
+
const tokens = estimateSemanticTokens();
|
|
134
|
+
result.semanticTokens = tokens;
|
|
135
|
+
|
|
136
|
+
const hardLimit = parseHardLimit();
|
|
137
|
+
const riskThreshold = parseRiskThreshold();
|
|
138
|
+
|
|
139
|
+
result.limits.hardLimitConfigured = hardLimit;
|
|
140
|
+
result.limits.riskThresholdConfigured = riskThreshold;
|
|
141
|
+
|
|
142
|
+
if (hardLimit && hardLimit !== DEFAULT_HARD_LIMIT) {
|
|
143
|
+
result.limits.coherent = false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (riskThreshold && riskThreshold !== DEFAULT_RISK_THRESHOLD) {
|
|
147
|
+
result.limits.coherent = false;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const effectiveHardLimit = hardLimit || DEFAULT_HARD_LIMIT;
|
|
151
|
+
const effectiveRiskThreshold = riskThreshold || DEFAULT_RISK_THRESHOLD;
|
|
152
|
+
|
|
153
|
+
if (tokens > effectiveHardLimit) {
|
|
154
|
+
result.semanticStatus = "hard-limit-exceeded";
|
|
155
|
+
} else if (tokens > effectiveRiskThreshold) {
|
|
156
|
+
result.semanticStatus = "risk-threshold";
|
|
157
|
+
} else {
|
|
158
|
+
result.semanticStatus = "safe";
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function printHuman(result) {
|
|
165
|
+
console.log("\nRunning deterministic doctor...\n");
|
|
166
|
+
|
|
167
|
+
if (!result.openclawDetected) {
|
|
168
|
+
console.log("❌ OpenClaw directory not found.");
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (!result.workspaceDetected) {
|
|
173
|
+
console.log("❌ Workspace missing.");
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
for (const [name, info] of Object.entries(result.files)) {
|
|
178
|
+
const label =
|
|
179
|
+
name === "operating"
|
|
180
|
+
? "OPERATING_RULES.md"
|
|
181
|
+
: name === "detSoul"
|
|
182
|
+
? "SOUL.deterministic.md"
|
|
183
|
+
: "memory-compactor SKILL.md";
|
|
184
|
+
|
|
185
|
+
if (info.status === "missing") {
|
|
186
|
+
console.log(`❌ ${label} missing.`);
|
|
187
|
+
} else if (info.status === "no-stamp") {
|
|
188
|
+
console.log(`⚠ ${label} version stamp missing.`);
|
|
189
|
+
} else if (info.status === "mismatch") {
|
|
190
|
+
console.log(
|
|
191
|
+
`⚠ ${label} version mismatch (installed ${info.version}, CLI ${pkg.version})`
|
|
192
|
+
);
|
|
193
|
+
} else {
|
|
194
|
+
console.log(`✅ ${label} version matches CLI (${info.version})`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
94
197
|
|
|
95
|
-
if (exists(files.soul)) {
|
|
96
198
|
console.log("✅ SOUL.md present.");
|
|
97
|
-
|
|
98
|
-
|
|
199
|
+
console.log(
|
|
200
|
+
result.overlayEnabled
|
|
201
|
+
? "✅ Deterministic overlay ENABLED in SOUL.md."
|
|
202
|
+
: "⚠ Deterministic overlay NOT enabled in SOUL.md."
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
if (!result.limits.coherent) {
|
|
206
|
+
console.log("⚠ Threshold configuration drift detected in SKILL.md.");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
console.log(`\nSemantic memory tokens (est): ${result.semanticTokens}`);
|
|
210
|
+
|
|
211
|
+
if (result.semanticStatus === "hard-limit-exceeded") {
|
|
212
|
+
console.log("❌ Semantic memory exceeds HARD_LIMIT.");
|
|
213
|
+
} else if (result.semanticStatus === "risk-threshold") {
|
|
214
|
+
console.log("⚠ Semantic memory above risk threshold.");
|
|
99
215
|
} else {
|
|
100
|
-
console.log("
|
|
216
|
+
console.log("✅ Semantic memory within safe bounds.");
|
|
101
217
|
}
|
|
102
|
-
|
|
103
|
-
console.log("
|
|
218
|
+
|
|
219
|
+
console.log("\nDoctor complete.\n");
|
|
104
220
|
}
|
|
105
221
|
|
|
106
|
-
const
|
|
107
|
-
|
|
222
|
+
const result = evaluate();
|
|
223
|
+
|
|
224
|
+
if (JSON_MODE) {
|
|
225
|
+
console.log(JSON.stringify(result, null, 2));
|
|
226
|
+
|
|
227
|
+
if (!result.openclawDetected || !result.workspaceDetected) {
|
|
228
|
+
process.exit(2);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (result.semanticStatus === "hard-limit-exceeded") {
|
|
232
|
+
process.exit(3);
|
|
233
|
+
}
|
|
108
234
|
|
|
109
|
-
|
|
110
|
-
console.log("❌ Semantic memory exceeds HARD_LIMIT (1200).");
|
|
111
|
-
} else if (semanticTokens > 1020) {
|
|
112
|
-
console.log("⚠ Semantic memory above risk threshold (1020).");
|
|
113
|
-
} else {
|
|
114
|
-
console.log("✅ Semantic memory within safe bounds.");
|
|
235
|
+
process.exit(0);
|
|
115
236
|
}
|
|
116
237
|
|
|
117
|
-
|
|
238
|
+
printHuman(result);
|
|
118
239
|
process.exit(0);
|