principles-disciple 1.104.1 → 1.105.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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/core/init.ts +7 -13
- package/src/core/thinking-models.ts +9 -29
- package/templates/langs/en/principles/THINKING_OS.md +12 -0
- package/templates/langs/zh/principles/THINKING_OS.md +12 -0
- package/tests/core/core-principle-registry-drift.test.ts +39 -0
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "principles-disciple",
|
|
3
3
|
"name": "Principles Disciple",
|
|
4
4
|
"description": "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.105.0",
|
|
6
6
|
"activation": {
|
|
7
7
|
"onCapabilities": [
|
|
8
8
|
"hook"
|
package/package.json
CHANGED
package/src/core/init.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { addPrincipleToLedger } from './principle-tree-ledger.js';
|
|
|
9
9
|
import type { LedgerPrinciple } from './principle-tree-ledger.js';
|
|
10
10
|
import { atomicWriteFileSync } from '../utils/io.js';
|
|
11
11
|
import { createDefaultKeywordStore, saveKeywordStore } from './empathy-keyword-matcher.js';
|
|
12
|
+
import { CORE_PRINCIPLES } from '@principles/core/runtime-v2';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Default PROFILE.json content
|
|
@@ -150,24 +151,17 @@ function copyRecursiveSync(srcDir: string, destDir: string, api: OpenClawPluginA
|
|
|
150
151
|
|
|
151
152
|
/**
|
|
152
153
|
* Core thinking model definitions (T-01 through T-10).
|
|
153
|
-
*
|
|
154
|
+
* Derived from the Core Principle Registry — the single source of truth.
|
|
154
155
|
*/
|
|
155
156
|
export const CORE_THINKING_MODELS: Array<{
|
|
156
157
|
id: string;
|
|
157
158
|
name: string;
|
|
158
159
|
description: string;
|
|
159
|
-
}> =
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
{ id: 'T-05', name: 'Safety Rails', description: 'Call out guardrails, prohibitions, and failure-prevention constraints.' },
|
|
165
|
-
{ id: 'T-06', name: 'Simplicity First', description: 'Prefer the smallest understandable solution over over-engineering.' },
|
|
166
|
-
{ id: 'T-07', name: 'Minimal Change Surface', description: 'Limit the blast radius and touch only what is necessary.' },
|
|
167
|
-
{ id: 'T-08', name: 'Pain As Signal', description: 'Treat failures and friction as clues to step back and rethink.' },
|
|
168
|
-
{ id: 'T-09', name: 'Divide And Conquer', description: 'Split the task into smaller phases before execution.' },
|
|
169
|
-
{ id: 'T-10', name: 'Memory Externalization', description: 'Write intermediate conclusions to files for persistence.' },
|
|
170
|
-
];
|
|
160
|
+
}> = CORE_PRINCIPLES.map(p => ({
|
|
161
|
+
id: p.id,
|
|
162
|
+
name: p.name,
|
|
163
|
+
description: p.description,
|
|
164
|
+
}));
|
|
171
165
|
|
|
172
166
|
/**
|
|
173
167
|
* Initialize core thinking models into the training store if it's empty.
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Thinking Models — Detection Engine
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Core principle metadata (id, name, description) comes from the
|
|
5
|
+
* Core Principle Registry in @principles/core/runtime-v2.
|
|
5
6
|
* Detection patterns are carefully tuned regexes that match AI output text.
|
|
6
7
|
*
|
|
7
8
|
* Flow:
|
|
8
|
-
*
|
|
9
|
+
* Core Principle Registry (authority) → id, name, description
|
|
9
10
|
* BUILTIN_PATTERNS (engine) → detection regexes per model id
|
|
10
11
|
* THINKING_MODELS (merged) → full definitions with patterns
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
import { loadThinkingOsFromWorkspace, generateDetectionPatterns } from './thinking-os-parser.js';
|
|
15
|
+
import { CORE_PRINCIPLES } from '@principles/core/runtime-v2';
|
|
14
16
|
|
|
15
17
|
export interface ThinkingModelDefinition {
|
|
16
18
|
id: string;
|
|
@@ -199,37 +201,15 @@ const BUILTIN_PATTERNS: BuiltinPatternEntry[] = [
|
|
|
199
201
|
|
|
200
202
|
const BUILTIN_PATTERN_MAP = new Map(BUILTIN_PATTERNS.map((p) => [p.id, p]));
|
|
201
203
|
|
|
202
|
-
// Fallback name/description lookup
|
|
204
|
+
// Fallback name/description lookup — delegates to Core Principle Registry
|
|
203
205
|
function getFallbackName(id: string): string {
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
'T-02': 'Respect Constraints',
|
|
207
|
-
'T-03': 'Evidence Over Assumption',
|
|
208
|
-
'T-04': 'Reversible First',
|
|
209
|
-
'T-05': 'Safety Rails',
|
|
210
|
-
'T-06': 'Simplicity First',
|
|
211
|
-
'T-07': 'Minimal Change Surface',
|
|
212
|
-
'T-08': 'Pain As Signal',
|
|
213
|
-
'T-09': 'Divide And Conquer',
|
|
214
|
-
'T-10': 'Memory Externalization',
|
|
215
|
-
};
|
|
216
|
-
return names[id] ?? id;
|
|
206
|
+
const entry = CORE_PRINCIPLES.find(p => p.id === id);
|
|
207
|
+
return entry?.name ?? id;
|
|
217
208
|
}
|
|
218
209
|
|
|
219
210
|
function getFallbackDescription(id: string): string {
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
'T-02': 'Trust files, not your context window. Write conclusions to files.',
|
|
223
|
-
'T-03': 'Use logs, code, and outputs before inferring causes.',
|
|
224
|
-
'T-04': 'Prefer changes that are safe to roll back when risk is high.',
|
|
225
|
-
'T-05': 'Call out guardrails, prohibitions, and failure-prevention constraints.',
|
|
226
|
-
'T-06': 'Prefer the smallest understandable solution over over-engineering.',
|
|
227
|
-
'T-07': 'Limit the blast radius and touch only what is necessary.',
|
|
228
|
-
'T-08': 'Treat failures and friction as clues to step back and rethink.',
|
|
229
|
-
'T-09': 'Split the task into smaller phases before execution.',
|
|
230
|
-
'T-10': 'Write intermediate conclusions to files for persistence.',
|
|
231
|
-
};
|
|
232
|
-
return descs[id] ?? '';
|
|
211
|
+
const entry = CORE_PRINCIPLES.find(p => p.id === id);
|
|
212
|
+
return entry?.description ?? '';
|
|
233
213
|
}
|
|
234
214
|
|
|
235
215
|
// ---------------------------------------------------------------------------
|
|
@@ -62,4 +62,16 @@ LLMs are highly sensitive to XML tags; this structure is designed to boost instr
|
|
|
62
62
|
<must>Maintain extreme digital cleanliness. The project root is SACRED. Use strict `kebab-case` for all naming. Clean up all test scripts and debug artifacts after the task.</must>
|
|
63
63
|
<forbidden>Creating arbitrary temporary files (e.g., `test.txt`, `temp.md`, `debug.log`) in the project root directory.</forbidden>
|
|
64
64
|
</directive>
|
|
65
|
+
|
|
66
|
+
<directive id="T-09" name="DIVIDE_AND_CONQUER">
|
|
67
|
+
<trigger>When facing a complex task, multi-step change, or an operation that can be decomposed.</trigger>
|
|
68
|
+
<must>Break the task into smaller, manageable phases before execution. Execute one phase at a time and verify each phase's result before proceeding.</must>
|
|
69
|
+
<forbidden>Attempting to execute a large, complex change in a single step, or proceeding without a decomposition plan.</forbidden>
|
|
70
|
+
</directive>
|
|
71
|
+
|
|
72
|
+
<directive id="T-10" name="MEMORY_EXTERNALIZATION">
|
|
73
|
+
<trigger>When reaching a significant conclusion, making a decision, or planning next steps across sessions.</trigger>
|
|
74
|
+
<must>Write intermediate conclusions, decisions, and plans to persistent files (e.g., plan.md, scratchpad) so they survive context compression and session boundaries.</must>
|
|
75
|
+
<forbidden>Relying solely on conversation context to retain important state that will be lost when the context window shifts.</forbidden>
|
|
76
|
+
</directive>
|
|
65
77
|
</thinking_os_core_directives>
|
|
@@ -62,4 +62,16 @@
|
|
|
62
62
|
<must>保持极致的数字洁癖。项目根目录是神圣的。所有命名必须严格使用 `kebab-case`。任务结束后清理所有的测试脚本和 Debug 遗留物。</must>
|
|
63
63
|
<forbidden>在项目根目录下随意创建临时文件(如 `test.txt`、`temp.md`、`debug.log`)。</forbidden>
|
|
64
64
|
</directive>
|
|
65
|
+
|
|
66
|
+
<directive id="T-09" name="DIVIDE_AND_CONQUER">
|
|
67
|
+
<trigger>当面对复杂任务、多步骤变更或可分解的操作时。</trigger>
|
|
68
|
+
<must>在执行前将任务拆分为更小的、可管理的阶段。逐阶段执行,并在进入下一阶段前验证当前阶段的结果。</must>
|
|
69
|
+
<forbidden>试图在单一步骤中执行大型复杂变更,或在没有分解计划的情况下直接推进。</forbidden>
|
|
70
|
+
</directive>
|
|
71
|
+
|
|
72
|
+
<directive id="T-10" name="MEMORY_EXTERNALIZATION">
|
|
73
|
+
<trigger>当得出重要结论、做出决策或规划跨会话的后续步骤时。</trigger>
|
|
74
|
+
<must>将中间结论、决策和计划写入持久化文件(如 plan.md、scratchpad),使其在上下文压缩和会话边界后仍然可用。</must>
|
|
75
|
+
<forbidden>仅依赖对话上下文来保持重要状态,这些状态在上下文窗口切换时将丢失。</forbidden>
|
|
76
|
+
</directive>
|
|
65
77
|
</thinking_os_core_directives>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { listThinkingModels } from '../../src/core/thinking-models.js';
|
|
3
|
+
import {
|
|
4
|
+
CORE_PRINCIPLES,
|
|
5
|
+
CORE_PRINCIPLE_IDS,
|
|
6
|
+
} from '@principles/core/runtime-v2';
|
|
7
|
+
|
|
8
|
+
describe('Core Principle Registry drift test', () => {
|
|
9
|
+
it('registry count matches thinking-models.ts builtin count', () => {
|
|
10
|
+
// No workspace → falls back to builtin patterns (T-01..T-10)
|
|
11
|
+
const models = listThinkingModels();
|
|
12
|
+
expect(models).toHaveLength(10);
|
|
13
|
+
expect(CORE_PRINCIPLES).toHaveLength(10);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('registry ids match thinking-models.ts ids', () => {
|
|
17
|
+
const models = listThinkingModels();
|
|
18
|
+
const modelIds = models.map(m => m.id).sort();
|
|
19
|
+
const registryIds = CORE_PRINCIPLE_IDS.slice().sort();
|
|
20
|
+
expect(registryIds).toEqual(modelIds);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('registry names match thinking-models.ts fallback names', () => {
|
|
24
|
+
const models = listThinkingModels();
|
|
25
|
+
for (const model of models) {
|
|
26
|
+
const registryEntry = CORE_PRINCIPLES.find(p => p.id === model.id);
|
|
27
|
+
expect(registryEntry).toBeDefined();
|
|
28
|
+
// model.name comes from getFallbackName() when no workspace
|
|
29
|
+
expect(registryEntry!.name).toBe(model.name);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('no extra or missing ids in registry', () => {
|
|
34
|
+
const models = listThinkingModels();
|
|
35
|
+
const modelIdSet = new Set(models.map(m => m.id));
|
|
36
|
+
const registryIdSet = new Set(CORE_PRINCIPLE_IDS);
|
|
37
|
+
expect(registryIdSet).toEqual(modelIdSet);
|
|
38
|
+
});
|
|
39
|
+
});
|