principles-disciple 1.16.0 → 1.18.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/README.md +13 -5
- package/openclaw.plugin.json +4 -4
- package/package.json +1 -1
- package/src/commands/archive-impl.ts +3 -3
- package/src/commands/capabilities.ts +1 -1
- package/src/commands/context.ts +3 -3
- package/src/commands/disable-impl.ts +1 -1
- package/src/commands/evolution-status.ts +2 -2
- package/src/commands/focus.ts +2 -2
- package/src/commands/nocturnal-train.ts +6 -6
- package/src/commands/pain.ts +4 -4
- package/src/commands/pd-reflect.ts +87 -0
- package/src/commands/rollback-impl.ts +4 -4
- package/src/commands/rollback.ts +2 -2
- package/src/commands/samples.ts +2 -2
- package/src/commands/workflow-debug.ts +1 -1
- package/src/config/errors.ts +1 -1
- package/src/core/adaptive-thresholds.ts +1 -1
- package/src/core/code-implementation-storage.ts +2 -2
- package/src/core/config.ts +1 -1
- package/src/core/diagnostician-task-store.ts +2 -2
- package/src/core/empathy-keyword-matcher.ts +3 -3
- package/src/core/event-log.ts +5 -5
- package/src/core/evolution-engine.ts +4 -4
- package/src/core/evolution-logger.ts +1 -1
- package/src/core/evolution-reducer.ts +3 -3
- package/src/core/evolution-types.ts +5 -5
- package/src/core/external-training-contract.ts +1 -1
- package/src/core/focus-history.ts +14 -14
- package/src/core/hygiene/tracker.ts +1 -1
- package/src/core/init.ts +2 -2
- package/src/core/model-deployment-registry.ts +2 -2
- package/src/core/model-training-registry.ts +2 -2
- package/src/core/nocturnal-arbiter.ts +1 -1
- package/src/core/nocturnal-artificer.ts +2 -2
- package/src/core/nocturnal-candidate-scoring.ts +2 -2
- package/src/core/nocturnal-compliance.ts +4 -3
- package/src/core/nocturnal-dataset.ts +3 -3
- package/src/core/nocturnal-export.ts +4 -4
- package/src/core/nocturnal-rule-implementation-validator.ts +1 -1
- package/src/core/nocturnal-snapshot-contract.ts +112 -0
- package/src/core/nocturnal-trajectory-extractor.ts +7 -5
- package/src/core/nocturnal-trinity.ts +480 -158
- package/src/core/pain-context-extractor.ts +3 -3
- package/src/core/pain.ts +124 -11
- package/src/core/path-resolver.ts +4 -4
- package/src/core/pd-task-reconciler.ts +10 -10
- package/src/core/pd-task-service.ts +1 -1
- package/src/core/pd-task-store.ts +1 -1
- package/src/core/principle-internalization/deprecated-readiness.ts +1 -1
- package/src/core/principle-training-state.ts +2 -2
- package/src/core/principle-tree-ledger.ts +7 -7
- package/src/core/promotion-gate.ts +9 -9
- package/src/core/replay-engine.ts +12 -12
- package/src/core/risk-calculator.ts +1 -1
- package/src/core/rule-host-types.ts +2 -2
- package/src/core/rule-host.ts +5 -5
- package/src/core/schema/db-types.ts +1 -1
- package/src/core/schema/schema-definitions.ts +1 -1
- package/src/core/session-tracker.ts +96 -4
- package/src/core/shadow-observation-registry.ts +3 -3
- package/src/core/system-logger.ts +2 -2
- package/src/core/thinking-os-parser.ts +1 -1
- package/src/core/training-program.ts +2 -2
- package/src/core/trajectory.ts +8 -8
- package/src/core/workspace-context.ts +2 -2
- package/src/core/workspace-dir-service.ts +85 -0
- package/src/core/workspace-dir-validation.ts +30 -107
- package/src/hooks/bash-risk.ts +3 -3
- package/src/hooks/edit-verification.ts +4 -4
- package/src/hooks/gate-block-helper.ts +4 -4
- package/src/hooks/gate.ts +10 -10
- package/src/hooks/gfi-gate.ts +7 -7
- package/src/hooks/lifecycle.ts +2 -2
- package/src/hooks/llm.ts +1 -1
- package/src/hooks/pain.ts +25 -5
- package/src/hooks/progressive-trust-gate.ts +7 -7
- package/src/hooks/prompt.ts +24 -5
- package/src/hooks/subagent.ts +2 -2
- package/src/hooks/thinking-checkpoint.ts +2 -2
- package/src/hooks/trajectory-collector.ts +1 -1
- package/src/http/principles-console-route.ts +14 -6
- package/src/i18n/commands.ts +4 -0
- package/src/index.ts +181 -185
- package/src/service/central-health-service.ts +1 -1
- package/src/service/central-overview-service.ts +3 -3
- package/src/service/evolution-query-service.ts +1 -1
- package/src/service/evolution-worker.ts +221 -109
- package/src/service/health-query-service.ts +27 -17
- package/src/service/monitoring-query-service.ts +3 -3
- package/src/service/nocturnal-runtime.ts +4 -4
- package/src/service/nocturnal-service.ts +40 -23
- package/src/service/nocturnal-target-selector.ts +11 -4
- package/src/service/runtime-summary-service.ts +1 -1
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +1 -1
- package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +3 -3
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +16 -13
- package/src/service/subagent-workflow/runtime-direct-driver.ts +10 -6
- package/src/service/subagent-workflow/types.ts +4 -4
- package/src/service/subagent-workflow/workflow-manager-base.ts +5 -5
- package/src/service/subagent-workflow/workflow-store.ts +2 -2
- package/src/tools/critique-prompt.ts +2 -3
- package/src/tools/deep-reflect.ts +17 -16
- package/src/tools/model-index.ts +1 -1
- package/src/utils/file-lock.ts +1 -1
- package/src/utils/io.ts +7 -2
- package/src/utils/nlp.ts +1 -1
- package/src/utils/plugin-logger.ts +2 -2
- package/src/utils/retry.ts +3 -2
- package/src/utils/subagent-probe.ts +20 -33
- package/templates/langs/en/skills/pd-pain-signal/SKILL.md +8 -7
- package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/nocturnal-trinity-quality-enhancement.json +111 -0
- package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +1 -1
- package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +1 -1
- package/templates/langs/zh/skills/pd-pain-signal/SKILL.md +8 -7
- package/templates/pain_settings.json +1 -1
- package/tests/build-artifacts.test.ts +4 -58
- package/tests/commands/pd-reflect.test.ts +49 -0
- package/tests/core/nocturnal-snapshot-contract.test.ts +70 -0
- package/tests/core/pain-auto-repair.test.ts +96 -0
- package/tests/core/pain-integration.test.ts +483 -0
- package/tests/core/pain.test.ts +5 -4
- package/tests/core/workspace-dir-service.test.ts +68 -0
- package/tests/core/workspace-dir-validation.test.ts +56 -192
- package/tests/hooks/pain.test.ts +20 -0
- package/tests/http/principles-console-route.test.ts +42 -20
- package/tests/integration/empathy-workflow-integration.test.ts +1 -2
- package/tests/integration/tool-hooks-workspace-dir.e2e.test.ts +9 -17
- package/tests/service/empathy-observer-workflow-manager.test.ts +1 -2
- package/tests/service/evolution-worker.nocturnal.test.ts +118 -109
- package/tests/service/nocturnal-runtime-hardening.test.ts +33 -0
- package/tests/utils/subagent-probe.test.ts +32 -0
package/src/index.ts
CHANGED
|
@@ -38,6 +38,7 @@ import { handleFocusCommand } from './commands/focus.js';
|
|
|
38
38
|
import { handleRollbackCommand } from './commands/rollback.js';
|
|
39
39
|
import { handlePromoteImplCommand } from './commands/promote-impl.js';
|
|
40
40
|
import { handleDisableImplCommand } from './commands/disable-impl.js';
|
|
41
|
+
import { handlePdReflect } from './commands/pd-reflect.js';
|
|
41
42
|
import { handleArchiveImplCommand } from './commands/archive-impl.js';
|
|
42
43
|
import { handleRollbackImplCommand } from './commands/rollback-impl.js';
|
|
43
44
|
import { handleEvolutionStatusCommand } from './commands/evolution-status.js';
|
|
@@ -57,11 +58,44 @@ import { migrateDirectoryStructure } from './core/migration.js';
|
|
|
57
58
|
import { SystemLogger } from './core/system-logger.js';
|
|
58
59
|
import { createDeepReflectTool } from './tools/deep-reflect.js';
|
|
59
60
|
import { PathResolver, resolveWorkspaceDirFromApi } from './core/path-resolver.js';
|
|
61
|
+
import { validateWorkspaceDir } from './core/workspace-dir-validation.js';
|
|
62
|
+
import { resolveRequiredWorkspaceDir, resolveWorkspaceDir, type WorkspaceResolutionContext } from './core/workspace-dir-service.js';
|
|
60
63
|
import { createPrinciplesConsoleRoute } from './http/principles-console-route.js';
|
|
61
64
|
|
|
62
65
|
// Track initialization to avoid repeated calls
|
|
63
66
|
let workspaceInitialized = false;
|
|
64
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Resolve workspaceDir for slash commands.
|
|
70
|
+
* Chain: ctx.workspaceDir → resolveWorkspaceDirFromApi (official OpenClaw API + env vars)
|
|
71
|
+
*
|
|
72
|
+
* CRITICAL: Throws if workspaceDir cannot be resolved. Silent failures are dangerous
|
|
73
|
+
* because commands might operate on the wrong directory.
|
|
74
|
+
*/
|
|
75
|
+
function resolveCommandWorkspaceDir(
|
|
76
|
+
api: OpenClawPluginApi,
|
|
77
|
+
ctx: { workspaceDir?: string },
|
|
78
|
+
): string {
|
|
79
|
+
// 1. Direct from command context (most reliable — set by OpenClaw for current session)
|
|
80
|
+
if (ctx.workspaceDir) {
|
|
81
|
+
const issue = validateWorkspaceDir(ctx.workspaceDir);
|
|
82
|
+
if (!issue) return ctx.workspaceDir;
|
|
83
|
+
api.logger.error(`[PD:Command] ctx.workspaceDir="${ctx.workspaceDir}" is invalid: ${issue}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 2. Official OpenClaw API → env vars → config file
|
|
87
|
+
const resolved = resolveWorkspaceDirFromApi(api);
|
|
88
|
+
if (resolved) return resolved;
|
|
89
|
+
|
|
90
|
+
// CRITICAL FAILURE: Cannot determine workspace directory
|
|
91
|
+
const errorMsg = `[PD:Command] CRITICAL: Cannot resolve workspace directory. ` +
|
|
92
|
+
`ctx.workspaceDir="${ctx.workspaceDir}" is invalid, and all fallbacks failed. ` +
|
|
93
|
+
`Commands will NOT execute to prevent data corruption.`;
|
|
94
|
+
api.logger.error(errorMsg);
|
|
95
|
+
|
|
96
|
+
throw new Error(errorMsg);
|
|
97
|
+
}
|
|
98
|
+
|
|
65
99
|
// Map from childSessionKey → shadowObservationId
|
|
66
100
|
// Used to complete shadow observations when subagent ends
|
|
67
101
|
const pendingShadowObservations = new Map<string, string>();
|
|
@@ -82,14 +116,19 @@ function computeRuntimeShadowTaskFingerprint(event: PluginHookSubagentSpawningEv
|
|
|
82
116
|
return crypto.createHash('sha256').update(JSON.stringify(payload)).digest('hex').slice(0, 16);
|
|
83
117
|
}
|
|
84
118
|
|
|
85
|
-
|
|
119
|
+
function resolveCommandWorkspaceDirStrict(
|
|
120
|
+
api: OpenClawPluginApi,
|
|
121
|
+
ctx: WorkspaceResolutionContext,
|
|
122
|
+
): string {
|
|
123
|
+
return resolveRequiredWorkspaceDir(api, ctx, { source: 'command' });
|
|
124
|
+
}
|
|
86
125
|
|
|
87
|
-
function
|
|
88
|
-
ctx:
|
|
126
|
+
function resolveToolHookWorkspaceDirSafe(
|
|
127
|
+
ctx: WorkspaceResolutionContext,
|
|
89
128
|
api: OpenClawPluginApi,
|
|
90
129
|
source: string,
|
|
91
|
-
): string {
|
|
92
|
-
return
|
|
130
|
+
): string | undefined {
|
|
131
|
+
return resolveWorkspaceDir(api, ctx, { source });
|
|
93
132
|
}
|
|
94
133
|
|
|
95
134
|
const plugin = {
|
|
@@ -105,7 +144,7 @@ const plugin = {
|
|
|
105
144
|
// Catches OpenClaw context bugs early (e.g., missing workspaceDir in tool hooks)
|
|
106
145
|
setTimeout(() => {
|
|
107
146
|
const testCtx = { agentId: 'main' };
|
|
108
|
-
const toolWorkspaceDir =
|
|
147
|
+
const toolWorkspaceDir = resolveToolHookWorkspaceDirSafe(testCtx, api, 'startup.health_check');
|
|
109
148
|
const toolIssue = validateWorkspaceDir(toolWorkspaceDir);
|
|
110
149
|
if (toolIssue) {
|
|
111
150
|
api.logger.error(`[PD:health] Tool hook workspaceDir is INVALID: "${toolWorkspaceDir}" - ${toolIssue}`);
|
|
@@ -121,9 +160,10 @@ const plugin = {
|
|
|
121
160
|
api.on(
|
|
122
161
|
'before_prompt_build',
|
|
123
162
|
async (event: PluginHookBeforePromptBuildEvent, ctx: PluginHookAgentContext): Promise<PluginHookBeforePromptBuildResult | void> => {
|
|
163
|
+
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'before_prompt_build');
|
|
164
|
+
if (!workspaceDir) return;
|
|
124
165
|
try {
|
|
125
|
-
|
|
126
|
-
if (!workspaceInitialized && workspaceDir) {
|
|
166
|
+
if (!workspaceInitialized) {
|
|
127
167
|
migrateDirectoryStructure(api, workspaceDir);
|
|
128
168
|
ensureWorkspaceTemplates(api, workspaceDir, language);
|
|
129
169
|
SystemLogger.log(workspaceDir, 'SYSTEM_BOOT', `Principles Disciple online. Language: ${language}`);
|
|
@@ -139,7 +179,6 @@ const plugin = {
|
|
|
139
179
|
|
|
140
180
|
return result;
|
|
141
181
|
} catch (err) {
|
|
142
|
-
const workspaceDir = ctx.workspaceDir || api.resolvePath('.');
|
|
143
182
|
WorkspaceContext.fromHookContext({ workspaceDir }).eventLog.recordHookExecution({
|
|
144
183
|
hook: 'before_prompt_build',
|
|
145
184
|
sessionId: ctx.sessionId,
|
|
@@ -154,7 +193,8 @@ const plugin = {
|
|
|
154
193
|
api.on(
|
|
155
194
|
'before_tool_call',
|
|
156
195
|
(event: PluginHookBeforeToolCallEvent, ctx: PluginHookToolContext): PluginHookBeforeToolCallResult | void => {
|
|
157
|
-
const workspaceDir =
|
|
196
|
+
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'before_tool_call');
|
|
197
|
+
if (!workspaceDir) return;
|
|
158
198
|
try {
|
|
159
199
|
const pluginConfig = api.pluginConfig ?? {};
|
|
160
200
|
const {logger} = api;
|
|
@@ -166,8 +206,7 @@ const plugin = {
|
|
|
166
206
|
|
|
167
207
|
return result;
|
|
168
208
|
} catch (err) {
|
|
169
|
-
|
|
170
|
-
WorkspaceContext.fromHookContext({ workspaceDir: fallbackDir }).eventLog.recordHookExecution({
|
|
209
|
+
WorkspaceContext.fromHookContext({ workspaceDir }).eventLog.recordHookExecution({
|
|
171
210
|
hook: 'before_tool_call',
|
|
172
211
|
error: String(err)
|
|
173
212
|
}, { flushImmediately: true });
|
|
@@ -180,7 +219,8 @@ const plugin = {
|
|
|
180
219
|
api.on(
|
|
181
220
|
'after_tool_call',
|
|
182
221
|
(event: PluginHookAfterToolCallEvent, ctx: PluginHookToolContext): void => {
|
|
183
|
-
const workspaceDir =
|
|
222
|
+
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'after_tool_call');
|
|
223
|
+
if (!workspaceDir) return;
|
|
184
224
|
try {
|
|
185
225
|
const pluginConfig = api.pluginConfig ?? {};
|
|
186
226
|
// Pass api separately to handleAfterToolCall to maintain type safety
|
|
@@ -190,8 +230,7 @@ const plugin = {
|
|
|
190
230
|
hook: 'after_tool_call'
|
|
191
231
|
}, { flushImmediately: true });
|
|
192
232
|
} catch (err) {
|
|
193
|
-
|
|
194
|
-
WorkspaceContext.fromHookContext({ workspaceDir: fallbackDir }).eventLog.recordHookExecution({
|
|
233
|
+
WorkspaceContext.fromHookContext({ workspaceDir }).eventLog.recordHookExecution({
|
|
195
234
|
hook: 'after_tool_call',
|
|
196
235
|
error: String(err)
|
|
197
236
|
}, { flushImmediately: true });
|
|
@@ -204,7 +243,8 @@ const plugin = {
|
|
|
204
243
|
api.on(
|
|
205
244
|
'llm_output',
|
|
206
245
|
(event: PluginHookLlmOutputEvent, ctx: PluginHookAgentContext): void => {
|
|
207
|
-
const workspaceDir =
|
|
246
|
+
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx as unknown as Record<string, unknown>, api, 'llm_output');
|
|
247
|
+
if (!workspaceDir) return;
|
|
208
248
|
try {
|
|
209
249
|
handleLlmOutput(event, { ...ctx, workspaceDir });
|
|
210
250
|
|
|
@@ -229,9 +269,10 @@ const plugin = {
|
|
|
229
269
|
'after_tool_call',
|
|
230
270
|
(event: PluginHookAfterToolCallEvent, ctx: PluginHookToolContext): void => {
|
|
231
271
|
try {
|
|
232
|
-
const workspaceDir =
|
|
272
|
+
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'trajectory.after_tool_call');
|
|
273
|
+
if (!workspaceDir) return;
|
|
233
274
|
TrajectoryCollector.handleAfterToolCall(event, { ...ctx, workspaceDir });
|
|
234
|
-
// eslint-disable-next-line
|
|
275
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- Reason: catch binding intentionally unused
|
|
235
276
|
} catch (_err) {
|
|
236
277
|
// Non-critical: don't log, just skip
|
|
237
278
|
}
|
|
@@ -242,9 +283,10 @@ const plugin = {
|
|
|
242
283
|
'llm_output',
|
|
243
284
|
(event: PluginHookLlmOutputEvent, ctx: PluginHookAgentContext): void => {
|
|
244
285
|
try {
|
|
245
|
-
const workspaceDir =
|
|
286
|
+
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx as unknown as Record<string, unknown>, api, 'trajectory.llm_output');
|
|
287
|
+
if (!workspaceDir) return;
|
|
246
288
|
TrajectoryCollector.handleLlmOutput(event, { ...ctx, workspaceDir });
|
|
247
|
-
// eslint-disable-next-line
|
|
289
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- Reason: catch binding intentionally unused
|
|
248
290
|
} catch (_err) {
|
|
249
291
|
// Non-critical: don't log, just skip
|
|
250
292
|
}
|
|
@@ -254,7 +296,7 @@ const plugin = {
|
|
|
254
296
|
// ── Hook: Subagent Loop Closure ──
|
|
255
297
|
api.on(
|
|
256
298
|
'subagent_spawning',
|
|
257
|
-
|
|
299
|
+
|
|
258
300
|
(event: PluginHookSubagentSpawningEvent, _ctx: PluginHookSubagentContext): void | PluginHookSubagentSpawningResult => {
|
|
259
301
|
try {
|
|
260
302
|
// Resolve workspace via official API, falling back to PathResolver
|
|
@@ -327,17 +369,20 @@ const plugin = {
|
|
|
327
369
|
|
|
328
370
|
// ── Hook: Lifecycle ──
|
|
329
371
|
api.on('before_reset', (event: PluginHookBeforeResetEvent, ctx: PluginHookAgentContext) => {
|
|
330
|
-
const workspaceDir = ctx
|
|
372
|
+
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'before_reset');
|
|
373
|
+
if (!workspaceDir) return;
|
|
331
374
|
return handleBeforeReset(event, { ...ctx, workspaceDir });
|
|
332
375
|
});
|
|
333
376
|
|
|
334
377
|
api.on('before_compaction', (event: PluginHookBeforeCompactionEvent, ctx: PluginHookAgentContext) => {
|
|
335
|
-
const workspaceDir = ctx
|
|
378
|
+
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'before_compaction');
|
|
379
|
+
if (!workspaceDir) return;
|
|
336
380
|
return handleBeforeCompaction(event, { ...ctx, workspaceDir });
|
|
337
381
|
});
|
|
338
382
|
|
|
339
383
|
api.on('after_compaction', (event: PluginHookAfterCompactionEvent, ctx: PluginHookAgentContext) => {
|
|
340
|
-
const workspaceDir = ctx
|
|
384
|
+
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'after_compaction');
|
|
385
|
+
if (!workspaceDir) return;
|
|
341
386
|
return handleAfterCompaction(event, { ...ctx, workspaceDir });
|
|
342
387
|
});
|
|
343
388
|
|
|
@@ -353,165 +398,116 @@ const plugin = {
|
|
|
353
398
|
}
|
|
354
399
|
|
|
355
400
|
// ── Slash Commands ──
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
handler: (ctx) => handleBootstrapTools(ctx)
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
api.registerCommand({
|
|
375
|
-
name: "pd-research",
|
|
376
|
-
description: getCommandDescription('pd-research', language),
|
|
377
|
-
handler: (ctx) => handleResearchTools(ctx)
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
api.registerCommand({
|
|
381
|
-
name: "pd-thinking",
|
|
382
|
-
description: getCommandDescription('pd-thinking', language),
|
|
383
|
-
acceptsArgs: true,
|
|
384
|
-
handler: (ctx) => handleThinkingOs(ctx)
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
api.registerCommand({
|
|
388
|
-
name: "pd-daily",
|
|
389
|
-
description: getCommandDescription('pd-daily', language),
|
|
390
|
-
handler: () => {
|
|
391
|
-
return { text: language === 'zh'
|
|
392
|
-
? "请执行 pd-daily 技能来配置并发送进化日报。系统将引导你完成配置流程,包括发送时间、渠道和报告风格偏好。"
|
|
393
|
-
: "Please execute the pd-daily skill to configure and send your daily evolution report. The system will guide you through the configuration process." };
|
|
401
|
+
// Register command with optional short alias
|
|
402
|
+
const registerCommandWithAlias = (name: string, alias: string | null, desc: string, handler: any, opts?: { acceptsArgs?: boolean }) => {
|
|
403
|
+
const base = {
|
|
404
|
+
name,
|
|
405
|
+
description: desc,
|
|
406
|
+
handler,
|
|
407
|
+
...(opts?.acceptsArgs ? { acceptsArgs: true } : {}),
|
|
408
|
+
};
|
|
409
|
+
api.registerCommand(base);
|
|
410
|
+
if (alias) {
|
|
411
|
+
api.registerCommand({
|
|
412
|
+
...base,
|
|
413
|
+
name: alias,
|
|
414
|
+
description: `${desc} (alias of /${name})`,
|
|
415
|
+
});
|
|
394
416
|
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
registerCommandWithAlias('pd-init', 'pdi', getCommandDescription('pd-init', language), (ctx: any) => handleInitStrategy(ctx));
|
|
420
|
+
registerCommandWithAlias('pd-okr', 'pdk', getCommandDescription('pd-okr', language), (ctx: any) => handleManageOkr(ctx));
|
|
421
|
+
registerCommandWithAlias('pd-bootstrap', 'pdb', getCommandDescription('pd-bootstrap', language), (ctx: any) => handleBootstrapTools(ctx));
|
|
422
|
+
registerCommandWithAlias('pd-research', 'pdr', getCommandDescription('pd-research', language), (ctx: any) => handleResearchTools(ctx));
|
|
423
|
+
registerCommandWithAlias('pd-thinking', 'pdt', getCommandDescription('pd-thinking', language), (ctx: any) => handleThinkingOs(ctx), { acceptsArgs: true });
|
|
424
|
+
registerCommandWithAlias('pd-reflect', 'pdrl', getCommandDescription('pd-reflect', language), (ctx: any) => {
|
|
425
|
+
try {
|
|
426
|
+
const workspaceDir = resolveCommandWorkspaceDirStrict(api, ctx);
|
|
427
|
+
return handlePdReflect.handler({ ...ctx, api, workspaceDir } as any);
|
|
428
|
+
} catch (err) {
|
|
429
|
+
api.logger.error(`[PD] Command /pd-reflect failed: ${String(err)}`);
|
|
430
|
+
return { text: language === 'zh' ? "命令执行失败,请检查日志。" : "Command failed. Check logs." };
|
|
404
431
|
}
|
|
405
432
|
});
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
433
|
+
registerCommandWithAlias('pd-daily', 'pdd', getCommandDescription('pd-daily', language), () => ({
|
|
434
|
+
text: language === 'zh'
|
|
435
|
+
? "请执行 pd-daily 技能来配置并发送进化日报。系统将引导你完成配置流程,包括发送时间、渠道和报告风格偏好。"
|
|
436
|
+
: "Please execute the pd-daily skill to configure and send your daily evolution report. The system will guide you through the configuration process."
|
|
437
|
+
}));
|
|
438
|
+
registerCommandWithAlias('pd-grooming', 'pdg', getCommandDescription('pd-grooming', language), () => ({
|
|
439
|
+
text: language === 'zh'
|
|
440
|
+
? "请执行 pd-grooming 技能来执行大扫除。例如输入: '执行 pd-grooming 技能'"
|
|
441
|
+
: "Please execute the pd-grooming skill to clean up. For example: 'Execute pd-grooming skill'"
|
|
442
|
+
}));
|
|
443
|
+
registerCommandWithAlias('pd-help', 'pdh', getCommandDescription('pd-help', language), () => {
|
|
411
444
|
if (language === 'zh') {
|
|
412
445
|
return { text: `
|
|
413
446
|
📖 **Principles Disciple 命令大全**
|
|
414
447
|
|
|
415
|
-
##
|
|
416
|
-
|
|
|
417
|
-
|
|
418
|
-
| \`/pd-init\` | 初始化工作区 |
|
|
419
|
-
| \`/pd-bootstrap\` | 环境工具扫描 |
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
| \`/pd-
|
|
426
|
-
| \`/
|
|
427
|
-
| \`/
|
|
428
|
-
| \`/
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
| \`/pd-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
|
438
|
-
|
|
439
|
-
| \`/pd-
|
|
440
|
-
| \`/pd-
|
|
441
|
-
| \`/pd-
|
|
442
|
-
|
|
443
|
-
## 💡 常用命令示例
|
|
444
|
-
|
|
445
|
-
**减少 token 消耗:**
|
|
446
|
-
\`\`\`
|
|
447
|
-
/pd-context minimal
|
|
448
|
-
\`\`\`
|
|
449
|
-
|
|
450
|
-
**恢复完整上下文:**
|
|
451
|
-
\`\`\`
|
|
452
|
-
/pd-context full
|
|
453
|
-
\`\`\`
|
|
454
|
-
|
|
455
|
-
**查看当前配置:**
|
|
456
|
-
\`\`\`
|
|
457
|
-
/pd-context status
|
|
458
|
-
\`\`\`
|
|
459
|
-
|
|
460
|
-
🔍 输入任意命令后加 \`help\` 可查看详细帮助,如 \`/pd-context help\`
|
|
448
|
+
## 快速开始
|
|
449
|
+
| 短命令 | 长命令 | 用途 |
|
|
450
|
+
|--------|--------|------|
|
|
451
|
+
| \`/pdi\` | \`/pd-init\` | 初始化工作区 |
|
|
452
|
+
| \`/pdb\` | \`/pd-bootstrap\` | 环境工具扫描 |
|
|
453
|
+
| \`/pdr\` | \`/pd-research\` | 研究工具方案 |
|
|
454
|
+
|
|
455
|
+
## 状态查询
|
|
456
|
+
| 短命令 | 长命令 | 用途 |
|
|
457
|
+
|--------|--------|------|
|
|
458
|
+
| \`/pdk\` | \`/pd-okr\` | OKR 目标管理 |
|
|
459
|
+
| \`/pdt\` | \`/pd-thinking\` | 思维模型管理 |
|
|
460
|
+
| \`/pdrl\` | \`/pd-reflect\` | 手动触发反思 |
|
|
461
|
+
| \`/pdd\` | \`/pd-daily\` | 进化日报 |
|
|
462
|
+
| \`/pdg\` | \`/pd-grooming\` | 工作区清理 |
|
|
463
|
+
|
|
464
|
+
## 其他命令
|
|
465
|
+
| 命令 | 用途 |
|
|
466
|
+
|------|------|
|
|
467
|
+
| \`/pd-status\` | 查看系统状态 |
|
|
468
|
+
| \`/pd-context\` | 控制上下文注入 |
|
|
469
|
+
| \`/pd-focus\` | 焦点文件管理 |
|
|
470
|
+
| \`/pd-export\` | 导出数据 |
|
|
471
|
+
| \`/pd-samples\` | 审核纠错样本 |
|
|
472
|
+
| \`/pd-nocturnal-review\` | 审核 nocturnal 样本 |
|
|
473
|
+
| \`/pd-rollback\` | 回滚情绪事件惩罚 |
|
|
474
|
+
| \`/pd-principle-rollback\` | 回滚原则 |
|
|
475
|
+
| \`/pd-help\` | 显示本帮助 |
|
|
461
476
|
`.trim() };
|
|
462
477
|
} else {
|
|
463
478
|
return { text: `
|
|
464
479
|
📖 **Principles Disciple Command Reference**
|
|
465
480
|
|
|
466
|
-
##
|
|
467
|
-
|
|
|
468
|
-
|
|
469
|
-
| \`/pd-init\` | Initialize workspace |
|
|
470
|
-
| \`/pd-bootstrap\` | Scan environment tools |
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
| \`/pd-
|
|
477
|
-
| \`/pd-
|
|
478
|
-
| \`/
|
|
479
|
-
| \`/
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
| \`/pd-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
|
489
|
-
|
|
490
|
-
| \`/pd-
|
|
491
|
-
| \`/pd-
|
|
492
|
-
| \`/pd-
|
|
493
|
-
|
|
494
|
-
## 💡 Common Examples
|
|
495
|
-
|
|
496
|
-
**Reduce token usage:**
|
|
497
|
-
\`\`\`
|
|
498
|
-
/pd-context minimal
|
|
499
|
-
\`\`\`
|
|
500
|
-
|
|
501
|
-
**Restore full context:**
|
|
502
|
-
\`\`\`
|
|
503
|
-
/pd-context full
|
|
504
|
-
\`\`\`
|
|
505
|
-
|
|
506
|
-
**View current config:**
|
|
507
|
-
\`\`\`
|
|
508
|
-
/pd-context status
|
|
509
|
-
\`\`\`
|
|
510
|
-
|
|
511
|
-
🔍 Add \`help\` after any command for details, e.g., \`/pd-context help\`
|
|
481
|
+
## Quick Start
|
|
482
|
+
| Short | Full | Purpose |
|
|
483
|
+
|-------|------|---------|
|
|
484
|
+
| \`/pdi\` | \`/pd-init\` | Initialize workspace |
|
|
485
|
+
| \`/pdb\` | \`/pd-bootstrap\` | Scan environment tools |
|
|
486
|
+
| \`/pdr\` | \`/pd-research\` | Research tool solutions |
|
|
487
|
+
|
|
488
|
+
## Status
|
|
489
|
+
| Short | Full | Purpose |
|
|
490
|
+
|-------|------|---------|
|
|
491
|
+
| \`/pdk\` | \`/pd-okr\` | OKR goal management |
|
|
492
|
+
| \`/pdt\` | \`/pd-thinking\` | Mental model management |
|
|
493
|
+
| \`/pdrl\` | \`/pd-reflect\` | Manual reflection trigger |
|
|
494
|
+
| \`/pdd\` | \`/pd-daily\` | Evolution report |
|
|
495
|
+
| \`/pdg\` | \`/pd-grooming\` | Workspace cleanup |
|
|
496
|
+
|
|
497
|
+
## Other Commands
|
|
498
|
+
| Command | Purpose |
|
|
499
|
+
|---------|---------|
|
|
500
|
+
| \`/pd-status\` | View system status |
|
|
501
|
+
| \`/pd-context\` | Control context injection |
|
|
502
|
+
| \`/pd-focus\` | Focus file management |
|
|
503
|
+
| \`/pd-export\` | Export data |
|
|
504
|
+
| \`/pd-samples\` | Review correction samples |
|
|
505
|
+
| \`/pd-nocturnal-review\` | Review nocturnal samples |
|
|
506
|
+
| \`/pd-rollback\` | Rollback empathy penalty |
|
|
507
|
+
| \`/pd-principle-rollback\` | Rollback principle |
|
|
508
|
+
| \`/pd-help\` | Show this help |
|
|
512
509
|
`.trim() };
|
|
513
510
|
}
|
|
514
|
-
}
|
|
515
511
|
});
|
|
516
512
|
|
|
517
513
|
api.registerCommand({
|
|
@@ -520,7 +516,7 @@ const plugin = {
|
|
|
520
516
|
acceptsArgs: true,
|
|
521
517
|
handler: (ctx) => {
|
|
522
518
|
try {
|
|
523
|
-
const workspaceDir = api
|
|
519
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
524
520
|
// Ensure workspaceDir is in config for handlePainCommand
|
|
525
521
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
526
522
|
return handlePainCommand(ctx);
|
|
@@ -537,7 +533,7 @@ const plugin = {
|
|
|
537
533
|
acceptsArgs: true,
|
|
538
534
|
handler: (ctx) => {
|
|
539
535
|
try {
|
|
540
|
-
const workspaceDir = api
|
|
536
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
541
537
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
542
538
|
return handleContextCommand(ctx);
|
|
543
539
|
} catch (err) {
|
|
@@ -553,7 +549,7 @@ const plugin = {
|
|
|
553
549
|
acceptsArgs: true,
|
|
554
550
|
handler: (ctx) => {
|
|
555
551
|
try {
|
|
556
|
-
const workspaceDir = api
|
|
552
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
557
553
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
558
554
|
return handleFocusCommand(ctx, api);
|
|
559
555
|
} catch (err) {
|
|
@@ -569,7 +565,7 @@ const plugin = {
|
|
|
569
565
|
description: getCommandDescription('pd-evolution-status', language),
|
|
570
566
|
handler: (ctx) => {
|
|
571
567
|
try {
|
|
572
|
-
const workspaceDir = api
|
|
568
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
573
569
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
574
570
|
return handleEvolutionStatusCommand(ctx);
|
|
575
571
|
} catch (err) {
|
|
@@ -585,7 +581,7 @@ const plugin = {
|
|
|
585
581
|
acceptsArgs: true,
|
|
586
582
|
handler: (ctx) => {
|
|
587
583
|
try {
|
|
588
|
-
const workspaceDir = api
|
|
584
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
589
585
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
590
586
|
return handlePrincipleRollbackCommand(ctx);
|
|
591
587
|
} catch (err) {
|
|
@@ -601,7 +597,7 @@ const plugin = {
|
|
|
601
597
|
acceptsArgs: true,
|
|
602
598
|
handler: (ctx) => {
|
|
603
599
|
try {
|
|
604
|
-
const workspaceDir = api
|
|
600
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
605
601
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
606
602
|
return handleRollbackCommand(ctx);
|
|
607
603
|
} catch (err) {
|
|
@@ -618,7 +614,7 @@ const plugin = {
|
|
|
618
614
|
acceptsArgs: true,
|
|
619
615
|
handler: (ctx) => {
|
|
620
616
|
try {
|
|
621
|
-
const workspaceDir = api
|
|
617
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
622
618
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
623
619
|
return handleExportCommand(ctx);
|
|
624
620
|
} catch (err) {
|
|
@@ -634,7 +630,7 @@ const plugin = {
|
|
|
634
630
|
acceptsArgs: true,
|
|
635
631
|
handler: (ctx) => {
|
|
636
632
|
try {
|
|
637
|
-
const workspaceDir = api
|
|
633
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
638
634
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
639
635
|
return handleSamplesCommand(ctx);
|
|
640
636
|
} catch (err) {
|
|
@@ -650,7 +646,7 @@ const plugin = {
|
|
|
650
646
|
acceptsArgs: true,
|
|
651
647
|
handler: (ctx) => {
|
|
652
648
|
try {
|
|
653
|
-
const workspaceDir = api
|
|
649
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
654
650
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
655
651
|
return handleNocturnalReviewCommand(ctx);
|
|
656
652
|
} catch (err) {
|
|
@@ -666,7 +662,7 @@ const plugin = {
|
|
|
666
662
|
acceptsArgs: true,
|
|
667
663
|
handler: (ctx) => {
|
|
668
664
|
try {
|
|
669
|
-
const workspaceDir = api
|
|
665
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
670
666
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
671
667
|
return handleNocturnalTrainCommand(ctx);
|
|
672
668
|
} catch (err) {
|
|
@@ -682,7 +678,7 @@ const plugin = {
|
|
|
682
678
|
acceptsArgs: true,
|
|
683
679
|
handler: (ctx) => {
|
|
684
680
|
try {
|
|
685
|
-
const workspaceDir = api
|
|
681
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
686
682
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
687
683
|
return handleNocturnalRolloutCommand(ctx);
|
|
688
684
|
} catch (err) {
|
|
@@ -698,7 +694,7 @@ const plugin = {
|
|
|
698
694
|
acceptsArgs: true,
|
|
699
695
|
handler: (ctx) => {
|
|
700
696
|
try {
|
|
701
|
-
const workspaceDir = api
|
|
697
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
702
698
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
703
699
|
return handleWorkflowDebugCommand(ctx);
|
|
704
700
|
} catch (err) {
|
|
@@ -715,7 +711,7 @@ const plugin = {
|
|
|
715
711
|
acceptsArgs: true,
|
|
716
712
|
handler: (ctx) => {
|
|
717
713
|
try {
|
|
718
|
-
const workspaceDir = api
|
|
714
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
719
715
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
720
716
|
return handlePromoteImplCommand(ctx);
|
|
721
717
|
} catch (err) {
|
|
@@ -731,7 +727,7 @@ const plugin = {
|
|
|
731
727
|
acceptsArgs: true,
|
|
732
728
|
handler: (ctx) => {
|
|
733
729
|
try {
|
|
734
|
-
const workspaceDir = api
|
|
730
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
735
731
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
736
732
|
return handleDisableImplCommand(ctx);
|
|
737
733
|
} catch (err) {
|
|
@@ -747,7 +743,7 @@ const plugin = {
|
|
|
747
743
|
acceptsArgs: true,
|
|
748
744
|
handler: (ctx) => {
|
|
749
745
|
try {
|
|
750
|
-
const workspaceDir = api
|
|
746
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
751
747
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
752
748
|
return handleArchiveImplCommand(ctx);
|
|
753
749
|
} catch (err) {
|
|
@@ -763,7 +759,7 @@ const plugin = {
|
|
|
763
759
|
acceptsArgs: true,
|
|
764
760
|
handler: (ctx) => {
|
|
765
761
|
try {
|
|
766
|
-
const workspaceDir = api
|
|
762
|
+
const workspaceDir = resolveCommandWorkspaceDir(api, ctx);
|
|
767
763
|
if (ctx.config) ctx.config.workspaceDir = workspaceDir;
|
|
768
764
|
return handleRollbackImplCommand(ctx);
|
|
769
765
|
} catch (err) {
|
|
@@ -17,7 +17,7 @@ export interface CentralHealthResponse {
|
|
|
17
17
|
* Evolution, Principles, and Queue stats are workspace-specific.
|
|
18
18
|
*/
|
|
19
19
|
export class CentralHealthService {
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
getAllWorkspaceHealth(): CentralHealthResponse {
|
|
22
22
|
const centralDb = getCentralDatabase();
|
|
23
23
|
const workspaces: WorkspaceHealthEntry[] = [];
|
|
@@ -23,14 +23,14 @@ export class CentralOverviewService {
|
|
|
23
23
|
this.centralDb = getCentralDatabase();
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
dispose(): void {
|
|
28
28
|
// Do NOT dispose centralDb — it's a singleton shared across all requests.
|
|
29
29
|
// Individual services that open per-request connections (e.g. HealthQueryService)
|
|
30
30
|
// must dispose their own connections, but the central aggregated DB lives for
|
|
31
31
|
// the lifetime of the process.
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
|
|
35
35
|
getOverview(days = 30): CentralOverviewResponse {
|
|
36
36
|
const stats = this.centralDb.getOverviewStats();
|
|
@@ -60,7 +60,7 @@ export class CentralOverviewService {
|
|
|
60
60
|
// gate_blocks: no equivalent in aggregated DB schema; hardcode to 0
|
|
61
61
|
|
|
62
62
|
// D-06: sampleQueue.counters from aggregated_correction_samples GROUP BY review_status
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
let sampleCounters: Record<string, number> = {};
|
|
65
65
|
try {
|
|
66
66
|
sampleCounters = this.centralDb.getSampleCountersByStatus();
|
|
@@ -154,7 +154,7 @@ export class EvolutionQueryService {
|
|
|
154
154
|
* 释放资源
|
|
155
155
|
* 注意:不关闭 trajectory,因为它是单例由 TrajectoryRegistry 管理
|
|
156
156
|
*/
|
|
157
|
-
|
|
157
|
+
|
|
158
158
|
dispose(): void {
|
|
159
159
|
// EvolutionQueryService 不拥有 trajectory,所以不关闭它
|
|
160
160
|
// trajectory 是由 TrajectoryRegistry 管理的单例
|