principles-disciple 1.197.2 → 1.197.4
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/assets/logo.svg +11 -0
- package/dist/assets/logo.svg +11 -0
- package/dist/bundle.js +382 -382
- package/dist/openclaw.plugin.json +2 -2
- package/openclaw.plugin.json +2 -2
- package/package.json +5 -4
- package/scripts/postinstall.cjs +177 -0
- package/dist/core/bootstrap-rules.js +0 -187790
- package/dist/core/principle-compiler/index.js +0 -188823
- package/dist/core/principle-training-state.js +0 -511
- package/dist/core/principle-tree-ledger.js +0 -658
- package/dist/core/trajectory/index.js +0 -189181
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "principles-disciple",
|
|
3
3
|
"name": "Principles Disciple",
|
|
4
|
-
"description": "
|
|
5
|
-
"version": "1.197.
|
|
4
|
+
"description": "Turn repeated Agent corrections into Owner-approved, observable, reversible behavior principles. Stop correcting the same AI behavior across sessions.",
|
|
5
|
+
"version": "1.197.4",
|
|
6
6
|
"activation": {
|
|
7
7
|
"onCapabilities": [
|
|
8
8
|
"hook"
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "principles-disciple",
|
|
3
3
|
"name": "Principles Disciple",
|
|
4
|
-
"description": "
|
|
5
|
-
"version": "1.197.
|
|
4
|
+
"description": "Turn repeated Agent corrections into Owner-approved, observable, reversible behavior principles. Stop correcting the same AI behavior across sessions.",
|
|
5
|
+
"version": "1.197.4",
|
|
6
6
|
"activation": {
|
|
7
7
|
"onCapabilities": [
|
|
8
8
|
"hook"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "principles-disciple",
|
|
3
|
-
"version": "1.197.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.197.4",
|
|
4
|
+
"description": "Turn repeated Agent corrections into Owner-approved, observable, reversible behavior principles. Stop correcting the same AI behavior across sessions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"dist",
|
|
27
27
|
"scripts",
|
|
28
28
|
"templates",
|
|
29
|
+
"assets",
|
|
29
30
|
"openclaw.plugin.json"
|
|
30
31
|
],
|
|
31
32
|
"publishConfig": {
|
|
@@ -43,13 +44,13 @@
|
|
|
43
44
|
"./dist/bundle.js"
|
|
44
45
|
],
|
|
45
46
|
"compat": {
|
|
46
|
-
"pluginApi": "2026.4.4"
|
|
47
|
+
"pluginApi": ">=2026.4.4"
|
|
47
48
|
},
|
|
48
49
|
"build": {
|
|
49
50
|
"openclawVersion": "2026.4.4"
|
|
50
51
|
},
|
|
51
52
|
"install": {
|
|
52
|
-
"minHostVersion": "2026.4.4"
|
|
53
|
+
"minHostVersion": ">=2026.4.4"
|
|
53
54
|
}
|
|
54
55
|
},
|
|
55
56
|
"scripts": {
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* PRI-343: postinstall hook — auto-configure allowConversationAccess.
|
|
4
|
+
*
|
|
5
|
+
* Runs during `npm install` (i.e. `openclaw plugins install principles-disciple`).
|
|
6
|
+
* Sets plugins.entries['principles-disciple'].hooks.allowConversationAccess = true
|
|
7
|
+
* in ~/.openclaw/openclaw.json so users never need to manually run
|
|
8
|
+
* `openclaw config set ... allowConversationAccess true`.
|
|
9
|
+
*
|
|
10
|
+
* Design constraints:
|
|
11
|
+
* - Idempotent: safe to run multiple times.
|
|
12
|
+
* - BOM-resistant: strip U+FEFF before JSON.parse (PowerShell UTF8 writes add BOM).
|
|
13
|
+
* - Atomic write: temp file + rename to avoid partial writes.
|
|
14
|
+
* - File-locked: uses O_EXCL lock file to prevent races with concurrent writers.
|
|
15
|
+
* - Never fail the install: all errors are caught and logged to stderr.
|
|
16
|
+
* - No dependencies: pure Node.js built-ins (fs, path, os).
|
|
17
|
+
*/
|
|
18
|
+
'use strict';
|
|
19
|
+
|
|
20
|
+
const { existsSync, readFileSync, writeFileSync, renameSync, unlinkSync, openSync, closeSync, statSync, writeSync, fsyncSync, constants } = require('fs');
|
|
21
|
+
const { join } = require('path');
|
|
22
|
+
const { homedir } = require('os');
|
|
23
|
+
|
|
24
|
+
const PLUGIN_ID = 'principles-disciple';
|
|
25
|
+
const CONFIG_PATH = join(homedir(), '.openclaw', 'openclaw.json');
|
|
26
|
+
const LOCK_PATH = CONFIG_PATH + '.lock';
|
|
27
|
+
const LOCK_MAX_RETRIES = 20;
|
|
28
|
+
const LOCK_BASE_DELAY_MS = 25;
|
|
29
|
+
|
|
30
|
+
function log(msg) {
|
|
31
|
+
process.stderr.write(`[PD:postinstall] ${msg}\n`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function isRecord(value) {
|
|
35
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isProcessAlive(pid) {
|
|
39
|
+
try {
|
|
40
|
+
process.kill(pid, 0);
|
|
41
|
+
return true;
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function tryAcquireLock() {
|
|
48
|
+
try {
|
|
49
|
+
const flags = constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL;
|
|
50
|
+
const fd = openSync(LOCK_PATH, flags, 0o600);
|
|
51
|
+
try {
|
|
52
|
+
writeSync(fd, String(process.pid));
|
|
53
|
+
fsyncSync(fd);
|
|
54
|
+
} finally {
|
|
55
|
+
closeSync(fd);
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
} catch (err) {
|
|
59
|
+
if (err.code === 'EEXIST') return false;
|
|
60
|
+
throw err;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function readLockPid() {
|
|
65
|
+
try {
|
|
66
|
+
const content = readFileSync(LOCK_PATH, 'utf8');
|
|
67
|
+
const pid = parseInt(content.trim(), 10);
|
|
68
|
+
return Number.isNaN(pid) ? null : pid;
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function cleanupStaleLock() {
|
|
75
|
+
try {
|
|
76
|
+
const stat = statSync(LOCK_PATH);
|
|
77
|
+
const pid = readLockPid();
|
|
78
|
+
const isStale = Date.now() - stat.mtimeMs > 10000;
|
|
79
|
+
const isDead = pid === null || !isProcessAlive(pid);
|
|
80
|
+
if (isStale || isDead) {
|
|
81
|
+
try {
|
|
82
|
+
unlinkSync(LOCK_PATH);
|
|
83
|
+
return true;
|
|
84
|
+
} catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
} catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function acquireLockSync() {
|
|
95
|
+
for (let attempt = 0; attempt < LOCK_MAX_RETRIES; attempt++) {
|
|
96
|
+
if (tryAcquireLock()) return true;
|
|
97
|
+
if (!cleanupStaleLock()) {
|
|
98
|
+
const delay = LOCK_BASE_DELAY_MS * Math.pow(2, Math.min(attempt, 5));
|
|
99
|
+
const jitter = delay * 0.2 * Math.random();
|
|
100
|
+
const waitUntil = Date.now() + delay + jitter;
|
|
101
|
+
while (Date.now() < waitUntil) { /* spin */ }
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (tryAcquireLock()) return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function releaseLock() {
|
|
110
|
+
try {
|
|
111
|
+
const pid = readLockPid();
|
|
112
|
+
if (pid === process.pid) {
|
|
113
|
+
unlinkSync(LOCK_PATH);
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
// best effort
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
122
|
+
log(`No openclaw.json at ${CONFIG_PATH} — skipping (will auto-fix on first load).`);
|
|
123
|
+
process.exit(0);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const locked = acquireLockSync();
|
|
127
|
+
if (!locked) {
|
|
128
|
+
log(`Could not acquire config lock — skipping (will auto-fix on first load).`);
|
|
129
|
+
process.exit(0);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
let exitCode = 0;
|
|
133
|
+
try {
|
|
134
|
+
// BOM-resistant read
|
|
135
|
+
const raw = readFileSync(CONFIG_PATH, 'utf8').replace(/^\uFEFF/, '');
|
|
136
|
+
const cfg = JSON.parse(raw);
|
|
137
|
+
|
|
138
|
+
if (!isRecord(cfg)) {
|
|
139
|
+
log(`openclaw.json is not a JSON object — skipping.`);
|
|
140
|
+
} else {
|
|
141
|
+
// Ensure plugins.entries path exists
|
|
142
|
+
if (!isRecord(cfg.plugins)) cfg.plugins = {};
|
|
143
|
+
if (!isRecord(cfg.plugins.entries)) cfg.plugins.entries = {};
|
|
144
|
+
|
|
145
|
+
const rawEntry = cfg.plugins.entries[PLUGIN_ID];
|
|
146
|
+
const entry = isRecord(rawEntry) ? rawEntry : { enabled: true };
|
|
147
|
+
|
|
148
|
+
if (!isRecord(entry.hooks)) entry.hooks = {};
|
|
149
|
+
|
|
150
|
+
if (entry.hooks.allowConversationAccess !== true) {
|
|
151
|
+
// Set allowConversationAccess = true
|
|
152
|
+
entry.hooks.allowConversationAccess = true;
|
|
153
|
+
cfg.plugins.entries[PLUGIN_ID] = entry;
|
|
154
|
+
|
|
155
|
+
// Atomic write: temp file + rename
|
|
156
|
+
const tmpPath = CONFIG_PATH + '.tmp.' + Date.now();
|
|
157
|
+
writeFileSync(tmpPath, JSON.stringify(cfg, null, 2), 'utf8');
|
|
158
|
+
renameSync(tmpPath, CONFIG_PATH);
|
|
159
|
+
|
|
160
|
+
log(`allowConversationAccess auto-configured to true in ${CONFIG_PATH}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
} catch (innerErr) {
|
|
164
|
+
log(`Auto-configuration failed: ${innerErr instanceof Error ? innerErr.message : String(innerErr)}`);
|
|
165
|
+
log(`The plugin will retry on first load. If it still fails, run:`);
|
|
166
|
+
log(` openclaw config set plugins.entries.principles-disciple.hooks.allowConversationAccess true`);
|
|
167
|
+
} finally {
|
|
168
|
+
releaseLock();
|
|
169
|
+
}
|
|
170
|
+
process.exit(exitCode);
|
|
171
|
+
} catch (err) {
|
|
172
|
+
// Never fail the install — the plugin's module-level auto-fix will retry on load.
|
|
173
|
+
log(`Auto-configuration failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
174
|
+
log(`The plugin will retry on first load. If it still fails, run:`);
|
|
175
|
+
log(` openclaw config set plugins.entries.principles-disciple.hooks.allowConversationAccess true`);
|
|
176
|
+
process.exit(0);
|
|
177
|
+
}
|