principles-disciple 1.72.0 → 1.74.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.
Files changed (319) hide show
  1. package/INSTALL.md +1 -3
  2. package/openclaw.plugin.json +10 -5
  3. package/package.json +17 -19
  4. package/scripts/acceptance-test.mjs +16 -73
  5. package/scripts/sync-plugin.mjs +382 -77
  6. package/src/commands/archive-impl.ts +2 -1
  7. package/src/commands/capabilities.ts +2 -2
  8. package/src/commands/context.ts +2 -2
  9. package/src/commands/disable-impl.ts +2 -1
  10. package/src/commands/evolution-status.ts +16 -16
  11. package/src/commands/export.ts +12 -67
  12. package/src/commands/pain.ts +91 -1
  13. package/src/commands/principle-rollback.ts +2 -1
  14. package/src/commands/promote-impl.ts +7 -43
  15. package/src/commands/rollback-impl.ts +2 -1
  16. package/src/commands/rollback.ts +2 -1
  17. package/src/commands/samples.ts +2 -1
  18. package/src/commands/thinking-os.ts +2 -1
  19. package/src/config/errors.ts +18 -2
  20. package/src/constants/diagnostician.ts +2 -2
  21. package/src/constants/tools.ts +2 -1
  22. package/src/core/__tests__/focus-history.test.ts +210 -0
  23. package/src/core/config.ts +1 -1
  24. package/src/core/correction-cue-learner.ts +2 -136
  25. package/src/core/correction-types.ts +16 -88
  26. package/src/core/dictionary.ts +19 -20
  27. package/src/core/empathy-keyword-matcher.ts +17 -289
  28. package/src/core/empathy-types.ts +18 -229
  29. package/src/core/event-log.ts +29 -132
  30. package/src/core/evolution-reducer.ts +21 -2
  31. package/src/core/evolution-types.ts +76 -464
  32. package/src/core/file-store.ts +80 -0
  33. package/src/core/focus-history.ts +228 -955
  34. package/src/core/local-worker-routing.ts +34 -314
  35. package/src/core/merge-gate-audit.ts +0 -195
  36. package/src/core/migration.ts +0 -1
  37. package/src/core/pain-diagnostic-gate.ts +154 -0
  38. package/src/core/pain-signal.ts +21 -138
  39. package/src/core/pain.ts +15 -88
  40. package/src/core/path-resolver.ts +0 -1
  41. package/src/core/paths.ts +0 -1
  42. package/src/core/pd-task-reconciler.ts +26 -115
  43. package/src/core/pd-task-service.ts +9 -9
  44. package/src/core/pd-task-types.ts +23 -127
  45. package/src/core/principle-compiler/__tests__/compiler-replay-gate.test.ts +174 -0
  46. package/src/core/principle-compiler/code-validator.ts +15 -42
  47. package/src/core/principle-compiler/compiler.ts +100 -15
  48. package/src/core/principle-compiler/index.ts +5 -2
  49. package/src/core/principle-compiler/template-generator.ts +4 -104
  50. package/src/core/principle-injection.ts +10 -202
  51. package/src/core/principle-internalization/filesystem-lifecycle-datasource.ts +42 -0
  52. package/src/core/principle-internalization/lifecycle-read-model.ts +39 -242
  53. package/src/core/principle-internalization/principle-lifecycle-service.ts +12 -10
  54. package/src/core/principle-tree-ledger-adapter.ts +145 -0
  55. package/src/core/principle-tree-ledger.ts +8 -6
  56. package/src/core/reflection/reflection-context.ts +14 -109
  57. package/src/core/replay-engine.ts +8 -500
  58. package/src/core/rule-host-helpers.ts +5 -35
  59. package/src/core/rule-host-types.ts +10 -82
  60. package/src/core/rule-host.ts +6 -63
  61. package/src/core/runtime-v2-prompt-activation-reader.ts +231 -0
  62. package/src/core/session-tracker.ts +87 -101
  63. package/src/core/shadow-observation-registry.ts +19 -48
  64. package/src/core/trajectory.ts +3 -1
  65. package/src/core/workflow-funnel-loader.ts +62 -68
  66. package/src/core/workspace-context.ts +46 -0
  67. package/src/core/workspace-dir-service.ts +1 -1
  68. package/src/core/workspace-dir-validation.ts +18 -9
  69. package/src/hooks/AGENTS.md +1 -1
  70. package/src/hooks/gate-block-helper.ts +71 -64
  71. package/src/hooks/gate.ts +183 -31
  72. package/src/hooks/lifecycle.ts +30 -32
  73. package/src/hooks/llm.ts +60 -32
  74. package/src/hooks/pain.ts +297 -103
  75. package/src/hooks/prompt.ts +400 -440
  76. package/src/hooks/subagent.ts +2 -29
  77. package/src/i18n/commands.ts +2 -10
  78. package/src/index.ts +95 -85
  79. package/src/openclaw-sdk.ts +311 -0
  80. package/src/service/central-database.ts +8 -4
  81. package/src/service/evolution-queue-migration.ts +2 -1
  82. package/src/service/evolution-worker.ts +163 -1786
  83. package/src/service/internalization-trigger-adapter.ts +302 -0
  84. package/src/service/keyword-optimization-service.ts +4 -4
  85. package/src/service/monitoring-query-service.ts +1 -215
  86. package/src/service/queue-io.ts +60 -331
  87. package/src/service/runtime-summary-service.ts +59 -16
  88. package/src/service/subagent-workflow/index.ts +0 -41
  89. package/src/service/subagent-workflow/types.ts +9 -120
  90. package/src/service/subagent-workflow/workflow-store.ts +2 -119
  91. package/src/service/workflow-watchdog.ts +0 -43
  92. package/src/types/event-payload.ts +16 -74
  93. package/src/types/event-types.ts +38 -547
  94. package/src/types/hygiene-types.ts +7 -30
  95. package/src/types/principle-tree-schema.ts +20 -222
  96. package/src/types/queue.ts +15 -70
  97. package/src/types/runtime-summary.ts +5 -49
  98. package/src/utils/io.ts +8 -20
  99. package/src/utils/retry.ts +1 -1
  100. package/src/utils/shadow-fingerprint.ts +2 -2
  101. package/src/utils/workspace-resolver.ts +50 -0
  102. package/templates/langs/en/core/AGENTS.md +7 -7
  103. package/templates/langs/en/core/BOOT.md +1 -1
  104. package/templates/langs/en/core/HEARTBEAT.md +2 -2
  105. package/templates/langs/en/principles/THINKING_OS.md +3 -2
  106. package/templates/langs/en/skills/ai-sprint-orchestration/references/agent-registry.json +1 -72
  107. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +6 -6
  108. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +6 -6
  109. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +2 -12
  110. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +2 -12
  111. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/run.mjs +51 -15
  112. package/templates/langs/en/skills/evolve-task/SKILL.md +3 -3
  113. package/templates/langs/en/skills/pd-cli-operator/SKILL.md +67 -0
  114. package/templates/langs/en/skills/pd-diagnostician/SKILL.md +1 -1
  115. package/templates/langs/en/skills/pd-mentor/SKILL.md +2 -3
  116. package/templates/langs/en/skills/pd-pain-signal/SKILL.md +17 -39
  117. package/templates/langs/en/skills/pd-runtime-v2/SKILL.md +61 -0
  118. package/templates/langs/zh/core/AGENTS.md +7 -7
  119. package/templates/langs/zh/core/BOOT.md +1 -1
  120. package/templates/langs/zh/core/HEARTBEAT.md +2 -2
  121. package/templates/langs/zh/principles/THINKING_OS.md +3 -2
  122. package/templates/langs/zh/skills/ai-sprint-orchestration/references/agent-registry.json +1 -72
  123. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +6 -6
  124. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +6 -6
  125. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/nocturnal-trinity-quality-enhancement.json +8 -8
  126. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +2 -12
  127. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +2 -12
  128. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +51 -15
  129. package/templates/langs/zh/skills/ai-sprint-orchestration/test/run.test.mjs +21 -5
  130. package/templates/langs/zh/skills/evolve-task/SKILL.md +4 -4
  131. package/templates/langs/zh/skills/pd-cli-operator/SKILL.md +67 -0
  132. package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +1 -1
  133. package/templates/langs/zh/skills/pd-mentor/SKILL.md +2 -3
  134. package/templates/langs/zh/skills/pd-pain-signal/SKILL.md +17 -38
  135. package/templates/langs/zh/skills/pd-runtime-v2/SKILL.md +61 -0
  136. package/tests/build-artifacts.test.ts +1 -3
  137. package/tests/commands/evolution-status.test.ts +0 -118
  138. package/tests/core/bootstrap-rules.test.ts +1 -1
  139. package/tests/core/config.test.ts +1 -1
  140. package/tests/core/event-log.test.ts +35 -0
  141. package/tests/core/evolution-engine.test.ts +610 -0
  142. package/tests/core/file-store.test.ts +102 -0
  143. package/tests/core/focus-history.test.ts +203 -11
  144. package/tests/core/merge-gate-audit.test.ts +2 -169
  145. package/tests/core/migration.test.ts +7 -7
  146. package/tests/core/model-deployment-registry.test.ts +7 -1
  147. package/tests/core/model-training-registry.test.ts +19 -0
  148. package/tests/core/observability.test.ts +0 -1
  149. package/tests/core/pain-diagnostic-gate.test.ts +498 -0
  150. package/tests/core/pain.test.ts +0 -1
  151. package/tests/core/path-resolver.test.ts +1 -1
  152. package/tests/core/paths-refactor.test.ts +0 -22
  153. package/tests/core/principle-internalization/deprecated-readiness.test.ts +2 -2
  154. package/tests/core/principle-internalization/lifecycle-metrics.test.ts +2 -2
  155. package/tests/core/principle-internalization/{internalization-routing-policy.test.ts → lifecycle-routing-policy.test.ts} +6 -6
  156. package/tests/core/principle-internalization/lineage-source-retired.test.ts +56 -0
  157. package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +1 -23
  158. package/tests/core/principle-tree-ledger-adapter.test.ts +253 -0
  159. package/tests/core/reflection-context.test.ts +0 -14
  160. package/tests/core/replay-engine.test.ts +127 -215
  161. package/tests/core/rule-host-helpers.test.ts +2 -2
  162. package/tests/core/rule-implementation-runtime.test.ts +0 -27
  163. package/tests/core/workflow-funnel-loader.test.ts +162 -0
  164. package/tests/core/workspace-context.test.ts +2 -2
  165. package/tests/core/workspace-dir-validation.test.ts +8 -1
  166. package/tests/core-anti-growth.test.ts +191 -0
  167. package/tests/hook-workspace-nextaction-contract.test.ts +42 -0
  168. package/tests/hooks/confirm-first-removal.test.ts +188 -0
  169. package/tests/hooks/gate-auto-correct-shadow.test.ts +310 -0
  170. package/tests/hooks/gate-auto-correct.test.ts +665 -0
  171. package/tests/hooks/gate-no-path-write-tool.test.ts +172 -0
  172. package/tests/hooks/gate-rule-host-pipeline.test.ts +2 -1
  173. package/tests/hooks/pain.test.ts +269 -12
  174. package/tests/hooks/prompt-characterization.test.ts +500 -0
  175. package/tests/hooks/prompt-size-guard.test.ts +32 -17
  176. package/tests/hooks/runtime-v2-prompt-activation.test.ts +869 -0
  177. package/tests/index.test.ts +94 -1
  178. package/tests/integration/auto-entry-gate.test.ts +248 -0
  179. package/tests/integration/internalization-trigger-guard.test.ts +69 -0
  180. package/tests/integration/m8-legacy-paths.test.ts +63 -0
  181. package/tests/integration/runtime-v2-pain-guard.test.ts +125 -0
  182. package/tests/plugin-config-resolution-cutover.test.ts +359 -0
  183. package/tests/runtime-v2-discovery-guard.test.ts +154 -0
  184. package/tests/service/central-database.test.ts +457 -0
  185. package/tests/service/evolution-worker.correction-observer.test.ts +173 -0
  186. package/tests/service/evolution-worker.timeout.test.ts +11 -129
  187. package/tests/service/internalization-trigger-adapter.test.ts +251 -0
  188. package/tests/service/monitoring-query-service.test.ts +1 -47
  189. package/tests/service/queue-io.test.ts +1 -62
  190. package/tests/service/runtime-summary-service.test.ts +3 -1
  191. package/tests/service/workflow-watchdog.test.ts +0 -91
  192. package/tests/utils/file-lock.test.ts +5 -3
  193. package/tests/utils/session-key.test.ts +52 -0
  194. package/tests/utils/subagent-probe.test.ts +48 -1
  195. package/vitest.config.ts +4 -11
  196. package/.planning/codebase/ARCHITECTURE.md +0 -157
  197. package/.planning/codebase/CONCERNS.md +0 -145
  198. package/.planning/codebase/CONVENTIONS.md +0 -148
  199. package/.planning/codebase/INTEGRATIONS.md +0 -81
  200. package/.planning/codebase/STACK.md +0 -87
  201. package/.planning/codebase/STRUCTURE.md +0 -193
  202. package/.planning/codebase/TESTING.md +0 -243
  203. package/.planning/phases/01-basic-visualization/01-GAP-CLOSURE-VERIFICATION.md +0 -113
  204. package/docs/COMMAND_REFERENCE.md +0 -76
  205. package/docs/COMMAND_REFERENCE_EN.md +0 -79
  206. package/scripts/build-web.mjs +0 -46
  207. package/scripts/diagnose-nocturnal.mjs +0 -537
  208. package/scripts/seed-nocturnal-scenarios.mjs +0 -384
  209. package/src/commands/nocturnal-review.ts +0 -322
  210. package/src/commands/nocturnal-rollout.ts +0 -790
  211. package/src/commands/nocturnal-train.ts +0 -986
  212. package/src/commands/pd-reflect.ts +0 -88
  213. package/src/core/adaptive-thresholds.ts +0 -478
  214. package/src/core/diagnostician-task-store.ts +0 -192
  215. package/src/core/nocturnal-arbiter.ts +0 -715
  216. package/src/core/nocturnal-artifact-lineage.ts +0 -116
  217. package/src/core/nocturnal-artificer.ts +0 -257
  218. package/src/core/nocturnal-candidate-scoring.ts +0 -530
  219. package/src/core/nocturnal-compliance.ts +0 -1146
  220. package/src/core/nocturnal-dataset.ts +0 -763
  221. package/src/core/nocturnal-executability.ts +0 -428
  222. package/src/core/nocturnal-export.ts +0 -499
  223. package/src/core/nocturnal-paths.ts +0 -240
  224. package/src/core/nocturnal-reasoning-deriver.ts +0 -343
  225. package/src/core/nocturnal-rule-implementation-validator.ts +0 -246
  226. package/src/core/nocturnal-snapshot-contract.ts +0 -99
  227. package/src/core/nocturnal-trajectory-extractor.ts +0 -512
  228. package/src/core/nocturnal-trinity-types.ts +0 -218
  229. package/src/core/nocturnal-trinity.ts +0 -2680
  230. package/src/core/principle-internalization/deprecated-readiness.ts +0 -93
  231. package/src/core/principle-internalization/internalization-routing-policy.ts +0 -208
  232. package/src/core/principle-internalization/lifecycle-metrics.ts +0 -152
  233. package/src/http/principles-console-route.ts +0 -709
  234. package/src/service/central-health-service.ts +0 -49
  235. package/src/service/central-overview-service.ts +0 -138
  236. package/src/service/control-ui-query-service.ts +0 -900
  237. package/src/service/cooldown-strategy.ts +0 -97
  238. package/src/service/evolution-pain-context.ts +0 -79
  239. package/src/service/evolution-query-service.ts +0 -407
  240. package/src/service/health-query-service.ts +0 -1038
  241. package/src/service/nocturnal-config.ts +0 -214
  242. package/src/service/nocturnal-runtime.ts +0 -734
  243. package/src/service/nocturnal-service.ts +0 -1605
  244. package/src/service/nocturnal-target-selector.ts +0 -545
  245. package/src/service/sleep-cycle.ts +0 -157
  246. package/src/service/startup-reconciler.ts +0 -112
  247. package/src/service/subagent-workflow/correction-observer-types.ts +0 -82
  248. package/src/service/subagent-workflow/correction-observer-workflow-manager.ts +0 -250
  249. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +0 -1
  250. package/src/service/subagent-workflow/dynamic-timeout.ts +0 -30
  251. package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +0 -268
  252. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +0 -795
  253. package/src/service/subagent-workflow/runtime-direct-driver.ts +0 -268
  254. package/src/service/subagent-workflow/workflow-manager-base.ts +0 -580
  255. package/src/tools/write-pain-flag.ts +0 -215
  256. package/templates/langs/en/skills/plan-script/SKILL.md +0 -32
  257. package/templates/langs/zh/skills/plan-script/SKILL.md +0 -32
  258. package/tests/commands/nocturnal-review.test.ts +0 -448
  259. package/tests/commands/nocturnal-train.test.ts +0 -97
  260. package/tests/commands/pd-reflect.test.ts +0 -49
  261. package/tests/core/adaptive-thresholds.test.ts +0 -261
  262. package/tests/core/nocturnal-arbiter.test.ts +0 -559
  263. package/tests/core/nocturnal-artifact-lineage.test.ts +0 -53
  264. package/tests/core/nocturnal-artificer.test.ts +0 -241
  265. package/tests/core/nocturnal-candidate-scoring.test.ts +0 -532
  266. package/tests/core/nocturnal-compliance-p-principles.test.ts +0 -133
  267. package/tests/core/nocturnal-compliance.test.ts +0 -646
  268. package/tests/core/nocturnal-dataset.test.ts +0 -892
  269. package/tests/core/nocturnal-e2e.test.ts +0 -234
  270. package/tests/core/nocturnal-executability.test.ts +0 -357
  271. package/tests/core/nocturnal-export.test.ts +0 -517
  272. package/tests/core/nocturnal-reasoning-deriver.test.ts +0 -372
  273. package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +0 -428
  274. package/tests/core/nocturnal-rule-implementation-validator.test.ts +0 -127
  275. package/tests/core/nocturnal-snapshot-contract.test.ts +0 -121
  276. package/tests/core/nocturnal-trajectory-extractor.test.ts +0 -634
  277. package/tests/core/nocturnal-trinity.test.ts +0 -2053
  278. package/tests/core/pain-auto-repair.test.ts +0 -96
  279. package/tests/core/pain-integration.test.ts +0 -510
  280. package/tests/fixtures/nocturnal-reviewed-subset.json +0 -183
  281. package/tests/http/principles-console-route.test.ts +0 -162
  282. package/tests/integration/chaos-resilience.test.ts +0 -348
  283. package/tests/integration/empathy-workflow-integration.test.ts +0 -626
  284. package/tests/integration/pain-diagnostician-loop.e2e.test.ts +0 -380
  285. package/tests/service/control-ui-query-service.test.ts +0 -121
  286. package/tests/service/cooldown-strategy.test.ts +0 -164
  287. package/tests/service/data-endpoints-regression.test.ts +0 -834
  288. package/tests/service/empathy-observer-workflow-manager.test.ts +0 -175
  289. package/tests/service/evolution-worker.nocturnal.test.ts +0 -601
  290. package/tests/service/nocturnal-runtime-hardening.test.ts +0 -118
  291. package/tests/service/nocturnal-runtime.test.ts +0 -473
  292. package/tests/service/nocturnal-service-code-candidate.test.ts +0 -330
  293. package/tests/service/nocturnal-target-selector.test.ts +0 -615
  294. package/tests/service/startup-reconciler.test.ts +0 -148
  295. package/tests/tools/write-pain-flag.test.ts +0 -358
  296. package/ui/src/App.tsx +0 -45
  297. package/ui/src/api.ts +0 -220
  298. package/ui/src/charts.tsx +0 -955
  299. package/ui/src/components/ErrorState.tsx +0 -6
  300. package/ui/src/components/Loading.tsx +0 -13
  301. package/ui/src/components/ProtectedRoute.tsx +0 -12
  302. package/ui/src/components/Shell.tsx +0 -91
  303. package/ui/src/components/WorkspaceConfig.tsx +0 -178
  304. package/ui/src/components/index.ts +0 -5
  305. package/ui/src/context/auth.tsx +0 -80
  306. package/ui/src/context/theme.tsx +0 -66
  307. package/ui/src/hooks/useAutoRefresh.ts +0 -39
  308. package/ui/src/i18n/ui.ts +0 -473
  309. package/ui/src/main.tsx +0 -16
  310. package/ui/src/pages/EvolutionPage.tsx +0 -333
  311. package/ui/src/pages/FeedbackPage.tsx +0 -138
  312. package/ui/src/pages/GateMonitorPage.tsx +0 -136
  313. package/ui/src/pages/LoginPage.tsx +0 -89
  314. package/ui/src/pages/OverviewPage.tsx +0 -599
  315. package/ui/src/pages/SamplesPage.tsx +0 -174
  316. package/ui/src/pages/ThinkingModelsPage.tsx +0 -702
  317. package/ui/src/styles.css +0 -2020
  318. package/ui/src/types.ts +0 -384
  319. package/ui/src/utils/format.ts +0 -15
@@ -7,32 +7,32 @@ export const PDTaskService: OpenClawPluginService = {
7
7
 
8
8
  async start(ctx: OpenClawPluginServiceContext): Promise<void> {
9
9
  const {workspaceDir} = ctx;
10
+ const logger = ctx.logger ?? ctx.api?.logger;
10
11
  if (!workspaceDir) {
11
- ctx.logger?.warn?.(`[PD:TaskManager] No workspaceDir, skipping PD task reconciliation`);
12
+ logger?.warn?.(`[PD:TaskManager] No workspaceDir, skipping PD task reconciliation`);
12
13
  return;
13
14
  }
14
15
 
15
- const {logger} = ctx;
16
- logger.info?.(`[PD:TaskManager] Starting PD task reconciliation...`);
16
+ logger?.info?.(`[PD:TaskManager] Starting PD task reconciliation...`);
17
17
 
18
18
  try {
19
- const result = await reconcilePDTasks(workspaceDir, { logger });
20
- logger.info?.(
19
+ const result = await reconcilePDTasks(workspaceDir, { logger: logger ?? console });
20
+ logger?.info?.(
21
21
  `[PD:TaskManager] Reconcile complete: +${result.created.length} ~${result.updated.length} =${result.skipped.length} orphan=${result.orphaned.length}`,
22
22
  );
23
23
  if (result.created.length > 0) {
24
- logger.info?.(`[PD:TaskManager] Created jobs: ${result.created.join(', ')}`);
24
+ logger?.info?.(`[PD:TaskManager] Created jobs: ${result.created.join(', ')}`);
25
25
  }
26
26
  if (result.updated.length > 0) {
27
- logger.info?.(`[PD:TaskManager] Updated jobs: ${result.updated.join(', ')}`);
27
+ logger?.info?.(`[PD:TaskManager] Updated jobs: ${result.updated.join(', ')}`);
28
28
  }
29
29
  if (result.errors.length > 0) {
30
- logger.warn?.(
30
+ logger?.warn?.(
31
31
  `[PD:TaskManager] Reconcile errors: ${result.errors.map((e) => e.message).join(', ')}`,
32
32
  );
33
33
  }
34
34
  } catch (err) {
35
- logger.warn?.(`[PD:TaskManager] Reconcile failed: ${String(err)}`);
35
+ logger?.warn?.(`[PD:TaskManager] Reconcile failed: ${String(err)}`);
36
36
  }
37
37
  },
38
38
 
@@ -1,128 +1,24 @@
1
- /**
2
- * PD Task Manager Types
3
- *
4
- * Type definitions for the PD Task Manager — a declarative cron task
5
- * management system that reconciles PD task declarations with OpenClaw's
6
- * cron/jobs.json using safe file operations (lock + atomic write).
7
- */
1
+ import type {
2
+ PDTaskSchedule as CorePDTaskSchedule,
3
+ PDTaskExecution as CorePDTaskExecution,
4
+ PDTaskDelivery as CorePDTaskDelivery,
5
+ PDTaskMeta as CorePDTaskMeta,
6
+ PDTaskSpec as CorePDTaskSpec,
7
+ } from '@principles/core/runtime-v2';
8
+
9
+ export type PDTaskSchedule = CorePDTaskSchedule;
10
+ export type PDTaskExecution = CorePDTaskExecution;
11
+ export type PDTaskDelivery = CorePDTaskDelivery;
12
+ export type PDTaskMeta = CorePDTaskMeta;
13
+ export type PDTaskSpec = CorePDTaskSpec;
14
+
15
+ export {
16
+ PDTaskScheduleSchema,
17
+ PDTaskExecutionSchema,
18
+ PDTaskDeliverySchema,
19
+ PDTaskMetaSchema,
20
+ PDTaskSpecSchema,
21
+ } from '@principles/core/runtime-v2';
22
+
23
+ export const BUILTIN_PD_TASKS: PDTaskSpec[] = [];
8
24
 
9
- // =========================================================================
10
- // PDTaskSpec — Declaration Schema
11
- // =========================================================================
12
-
13
- /** Cron schedule for PD tasks (only "every" kind supported for now) */
14
- export interface PDTaskSchedule {
15
- kind: 'every';
16
- everyMs: number;
17
- }
18
-
19
- /** Execution configuration for a PD task */
20
- export interface PDTaskExecution {
21
- /** Which prompt builder to use */
22
- promptTemplate: string;
23
- /** Execution timeout in seconds (default: 120) */
24
- timeoutSeconds?: number;
25
- /** Use lightweight context to save tokens */
26
- lightContext?: boolean;
27
- /** Restrict available tools */
28
- toolsAllow?: string[];
29
- }
30
-
31
- /** Delivery configuration for task results */
32
- export interface PDTaskDelivery {
33
- mode: 'none' | 'announce';
34
- channel?: string;
35
- to?: string;
36
- }
37
-
38
- /** Metadata — not synced to cron, used for health tracking */
39
- export interface PDTaskMeta {
40
- /** When this task was first declared */
41
- createdAtMs?: number;
42
- /** Last successful reconcile timestamp */
43
- lastSyncedAtMs?: number;
44
- /** The cron job ID from last sync */
45
- lastSyncedJobId?: string;
46
- /** Last sync status */
47
- lastSyncStatus?: 'ok' | 'error';
48
- /** Last sync error message */
49
- lastSyncError?: string;
50
- /** Consecutive failure count (from CronJobState.consecutiveErrors) */
51
- consecutiveFailCount?: number;
52
- /** Timestamp of last failure */
53
- lastFailedAtMs?: number;
54
- /** Whether this task was auto-disabled due to health issues */
55
- autoDisabled?: boolean;
56
- /** When the task was auto-disabled */
57
- autoDisabledAt?: number;
58
- /** Reason for auto-disable */
59
- autoDisabledReason?: string;
60
- /** Last manual trigger timestamp */
61
- lastTriggeredAtMs?: number;
62
- /** Last manual trigger status */
63
- lastTriggerStatus?: 'succeeded' | 'failed' | 'pending';
64
- }
65
-
66
- /**
67
- * PDTaskSpec — A declarative specification for a PD background task.
68
- *
69
- * This is the source of truth. The reconciler translates these into
70
- * CronJob entries in OpenClaw's cron/jobs.json.
71
- */
72
- export interface PDTaskSpec {
73
- /** Stable unique ID — never changes across versions */
74
- id: string;
75
- /** Human-readable name — becomes the CronJob name (must start with "PD ") */
76
- name: string;
77
- /** Description shown to users */
78
- description: string;
79
- /** Whether this task should be active */
80
- enabled: boolean;
81
- /** Schema version — bumped when prompt/config changes require re-sync */
82
- version: string;
83
- /** Cron schedule (only "every" kind supported for now) */
84
- schedule: PDTaskSchedule;
85
- /** OpenClaw agent ID to run under (default: "main") */
86
- agentId?: string;
87
- /** Execution configuration */
88
- execution: PDTaskExecution;
89
- /** Delivery configuration */
90
- delivery: PDTaskDelivery;
91
- /** Metadata — not synced to cron */
92
- meta?: PDTaskMeta;
93
- }
94
-
95
- // =========================================================================
96
- // Builtin PD Tasks
97
- // =========================================================================
98
-
99
- /**
100
- * Built-in PD tasks declared by the plugin.
101
- *
102
- * These are reconciled on plugin startup. Adding a new task here
103
- * automatically creates the corresponding cron job on next restart.
104
- */
105
- export const BUILTIN_PD_TASKS: PDTaskSpec[] = [
106
- {
107
- id: 'empathy-optimizer',
108
- name: 'PD Empathy Optimizer',
109
- description:
110
- 'Analyzes recent user messages to discover new frustration expressions and optimize keyword weights.',
111
- enabled: true,
112
- version: '1.0.1', // Bumped to force cron job settings update
113
- schedule: {
114
- kind: 'every',
115
- everyMs: 5 * 60 * 1000, // 5 minutes (testing); increase to 6h once stable
116
- },
117
- agentId: 'main',
118
- execution: {
119
- promptTemplate: 'empathy-optimizer',
120
- timeoutSeconds: 300, // 5 min — needs time to scan events.jsonl
121
- lightContext: true,
122
- toolsAllow: ['read_file', 'write_file', 'search_file_content'],
123
- },
124
- delivery: {
125
- mode: 'none',
126
- },
127
- },
128
- ];
@@ -0,0 +1,174 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+
3
+ // --- Mocks (hoisted for vi.mock compatibility) ---
4
+
5
+ const {
6
+ mockCollect, mockRegister, mockCreateAssetDir,
7
+ mockLoadModule, mockValidate, mockGenerate,
8
+ } = vi.hoisted(() => ({
9
+ mockCollect: vi.fn(),
10
+ mockRegister: vi.fn(),
11
+ mockCreateAssetDir: vi.fn(),
12
+ mockLoadModule: vi.fn(),
13
+ mockValidate: vi.fn(),
14
+ mockGenerate: vi.fn(),
15
+ }));
16
+
17
+ vi.mock('../code-validator.js', () => ({
18
+ validateGeneratedCode: mockValidate,
19
+ }));
20
+
21
+ vi.mock('../template-generator.js', () => ({
22
+ generateFromTemplate: mockGenerate,
23
+ }));
24
+
25
+ vi.mock('../ledger-registrar.js', () => ({
26
+ registerCompiledRule: mockRegister,
27
+ }));
28
+
29
+ vi.mock('../../code-implementation-storage.js', () => ({
30
+ createImplementationAssetDir: mockCreateAssetDir,
31
+ }));
32
+
33
+ vi.mock('../../rule-implementation-runtime.js', () => ({
34
+ loadRuleImplementationModule: mockLoadModule,
35
+ }));
36
+
37
+ import { PrincipleCompiler } from '../compiler.js';
38
+
39
+ // --- Fixtures ---
40
+
41
+ const PRINCIPLE_ID = 'P_test_001';
42
+
43
+ function makeContext(overrides?: { reason?: string }) {
44
+ return {
45
+ principle: {
46
+ id: PRINCIPLE_ID,
47
+ version: 1,
48
+ text: 'Never delete system files via bash',
49
+ triggerPattern: 'bash rm',
50
+ action: 'block dangerous bash commands',
51
+ status: 'active' as const,
52
+ priority: 'high' as const,
53
+ scope: 'global' as const,
54
+ evaluability: 'deterministic' as const,
55
+ valueScore: 0.9,
56
+ adherenceRate: 0.8,
57
+ painPreventedCount: 5,
58
+ derivedFromPainIds: ['pain_001'],
59
+ ruleIds: [] as string[],
60
+ conflictsWithPrincipleIds: [] as string[],
61
+ createdAt: '2026-05-01T00:00:00Z',
62
+ updatedAt: '2026-05-01T00:00:00Z',
63
+ },
64
+ painEvents: [
65
+ {
66
+ reason: overrides?.reason ?? 'bash command failed on /etc/important.conf',
67
+ source: 'tool_failure',
68
+ },
69
+ ],
70
+ sessionSnapshot: null,
71
+ lineage: { sourcePainIds: ['pain_001'], sessionId: null as string | null },
72
+ };
73
+ }
74
+
75
+ // --- Tests ---
76
+
77
+ describe('PrincipleCompiler replay gate (PRI-115)', () => {
78
+ let compiler: PrincipleCompiler;
79
+
80
+ beforeEach(() => {
81
+ vi.clearAllMocks();
82
+
83
+ // Mock collector.collect directly on the instance
84
+ mockCollect.mockReturnValue(makeContext());
85
+
86
+ mockValidate.mockReturnValue({ valid: true, errors: [], warnings: [] });
87
+ mockGenerate.mockReturnValue(
88
+ 'export function evaluate() { return { decision: "block", matched: true, reason: "test", confidence: 0.95 }; }',
89
+ );
90
+ mockRegister.mockReturnValue({ ruleId: 'R_test_auto', implementationId: 'IMPL_test_auto' });
91
+
92
+ compiler = new PrincipleCompiler('/tmp/test-state', {} as any);
93
+ // Override collector after construction to avoid module resolution issues
94
+ (compiler as any).collector = { collect: mockCollect, collectBatch: vi.fn() };
95
+ });
96
+
97
+ it('failing replay returns degraded=true and blocks registration', () => {
98
+ mockCollect.mockReturnValue(makeContext());
99
+
100
+ mockLoadModule.mockReturnValue({
101
+ evaluate: () => ({ decision: 'allow', matched: false, reason: 'pass', confidence: 1.0 }),
102
+ });
103
+
104
+ const result = compiler.compileOne(PRINCIPLE_ID);
105
+
106
+ expect(result.success).toBe(false);
107
+ expect(result.degraded).toBe(true);
108
+ expect(result.reason).toBe('replay_validation_failed');
109
+ expect(result.replayResult).toBeDefined();
110
+ expect(result.replayResult!.passed).toBe(false);
111
+ expect(mockRegister).not.toHaveBeenCalled();
112
+ });
113
+
114
+ it('no asset dir created on replay failure', () => {
115
+ mockCollect.mockReturnValue(makeContext());
116
+
117
+ mockLoadModule.mockReturnValue({
118
+ evaluate: () => ({ decision: 'allow', matched: false, reason: 'pass', confidence: 1.0 }),
119
+ });
120
+
121
+ compiler.compileOne(PRINCIPLE_ID);
122
+
123
+ expect(mockCreateAssetDir).not.toHaveBeenCalled();
124
+ });
125
+
126
+ it('passing replay registers normally', () => {
127
+ mockCollect.mockReturnValue(makeContext());
128
+
129
+ mockLoadModule.mockReturnValue({
130
+ evaluate: (input: any) => {
131
+ const path = input?.action?.paramsSummary?.path;
132
+ if (path && path.includes('passwd')) {
133
+ return { decision: 'block', matched: true, reason: 'dangerous', confidence: 0.95 };
134
+ }
135
+ return { decision: 'allow', matched: false, reason: 'safe', confidence: 1.0 };
136
+ },
137
+ });
138
+
139
+ const result = compiler.compileOne(PRINCIPLE_ID);
140
+
141
+ expect(result.success).toBe(true);
142
+ expect(result.degraded).toBeUndefined();
143
+ expect(mockRegister).toHaveBeenCalledOnce();
144
+ expect(mockCreateAssetDir).toHaveBeenCalledOnce();
145
+ });
146
+
147
+ it('no cases (no regex qualifier) skips replay gate and registers', () => {
148
+ mockCollect.mockReturnValue(makeContext({ reason: 'bash failed unexpectedly' }));
149
+
150
+ mockLoadModule.mockReturnValue({
151
+ evaluate: () => ({ decision: 'block', matched: true, reason: 'test', confidence: 0.95 }),
152
+ });
153
+
154
+ const result = compiler.compileOne(PRINCIPLE_ID);
155
+
156
+ expect(result.success).toBe(true);
157
+ expect(result.degraded).toBeUndefined();
158
+ expect(mockRegister).toHaveBeenCalledOnce();
159
+ expect(mockLoadModule).not.toHaveBeenCalled();
160
+ });
161
+
162
+ it('no evaluate export returns degraded', () => {
163
+ mockCollect.mockReturnValue(makeContext());
164
+
165
+ mockLoadModule.mockReturnValue({});
166
+
167
+ const result = compiler.compileOne(PRINCIPLE_ID);
168
+
169
+ expect(result.success).toBe(false);
170
+ expect(result.degraded).toBe(true);
171
+ expect(result.reason).toContain('no evaluate export');
172
+ expect(mockRegister).not.toHaveBeenCalled();
173
+ });
174
+ });
@@ -1,45 +1,18 @@
1
1
  /**
2
2
  * Code Validator — Validates LLM-generated rule implementation code
3
3
  *
4
- * PURPOSE: Ensure generated code is safe, syntactically correct, and exports
5
- * the expected shape before it is stored as a rule implementation.
6
- *
7
4
  * CHECKS:
8
- * 1. Syntax: code parses without errors
9
- * 2. Forbidden patterns: no require, import, fetch, eval, Function, process, globalThis
10
- * 3. Export check: sandbox loads and exports evaluate + meta
11
- * 4. Return shape: evaluate(mockInput) returns { matched: boolean }
5
+ * 1. Syntax: code parses without errors (VM)
6
+ * 2. Forbidden patterns: delegates to core checkForbiddenPatterns (PRI-44)
7
+ * 3. Export check: sandbox loads and exports evaluate + meta (VM)
8
+ * 4. Return shape: evaluate(mockInput) returns { matched: boolean } (VM)
12
9
  *
13
- * Reuses loadRuleImplementationModule for sandbox execution (node:vm isolation).
10
+ * PRI-44: Forbidden pattern detection extracted to @principles/core.
14
11
  */
15
12
 
16
13
  import { nodeVm } from '../../utils/node-vm-polyfill.js';
17
14
  import { loadRuleImplementationModule } from '../rule-implementation-runtime.js';
18
-
19
- export interface ValidationResult {
20
- valid: boolean;
21
- errors: string[];
22
- warnings: string[];
23
- }
24
-
25
- const FORBIDDEN_PATTERNS: { pattern: RegExp; label: string }[] = [
26
- { pattern: /\brequire\s*\(/, label: 'require' },
27
- { pattern: /\bimport\s+/, label: 'import' },
28
- { pattern: /\bfetch\s*\(/, label: 'fetch' },
29
- { pattern: /\beval\s*\(/, label: 'eval' },
30
- { pattern: /\bFunction\s*\(/, label: 'Function' },
31
- { pattern: /\bprocess\b/, label: 'process' },
32
- { pattern: /\bglobalThis\b/, label: 'globalThis' },
33
- { pattern: /\bglobal\b/, label: 'global' },
34
- { pattern: /\bReflect\b/, label: 'Reflect' },
35
- { pattern: /\bProxy\b/, label: 'Proxy' },
36
- { pattern: /\bconstructor\b/, label: 'constructor' },
37
- { pattern: /\bBuffer\b/, label: 'Buffer' },
38
- { pattern: /\bsetTimeout\b/, label: 'setTimeout' },
39
- { pattern: /\bsetInterval\b/, label: 'setInterval' },
40
- // Bracket notation access to globals
41
- { pattern: /\[\s*['"](require|import|fetch|eval|process|globalThis|global|Reflect|Proxy|Buffer|Function)\s*['"]\s*\]/, label: 'bracket access to forbidden global' },
42
- ];
15
+ import { checkForbiddenPatterns, type ValidationResult } from '@principles/core/runtime-v2';
43
16
 
44
17
  const MOCK_INPUT = {
45
18
  action: {
@@ -53,12 +26,13 @@ const MOCK_INPUT = {
53
26
  derived: { estimatedLineChanges: 0, bashRisk: 'safe' },
54
27
  };
55
28
 
29
+ export type { ValidationResult } from '@principles/core/runtime-v2';
30
+
56
31
  export function validateGeneratedCode(code: string): ValidationResult {
57
32
  const errors: string[] = [];
58
33
  const warnings: string[] = [];
59
34
 
60
35
  // --- Check 1: Syntax ---
61
- // Normalize export keywords so vm.Script can parse ES module source
62
36
  const normalized = code
63
37
  .replace(/export\s+const\s+/g, 'const ')
64
38
  .replace(/export\s+function\s+/g, 'function ');
@@ -69,11 +43,10 @@ export function validateGeneratedCode(code: string): ValidationResult {
69
43
  return { valid: false, errors, warnings };
70
44
  }
71
45
 
72
- // --- Check 2: Forbidden patterns ---
73
- for (const { pattern, label } of FORBIDDEN_PATTERNS) {
74
- if (pattern.test(code)) {
75
- errors.push(`Forbidden pattern: ${label}`);
76
- }
46
+ // --- Check 2: Forbidden patterns (delegated to core) ---
47
+ const forbiddenLabels = checkForbiddenPatterns(code);
48
+ for (const label of forbiddenLabels) {
49
+ errors.push(`Forbidden pattern: ${label}`);
77
50
  }
78
51
 
79
52
  if (errors.length > 0) {
@@ -102,6 +75,9 @@ export function validateGeneratedCode(code: string): ValidationResult {
102
75
  }
103
76
 
104
77
  // --- Check 4: Return shape ---
78
+ // evaluate() throwing on mock input is acceptable — the function exists and has the
79
+ // right signature, it just can't handle our generic mock data.
80
+ // Track as a non-blocking warning so operators know the rule may be fragile.
105
81
  try {
106
82
  const result = (moduleExports.evaluate as (input: unknown) => unknown)(MOCK_INPUT);
107
83
  if (!result || typeof result !== 'object') {
@@ -110,9 +86,6 @@ export function validateGeneratedCode(code: string): ValidationResult {
110
86
  errors.push('evaluate must return { matched: boolean }');
111
87
  }
112
88
  } catch (evalWarning) {
113
- // evaluate throwing on mock input is acceptable — the function exists and
114
- // has the right signature, it just can't handle our generic mock data.
115
- // Track as a non-blocking warning so operators know the rule may be fragile.
116
89
  warnings.push(`evaluate() threw on mock input: ${(evalWarning as Error).message}`);
117
90
  }
118
91
 
@@ -3,12 +3,13 @@
3
3
  *
4
4
  * Orchestrates the full compilation flow:
5
5
  * ReflectionContextCollector.collect() → extract patterns → generateFromTemplate()
6
- * → validateGeneratedCode() → registerCompiledRule()
6
+ * → validateGeneratedCode() → [replay validation] → registerCompiledRule()
7
7
  *
8
8
  * DESIGN DECISIONS:
9
9
  * - extractPatterns infers toolName from pain event reasons and session tool calls
10
10
  * - Groups by toolName into PainPattern objects
11
11
  * - If no patterns can be extracted, returns a 'no patterns' failure
12
+ * - PRI-115: Replay validation gate runs after code validation, before registration
12
13
  */
13
14
 
14
15
  import { ReflectionContextCollector } from '../reflection/reflection-context.js';
@@ -17,19 +18,13 @@ import { generateFromTemplate, type PainPattern } from './template-generator.js'
17
18
  import { registerCompiledRule } from './ledger-registrar.js';
18
19
  import { createImplementationAssetDir } from '../code-implementation-storage.js';
19
20
  import type { TrajectoryDatabase } from '../trajectory.js';
21
+ import type { CompileResult } from '@principles/core/runtime-v2';
22
+ import { loadRuleImplementationModule } from '../rule-implementation-runtime.js';
23
+ import { createGoldenTraceFixture, type GoldenTraceCase } from '@principles/core/runtime-v2';
24
+ import { replayGoldenTrace, type ReplayEvaluateFn } from '@principles/core/runtime-v2';
20
25
 
21
- // ---------------------------------------------------------------------------
22
- // Types
23
- // ---------------------------------------------------------------------------
24
-
25
- export interface CompileResult {
26
- success: boolean;
27
- principleId: string;
28
- ruleId?: string;
29
- implementationId?: string;
30
- code?: string;
31
- reason?: string;
32
- }
26
+ // Re-export CompileResult from core
27
+ export type { CompileResult } from '@principles/core/runtime-v2';
33
28
 
34
29
  // ---------------------------------------------------------------------------
35
30
  // Constants
@@ -119,13 +114,20 @@ function extractPatterns(context: {
119
114
  /**
120
115
  * Infer tool name from text by checking for known tool names.
121
116
  * Returns the first matching known tool name, or null if none found.
117
+ *
118
+ * Uses negative lookbehind to avoid matching natural-language uses:
119
+ * - "please read the error" → read is a verb, not a tool reference
120
+ * - "could write to file" → write is a verb, not a tool reference
121
+ * Tool references in pain events typically appear near words like
122
+ * "tool", "call", "command", "failed", "via", "using", etc.
122
123
  */
123
124
  function inferToolName(text: string): string | null {
124
125
  const lower = text.toLowerCase();
125
126
  for (const tool of KNOWN_TOOLS) {
126
- // Match as a standalone word to avoid false positives
127
+ // Match as a standalone word but exclude common natural-language patterns
127
128
  // e.g., "bash" in "bash" or "bash command" but not in "ambush"
128
- const regex = new RegExp(`\\b${tool}\\b`);
129
+ // and not in "please read" or "could write" where it's a verb
130
+ const regex = new RegExp(`(?<!please |could |should |would )\\b${tool}\\b`);
129
131
  if (regex.test(lower)) {
130
132
  return tool;
131
133
  }
@@ -173,6 +175,7 @@ export class PrincipleCompiler {
173
175
  * 2. Extract pain patterns
174
176
  * 3. Generate code from template
175
177
  * 4. Validate generated code
178
+ * 4.5. Replay validation against GoldenTrace (PRI-115)
176
179
  * 5. Register in ledger
177
180
  */
178
181
  compileOne(principleId: string): CompileResult {
@@ -205,6 +208,49 @@ export class PrincipleCompiler {
205
208
  };
206
209
  }
207
210
 
211
+ // Step 4.5: Replay validation against GoldenTrace (PRI-115)
212
+ const replayCases = this.buildGoldenTraceCases(patterns, context);
213
+ if (replayCases.length > 0) {
214
+ let moduleExports: { evaluate?: unknown };
215
+ try {
216
+ moduleExports = loadRuleImplementationModule(code, `replay-${principleId}.js`);
217
+ } catch (err) {
218
+ return {
219
+ success: false,
220
+ principleId,
221
+ reason: `module_load_error: ${(err as Error).message}`,
222
+ code,
223
+ degraded: true,
224
+ };
225
+ }
226
+
227
+ if (typeof moduleExports.evaluate !== 'function') {
228
+ return { success: false, principleId, reason: 'replay: no evaluate export', degraded: true };
229
+ }
230
+
231
+ try {
232
+ const evaluateFn = moduleExports.evaluate as ReplayEvaluateFn;
233
+ const replayResult = replayGoldenTrace(evaluateFn, replayCases);
234
+ if (!replayResult.passed) {
235
+ return {
236
+ success: false,
237
+ principleId,
238
+ reason: 'replay_validation_failed',
239
+ code,
240
+ replayResult,
241
+ degraded: true,
242
+ };
243
+ }
244
+ } catch (err) {
245
+ return {
246
+ success: false,
247
+ principleId,
248
+ reason: `replay_error: ${(err as Error).message}`,
249
+ code,
250
+ degraded: true,
251
+ };
252
+ }
253
+ }
208
254
  // Step 5: Register
209
255
  const registration = registerCompiledRule(this.stateDir, {
210
256
  principleId,
@@ -226,6 +272,43 @@ export class PrincipleCompiler {
226
272
  };
227
273
  }
228
274
 
275
+ /**
276
+ * Build GoldenTrace test cases from extracted pain patterns.
277
+ *
278
+ * Generates synthetic negative/positive parameter pairs based on whether
279
+ * the pattern targets commands (commandRegex) or paths (pathRegex).
280
+ * Returns an empty array when no patterns are available.
281
+ */
282
+ private buildGoldenTraceCases(
283
+ patterns: PainPattern[],
284
+ _context: { painEvents: Array<{ reason: string | null; source: string }> },
285
+ ): GoldenTraceCase[] {
286
+ if (patterns.length === 0) return [];
287
+
288
+ const pattern = patterns[0];
289
+ // Skip replay when the pattern has no regex qualifier -- the generated template
290
+ // blocks ALL calls to the tool, making it impossible to construct a passing
291
+ // positive case. Replay is only meaningful when the template is selective.
292
+ // Also skip contentRegex-only patterns: synthetic content params are not meaningful.
293
+ if (!pattern.commandRegex && !pattern.pathRegex) return [];
294
+ const negativeParams: Record<string, unknown> = {};
295
+ if (pattern.commandRegex) negativeParams.command = 'rm -rf /';
296
+ else negativeParams.path = '/etc/passwd';
297
+
298
+ const positiveParams: Record<string, unknown> = {};
299
+ if (pattern.commandRegex) positiveParams.command = 'echo hello';
300
+ else positiveParams.path = '/tmp/safe.txt';
301
+
302
+ const fixture = createGoldenTraceFixture({
303
+ toolName: pattern.toolName,
304
+ negativeParams,
305
+ positiveParams,
306
+ expectedDecision: 'block',
307
+ });
308
+
309
+ return fixture.cases;
310
+ }
311
+
229
312
  /**
230
313
  * Compile all eligible principles (those with derivedFromPainIds).
231
314
  */
@@ -235,6 +318,8 @@ export class PrincipleCompiler {
235
318
  try {
236
319
  return this.compileOne(ctx.principle.id);
237
320
  } catch (e) {
321
+ // Log for operator visibility — catch-return is intentional for batch容错
322
+ console.warn(`[PrincipleCompiler] compileAll failed for ${ctx.principle.id}: ${(e as Error).message}`);
238
323
  return { success: false, principleId: ctx.principle.id, reason: `unhandled: ${(e as Error).message}` };
239
324
  }
240
325
  });
@@ -2,9 +2,12 @@
2
2
  * Principle Compiler — Barrel Export
3
3
  *
4
4
  * Re-exports all principle-compiler components for convenient importing.
5
+ * PRI-44: Types and pure logic re-exported from @principles/core.
5
6
  */
6
7
 
7
- export { PrincipleCompiler, type CompileResult } from './compiler.js';
8
- export { validateGeneratedCode, type ValidationResult } from './code-validator.js';
8
+ export { PrincipleCompiler } from './compiler.js';
9
+ export type { CompileResult } from './compiler.js';
10
+ export { validateGeneratedCode } from './code-validator.js';
11
+ export type { ValidationResult } from './code-validator.js';
9
12
  export { generateFromTemplate, type PainPattern } from './template-generator.js';
10
13
  export { registerCompiledRule, type RegisterInput, type RegisterResult } from './ledger-registrar.js';