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.
Files changed (160) hide show
  1. package/package.json +2 -2
  2. package/pd-cli/dist/commands/legacy-cleanup.d.ts.map +1 -1
  3. package/pd-cli/dist/commands/legacy-cleanup.js +19 -2
  4. package/pd-cli/dist/commands/legacy-cleanup.js.map +1 -1
  5. package/pd-cli/dist/commands/pain-evidence.d.ts +3 -1
  6. package/pd-cli/dist/commands/pain-evidence.d.ts.map +1 -1
  7. package/pd-cli/dist/commands/pain-evidence.js +12 -3
  8. package/pd-cli/dist/commands/pain-evidence.js.map +1 -1
  9. package/pd-cli/dist/commands/rulecode.d.ts +13 -0
  10. package/pd-cli/dist/commands/rulecode.d.ts.map +1 -1
  11. package/pd-cli/dist/commands/rulecode.js +23 -2
  12. package/pd-cli/dist/commands/rulecode.js.map +1 -1
  13. package/pd-cli/dist/resolve-workspace.d.ts.map +1 -1
  14. package/pd-cli/dist/resolve-workspace.js +33 -12
  15. package/pd-cli/dist/resolve-workspace.js.map +1 -1
  16. package/pd-cli/dist/services/console-launcher.d.ts +8 -1
  17. package/pd-cli/dist/services/console-launcher.d.ts.map +1 -1
  18. package/pd-cli/dist/services/console-launcher.js +45 -3
  19. package/pd-cli/dist/services/console-launcher.js.map +1 -1
  20. package/pd-cli/dist/services/pd-config-loader.d.ts.map +1 -1
  21. package/pd-cli/dist/services/pd-config-loader.js +34 -1
  22. package/pd-cli/dist/services/pd-config-loader.js.map +1 -1
  23. package/pd-cli/dist/services/quality-scorecard/strong-model-gate.d.ts +19 -0
  24. package/pd-cli/dist/services/quality-scorecard/strong-model-gate.d.ts.map +1 -1
  25. package/pd-cli/dist/services/quality-scorecard/strong-model-gate.js +44 -2
  26. package/pd-cli/dist/services/quality-scorecard/strong-model-gate.js.map +1 -1
  27. package/pd-cli/dist/utils/path-security.d.ts +60 -0
  28. package/pd-cli/dist/utils/path-security.d.ts.map +1 -0
  29. package/pd-cli/dist/utils/path-security.js +90 -0
  30. package/pd-cli/dist/utils/path-security.js.map +1 -0
  31. package/plugin/dist/bundle.js +13 -11
  32. package/plugin/dist/constants/tools.d.ts +1 -1
  33. package/plugin/dist/hooks/prompt-helpers.d.ts +5 -5
  34. package/plugin/dist/templates/langs/en/core/AGENTS.md +40 -180
  35. package/plugin/dist/templates/langs/en/core/BOOT.md +19 -47
  36. package/plugin/dist/templates/langs/en/core/HEARTBEAT.md +26 -58
  37. package/plugin/dist/templates/langs/en/core/IDENTITY.md +15 -8
  38. package/plugin/dist/templates/langs/en/core/PRINCIPLES.md +6 -7
  39. package/plugin/dist/templates/langs/en/core/SOUL.md +10 -41
  40. package/plugin/dist/templates/langs/en/core/TOOLS.md +18 -10
  41. package/plugin/dist/templates/langs/en/core/USER.md +13 -8
  42. package/plugin/dist/templates/langs/en/skills/pd-auditor/SKILL.md +1 -1
  43. package/plugin/dist/templates/langs/en/skills/pd-explorer/SKILL.md +1 -1
  44. package/plugin/dist/templates/langs/en/skills/pd-implementer/SKILL.md +1 -1
  45. package/plugin/dist/templates/langs/en/skills/pd-mentor/SKILL.md +6 -30
  46. package/plugin/dist/templates/langs/en/skills/pd-planner/SKILL.md +1 -1
  47. package/plugin/dist/templates/langs/zh/core/AGENTS.md +38 -173
  48. package/plugin/dist/templates/langs/zh/core/BOOT.md +14 -46
  49. package/plugin/dist/templates/langs/zh/core/HEARTBEAT.md +20 -82
  50. package/plugin/dist/templates/langs/zh/core/IDENTITY.md +15 -8
  51. package/plugin/dist/templates/langs/zh/core/PRINCIPLES.md +7 -7
  52. package/plugin/dist/templates/langs/zh/core/SOUL.md +9 -41
  53. package/plugin/dist/templates/langs/zh/core/TOOLS.md +14 -10
  54. package/plugin/dist/templates/langs/zh/core/USER.md +12 -8
  55. package/plugin/dist/templates/langs/zh/skills/pd-auditor/SKILL.md +1 -1
  56. package/plugin/dist/templates/langs/zh/skills/pd-explorer/SKILL.md +1 -1
  57. package/plugin/dist/templates/langs/zh/skills/pd-implementer/SKILL.md +1 -1
  58. package/plugin/dist/templates/langs/zh/skills/pd-mentor/SKILL.md +6 -30
  59. package/plugin/dist/templates/langs/zh/skills/pd-planner/SKILL.md +1 -1
  60. package/plugin/dist/templates/pain_settings.json +1 -2
  61. package/plugin/openclaw.plugin.json +1 -1
  62. package/plugin/package.json +1 -2
  63. package/plugin/templates/langs/en/core/AGENTS.md +40 -180
  64. package/plugin/templates/langs/en/core/BOOT.md +19 -47
  65. package/plugin/templates/langs/en/core/HEARTBEAT.md +26 -58
  66. package/plugin/templates/langs/en/core/IDENTITY.md +15 -8
  67. package/plugin/templates/langs/en/core/PRINCIPLES.md +6 -7
  68. package/plugin/templates/langs/en/core/SOUL.md +10 -41
  69. package/plugin/templates/langs/en/core/TOOLS.md +18 -10
  70. package/plugin/templates/langs/en/core/USER.md +13 -8
  71. package/plugin/templates/langs/en/skills/pd-auditor/SKILL.md +1 -1
  72. package/plugin/templates/langs/en/skills/pd-explorer/SKILL.md +1 -1
  73. package/plugin/templates/langs/en/skills/pd-implementer/SKILL.md +1 -1
  74. package/plugin/templates/langs/en/skills/pd-mentor/SKILL.md +6 -30
  75. package/plugin/templates/langs/en/skills/pd-planner/SKILL.md +1 -1
  76. package/plugin/templates/langs/zh/core/AGENTS.md +38 -173
  77. package/plugin/templates/langs/zh/core/BOOT.md +14 -46
  78. package/plugin/templates/langs/zh/core/HEARTBEAT.md +20 -82
  79. package/plugin/templates/langs/zh/core/IDENTITY.md +15 -8
  80. package/plugin/templates/langs/zh/core/PRINCIPLES.md +7 -7
  81. package/plugin/templates/langs/zh/core/SOUL.md +9 -41
  82. package/plugin/templates/langs/zh/core/TOOLS.md +14 -10
  83. package/plugin/templates/langs/zh/core/USER.md +12 -8
  84. package/plugin/templates/langs/zh/skills/pd-auditor/SKILL.md +1 -1
  85. package/plugin/templates/langs/zh/skills/pd-explorer/SKILL.md +1 -1
  86. package/plugin/templates/langs/zh/skills/pd-implementer/SKILL.md +1 -1
  87. package/plugin/templates/langs/zh/skills/pd-mentor/SKILL.md +6 -30
  88. package/plugin/templates/langs/zh/skills/pd-planner/SKILL.md +1 -1
  89. package/plugin/templates/pain_settings.json +1 -2
  90. package/plugin/dist/templates/langs/en/core/BOOTSTRAP.md +0 -259
  91. package/plugin/dist/templates/langs/en/skills/admin/SKILL.md +0 -39
  92. package/plugin/dist/templates/langs/en/skills/bootstrap-tools/SKILL.md +0 -53
  93. package/plugin/dist/templates/langs/en/skills/deductive-audit/SKILL.md +0 -36
  94. package/plugin/dist/templates/langs/en/skills/evolution-framework-update/SKILL.md +0 -31
  95. package/plugin/dist/templates/langs/en/skills/evolve-task/SKILL.md +0 -83
  96. package/plugin/dist/templates/langs/en/skills/feedback/SKILL.md +0 -51
  97. package/plugin/dist/templates/langs/en/skills/init-strategy/SKILL.md +0 -54
  98. package/plugin/dist/templates/langs/en/skills/inject-rule/SKILL.md +0 -19
  99. package/plugin/dist/templates/langs/en/skills/profile/SKILL.md +0 -24
  100. package/plugin/dist/templates/langs/en/skills/reflection/SKILL.md +0 -40
  101. package/plugin/dist/templates/langs/en/skills/reflection-log/SKILL.md +0 -37
  102. package/plugin/dist/templates/langs/en/skills/report/SKILL.md +0 -13
  103. package/plugin/dist/templates/langs/en/skills/root-cause/SKILL.md +0 -33
  104. package/plugin/dist/templates/langs/en/skills/triage/SKILL.md +0 -29
  105. package/plugin/dist/templates/langs/en/skills/watch-evolution/SKILL.md +0 -33
  106. package/plugin/dist/templates/langs/zh/core/BOOTSTRAP.md +0 -260
  107. package/plugin/dist/templates/langs/zh/skills/admin/SKILL.md +0 -41
  108. package/plugin/dist/templates/langs/zh/skills/bootstrap-tools/SKILL.md +0 -52
  109. package/plugin/dist/templates/langs/zh/skills/deductive-audit/SKILL.md +0 -36
  110. package/plugin/dist/templates/langs/zh/skills/evolution-framework-update/SKILL.md +0 -31
  111. package/plugin/dist/templates/langs/zh/skills/evolve-task/SKILL.md +0 -83
  112. package/plugin/dist/templates/langs/zh/skills/feedback/SKILL.md +0 -53
  113. package/plugin/dist/templates/langs/zh/skills/init-strategy/SKILL.md +0 -54
  114. package/plugin/dist/templates/langs/zh/skills/inject-rule/SKILL.md +0 -19
  115. package/plugin/dist/templates/langs/zh/skills/profile/SKILL.md +0 -24
  116. package/plugin/dist/templates/langs/zh/skills/reflection/SKILL.md +0 -40
  117. package/plugin/dist/templates/langs/zh/skills/reflection-log/SKILL.md +0 -37
  118. package/plugin/dist/templates/langs/zh/skills/report/SKILL.md +0 -13
  119. package/plugin/dist/templates/langs/zh/skills/root-cause/SKILL.md +0 -33
  120. package/plugin/dist/templates/langs/zh/skills/triage/SKILL.md +0 -29
  121. package/plugin/dist/templates/langs/zh/skills/watch-evolution/SKILL.md +0 -33
  122. package/plugin/scripts/acceptance-test.mjs +0 -257
  123. package/plugin/scripts/bootstrap-rules.mjs +0 -70
  124. package/plugin/scripts/compile-principles.mjs +0 -104
  125. package/plugin/scripts/install-dependencies.cjs +0 -47
  126. package/plugin/scripts/postinstall.cjs +0 -177
  127. package/plugin/scripts/sync-plugin.mjs +0 -1442
  128. package/plugin/scripts/verify-build.mjs +0 -120
  129. package/plugin/templates/langs/en/core/BOOTSTRAP.md +0 -259
  130. package/plugin/templates/langs/en/skills/admin/SKILL.md +0 -39
  131. package/plugin/templates/langs/en/skills/bootstrap-tools/SKILL.md +0 -53
  132. package/plugin/templates/langs/en/skills/deductive-audit/SKILL.md +0 -36
  133. package/plugin/templates/langs/en/skills/evolution-framework-update/SKILL.md +0 -31
  134. package/plugin/templates/langs/en/skills/evolve-task/SKILL.md +0 -83
  135. package/plugin/templates/langs/en/skills/feedback/SKILL.md +0 -51
  136. package/plugin/templates/langs/en/skills/init-strategy/SKILL.md +0 -54
  137. package/plugin/templates/langs/en/skills/inject-rule/SKILL.md +0 -19
  138. package/plugin/templates/langs/en/skills/profile/SKILL.md +0 -24
  139. package/plugin/templates/langs/en/skills/reflection/SKILL.md +0 -40
  140. package/plugin/templates/langs/en/skills/reflection-log/SKILL.md +0 -37
  141. package/plugin/templates/langs/en/skills/report/SKILL.md +0 -13
  142. package/plugin/templates/langs/en/skills/root-cause/SKILL.md +0 -33
  143. package/plugin/templates/langs/en/skills/triage/SKILL.md +0 -29
  144. package/plugin/templates/langs/en/skills/watch-evolution/SKILL.md +0 -33
  145. package/plugin/templates/langs/zh/core/BOOTSTRAP.md +0 -260
  146. package/plugin/templates/langs/zh/skills/admin/SKILL.md +0 -41
  147. package/plugin/templates/langs/zh/skills/bootstrap-tools/SKILL.md +0 -52
  148. package/plugin/templates/langs/zh/skills/deductive-audit/SKILL.md +0 -36
  149. package/plugin/templates/langs/zh/skills/evolution-framework-update/SKILL.md +0 -31
  150. package/plugin/templates/langs/zh/skills/evolve-task/SKILL.md +0 -83
  151. package/plugin/templates/langs/zh/skills/feedback/SKILL.md +0 -53
  152. package/plugin/templates/langs/zh/skills/init-strategy/SKILL.md +0 -54
  153. package/plugin/templates/langs/zh/skills/inject-rule/SKILL.md +0 -19
  154. package/plugin/templates/langs/zh/skills/profile/SKILL.md +0 -24
  155. package/plugin/templates/langs/zh/skills/reflection/SKILL.md +0 -40
  156. package/plugin/templates/langs/zh/skills/reflection-log/SKILL.md +0 -37
  157. package/plugin/templates/langs/zh/skills/report/SKILL.md +0 -13
  158. package/plugin/templates/langs/zh/skills/root-cause/SKILL.md +0 -33
  159. package/plugin/templates/langs/zh/skills/triage/SKILL.md +0 -29
  160. 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
- }