principles-disciple 1.7.3 → 1.7.5
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/evolution-status.js +4 -2
- package/dist/commands/focus.js +30 -155
- package/dist/constants/diagnostician.d.ts +16 -0
- package/dist/constants/diagnostician.js +60 -0
- package/dist/constants/tools.d.ts +2 -2
- package/dist/constants/tools.js +1 -1
- package/dist/core/config.d.ts +23 -0
- package/dist/core/config.js +26 -1
- package/dist/core/evolution-engine.js +1 -1
- package/dist/core/evolution-logger.d.ts +137 -0
- package/dist/core/evolution-logger.js +256 -0
- package/dist/core/evolution-reducer.d.ts +23 -0
- package/dist/core/evolution-reducer.js +73 -29
- package/dist/core/evolution-types.d.ts +6 -0
- package/dist/core/focus-history.d.ts +145 -0
- package/dist/core/focus-history.js +919 -0
- package/dist/core/init.js +24 -0
- package/dist/core/profile.js +1 -1
- package/dist/core/risk-calculator.d.ts +15 -0
- package/dist/core/risk-calculator.js +48 -0
- package/dist/core/trajectory.d.ts +73 -0
- package/dist/core/trajectory.js +206 -0
- package/dist/hooks/gate.js +130 -20
- package/dist/hooks/lifecycle.js +104 -0
- package/dist/hooks/pain.js +31 -0
- package/dist/hooks/prompt.js +136 -38
- package/dist/hooks/subagent.d.ts +1 -0
- package/dist/hooks/subagent.js +200 -18
- package/dist/http/principles-console-route.d.ts +7 -0
- package/dist/http/principles-console-route.js +301 -1
- package/dist/index.js +0 -2
- package/dist/service/central-database.d.ts +104 -0
- package/dist/service/central-database.js +648 -0
- package/dist/service/control-ui-query-service.d.ts +2 -0
- package/dist/service/control-ui-query-service.js +4 -0
- package/dist/service/empathy-observer-manager.d.ts +8 -0
- package/dist/service/empathy-observer-manager.js +40 -0
- package/dist/service/evolution-query-service.d.ts +155 -0
- package/dist/service/evolution-query-service.js +258 -0
- package/dist/service/evolution-worker.d.ts +4 -0
- package/dist/service/evolution-worker.js +185 -63
- package/dist/service/phase3-input-filter.d.ts +37 -0
- package/dist/service/phase3-input-filter.js +106 -0
- package/dist/service/runtime-summary-service.d.ts +15 -0
- package/dist/service/runtime-summary-service.js +111 -23
- package/dist/tools/deep-reflect.js +8 -2
- package/dist/utils/subagent-probe.d.ts +34 -0
- package/dist/utils/subagent-probe.js +81 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +6 -4
- package/templates/langs/en/core/AGENTS.md +15 -3
- package/templates/langs/en/core/BOOTSTRAP.md +24 -1
- package/templates/langs/en/core/TOOLS.md +9 -0
- package/templates/langs/zh/core/AGENTS.md +15 -3
- package/templates/langs/zh/core/BOOTSTRAP.md +24 -1
- package/templates/langs/zh/core/TOOLS.md +9 -0
- package/templates/langs/zh/skills/pd-auditor/SKILL.md +61 -0
- package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +287 -0
- package/templates/langs/zh/skills/pd-explorer/SKILL.md +65 -0
- package/templates/langs/zh/skills/pd-implementer/SKILL.md +68 -0
- package/templates/langs/zh/skills/pd-planner/SKILL.md +65 -0
- package/templates/langs/zh/skills/pd-reporter/SKILL.md +78 -0
- package/templates/langs/zh/skills/pd-reviewer/SKILL.md +66 -0
- package/dist/core/agent-loader.d.ts +0 -44
- package/dist/core/agent-loader.js +0 -147
- package/dist/tools/agent-spawn.d.ts +0 -54
- package/dist/tools/agent-spawn.js +0 -445
|
@@ -4,6 +4,7 @@ import { readPainFlagData } from '../core/pain.js';
|
|
|
4
4
|
import { resolvePdPath } from '../core/paths.js';
|
|
5
5
|
import { listSessions } from '../core/session-tracker.js';
|
|
6
6
|
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
7
|
+
import { evaluatePhase3Inputs } from './phase3-input-filter.js';
|
|
7
8
|
const MAX_SOURCE_EVENTS = 5;
|
|
8
9
|
const LEGACY_TRUST_REWARD_POLICY = 'frozen_all_positive';
|
|
9
10
|
const GFI_PARTIAL_WARNING = 'GFI source attribution remains partial in Phase 2b because only the empathy slice is source-attributed; most non-empathy friction still lacks full per-source attribution.';
|
|
@@ -51,10 +52,11 @@ export class RuntimeSummaryService {
|
|
|
51
52
|
const queue = this.readJsonFile(wctx.resolve('EVOLUTION_QUEUE'), warnings, false);
|
|
52
53
|
const directive = this.readJsonFile(wctx.resolve('EVOLUTION_DIRECTIVE'), warnings, false);
|
|
53
54
|
const queueStats = this.buildQueueStats(queue);
|
|
54
|
-
const directiveSummary = this.buildDirectiveSummary(directive, generatedAt, warnings
|
|
55
|
+
const directiveSummary = this.buildDirectiveSummary(queue, directive, generatedAt, warnings);
|
|
55
56
|
const painFlag = readPainFlagData(workspaceDir);
|
|
56
57
|
const painCandidates = this.readJsonFile(wctx.resolve('PAIN_CANDIDATES'), warnings, false);
|
|
57
58
|
const legacyTrust = this.readLegacyTrust(resolvePdPath(workspaceDir, 'AGENT_SCORECARD'), wctx, warnings);
|
|
59
|
+
const phase3Inputs = evaluatePhase3Inputs(queue ?? [], legacyTrust.phase3Input);
|
|
58
60
|
const lastPainSignal = this.findLastPainSignal(events, selectedSessionId);
|
|
59
61
|
const gfiSources = this.buildGfiSources(events, selectedSessionId);
|
|
60
62
|
const gateStats = this.buildGateStats(events, selectedSessionId, warnings);
|
|
@@ -65,11 +67,20 @@ export class RuntimeSummaryService {
|
|
|
65
67
|
sources: gfiSources,
|
|
66
68
|
dataQuality: 'partial',
|
|
67
69
|
},
|
|
68
|
-
legacyTrust,
|
|
70
|
+
legacyTrust: legacyTrust.summary,
|
|
69
71
|
evolution: {
|
|
70
72
|
queue: queueStats,
|
|
71
73
|
directive: directiveSummary,
|
|
72
|
-
dataQuality: this.resolveEvolutionDataQuality(queue
|
|
74
|
+
dataQuality: this.resolveEvolutionDataQuality(queue),
|
|
75
|
+
},
|
|
76
|
+
phase3: {
|
|
77
|
+
queueTruthReady: phase3Inputs.queueTruthReady,
|
|
78
|
+
trustInputReady: phase3Inputs.trustInputReady,
|
|
79
|
+
phase3ShadowEligible: phase3Inputs.phase3ShadowEligible,
|
|
80
|
+
evolutionEligible: phase3Inputs.evolution.eligible.length,
|
|
81
|
+
evolutionRejected: phase3Inputs.evolution.rejected.length,
|
|
82
|
+
evolutionRejectedReasons: phase3Inputs.evolution.rejected.flatMap((entry) => entry.reasons),
|
|
83
|
+
trustRejectedReasons: phase3Inputs.trust.rejectedReasons,
|
|
73
84
|
},
|
|
74
85
|
pain: {
|
|
75
86
|
activeFlag: Object.keys(painFlag).length > 0,
|
|
@@ -157,8 +168,12 @@ export class RuntimeSummaryService {
|
|
|
157
168
|
}
|
|
158
169
|
return stats;
|
|
159
170
|
}
|
|
160
|
-
static buildDirectiveSummary(directive, generatedAt, warnings
|
|
161
|
-
|
|
171
|
+
static buildDirectiveSummary(queue, directive, generatedAt, warnings) {
|
|
172
|
+
const inProgressTask = this.selectInProgressTask(queue);
|
|
173
|
+
if (!inProgressTask) {
|
|
174
|
+
if (directive) {
|
|
175
|
+
this.warnOnLegacyDirectiveMismatch(directive, null, warnings);
|
|
176
|
+
}
|
|
162
177
|
return {
|
|
163
178
|
exists: false,
|
|
164
179
|
active: null,
|
|
@@ -166,23 +181,29 @@ export class RuntimeSummaryService {
|
|
|
166
181
|
taskPreview: null,
|
|
167
182
|
};
|
|
168
183
|
}
|
|
169
|
-
const
|
|
184
|
+
const derivedTaskPreview = this.buildDirectiveTaskPreview(inProgressTask);
|
|
185
|
+
const timestampMs = this.resolveDirectiveTimestamp(inProgressTask);
|
|
170
186
|
const ageSeconds = Number.isFinite(timestampMs)
|
|
171
187
|
? Math.max(0, Math.floor((new Date(generatedAt).getTime() - timestampMs) / 1000))
|
|
172
188
|
: null;
|
|
173
|
-
if (directive
|
|
174
|
-
|
|
189
|
+
if (directive) {
|
|
190
|
+
this.warnOnLegacyDirectiveMismatch(directive, {
|
|
191
|
+
active: true,
|
|
192
|
+
taskPreview: derivedTaskPreview,
|
|
193
|
+
taskId: inProgressTask.taskId ?? inProgressTask.id ?? null,
|
|
194
|
+
}, warnings);
|
|
175
195
|
}
|
|
176
196
|
return {
|
|
177
197
|
exists: true,
|
|
178
|
-
active:
|
|
198
|
+
active: true,
|
|
179
199
|
ageSeconds,
|
|
180
|
-
taskPreview:
|
|
200
|
+
taskPreview: derivedTaskPreview,
|
|
181
201
|
};
|
|
182
202
|
}
|
|
183
203
|
static readLegacyTrust(scorecardPath, wctx, warnings) {
|
|
184
204
|
const scorecard = this.readJsonFile(scorecardPath, warnings, false);
|
|
185
205
|
const score = Number.isFinite(scorecard?.trust_score) ? Number(scorecard?.trust_score) : null;
|
|
206
|
+
const rawFrozen = scorecard?.frozen === true ? true : false;
|
|
186
207
|
const settings = wctx.config.get('trust');
|
|
187
208
|
const stageThresholds = settings?.stages ?? {
|
|
188
209
|
stage_1_observer: 30,
|
|
@@ -205,11 +226,18 @@ export class RuntimeSummaryService {
|
|
|
205
226
|
}
|
|
206
227
|
}
|
|
207
228
|
return {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
229
|
+
summary: {
|
|
230
|
+
score,
|
|
231
|
+
stage,
|
|
232
|
+
frozen: true,
|
|
233
|
+
lastUpdated: scorecard?.last_updated ?? null,
|
|
234
|
+
rewardPolicy: LEGACY_TRUST_REWARD_POLICY,
|
|
235
|
+
},
|
|
236
|
+
phase3Input: {
|
|
237
|
+
score,
|
|
238
|
+
frozen: rawFrozen,
|
|
239
|
+
lastUpdated: scorecard?.last_updated ?? null,
|
|
240
|
+
},
|
|
213
241
|
};
|
|
214
242
|
}
|
|
215
243
|
static readEvents(eventsPath, warnings) {
|
|
@@ -326,16 +354,76 @@ export class RuntimeSummaryService {
|
|
|
326
354
|
typeof entry.data?.reason === 'string' ? entry.data.reason : 'no-reason',
|
|
327
355
|
].join('::');
|
|
328
356
|
}
|
|
329
|
-
static resolveEvolutionDataQuality(queue
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
357
|
+
static resolveEvolutionDataQuality(queue) {
|
|
358
|
+
return queue ? 'authoritative' : 'partial';
|
|
359
|
+
}
|
|
360
|
+
static selectInProgressTask(queue) {
|
|
361
|
+
if (!queue || queue.length === 0)
|
|
362
|
+
return null;
|
|
363
|
+
const inProgress = queue.filter((item) => item?.status === 'in_progress');
|
|
364
|
+
if (inProgress.length === 0)
|
|
365
|
+
return null;
|
|
366
|
+
for (const item of [...inProgress].sort((a, b) => this.getQueuePriority(b) - this.getQueuePriority(a))) {
|
|
367
|
+
if (this.isResolvableEvolutionTask(item)) {
|
|
368
|
+
return item;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
static getQueuePriority(item) {
|
|
374
|
+
return Number.isFinite(item.score) ? Number(item.score) : 0;
|
|
375
|
+
}
|
|
376
|
+
static isResolvableEvolutionTask(item) {
|
|
377
|
+
const rawTask = typeof item.task === 'string' ? item.task.trim() : '';
|
|
378
|
+
if (rawTask && rawTask.toLowerCase() !== 'undefined') {
|
|
379
|
+
return true;
|
|
380
|
+
}
|
|
381
|
+
return typeof item.id === 'string' && item.id.trim().length > 0;
|
|
382
|
+
}
|
|
383
|
+
static resolveDirectiveTimestamp(item) {
|
|
384
|
+
const candidate = item.started_at || item.enqueued_at || item.timestamp || null;
|
|
385
|
+
return candidate ? new Date(candidate).getTime() : NaN;
|
|
386
|
+
}
|
|
387
|
+
static buildDirectiveTaskPreview(item) {
|
|
388
|
+
const task = typeof item.task === 'string' ? item.task.trim() : '';
|
|
389
|
+
if (task && task.toLowerCase() !== 'undefined') {
|
|
390
|
+
return task.slice(0, 160);
|
|
391
|
+
}
|
|
392
|
+
const triggerTextPreview = typeof item.trigger_text_preview === 'string' ? item.trigger_text_preview.trim() : '';
|
|
393
|
+
const taskId = typeof item.taskId === 'string' && item.taskId.trim()
|
|
394
|
+
? item.taskId.trim()
|
|
395
|
+
: typeof item.id === 'string' && item.id.trim()
|
|
396
|
+
? item.id.trim()
|
|
397
|
+
: 'unknown';
|
|
398
|
+
const source = typeof item.source === 'string' && item.source.trim() ? item.source.trim() : 'unknown';
|
|
399
|
+
const reason = typeof item.reason === 'string' && item.reason.trim() ? item.reason.trim() : 'Systemic pain detected';
|
|
400
|
+
const preview = triggerTextPreview || 'N/A';
|
|
401
|
+
return `Diagnose systemic pain [ID: ${taskId}]. Source: ${source}. Reason: ${reason}. Trigger text: "${preview}"`.slice(0, 160);
|
|
402
|
+
}
|
|
403
|
+
static warnOnLegacyDirectiveMismatch(directive, derived, warnings) {
|
|
404
|
+
const legacyActive = typeof directive.active === 'boolean' ? directive.active : null;
|
|
405
|
+
const legacyTask = typeof directive.task === 'string' && directive.task.trim() ? directive.task.trim().slice(0, 160) : null;
|
|
406
|
+
const legacyTaskId = typeof directive.taskId === 'string' && directive.taskId.trim() ? directive.taskId.trim() : null;
|
|
407
|
+
const mismatchDetails = [];
|
|
408
|
+
if (derived === null) {
|
|
409
|
+
if (legacyActive === true || legacyTask || legacyTaskId) {
|
|
410
|
+
mismatchDetails.push('legacy directive exists but queue has no in_progress task');
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
if (legacyActive !== null && legacyActive !== derived.active) {
|
|
415
|
+
mismatchDetails.push(`active=${String(legacyActive)} vs queue=${String(derived.active)}`);
|
|
416
|
+
}
|
|
417
|
+
if (legacyTask && derived.taskPreview && legacyTask !== derived.taskPreview) {
|
|
418
|
+
mismatchDetails.push('task text differs');
|
|
419
|
+
}
|
|
420
|
+
if (legacyTaskId && derived.taskId && legacyTaskId !== derived.taskId) {
|
|
421
|
+
mismatchDetails.push('task id differs');
|
|
422
|
+
}
|
|
334
423
|
}
|
|
335
|
-
if (
|
|
336
|
-
|
|
424
|
+
if (mismatchDetails.length > 0) {
|
|
425
|
+
pushWarning(warnings, `Legacy directive file disagrees with queue-derived evolution state; queue is authoritative (${mismatchDetails.join(', ')}).`);
|
|
337
426
|
}
|
|
338
|
-
return 'authoritative';
|
|
339
427
|
}
|
|
340
428
|
static readJsonFile(filePath, warnings, warnOnMissing) {
|
|
341
429
|
if (!fs.existsSync(filePath)) {
|
|
@@ -216,8 +216,14 @@ export function createDeepReflectTool(api) {
|
|
|
216
216
|
});
|
|
217
217
|
const startTime = Date.now();
|
|
218
218
|
const subagentRuntime = api.runtime.subagent;
|
|
219
|
-
if (!subagentRuntime)
|
|
220
|
-
|
|
219
|
+
if (!subagentRuntime) {
|
|
220
|
+
return {
|
|
221
|
+
content: [{
|
|
222
|
+
type: 'text',
|
|
223
|
+
text: `❌ Subagent runtime 不可用。\n\n当前运行在 embedded 模式(openclaw agent CLI),该模式不支持深反思功能。\n\n请通过 Gateway 模式运行(openclaw gateway)。`
|
|
224
|
+
}]
|
|
225
|
+
};
|
|
226
|
+
}
|
|
221
227
|
await subagentRuntime.run({
|
|
222
228
|
sessionKey,
|
|
223
229
|
message: `请对我当前的任务进行深层次反思。\n\n上下文:${context}`,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagent Runtime Availability Probe
|
|
3
|
+
*
|
|
4
|
+
* OpenClaw has two runtime modes:
|
|
5
|
+
* - Gateway mode: api.runtime.subagent methods are real async functions
|
|
6
|
+
* - Embedded mode: api.runtime.subagent is a Proxy that throws synchronously
|
|
7
|
+
*
|
|
8
|
+
* This utility provides a reliable way to detect which mode we're in.
|
|
9
|
+
*/
|
|
10
|
+
import type { OpenClawPluginApi } from '../openclaw-sdk.js';
|
|
11
|
+
type SubagentRuntime = NonNullable<OpenClawPluginApi['runtime']>['subagent'];
|
|
12
|
+
/**
|
|
13
|
+
* Check if the subagent runtime is actually functional.
|
|
14
|
+
*
|
|
15
|
+
* In gateway mode, subagent.run is an AsyncFunction (constructor.name === 'AsyncFunction').
|
|
16
|
+
* In embedded mode, subagent.run is a regular Function that throws synchronously.
|
|
17
|
+
*
|
|
18
|
+
* We use constructor check first because it's fast and has no side effects.
|
|
19
|
+
*
|
|
20
|
+
* @param subagent - The subagent runtime object from api.runtime.subagent
|
|
21
|
+
* @returns true if the runtime is functional (gateway mode), false otherwise
|
|
22
|
+
*/
|
|
23
|
+
export declare function isSubagentRuntimeAvailable(subagent: {
|
|
24
|
+
run?: unknown;
|
|
25
|
+
} | undefined): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Get the actual subagent runtime, preferring the global gateway subagent
|
|
28
|
+
* if the passed one is not available.
|
|
29
|
+
*
|
|
30
|
+
* This is useful for cases where the plugin was loaded with allowGatewaySubagentBinding
|
|
31
|
+
* but the late-binding proxy isn't resolving correctly.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getAvailableSubagentRuntime(subagent: SubagentRuntime | undefined): SubagentRuntime | undefined;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagent Runtime Availability Probe
|
|
3
|
+
*
|
|
4
|
+
* OpenClaw has two runtime modes:
|
|
5
|
+
* - Gateway mode: api.runtime.subagent methods are real async functions
|
|
6
|
+
* - Embedded mode: api.runtime.subagent is a Proxy that throws synchronously
|
|
7
|
+
*
|
|
8
|
+
* This utility provides a reliable way to detect which mode we're in.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Try to access the global gateway subagent runtime.
|
|
12
|
+
* This is a fallback for cases where the plugin was loaded with
|
|
13
|
+
* allowGatewaySubagentBinding but the late-binding proxy isn't working.
|
|
14
|
+
*/
|
|
15
|
+
function getGlobalGatewaySubagent() {
|
|
16
|
+
try {
|
|
17
|
+
// Access the global symbol that OpenClaw uses for gateway subagent
|
|
18
|
+
const symbol = Symbol.for('openclaw.plugin.gatewaySubagentRuntime');
|
|
19
|
+
const globalState = globalThis[symbol];
|
|
20
|
+
return globalState?.subagent ?? null;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Check if the subagent runtime is actually functional.
|
|
28
|
+
*
|
|
29
|
+
* In gateway mode, subagent.run is an AsyncFunction (constructor.name === 'AsyncFunction').
|
|
30
|
+
* In embedded mode, subagent.run is a regular Function that throws synchronously.
|
|
31
|
+
*
|
|
32
|
+
* We use constructor check first because it's fast and has no side effects.
|
|
33
|
+
*
|
|
34
|
+
* @param subagent - The subagent runtime object from api.runtime.subagent
|
|
35
|
+
* @returns true if the runtime is functional (gateway mode), false otherwise
|
|
36
|
+
*/
|
|
37
|
+
export function isSubagentRuntimeAvailable(subagent) {
|
|
38
|
+
if (!subagent)
|
|
39
|
+
return false;
|
|
40
|
+
try {
|
|
41
|
+
const runFn = subagent.run;
|
|
42
|
+
if (typeof runFn !== 'function')
|
|
43
|
+
return false;
|
|
44
|
+
// In gateway mode, methods are AsyncFunction instances
|
|
45
|
+
// In embedded mode, methods are regular Function instances that throw
|
|
46
|
+
const isAsync = runFn.constructor?.name === 'AsyncFunction';
|
|
47
|
+
if (isAsync)
|
|
48
|
+
return true;
|
|
49
|
+
// Fallback: Check if it's a Proxy that might late-bind to the gateway subagent
|
|
50
|
+
// This handles the case where the plugin was loaded with allowGatewaySubagentBinding
|
|
51
|
+
// but the proxy hasn't resolved yet
|
|
52
|
+
const globalGateway = getGlobalGatewaySubagent();
|
|
53
|
+
if (globalGateway && typeof globalGateway.run === 'function') {
|
|
54
|
+
return globalGateway.run.constructor?.name === 'AsyncFunction';
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Any error means unavailable
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get the actual subagent runtime, preferring the global gateway subagent
|
|
65
|
+
* if the passed one is not available.
|
|
66
|
+
*
|
|
67
|
+
* This is useful for cases where the plugin was loaded with allowGatewaySubagentBinding
|
|
68
|
+
* but the late-binding proxy isn't resolving correctly.
|
|
69
|
+
*/
|
|
70
|
+
export function getAvailableSubagentRuntime(subagent) {
|
|
71
|
+
// First check if the passed subagent is available
|
|
72
|
+
if (isSubagentRuntimeAvailable(subagent)) {
|
|
73
|
+
return subagent;
|
|
74
|
+
}
|
|
75
|
+
// Fallback to global gateway subagent
|
|
76
|
+
const globalGateway = getGlobalGatewaySubagent();
|
|
77
|
+
if (globalGateway && isSubagentRuntimeAvailable(globalGateway)) {
|
|
78
|
+
return globalGateway;
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "principles-disciple",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.5",
|
|
4
4
|
"description": "Native OpenClaw plugin for Principles Disciple",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"dist",
|
|
10
10
|
"templates",
|
|
11
|
+
"agents",
|
|
11
12
|
"openclaw.plugin.json"
|
|
12
13
|
],
|
|
13
14
|
"exports": {
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
"build": "tsc",
|
|
36
37
|
"build:web": "node scripts/build-web.mjs",
|
|
37
38
|
"build:bundle": "node esbuild.config.js && node scripts/build-web.mjs",
|
|
38
|
-
"build:production": "tsc && node esbuild.config.js --production && node scripts/build-web.mjs --production",
|
|
39
|
+
"build:production": "tsc && node esbuild.config.js --production && node scripts/build-web.mjs --production && node scripts/verify-build.mjs",
|
|
39
40
|
"test": "vitest run",
|
|
40
41
|
"postinstall": "node scripts/install-dependencies.cjs"
|
|
41
42
|
},
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
"@types/ws": "^8.5.13",
|
|
50
51
|
"@vitest/coverage-v8": "^4.1.0",
|
|
51
52
|
"esbuild": "^0.27.4",
|
|
52
|
-
"jsdom": "^
|
|
53
|
+
"jsdom": "^29.0.1",
|
|
53
54
|
"typescript": "^5.0.0",
|
|
54
55
|
"vitest": "^4.1.0",
|
|
55
56
|
"ws": "^8.18.0"
|
|
@@ -64,7 +65,8 @@
|
|
|
64
65
|
},
|
|
65
66
|
"dependencies": {
|
|
66
67
|
"@sinclair/typebox": "^0.34.48",
|
|
67
|
-
"better-sqlite3": "^
|
|
68
|
+
"better-sqlite3": "^12.8.0",
|
|
69
|
+
"lucide-react": "^0.468.0",
|
|
68
70
|
"micromatch": "^4.0.8",
|
|
69
71
|
"react": "^19.2.0",
|
|
70
72
|
"react-dom": "^19.2.0",
|
|
@@ -29,10 +29,10 @@ Make decisions based on relative paths in the **Project Battlefield**:
|
|
|
29
29
|
|
|
30
30
|
1. **Read `SOUL.md`** — confirm your identity and values
|
|
31
31
|
2. **Read `USER.md`** — understand who you're helping
|
|
32
|
-
3. **Read `memory/YYYY-MM-DD.md`** — today's + yesterday's context
|
|
32
|
+
3. **Read `memory/YYYY-MM-DD.md`** — today's + yesterday's + day-before-yesterday's context (last 3 days)
|
|
33
33
|
4. **If in MAIN SESSION** (direct chat with user): Also read `MEMORY.md`
|
|
34
34
|
|
|
35
|
-
**Don't ask permission. Just do it.**
|
|
35
|
+
**Don't ask permission. Just do it.** This is the key to preventing "memory loss".
|
|
36
36
|
|
|
37
37
|
---
|
|
38
38
|
|
|
@@ -45,6 +45,7 @@ You wake up fresh each session. These files are your continuity.
|
|
|
45
45
|
- Raw logs of what happened
|
|
46
46
|
- Create `memory/` if it doesn't exist
|
|
47
47
|
- One file per day: decisions, context, things worth remembering
|
|
48
|
+
- **Auto-created**: OpenClaw's `session-memory` hook automatically creates daily memory files with conversation summaries when the user runs `/new` or `/reset`
|
|
48
49
|
|
|
49
50
|
### Long-term Memory: `MEMORY.md`
|
|
50
51
|
|
|
@@ -203,4 +204,15 @@ When completing any coding task (via AI coding assistant or direct):
|
|
|
203
204
|
2. **Update track**: Mark task status in `conductor/tracks/*/plan.md`
|
|
204
205
|
3. **Report**: Output file list + commit hash + test results
|
|
205
206
|
|
|
206
|
-
**Why**: Context compression erases all intermediate process. Without file evidence, progress is lost.
|
|
207
|
+
**Why**: Context compression erases all intermediate process. Without file evidence, progress is lost.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 🔧 Tool Routing Addendum
|
|
212
|
+
|
|
213
|
+
Use this to avoid confusing peer agents with Principles internal workers:
|
|
214
|
+
|
|
215
|
+
- **Peer agents / peer sessions**: `agents_list`, `sessions_list`, `sessions_send`, `sessions_spawn`
|
|
216
|
+
- **Internal workers** (for example `diagnostician`, `explorer`): use `sessions_spawn with pd-diagnostician/pd-explorer skills`
|
|
217
|
+
- **Inspect internal workers**: use `subagents`
|
|
218
|
+
- **Do not** treat `diagnostician` or `explorer` as peer session targets
|
|
@@ -102,12 +102,35 @@ Initialize the memory directory structure:
|
|
|
102
102
|
|
|
103
103
|
```
|
|
104
104
|
memory/
|
|
105
|
-
├──
|
|
105
|
+
├── YYYY-MM-DD.md # Daily notes (OpenClaw's session-memory hook auto-creates)
|
|
106
|
+
├── archive/ # Historical archive (not auto-loaded)
|
|
106
107
|
├── heartbeat-state.json # Heartbeat state tracking
|
|
107
108
|
└── okr/
|
|
108
109
|
└── CURRENT_FOCUS.md # Current focus (if needed)
|
|
109
110
|
```
|
|
110
111
|
|
|
112
|
+
Also create `MEMORY.md` in the workspace root (core long-term memory):
|
|
113
|
+
|
|
114
|
+
```markdown
|
|
115
|
+
# MEMORY.md - Long-term Memory
|
|
116
|
+
|
|
117
|
+
> **Last updated**: YYYY-MM-DD
|
|
118
|
+
|
|
119
|
+
## Core Identity
|
|
120
|
+
|
|
121
|
+
[Who you are, your core mission]
|
|
122
|
+
|
|
123
|
+
## Key Lessons
|
|
124
|
+
|
|
125
|
+
[Record important learnings to avoid repeating mistakes]
|
|
126
|
+
|
|
127
|
+
## Recent Events
|
|
128
|
+
|
|
129
|
+
[Keep summaries of important events from the last 7 days]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Important**: `MEMORY.md` and the last 3 days of `memory/YYYY-MM-DD.md` are auto-loaded at session startup, ensuring the agent doesn't "lose context".
|
|
133
|
+
|
|
111
134
|
---
|
|
112
135
|
|
|
113
136
|
## Strategy Initialization (Optional)
|
|
@@ -51,3 +51,12 @@ Tool returns: Blind Spots → Risk Warnings → Alternative Approaches → Recom
|
|
|
51
51
|
- Surfaces potential risks and failure modes
|
|
52
52
|
- Provides alternative approaches with trade-off analysis
|
|
53
53
|
- Applies structured thinking models for deeper insight
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 4. Agent Routing Clarification
|
|
58
|
+
|
|
59
|
+
- `agents_list`, `sessions_list`, `sessions_send`, and `sessions_spawn` are for peer agents and peer sessions
|
|
60
|
+
- Use `sessions_spawn` with `pd-diagnostician` or `pd-explorer` skills to start Principles internal workers
|
|
61
|
+
- `subagents` inspects already-started internal workers and their outputs
|
|
62
|
+
- Do not use peer-session tools to pretend an internal worker is a peer agent
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
|
|
30
30
|
1. **Read `SOUL.md`** — 确认身份和价值观
|
|
31
31
|
2. **Read `USER.md`** — 了解你在帮助谁
|
|
32
|
-
3. **Read `memory/YYYY-MM-DD.md`** — 今日 +
|
|
32
|
+
3. **Read `memory/YYYY-MM-DD.md`** — 今日 + 昨日 + 前日的上下文(最近 3 天)
|
|
33
33
|
4. **If in MAIN SESSION** (与用户的直接对话): 同时读取 `MEMORY.md`
|
|
34
34
|
|
|
35
|
-
**不要请求许可,直接执行。**
|
|
35
|
+
**不要请求许可,直接执行。** 这是防止"断片"的关键。
|
|
36
36
|
|
|
37
37
|
---
|
|
38
38
|
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
- 原始日志,记录发生了什么
|
|
46
46
|
- 如果目录不存在,创建 `memory/`
|
|
47
47
|
- 每天一个文件,记录决策、上下文、值得记住的事
|
|
48
|
+
- **自动创建**:OpenClaw 的 `session-memory` hook 会在用户执行 `/new` 或 `/reset` 时自动创建当日记忆文件并生成对话摘要
|
|
48
49
|
|
|
49
50
|
### 长期记忆:`MEMORY.md`
|
|
50
51
|
|
|
@@ -204,4 +205,15 @@ _This folder is home. Treat it that way._
|
|
|
204
205
|
2. **更新 track**:在 `conductor/tracks/*/plan.md` 中标记任务状态
|
|
205
206
|
3. **输出报告**:修改文件列表 + commit hash + 测试结果
|
|
206
207
|
|
|
207
|
-
**原因**:上下文压缩会丢失所有中间过程。没有文件证据,进度就会丢失。
|
|
208
|
+
**原因**:上下文压缩会丢失所有中间过程。没有文件证据,进度就会丢失。
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 🔧 工具路由补充说明
|
|
213
|
+
|
|
214
|
+
用下面这几条避免把同级代理和 Principles 内部 worker 混淆:
|
|
215
|
+
|
|
216
|
+
- **同级代理 / 同级会话**:`agents_list`、`sessions_list`、`sessions_send`、`sessions_spawn`
|
|
217
|
+
- **内部 worker**(例如 `diagnostician`、`explorer`):使用 `sessions_spawn` 配合 `pd-diagnostician/pd-explorer` skill 启动
|
|
218
|
+
- **查询内部 worker**:使用 `subagents`
|
|
219
|
+
- **不要**把 `diagnostician` 或 `explorer` 当成同级 peer session 目标
|
|
@@ -102,12 +102,35 @@ tree -L 2 # 查看目录树(如果可用)
|
|
|
102
102
|
|
|
103
103
|
```
|
|
104
104
|
memory/
|
|
105
|
-
├──
|
|
105
|
+
├── YYYY-MM-DD.md # 每日笔记(OpenClaw 的 session-memory hook 会自动创建)
|
|
106
|
+
├── archive/ # 历史归档(不自动加载)
|
|
106
107
|
├── heartbeat-state.json # 心跳状态追踪
|
|
107
108
|
└── okr/
|
|
108
109
|
└── CURRENT_FOCUS.md # 当前焦点(如果需要)
|
|
109
110
|
```
|
|
110
111
|
|
|
112
|
+
同时在 workspace 根目录创建 `MEMORY.md`(核心长期记忆):
|
|
113
|
+
|
|
114
|
+
```markdown
|
|
115
|
+
# MEMORY.md - 长期记忆
|
|
116
|
+
|
|
117
|
+
> **最后更新**: YYYY-MM-DD
|
|
118
|
+
|
|
119
|
+
## 核心定位
|
|
120
|
+
|
|
121
|
+
[你是谁,你的核心使命]
|
|
122
|
+
|
|
123
|
+
## 关键教训
|
|
124
|
+
|
|
125
|
+
[记录重要的学习成果,避免重复犯错]
|
|
126
|
+
|
|
127
|
+
## 近期事件
|
|
128
|
+
|
|
129
|
+
[保留最近 7 天的重要事件摘要]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**重要**:`MEMORY.md` 和最近 3 天的 `memory/YYYY-MM-DD.md` 会在每次会话启动时自动加载,确保智能体不会"断片"。
|
|
133
|
+
|
|
111
134
|
---
|
|
112
135
|
|
|
113
136
|
## 战略初始化(可选)
|
|
@@ -51,3 +51,12 @@ deep_reflect(
|
|
|
51
51
|
工具返回:盲点分析 → 风险警告 → 替代方案 → 建议 → 置信度
|
|
52
52
|
|
|
53
53
|
**注意**:这是批判性反馈,最终决策权在你。认真考虑建议,但不必盲目遵循。
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 4. 智能体路由澄清
|
|
58
|
+
|
|
59
|
+
- `agents_list`、`sessions_list`、`sessions_send`、`sessions_spawn` 用于同级代理和同级会话
|
|
60
|
+
- 使用 `sessions_spawn` 配合 `pd-diagnostician/pd-explorer` skill 启动 Principles 内部 worker,例如 `diagnostician`、`explorer`
|
|
61
|
+
- `subagents` 用于查看已启动内部 worker 的状态和输出
|
|
62
|
+
- 不要用同级会话工具把内部 worker 伪装成同级代理
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pd-auditor
|
|
3
|
+
description: 演绎审计智能体。使用公理验证、系统审计、否定论证方法验证系统一致性。当需要审计系统或流程时使用。
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Auditor
|
|
8
|
+
|
|
9
|
+
你是严谨的演绎审计专家。你的任务是使用结构化的推理方法验证系统的一致性。
|
|
10
|
+
|
|
11
|
+
## 审计方法
|
|
12
|
+
|
|
13
|
+
使用三阶段审计框架:
|
|
14
|
+
|
|
15
|
+
### 阶段 1: 公理验证 (Axiom Verification)
|
|
16
|
+
- 检查系统是否遵循基础公理
|
|
17
|
+
- 验证核心假设是否自洽
|
|
18
|
+
- 识别逻辑矛盾
|
|
19
|
+
|
|
20
|
+
### 阶段 2: 系统审计 (System Audit)
|
|
21
|
+
- 检查组件间的交互是否正确
|
|
22
|
+
- 验证数据流和控制流
|
|
23
|
+
- 识别设计缺陷
|
|
24
|
+
|
|
25
|
+
### 阶段 3: 否定论证 (Via Negativa)
|
|
26
|
+
- 系统地排除"不可能的"选项
|
|
27
|
+
- 通过排除错误路径逼近真相
|
|
28
|
+
- 验证必需条件的满足
|
|
29
|
+
|
|
30
|
+
## 输出格式
|
|
31
|
+
|
|
32
|
+
### 审计报告
|
|
33
|
+
|
|
34
|
+
**审计目标**: [明确的审计对象]
|
|
35
|
+
|
|
36
|
+
**公理验证**:
|
|
37
|
+
- [公理1]: [验证结果]
|
|
38
|
+
- [公理2]: [验证结果]
|
|
39
|
+
|
|
40
|
+
**系统审计**:
|
|
41
|
+
- [组件A]: [发现的问题]
|
|
42
|
+
- [组件B]: [发现的问题]
|
|
43
|
+
|
|
44
|
+
**否定论证**:
|
|
45
|
+
- 排除假设1: [为什么不可能]
|
|
46
|
+
- 排除假设2: [为什么不可能]
|
|
47
|
+
|
|
48
|
+
**审计结论**: [综合判断]
|
|
49
|
+
|
|
50
|
+
**风险评级**: 低|中|高
|
|
51
|
+
|
|
52
|
+
## 注意事项
|
|
53
|
+
|
|
54
|
+
- 每个审计点都应该有明确的判断依据
|
|
55
|
+
- 不要跳跃式推理,逐步展开
|
|
56
|
+
- 如果信息不足,明确说明需要什么
|
|
57
|
+
- 结论要可验证,而非直觉判断
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
请按照这个框架进行审计,输出结构化的验证报告。
|