principles-disciple 1.6.0 โ 1.7.1
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/dist/commands/context.js +7 -3
- package/dist/commands/evolution-status.d.ts +4 -0
- package/dist/commands/evolution-status.js +134 -0
- package/dist/commands/export.d.ts +2 -0
- package/dist/commands/export.js +45 -0
- package/dist/commands/focus.js +9 -6
- package/dist/commands/pain.js +8 -0
- package/dist/commands/principle-rollback.d.ts +4 -0
- package/dist/commands/principle-rollback.js +22 -0
- package/dist/commands/rollback.js +9 -3
- package/dist/commands/samples.d.ts +2 -0
- package/dist/commands/samples.js +55 -0
- package/dist/commands/trust.js +64 -81
- package/dist/core/config.d.ts +5 -0
- package/dist/core/control-ui-db.d.ts +68 -0
- package/dist/core/control-ui-db.js +274 -0
- package/dist/core/detection-funnel.d.ts +1 -1
- package/dist/core/detection-funnel.js +4 -0
- package/dist/core/dictionary.d.ts +2 -0
- package/dist/core/dictionary.js +13 -0
- package/dist/core/event-log.d.ts +7 -1
- package/dist/core/event-log.js +10 -0
- package/dist/core/evolution-engine.d.ts +5 -5
- package/dist/core/evolution-engine.js +18 -18
- package/dist/core/evolution-migration.d.ts +5 -0
- package/dist/core/evolution-migration.js +65 -0
- package/dist/core/evolution-reducer.d.ts +69 -0
- package/dist/core/evolution-reducer.js +369 -0
- package/dist/core/evolution-types.d.ts +103 -0
- package/dist/core/path-resolver.js +75 -36
- package/dist/core/paths.d.ts +7 -8
- package/dist/core/paths.js +48 -40
- package/dist/core/profile.js +1 -1
- package/dist/core/session-tracker.d.ts +14 -2
- package/dist/core/session-tracker.js +75 -9
- package/dist/core/thinking-models.d.ts +38 -0
- package/dist/core/thinking-models.js +170 -0
- package/dist/core/trajectory.d.ts +184 -0
- package/dist/core/trajectory.js +817 -0
- package/dist/core/trust-engine.d.ts +6 -0
- package/dist/core/trust-engine.js +50 -29
- package/dist/core/workspace-context.d.ts +13 -0
- package/dist/core/workspace-context.js +50 -7
- package/dist/hooks/gate.js +171 -87
- package/dist/hooks/llm.js +119 -71
- package/dist/hooks/pain.js +105 -5
- package/dist/hooks/prompt.d.ts +11 -14
- package/dist/hooks/prompt.js +283 -57
- package/dist/hooks/subagent.js +69 -28
- package/dist/hooks/trajectory-collector.d.ts +32 -0
- package/dist/hooks/trajectory-collector.js +256 -0
- package/dist/http/principles-console-route.d.ts +2 -0
- package/dist/http/principles-console-route.js +257 -0
- package/dist/i18n/commands.js +16 -0
- package/dist/index.js +105 -4
- package/dist/service/control-ui-query-service.d.ts +217 -0
- package/dist/service/control-ui-query-service.js +537 -0
- package/dist/service/empathy-observer-manager.d.ts +2 -0
- package/dist/service/empathy-observer-manager.js +43 -1
- package/dist/service/evolution-worker.d.ts +27 -0
- package/dist/service/evolution-worker.js +256 -41
- package/dist/service/runtime-summary-service.d.ts +79 -0
- package/dist/service/runtime-summary-service.js +319 -0
- package/dist/service/trajectory-service.d.ts +2 -0
- package/dist/service/trajectory-service.js +15 -0
- package/dist/tools/agent-spawn.d.ts +27 -6
- package/dist/tools/agent-spawn.js +339 -87
- package/dist/tools/deep-reflect.d.ts +27 -7
- package/dist/tools/deep-reflect.js +210 -121
- package/dist/types/event-types.d.ts +10 -2
- package/dist/types.d.ts +10 -0
- package/dist/types.js +5 -0
- package/openclaw.plugin.json +43 -11
- package/package.json +14 -4
- package/templates/langs/zh/skills/pd-daily/SKILL.md +97 -13
package/dist/commands/context.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
|
+
import { defaultContextConfig } from '../types.js';
|
|
3
4
|
import { loadContextInjectionConfig } from '../hooks/prompt.js';
|
|
4
5
|
/**
|
|
5
6
|
* Get workspace directory from context
|
|
@@ -185,7 +186,8 @@ function applyPreset(workspaceDir, preset, isZh) {
|
|
|
185
186
|
thinkingOs: false,
|
|
186
187
|
trustScore: true,
|
|
187
188
|
reflectionLog: false,
|
|
188
|
-
projectFocus: 'off'
|
|
189
|
+
projectFocus: 'off',
|
|
190
|
+
evolutionContext: { ...defaultContextConfig.evolutionContext }
|
|
189
191
|
};
|
|
190
192
|
break;
|
|
191
193
|
case 'standard':
|
|
@@ -193,7 +195,8 @@ function applyPreset(workspaceDir, preset, isZh) {
|
|
|
193
195
|
thinkingOs: true,
|
|
194
196
|
trustScore: true,
|
|
195
197
|
reflectionLog: false,
|
|
196
|
-
projectFocus: 'off'
|
|
198
|
+
projectFocus: 'off',
|
|
199
|
+
evolutionContext: { ...defaultContextConfig.evolutionContext }
|
|
197
200
|
};
|
|
198
201
|
break;
|
|
199
202
|
case 'full':
|
|
@@ -201,7 +204,8 @@ function applyPreset(workspaceDir, preset, isZh) {
|
|
|
201
204
|
thinkingOs: true,
|
|
202
205
|
trustScore: true,
|
|
203
206
|
reflectionLog: true,
|
|
204
|
-
projectFocus: 'summary'
|
|
207
|
+
projectFocus: 'summary',
|
|
208
|
+
evolutionContext: { ...defaultContextConfig.evolutionContext }
|
|
205
209
|
};
|
|
206
210
|
break;
|
|
207
211
|
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { EvolutionReducerImpl } from '../core/evolution-reducer.js';
|
|
2
|
+
import { normalizeLanguage } from '../i18n/commands.js';
|
|
3
|
+
import { RuntimeSummaryService } from '../service/runtime-summary-service.js';
|
|
4
|
+
function formatAge(ageSeconds, lang) {
|
|
5
|
+
if (ageSeconds === null) {
|
|
6
|
+
return '--';
|
|
7
|
+
}
|
|
8
|
+
if (ageSeconds < 60) {
|
|
9
|
+
return lang === 'zh' ? `${ageSeconds} \u79d2` : `${ageSeconds}s`;
|
|
10
|
+
}
|
|
11
|
+
const minutes = Math.floor(ageSeconds / 60);
|
|
12
|
+
if (minutes < 60) {
|
|
13
|
+
return lang === 'zh' ? `${minutes} \u5206\u949f` : `${minutes}m`;
|
|
14
|
+
}
|
|
15
|
+
const hours = Math.floor(minutes / 60);
|
|
16
|
+
if (hours < 24) {
|
|
17
|
+
return lang === 'zh' ? `${hours} \u5c0f\u65f6` : `${hours}h`;
|
|
18
|
+
}
|
|
19
|
+
const days = Math.floor(hours / 24);
|
|
20
|
+
return lang === 'zh' ? `${days} \u5929` : `${days}d`;
|
|
21
|
+
}
|
|
22
|
+
function formatNumber(value) {
|
|
23
|
+
if (value === null || Number.isNaN(value)) {
|
|
24
|
+
return '--';
|
|
25
|
+
}
|
|
26
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(1);
|
|
27
|
+
}
|
|
28
|
+
function formatStage(value) {
|
|
29
|
+
return value === null ? '--' : String(value);
|
|
30
|
+
}
|
|
31
|
+
function formatSources(sources) {
|
|
32
|
+
if (sources.length === 0) {
|
|
33
|
+
return '--';
|
|
34
|
+
}
|
|
35
|
+
return sources
|
|
36
|
+
.map((source) => source.score === undefined
|
|
37
|
+
? source.source
|
|
38
|
+
: `${source.source}(${formatNumber(source.score)})`)
|
|
39
|
+
.join(', ');
|
|
40
|
+
}
|
|
41
|
+
function buildEnglishOutput(workspaceDir, sessionId, warnings, stats, summary) {
|
|
42
|
+
const lines = [
|
|
43
|
+
'Evolution Status',
|
|
44
|
+
'================',
|
|
45
|
+
'',
|
|
46
|
+
'Control Plane',
|
|
47
|
+
`- Legacy Trust: ${formatNumber(summary.legacyTrust.score)}/100 (stage ${formatStage(summary.legacyTrust.stage)}, legacy/frozen, ${summary.legacyTrust.rewardPolicy})`,
|
|
48
|
+
`- Session GFI: current ${formatNumber(summary.gfi.current)}, peak ${formatNumber(summary.gfi.peak)} (${summary.gfi.dataQuality})`,
|
|
49
|
+
`- GFI Sources: ${formatSources(summary.gfi.sources)}`,
|
|
50
|
+
`- Pain Flag: ${summary.pain.activeFlag ? 'active' : 'inactive'}${summary.pain.activeFlagSource ? ` (${summary.pain.activeFlagSource})` : ''}`,
|
|
51
|
+
`- Last Pain Signal: ${summary.pain.lastSignal ? `${summary.pain.lastSignal.source}${summary.pain.lastSignal.reason ? ` - ${summary.pain.lastSignal.reason}` : ''}` : '--'}`,
|
|
52
|
+
`- Gate Events: blocks ${formatNumber(summary.gate.recentBlocks)}, bypasses ${formatNumber(summary.gate.recentBypasses)} (${summary.gate.dataQuality})`,
|
|
53
|
+
'',
|
|
54
|
+
'Evolution',
|
|
55
|
+
`- Queue: pending ${summary.evolution.queue.pending}, in_progress ${summary.evolution.queue.inProgress}, completed ${summary.evolution.queue.completed} (${summary.evolution.dataQuality})`,
|
|
56
|
+
`- Directive: ${summary.evolution.directive.exists ? 'present' : 'missing'}, active ${summary.evolution.directive.active === null ? '--' : summary.evolution.directive.active ? 'yes' : 'no'}, age ${formatAge(summary.evolution.directive.ageSeconds, 'en')}`,
|
|
57
|
+
`- Directive Task: ${summary.evolution.directive.taskPreview ?? '--'}`,
|
|
58
|
+
'',
|
|
59
|
+
'Principles',
|
|
60
|
+
`- candidate principles: ${stats.candidateCount}`,
|
|
61
|
+
`- probation principles: ${stats.probationCount}`,
|
|
62
|
+
`- active principles: ${stats.activeCount}`,
|
|
63
|
+
`- deprecated principles: ${stats.deprecatedCount}`,
|
|
64
|
+
`- last promoted: ${stats.lastPromotedAt ?? 'none'}`,
|
|
65
|
+
'',
|
|
66
|
+
'Metadata',
|
|
67
|
+
`- workspace: ${workspaceDir}`,
|
|
68
|
+
`- session: ${sessionId ?? '--'} (${summary.metadata.selectedSessionReason})`,
|
|
69
|
+
`- generatedAt: ${summary.metadata.generatedAt}`,
|
|
70
|
+
];
|
|
71
|
+
if (warnings.length > 0) {
|
|
72
|
+
lines.push('', 'Warnings');
|
|
73
|
+
for (const warning of warnings) {
|
|
74
|
+
lines.push(`- ${warning}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return lines.join('\n');
|
|
78
|
+
}
|
|
79
|
+
function buildChineseOutput(workspaceDir, sessionId, warnings, stats, summary) {
|
|
80
|
+
const lines = [
|
|
81
|
+
'\u8fdb\u5316\u72b6\u6001',
|
|
82
|
+
'================',
|
|
83
|
+
'',
|
|
84
|
+
'\u63a7\u5236\u9762',
|
|
85
|
+
`- Legacy Trust: ${formatNumber(summary.legacyTrust.score)}/100\uff08\u9636\u6bb5 ${formatStage(summary.legacyTrust.stage)}\uff0clegacy/frozen\uff0c${summary.legacyTrust.rewardPolicy}\uff09`,
|
|
86
|
+
`- \u4f1a\u8bdd GFI: \u5f53\u524d ${formatNumber(summary.gfi.current)}\uff0c\u5cf0\u503c ${formatNumber(summary.gfi.peak)}\uff08${summary.gfi.dataQuality}\uff09`,
|
|
87
|
+
`- GFI \u6765\u6e90: ${formatSources(summary.gfi.sources)}`,
|
|
88
|
+
`- Pain Flag: ${summary.pain.activeFlag ? 'active' : 'inactive'}${summary.pain.activeFlagSource ? `\uff08${summary.pain.activeFlagSource}\uff09` : ''}`,
|
|
89
|
+
`- \u6700\u8fd1 Pain \u4fe1\u53f7: ${summary.pain.lastSignal ? `${summary.pain.lastSignal.source}${summary.pain.lastSignal.reason ? ` - ${summary.pain.lastSignal.reason}` : ''}` : '--'}`,
|
|
90
|
+
`- Gate \u4e8b\u4ef6: block ${formatNumber(summary.gate.recentBlocks)}\uff0cbypass ${formatNumber(summary.gate.recentBypasses)}\uff08${summary.gate.dataQuality}\uff09`,
|
|
91
|
+
'',
|
|
92
|
+
'\u8fdb\u5316',
|
|
93
|
+
`- \u961f\u5217: pending ${summary.evolution.queue.pending}\uff0cin_progress ${summary.evolution.queue.inProgress}\uff0ccompleted ${summary.evolution.queue.completed}\uff08${summary.evolution.dataQuality}\uff09`,
|
|
94
|
+
`- Directive: ${summary.evolution.directive.exists ? 'present' : 'missing'}\uff0cactive ${summary.evolution.directive.active === null ? '--' : summary.evolution.directive.active ? 'yes' : 'no'}\uff0cage ${formatAge(summary.evolution.directive.ageSeconds, 'zh')}`,
|
|
95
|
+
`- Directive \u4efb\u52a1: ${summary.evolution.directive.taskPreview ?? '--'}`,
|
|
96
|
+
'',
|
|
97
|
+
'\u539f\u5219\u7edf\u8ba1',
|
|
98
|
+
`- \u5019\u9009\u539f\u5219: ${stats.candidateCount}`,
|
|
99
|
+
`- \u89c2\u5bdf\u671f\u539f\u5219: ${stats.probationCount}`,
|
|
100
|
+
`- \u751f\u6548\u539f\u5219: ${stats.activeCount}`,
|
|
101
|
+
`- \u5df2\u5e9f\u5f03\u539f\u5219: ${stats.deprecatedCount}`,
|
|
102
|
+
`- \u6700\u8fd1\u664b\u5347: ${stats.lastPromotedAt ?? '\u65e0'}`,
|
|
103
|
+
'',
|
|
104
|
+
'\u5143\u6570\u636e',
|
|
105
|
+
`- \u5de5\u4f5c\u533a: ${workspaceDir}`,
|
|
106
|
+
`- Session: ${sessionId ?? '--'}\uff08${summary.metadata.selectedSessionReason}\uff09`,
|
|
107
|
+
`- \u751f\u6210\u65f6\u95f4: ${summary.metadata.generatedAt}`,
|
|
108
|
+
];
|
|
109
|
+
if (warnings.length > 0) {
|
|
110
|
+
lines.push('', '่ญฆๅ');
|
|
111
|
+
for (const warning of warnings) {
|
|
112
|
+
lines.push(`- ${warning}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return lines.join('\n');
|
|
116
|
+
}
|
|
117
|
+
export function handleEvolutionStatusCommand(ctx) {
|
|
118
|
+
const workspaceDir = ctx.config?.workspaceDir || process.cwd();
|
|
119
|
+
const sessionId = ctx.sessionId ?? null;
|
|
120
|
+
const reducer = new EvolutionReducerImpl({ workspaceDir });
|
|
121
|
+
const stats = reducer.getStats();
|
|
122
|
+
const summary = RuntimeSummaryService.getSummary(workspaceDir, { sessionId });
|
|
123
|
+
const rawLang = ctx.config?.language || 'en';
|
|
124
|
+
const lang = normalizeLanguage(rawLang);
|
|
125
|
+
const warnings = summary.metadata.warnings.slice(0, 12);
|
|
126
|
+
if (lang === 'zh') {
|
|
127
|
+
return {
|
|
128
|
+
text: buildChineseOutput(workspaceDir, summary.metadata.sessionId, warnings, stats, summary),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
text: buildEnglishOutput(workspaceDir, summary.metadata.sessionId, warnings, stats, summary),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
2
|
+
function isZh(ctx) {
|
|
3
|
+
return String(ctx.config?.language || 'en').startsWith('zh');
|
|
4
|
+
}
|
|
5
|
+
export function handleExportCommand(ctx) {
|
|
6
|
+
const workspaceDir = ctx.config?.workspaceDir || process.cwd();
|
|
7
|
+
const zh = isZh(ctx);
|
|
8
|
+
const args = (ctx.args || '').trim();
|
|
9
|
+
const [subcommand = 'corrections'] = args.split(/\s+/).filter(Boolean);
|
|
10
|
+
const wctx = WorkspaceContext.fromHookContext({ workspaceDir, ...ctx.config });
|
|
11
|
+
if (subcommand !== 'analytics' && subcommand !== 'corrections') {
|
|
12
|
+
return {
|
|
13
|
+
text: zh
|
|
14
|
+
? 'ๆ ๆ็ๅฏผๅบ็ฑปๅใ่ฏทไฝฟ็จ `analytics` ๆ `corrections [--redacted]`ใ'
|
|
15
|
+
: 'Invalid export target. Use `analytics` or `corrections [--redacted]`.',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
if (subcommand === 'analytics') {
|
|
20
|
+
const result = wctx.trajectory.exportAnalytics();
|
|
21
|
+
return {
|
|
22
|
+
text: zh
|
|
23
|
+
? `ๅทฒๅฏผๅบ analytics ๅฟซ็
งๅฐ ${result.filePath}๏ผๅ
ฑ ${result.count} ๆก่ๅ่ฎฐๅฝใ`
|
|
24
|
+
: `Exported analytics snapshot to ${result.filePath} (${result.count} aggregated rows).`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const redacted = args.includes('--redacted');
|
|
28
|
+
const result = wctx.trajectory.exportCorrections({
|
|
29
|
+
mode: redacted ? 'redacted' : 'raw',
|
|
30
|
+
approvedOnly: true,
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
text: zh
|
|
34
|
+
? `ๅทฒๅฏผๅบ็บ ้ๆ ทๆฌๅฐ ${result.filePath}๏ผๆจกๅผ ${result.mode}๏ผๅ
ฑ ${result.count} ๆกใ`
|
|
35
|
+
: `Exported correction samples to ${result.filePath} (mode=${result.mode}, count=${result.count}).`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return {
|
|
40
|
+
text: zh
|
|
41
|
+
? 'ๅฏผๅบๅคฑ่ดฅ๏ผ่ฏทๆฃๆฅๆฅๅฟใ'
|
|
42
|
+
: 'Export failed. Check logs.',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
package/dist/commands/focus.js
CHANGED
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import * as fs from 'fs';
|
|
11
11
|
import * as path from 'path';
|
|
12
|
+
import { randomUUID } from 'node:crypto';
|
|
12
13
|
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
13
14
|
import { getHistoryDir, backupToHistory, cleanupHistory, extractVersion, extractDate, } from '../core/focus-history.js';
|
|
14
|
-
import {
|
|
15
|
+
import { createAgentSpawnTool } from '../tools/agent-spawn.js';
|
|
15
16
|
/**
|
|
16
17
|
* ๆธ
็ Markdown ไปฃ็ ๅๅดๆ
|
|
17
18
|
* ็งป้คๅผๅคด็ ```lang ๅ็ปๅฐพ็ ```
|
|
@@ -329,14 +330,16 @@ If no milestones to record, leave ===MEMORY=== section empty.`;
|
|
|
329
330
|
let memoryUpdated = false;
|
|
330
331
|
try {
|
|
331
332
|
// ่ฐ็จๅญๆบ่ฝไฝ่ฟ่กๅ็ผฉ
|
|
332
|
-
const
|
|
333
|
+
const tool = createAgentSpawnTool(api);
|
|
334
|
+
const result = await tool.execute(`focus-compress-${randomUUID()}`, {
|
|
333
335
|
agentType: 'reporter', // ไฝฟ็จ reporter ็ฑปๅ๏ผ้ๅๆป็ปๅๅ็ผฉ
|
|
334
336
|
task: compressPrompt,
|
|
335
|
-
}
|
|
337
|
+
});
|
|
336
338
|
// ่งฃๆ่พๅบ๏ผๆๅ MEMORY ๅ COMPRESSED ้จๅ
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const
|
|
339
|
+
const resultText = result?.content?.[0]?.text || '';
|
|
340
|
+
if (resultText.trim()) {
|
|
341
|
+
const memoryMatch = resultText.match(/===MEMORY===([\s\S]*?)===COMPRESSED===/);
|
|
342
|
+
const compressedMatch = resultText.match(/===COMPRESSED===([\s\S]*?)$/);
|
|
340
343
|
if (compressedMatch && compressedMatch[1].trim()) {
|
|
341
344
|
// ๆธ
็ Markdown ไปฃ็ ๅๅดๆ
|
|
342
345
|
compressedContent = stripMarkdownFence(compressedMatch[1]);
|
package/dist/commands/pain.js
CHANGED
|
@@ -93,6 +93,14 @@ export function handlePainCommand(ctx) {
|
|
|
93
93
|
const newScore = wctx.trust.getScore();
|
|
94
94
|
return { text: isZh ? `โ
ๆบ่ฝไฝไฟกไปปๅๅทฒ้็ฝฎไธบๅๅงๅผ (${newScore})ใ` : `โ
Agent trust score has been reset to initial value (${newScore}).` };
|
|
95
95
|
}
|
|
96
|
+
if (args === 'data') {
|
|
97
|
+
const stats = wctx.trajectory.getDataStats();
|
|
98
|
+
return {
|
|
99
|
+
text: isZh
|
|
100
|
+
? `่ฝจ่ฟนๆฐๆฎ็ถๆ\n- ๆฐๆฎๅบ: ${stats.dbPath}\n- ๅฉๆ่ฝฎๆฌก: ${stats.assistantTurns}\n- ็จๆท่ฝฎๆฌก: ${stats.userTurns}\n- ๅทฅๅ
ท่ฐ็จ: ${stats.toolCalls}\n- ็ๆไบไปถ: ${stats.painEvents}\n- ๅพ
ๅฎกๆ ธๆ ทๆฌ: ${stats.pendingSamples}\n- ๅทฒ้่ฟๆ ทๆฌ: ${stats.approvedSamples}\n- Blob ๅญ่ๆฐ: ${stats.blobBytes}\n- ๆ่ฟๅๅ
ฅ: ${stats.lastIngestAt ?? 'none'}`
|
|
101
|
+
: `Trajectory Data Status\n- DB: ${stats.dbPath}\n- assistant turns: ${stats.assistantTurns}\n- user turns: ${stats.userTurns}\n- tool calls: ${stats.toolCalls}\n- pain events: ${stats.painEvents}\n- pending samples: ${stats.pendingSamples}\n- approved samples: ${stats.approvedSamples}\n- blob bytes: ${stats.blobBytes}\n- last ingest: ${stats.lastIngestAt ?? 'none'}`
|
|
102
|
+
};
|
|
103
|
+
}
|
|
96
104
|
// Default: Show status
|
|
97
105
|
const session = sessionId ? getSession(sessionId) : undefined;
|
|
98
106
|
const gfi = session ? session.currentGfi : 0;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { EvolutionReducerImpl } from '../core/evolution-reducer.js';
|
|
2
|
+
export function handlePrincipleRollbackCommand(ctx) {
|
|
3
|
+
const workspaceDir = ctx.config?.workspaceDir || process.cwd();
|
|
4
|
+
const argText = (ctx.args || '').trim();
|
|
5
|
+
const [principleId = '', ...reasonParts] = argText.split(/\s+/);
|
|
6
|
+
const reason = (reasonParts.join(' ') || 'manual rollback').trim();
|
|
7
|
+
const isZh = ctx.config?.language?.startsWith('zh');
|
|
8
|
+
if (!principleId) {
|
|
9
|
+
return { text: isZh ? '็จๆณ: /pd-principle-rollback <principleId> [reason]' : 'Usage: /pd-principle-rollback <principleId> [reason]' };
|
|
10
|
+
}
|
|
11
|
+
const reducer = new EvolutionReducerImpl({ workspaceDir });
|
|
12
|
+
const principle = reducer.getPrincipleById(principleId);
|
|
13
|
+
if (!principle) {
|
|
14
|
+
return { text: isZh ? `ๆชๆพๅฐๅๅ: ${principleId}` : `Principle not found: ${principleId}` };
|
|
15
|
+
}
|
|
16
|
+
reducer.rollbackPrinciple(principleId, reason);
|
|
17
|
+
return {
|
|
18
|
+
text: isZh
|
|
19
|
+
? `โ
ๅทฒๅๆปๅๅ ${principleId}\nๅๅ : ${reason}`
|
|
20
|
+
: `โ
Rolled back principle ${principleId}\nReason: ${reason}`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -63,7 +63,10 @@ Usage:
|
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
// Reduce the GFI by the rolled back score
|
|
66
|
-
resetFriction(sessionId
|
|
66
|
+
resetFriction(sessionId, workspaceDir, {
|
|
67
|
+
source: 'user_empathy',
|
|
68
|
+
amount: rolledBackScore,
|
|
69
|
+
});
|
|
67
70
|
return {
|
|
68
71
|
text: isZh
|
|
69
72
|
? `โ
ๅทฒๅๆปๆ
็ปชไบไปถ
|
|
@@ -107,8 +110,11 @@ export function handleNaturalLanguageRollback(wctx, sessionId, reason) {
|
|
|
107
110
|
message: isZh ? 'ๅๆปๅคฑ่ดฅ๏ผไบไปถๅฏ่ฝไธๅญๅจ' : 'Rollback failed, event may not exist'
|
|
108
111
|
};
|
|
109
112
|
}
|
|
110
|
-
// Reduce the GFI
|
|
111
|
-
resetFriction(sessionId
|
|
113
|
+
// Reduce only the empathy slice instead of wiping the whole session GFI.
|
|
114
|
+
resetFriction(sessionId, wctx.workspaceDir, {
|
|
115
|
+
source: 'user_empathy',
|
|
116
|
+
amount: rolledBackScore,
|
|
117
|
+
});
|
|
112
118
|
return {
|
|
113
119
|
success: true,
|
|
114
120
|
score: rolledBackScore,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
2
|
+
function isZh(ctx) {
|
|
3
|
+
return String(ctx.config?.language || 'en').startsWith('zh');
|
|
4
|
+
}
|
|
5
|
+
export function handleSamplesCommand(ctx) {
|
|
6
|
+
const workspaceDir = ctx.config?.workspaceDir || process.cwd();
|
|
7
|
+
const zh = isZh(ctx);
|
|
8
|
+
const args = (ctx.args || '').trim();
|
|
9
|
+
const wctx = WorkspaceContext.fromHookContext({ workspaceDir, ...ctx.config });
|
|
10
|
+
if (args.startsWith('review ')) {
|
|
11
|
+
const [, decision = '', sampleId = '', ...noteParts] = args.split(/\s+/);
|
|
12
|
+
if (decision !== 'approve' && decision !== 'reject') {
|
|
13
|
+
return {
|
|
14
|
+
text: zh
|
|
15
|
+
? 'ๆ ๆ็ๅฎกๆ ธๅจไฝใ่ฏทไฝฟ็จ `review approve <sample-id> [note]` ๆ `review reject <sample-id> [note]`ใ'
|
|
16
|
+
: 'Invalid review action. Use `review approve <sample-id> [note]` or `review reject <sample-id> [note]`.',
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (!sampleId) {
|
|
20
|
+
return {
|
|
21
|
+
text: zh
|
|
22
|
+
? '็ผบๅฐ sample-idใ'
|
|
23
|
+
: 'Missing sample-id.',
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const normalizedDecision = decision === 'approve' ? 'approved' : 'rejected';
|
|
27
|
+
const note = noteParts.join(' ').trim();
|
|
28
|
+
let record;
|
|
29
|
+
try {
|
|
30
|
+
record = wctx.trajectory.reviewCorrectionSample(sampleId, normalizedDecision, note);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return {
|
|
34
|
+
text: zh
|
|
35
|
+
? `ๅฎกๆ ธๆ ทๆฌๅคฑ่ดฅ๏ผ${sampleId}`
|
|
36
|
+
: `Failed to review sample: ${sampleId}`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
text: zh
|
|
41
|
+
? `ๆ ทๆฌ ${record.sampleId} ๅทฒๆ ่ฎฐไธบ ${record.reviewStatus}ใ`
|
|
42
|
+
: `Sample ${record.sampleId} marked as ${record.reviewStatus}.`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const samples = wctx.trajectory.listCorrectionSamples('pending');
|
|
46
|
+
if (samples.length === 0) {
|
|
47
|
+
return { text: zh ? 'ๅฝๅๆฒกๆๅพ
ๅฎกๆ ธ็บ ้ๆ ทๆฌใ' : 'No pending correction samples.' };
|
|
48
|
+
}
|
|
49
|
+
const lines = samples.map((sample) => `- ${sample.sampleId} | session=${sample.sessionId} | score=${sample.qualityScore}`);
|
|
50
|
+
return {
|
|
51
|
+
text: zh
|
|
52
|
+
? `ๅพ
ๅฎกๆ ธ็บ ้ๆ ทๆฌ:\n${lines.join('\n')}`
|
|
53
|
+
: `Pending correction samples:\n${lines.join('\n')}`,
|
|
54
|
+
};
|
|
55
|
+
}
|
package/dist/commands/trust.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
function createProgressBar(value, max, length = 12) {
|
|
3
|
+
const safeValue = Math.max(0, Math.min(max, value));
|
|
4
|
+
const filledLength = Math.round((safeValue / max) * length);
|
|
5
|
+
const emptyLength = Math.max(0, length - filledLength);
|
|
6
|
+
return `[${'#'.repeat(filledLength)}${'-'.repeat(emptyLength)}]`;
|
|
7
|
+
}
|
|
8
|
+
function formatStageTitle(stage, isZh) {
|
|
9
|
+
const titles = isZh
|
|
10
|
+
? ['Observer', 'Editor', 'Developer', 'Architect']
|
|
11
|
+
: ['Observer', 'Editor', 'Developer', 'Architect'];
|
|
12
|
+
return titles[Math.max(0, Math.min(3, stage - 1))] ?? 'Unknown';
|
|
9
13
|
}
|
|
10
14
|
export function handleTrustCommand(ctx) {
|
|
11
15
|
const { workspaceDir } = ctx;
|
|
@@ -14,82 +18,61 @@ export function handleTrustCommand(ctx) {
|
|
|
14
18
|
const wctx = WorkspaceContext.fromHookContext(ctx);
|
|
15
19
|
const trustEngine = wctx.trust;
|
|
16
20
|
const trustScore = trustEngine.getScore();
|
|
17
|
-
const
|
|
21
|
+
const stage = trustEngine.getStage();
|
|
18
22
|
const isZh = wctx.config.get('language') === 'zh';
|
|
19
|
-
|
|
20
|
-
let title = isZh ? '็ผ่พ่
' : 'Editor';
|
|
21
|
-
let permissions = isZh
|
|
22
|
-
? `- ๅ
่ฎธๅฐ่ๅดไฟฎๆน (< ${trustSettings.limits.stage_2_max_lines} ่ก)\n- ็ฆๆญขไฟฎๆน้ฃ้ฉ็ฎๅฝ`
|
|
23
|
-
: `- Small modifications (< ${trustSettings.limits.stage_2_max_lines} lines)\n- Non-risk paths only`;
|
|
24
|
-
let nextLevel = `Trust Score >= ${trustSettings.stages.stage_3_developer}`;
|
|
25
|
-
if (trustScore < trustSettings.stages.stage_1_observer) {
|
|
26
|
-
stage = 1;
|
|
27
|
-
title = isZh ? '่งๅฏ่
(ๅช่ฏปๆจกๅผ)' : 'Observer (Read-only)';
|
|
28
|
-
permissions = isZh ? '- ไป
้ๅช่ฏป่ฎฟ้ฎ\n- ไป
้่ฏๆญๅทฅๅ
ท' : '- Read-only access\n- Diagnosis tools only';
|
|
29
|
-
nextLevel = `Trust Score >= ${trustSettings.stages.stage_1_observer}`;
|
|
30
|
-
}
|
|
31
|
-
else if (trustScore < trustSettings.stages.stage_2_editor) {
|
|
32
|
-
// Default stage 2
|
|
33
|
-
nextLevel = `Trust Score >= ${trustSettings.stages.stage_2_editor}`;
|
|
34
|
-
}
|
|
35
|
-
else if (trustScore < trustSettings.stages.stage_3_developer) {
|
|
36
|
-
stage = 3;
|
|
37
|
-
title = isZh ? 'ๅผๅ่
' : 'Developer';
|
|
38
|
-
permissions = isZh
|
|
39
|
-
? `- ๅ
่ฎธไธญ็ญ่ๅดไฟฎๆน (< ${trustSettings.limits.stage_3_max_lines} ่ก)\n- ้ฃ้ฉ็ฎๅฝไฟฎๆน้่ฆๆ PLAN (่ฎกๅ)`
|
|
40
|
-
: `- Medium modifications (< ${trustSettings.limits.stage_3_max_lines} lines)\n- Risk paths require READY plan`;
|
|
41
|
-
nextLevel = `Trust Score >= ${trustSettings.stages.stage_3_developer}`;
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
stage = 4;
|
|
45
|
-
title = isZh ? 'ๆถๆๅธ' : 'Architect';
|
|
46
|
-
permissions = isZh ? '- ๐จ **ๆ ้ๅถ่ฎฟ้ฎ**\n- ่ฎกๅๅๅฎก่ฎก้ๅผบๅถ่ฆๆฑ' : '- ๐จ **UNRESTRICTED access**\n- Plan and Audit are optional';
|
|
47
|
-
nextLevel = isZh ? 'ๅทฒ่พพๆ้ซ็บง' : 'MAX LEVEL REACHED';
|
|
48
|
-
}
|
|
49
|
-
const progressBar = createProgressBar(trustScore, 100, 15);
|
|
23
|
+
const scorecard = trustEngine.getScorecard();
|
|
50
24
|
const hygiene = wctx.hygiene.getStats();
|
|
51
|
-
const
|
|
52
|
-
const
|
|
25
|
+
const trustBar = createProgressBar(trustScore, 100);
|
|
26
|
+
const hygieneScore = Math.min(100, hygiene.persistenceCount * 10);
|
|
27
|
+
const hygieneBar = createProgressBar(hygieneScore, 100);
|
|
28
|
+
const rewardPolicy = scorecard.reward_policy ?? 'frozen_all_positive';
|
|
29
|
+
const lastUpdated = scorecard.last_updated ?? '--';
|
|
53
30
|
if (isZh) {
|
|
54
|
-
return
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
${
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
78
|
-
๐ก๏ธ **Security Stage**: Stage ${stage} (${title})
|
|
79
|
-
๐ฐ **Trust Score**: ${progressBar} ${trustScore}/100
|
|
80
|
-
๐ง **Cognitive Hygiene**: ${hygieneBar} ${hygiene.persistenceCount} actions (Today)
|
|
81
|
-
|
|
82
|
-
**Current Permissions**:
|
|
83
|
-
${permissions}
|
|
84
|
-
|
|
85
|
-
**Knowledge Assets Today**:
|
|
86
|
-
- Physical Persists: ${hygiene.persistenceCount} actions
|
|
87
|
-
- Total Chars: ${hygiene.totalCharsPersisted} chars
|
|
88
|
-
- Workspace Grooming: ${hygiene.groomingExecutedCount > 0 ? '๐ข Good' : '๐ก Pending'}
|
|
89
|
-
|
|
90
|
-
**Next Promotion Requirement**: ${nextLevel}
|
|
91
|
-
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
92
|
-
*๐ก Hint: Frequent notes (PLAN.md/memory) prevent amnesia and ensure task continuity.*
|
|
93
|
-
`.trim();
|
|
31
|
+
return [
|
|
32
|
+
'Principles Disciple - Legacy Trust',
|
|
33
|
+
'=================================',
|
|
34
|
+
'',
|
|
35
|
+
`- Legacy Trust: ${trustBar} ${trustScore}/100`,
|
|
36
|
+
`- Stage: ${stage} (${formatStageTitle(stage, true)})`,
|
|
37
|
+
`- Status: legacy/frozen`,
|
|
38
|
+
`- Reward Policy: ${rewardPolicy}`,
|
|
39
|
+
`- Last Updated: ${lastUpdated}`,
|
|
40
|
+
'',
|
|
41
|
+
'่ฏดๆ',
|
|
42
|
+
'- ่ฟๆฏๅ
ผๅฎนๆงๆงๅถ้ข็ legacy trust ่งๅพ๏ผไธๅไปฃ่กจๆฐ็้ฟๆ่ฝๅๆจกๅใ',
|
|
43
|
+
'- `tool_success` ไธ `subagent_success` ไธๅ่ชๅจๆๅ trustใ',
|
|
44
|
+
'- ๅฝๅ่งๅฏ็ชๅฃๅ
๏ผtrust ไธป่ฆไฟ็ไธบๅ
ผๅฎน่ฏปๆฐไธ gate ๅ
ผๅฎน่พๅ
ฅใ',
|
|
45
|
+
'',
|
|
46
|
+
'่ฎค็ฅๅซ็',
|
|
47
|
+
`- Persistence: ${hygieneBar} ${hygiene.persistenceCount} actions today`,
|
|
48
|
+
`- Total Chars Persisted: ${hygiene.totalCharsPersisted}`,
|
|
49
|
+
`- Workspace Grooming: ${hygiene.groomingExecutedCount > 0 ? 'done' : 'pending'}`,
|
|
50
|
+
'',
|
|
51
|
+
'ไธไธๆญฅ',
|
|
52
|
+
'- ๅจ่ฟๅ
ฅ Phase 3 capability shadow ไนๅ๏ผๅ
็ production observation ๆฐๆฎๆฏๅฆ็จณๅฎใ',
|
|
53
|
+
].join('\n');
|
|
94
54
|
}
|
|
55
|
+
return [
|
|
56
|
+
'Principles Disciple - Legacy Trust',
|
|
57
|
+
'=================================',
|
|
58
|
+
'',
|
|
59
|
+
`- Legacy Trust: ${trustBar} ${trustScore}/100`,
|
|
60
|
+
`- Stage: ${stage} (${formatStageTitle(stage, false)})`,
|
|
61
|
+
'- Status: legacy/frozen',
|
|
62
|
+
`- Reward Policy: ${rewardPolicy}`,
|
|
63
|
+
`- Last Updated: ${lastUpdated}`,
|
|
64
|
+
'',
|
|
65
|
+
'Notes',
|
|
66
|
+
'- This is a compatibility view of legacy trust, not the future long-term capability model.',
|
|
67
|
+
'- `tool_success` and `subagent_success` no longer raise trust automatically.',
|
|
68
|
+
'- During the current observation window, trust remains mainly for compatibility reads and gate compatibility.',
|
|
69
|
+
'',
|
|
70
|
+
'Cognitive Hygiene',
|
|
71
|
+
`- Persistence: ${hygieneBar} ${hygiene.persistenceCount} actions today`,
|
|
72
|
+
`- Total Chars Persisted: ${hygiene.totalCharsPersisted}`,
|
|
73
|
+
`- Workspace Grooming: ${hygiene.groomingExecutedCount > 0 ? 'done' : 'pending'}`,
|
|
74
|
+
'',
|
|
75
|
+
'Next',
|
|
76
|
+
'- Do not move into Phase 3 capability shadow until production observation data is stable.',
|
|
77
|
+
].join('\n');
|
|
95
78
|
}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -65,6 +65,11 @@ export interface TrustSettings {
|
|
|
65
65
|
}
|
|
66
66
|
export interface PainSettings {
|
|
67
67
|
language: 'en' | 'zh';
|
|
68
|
+
trajectory?: {
|
|
69
|
+
blob_inline_threshold_bytes?: number;
|
|
70
|
+
busy_timeout_ms?: number;
|
|
71
|
+
orphan_blob_grace_days?: number;
|
|
72
|
+
};
|
|
68
73
|
thresholds: {
|
|
69
74
|
pain_trigger: number;
|
|
70
75
|
cognitive_paralysis_input: number;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export interface ThinkingModelEventInput {
|
|
2
|
+
sessionId: string;
|
|
3
|
+
runId: string;
|
|
4
|
+
assistantTurnId: number;
|
|
5
|
+
modelId: string;
|
|
6
|
+
matchedPattern: string;
|
|
7
|
+
scenarioJson: unknown;
|
|
8
|
+
toolContextJson: unknown;
|
|
9
|
+
painContextJson: unknown;
|
|
10
|
+
principleContextJson: unknown;
|
|
11
|
+
triggerExcerpt: string;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ControlUiDatabaseOptions {
|
|
15
|
+
workspaceDir: string;
|
|
16
|
+
busyTimeoutMs?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface RecentThinkingContext {
|
|
19
|
+
toolCalls: Array<{
|
|
20
|
+
id: number;
|
|
21
|
+
toolName: string;
|
|
22
|
+
outcome: 'success' | 'failure' | 'blocked';
|
|
23
|
+
errorType: string | null;
|
|
24
|
+
errorMessage: string | null;
|
|
25
|
+
createdAt: string;
|
|
26
|
+
}>;
|
|
27
|
+
painEvents: Array<{
|
|
28
|
+
id: number;
|
|
29
|
+
source: string;
|
|
30
|
+
score: number;
|
|
31
|
+
reason: string | null;
|
|
32
|
+
createdAt: string;
|
|
33
|
+
}>;
|
|
34
|
+
gateBlocks: Array<{
|
|
35
|
+
id: number;
|
|
36
|
+
toolName: string;
|
|
37
|
+
reason: string;
|
|
38
|
+
filePath: string | null;
|
|
39
|
+
createdAt: string;
|
|
40
|
+
}>;
|
|
41
|
+
userCorrections: Array<{
|
|
42
|
+
id: number;
|
|
43
|
+
correctionCue: string | null;
|
|
44
|
+
rawExcerpt: string | null;
|
|
45
|
+
createdAt: string;
|
|
46
|
+
}>;
|
|
47
|
+
principleEvents: Array<{
|
|
48
|
+
id: number;
|
|
49
|
+
principleId: string | null;
|
|
50
|
+
eventType: string;
|
|
51
|
+
createdAt: string;
|
|
52
|
+
}>;
|
|
53
|
+
}
|
|
54
|
+
export declare class ControlUiDatabase {
|
|
55
|
+
private readonly workspaceDir;
|
|
56
|
+
private readonly dbPath;
|
|
57
|
+
private readonly blobDir;
|
|
58
|
+
private readonly db;
|
|
59
|
+
constructor(opts: ControlUiDatabaseOptions);
|
|
60
|
+
dispose(): void;
|
|
61
|
+
recordThinkingModelEvent(input: ThinkingModelEventInput): number;
|
|
62
|
+
getRecentThinkingContext(sessionId: string, beforeCreatedAt: string, limit?: number): RecentThinkingContext;
|
|
63
|
+
all<T>(sql: string, ...params: unknown[]): T[];
|
|
64
|
+
get<T>(sql: string, ...params: unknown[]): T | undefined;
|
|
65
|
+
restoreRawText(inlineText?: string | null, blobRef?: string | null): string;
|
|
66
|
+
private initSchema;
|
|
67
|
+
private withWrite;
|
|
68
|
+
}
|