@sdotwinter/openclaw-deterministic 0.6.0 → 0.8.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 +72 -57
- package/bin/install.js +75 -32
- package/package.json +1 -1
package/bin/doctor.js
CHANGED
|
@@ -3,25 +3,19 @@
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
|
|
6
|
+
const pkg = require("../package.json");
|
|
7
|
+
|
|
6
8
|
const HOME = process.env.HOME;
|
|
7
|
-
const
|
|
9
|
+
const openclawRoot = path.join(HOME, ".openclaw");
|
|
10
|
+
const workspace = path.join(openclawRoot, "workspace");
|
|
8
11
|
|
|
9
|
-
const
|
|
12
|
+
const files = {
|
|
10
13
|
operating: path.join(workspace, "OPERATING_RULES.md"),
|
|
11
|
-
soul: path.join(workspace, "SOUL.md"),
|
|
12
14
|
detSoul: path.join(workspace, "SOUL.deterministic.md"),
|
|
15
|
+
soul: path.join(workspace, "SOUL.md"),
|
|
13
16
|
compactor: path.join(workspace, "skills", "memory-compactor", "SKILL.md"),
|
|
14
|
-
semantic: path.join(workspace, "memory", "semantic", "openclaw.md"),
|
|
15
17
|
};
|
|
16
18
|
|
|
17
|
-
const MARKER_OVERLAY = "## Deterministic Governance Overlay";
|
|
18
|
-
const MARKER_OPERATING_CANON = "Deterministic Execution Contract — Hardened Overlay";
|
|
19
|
-
const MARKER_DETSOUL_CANON = "Deterministic Governance Overlay — Canonical";
|
|
20
|
-
const MARKER_COMPACTOR_CANON = "## Hybrid Trigger Model";
|
|
21
|
-
|
|
22
|
-
const HARD_LIMIT = 1200;
|
|
23
|
-
const RISK_THRESHOLD = 1020;
|
|
24
|
-
|
|
25
19
|
function exists(p) {
|
|
26
20
|
try {
|
|
27
21
|
fs.accessSync(p);
|
|
@@ -35,68 +29,89 @@ function read(p) {
|
|
|
35
29
|
return fs.readFileSync(p, "utf8");
|
|
36
30
|
}
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const words = text.trim().split(/\s+/).filter(Boolean).length;
|
|
42
|
-
return Math.ceil(words * 1.3);
|
|
32
|
+
function versionFromFile(content) {
|
|
33
|
+
const match = content.match(/Installed by openclaw-deterministic v([0-9.]+)/);
|
|
34
|
+
return match ? match[1] : null;
|
|
43
35
|
}
|
|
44
36
|
|
|
45
|
-
function
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
function checkVersion(filePath, label) {
|
|
38
|
+
if (!exists(filePath)) {
|
|
39
|
+
console.log(`❌ ${label} missing.`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
48
42
|
|
|
49
|
-
|
|
43
|
+
const content = read(filePath);
|
|
44
|
+
const version = versionFromFile(content);
|
|
50
45
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
+
}
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
if (!exists(
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
function overlayEnabled() {
|
|
59
|
+
if (!exists(files.soul)) return false;
|
|
60
|
+
const content = read(files.soul);
|
|
61
|
+
return content.includes("SOUL.deterministic.md");
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
function estimateSemanticTokens() {
|
|
65
|
+
const semanticPath = path.join(
|
|
66
|
+
openclawRoot,
|
|
67
|
+
"workspace",
|
|
68
|
+
"memory",
|
|
69
|
+
"semantic",
|
|
70
|
+
"openclaw.md"
|
|
71
|
+
);
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
const operating = read(paths.operating);
|
|
70
|
-
if (operating.includes(MARKER_OPERATING_CANON)) ok("OPERATING_RULES.md matches canonical marker.");
|
|
71
|
-
else warn("OPERATING_RULES.md marker missing (file may be customized or outdated).");
|
|
73
|
+
if (!exists(semanticPath)) return 0;
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
const content = read(semanticPath);
|
|
76
|
+
return Math.ceil(content.length / 4);
|
|
77
|
+
}
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
if (detSoul.includes(MARKER_DETSOUL_CANON)) ok("SOUL.deterministic.md matches canonical marker.");
|
|
78
|
-
else warn("SOUL.deterministic.md marker missing (file may be customized or outdated).");
|
|
79
|
+
console.log("\nRunning deterministic doctor...\n");
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
if (!exists(openclawRoot)) {
|
|
82
|
+
console.log("❌ OpenClaw directory not found.");
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
83
85
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
if (!exists(workspace)) {
|
|
87
|
+
console.log("❌ Workspace missing.");
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
88
90
|
|
|
89
|
-
|
|
91
|
+
checkVersion(files.operating, "OPERATING_RULES.md");
|
|
92
|
+
checkVersion(files.detSoul, "SOUL.deterministic.md");
|
|
93
|
+
checkVersion(files.compactor, "memory-compactor SKILL.md");
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
if (exists(files.soul)) {
|
|
96
|
+
console.log("✅ SOUL.md present.");
|
|
97
|
+
if (overlayEnabled()) {
|
|
98
|
+
console.log("✅ Deterministic overlay ENABLED in SOUL.md.");
|
|
95
99
|
} else {
|
|
96
|
-
|
|
100
|
+
console.log("⚠ Deterministic overlay NOT enabled in SOUL.md.");
|
|
97
101
|
}
|
|
98
102
|
} else {
|
|
99
|
-
console.log("
|
|
103
|
+
console.log("⚠ SOUL.md not found.");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const semanticTokens = estimateSemanticTokens();
|
|
107
|
+
console.log(`\nSemantic memory tokens (est): ${semanticTokens}`);
|
|
108
|
+
|
|
109
|
+
if (semanticTokens > 1200) {
|
|
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.");
|
|
100
115
|
}
|
|
101
116
|
|
|
102
117
|
console.log("\nDoctor complete.\n");
|
package/bin/install.js
CHANGED
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
|
|
6
|
+
const pkg = require("../package.json");
|
|
7
|
+
|
|
6
8
|
const HOME = process.env.HOME;
|
|
7
9
|
const openclawRoot = path.join(HOME, ".openclaw");
|
|
8
10
|
const workspace = path.join(openclawRoot, "workspace");
|
|
9
11
|
const backupsRoot = path.join(openclawRoot, "backups", "deterministic");
|
|
10
12
|
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
const DRY_RUN = args.includes("--dry-run");
|
|
15
|
+
|
|
11
16
|
const tpl = (name) => path.join(__dirname, "..", "templates", name);
|
|
12
17
|
|
|
13
18
|
const target = {
|
|
@@ -24,56 +29,72 @@ This system loads and adheres to SOUL.deterministic.md as a governing philosophi
|
|
|
24
29
|
`;
|
|
25
30
|
|
|
26
31
|
function exists(p) {
|
|
27
|
-
try {
|
|
32
|
+
try {
|
|
33
|
+
fs.accessSync(p);
|
|
34
|
+
return true;
|
|
35
|
+
} catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
28
38
|
}
|
|
29
39
|
|
|
30
40
|
function ensureDir(p) {
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function read(p) {
|
|
35
|
-
return fs.readFileSync(p, "utf8");
|
|
41
|
+
if (!DRY_RUN) {
|
|
42
|
+
fs.mkdirSync(p, { recursive: true });
|
|
43
|
+
}
|
|
36
44
|
}
|
|
37
45
|
|
|
38
|
-
function
|
|
46
|
+
function writeFile(p, content) {
|
|
47
|
+
if (DRY_RUN) {
|
|
48
|
+
console.log(`[DRY-RUN] Would write: ${p}`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
39
51
|
ensureDir(path.dirname(p));
|
|
40
52
|
fs.writeFileSync(p, content);
|
|
41
53
|
}
|
|
42
54
|
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
fs.
|
|
55
|
+
function copyWithVersionStamp(templatePath, targetPath) {
|
|
56
|
+
const versionStamp = `<!-- Installed by openclaw-deterministic v${pkg.version} -->\n`;
|
|
57
|
+
const content = fs.readFileSync(templatePath, "utf8");
|
|
58
|
+
const stamped = versionStamp + content;
|
|
59
|
+
|
|
60
|
+
if (DRY_RUN) {
|
|
61
|
+
console.log(`[DRY-RUN] Would install: ${targetPath}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
writeFile(targetPath, stamped);
|
|
46
65
|
}
|
|
47
66
|
|
|
48
|
-
function
|
|
49
|
-
return new Date().toISOString().
|
|
67
|
+
function timestamp() {
|
|
68
|
+
return new Date().toISOString().replace(/:/g, "-");
|
|
50
69
|
}
|
|
51
70
|
|
|
52
71
|
function backupSnapshot(pathsToBackup) {
|
|
72
|
+
if (DRY_RUN) {
|
|
73
|
+
console.log("[DRY-RUN] Would create backup snapshot.");
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
53
77
|
ensureDir(backupsRoot);
|
|
54
|
-
const snap = path.join(backupsRoot,
|
|
78
|
+
const snap = path.join(backupsRoot, timestamp());
|
|
55
79
|
ensureDir(snap);
|
|
56
80
|
|
|
57
81
|
for (const p of pathsToBackup) {
|
|
58
82
|
if (!exists(p)) continue;
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
83
|
+
|
|
84
|
+
const relative = path.relative(openclawRoot, p);
|
|
85
|
+
const destination = path.join(snap, relative);
|
|
86
|
+
|
|
87
|
+
ensureDir(path.dirname(destination));
|
|
88
|
+
fs.copyFileSync(p, destination);
|
|
63
89
|
}
|
|
64
90
|
|
|
65
91
|
return snap;
|
|
66
92
|
}
|
|
67
93
|
|
|
68
94
|
function installTemplates() {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
copyFile(tpl("SOUL.deterministic.md"), target.detSoul);
|
|
73
|
-
console.log("Installed: SOUL.deterministic.md");
|
|
74
|
-
|
|
75
|
-
copyFile(tpl("memory-compactor.SKILL.md"), target.compactor);
|
|
76
|
-
console.log("Installed: skills/memory-compactor/SKILL.md");
|
|
95
|
+
copyWithVersionStamp(tpl("OPERATING_RULES.md"), target.operating);
|
|
96
|
+
copyWithVersionStamp(tpl("SOUL.deterministic.md"), target.detSoul);
|
|
97
|
+
copyWithVersionStamp(tpl("memory-compactor.SKILL.md"), target.compactor);
|
|
77
98
|
}
|
|
78
99
|
|
|
79
100
|
function bootstrapSoulIfMissing() {
|
|
@@ -83,28 +104,50 @@ function bootstrapSoulIfMissing() {
|
|
|
83
104
|
}
|
|
84
105
|
|
|
85
106
|
console.log("No SOUL.md detected — bootstrapping fresh SOUL.md with deterministic overlay.");
|
|
86
|
-
|
|
107
|
+
|
|
108
|
+
if (DRY_RUN) {
|
|
109
|
+
console.log("[DRY-RUN] Would create SOUL.md with deterministic overlay.");
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
writeFile(target.soul, OVERLAY_BLOCK.trim() + "\n");
|
|
87
114
|
console.log("Created: SOUL.md (deterministic overlay enabled by default)");
|
|
88
115
|
}
|
|
89
116
|
|
|
90
117
|
if (!exists(openclawRoot)) {
|
|
91
118
|
console.error("OpenClaw not found at ~/.openclaw");
|
|
92
|
-
console.error("Install OpenClaw first, then rerun oc-deterministic install.");
|
|
93
119
|
process.exit(1);
|
|
94
120
|
}
|
|
95
121
|
|
|
96
122
|
if (!exists(workspace)) {
|
|
97
123
|
console.error("OpenClaw workspace missing at ~/.openclaw/workspace");
|
|
98
|
-
console.error("OpenClaw may not be fully initialized. Run `openclaw onboard` then retry.");
|
|
99
124
|
process.exit(1);
|
|
100
125
|
}
|
|
101
126
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
127
|
+
if (DRY_RUN) {
|
|
128
|
+
console.log("\nRunning deterministic install (dry-run mode)...\n");
|
|
129
|
+
} else {
|
|
130
|
+
console.log("Creating deterministic backup snapshot...");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const snap = backupSnapshot([
|
|
134
|
+
target.operating,
|
|
135
|
+
target.detSoul,
|
|
136
|
+
target.soul,
|
|
137
|
+
target.compactor,
|
|
138
|
+
]);
|
|
139
|
+
|
|
140
|
+
if (snap) {
|
|
141
|
+
console.log(`Backup location: ${snap}`);
|
|
142
|
+
}
|
|
105
143
|
|
|
106
144
|
installTemplates();
|
|
107
145
|
bootstrapSoulIfMissing();
|
|
108
146
|
|
|
109
|
-
|
|
147
|
+
if (DRY_RUN) {
|
|
148
|
+
console.log("\nDry-run complete. No changes were written.\n");
|
|
149
|
+
} else {
|
|
150
|
+
console.log("\nDeterministic governance installed successfully.\n");
|
|
151
|
+
}
|
|
152
|
+
|
|
110
153
|
process.exit(0);
|