principles-disciple 1.72.0 → 1.73.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 (309) hide show
  1. package/openclaw.plugin.json +10 -5
  2. package/package.json +17 -19
  3. package/scripts/acceptance-test.mjs +16 -73
  4. package/scripts/sync-plugin.mjs +382 -77
  5. package/src/commands/archive-impl.ts +2 -1
  6. package/src/commands/capabilities.ts +2 -2
  7. package/src/commands/context.ts +2 -2
  8. package/src/commands/disable-impl.ts +2 -1
  9. package/src/commands/evolution-status.ts +16 -16
  10. package/src/commands/export.ts +12 -67
  11. package/src/commands/pain.ts +91 -1
  12. package/src/commands/principle-rollback.ts +2 -1
  13. package/src/commands/promote-impl.ts +7 -43
  14. package/src/commands/rollback-impl.ts +2 -1
  15. package/src/commands/rollback.ts +2 -1
  16. package/src/commands/samples.ts +2 -1
  17. package/src/commands/thinking-os.ts +2 -1
  18. package/src/config/errors.ts +18 -2
  19. package/src/constants/diagnostician.ts +2 -2
  20. package/src/constants/tools.ts +2 -1
  21. package/src/core/__tests__/focus-history.test.ts +210 -0
  22. package/src/core/config.ts +1 -1
  23. package/src/core/confirm-first-gate.ts +255 -0
  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 +38 -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/pain-diagnostic-gate.ts +154 -0
  37. package/src/core/pain-signal.ts +21 -138
  38. package/src/core/pain.ts +15 -88
  39. package/src/core/pd-task-reconciler.ts +26 -115
  40. package/src/core/pd-task-service.ts +9 -9
  41. package/src/core/pd-task-types.ts +23 -127
  42. package/src/core/principle-compiler/__tests__/compiler-replay-gate.test.ts +174 -0
  43. package/src/core/principle-compiler/code-validator.ts +15 -42
  44. package/src/core/principle-compiler/compiler.ts +100 -15
  45. package/src/core/principle-compiler/index.ts +5 -2
  46. package/src/core/principle-compiler/template-generator.ts +4 -104
  47. package/src/core/principle-injection.ts +10 -202
  48. package/src/core/principle-internalization/filesystem-lifecycle-datasource.ts +42 -0
  49. package/src/core/principle-internalization/lifecycle-read-model.ts +39 -242
  50. package/src/core/principle-internalization/principle-lifecycle-service.ts +12 -10
  51. package/src/core/principle-tree-ledger-adapter.ts +145 -0
  52. package/src/core/principle-tree-ledger.ts +8 -6
  53. package/src/core/reflection/reflection-context.ts +14 -109
  54. package/src/core/replay-engine.ts +8 -500
  55. package/src/core/rule-host-helpers.ts +5 -35
  56. package/src/core/rule-host-types.ts +10 -82
  57. package/src/core/rule-host.ts +6 -63
  58. package/src/core/runtime-v2-prompt-activation-reader.ts +231 -0
  59. package/src/core/session-tracker.ts +87 -101
  60. package/src/core/shadow-observation-registry.ts +19 -48
  61. package/src/core/trajectory.ts +3 -1
  62. package/src/core/workflow-funnel-loader.ts +62 -68
  63. package/src/core/workspace-context.ts +46 -0
  64. package/src/core/workspace-dir-service.ts +1 -1
  65. package/src/core/workspace-dir-validation.ts +18 -9
  66. package/src/hooks/AGENTS.md +1 -1
  67. package/src/hooks/gate-block-helper.ts +46 -44
  68. package/src/hooks/gate.ts +207 -7
  69. package/src/hooks/lifecycle.ts +30 -32
  70. package/src/hooks/llm.ts +60 -32
  71. package/src/hooks/pain.ts +297 -103
  72. package/src/hooks/prompt.ts +459 -439
  73. package/src/hooks/subagent.ts +2 -29
  74. package/src/i18n/commands.ts +2 -10
  75. package/src/index.ts +95 -85
  76. package/src/openclaw-sdk.ts +311 -0
  77. package/src/service/central-database.ts +8 -4
  78. package/src/service/evolution-queue-migration.ts +2 -1
  79. package/src/service/evolution-worker.ts +163 -1786
  80. package/src/service/internalization-trigger-adapter.ts +302 -0
  81. package/src/service/keyword-optimization-service.ts +4 -4
  82. package/src/service/monitoring-query-service.ts +1 -215
  83. package/src/service/queue-io.ts +60 -331
  84. package/src/service/runtime-summary-service.ts +59 -16
  85. package/src/service/subagent-workflow/index.ts +0 -41
  86. package/src/service/subagent-workflow/types.ts +9 -120
  87. package/src/service/subagent-workflow/workflow-store.ts +2 -119
  88. package/src/service/workflow-watchdog.ts +0 -43
  89. package/src/types/event-payload.ts +16 -74
  90. package/src/types/event-types.ts +39 -547
  91. package/src/types/hygiene-types.ts +7 -30
  92. package/src/types/principle-tree-schema.ts +20 -222
  93. package/src/types/queue.ts +15 -70
  94. package/src/types/runtime-summary.ts +5 -49
  95. package/src/utils/io.ts +10 -0
  96. package/src/utils/retry.ts +1 -1
  97. package/src/utils/shadow-fingerprint.ts +2 -2
  98. package/src/utils/workspace-resolver.ts +50 -0
  99. package/templates/langs/en/core/AGENTS.md +2 -2
  100. package/templates/langs/en/core/BOOT.md +1 -1
  101. package/templates/langs/en/core/HEARTBEAT.md +2 -2
  102. package/templates/langs/en/skills/ai-sprint-orchestration/references/agent-registry.json +1 -72
  103. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +6 -6
  104. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +6 -6
  105. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +2 -12
  106. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +2 -12
  107. package/templates/langs/en/skills/ai-sprint-orchestration/runtime/.gitignore +2 -2
  108. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/run.mjs +51 -15
  109. package/templates/langs/en/skills/evolve-task/SKILL.md +1 -1
  110. package/templates/langs/en/skills/pd-cli-operator/SKILL.md +67 -0
  111. package/templates/langs/en/skills/pd-diagnostician/SKILL.md +1 -1
  112. package/templates/langs/en/skills/pd-mentor/SKILL.md +1 -1
  113. package/templates/langs/en/skills/pd-pain-signal/SKILL.md +17 -39
  114. package/templates/langs/en/skills/pd-runtime-v2/SKILL.md +61 -0
  115. package/templates/langs/zh/core/AGENTS.md +2 -2
  116. package/templates/langs/zh/core/BOOT.md +1 -1
  117. package/templates/langs/zh/core/HEARTBEAT.md +2 -2
  118. package/templates/langs/zh/skills/ai-sprint-orchestration/references/agent-registry.json +1 -72
  119. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +6 -6
  120. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +6 -6
  121. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/nocturnal-trinity-quality-enhancement.json +8 -8
  122. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +2 -12
  123. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +2 -12
  124. package/templates/langs/zh/skills/ai-sprint-orchestration/runtime/.gitignore +2 -2
  125. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +51 -15
  126. package/templates/langs/zh/skills/ai-sprint-orchestration/test/run.test.mjs +21 -5
  127. package/templates/langs/zh/skills/evolve-task/SKILL.md +2 -2
  128. package/templates/langs/zh/skills/pd-cli-operator/SKILL.md +67 -0
  129. package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +1 -1
  130. package/templates/langs/zh/skills/pd-mentor/SKILL.md +1 -1
  131. package/templates/langs/zh/skills/pd-pain-signal/SKILL.md +17 -38
  132. package/templates/langs/zh/skills/pd-runtime-v2/SKILL.md +61 -0
  133. package/tests/build-artifacts.test.ts +1 -3
  134. package/tests/commands/evolution-status.test.ts +0 -118
  135. package/tests/core/bootstrap-rules.test.ts +1 -1
  136. package/tests/core/config.test.ts +1 -1
  137. package/tests/core/event-log.test.ts +35 -0
  138. package/tests/core/evolution-engine.test.ts +610 -0
  139. package/tests/core/file-store.test.ts +102 -0
  140. package/tests/core/focus-history.test.ts +203 -11
  141. package/tests/core/merge-gate-audit.test.ts +2 -169
  142. package/tests/core/model-deployment-registry.test.ts +7 -1
  143. package/tests/core/model-training-registry.test.ts +19 -0
  144. package/tests/core/observability.test.ts +0 -1
  145. package/tests/core/pain-diagnostic-gate.test.ts +498 -0
  146. package/tests/core/pain.test.ts +0 -1
  147. package/tests/core/principle-internalization/deprecated-readiness.test.ts +2 -2
  148. package/tests/core/principle-internalization/lifecycle-metrics.test.ts +2 -2
  149. package/tests/core/principle-internalization/{internalization-routing-policy.test.ts → lifecycle-routing-policy.test.ts} +6 -6
  150. package/tests/core/principle-internalization/lineage-source-retired.test.ts +56 -0
  151. package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +1 -23
  152. package/tests/core/principle-tree-ledger-adapter.test.ts +253 -0
  153. package/tests/core/reflection-context.test.ts +0 -14
  154. package/tests/core/replay-engine.test.ts +127 -215
  155. package/tests/core/rule-host-helpers.test.ts +2 -2
  156. package/tests/core/rule-implementation-runtime.test.ts +0 -27
  157. package/tests/core/workflow-funnel-loader.test.ts +162 -0
  158. package/tests/core/workspace-dir-validation.test.ts +8 -1
  159. package/tests/core-anti-growth.test.ts +192 -0
  160. package/tests/hook-workspace-nextaction-contract.test.ts +42 -0
  161. package/tests/hooks/confirm-first-gate.test.ts +333 -0
  162. package/tests/hooks/gate-auto-correct-shadow.test.ts +310 -0
  163. package/tests/hooks/gate-auto-correct.test.ts +665 -0
  164. package/tests/hooks/gate-rule-host-pipeline.test.ts +2 -1
  165. package/tests/hooks/pain.test.ts +269 -12
  166. package/tests/hooks/prompt-characterization.test.ts +500 -0
  167. package/tests/hooks/prompt-size-guard.test.ts +32 -17
  168. package/tests/hooks/runtime-v2-prompt-activation.test.ts +869 -0
  169. package/tests/index.test.ts +94 -1
  170. package/tests/integration/auto-entry-gate.test.ts +248 -0
  171. package/tests/integration/internalization-trigger-guard.test.ts +69 -0
  172. package/tests/integration/m8-legacy-paths.test.ts +63 -0
  173. package/tests/integration/runtime-v2-pain-guard.test.ts +125 -0
  174. package/tests/plugin-config-resolution-cutover.test.ts +359 -0
  175. package/tests/runtime-v2-discovery-guard.test.ts +154 -0
  176. package/tests/service/central-database.test.ts +457 -0
  177. package/tests/service/evolution-worker.correction-observer.test.ts +173 -0
  178. package/tests/service/evolution-worker.timeout.test.ts +11 -129
  179. package/tests/service/internalization-trigger-adapter.test.ts +251 -0
  180. package/tests/service/monitoring-query-service.test.ts +1 -47
  181. package/tests/service/queue-io.test.ts +1 -62
  182. package/tests/service/runtime-summary-service.test.ts +3 -1
  183. package/tests/service/workflow-watchdog.test.ts +0 -91
  184. package/tests/utils/file-lock.test.ts +5 -3
  185. package/tests/utils/session-key.test.ts +52 -0
  186. package/tests/utils/subagent-probe.test.ts +48 -1
  187. package/vitest.config.ts +4 -11
  188. package/.planning/codebase/ARCHITECTURE.md +0 -157
  189. package/.planning/codebase/CONCERNS.md +0 -145
  190. package/.planning/codebase/CONVENTIONS.md +0 -148
  191. package/.planning/codebase/INTEGRATIONS.md +0 -81
  192. package/.planning/codebase/STACK.md +0 -87
  193. package/.planning/codebase/STRUCTURE.md +0 -193
  194. package/.planning/codebase/TESTING.md +0 -243
  195. package/.planning/phases/01-basic-visualization/01-GAP-CLOSURE-VERIFICATION.md +0 -113
  196. package/docs/COMMAND_REFERENCE.md +0 -76
  197. package/docs/COMMAND_REFERENCE_EN.md +0 -79
  198. package/scripts/build-web.mjs +0 -46
  199. package/scripts/diagnose-nocturnal.mjs +0 -537
  200. package/scripts/seed-nocturnal-scenarios.mjs +0 -384
  201. package/src/commands/nocturnal-review.ts +0 -322
  202. package/src/commands/nocturnal-rollout.ts +0 -790
  203. package/src/commands/nocturnal-train.ts +0 -986
  204. package/src/commands/pd-reflect.ts +0 -88
  205. package/src/core/adaptive-thresholds.ts +0 -478
  206. package/src/core/diagnostician-task-store.ts +0 -192
  207. package/src/core/nocturnal-arbiter.ts +0 -715
  208. package/src/core/nocturnal-artifact-lineage.ts +0 -116
  209. package/src/core/nocturnal-artificer.ts +0 -257
  210. package/src/core/nocturnal-candidate-scoring.ts +0 -530
  211. package/src/core/nocturnal-compliance.ts +0 -1146
  212. package/src/core/nocturnal-dataset.ts +0 -763
  213. package/src/core/nocturnal-executability.ts +0 -428
  214. package/src/core/nocturnal-export.ts +0 -499
  215. package/src/core/nocturnal-paths.ts +0 -240
  216. package/src/core/nocturnal-reasoning-deriver.ts +0 -343
  217. package/src/core/nocturnal-rule-implementation-validator.ts +0 -246
  218. package/src/core/nocturnal-snapshot-contract.ts +0 -99
  219. package/src/core/nocturnal-trajectory-extractor.ts +0 -512
  220. package/src/core/nocturnal-trinity-types.ts +0 -218
  221. package/src/core/nocturnal-trinity.ts +0 -2680
  222. package/src/core/principle-internalization/deprecated-readiness.ts +0 -93
  223. package/src/core/principle-internalization/internalization-routing-policy.ts +0 -208
  224. package/src/core/principle-internalization/lifecycle-metrics.ts +0 -152
  225. package/src/http/principles-console-route.ts +0 -709
  226. package/src/service/central-health-service.ts +0 -49
  227. package/src/service/central-overview-service.ts +0 -138
  228. package/src/service/control-ui-query-service.ts +0 -900
  229. package/src/service/cooldown-strategy.ts +0 -97
  230. package/src/service/evolution-pain-context.ts +0 -79
  231. package/src/service/evolution-query-service.ts +0 -407
  232. package/src/service/health-query-service.ts +0 -1038
  233. package/src/service/nocturnal-config.ts +0 -214
  234. package/src/service/nocturnal-runtime.ts +0 -734
  235. package/src/service/nocturnal-service.ts +0 -1605
  236. package/src/service/nocturnal-target-selector.ts +0 -545
  237. package/src/service/sleep-cycle.ts +0 -157
  238. package/src/service/startup-reconciler.ts +0 -112
  239. package/src/service/subagent-workflow/correction-observer-types.ts +0 -82
  240. package/src/service/subagent-workflow/correction-observer-workflow-manager.ts +0 -250
  241. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +0 -1
  242. package/src/service/subagent-workflow/dynamic-timeout.ts +0 -30
  243. package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +0 -268
  244. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +0 -795
  245. package/src/service/subagent-workflow/runtime-direct-driver.ts +0 -268
  246. package/src/service/subagent-workflow/workflow-manager-base.ts +0 -580
  247. package/src/tools/write-pain-flag.ts +0 -215
  248. package/tests/commands/nocturnal-review.test.ts +0 -448
  249. package/tests/commands/nocturnal-train.test.ts +0 -97
  250. package/tests/commands/pd-reflect.test.ts +0 -49
  251. package/tests/core/adaptive-thresholds.test.ts +0 -261
  252. package/tests/core/nocturnal-arbiter.test.ts +0 -559
  253. package/tests/core/nocturnal-artifact-lineage.test.ts +0 -53
  254. package/tests/core/nocturnal-artificer.test.ts +0 -241
  255. package/tests/core/nocturnal-candidate-scoring.test.ts +0 -532
  256. package/tests/core/nocturnal-compliance-p-principles.test.ts +0 -133
  257. package/tests/core/nocturnal-compliance.test.ts +0 -646
  258. package/tests/core/nocturnal-dataset.test.ts +0 -892
  259. package/tests/core/nocturnal-e2e.test.ts +0 -234
  260. package/tests/core/nocturnal-executability.test.ts +0 -357
  261. package/tests/core/nocturnal-export.test.ts +0 -517
  262. package/tests/core/nocturnal-reasoning-deriver.test.ts +0 -372
  263. package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +0 -428
  264. package/tests/core/nocturnal-rule-implementation-validator.test.ts +0 -127
  265. package/tests/core/nocturnal-snapshot-contract.test.ts +0 -121
  266. package/tests/core/nocturnal-trajectory-extractor.test.ts +0 -634
  267. package/tests/core/nocturnal-trinity.test.ts +0 -2053
  268. package/tests/core/pain-auto-repair.test.ts +0 -96
  269. package/tests/core/pain-integration.test.ts +0 -510
  270. package/tests/fixtures/nocturnal-reviewed-subset.json +0 -183
  271. package/tests/http/principles-console-route.test.ts +0 -162
  272. package/tests/integration/chaos-resilience.test.ts +0 -348
  273. package/tests/integration/empathy-workflow-integration.test.ts +0 -626
  274. package/tests/integration/pain-diagnostician-loop.e2e.test.ts +0 -380
  275. package/tests/service/control-ui-query-service.test.ts +0 -121
  276. package/tests/service/cooldown-strategy.test.ts +0 -164
  277. package/tests/service/data-endpoints-regression.test.ts +0 -834
  278. package/tests/service/empathy-observer-workflow-manager.test.ts +0 -175
  279. package/tests/service/evolution-worker.nocturnal.test.ts +0 -601
  280. package/tests/service/nocturnal-runtime-hardening.test.ts +0 -118
  281. package/tests/service/nocturnal-runtime.test.ts +0 -473
  282. package/tests/service/nocturnal-service-code-candidate.test.ts +0 -330
  283. package/tests/service/nocturnal-target-selector.test.ts +0 -615
  284. package/tests/service/startup-reconciler.test.ts +0 -148
  285. package/tests/tools/write-pain-flag.test.ts +0 -358
  286. package/ui/src/App.tsx +0 -45
  287. package/ui/src/api.ts +0 -220
  288. package/ui/src/charts.tsx +0 -955
  289. package/ui/src/components/ErrorState.tsx +0 -6
  290. package/ui/src/components/Loading.tsx +0 -13
  291. package/ui/src/components/ProtectedRoute.tsx +0 -12
  292. package/ui/src/components/Shell.tsx +0 -91
  293. package/ui/src/components/WorkspaceConfig.tsx +0 -178
  294. package/ui/src/components/index.ts +0 -5
  295. package/ui/src/context/auth.tsx +0 -80
  296. package/ui/src/context/theme.tsx +0 -66
  297. package/ui/src/hooks/useAutoRefresh.ts +0 -39
  298. package/ui/src/i18n/ui.ts +0 -473
  299. package/ui/src/main.tsx +0 -16
  300. package/ui/src/pages/EvolutionPage.tsx +0 -333
  301. package/ui/src/pages/FeedbackPage.tsx +0 -138
  302. package/ui/src/pages/GateMonitorPage.tsx +0 -136
  303. package/ui/src/pages/LoginPage.tsx +0 -89
  304. package/ui/src/pages/OverviewPage.tsx +0 -599
  305. package/ui/src/pages/SamplesPage.tsx +0 -174
  306. package/ui/src/pages/ThinkingModelsPage.tsx +0 -702
  307. package/ui/src/styles.css +0 -2020
  308. package/ui/src/types.ts +0 -384
  309. package/ui/src/utils/format.ts +0 -15
@@ -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';