create-principles-disciple 1.112.0 → 1.112.2
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/package.json +2 -2
- package/pd-cli/dist/commands/legacy-cleanup.d.ts.map +1 -1
- package/pd-cli/dist/commands/legacy-cleanup.js +19 -2
- package/pd-cli/dist/commands/legacy-cleanup.js.map +1 -1
- package/pd-cli/dist/commands/pain-evidence.d.ts +3 -1
- package/pd-cli/dist/commands/pain-evidence.d.ts.map +1 -1
- package/pd-cli/dist/commands/pain-evidence.js +12 -3
- package/pd-cli/dist/commands/pain-evidence.js.map +1 -1
- package/pd-cli/dist/commands/rulecode.d.ts +13 -0
- package/pd-cli/dist/commands/rulecode.d.ts.map +1 -1
- package/pd-cli/dist/commands/rulecode.js +23 -2
- package/pd-cli/dist/commands/rulecode.js.map +1 -1
- package/pd-cli/dist/resolve-workspace.d.ts.map +1 -1
- package/pd-cli/dist/resolve-workspace.js +33 -12
- package/pd-cli/dist/resolve-workspace.js.map +1 -1
- package/pd-cli/dist/services/console-launcher.d.ts +8 -1
- package/pd-cli/dist/services/console-launcher.d.ts.map +1 -1
- package/pd-cli/dist/services/console-launcher.js +45 -3
- package/pd-cli/dist/services/console-launcher.js.map +1 -1
- package/pd-cli/dist/services/pd-config-loader.d.ts.map +1 -1
- package/pd-cli/dist/services/pd-config-loader.js +34 -1
- package/pd-cli/dist/services/pd-config-loader.js.map +1 -1
- package/pd-cli/dist/services/quality-scorecard/strong-model-gate.d.ts +19 -0
- package/pd-cli/dist/services/quality-scorecard/strong-model-gate.d.ts.map +1 -1
- package/pd-cli/dist/services/quality-scorecard/strong-model-gate.js +44 -2
- package/pd-cli/dist/services/quality-scorecard/strong-model-gate.js.map +1 -1
- package/pd-cli/dist/utils/path-security.d.ts +60 -0
- package/pd-cli/dist/utils/path-security.d.ts.map +1 -0
- package/pd-cli/dist/utils/path-security.js +90 -0
- package/pd-cli/dist/utils/path-security.js.map +1 -0
- package/plugin/dist/bundle.js +13 -11
- package/plugin/dist/constants/tools.d.ts +1 -1
- package/plugin/dist/hooks/prompt-helpers.d.ts +5 -5
- package/plugin/dist/templates/langs/en/core/AGENTS.md +40 -180
- package/plugin/dist/templates/langs/en/core/BOOT.md +19 -47
- package/plugin/dist/templates/langs/en/core/HEARTBEAT.md +26 -58
- package/plugin/dist/templates/langs/en/core/IDENTITY.md +15 -8
- package/plugin/dist/templates/langs/en/core/PRINCIPLES.md +6 -7
- package/plugin/dist/templates/langs/en/core/SOUL.md +10 -41
- package/plugin/dist/templates/langs/en/core/TOOLS.md +18 -10
- package/plugin/dist/templates/langs/en/core/USER.md +13 -8
- package/plugin/dist/templates/langs/en/skills/pd-auditor/SKILL.md +1 -1
- package/plugin/dist/templates/langs/en/skills/pd-explorer/SKILL.md +1 -1
- package/plugin/dist/templates/langs/en/skills/pd-implementer/SKILL.md +1 -1
- package/plugin/dist/templates/langs/en/skills/pd-mentor/SKILL.md +6 -30
- package/plugin/dist/templates/langs/en/skills/pd-planner/SKILL.md +1 -1
- package/plugin/dist/templates/langs/zh/core/AGENTS.md +38 -173
- package/plugin/dist/templates/langs/zh/core/BOOT.md +14 -46
- package/plugin/dist/templates/langs/zh/core/HEARTBEAT.md +20 -82
- package/plugin/dist/templates/langs/zh/core/IDENTITY.md +15 -8
- package/plugin/dist/templates/langs/zh/core/PRINCIPLES.md +7 -7
- package/plugin/dist/templates/langs/zh/core/SOUL.md +9 -41
- package/plugin/dist/templates/langs/zh/core/TOOLS.md +14 -10
- package/plugin/dist/templates/langs/zh/core/USER.md +12 -8
- package/plugin/dist/templates/langs/zh/skills/pd-auditor/SKILL.md +1 -1
- package/plugin/dist/templates/langs/zh/skills/pd-explorer/SKILL.md +1 -1
- package/plugin/dist/templates/langs/zh/skills/pd-implementer/SKILL.md +1 -1
- package/plugin/dist/templates/langs/zh/skills/pd-mentor/SKILL.md +6 -30
- package/plugin/dist/templates/langs/zh/skills/pd-planner/SKILL.md +1 -1
- package/plugin/dist/templates/pain_settings.json +1 -2
- package/plugin/openclaw.plugin.json +1 -1
- package/plugin/package.json +1 -2
- package/plugin/templates/langs/en/core/AGENTS.md +40 -180
- package/plugin/templates/langs/en/core/BOOT.md +19 -47
- package/plugin/templates/langs/en/core/HEARTBEAT.md +26 -58
- package/plugin/templates/langs/en/core/IDENTITY.md +15 -8
- package/plugin/templates/langs/en/core/PRINCIPLES.md +6 -7
- package/plugin/templates/langs/en/core/SOUL.md +10 -41
- package/plugin/templates/langs/en/core/TOOLS.md +18 -10
- package/plugin/templates/langs/en/core/USER.md +13 -8
- package/plugin/templates/langs/en/skills/pd-auditor/SKILL.md +1 -1
- package/plugin/templates/langs/en/skills/pd-explorer/SKILL.md +1 -1
- package/plugin/templates/langs/en/skills/pd-implementer/SKILL.md +1 -1
- package/plugin/templates/langs/en/skills/pd-mentor/SKILL.md +6 -30
- package/plugin/templates/langs/en/skills/pd-planner/SKILL.md +1 -1
- package/plugin/templates/langs/zh/core/AGENTS.md +38 -173
- package/plugin/templates/langs/zh/core/BOOT.md +14 -46
- package/plugin/templates/langs/zh/core/HEARTBEAT.md +20 -82
- package/plugin/templates/langs/zh/core/IDENTITY.md +15 -8
- package/plugin/templates/langs/zh/core/PRINCIPLES.md +7 -7
- package/plugin/templates/langs/zh/core/SOUL.md +9 -41
- package/plugin/templates/langs/zh/core/TOOLS.md +14 -10
- package/plugin/templates/langs/zh/core/USER.md +12 -8
- package/plugin/templates/langs/zh/skills/pd-auditor/SKILL.md +1 -1
- package/plugin/templates/langs/zh/skills/pd-explorer/SKILL.md +1 -1
- package/plugin/templates/langs/zh/skills/pd-implementer/SKILL.md +1 -1
- package/plugin/templates/langs/zh/skills/pd-mentor/SKILL.md +6 -30
- package/plugin/templates/langs/zh/skills/pd-planner/SKILL.md +1 -1
- package/plugin/templates/pain_settings.json +1 -2
- package/plugin/dist/templates/langs/en/core/BOOTSTRAP.md +0 -259
- package/plugin/dist/templates/langs/en/skills/admin/SKILL.md +0 -39
- package/plugin/dist/templates/langs/en/skills/bootstrap-tools/SKILL.md +0 -53
- package/plugin/dist/templates/langs/en/skills/deductive-audit/SKILL.md +0 -36
- package/plugin/dist/templates/langs/en/skills/evolution-framework-update/SKILL.md +0 -31
- package/plugin/dist/templates/langs/en/skills/evolve-task/SKILL.md +0 -83
- package/plugin/dist/templates/langs/en/skills/feedback/SKILL.md +0 -51
- package/plugin/dist/templates/langs/en/skills/init-strategy/SKILL.md +0 -54
- package/plugin/dist/templates/langs/en/skills/inject-rule/SKILL.md +0 -19
- package/plugin/dist/templates/langs/en/skills/profile/SKILL.md +0 -24
- package/plugin/dist/templates/langs/en/skills/reflection/SKILL.md +0 -40
- package/plugin/dist/templates/langs/en/skills/reflection-log/SKILL.md +0 -37
- package/plugin/dist/templates/langs/en/skills/report/SKILL.md +0 -13
- package/plugin/dist/templates/langs/en/skills/root-cause/SKILL.md +0 -33
- package/plugin/dist/templates/langs/en/skills/triage/SKILL.md +0 -29
- package/plugin/dist/templates/langs/en/skills/watch-evolution/SKILL.md +0 -33
- package/plugin/dist/templates/langs/zh/core/BOOTSTRAP.md +0 -260
- package/plugin/dist/templates/langs/zh/skills/admin/SKILL.md +0 -41
- package/plugin/dist/templates/langs/zh/skills/bootstrap-tools/SKILL.md +0 -52
- package/plugin/dist/templates/langs/zh/skills/deductive-audit/SKILL.md +0 -36
- package/plugin/dist/templates/langs/zh/skills/evolution-framework-update/SKILL.md +0 -31
- package/plugin/dist/templates/langs/zh/skills/evolve-task/SKILL.md +0 -83
- package/plugin/dist/templates/langs/zh/skills/feedback/SKILL.md +0 -53
- package/plugin/dist/templates/langs/zh/skills/init-strategy/SKILL.md +0 -54
- package/plugin/dist/templates/langs/zh/skills/inject-rule/SKILL.md +0 -19
- package/plugin/dist/templates/langs/zh/skills/profile/SKILL.md +0 -24
- package/plugin/dist/templates/langs/zh/skills/reflection/SKILL.md +0 -40
- package/plugin/dist/templates/langs/zh/skills/reflection-log/SKILL.md +0 -37
- package/plugin/dist/templates/langs/zh/skills/report/SKILL.md +0 -13
- package/plugin/dist/templates/langs/zh/skills/root-cause/SKILL.md +0 -33
- package/plugin/dist/templates/langs/zh/skills/triage/SKILL.md +0 -29
- package/plugin/dist/templates/langs/zh/skills/watch-evolution/SKILL.md +0 -33
- package/plugin/scripts/acceptance-test.mjs +0 -257
- package/plugin/scripts/bootstrap-rules.mjs +0 -70
- package/plugin/scripts/compile-principles.mjs +0 -104
- package/plugin/scripts/install-dependencies.cjs +0 -47
- package/plugin/scripts/postinstall.cjs +0 -177
- package/plugin/scripts/sync-plugin.mjs +0 -1442
- package/plugin/scripts/verify-build.mjs +0 -120
- package/plugin/templates/langs/en/core/BOOTSTRAP.md +0 -259
- package/plugin/templates/langs/en/skills/admin/SKILL.md +0 -39
- package/plugin/templates/langs/en/skills/bootstrap-tools/SKILL.md +0 -53
- package/plugin/templates/langs/en/skills/deductive-audit/SKILL.md +0 -36
- package/plugin/templates/langs/en/skills/evolution-framework-update/SKILL.md +0 -31
- package/plugin/templates/langs/en/skills/evolve-task/SKILL.md +0 -83
- package/plugin/templates/langs/en/skills/feedback/SKILL.md +0 -51
- package/plugin/templates/langs/en/skills/init-strategy/SKILL.md +0 -54
- package/plugin/templates/langs/en/skills/inject-rule/SKILL.md +0 -19
- package/plugin/templates/langs/en/skills/profile/SKILL.md +0 -24
- package/plugin/templates/langs/en/skills/reflection/SKILL.md +0 -40
- package/plugin/templates/langs/en/skills/reflection-log/SKILL.md +0 -37
- package/plugin/templates/langs/en/skills/report/SKILL.md +0 -13
- package/plugin/templates/langs/en/skills/root-cause/SKILL.md +0 -33
- package/plugin/templates/langs/en/skills/triage/SKILL.md +0 -29
- package/plugin/templates/langs/en/skills/watch-evolution/SKILL.md +0 -33
- package/plugin/templates/langs/zh/core/BOOTSTRAP.md +0 -260
- package/plugin/templates/langs/zh/skills/admin/SKILL.md +0 -41
- package/plugin/templates/langs/zh/skills/bootstrap-tools/SKILL.md +0 -52
- package/plugin/templates/langs/zh/skills/deductive-audit/SKILL.md +0 -36
- package/plugin/templates/langs/zh/skills/evolution-framework-update/SKILL.md +0 -31
- package/plugin/templates/langs/zh/skills/evolve-task/SKILL.md +0 -83
- package/plugin/templates/langs/zh/skills/feedback/SKILL.md +0 -53
- package/plugin/templates/langs/zh/skills/init-strategy/SKILL.md +0 -54
- package/plugin/templates/langs/zh/skills/inject-rule/SKILL.md +0 -19
- package/plugin/templates/langs/zh/skills/profile/SKILL.md +0 -24
- package/plugin/templates/langs/zh/skills/reflection/SKILL.md +0 -40
- package/plugin/templates/langs/zh/skills/reflection-log/SKILL.md +0 -37
- package/plugin/templates/langs/zh/skills/report/SKILL.md +0 -13
- package/plugin/templates/langs/zh/skills/root-cause/SKILL.md +0 -33
- package/plugin/templates/langs/zh/skills/triage/SKILL.md +0 -29
- package/plugin/templates/langs/zh/skills/watch-evolution/SKILL.md +0 -33
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* PD Pipeline — End-to-End Acceptance Test
|
|
5
|
-
*
|
|
6
|
-
* Verifies that all components of the PD reflection pipeline
|
|
7
|
-
* work correctly in a real environment (not unit tests).
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* node scripts/acceptance-test.mjs --workspace /path/to/workspace
|
|
11
|
-
*
|
|
12
|
-
* Output: Pass/Fail for each checkpoint with detailed diagnostics.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { existsSync, readFileSync, writeFileSync, rmSync, mkdirSync, readdirSync } from 'fs';
|
|
16
|
-
import { join, dirname } from 'path';
|
|
17
|
-
import { fileURLToPath } from 'url';
|
|
18
|
-
import { execFileSync } from 'child_process';
|
|
19
|
-
|
|
20
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
21
|
-
const __dirname = dirname(__filename);
|
|
22
|
-
|
|
23
|
-
// ─── Helpers ───
|
|
24
|
-
let passCount = 0;
|
|
25
|
-
let failCount = 0;
|
|
26
|
-
let warnCount = 0;
|
|
27
|
-
|
|
28
|
-
function assert(condition, testName, detail = '') {
|
|
29
|
-
if (condition) {
|
|
30
|
-
console.log(` ✅ ${testName}`);
|
|
31
|
-
passCount++;
|
|
32
|
-
} else {
|
|
33
|
-
console.log(` ❌ ${testName}${detail ? ` — ${detail}` : ''}`);
|
|
34
|
-
failCount++;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function warn(testName, detail = '') {
|
|
39
|
-
console.log(` ⚠️ ${testName}${detail ? ` — ${detail}` : ''}`);
|
|
40
|
-
warnCount++;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function runSql(dbPath, sql) {
|
|
44
|
-
return execFileSync('sqlite3', [dbPath, sql], {
|
|
45
|
-
encoding: 'utf-8',
|
|
46
|
-
timeout: 5000,
|
|
47
|
-
}).trim();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ─── Parse workspace ───
|
|
51
|
-
function parseArgs() {
|
|
52
|
-
const argv = process.argv.slice(2);
|
|
53
|
-
for (let i = 0; i < argv.length; i++) {
|
|
54
|
-
if (argv[i] === '--workspace' && argv[i + 1]) return argv[++i];
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
return execFileSync('git', ['rev-parse', '--show-toplevel'], { encoding: 'utf-8' }).trim();
|
|
58
|
-
} catch {
|
|
59
|
-
return process.cwd();
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// ─── Main ───
|
|
64
|
-
function main() {
|
|
65
|
-
const workspaceDir = parseArgs();
|
|
66
|
-
const stateDir = join(workspaceDir, '.state');
|
|
67
|
-
const dbPath = join(stateDir, 'trajectory.db');
|
|
68
|
-
|
|
69
|
-
if (!existsSync(dbPath)) {
|
|
70
|
-
console.error('❌ trajectory.db not found. Run seed script first.');
|
|
71
|
-
process.exit(1);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
console.log('\n🧪 PD Pipeline Acceptance Test');
|
|
75
|
-
console.log('═'.repeat(55));
|
|
76
|
-
console.log(`Workspace: ${workspaceDir}`);
|
|
77
|
-
console.log(`Database: ${dbPath}\n`);
|
|
78
|
-
|
|
79
|
-
// ═══════════════════════════════════════════════
|
|
80
|
-
// SECTION 1: Seed Scenario Data Integrity
|
|
81
|
-
// ═══════════════════════════════════════════════
|
|
82
|
-
console.log('── 1. Seed Scenario Data Integrity ──');
|
|
83
|
-
|
|
84
|
-
// 1.1 Count seed sessions
|
|
85
|
-
const sessionCount = parseInt(runSql(dbPath, "SELECT COUNT(*) FROM sessions WHERE session_id LIKE 'seed-%';"));
|
|
86
|
-
assert(sessionCount === 10, '10 seed sessions exist', `found ${sessionCount}`);
|
|
87
|
-
|
|
88
|
-
// 1.2 Count seed pain events
|
|
89
|
-
const painCount = parseInt(runSql(dbPath, "SELECT COUNT(*) FROM pain_events WHERE session_id LIKE 'seed-%';"));
|
|
90
|
-
assert(painCount >= 10, 'Pain events exist for seed sessions', `found ${painCount}`);
|
|
91
|
-
|
|
92
|
-
// 1.3 Verify signal diversity
|
|
93
|
-
const sources = runSql(dbPath, "SELECT DISTINCT source FROM pain_events WHERE session_id LIKE 'seed-%';").split('\n');
|
|
94
|
-
assert(sources.includes('tool_failure'), 'tool_failure signal present');
|
|
95
|
-
assert(sources.includes('user_empathy'), 'user_empathy signal present');
|
|
96
|
-
|
|
97
|
-
// 1.4 Verify pain event scores are in valid range
|
|
98
|
-
const invalidScores = runSql(dbPath, "SELECT COUNT(*) FROM pain_events WHERE session_id LIKE 'seed-%' AND (score < 0 OR score > 100);");
|
|
99
|
-
assert(parseInt(invalidScores) === 0, 'All pain scores in 0-100 range', `${invalidScores} invalid`);
|
|
100
|
-
|
|
101
|
-
// 1.5 Verify correction cues exist
|
|
102
|
-
const correctionCount = parseInt(runSql(dbPath, "SELECT COUNT(*) FROM user_turns WHERE session_id LIKE 'seed-%' AND correction_detected = 1;"));
|
|
103
|
-
assert(correctionCount >= 5, 'Multiple correction cues present', `found ${correctionCount}`);
|
|
104
|
-
|
|
105
|
-
// 1.6 Verify tool calls (both success and failure)
|
|
106
|
-
const failureCalls = parseInt(runSql(dbPath, "SELECT COUNT(*) FROM tool_calls WHERE session_id LIKE 'seed-%' AND outcome = 'failure';"));
|
|
107
|
-
const successCalls = parseInt(runSql(dbPath, "SELECT COUNT(*) FROM tool_calls WHERE session_id LIKE 'seed-%' AND outcome = 'success';"));
|
|
108
|
-
assert(failureCalls > 0, 'Failed tool calls in seed data', `found ${failureCalls}`);
|
|
109
|
-
assert(successCalls > 0, 'Successful tool calls in seed data', `found ${successCalls}`);
|
|
110
|
-
|
|
111
|
-
// 1.7 Verify scenario descriptions are unique and meaningful
|
|
112
|
-
const reasons = runSql(dbPath, "SELECT DISTINCT reason FROM pain_events WHERE session_id LIKE 'seed-%' ORDER BY reason;").split('\n');
|
|
113
|
-
const uniqueReasons = new Set(reasons);
|
|
114
|
-
assert(uniqueReasons.size === reasons.length, 'All pain reasons are unique', `${uniqueReasons.size}/${reasons.length} unique`);
|
|
115
|
-
|
|
116
|
-
// ═══════════════════════════════════════════════
|
|
117
|
-
// SECTION 2: PainSignalBridge + Runtime v2
|
|
118
|
-
// ═══════════════════════════════════════════════
|
|
119
|
-
console.log('\n── 2. PainSignalBridge + Runtime v2 ──');
|
|
120
|
-
|
|
121
|
-
// 2.1 Verify PainSignalBridge is imported from runtime-v2 in pain.ts
|
|
122
|
-
const painHookSource = join(__dirname, '..', 'src', 'hooks', 'pain.ts');
|
|
123
|
-
if (existsSync(painHookSource)) {
|
|
124
|
-
const painContent = readFileSync(painHookSource, 'utf-8');
|
|
125
|
-
assert(painContent.includes('PainToPrincipleService'), 'pain.ts uses PainToPrincipleService from runtime-v2');
|
|
126
|
-
assert(!painContent.includes('createPainSignalBridge'), 'pain.ts no longer imports createPainSignalBridge');
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// 2.2 Verify write_pain_flag tool is NOT registered in index.ts
|
|
130
|
-
const indexSource2 = join(__dirname, '..', 'src', 'index.ts');
|
|
131
|
-
if (existsSync(indexSource2)) {
|
|
132
|
-
const indexContent = readFileSync(indexSource2, 'utf-8');
|
|
133
|
-
assert(!indexContent.includes('createWritePainFlagTool'), 'write_pain_flag NOT registered in index.ts');
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ═══════════════════════════════════════════════
|
|
137
|
-
// SECTION 3: Dedup Logic
|
|
138
|
-
// ═══════════════════════════════════════════════
|
|
139
|
-
console.log('\n── 3. Dedup Logic (Phase 3c) ──');
|
|
140
|
-
|
|
141
|
-
const workerSource = join(__dirname, '..', 'src', 'service', 'evolution-worker.ts');
|
|
142
|
-
if (existsSync(workerSource)) {
|
|
143
|
-
const workerContent = readFileSync(workerSource, 'utf-8');
|
|
144
|
-
|
|
145
|
-
// 3.1 Helper functions exist
|
|
146
|
-
assert(workerContent.includes('hasRecentSimilarReflection'), 'hasRecentSimilarReflection helper extracted');
|
|
147
|
-
assert(workerContent.includes('buildPainSourceKey'), 'buildPainSourceKey helper extracted');
|
|
148
|
-
assert(workerContent.includes('shouldSkipForDedup'), 'shouldSkipForDedup helper extracted');
|
|
149
|
-
|
|
150
|
-
// 3.2 Dedup window is configured
|
|
151
|
-
assert(workerContent.includes('4 * 60 * 60 * 1000') || workerContent.includes('DEDUP_WINDOW_MS'), '4-hour dedup window configured');
|
|
152
|
-
|
|
153
|
-
// 3.3 No-pain-context bypass
|
|
154
|
-
const bypassCheck = workerContent.includes('!painSourceKey') || workerContent.includes('painSourceKey === null') ||
|
|
155
|
-
workerContent.includes('painSourceKey) return false') || workerContent.includes('if (!painSourceKey) return false');
|
|
156
|
-
assert(bypassCheck, 'no_pain_context bypasses dedup', 'bypass pattern not found');
|
|
157
|
-
|
|
158
|
-
// 3.4 Only completed tasks are checked (not failed)
|
|
159
|
-
assert(workerContent.includes("status !== 'completed'") || workerContent.includes("status === 'completed'"), 'Only completed tasks matched for dedup');
|
|
160
|
-
} else {
|
|
161
|
-
fail('Dedup logic check', 'evolution-worker.ts not found');
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// ═══════════════════════════════════════════════
|
|
165
|
-
// SECTION 4: Correction Rejected Pain Event
|
|
166
|
-
// ═══════════════════════════════════════════════
|
|
167
|
-
console.log('\n── 4. Correction Rejected Pain Signal ──');
|
|
168
|
-
|
|
169
|
-
const trajectorySource = join(__dirname, '..', 'src', 'core', 'trajectory.ts');
|
|
170
|
-
if (existsSync(trajectorySource)) {
|
|
171
|
-
const trajContent = readFileSync(trajectorySource, 'utf-8');
|
|
172
|
-
|
|
173
|
-
// 4.1 Method exists
|
|
174
|
-
assert(trajContent.includes('recordCorrectionRejectedPain'), 'recordCorrectionRejectedPain method exists');
|
|
175
|
-
|
|
176
|
-
// 4.2 Called on rejected status
|
|
177
|
-
assert(trajContent.includes("status === 'rejected'"), 'Pain event created on rejected status');
|
|
178
|
-
|
|
179
|
-
// 4.3 Uses correct source
|
|
180
|
-
assert(trajContent.includes("'correction_rejected'"), 'Uses correction_rejected source');
|
|
181
|
-
|
|
182
|
-
// 4.4 Score is clamped
|
|
183
|
-
assert(trajContent.includes('Math.max(0') && trajContent.includes('Math.min(100'), 'Score clamped 0-100');
|
|
184
|
-
} else {
|
|
185
|
-
fail('Correction rejected check', 'trajectory.ts not found');
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// ═══════════════════════════════════════════════
|
|
189
|
-
// SECTION 5: Shell Injection Safety
|
|
190
|
-
// ═══════════════════════════════════════════════
|
|
191
|
-
console.log('\n── 5. Shell Injection Safety ──');
|
|
192
|
-
// (Nocturnal scripts removed in PRI-231 — section retained for future script checks)
|
|
193
|
-
|
|
194
|
-
// ═══════════════════════════════════════════════
|
|
195
|
-
// SECTION 6: Pending Review Warning Fix
|
|
196
|
-
// ═══════════════════════════════════════════════
|
|
197
|
-
console.log('\n── 6. Pending Review Warning Fix ──');
|
|
198
|
-
// (Nocturnal scripts removed in PRI-231 — section retained for future checks)
|
|
199
|
-
|
|
200
|
-
// ═══════════════════════════════════════════════
|
|
201
|
-
// SECTION 7: Path Resolver Fallback
|
|
202
|
-
// ═══════════════════════════════════════════════
|
|
203
|
-
console.log('\n── 7. Path Resolver Fallback ──');
|
|
204
|
-
|
|
205
|
-
const pathResolverSource = join(__dirname, '..', 'src', 'core', 'path-resolver.ts');
|
|
206
|
-
if (existsSync(pathResolverSource)) {
|
|
207
|
-
const prContent = readFileSync(pathResolverSource, 'utf-8');
|
|
208
|
-
// 7.1 resolveWorkspaceDirFromApi checks config.workspaceDir
|
|
209
|
-
assert(prContent.includes('config.workspaceDir') || prContent.includes('cfgWorkspaceDir'),
|
|
210
|
-
'resolveWorkspaceDirFromApi checks config.workspaceDir');
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// ═══════════════════════════════════════════════
|
|
214
|
-
// SECTION 8: Seed Scenario Quality (Manual Review)
|
|
215
|
-
// ═══════════════════════════════════════════════
|
|
216
|
-
console.log('\n── 8. Seed Scenario Quality ──');
|
|
217
|
-
|
|
218
|
-
// 8.1 Verify pain score distribution
|
|
219
|
-
const avgScore = parseFloat(runSql(dbPath, "SELECT ROUND(AVG(score), 1) FROM pain_events WHERE session_id LIKE 'seed-%';"));
|
|
220
|
-
assert(avgScore > 50 && avgScore < 100, 'Average pain score reasonable (50-100)', `avg=${avgScore}`);
|
|
221
|
-
|
|
222
|
-
// 8.2 Verify severity levels are set
|
|
223
|
-
const nullSeverity = parseInt(runSql(dbPath, "SELECT COUNT(*) FROM pain_events WHERE session_id LIKE 'seed-%' AND severity IS NULL;"));
|
|
224
|
-
assert(nullSeverity === 0, 'All seed pain events have severity', `${nullSeverity} null`);
|
|
225
|
-
|
|
226
|
-
// 8.3 Verify origin is set
|
|
227
|
-
const nullOrigin = parseInt(runSql(dbPath, "SELECT COUNT(*) FROM pain_events WHERE session_id LIKE 'seed-%' AND origin IS NULL;"));
|
|
228
|
-
assert(nullOrigin === 0, 'All seed pain events have origin', `${nullOrigin} null`);
|
|
229
|
-
|
|
230
|
-
// 8.4 Verify all 10 scenario IDs follow naming convention
|
|
231
|
-
const seedSessions = runSql(dbPath, "SELECT session_id FROM sessions WHERE session_id LIKE 'seed-%' ORDER BY session_id;").split('\n');
|
|
232
|
-
const validPattern = /^seed-[a-z-]+-\d{3}$/;
|
|
233
|
-
const allValid = seedSessions.every(s => validPattern.test(s));
|
|
234
|
-
assert(allValid, 'All session IDs follow naming convention', `${seedSessions.filter(s => !validPattern.test(s)).length} invalid`);
|
|
235
|
-
|
|
236
|
-
// ═══════════════════════════════════════════════
|
|
237
|
-
// SUMMARY
|
|
238
|
-
// ═══════════════════════════════════════════════
|
|
239
|
-
console.log('\n' + '═'.repeat(55));
|
|
240
|
-
console.log(` Acceptance Test Summary`);
|
|
241
|
-
console.log('═'.repeat(55));
|
|
242
|
-
console.log(` ✅ Passed: ${passCount}`);
|
|
243
|
-
console.log(` ❌ Failed: ${failCount}`);
|
|
244
|
-
console.log(` ⚠️ Warnings: ${warnCount}`);
|
|
245
|
-
console.log(` Total: ${passCount + failCount + warnCount}`);
|
|
246
|
-
console.log('═'.repeat(55));
|
|
247
|
-
|
|
248
|
-
if (failCount === 0) {
|
|
249
|
-
console.log('\n🎉 All acceptance tests passed!');
|
|
250
|
-
process.exit(0);
|
|
251
|
-
} else {
|
|
252
|
-
console.log(`\n❌ ${failCount} test(s) failed. Review details above.`);
|
|
253
|
-
process.exit(1);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
main();
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Minimal Rule Bootstrap CLI (Phase 17)
|
|
5
|
-
*
|
|
6
|
-
* Seeds 1-3 stub Rule entities for high-value deterministic principles.
|
|
7
|
-
* Idempotent: re-running skips already-existing rules.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* npm run bootstrap-rules # default (3 principles)
|
|
11
|
-
* BOOTSTRAP_LIMIT=2 npm run bootstrap-rules # limit to 2 principles
|
|
12
|
-
* STATE_DIR=/path/to/state npm run bootstrap-rules # custom state dir
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { join, dirname } from 'path';
|
|
16
|
-
import { fileURLToPath } from 'url';
|
|
17
|
-
|
|
18
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
-
const __dirname = dirname(__filename);
|
|
20
|
-
|
|
21
|
-
const PROJECT_ROOT = join(__dirname, '..');
|
|
22
|
-
const STATE_DIR = process.env.STATE_DIR || join(PROJECT_ROOT, '..', '.state');
|
|
23
|
-
const LIMIT = parseInt(process.env.BOOTSTRAP_LIMIT || '3', 10);
|
|
24
|
-
|
|
25
|
-
async function run() {
|
|
26
|
-
let BootstrapModule;
|
|
27
|
-
try {
|
|
28
|
-
BootstrapModule = await import('../dist/core/bootstrap-rules.js');
|
|
29
|
-
} catch {
|
|
30
|
-
console.error('Bootstrap module not found in dist/. Build first: node esbuild.config.js');
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const { bootstrapRules, validateBootstrap, selectPrinciplesForBootstrap } = BootstrapModule;
|
|
35
|
-
|
|
36
|
-
console.log('Selecting principles for bootstrap...');
|
|
37
|
-
console.log(` State dir: ${STATE_DIR}`);
|
|
38
|
-
console.log(` Limit: ${LIMIT}`);
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
const selectedIds = selectPrinciplesForBootstrap(STATE_DIR, LIMIT);
|
|
42
|
-
console.log(` Selected ${selectedIds.length} principle(s): ${selectedIds.join(', ')}`);
|
|
43
|
-
|
|
44
|
-
console.log('\nRunning bootstrap...');
|
|
45
|
-
const results = bootstrapRules(STATE_DIR, LIMIT);
|
|
46
|
-
|
|
47
|
-
for (const r of results) {
|
|
48
|
-
console.log(` ${r.status === 'created' ? '+' : '='} ${r.principleId} -> ${r.ruleId} (${r.status})`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const created = results.filter((r) => r.status === 'created');
|
|
52
|
-
const skipped = results.filter((r) => r.status === 'skipped');
|
|
53
|
-
console.log(`\nDone: ${created.length} created, ${skipped.length} skipped.`);
|
|
54
|
-
|
|
55
|
-
if (created.length > 0) {
|
|
56
|
-
console.log('\nValidating...');
|
|
57
|
-
const valid = validateBootstrap(STATE_DIR, selectedIds);
|
|
58
|
-
console.log(` Validation: ${valid ? 'PASS' : 'FAIL'}`);
|
|
59
|
-
}
|
|
60
|
-
} catch (err) {
|
|
61
|
-
if (err && typeof err === 'object' && 'code' in err && err.code === 'NO_DETERMINISTIC_PRINCIPLES') {
|
|
62
|
-
console.log('\nNothing to bootstrap yet; the workspace has no deterministic principles.');
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
console.error(`\nBootstrap failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
66
|
-
process.exit(1);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
run();
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Principle Compiler CLI
|
|
5
|
-
*
|
|
6
|
-
* Compiles eligible principles (those derived from pain events) into
|
|
7
|
-
* auto-generated rules via the PrincipleCompiler pipeline.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* npm run compile-principles
|
|
11
|
-
* WORKSPACE_DIR=/path/to/workspace npm run compile-principles
|
|
12
|
-
* node scripts/compile-principles.mjs /path/to/workspace
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { join, dirname } from 'path';
|
|
16
|
-
import { fileURLToPath } from 'url';
|
|
17
|
-
|
|
18
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
-
const __dirname = dirname(__filename);
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Cross-platform home directory (Linux: HOME, Windows: USERPROFILE/HOMEDRIVE+HOMEPATH)
|
|
23
|
-
*/
|
|
24
|
-
function getHomeDir() {
|
|
25
|
-
return process.env.HOME
|
|
26
|
-
|| process.env.USERPROFILE
|
|
27
|
-
|| (process.env.HOMEDRIVE && process.env.HOMEPATH ? process.env.HOMEDRIVE + process.env.HOMEPATH : null)
|
|
28
|
-
|| '.';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Resolve workspace directory: CLI arg > env var > default
|
|
32
|
-
const WORKSPACE_DIR = process.argv[2]
|
|
33
|
-
|| process.env.WORKSPACE_DIR
|
|
34
|
-
|| join(getHomeDir(), '.openclaw', 'workspace');
|
|
35
|
-
|
|
36
|
-
const STATE_DIR = join(WORKSPACE_DIR, '.state');
|
|
37
|
-
|
|
38
|
-
async function run() {
|
|
39
|
-
console.log('Principle Compiler CLI');
|
|
40
|
-
console.log(` Workspace: ${WORKSPACE_DIR}`);
|
|
41
|
-
console.log(` State dir: ${STATE_DIR}`);
|
|
42
|
-
|
|
43
|
-
let compilerModule, trajectoryModule;
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
compilerModule = await import('../dist/core/principle-compiler/index.js');
|
|
47
|
-
} catch {
|
|
48
|
-
console.error('PrincipleCompiler module not found in dist/. Build first: node esbuild.config.js');
|
|
49
|
-
process.exit(1);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
trajectoryModule = await import('../dist/core/trajectory/index.js');
|
|
54
|
-
} catch {
|
|
55
|
-
console.error('TrajectoryDatabase module not found in dist/. Build first: node esbuild.config.js');
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const { PrincipleCompiler } = compilerModule;
|
|
60
|
-
const { TrajectoryDatabase } = trajectoryModule;
|
|
61
|
-
|
|
62
|
-
let trajectory;
|
|
63
|
-
try {
|
|
64
|
-
trajectory = new TrajectoryDatabase({ workspaceDir: WORKSPACE_DIR });
|
|
65
|
-
} catch (err) {
|
|
66
|
-
console.error(`Failed to open trajectory database: ${err.message}`);
|
|
67
|
-
process.exit(1);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
const compiler = new PrincipleCompiler(STATE_DIR, trajectory);
|
|
72
|
-
|
|
73
|
-
console.log('\nCompiling eligible principles...');
|
|
74
|
-
const results = compiler.compileAll();
|
|
75
|
-
|
|
76
|
-
const succeeded = results.filter(r => r.success);
|
|
77
|
-
const failed = results.filter(r => !r.success);
|
|
78
|
-
|
|
79
|
-
console.log(`\nResults: ${succeeded.length} succeeded, ${failed.length} failed`);
|
|
80
|
-
|
|
81
|
-
for (const r of succeeded) {
|
|
82
|
-
console.log(` + ${r.principleId} -> rule ${r.ruleId} (impl: ${r.implementationId})`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
for (const r of failed) {
|
|
86
|
-
console.log(` x ${r.principleId}: ${r.reason}`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (results.length === 0) {
|
|
90
|
-
console.log(' No eligible principles found for compilation.');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (failed.length > 0) {
|
|
94
|
-
process.exitCode = 1;
|
|
95
|
-
}
|
|
96
|
-
} finally {
|
|
97
|
-
trajectory.dispose();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
run().catch((err) => {
|
|
102
|
-
console.error(`Fatal: ${err.message}`);
|
|
103
|
-
process.exit(1);
|
|
104
|
-
});
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { execFileSync } = require('child_process');
|
|
4
|
-
const { existsSync, readFileSync } = require('fs');
|
|
5
|
-
const { join } = require('path');
|
|
6
|
-
|
|
7
|
-
const PLUGIN_DIR = join(__dirname, '..');
|
|
8
|
-
|
|
9
|
-
console.log('Setting up Principles Disciple plugin dependencies...');
|
|
10
|
-
|
|
11
|
-
const packageJsonPath = join(PLUGIN_DIR, 'package.json');
|
|
12
|
-
if (!existsSync(packageJsonPath)) {
|
|
13
|
-
console.log('Not in plugin directory, skipping dependency setup');
|
|
14
|
-
process.exit(0);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
18
|
-
const dependencyNames = ['micromatch', '@sinclair/typebox', 'better-sqlite3'];
|
|
19
|
-
const DEPENDENCIES = dependencyNames.map((name) => {
|
|
20
|
-
const version = packageJson.dependencies?.[name] || packageJson.devDependencies?.[name];
|
|
21
|
-
if (!version) {
|
|
22
|
-
throw new Error(`Missing dependency version in package.json for ${name}`);
|
|
23
|
-
}
|
|
24
|
-
return `${name}@${version}`;
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const nodeModulesDir = join(PLUGIN_DIR, 'node_modules');
|
|
28
|
-
const betterSqliteDir = join(nodeModulesDir, 'better-sqlite3');
|
|
29
|
-
if (existsSync(nodeModulesDir) && existsSync(betterSqliteDir)) {
|
|
30
|
-
console.log('Dependencies already installed');
|
|
31
|
-
process.exit(0);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
console.log('Installing plugin dependencies...');
|
|
35
|
-
try {
|
|
36
|
-
execFileSync('npm', ['install', ...DEPENDENCIES], {
|
|
37
|
-
cwd: PLUGIN_DIR,
|
|
38
|
-
stdio: 'inherit',
|
|
39
|
-
});
|
|
40
|
-
console.log('Plugin dependencies installed successfully');
|
|
41
|
-
} catch (error) {
|
|
42
|
-
console.error('Failed to install plugin dependencies:', error.message);
|
|
43
|
-
console.log('\nManual fix:');
|
|
44
|
-
console.log(' cd', PLUGIN_DIR);
|
|
45
|
-
console.log(' npm install', DEPENDENCIES.join(' '));
|
|
46
|
-
process.exit(1);
|
|
47
|
-
}
|
|
@@ -1,177 +0,0 @@
|
|
|
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
|
-
}
|