principles-disciple 1.7.5 → 1.7.8
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 +5 -15
- package/dist/commands/evolution-status.js +29 -48
- package/dist/commands/export.js +61 -8
- package/dist/commands/nocturnal-review.d.ts +24 -0
- package/dist/commands/nocturnal-review.js +265 -0
- package/dist/commands/nocturnal-rollout.d.ts +27 -0
- package/dist/commands/nocturnal-rollout.js +671 -0
- package/dist/commands/nocturnal-train.d.ts +25 -0
- package/dist/commands/nocturnal-train.js +919 -0
- package/dist/commands/pain.js +8 -21
- package/dist/config/defaults/runtime.d.ts +40 -0
- package/dist/config/defaults/runtime.js +44 -0
- package/dist/config/errors.d.ts +84 -0
- package/dist/config/errors.js +94 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.js +7 -0
- package/dist/constants/diagnostician.d.ts +0 -4
- package/dist/constants/diagnostician.js +0 -4
- package/dist/constants/tools.d.ts +2 -2
- package/dist/constants/tools.js +1 -1
- package/dist/core/adaptive-thresholds.d.ts +186 -0
- package/dist/core/adaptive-thresholds.js +300 -0
- package/dist/core/config.d.ts +2 -38
- package/dist/core/config.js +6 -61
- package/dist/core/control-ui-db.d.ts +27 -0
- package/dist/core/control-ui-db.js +18 -0
- package/dist/core/event-log.d.ts +1 -2
- package/dist/core/event-log.js +0 -3
- package/dist/core/evolution-engine.js +1 -21
- package/dist/core/evolution-reducer.d.ts +7 -1
- package/dist/core/evolution-reducer.js +56 -4
- package/dist/core/evolution-types.d.ts +61 -9
- package/dist/core/evolution-types.js +31 -9
- package/dist/core/external-training-contract.d.ts +276 -0
- package/dist/core/external-training-contract.js +269 -0
- package/dist/core/local-worker-routing.d.ts +175 -0
- package/dist/core/local-worker-routing.js +525 -0
- package/dist/core/model-deployment-registry.d.ts +218 -0
- package/dist/core/model-deployment-registry.js +503 -0
- package/dist/core/model-training-registry.d.ts +295 -0
- package/dist/core/model-training-registry.js +475 -0
- package/dist/core/nocturnal-arbiter.d.ts +159 -0
- package/dist/core/nocturnal-arbiter.js +534 -0
- package/dist/core/nocturnal-candidate-scoring.d.ts +137 -0
- package/dist/core/nocturnal-candidate-scoring.js +266 -0
- package/dist/core/nocturnal-compliance.d.ts +175 -0
- package/dist/core/nocturnal-compliance.js +824 -0
- package/dist/core/nocturnal-dataset.d.ts +224 -0
- package/dist/core/nocturnal-dataset.js +443 -0
- package/dist/core/nocturnal-executability.d.ts +85 -0
- package/dist/core/nocturnal-executability.js +331 -0
- package/dist/core/nocturnal-export.d.ts +124 -0
- package/dist/core/nocturnal-export.js +275 -0
- package/dist/core/nocturnal-paths.d.ts +124 -0
- package/dist/core/nocturnal-paths.js +214 -0
- package/dist/core/nocturnal-trajectory-extractor.d.ts +242 -0
- package/dist/core/nocturnal-trajectory-extractor.js +307 -0
- package/dist/core/nocturnal-trinity.d.ts +311 -0
- package/dist/core/nocturnal-trinity.js +880 -0
- package/dist/core/path-resolver.js +2 -1
- package/dist/core/paths.d.ts +6 -0
- package/dist/core/paths.js +6 -0
- package/dist/core/principle-training-state.d.ts +121 -0
- package/dist/core/principle-training-state.js +321 -0
- package/dist/core/promotion-gate.d.ts +238 -0
- package/dist/core/promotion-gate.js +529 -0
- package/dist/core/session-tracker.d.ts +10 -0
- package/dist/core/session-tracker.js +14 -0
- package/dist/core/shadow-observation-registry.d.ts +217 -0
- package/dist/core/shadow-observation-registry.js +308 -0
- package/dist/core/training-program.d.ts +233 -0
- package/dist/core/training-program.js +433 -0
- package/dist/core/trajectory.d.ts +155 -1
- package/dist/core/trajectory.js +292 -8
- package/dist/core/workspace-context.d.ts +0 -6
- package/dist/core/workspace-context.js +0 -12
- package/dist/hooks/bash-risk.d.ts +57 -0
- package/dist/hooks/bash-risk.js +137 -0
- package/dist/hooks/edit-verification.d.ts +62 -0
- package/dist/hooks/edit-verification.js +256 -0
- package/dist/hooks/gate-block-helper.d.ts +44 -0
- package/dist/hooks/gate-block-helper.js +119 -0
- package/dist/hooks/gate.d.ts +18 -0
- package/dist/hooks/gate.js +62 -751
- package/dist/hooks/gfi-gate.d.ts +40 -0
- package/dist/hooks/gfi-gate.js +113 -0
- package/dist/hooks/pain.js +6 -9
- package/dist/hooks/progressive-trust-gate.d.ts +51 -0
- package/dist/hooks/progressive-trust-gate.js +89 -0
- package/dist/hooks/prompt.d.ts +11 -11
- package/dist/hooks/prompt.js +167 -77
- package/dist/hooks/subagent.js +43 -6
- package/dist/hooks/thinking-checkpoint.d.ts +37 -0
- package/dist/hooks/thinking-checkpoint.js +51 -0
- package/dist/http/principles-console-route.js +13 -3
- package/dist/i18n/commands.js +8 -8
- package/dist/index.js +129 -28
- package/dist/service/central-database.js +2 -1
- package/dist/service/control-ui-query-service.d.ts +1 -1
- package/dist/service/control-ui-query-service.js +3 -3
- package/dist/service/evolution-query-service.d.ts +1 -1
- package/dist/service/evolution-query-service.js +5 -5
- package/dist/service/evolution-worker.d.ts +52 -4
- package/dist/service/evolution-worker.js +328 -16
- package/dist/service/nocturnal-runtime.d.ts +183 -0
- package/dist/service/nocturnal-runtime.js +352 -0
- package/dist/service/nocturnal-service.d.ts +163 -0
- package/dist/service/nocturnal-service.js +787 -0
- package/dist/service/nocturnal-target-selector.d.ts +145 -0
- package/dist/service/nocturnal-target-selector.js +315 -0
- package/dist/service/phase3-input-filter.d.ts +48 -12
- package/dist/service/phase3-input-filter.js +84 -18
- package/dist/service/runtime-summary-service.d.ts +34 -10
- package/dist/service/runtime-summary-service.js +87 -48
- package/dist/tools/deep-reflect.js +2 -1
- package/dist/types/event-types.d.ts +4 -10
- package/dist/types/runtime-summary.d.ts +47 -0
- package/dist/types/runtime-summary.js +1 -0
- package/dist/types.d.ts +0 -3
- package/dist/types.js +0 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/templates/langs/en/skills/pd-mentor/SKILL.md +5 -5
- package/templates/langs/zh/skills/pd-mentor/SKILL.md +5 -5
- package/templates/pain_settings.json +0 -6
- package/dist/commands/trust.d.ts +0 -4
- package/dist/commands/trust.js +0 -78
- package/dist/core/trust-engine.d.ts +0 -96
- package/dist/core/trust-engine.js +0 -286
package/dist/commands/context.js
CHANGED
|
@@ -64,7 +64,6 @@ function showStatus(workspaceDir, isZh) {
|
|
|
64
64
|
|------|------|------|
|
|
65
65
|
| 核心原则 | ✅ 始终开启 | 不可关闭 |
|
|
66
66
|
| 思维模型 | ${config.thinkingOs ? '✅ 开启' : '❌ 关闭'} | /pd-context thinking on/off |
|
|
67
|
-
| 信任分数 | ${config.trustScore ? '✅ 开启' : '❌ 关闭'} | /pd-context trust on/off |
|
|
68
67
|
| 反思日志 | ${config.reflectionLog ? '✅ 开启' : '❌ 关闭'} | /pd-context reflection on/off |
|
|
69
68
|
| 项目上下文 | ${formatProjectFocus(config.projectFocus, isZh)} | /pd-context focus full/summary/off |
|
|
70
69
|
|
|
@@ -79,7 +78,6 @@ function showStatus(workspaceDir, isZh) {
|
|
|
79
78
|
|---------|--------|---------|
|
|
80
79
|
| Core Principles | ✅ Always ON | Not configurable |
|
|
81
80
|
| Thinking OS | ${config.thinkingOs ? '✅ ON' : '❌ OFF'} | /pd-context thinking on/off |
|
|
82
|
-
| Trust Score | ${config.trustScore ? '✅ ON' : '❌ OFF'} | /pd-context trust on/off |
|
|
83
81
|
| Reflection Log | ${config.reflectionLog ? '✅ ON' : '❌ OFF'} | /pd-context reflection on/off |
|
|
84
82
|
| Project Context | ${formatProjectFocus(config.projectFocus, isZh)} | /pd-context focus full/summary/off |
|
|
85
83
|
|
|
@@ -106,7 +104,7 @@ function toggleSetting(workspaceDir, key, value, isZh) {
|
|
|
106
104
|
}
|
|
107
105
|
const newValue = config[key];
|
|
108
106
|
const keyName = isZh
|
|
109
|
-
? { thinkingOs: '思维模型',
|
|
107
|
+
? { thinkingOs: '思维模型', reflectionLog: '反思日志' }[key]
|
|
110
108
|
: key;
|
|
111
109
|
// No change needed
|
|
112
110
|
if (oldValue === newValue) {
|
|
@@ -184,7 +182,6 @@ function applyPreset(workspaceDir, preset, isZh) {
|
|
|
184
182
|
case 'minimal':
|
|
185
183
|
config = {
|
|
186
184
|
thinkingOs: false,
|
|
187
|
-
trustScore: true,
|
|
188
185
|
reflectionLog: false,
|
|
189
186
|
projectFocus: 'off',
|
|
190
187
|
evolutionContext: { ...defaultContextConfig.evolutionContext }
|
|
@@ -193,7 +190,6 @@ function applyPreset(workspaceDir, preset, isZh) {
|
|
|
193
190
|
case 'standard':
|
|
194
191
|
config = {
|
|
195
192
|
thinkingOs: true,
|
|
196
|
-
trustScore: true,
|
|
197
193
|
reflectionLog: false,
|
|
198
194
|
projectFocus: 'off',
|
|
199
195
|
evolutionContext: { ...defaultContextConfig.evolutionContext }
|
|
@@ -202,7 +198,6 @@ function applyPreset(workspaceDir, preset, isZh) {
|
|
|
202
198
|
case 'full':
|
|
203
199
|
config = {
|
|
204
200
|
thinkingOs: true,
|
|
205
|
-
trustScore: true,
|
|
206
201
|
reflectionLog: true,
|
|
207
202
|
projectFocus: 'summary',
|
|
208
203
|
evolutionContext: { ...defaultContextConfig.evolutionContext }
|
|
@@ -236,13 +231,12 @@ function showHelp(isZh) {
|
|
|
236
231
|
|
|
237
232
|
**单项控制**:
|
|
238
233
|
\`/pd-context thinking on/off\` - 开关思维模型
|
|
239
|
-
\`/pd-context trust on/off\` - 开关信任分数
|
|
240
234
|
\`/pd-context reflection on/off\` - 开关反思日志
|
|
241
235
|
\`/pd-context focus full/summary/off\` - 设置项目上下文模式
|
|
242
236
|
|
|
243
237
|
**预设模式**:
|
|
244
|
-
\`/pd-context minimal\` -
|
|
245
|
-
\`/pd-context standard\` -
|
|
238
|
+
\`/pd-context minimal\` - 最小模式(仅核心原则)
|
|
239
|
+
\`/pd-context standard\` - 标准模式(原则+思维模型)
|
|
246
240
|
\`/pd-context full\` - 完整模式(全部开启)
|
|
247
241
|
|
|
248
242
|
**注意**: 核心原则始终注入,不可关闭。
|
|
@@ -257,13 +251,12 @@ function showHelp(isZh) {
|
|
|
257
251
|
|
|
258
252
|
**Individual Control**:
|
|
259
253
|
\`/pd-context thinking on/off\` - Toggle Thinking OS
|
|
260
|
-
\`/pd-context trust on/off\` - Toggle Trust Score
|
|
261
254
|
\`/pd-context reflection on/off\` - Toggle Reflection Log
|
|
262
255
|
\`/pd-context focus full/summary/off\` - Set Project Context mode
|
|
263
256
|
|
|
264
257
|
**Presets**:
|
|
265
|
-
\`/pd-context minimal\` - Minimal mode (
|
|
266
|
-
\`/pd-context standard\` - Standard mode (principles + thinking
|
|
258
|
+
\`/pd-context minimal\` - Minimal mode (core principles only)
|
|
259
|
+
\`/pd-context standard\` - Standard mode (principles + thinking)
|
|
267
260
|
\`/pd-context full\` - Full mode (all enabled)
|
|
268
261
|
|
|
269
262
|
**Note**: Core Principles are always injected and cannot be disabled.
|
|
@@ -288,9 +281,6 @@ export function handleContextCommand(ctx) {
|
|
|
288
281
|
case 'thinking':
|
|
289
282
|
result = toggleSetting(workspaceDir, 'thinkingOs', value, isZh);
|
|
290
283
|
break;
|
|
291
|
-
case 'trust':
|
|
292
|
-
result = toggleSetting(workspaceDir, 'trustScore', value, isZh);
|
|
293
|
-
break;
|
|
294
284
|
case 'reflection':
|
|
295
285
|
result = toggleSetting(workspaceDir, 'reflectionLog', value, isZh);
|
|
296
286
|
break;
|
|
@@ -1,33 +1,12 @@
|
|
|
1
1
|
import { EvolutionReducerImpl } from '../core/evolution-reducer.js';
|
|
2
2
|
import { normalizeLanguage } from '../i18n/commands.js';
|
|
3
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
4
|
function formatNumber(value) {
|
|
23
5
|
if (value === null || Number.isNaN(value)) {
|
|
24
6
|
return '--';
|
|
25
7
|
}
|
|
26
8
|
return Number.isInteger(value) ? String(value) : value.toFixed(1);
|
|
27
9
|
}
|
|
28
|
-
function formatStage(value) {
|
|
29
|
-
return value === null ? '--' : String(value);
|
|
30
|
-
}
|
|
31
10
|
function formatSources(sources) {
|
|
32
11
|
if (sources.length === 0) {
|
|
33
12
|
return '--';
|
|
@@ -44,7 +23,6 @@ function buildEnglishOutput(workspaceDir, sessionId, warnings, stats, summary) {
|
|
|
44
23
|
'================',
|
|
45
24
|
'',
|
|
46
25
|
'Control Plane',
|
|
47
|
-
`- Legacy Trust: ${formatNumber(summary.legacyTrust.score)}/100 (stage ${formatStage(summary.legacyTrust.stage)}, legacy/frozen, ${summary.legacyTrust.rewardPolicy})`,
|
|
48
26
|
`- Session GFI: current ${formatNumber(summary.gfi.current)}, peak ${formatNumber(summary.gfi.peak)} (${summary.gfi.dataQuality})`,
|
|
49
27
|
`- GFI Sources: ${formatSources(summary.gfi.sources)}`,
|
|
50
28
|
`- Pain Flag: ${summary.pain.activeFlag ? 'active' : 'inactive'}${summary.pain.activeFlagSource ? ` (${summary.pain.activeFlagSource})` : ''}`,
|
|
@@ -53,9 +31,11 @@ function buildEnglishOutput(workspaceDir, sessionId, warnings, stats, summary) {
|
|
|
53
31
|
'',
|
|
54
32
|
'Evolution',
|
|
55
33
|
`- Queue: pending ${summary.evolution.queue.pending}, in_progress ${summary.evolution.queue.inProgress}, completed ${summary.evolution.queue.completed} (${summary.evolution.dataQuality})`,
|
|
56
|
-
`- Directive
|
|
57
|
-
`-
|
|
58
|
-
`-
|
|
34
|
+
`- Legacy Directive File: ${summary.phase3.legacyDirectiveFilePresent ? 'present' : 'missing'} (compatibility-only display artifact)`,
|
|
35
|
+
`- Note: Legacy directive file is NOT a truth source for Phase 3 eligibility. Queue is the only authoritative execution truth source.`,
|
|
36
|
+
`- Active Evolution Task: ${summary.evolution.directive.taskPreview ?? '--'}`,
|
|
37
|
+
`- Phase 3: ready ${summary.phase3.phase3ShadowEligible ? 'yes' : 'no'}, queueTruthReady ${summary.phase3.queueTruthReady ? 'yes' : 'no'}, eligible ${summary.phase3.evolutionEligible}, reference_only ${summary.phase3.evolutionReferenceOnly}, rejected ${summary.phase3.evolutionRejected}${summary.phase3.evolutionReferenceOnlyReasons.length > 0 ? ` (reference ${summary.phase3.evolutionReferenceOnlyReasons.slice(0, 2).join(', ')})` : ''}${summary.phase3.evolutionRejectedReasons.length > 0 ? ` (${summary.phase3.evolutionRejectedReasons.slice(0, 3).join(', ')})` : ''}`,
|
|
38
|
+
`- Phase 3 Legacy Directive File: ${summary.phase3.directiveStatus} (${summary.phase3.directiveIgnoredReason})`,
|
|
59
39
|
'',
|
|
60
40
|
'Principles',
|
|
61
41
|
`- candidate principles: ${stats.candidateCount}`,
|
|
@@ -79,34 +59,35 @@ function buildEnglishOutput(workspaceDir, sessionId, warnings, stats, summary) {
|
|
|
79
59
|
}
|
|
80
60
|
function buildChineseOutput(workspaceDir, sessionId, warnings, stats, summary) {
|
|
81
61
|
const lines = [
|
|
82
|
-
'
|
|
62
|
+
'进化状态',
|
|
83
63
|
'================',
|
|
84
64
|
'',
|
|
85
|
-
'
|
|
86
|
-
`-
|
|
87
|
-
`-
|
|
88
|
-
`-
|
|
89
|
-
`- Pain
|
|
90
|
-
`-
|
|
91
|
-
`- Gate \u4e8b\u4ef6: block ${formatNumber(summary.gate.recentBlocks)}\uff0cbypass ${formatNumber(summary.gate.recentBypasses)}\uff08${summary.gate.dataQuality}\uff09`,
|
|
65
|
+
'控制面',
|
|
66
|
+
`- 会话 GFI: 当前 ${formatNumber(summary.gfi.current)},峰值 ${formatNumber(summary.gfi.peak)}(${summary.gfi.dataQuality})`,
|
|
67
|
+
`- GFI 来源: ${formatSources(summary.gfi.sources)}`,
|
|
68
|
+
`- Pain Flag: ${summary.pain.activeFlag ? 'active' : 'inactive'}${summary.pain.activeFlagSource ? `(${summary.pain.activeFlagSource})` : ''}`,
|
|
69
|
+
`- 最近 Pain 信号: ${summary.pain.lastSignal ? `${summary.pain.lastSignal.source}${summary.pain.lastSignal.reason ? ` - ${summary.pain.lastSignal.reason}` : ''}` : '--'}`,
|
|
70
|
+
`- Gate 事件: block ${formatNumber(summary.gate.recentBlocks)},bypass ${formatNumber(summary.gate.recentBypasses)}(${summary.gate.dataQuality})`,
|
|
92
71
|
'',
|
|
93
|
-
'
|
|
94
|
-
`-
|
|
95
|
-
`- Directive
|
|
96
|
-
`-
|
|
97
|
-
`-
|
|
72
|
+
'进化',
|
|
73
|
+
`- 队列: pending ${summary.evolution.queue.pending},in_progress ${summary.evolution.queue.inProgress},completed ${summary.evolution.queue.completed}(${summary.evolution.dataQuality})`,
|
|
74
|
+
`- Legacy Directive File: ${summary.phase3.legacyDirectiveFilePresent ? 'present' : 'missing'} (兼容仅显示产物)`,
|
|
75
|
+
`- 注:Legacy directive file 不是 Phase 3 合格性的真实源。队列是唯一权威的执行真实源。`,
|
|
76
|
+
`- Active Evolution Task: ${summary.evolution.directive.taskPreview ?? '--'}`,
|
|
77
|
+
`- Phase 3: ready ${summary.phase3.phase3ShadowEligible ? 'yes' : 'no'},queueTruthReady ${summary.phase3.queueTruthReady ? 'yes' : 'no'},eligible ${summary.phase3.evolutionEligible},reference_only ${summary.phase3.evolutionReferenceOnly},rejected ${summary.phase3.evolutionRejected}${summary.phase3.evolutionReferenceOnlyReasons.length > 0 ? `(reference ${summary.phase3.evolutionReferenceOnlyReasons.slice(0, 2).join(', ')})` : ''}${summary.phase3.evolutionRejectedReasons.length > 0 ? `(${summary.phase3.evolutionRejectedReasons.slice(0, 3).join(', ')})` : ''}`,
|
|
78
|
+
`- Phase 3 Legacy Directive File: ${summary.phase3.directiveStatus} (${summary.phase3.directiveIgnoredReason})`,
|
|
98
79
|
'',
|
|
99
|
-
'
|
|
100
|
-
`-
|
|
101
|
-
`-
|
|
102
|
-
`-
|
|
103
|
-
`-
|
|
104
|
-
`-
|
|
80
|
+
'原则统计',
|
|
81
|
+
`- 候选原则: ${stats.candidateCount}`,
|
|
82
|
+
`- 观察期原则: ${stats.probationCount}`,
|
|
83
|
+
`- 生效原则: ${stats.activeCount}`,
|
|
84
|
+
`- 已废弃原则: ${stats.deprecatedCount}`,
|
|
85
|
+
`- 最近晋升: ${stats.lastPromotedAt ?? '无'}`,
|
|
105
86
|
'',
|
|
106
|
-
'
|
|
107
|
-
`-
|
|
108
|
-
`- Session: ${sessionId ?? '--'}
|
|
109
|
-
`-
|
|
87
|
+
'元数据',
|
|
88
|
+
`- 工作区: ${workspaceDir}`,
|
|
89
|
+
`- Session: ${sessionId ?? '--'}(${summary.metadata.selectedSessionReason})`,
|
|
90
|
+
`- 生成时间: ${summary.metadata.generatedAt}`,
|
|
110
91
|
];
|
|
111
92
|
if (warnings.length > 0) {
|
|
112
93
|
lines.push('', '警告');
|
package/dist/commands/export.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
2
|
+
import { exportORPOSamples, listExports } from '../core/nocturnal-export.js';
|
|
2
3
|
function isZh(ctx) {
|
|
3
4
|
return String(ctx.config?.language || 'en').startsWith('zh');
|
|
4
5
|
}
|
|
@@ -6,16 +7,68 @@ export function handleExportCommand(ctx) {
|
|
|
6
7
|
const workspaceDir = ctx.config?.workspaceDir || process.cwd();
|
|
7
8
|
const zh = isZh(ctx);
|
|
8
9
|
const args = (ctx.args || '').trim();
|
|
9
|
-
const
|
|
10
|
+
const parts = args.split(/\s+/).filter(Boolean);
|
|
11
|
+
const [subcommand = 'corrections'] = parts;
|
|
10
12
|
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
13
|
try {
|
|
14
|
+
if (subcommand === 'orpo') {
|
|
15
|
+
// Nocturnal ORPO export
|
|
16
|
+
// Usage: pd-export orpo [--family=<targetModelFamily>]
|
|
17
|
+
const familyArg = parts.find((p) => p.startsWith('--family='));
|
|
18
|
+
const targetModelFamily = familyArg ? familyArg.split('=')[1] : undefined;
|
|
19
|
+
const result = exportORPOSamples(workspaceDir, targetModelFamily);
|
|
20
|
+
if (!result.success) {
|
|
21
|
+
const reasonMap = {
|
|
22
|
+
no_approved_samples: zh
|
|
23
|
+
? '没有已批准的样本'
|
|
24
|
+
: 'No approved samples',
|
|
25
|
+
family_mismatch: zh
|
|
26
|
+
? '没有找到指定模型家族的已批准样本'
|
|
27
|
+
: 'No approved samples for the specified target model family',
|
|
28
|
+
all_samples_missing_artifacts: zh
|
|
29
|
+
? '所有样本的 artifact 文件都缺失'
|
|
30
|
+
: 'All sample artifact files are missing',
|
|
31
|
+
};
|
|
32
|
+
return {
|
|
33
|
+
text: zh
|
|
34
|
+
? `ORPO 导出失败: ${reasonMap[result.emptyReason ?? ''] ?? result.error}`
|
|
35
|
+
: `ORPO export failed: ${reasonMap[result.emptyReason ?? ''] ?? result.error}`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
text: zh
|
|
40
|
+
? `已导出 ORPO 决策点样本到 ${result.manifest.exportPath},` +
|
|
41
|
+
`共 ${result.manifest.sampleCount} 条,模型家族: ${result.manifest.targetModelFamily},` +
|
|
42
|
+
`数据集指纹: ${result.manifest.datasetFingerprint.substring(0, 16)}...`
|
|
43
|
+
: `Exported ORPO decision-point samples to ${result.manifest.exportPath}, ` +
|
|
44
|
+
`${result.manifest.sampleCount} samples, target: ${result.manifest.targetModelFamily}, ` +
|
|
45
|
+
`dataset fingerprint: ${result.manifest.datasetFingerprint.substring(0, 16)}...`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (subcommand === 'orpo-list') {
|
|
49
|
+
// List previous ORPO exports
|
|
50
|
+
const exports = listExports(workspaceDir);
|
|
51
|
+
if (exports.length === 0) {
|
|
52
|
+
return {
|
|
53
|
+
text: zh
|
|
54
|
+
? '没有找到 ORPO 导出记录。'
|
|
55
|
+
: 'No ORPO exports found.',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const lines = exports.slice(0, 10).map((e) => `- ${e.exportId.substring(0, 8)}... | ${e.sampleCount} samples | ${e.targetModelFamily} | ${new Date(e.createdAt).toLocaleDateString()}`);
|
|
59
|
+
return {
|
|
60
|
+
text: zh
|
|
61
|
+
? `ORPO 导出记录:\n${lines.join('\n')}`
|
|
62
|
+
: `ORPO exports:\n${lines.join('\n')}`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (subcommand !== 'analytics' && subcommand !== 'corrections') {
|
|
66
|
+
return {
|
|
67
|
+
text: zh
|
|
68
|
+
? '无效的导出类型。请使用 `analytics`、`corrections [--redacted]` 或 `orpo [--family=<target>]`。'
|
|
69
|
+
: 'Invalid export target. Use `analytics`, `corrections [--redacted]`, or `orpo [--family=<target>]`',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
19
72
|
if (subcommand === 'analytics') {
|
|
20
73
|
const result = wctx.trajectory.exportAnalytics();
|
|
21
74
|
return {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nocturnal Review Command — Human Review Queue for Nocturnal Dataset
|
|
3
|
+
* =================================================================
|
|
4
|
+
*
|
|
5
|
+
* PURPOSE: Provide human review gateway before training export.
|
|
6
|
+
* Reviews operate on nocturnal dataset records, NOT on artifact files directly.
|
|
7
|
+
*
|
|
8
|
+
* COMMAND SHAPE:
|
|
9
|
+
* pd-nocturnal-review list — list pending review samples
|
|
10
|
+
* pd-nocturnal-review approve <fingerprint> [reason] — approve for training
|
|
11
|
+
* pd-nocturnal-review reject <fingerprint> [reason] — reject sample
|
|
12
|
+
* pd-nocturnal-review show <fingerprint> — show sample lineage summary
|
|
13
|
+
* pd-nocturnal-review set-family <fingerprint> <family> — set target model family
|
|
14
|
+
* pd-nocturnal-review stats — show dataset statistics
|
|
15
|
+
*
|
|
16
|
+
* DESIGN CONSTRAINTS:
|
|
17
|
+
* - Review state lives in dataset registry, not in artifacts
|
|
18
|
+
* - approve/reject require reason (unless default is provided)
|
|
19
|
+
* - Rejected samples cannot enter export
|
|
20
|
+
* - Superseded samples cannot enter export
|
|
21
|
+
* - No Web UI (CLI only)
|
|
22
|
+
*/
|
|
23
|
+
import type { PluginCommandContext, PluginCommandResult } from '../openclaw-sdk.js';
|
|
24
|
+
export declare function handleNocturnalReviewCommand(ctx: PluginCommandContext): PluginCommandResult;
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nocturnal Review Command — Human Review Queue for Nocturnal Dataset
|
|
3
|
+
* =================================================================
|
|
4
|
+
*
|
|
5
|
+
* PURPOSE: Provide human review gateway before training export.
|
|
6
|
+
* Reviews operate on nocturnal dataset records, NOT on artifact files directly.
|
|
7
|
+
*
|
|
8
|
+
* COMMAND SHAPE:
|
|
9
|
+
* pd-nocturnal-review list — list pending review samples
|
|
10
|
+
* pd-nocturnal-review approve <fingerprint> [reason] — approve for training
|
|
11
|
+
* pd-nocturnal-review reject <fingerprint> [reason] — reject sample
|
|
12
|
+
* pd-nocturnal-review show <fingerprint> — show sample lineage summary
|
|
13
|
+
* pd-nocturnal-review set-family <fingerprint> <family> — set target model family
|
|
14
|
+
* pd-nocturnal-review stats — show dataset statistics
|
|
15
|
+
*
|
|
16
|
+
* DESIGN CONSTRAINTS:
|
|
17
|
+
* - Review state lives in dataset registry, not in artifacts
|
|
18
|
+
* - approve/reject require reason (unless default is provided)
|
|
19
|
+
* - Rejected samples cannot enter export
|
|
20
|
+
* - Superseded samples cannot enter export
|
|
21
|
+
* - No Web UI (CLI only)
|
|
22
|
+
*/
|
|
23
|
+
import * as fs from 'fs';
|
|
24
|
+
import { listDatasetRecords, getDatasetRecord, updateReviewStatus, updateTargetModelFamily, getDatasetStats, } from '../core/nocturnal-dataset.js';
|
|
25
|
+
function isZh(ctx) {
|
|
26
|
+
return String(ctx.config?.language || 'en').startsWith('zh');
|
|
27
|
+
}
|
|
28
|
+
function formatRecord(record, includeDetails = false) {
|
|
29
|
+
const lines = [];
|
|
30
|
+
lines.push(` sampleFingerprint: ${record.sampleFingerprint.substring(0, 16)}...`);
|
|
31
|
+
lines.push(` artifactId: ${record.artifactId}`);
|
|
32
|
+
lines.push(` sessionId: ${record.sessionId}`);
|
|
33
|
+
lines.push(` principleId: ${record.principleId}`);
|
|
34
|
+
lines.push(` targetModelFamily: ${record.targetModelFamily ?? '(none)'}`);
|
|
35
|
+
lines.push(` reviewStatus: ${record.reviewStatus}`);
|
|
36
|
+
if (record.reviewReason) {
|
|
37
|
+
lines.push(` reviewReason: ${record.reviewReason}`);
|
|
38
|
+
}
|
|
39
|
+
lines.push(` createdAt: ${new Date(record.createdAt).toLocaleString('en-US')}`);
|
|
40
|
+
if (includeDetails) {
|
|
41
|
+
const artifactPath = record.artifactPath;
|
|
42
|
+
if (fs.existsSync(artifactPath)) {
|
|
43
|
+
try {
|
|
44
|
+
const content = fs.readFileSync(artifactPath, 'utf-8');
|
|
45
|
+
const artifact = JSON.parse(content);
|
|
46
|
+
lines.push(` artifact: ${artifactPath}`);
|
|
47
|
+
if (artifact.badDecision) {
|
|
48
|
+
lines.push(` badDecision: ${artifact.badDecision.substring(0, 80)}...`);
|
|
49
|
+
}
|
|
50
|
+
if (artifact.betterDecision) {
|
|
51
|
+
lines.push(` betterDecision: ${artifact.betterDecision.substring(0, 80)}...`);
|
|
52
|
+
}
|
|
53
|
+
if (artifact.rationale) {
|
|
54
|
+
lines.push(` rationale: ${artifact.rationale.substring(0, 80)}...`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
lines.push(` artifact: (could not read)`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
lines.push(` artifact: ${artifactPath} (MISSING)`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return lines.join('\n');
|
|
66
|
+
}
|
|
67
|
+
function statusLabel(status, zh) {
|
|
68
|
+
const labels = {
|
|
69
|
+
pending_review: { zh: '待审核', en: 'pending_review' },
|
|
70
|
+
approved_for_training: { zh: '已批准', en: 'approved_for_training' },
|
|
71
|
+
rejected: { zh: '已拒绝', en: 'rejected' },
|
|
72
|
+
superseded: { zh: '已替代', en: 'superseded' },
|
|
73
|
+
};
|
|
74
|
+
return labels[status][zh ? 'zh' : 'en'];
|
|
75
|
+
}
|
|
76
|
+
export function handleNocturnalReviewCommand(ctx) {
|
|
77
|
+
const workspaceDir = ctx.config?.workspaceDir || process.cwd();
|
|
78
|
+
const zh = isZh(ctx);
|
|
79
|
+
const args = (ctx.args || '').trim();
|
|
80
|
+
const parts = args.split(/\s+/).filter(Boolean);
|
|
81
|
+
const [action = 'list'] = parts;
|
|
82
|
+
try {
|
|
83
|
+
if (action === 'list') {
|
|
84
|
+
const pending = listDatasetRecords(workspaceDir, { reviewStatus: 'pending_review' });
|
|
85
|
+
const all = listDatasetRecords(workspaceDir);
|
|
86
|
+
if (pending.length === 0) {
|
|
87
|
+
return {
|
|
88
|
+
text: zh
|
|
89
|
+
? '没有待审核的 nocturnal 样本。'
|
|
90
|
+
: 'No pending nocturnal samples for review.',
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const lines = pending.map((r) => {
|
|
94
|
+
const label = statusLabel(r.reviewStatus, zh);
|
|
95
|
+
return `[${label}] ${r.sampleFingerprint.substring(0, 16)}... | ${r.principleId} | ${r.targetModelFamily ?? '(no family)'}`;
|
|
96
|
+
});
|
|
97
|
+
return {
|
|
98
|
+
text: zh
|
|
99
|
+
? `待审核样本 (${pending.length}/${all.length}):\n${lines.join('\n')}\n\n使用 /pd-nocturnal-review show <fingerprint> 查看详情。`
|
|
100
|
+
: `Pending review samples (${pending.length}/${all.length}):\n${lines.join('\n')}\n\nUse /pd-nocturnal-review show <fingerprint> for details.`,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (action === 'show') {
|
|
104
|
+
const fingerprint = parts[1];
|
|
105
|
+
if (!fingerprint) {
|
|
106
|
+
return {
|
|
107
|
+
text: zh
|
|
108
|
+
? '用法: /pd-nocturnal-review show <fingerprint>'
|
|
109
|
+
: 'Usage: /pd-nocturnal-review show <fingerprint>',
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const record = getDatasetRecord(workspaceDir, fingerprint);
|
|
113
|
+
if (!record) {
|
|
114
|
+
return {
|
|
115
|
+
text: zh
|
|
116
|
+
? `未找到样本: ${fingerprint}`
|
|
117
|
+
: `Sample not found: ${fingerprint}`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const details = formatRecord(record, true);
|
|
121
|
+
return {
|
|
122
|
+
text: zh
|
|
123
|
+
? `样本详情:\n${details}`
|
|
124
|
+
: `Sample details:\n${details}`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
if (action === 'approve') {
|
|
128
|
+
const fingerprint = parts[1];
|
|
129
|
+
const reason = parts.slice(2).join(' ') || (zh ? 'Approved by human reviewer' : 'Approved by human reviewer');
|
|
130
|
+
if (!fingerprint) {
|
|
131
|
+
return {
|
|
132
|
+
text: zh
|
|
133
|
+
? '用法: /pd-nocturnal-review approve <fingerprint> [reason]'
|
|
134
|
+
: 'Usage: /pd-nocturnal-review approve <fingerprint> [reason]',
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
const record = getDatasetRecord(workspaceDir, fingerprint);
|
|
138
|
+
if (!record) {
|
|
139
|
+
return {
|
|
140
|
+
text: zh
|
|
141
|
+
? `未找到样本: ${fingerprint}`
|
|
142
|
+
: `Sample not found: ${fingerprint}`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (record.reviewStatus === 'approved_for_training') {
|
|
146
|
+
return {
|
|
147
|
+
text: zh
|
|
148
|
+
? `样本已是 approved_for_training 状态。`
|
|
149
|
+
: `Sample is already approved_for_training.`,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
if (record.reviewStatus === 'rejected') {
|
|
153
|
+
return {
|
|
154
|
+
text: zh
|
|
155
|
+
? `样本已被 rejected,需要先重置为 pending_review 才能重新审核。`
|
|
156
|
+
: `Sample is rejected. Reset to pending_review first before re-reviewing.`,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (record.reviewStatus === 'superseded') {
|
|
160
|
+
return {
|
|
161
|
+
text: zh
|
|
162
|
+
? `样本已被 superseded,无法更改。`
|
|
163
|
+
: `Sample is superseded and cannot be changed.`,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
const updated = updateReviewStatus(workspaceDir, fingerprint, 'approved_for_training', reason);
|
|
167
|
+
return {
|
|
168
|
+
text: zh
|
|
169
|
+
? `样本已批准用于训练:\n fingerprint: ${updated.sampleFingerprint.substring(0, 16)}...\n principleId: ${updated.principleId}\n targetModelFamily: ${updated.targetModelFamily ?? '(none)'}\n reason: ${updated.reviewReason}`
|
|
170
|
+
: `Sample approved for training:\n fingerprint: ${updated.sampleFingerprint.substring(0, 16)}...\n principleId: ${updated.principleId}\n targetModelFamily: ${updated.targetModelFamily ?? '(none)'}\n reason: ${updated.reviewReason}`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (action === 'reject') {
|
|
174
|
+
const fingerprint = parts[1];
|
|
175
|
+
const reason = parts.slice(2).join(' ') || (zh ? 'Rejected by human reviewer' : 'Rejected by human reviewer');
|
|
176
|
+
if (!fingerprint) {
|
|
177
|
+
return {
|
|
178
|
+
text: zh
|
|
179
|
+
? '用法: /pd-nocturnal-review reject <fingerprint> [reason]'
|
|
180
|
+
: 'Usage: /pd-nocturnal-review reject <fingerprint> [reason]',
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
const record = getDatasetRecord(workspaceDir, fingerprint);
|
|
184
|
+
if (!record) {
|
|
185
|
+
return {
|
|
186
|
+
text: zh
|
|
187
|
+
? `未找到样本: ${fingerprint}`
|
|
188
|
+
: `Sample not found: ${fingerprint}`,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
if (record.reviewStatus === 'rejected') {
|
|
192
|
+
return {
|
|
193
|
+
text: zh
|
|
194
|
+
? `样本已是 rejected 状态。`
|
|
195
|
+
: `Sample is already rejected.`,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
if (record.reviewStatus === 'superseded') {
|
|
199
|
+
return {
|
|
200
|
+
text: zh
|
|
201
|
+
? `样本已被 superseded,无法更改。`
|
|
202
|
+
: `Sample is superseded and cannot be changed.`,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const updated = updateReviewStatus(workspaceDir, fingerprint, 'rejected', reason);
|
|
206
|
+
return {
|
|
207
|
+
text: zh
|
|
208
|
+
? `样本已拒绝:\n fingerprint: ${updated.sampleFingerprint.substring(0, 16)}...\n reason: ${updated.reviewReason}`
|
|
209
|
+
: `Sample rejected:\n fingerprint: ${updated.sampleFingerprint.substring(0, 16)}...\n reason: ${updated.reviewReason}`,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (action === 'set-family') {
|
|
213
|
+
const fingerprint = parts[1];
|
|
214
|
+
const family = parts[2];
|
|
215
|
+
if (!fingerprint || !family) {
|
|
216
|
+
return {
|
|
217
|
+
text: zh
|
|
218
|
+
? '用法: /pd-nocturnal-review set-family <fingerprint> <model-family>'
|
|
219
|
+
: 'Usage: /pd-nocturnal-review set-family <fingerprint> <model-family>',
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
const record = getDatasetRecord(workspaceDir, fingerprint);
|
|
223
|
+
if (!record) {
|
|
224
|
+
return {
|
|
225
|
+
text: zh
|
|
226
|
+
? `未找到样本: ${fingerprint}`
|
|
227
|
+
: `Sample not found: ${fingerprint}`,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
if (record.reviewStatus === 'superseded') {
|
|
231
|
+
return {
|
|
232
|
+
text: zh
|
|
233
|
+
? `样本已被 superseded,无法修改模型家族。`
|
|
234
|
+
: `Sample is superseded and cannot be modified.`,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
const updated = updateTargetModelFamily(workspaceDir, fingerprint, family);
|
|
238
|
+
return {
|
|
239
|
+
text: zh
|
|
240
|
+
? `已设置目标模型家族:\n fingerprint: ${updated.sampleFingerprint.substring(0, 16)}...\n targetModelFamily: ${updated.targetModelFamily}`
|
|
241
|
+
: `Target model family set:\n fingerprint: ${updated.sampleFingerprint.substring(0, 16)}...\n targetModelFamily: ${updated.targetModelFamily}`,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
if (action === 'stats') {
|
|
245
|
+
const stats = getDatasetStats(workspaceDir);
|
|
246
|
+
return {
|
|
247
|
+
text: zh
|
|
248
|
+
? `Nocturnal Dataset 统计:\n 总样本数: ${stats.total}\n 待审核: ${stats.pendingReview}\n 已批准训练: ${stats.approvedForTraining}\n 已拒绝: ${stats.rejected}\n 已替代: ${stats.superseded}\n 可导出 (按家族): ${Object.entries(stats.exportReadyByFamily).map(([f, c]) => `${f}: ${c}`).join(', ') || '无'}`
|
|
249
|
+
: `Nocturnal Dataset Stats:\n Total: ${stats.total}\n Pending review: ${stats.pendingReview}\n Approved for training: ${stats.approvedForTraining}\n Rejected: ${stats.rejected}\n Superseded: ${stats.superseded}\n Export-ready (by family): ${Object.entries(stats.exportReadyByFamily).map(([f, c]) => `${f}: ${c}`).join(', ') || 'none'}`,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
text: zh
|
|
254
|
+
? `未知操作: ${action}\n用法:\n /pd-nocturnal-review list\n /pd-nocturnal-review show <fingerprint>\n /pd-nocturnal-review approve <fingerprint> [reason]\n /pd-nocturnal-review reject <fingerprint> [reason]\n /pd-nocturnal-review set-family <fingerprint> <model-family>\n /pd-nocturnal-review stats`
|
|
255
|
+
: `Unknown action: ${action}\nUsage:\n /pd-nocturnal-review list\n /pd-nocturnal-review show <fingerprint>\n /pd-nocturnal-review approve <fingerprint> [reason]\n /pd-nocturnal-review reject <fingerprint> [reason]\n /pd-nocturnal-review set-family <fingerprint> <model-family>\n /pd-nocturnal-review stats`,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
return {
|
|
260
|
+
text: zh
|
|
261
|
+
? `审核操作失败: ${String(err)}`
|
|
262
|
+
: `Review operation failed: ${String(err)}`,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nocturnal Rollout Command Handler
|
|
3
|
+
* =================================
|
|
4
|
+
*
|
|
5
|
+
* Plugin command handler for nocturnal rollout and promotion operations.
|
|
6
|
+
* Provides commands for:
|
|
7
|
+
* - evaluate-promotion: Evaluate if checkpoint passes promotion gate
|
|
8
|
+
* - advance-promotion: Advance checkpoint promotion state
|
|
9
|
+
* - bind: Bind checkpoint to worker profile
|
|
10
|
+
* - enable-routing: Enable routing for a profile
|
|
11
|
+
* - disable-routing: Disable routing for a profile
|
|
12
|
+
* - rollback: Rollback deployment to previous checkpoint
|
|
13
|
+
* - status: Show deployment status for profiles
|
|
14
|
+
* - show-promotion: Show promotion record for a checkpoint
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* /nocturnal-rollout evaluate-promotion <checkpointId> [--profile=<profile>]
|
|
18
|
+
* /nocturnal-rollout advance-promotion <checkpointId> [--profile=<profile>] [--review]
|
|
19
|
+
* /nocturnal-rollout bind <checkpointId> --profile=<profile>
|
|
20
|
+
* /nocturnal-rollout enable-routing <profile>
|
|
21
|
+
* /nocturnal-rollout disable-routing <profile>
|
|
22
|
+
* /nocturnal-rollout rollback <profile>
|
|
23
|
+
* /nocturnal-rollout status [--profile=<profile>]
|
|
24
|
+
* /nocturnal-rollout show-promotion <checkpointId>
|
|
25
|
+
*/
|
|
26
|
+
import type { PluginCommandContext, PluginCommandResult } from '../openclaw-sdk.js';
|
|
27
|
+
export declare function handleNocturnalRolloutCommand(ctx: PluginCommandContext): PluginCommandResult;
|