principles-disciple 1.66.0 → 1.68.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.
@@ -44,10 +44,6 @@
44
44
  * `success_base` (默认: 1): 成功干完一个小任务,加 1 分。
45
45
  * `streak_bonus` (默认: 5): 连续 5 次成功(连杀奖励),额外加 5 分。
46
46
 
47
- ### 5. 元认知深度反思 (`deep_reflection`)
48
- * `enabled`: 是否允许 AI 停下来深思熟虑。
49
- * `auto_trigger_conditions.error_rate_threshold` (默认: 0.3): 当近期操作的错误率超过 30% 时,强制让 AI 停下手头的活,调用 `deep_reflect` 工具分析自己是不是大方向搞错了。
50
-
51
47
  ---
52
48
 
53
49
  ### ⚠️ 高风险操作警告!
package/README.md CHANGED
@@ -44,15 +44,6 @@ All commands support **short aliases** for easier input:
44
44
  | `/nocturnal-rollout` | Nocturnal rollout and promotion |
45
45
  | `/pd-workflow-debug` | Debug workflow state |
46
46
 
47
- ### Tools
48
-
49
- **`deep_reflect`** - Executes deep meta-cognitive reflection to analyze potential risks, logical gaps, or architectural improvements in the current task.
50
-
51
- Parameters:
52
- - `context` (required): Task context, code snippet, or current difficulty
53
- - `depth` (optional): Reflection depth 1-3 (default: 2)
54
- - `model_id` (optional): Force specific thinking model
55
-
56
47
  ### Configuration
57
48
 
58
49
  The plugin accepts the following configuration options:
@@ -62,8 +53,6 @@ The plugin accepts the following configuration options:
62
53
  | `language` | `zh` | Interaction language (`en` or `zh`) |
63
54
  | `auditLevel` | `medium` | Security guardrail level (`low`, `medium`, `high`) |
64
55
  | `riskPaths` | `[]` | High-risk directories requiring explicit authorization |
65
- | `deep_reflection.enabled` | `true` | Enable AI deep reflection |
66
- | `deep_reflection.mode` | `auto` | Reflection trigger mode (`auto` or `forced`) |
67
56
 
68
57
  ## Part of the principles monorepo
69
58
 
@@ -2,9 +2,10 @@
2
2
  "id": "principles-disciple",
3
3
  "name": "Principles Disciple",
4
4
  "description": "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
5
- "version": "1.66.0",
5
+ "version": "1.68.0",
6
6
  "skills": [
7
- "./skills"
7
+ "templates/langs/en/skills",
8
+ "templates/langs/zh/skills"
8
9
  ],
9
10
  "configSchema": {
10
11
  "type": "object",
@@ -37,27 +38,6 @@
37
38
  "default": [],
38
39
  "description": "自定义高危目录(例如 .git/, prod_db/)。AI 试图修改这些目录前,将被强制拦截并要求出具安全计划。"
39
40
  },
40
- "deep_reflection": {
41
- "type": "object",
42
- "additionalProperties": false,
43
- "description": "当 AI 遇到复杂问题或连续报错时,是否允许它停下来进行深度自我反思?",
44
- "properties": {
45
- "enabled": {
46
- "type": "boolean",
47
- "default": true,
48
- "description": "开启 AI 深度反思功能"
49
- },
50
- "mode": {
51
- "type": "string",
52
- "enum": [
53
- "auto",
54
- "forced"
55
- ],
56
- "default": "auto",
57
- "description": "auto: 遇到困难自动触发; forced: 每次回答前都强制反思 (极耗时间,不推荐)"
58
- }
59
- }
60
- }
61
41
  }
62
42
  },
63
43
  "uiHints": {
@@ -70,9 +50,6 @@
70
50
  },
71
51
  "riskPaths": {
72
52
  "label": "⚠️ 绝对高危目录 (空表示不设限)"
73
- },
74
- "deep_reflection": {
75
- "label": "💡 AI 深度反思功能"
76
53
  }
77
54
  },
78
55
  "buildFingerprint": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "principles-disciple",
3
- "version": "1.66.0",
3
+ "version": "1.68.0",
4
4
  "description": "Native OpenClaw plugin for Principles Disciple",
5
5
  "type": "module",
6
6
  "main": "./dist/bundle.js",
@@ -400,6 +400,7 @@ function verifyBundleContents() {
400
400
  { name: 'checkPainFlag', reason: 'pain flag detection' },
401
401
  { name: 'processEvolutionQueue', reason: 'queue processing' },
402
402
  { name: 'acquireQueueLock', reason: 'queue lock for pd-reflect and worker' },
403
+ { name: 'write_pain_flag', reason: 'pain signal recording tool' },
403
404
  ];
404
405
 
405
406
  const missing = [];
@@ -523,6 +524,26 @@ function verifyInstalledFingerprint() {
523
524
  console.log('✅ Installed fingerprint verified');
524
525
  }
525
526
 
527
+ /**
528
+ * Update the plugin version in openclaw.json after successful sync.
529
+ * This ensures the recorded version always matches the installed version.
530
+ */
531
+ function updateInstalledPluginVersion(version) {
532
+ const configPath = join(OPENCLAW_DIR, 'openclaw.json');
533
+ try {
534
+ const raw = readFileSync(configPath, 'utf-8');
535
+ const config = JSON.parse(raw);
536
+ if (config?.plugins?.installs?.['principles-disciple']) {
537
+ config.plugins.installs['principles-disciple'].version = version;
538
+ config.plugins.installs['principles-disciple'].installedAt = new Date().toISOString();
539
+ writeFileAtomic(configPath, JSON.stringify(config, null, 2) + '\n');
540
+ console.log(`✅ openclaw.json updated: version=${version}`);
541
+ }
542
+ } catch (err) {
543
+ console.warn(`⚠️ Could not update openclaw.json: ${err.message}`);
544
+ }
545
+ }
546
+
526
547
  /**
527
548
  * Remove existing installation directory with Windows-friendly retry logic.
528
549
  */
@@ -583,16 +604,37 @@ function ensureInstallDir() {
583
604
  }
584
605
 
585
606
  /**
586
- * Sync skills.
607
+ * Sync skills directories based on the skills field in openclaw.plugin.json.
608
+ * Reads the manifest to find declared skill paths, resolves them relative to
609
+ * source root, then copies each to the install target.
587
610
  */
588
- function syncSkills(lang) {
589
- const skillsSource = join(SOURCE_DIR, 'templates', 'langs', lang, 'skills');
590
- const skillsTarget = join(INSTALL_DIR, 'skills');
591
- if (!existsSync(skillsSource)) return false;
592
- if (existsSync(skillsTarget)) rmSync(skillsTarget, { recursive: true, force: true });
593
- cpSync(skillsSource, skillsTarget, { recursive: true });
594
- console.log(` 📄 skills (from ${lang})`);
595
- return true;
611
+ function syncSkillDirs() {
612
+ const manifestPath = join(SOURCE_DIR, 'openclaw.plugin.json');
613
+ if (!existsSync(manifestPath)) return;
614
+
615
+ let skillsPaths;
616
+ try {
617
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
618
+ skillsPaths = manifest.skills;
619
+ } catch {
620
+ return;
621
+ }
622
+
623
+ if (!skillsPaths || !Array.isArray(skillsPaths)) return;
624
+
625
+ for (const sp of skillsPaths) {
626
+ if (typeof sp !== 'string') continue;
627
+ const source = join(SOURCE_DIR, sp);
628
+ const name = sp.split('/').pop();
629
+ const target = join(INSTALL_DIR, 'skills', name);
630
+ if (!existsSync(source)) {
631
+ console.warn(` ⚠️ skills path not found: ${sp}`);
632
+ continue;
633
+ }
634
+ if (existsSync(target)) rmSync(target, { recursive: true, force: true });
635
+ cpSync(source, target, { recursive: true });
636
+ console.log(` 📄 skills/${name} (from ${sp})`);
637
+ }
596
638
  }
597
639
 
598
640
  /**
@@ -701,6 +743,23 @@ function isWindows() {
701
743
  return process.platform === 'win32';
702
744
  }
703
745
 
746
+ /**
747
+ * Check if a process is running by PID.
748
+ */
749
+ function isProcessRunning(pid) {
750
+ try {
751
+ if (isWindows()) {
752
+ execSync(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`, { stdio: 'ignore' });
753
+ return true;
754
+ } else {
755
+ process.kill(pid, 0);
756
+ return true;
757
+ }
758
+ } catch {
759
+ return false;
760
+ }
761
+ }
762
+
704
763
  /**
705
764
  * Get temporary directory path (cross-platform).
706
765
  */
@@ -751,32 +810,57 @@ function restartGatewayWindows() {
751
810
  }
752
811
  } catch { /* no existing processes */ }
753
812
 
813
+ // Clean stale lock files — prevents ghost gateway false positives
814
+ try {
815
+ const lockDir = join(getTempDir(), 'openclaw');
816
+ if (existsSync(lockDir)) {
817
+ const files = readdirSync(lockDir).filter(f => f.startsWith('gateway.') && f.endsWith('.lock'));
818
+ for (const file of files) {
819
+ const lockPath = join(lockDir, file);
820
+ try {
821
+ const content = readFileSync(lockPath, 'utf-8');
822
+ const pid = parseInt(content.trim());
823
+ // Only remove if PID is not running
824
+ if (!pid || !isProcessRunning(pid)) {
825
+ rmSync(lockPath, { force: true });
826
+ console.log(` Removed stale lock: ${file}`);
827
+ }
828
+ } catch { /* ignore */ }
829
+ }
830
+ }
831
+ } catch { /* ignore lock cleanup failures */ }
832
+
754
833
  // Trigger via schtasks — reliable, avoids CLI busy-port misdetection
755
834
  console.log(' Starting gateway via scheduled task...');
756
835
  execSync('schtasks /Run /TN "OpenClaw Gateway"', { stdio: 'inherit' });
757
836
 
758
- // Wait for gateway to start and PD plugin to register
759
- const deadline = Date.now() + 20000;
837
+ // Wait for gateway to be listening on port (同步等待,不异步)
838
+ const port = 18789;
839
+ const deadline = Date.now() + 30000;
760
840
  const pollInterval = 1000;
841
+ let gatewayListening = false;
761
842
 
762
- const waitForRegistration = () => {
763
- if (Date.now() > deadline) {
764
- console.warn('⚠️ Gateway started but PD registration not confirmed after 20s.');
765
- console.log(' Check logs at: ' + logPath);
766
- return;
767
- }
843
+ while (Date.now() < deadline) {
768
844
  try {
769
- if (existsSync(logPath)) {
770
- const logs = readFileSync(logPath, 'utf-8');
771
- if (logs.includes('Principles Disciple Plugin registered')) {
772
- console.log('✅ SUCCESS: Principles Disciple plugin registered successfully!');
773
- return;
774
- }
845
+ const result = execSync(
846
+ `powershell -NoProfile -Command "Get-NetTCPConnection -LocalPort ${port} -State Listen -ErrorAction SilentlyContinue | Measure-Object -Line).Count"`,
847
+ { encoding: 'utf-8', timeout: 5000 }
848
+ ).trim();
849
+ if (parseInt(result) > 0) {
850
+ gatewayListening = true;
851
+ break;
775
852
  }
776
- } catch { /* ignore */ }
777
- setTimeout(waitForRegistration, pollInterval);
778
- };
779
- waitForRegistration();
853
+ } catch { /* port not listening yet */ }
854
+ execSync('timeout /t 1 /nobreak > nul', { shell: true, stdio: 'ignore' });
855
+ }
856
+
857
+ if (!gatewayListening) {
858
+ console.error('\n❌ Gateway did not start on port 18789 within 30s.');
859
+ console.error(' Please restart manually: openclaw gateway start');
860
+ process.exit(1);
861
+ }
862
+
863
+ console.log(' ✅ Gateway is listening on port 18789');
780
864
 
781
865
  } catch (error) {
782
866
  console.error(`\n❌ Gateway restart failed: ${error.message}`);
@@ -890,7 +974,7 @@ function main() {
890
974
 
891
975
  console.log('\n📦 Syncing files to OpenClaw...');
892
976
  for (const item of SYNC_ITEMS) syncItem(item);
893
- syncSkills(args.lang);
977
+ syncSkillDirs();
894
978
 
895
979
  injectLocalWorkspacePackages();
896
980
  installTargetDependencies();
@@ -948,6 +1032,7 @@ function main() {
948
1032
  }
949
1033
 
950
1034
  verifyInstalledFingerprint();
1035
+ updateInstalledPluginVersion(sourceVersion);
951
1036
  if (args.dev || args.restart) cleanStaleBackups();
952
1037
 
953
1038
  console.log('\n╔════════════════════════════════════════════════════════════╗');
@@ -74,7 +74,6 @@ function showStatus(workspaceDir: string, isZh: boolean): string {
74
74
  |------|------|------|
75
75
  | 核心原则 | ✅ 始终开启 | 不可关闭 |
76
76
  | 思维模型 | ${config.thinkingOs ? '✅ 开启' : '❌ 关闭'} | /pd-context thinking on/off |
77
- | 反思日志 | ${config.reflectionLog ? '✅ 开启' : '❌ 关闭'} | /pd-context reflection on/off |
78
77
  | 项目上下文 | ${formatProjectFocus(config.projectFocus, isZh)} | /pd-context focus full/summary/off |
79
78
 
80
79
  💡 输入 \`/pd-context help\` 查看更多选项
@@ -87,7 +86,6 @@ function showStatus(workspaceDir: string, isZh: boolean): string {
87
86
  |---------|--------|---------|
88
87
  | Core Principles | ✅ Always ON | Not configurable |
89
88
  | Thinking OS | ${config.thinkingOs ? '✅ ON' : '❌ OFF'} | /pd-context thinking on/off |
90
- | Reflection Log | ${config.reflectionLog ? '✅ ON' : '❌ OFF'} | /pd-context reflection on/off |
91
89
  | Project Context | ${formatProjectFocus(config.projectFocus, isZh)} | /pd-context focus full/summary/off |
92
90
 
93
91
  💡 Type \`/pd-context help\` for more options
@@ -102,26 +100,26 @@ function showStatus(workspaceDir: string, isZh: boolean): string {
102
100
 
103
101
  function toggleSetting(
104
102
  workspaceDir: string,
105
- key: 'thinkingOs' | 'reflectionLog',
103
+ key: 'thinkingOs',
106
104
  value: string,
107
105
  isZh: boolean
108
106
  ): string {
109
107
  const config = loadContextInjectionConfig(workspaceDir);
110
108
  const oldValue = config[key];
111
-
109
+
112
110
  if (value === 'on') {
113
111
  config[key] = true;
114
112
  } else if (value === 'off') {
115
113
  config[key] = false;
116
114
  } else {
117
- return isZh
115
+ return isZh
118
116
  ? `❌ 无效值: "${value}"。使用 "on" 或 "off"。`
119
117
  : `❌ Invalid value: "${value}". Use "on" or "off".`;
120
118
  }
121
-
119
+
122
120
  const newValue = config[key];
123
- const keyName = isZh
124
- ? { thinkingOs: '思维模型', reflectionLog: '反思日志' }[key]
121
+ const keyName = isZh
122
+ ? { thinkingOs: '思维模型' }[key]
125
123
  : key;
126
124
 
127
125
  // No change needed
@@ -222,7 +220,6 @@ function applyPreset(
222
220
  case 'minimal':
223
221
  config = {
224
222
  thinkingOs: false,
225
- reflectionLog: false,
226
223
  projectFocus: 'off',
227
224
  evolutionContext: { ...defaultContextConfig.evolutionContext }
228
225
  };
@@ -230,7 +227,6 @@ function applyPreset(
230
227
  case 'standard':
231
228
  config = {
232
229
  thinkingOs: true,
233
- reflectionLog: false,
234
230
  projectFocus: 'off',
235
231
  evolutionContext: { ...defaultContextConfig.evolutionContext }
236
232
  };
@@ -238,7 +234,6 @@ function applyPreset(
238
234
  case 'full':
239
235
  config = {
240
236
  thinkingOs: true,
241
- reflectionLog: true,
242
237
  projectFocus: 'summary',
243
238
  evolutionContext: { ...defaultContextConfig.evolutionContext }
244
239
  };
@@ -328,9 +323,6 @@ export function handleContextCommand(ctx: PluginCommandContext): PluginCommandRe
328
323
  case 'thinking':
329
324
  result = toggleSetting(workspaceDir, 'thinkingOs', value, isZh);
330
325
  break;
331
- case 'reflection':
332
- result = toggleSetting(workspaceDir, 'reflectionLog', value, isZh);
333
- break;
334
326
  case 'focus':
335
327
  result = setProjectFocus(workspaceDir, value, isZh);
336
328
  break;
@@ -100,6 +100,17 @@ function buildEnglishOutput(
100
100
  `- generatedAt: ${summary.metadata.generatedAt}`,
101
101
  ];
102
102
 
103
+ // E: YAML-driven Workflow Funnels (Phase 6)
104
+ if (summary.workflowFunnels && summary.workflowFunnels.length > 0) {
105
+ lines.push('');
106
+ for (const funnel of summary.workflowFunnels) {
107
+ lines.push(`Workflow Funnel: ${funnel.funnelLabel}`);
108
+ for (const stage of funnel.stages) {
109
+ lines.push(` - ${stage.label}: ${stage.count}`);
110
+ }
111
+ }
112
+ }
113
+
103
114
  if (warnings.length > 0) {
104
115
  lines.push('', 'Warnings');
105
116
  for (const warning of warnings) {
@@ -110,8 +121,8 @@ function buildEnglishOutput(
110
121
  return lines.join('\n');
111
122
  }
112
123
 
113
-
114
-
124
+
125
+
115
126
  function buildChineseOutput(
116
127
  workspaceDir: string,
117
128
  sessionId: string | null,
@@ -161,6 +172,17 @@ function buildChineseOutput(
161
172
  `- 生成时间: ${summary.metadata.generatedAt}`,
162
173
  ];
163
174
 
175
+ // E: YAML驱动的Workflow Funnels (Phase 6)
176
+ if (summary.workflowFunnels && summary.workflowFunnels.length > 0) {
177
+ lines.push('');
178
+ for (const funnel of summary.workflowFunnels) {
179
+ lines.push(`Workflow 漏斗: ${funnel.funnelLabel}`);
180
+ for (const stage of funnel.stages) {
181
+ lines.push(` - ${stage.label}: ${stage.count}`);
182
+ }
183
+ }
184
+ }
185
+
164
186
  if (warnings.length > 0) {
165
187
  lines.push('', '警告');
166
188
  for (const warning of warnings) {
@@ -183,7 +205,11 @@ export function handleEvolutionStatusCommand(ctx: PluginCommandContext): { text:
183
205
  const loader = new WorkflowFunnelLoader(stateDir);
184
206
  loader.watch();
185
207
  try {
186
- const summary = RuntimeSummaryService.getSummary(workspaceDir, { sessionId, loaderWarnings: loader.getWarnings() });
208
+ const summary = RuntimeSummaryService.getSummary(workspaceDir, {
209
+ sessionId,
210
+ loaderWarnings: loader.getWarnings(),
211
+ funnels: loader.getAllFunnels(),
212
+ });
187
213
  const recommendations = WorkspaceContext.fromHookContext({ workspaceDir })
188
214
  .principleLifecycle
189
215
  .recomputeAll()
@@ -156,8 +156,7 @@ export function handlePainCommand(ctx: PluginCommandContext): PluginCommandResul
156
156
  suggestionText = `
157
157
  💡 **建议 (系统检测到您当前遇到较大阻力)**:
158
158
  1. 执行 \`/pd-status reset\` 清零疲劳值。
159
- 2. AI 调用 \`deep_reflect\` 工具进行深度反思。
160
- 3. 如果当前上下文太乱,考虑使用 \`/clear\` 开启新会话。`;
159
+ 2. 如果当前上下文太乱,考虑使用 \`/clear\` 开启新会话。`;
161
160
  }
162
161
  else if (gfi > 50) healthLabel = '遇到阻力 🟡';
163
162
  else if (gfi > 20) healthLabel = '轻微受挫 🟢';
@@ -168,8 +167,8 @@ export function handlePainCommand(ctx: PluginCommandContext): PluginCommandResul
168
167
  suggestionText = `
169
168
  💡 **Suggestion (High friction detected)**:
170
169
  1. Run \`/pd-status reset\` to clear friction.
171
- 2. Ask the AI to use the \`deep_reflect\` tool.
172
- 4. Consider starting a new session with \`/clear\`.`;
170
+ 2. Ask the AI to reflect deeply before continuing.
171
+ 3. Consider starting a new session with \`/clear\`.`;
173
172
  }
174
173
  else if (gfi > 50) healthLabel = 'High Friction 🟡';
175
174
  else if (gfi > 20) healthLabel = 'Minor Issues 🟢';
@@ -115,8 +115,6 @@ export const MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
115
115
 
116
116
  // ── Workflow TTL Settings ───────────────────────────────────────────────────────
117
117
 
118
- /** Deep-reflect workflow TTL (10 minutes) */
119
- export const DEEP_REFLECT_TTL_MS = 10 * ONE_MINUTE_MS;
120
118
 
121
119
  // ── Time Window Constants ───────────────────────────────────────────────────────
122
120
 
@@ -6,7 +6,6 @@ export const READ_ONLY_TOOL_NAMES = [
6
6
  'resolve-library-id', 'get-library-docs',
7
7
  'memory_recall', 'save_memory', 'todo_read', 'todo_write',
8
8
  'ask_user', 'ask_user_question',
9
- 'deep_reflect',
10
9
  'pd-status', 'report',
11
10
  ] as const;
12
11
 
@@ -3,21 +3,6 @@ import * as fs from 'fs';
3
3
  import * as path from 'path';
4
4
  import { atomicWriteFileSync } from '../utils/io.js';
5
5
 
6
- export interface DeepReflectionSettings {
7
- enabled: boolean;
8
- mode: 'auto' | 'forced' | 'disabled';
9
- force_checkpoint?: boolean;
10
- checkpoint_message?: string;
11
- auto_trigger_conditions?: {
12
- min_tool_calls?: number;
13
- error_rate_threshold?: number;
14
- complexity_keywords?: string[];
15
- };
16
- default_model?: string;
17
- default_depth?: number;
18
- timeout_ms?: number;
19
- modelsDir?: string;
20
- }
21
6
 
22
7
  export interface GfiGateSettings {
23
8
  enabled: boolean;
@@ -83,7 +68,6 @@ export interface PainSettings {
83
68
  initial_delay_ms: number;
84
69
  task_timeout_ms: number;
85
70
  };
86
- deep_reflection?: DeepReflectionSettings;
87
71
  empathy_engine?: {
88
72
  enabled?: boolean;
89
73
  dedupe_window_ms?: number;
@@ -159,20 +143,6 @@ export const DEFAULT_SETTINGS: PainSettings = {
159
143
  initial_delay_ms: 5000,
160
144
  task_timeout_ms: 60 * 60 * 1000 // 1 hour, matching evolution-worker.ts default
161
145
  },
162
- deep_reflection: {
163
- enabled: true,
164
- mode: 'auto',
165
- force_checkpoint: true,
166
- checkpoint_message: 'Before responding, quick self-check: 1. Task complexity (simple/medium/complex) 2. Information sufficiency (sufficient/need more) 3. If complex or insufficient info, call deep_reflect tool',
167
- auto_trigger_conditions: {
168
- min_tool_calls: 5,
169
- error_rate_threshold: 0.3,
170
- complexity_keywords: ['refactor', 'architecture', 'design', 'optimize', 'security', 'critical']
171
- },
172
- default_model: 'T-01',
173
- default_depth: 2,
174
- timeout_ms: 60000
175
- },
176
146
  empathy_engine: {
177
147
  enabled: true,
178
148
  dedupe_window_ms: 60000,
@@ -16,7 +16,6 @@ import type {
16
16
  GateBypassEventData,
17
17
  PlanApprovalEventData,
18
18
  EvolutionTaskEventData,
19
- DeepReflectionEventData,
20
19
  EmpathyRollbackEventData,
21
20
  // C: New event data types
22
21
  DiagnosisTaskEventData,
@@ -178,11 +177,6 @@ export class EventLog {
178
177
  this.record('evolution_task', 'completed', undefined, data);
179
178
  }
180
179
 
181
- recordDeepReflection(sessionId: string | undefined, data: DeepReflectionEventData): void {
182
- const category = data.passed ? 'passed' : data.timeout ? 'failure' : 'completed';
183
- this.record('deep_reflection', category, sessionId, data);
184
- }
185
-
186
180
  recordEmpathyRollback(sessionId: string | undefined, data: EmpathyRollbackEventData): void {
187
181
  this.record('empathy_rollback', 'rolled_back', sessionId, data);
188
182
  }
@@ -435,7 +435,7 @@ export async function handleBeforePromptBuild(
435
435
  const contextConfig = loadContextInjectionConfig(workspaceDir);
436
436
 
437
437
  // Minimal mode: heartbeat and subagents skip most context to reduce tokens
438
- const isMinimalMode = trigger === "heartbeat" || sessionId?.includes(":subagent:") === true;
438
+ const isMinimalMode = trigger === "heartbeat" || trigger === "cron" || sessionId?.includes(":subagent:") === true;
439
439
 
440
440
  const session = sessionId ? getSession(sessionId) : undefined;
441
441
 
@@ -700,8 +700,8 @@ The empathy observer subagent handles pain detection independently.
700
700
  // }
701
701
  }
702
702
 
703
- // ──── 4. Heartbeat-specific checklist ────
704
- if (trigger === 'heartbeat') {
703
+ // ──── 4. Heartbeat-specific checklist (also fires for cron-triggered sessions) ────
704
+ if (trigger === 'heartbeat' || trigger === 'cron') {
705
705
  // ──── 4a. GFI Time-based Decay ────
706
706
  // Apply segmented exponential decay to GFI on each heartbeat
707
707
  if (sessionId) {
@@ -789,7 +789,6 @@ ${taskBlocks}${processingNote}
789
789
  - **STOP** aggressive file modifications.
790
790
  - **START** every response with a sincere, non-defensive apology.
791
791
  - **ACTION**: Explain why you failed, and propose a highly cautious recovery plan.
792
- - Use 'deep_reflect' to analyze the root cause before proceeding with code changes.
793
792
  `;
794
793
  } else if (currentGfi >= 40) {
795
794
  attitudeDirective = `
@@ -839,18 +838,6 @@ ${taskBlocks}${processingNote}
839
838
  }
840
839
  }
841
840
 
842
- // Reflection Log (configurable) - moved to appendSystemContext for WebUI UX
843
- let reflectionLogContent = '';
844
- if (contextConfig.reflectionLog) {
845
- const reflectionLogPath = wctx.resolve('REFLECTION_LOG');
846
- try {
847
- const cached = cachedReadFile(reflectionLogPath);
848
- if (cached) reflectionLogContent = cached.trim();
849
- } catch (e) {
850
- logger?.error(`[PD:Prompt] Failed to read REFLECTION_LOG: ${String(e)}`);
851
- }
852
- }
853
-
854
841
  // Project Context (configurable: full/summary/off) - moved to appendSystemContext for WebUI UX
855
842
  let projectContextContent = '';
856
843
  let workingMemoryContent = '';
@@ -988,17 +975,12 @@ ${empathySilenceConstraint}
988
975
  appendParts.push(workingMemoryContent);
989
976
  }
990
977
 
991
- // 2. Reflection Log
992
- if (reflectionLogContent) {
993
- appendParts.push(`<reflection_log>\n${reflectionLogContent}\n</reflection_log>`);
994
- }
995
-
996
- // 3. Thinking OS (configurable)
978
+ // 2. Thinking OS (configurable)
997
979
  if (thinkingOsContent) {
998
980
  appendParts.push(`<thinking_os>\n${thinkingOsContent}\n</thinking_os>`);
999
981
  }
1000
982
 
1001
- // 4. Evolution Loop principles (active/probation)
983
+ // 3. Evolution Loop principles (active/probation)
1002
984
  if (evolutionPrinciplesContent) {
1003
985
  appendParts.push(`<evolution_principles>\n${evolutionPrinciplesContent}\n</evolution_principles>`);
1004
986
  }
@@ -1163,22 +1145,8 @@ ${attitudeDirective}
1163
1145
  }
1164
1146
  }
1165
1147
 
1166
- // 2. Truncate reflection_log if still over limit
1148
+ // 2. Final check
1167
1149
  let newSize = prependSystemContext.length + prependContext.length + appendSystemContext.length;
1168
- if (newSize > MAX_SIZE && reflectionLogContent && appendSystemContext.includes('<reflection_log>')) {
1169
- const lines = reflectionLogContent.split('\n');
1170
- if (lines.length > 30) {
1171
- const truncated = lines.slice(0, 30).join('\n') + '\n...[truncated]';
1172
- appendSystemContext = appendSystemContext.replace(
1173
- `<reflection_log>\n${reflectionLogContent}\n</reflection_log>`,
1174
- `<reflection_log>\n${truncated}\n</reflection_log>`
1175
- );
1176
- truncationLog.push('reflection_log');
1177
- }
1178
- }
1179
-
1180
- // 3. Final check
1181
- newSize = prependSystemContext.length + prependContext.length + appendSystemContext.length;
1182
1150
  if (newSize > MAX_SIZE) {
1183
1151
  // NOTE: We still return the content even if over limit, as truncating more
1184
1152
  // could lose critical context like principles or evolution directives.
@@ -6,7 +6,6 @@ import { extractAgentIdFromSessionKey } from '../utils/session-key.js';
6
6
  import { recordEvolutionSuccess } from '../core/evolution-engine.js';
7
7
  import { WorkflowStore } from '../service/subagent-workflow/workflow-store.js';
8
8
  import { EmpathyObserverWorkflowManager } from '../service/subagent-workflow/empathy-observer-workflow-manager.js';
9
- import { DeepReflectWorkflowManager } from '../service/subagent-workflow/deep-reflect-workflow-manager.js';
10
9
  import type { WorkflowManager } from '../service/subagent-workflow/types.js';
11
10
 
12
11
  /**
@@ -35,12 +34,6 @@ function createWorkflowManagerForType(
35
34
  logger: loggerAdapter,
36
35
  subagent,
37
36
  });
38
- case 'deep-reflect':
39
- return new DeepReflectWorkflowManager({
40
- workspaceDir,
41
- logger: loggerAdapter,
42
- subagent,
43
- });
44
37
  default:
45
38
  return null;
46
39
  }