@sdotwinter/openclaw-deterministic 0.5.1 → 0.7.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/audit.js +86 -0
- package/bin/cli.js +5 -0
- package/bin/doctor.js +72 -57
- package/bin/install.js +40 -21
- package/package.json +1 -1
package/bin/audit.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { execSync } = require("child_process");
|
|
6
|
+
|
|
7
|
+
const HOME = process.env.HOME;
|
|
8
|
+
const workspace = path.join(HOME, ".openclaw", "workspace");
|
|
9
|
+
|
|
10
|
+
const files = [
|
|
11
|
+
{
|
|
12
|
+
name: "OPERATING_RULES.md",
|
|
13
|
+
installed: path.join(workspace, "OPERATING_RULES.md"),
|
|
14
|
+
template: path.join(__dirname, "..", "templates", "OPERATING_RULES.md"),
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "SOUL.deterministic.md",
|
|
18
|
+
installed: path.join(workspace, "SOUL.deterministic.md"),
|
|
19
|
+
template: path.join(__dirname, "..", "templates", "SOUL.deterministic.md"),
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: "memory-compactor SKILL.md",
|
|
23
|
+
installed: path.join(workspace, "skills", "memory-compactor", "SKILL.md"),
|
|
24
|
+
template: path.join(__dirname, "..", "templates", "memory-compactor.SKILL.md"),
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
function exists(p) {
|
|
29
|
+
try {
|
|
30
|
+
fs.accessSync(p);
|
|
31
|
+
return true;
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log("\nRunning deterministic audit...\n");
|
|
38
|
+
|
|
39
|
+
let driftFound = false;
|
|
40
|
+
|
|
41
|
+
for (const file of files) {
|
|
42
|
+
if (!exists(file.installed)) {
|
|
43
|
+
console.log(`❌ ${file.name} missing in workspace.`);
|
|
44
|
+
driftFound = true;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!exists(file.template)) {
|
|
49
|
+
console.log(`❌ Template missing for ${file.name}.`);
|
|
50
|
+
driftFound = true;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const diff = execSync(
|
|
56
|
+
`diff -u "${file.template}" "${file.installed}"`,
|
|
57
|
+
{ stdio: "pipe" }
|
|
58
|
+
).toString();
|
|
59
|
+
|
|
60
|
+
if (diff.trim().length === 0) {
|
|
61
|
+
console.log(`✅ ${file.name} matches template.`);
|
|
62
|
+
} else {
|
|
63
|
+
console.log(`⚠ Drift detected in ${file.name}:\n`);
|
|
64
|
+
console.log(diff);
|
|
65
|
+
driftFound = true;
|
|
66
|
+
}
|
|
67
|
+
} catch (err) {
|
|
68
|
+
if (err.status === 1) {
|
|
69
|
+
console.log(`⚠ Drift detected in ${file.name}:\n`);
|
|
70
|
+
console.log(err.stdout.toString());
|
|
71
|
+
driftFound = true;
|
|
72
|
+
} else {
|
|
73
|
+
console.log(`❌ Error auditing ${file.name}`);
|
|
74
|
+
driftFound = true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!driftFound) {
|
|
80
|
+
console.log("\nNo drift detected. Files match canonical templates.");
|
|
81
|
+
} else {
|
|
82
|
+
console.log("\nAudit complete. Drift detected.");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.log("");
|
|
86
|
+
process.exit(0);
|
package/bin/cli.js
CHANGED
|
@@ -30,6 +30,10 @@ switch (command) {
|
|
|
30
30
|
case "revert":
|
|
31
31
|
require(path.join(__dirname, "revert"));
|
|
32
32
|
break;
|
|
33
|
+
|
|
34
|
+
case "audit":
|
|
35
|
+
require(path.join(__dirname, "audit"));
|
|
36
|
+
break;
|
|
33
37
|
|
|
34
38
|
case "--version":
|
|
35
39
|
case "-v":
|
|
@@ -57,6 +61,7 @@ function showHelp() {
|
|
|
57
61
|
console.log(" oc-deterministic install");
|
|
58
62
|
console.log(" oc-deterministic enable");
|
|
59
63
|
console.log(" oc-deterministic revert");
|
|
64
|
+
console.log(" oc-deterministic audit");
|
|
60
65
|
console.log(" oc-deterministic --version");
|
|
61
66
|
console.log(" oc-deterministic --help\n");
|
|
62
67
|
}
|
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
|
@@ -8,6 +8,8 @@ const openclawRoot = path.join(HOME, ".openclaw");
|
|
|
8
8
|
const workspace = path.join(openclawRoot, "workspace");
|
|
9
9
|
const backupsRoot = path.join(openclawRoot, "backups", "deterministic");
|
|
10
10
|
|
|
11
|
+
const pkg = require("../package.json");
|
|
12
|
+
|
|
11
13
|
const tpl = (name) => path.join(__dirname, "..", "templates", name);
|
|
12
14
|
|
|
13
15
|
const target = {
|
|
@@ -24,55 +26,67 @@ This system loads and adheres to SOUL.deterministic.md as a governing philosophi
|
|
|
24
26
|
`;
|
|
25
27
|
|
|
26
28
|
function exists(p) {
|
|
27
|
-
try {
|
|
29
|
+
try {
|
|
30
|
+
fs.accessSync(p);
|
|
31
|
+
return true;
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
function ensureDir(p) {
|
|
31
38
|
fs.mkdirSync(p, { recursive: true });
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
function
|
|
35
|
-
return fs.readFileSync(p, "utf8");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function write(p, content) {
|
|
41
|
+
function writeFile(p, content) {
|
|
39
42
|
ensureDir(path.dirname(p));
|
|
40
43
|
fs.writeFileSync(p, content);
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
fs.
|
|
46
|
+
function copyWithVersionStamp(templatePath, targetPath) {
|
|
47
|
+
const versionStamp = `<!-- Installed by openclaw-deterministic v${pkg.version} -->\n`;
|
|
48
|
+
const content = fs.readFileSync(templatePath, "utf8");
|
|
49
|
+
const stamped = versionStamp + content;
|
|
50
|
+
writeFile(targetPath, stamped);
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
function
|
|
49
|
-
return new Date().toISOString().
|
|
53
|
+
function timestamp() {
|
|
54
|
+
return new Date().toISOString().replace(/:/g, "-");
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
function backupSnapshot(pathsToBackup) {
|
|
53
58
|
ensureDir(backupsRoot);
|
|
54
|
-
const snap = path.join(backupsRoot,
|
|
59
|
+
const snap = path.join(backupsRoot, timestamp());
|
|
55
60
|
ensureDir(snap);
|
|
56
61
|
|
|
57
62
|
for (const p of pathsToBackup) {
|
|
58
63
|
if (!exists(p)) continue;
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
ensureDir(path.dirname(
|
|
62
|
-
fs.copyFileSync(p,
|
|
64
|
+
const relative = path.relative(openclawRoot, p);
|
|
65
|
+
const destination = path.join(snap, relative);
|
|
66
|
+
ensureDir(path.dirname(destination));
|
|
67
|
+
fs.copyFileSync(p, destination);
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
return snap;
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
function installTemplates() {
|
|
69
|
-
|
|
74
|
+
copyWithVersionStamp(
|
|
75
|
+
tpl("OPERATING_RULES.md"),
|
|
76
|
+
target.operating
|
|
77
|
+
);
|
|
70
78
|
console.log("Installed: OPERATING_RULES.md");
|
|
71
79
|
|
|
72
|
-
|
|
80
|
+
copyWithVersionStamp(
|
|
81
|
+
tpl("SOUL.deterministic.md"),
|
|
82
|
+
target.detSoul
|
|
83
|
+
);
|
|
73
84
|
console.log("Installed: SOUL.deterministic.md");
|
|
74
85
|
|
|
75
|
-
|
|
86
|
+
copyWithVersionStamp(
|
|
87
|
+
tpl("memory-compactor.SKILL.md"),
|
|
88
|
+
target.compactor
|
|
89
|
+
);
|
|
76
90
|
console.log("Installed: skills/memory-compactor/SKILL.md");
|
|
77
91
|
}
|
|
78
92
|
|
|
@@ -83,7 +97,7 @@ function bootstrapSoulIfMissing() {
|
|
|
83
97
|
}
|
|
84
98
|
|
|
85
99
|
console.log("No SOUL.md detected — bootstrapping fresh SOUL.md with deterministic overlay.");
|
|
86
|
-
|
|
100
|
+
writeFile(target.soul, OVERLAY_BLOCK.trim() + "\n");
|
|
87
101
|
console.log("Created: SOUL.md (deterministic overlay enabled by default)");
|
|
88
102
|
}
|
|
89
103
|
|
|
@@ -100,7 +114,12 @@ if (!exists(workspace)) {
|
|
|
100
114
|
}
|
|
101
115
|
|
|
102
116
|
console.log("Creating deterministic backup snapshot...");
|
|
103
|
-
const snap = backupSnapshot([
|
|
117
|
+
const snap = backupSnapshot([
|
|
118
|
+
target.operating,
|
|
119
|
+
target.detSoul,
|
|
120
|
+
target.soul,
|
|
121
|
+
target.compactor,
|
|
122
|
+
]);
|
|
104
123
|
console.log(`Backup location: ${snap}`);
|
|
105
124
|
|
|
106
125
|
installTemplates();
|