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
@@ -1,108 +1,8 @@
1
1
  /**
2
- * Template Generator for Principle Compiler
2
+ * Template Generator Re-export from @principles/core
3
3
  *
4
- * Generates RuleHost sandbox code from PainPattern descriptors.
5
- * Produces self-contained JS modules with `export const meta` and
6
- * `export function evaluate(input)` that can be loaded at runtime.
7
- *
8
- * SECURITY: All interpolated values use JSON.stringify or safe helpers
9
- * to prevent code injection through principleId, coversCondition, or regex patterns.
10
- */
11
-
12
- export interface PainPattern {
13
- toolName: string;
14
- pathRegex?: string;
15
- commandRegex?: string;
16
- contentRegex?: string;
17
- errorType?: string;
18
- }
19
-
20
- /**
21
- * Derives the auto-rule display name from a principle ID.
22
- */
23
- function toAutoName(principleId: string): string {
24
- return `Auto_${principleId}`;
25
- }
26
-
27
- /**
28
- * Derives the auto-rule ID from a principle ID.
29
- * Must match ledger-registrar convention: "P_066" => "R_P_066_auto"
30
- */
31
- function toAutoRuleId(principleId: string): string {
32
- return `R_${principleId}_auto`;
33
- }
34
-
35
- /**
36
- * Builds a single `if` branch for a pain pattern.
37
- *
38
- * SECURITY: Uses `new RegExp(JSON.stringify(...))` instead of regex literals
39
- * to prevent code injection through pathRegex/commandRegex/contentRegex values.
40
- * principleId in reason uses JSON.stringify to prevent string breakout.
4
+ * PRI-44: Pure template generation logic moved to core.
5
+ * This file re-exports for backward compatibility.
41
6
  */
42
- function buildBranch(principleId: string, pattern: PainPattern): string {
43
- const conditions: string[] = [];
44
-
45
- conditions.push(`input.action.toolName === ${JSON.stringify(pattern.toolName)}`);
46
-
47
- if (pattern.pathRegex) {
48
- conditions.push(`new RegExp(${JSON.stringify(pattern.pathRegex)}).test(input.action.normalizedPath || '')`);
49
- }
50
-
51
- if (pattern.commandRegex) {
52
- conditions.push(`new RegExp(${JSON.stringify(pattern.commandRegex)}).test(input.action.paramsSummary.command || '')`);
53
- }
54
-
55
- if (pattern.contentRegex) {
56
- conditions.push(
57
- `new RegExp(${JSON.stringify(pattern.contentRegex)}).test(input.action.paramsSummary.content || input.action.paramsSummary.new_string || '')`,
58
- );
59
- }
60
-
61
- const guard = conditions.join(' && ');
62
- const reason = `[${principleId}] Blocked by auto-generated rule`;
63
-
64
- return (
65
- ` if (${guard}) {\n` +
66
- ` return { decision: 'block', matched: true, reason: ${JSON.stringify(reason)} };\n` +
67
- ` }`
68
- );
69
- }
70
-
71
- /**
72
- * Generates sandbox-ready JS code from a principle ID and pain patterns.
73
- *
74
- * Returns `null` when `patterns` is empty.
75
- */
76
- export function generateFromTemplate(
77
- principleId: string,
78
- coversCondition: string,
79
- patterns: PainPattern[],
80
- ): string | null {
81
- if (patterns.length === 0) {
82
- return null;
83
- }
84
-
85
- const name = toAutoName(principleId);
86
- const ruleId = toAutoRuleId(principleId);
87
- const compiledAt = new Date().toISOString();
88
-
89
- const branches = patterns
90
- .map((p) => buildBranch(principleId, p))
91
- .join('\n');
92
7
 
93
- return (
94
- `// Auto-generated by Principle Compiler\n` +
95
- `export const meta = {\n` +
96
- ` name: ${JSON.stringify(name)},\n` +
97
- ` version: '1.0.0',\n` +
98
- ` ruleId: ${JSON.stringify(ruleId)},\n` +
99
- ` coversCondition: ${JSON.stringify(coversCondition)},\n` +
100
- ` compiledAt: ${JSON.stringify(compiledAt)},\n` +
101
- ` sourcePrincipleId: ${JSON.stringify(principleId)},\n` +
102
- `};\n\n` +
103
- `export function evaluate(input) {\n` +
104
- `${branches}\n` +
105
- ` return { matched: false };\n` +
106
- `}\n`
107
- );
108
- }
8
+ export { generateFromTemplate, type PainPattern } from '@principles/core/runtime-v2';
@@ -1,208 +1,16 @@
1
1
  /**
2
2
  * Principle Injection — Budget-Aware Principle Selection
3
- * ========================================================
4
3
  *
5
- * PURPOSE: Select principles for prompt injection within a character budget,
6
- * prioritizing by priority tier (P0 > P1 > P2) and recency, while ensuring
7
- * at least one P0 principle is included when available.
4
+ * Phase: PRI-75 Prompt Injection SDK Migration Phase 2
8
5
  *
9
- * DESIGN:
10
- * - Sorts principles by priority (P0 first, then P1, then P2)
11
- * - Within same priority, sorts by recency (createdAt descending)
12
- * - Selects principles until the cumulative character budget is exceeded
13
- * - Guarantees at least one P0 principle is included if any exist
14
- * - Returns the selected principles and total character usage
15
- *
16
- * This replaces the previous hardcoded slice(-3)/slice(0,5) approach in
17
- * prompt.ts with a budget-aware, priority-respecting selection algorithm.
18
- */
19
-
20
- import type { PrinciplePriority } from '../types/principle-tree-schema.js';
21
-
22
- // ---------------------------------------------------------------------------
23
- // Types
24
- // ---------------------------------------------------------------------------
25
-
26
- /**
27
- * Minimal principle shape required for injection selection.
28
- * Accepts both evolution-types.Principle and principle-tree-schema.Principle.
29
- */
30
- export interface InjectablePrinciple {
31
- id: string;
32
- text: string;
33
- /** Priority level. Defaults to 'P1' if not set by the source. */
34
- priority?: PrinciplePriority;
35
- createdAt: string;
36
- }
37
-
38
- /**
39
- * Result of principle selection for injection.
40
- */
41
- export interface PrincipleSelectionResult {
42
- /** Selected principles in injection order (priority-first, then recency) */
43
- selected: InjectablePrinciple[];
44
- /** Total character count of selected principles' formatted output */
45
- totalChars: number;
46
- /** Number of principles by priority tier */
47
- breakdown: {
48
- p0: number;
49
- p1: number;
50
- p2: number;
51
- };
52
- /** Whether at least one P0 principle was included */
53
- hasP0: boolean;
54
- /** Whether the selection was truncated due to budget */
55
- wasTruncated: boolean;
56
- }
57
-
58
- // ---------------------------------------------------------------------------
59
- // Priority Ordering
60
- // ---------------------------------------------------------------------------
61
-
62
- const PRIORITY_ORDER: Record<PrinciplePriority, number> = {
63
- P0: 0,
64
- P1: 1,
65
- P2: 2,
66
- };
67
-
68
- /**
69
- * Compare two principles for sorting.
70
- * Primary: priority (P0 < P1 < P2 — lower is higher priority).
71
- * Secondary: recency (newer createdAt first).
72
- */
73
- function comparePrinciples(a: InjectablePrinciple, b: InjectablePrinciple): number {
74
- const priorityA = PRIORITY_ORDER[a.priority ?? 'P1'] ?? 99;
75
- const priorityB = PRIORITY_ORDER[b.priority ?? 'P1'] ?? 99;
76
-
77
- if (priorityA !== priorityB) {
78
- return priorityA - priorityB;
79
- }
80
-
81
- // Same priority: sort by recency (newer first)
82
- return b.createdAt.localeCompare(a.createdAt);
83
- }
84
-
85
- // ---------------------------------------------------------------------------
86
- // Formatting
87
- // ---------------------------------------------------------------------------
88
-
89
- /**
90
- * Format a single principle for injection.
91
- * Returns the formatted string including ID and text.
92
- *
93
- * Format: "- [ID] text" (matches existing prompt.ts format)
6
+ * This file is now a thin re-export layer.
7
+ * All pure logic lives in @principles/core/prompt-builder/principle-selection.ts.
94
8
  */
95
- export function formatPrinciple(p: InjectablePrinciple): string {
96
- return `- [${p.id}] ${p.text}`;
97
- }
98
9
 
99
- /**
100
- * Calculate the character length of a formatted principle, including newline.
101
- */
102
- function formattedLength(p: InjectablePrinciple): number {
103
- return formatPrinciple(p).length + 1; // +1 for newline separator
104
- }
105
-
106
- // ---------------------------------------------------------------------------
107
- // Selection Algorithm
108
- // ---------------------------------------------------------------------------
109
-
110
- /**
111
- * Select principles for prompt injection within a character budget.
112
- *
113
- * Algorithm:
114
- * 1. Sort all principles by priority (P0 > P1 > P2), then by recency
115
- * 2. Iterate through sorted principles, accumulating character count
116
- * 3. Stop when adding the next principle would exceed budgetChars
117
- * 4. Ensure at least one P0 principle is included (even if it exceeds budget)
118
- *
119
- * @param principles - All available principles to select from
120
- * @param budgetChars - Maximum character budget for formatted output
121
- * @returns Selection result with chosen principles and metadata
122
- */
123
- export function selectPrinciplesForInjection(
124
- principles: InjectablePrinciple[],
125
- budgetChars: number,
126
- ): PrincipleSelectionResult {
127
- if (principles.length === 0) {
128
- return {
129
- selected: [],
130
- totalChars: 0,
131
- breakdown: { p0: 0, p1: 0, p2: 0 },
132
- hasP0: false,
133
- wasTruncated: false,
134
- };
135
- }
136
-
137
- // Sort by priority then recency
138
- const sorted = [...principles].sort(comparePrinciples);
139
-
140
- const selected: InjectablePrinciple[] = [];
141
- let totalChars = 0;
142
- let p0Included = false;
143
- let wasTruncated = false;
144
-
145
- for (const principle of sorted) {
146
- const cost = formattedLength(principle);
147
-
148
- // Check if adding this principle would exceed budget
149
- if (totalChars + cost > budgetChars) {
150
- // Special case: if no P0 has been included yet, force-include the first P0
151
- // even if it exceeds the budget (P0 principles are critical)
152
- if (!p0Included && principle.priority === 'P0') {
153
- selected.push(principle);
154
- totalChars += cost;
155
- p0Included = true;
156
- wasTruncated = true;
157
- // Continue to try to fit more principles after this forced inclusion
158
- continue;
159
- }
160
-
161
- wasTruncated = true;
162
- break;
163
- }
164
-
165
- selected.push(principle);
166
- totalChars += cost;
167
- if (principle.priority === 'P0') {
168
- p0Included = true;
169
- }
170
- }
171
-
172
- // Safety net: if we went through all principles and still no P0 included
173
- // (because P0 was beyond budget threshold), force-include the first P0
174
- if (!p0Included) {
175
- const firstP0 = sorted.find(p => p.priority === 'P0');
176
- if (firstP0 && !selected.includes(firstP0)) {
177
- // Insert P0 at the beginning of selected (highest priority)
178
- selected.unshift(firstP0);
179
- totalChars += formattedLength(firstP0);
180
- p0Included = true;
181
- }
182
- }
183
-
184
- const breakdown = {
185
- p0: selected.filter(p => (p.priority ?? 'P1') === 'P0').length,
186
- p1: selected.filter(p => (p.priority ?? 'P1') === 'P1').length,
187
- p2: selected.filter(p => (p.priority ?? 'P1') === 'P2').length,
188
- };
189
-
190
- return {
191
- selected,
192
- totalChars,
193
- breakdown,
194
- hasP0: p0Included,
195
- wasTruncated,
196
- };
197
- }
198
-
199
- // ---------------------------------------------------------------------------
200
- // Default Budget
201
- // ---------------------------------------------------------------------------
202
-
203
- /**
204
- * Default character budget for principle injection.
205
- * 4000 characters is ~800 tokens, leaving ample room for other prompt sections
206
- * within the 10K character injection limit.
207
- */
208
- export const DEFAULT_PRINCIPLE_BUDGET = 4000;
10
+ // Re-exported from core for backward compatibility with existing imports
11
+ export {
12
+ formatPrinciple,
13
+ selectPrinciplesForInjection,
14
+ DEFAULT_PRINCIPLE_BUDGET,
15
+ } from '@principles/core/prompt-builder';
16
+ export type { InjectablePrinciple, PrincipleSelectionResult } from '@principles/core/prompt-builder';
@@ -0,0 +1,42 @@
1
+ import type { LifecycleDatasource } from '@principles/core/runtime-v2';
2
+ import type { LedgerTreeStore, ReplayReport, ArtifactLineageRecord } from '@principles/core/runtime-v2';
3
+ import { loadLedger } from '../principle-tree-ledger.js';
4
+ import { ReplayEngine } from '../replay-engine.js';
5
+
6
+ export class LineageSourceRetiredError extends Error {
7
+ constructor() {
8
+ super(
9
+ 'Artifact lineage source retired in PRI-230. ' +
10
+ 'The nocturnal-artifact-lineage module has been deleted; ' +
11
+ 'this datasource cannot provide lineage records. ' +
12
+ 'Callers must handle this error explicitly rather than interpreting an empty result as "no lineage".'
13
+ );
14
+ this.name = 'LineageSourceRetiredError';
15
+ }
16
+ }
17
+
18
+ export class FilesystemLifecycleDatasource implements LifecycleDatasource {
19
+ private _engine?: ReplayEngine;
20
+
21
+ constructor(
22
+ private readonly workspaceDir: string,
23
+ private readonly stateDir: string,
24
+ ) {}
25
+
26
+ private get engine(): ReplayEngine {
27
+ if (!this._engine) this._engine = new ReplayEngine(this.workspaceDir, this.stateDir);
28
+ return this._engine;
29
+ }
30
+
31
+ loadLedger(): LedgerTreeStore {
32
+ return loadLedger(this.stateDir).tree as unknown as LedgerTreeStore;
33
+ }
34
+
35
+ listReplayReports(implementationId: string): ReplayReport[] {
36
+ return this.engine.listReports(implementationId);
37
+ }
38
+
39
+ listLineageRecords(_kind: 'behavioral-sample' | 'rule-implementation-candidate'): ArtifactLineageRecord[] {
40
+ throw new LineageSourceRetiredError();
41
+ }
42
+ }
@@ -1,243 +1,40 @@
1
- import { loadLedger, type LedgerPrinciple, type LedgerRule } from '../principle-tree-ledger.js';
2
- import { listArtifactLineageRecords, type ArtifactLineageRecord } from '../nocturnal-artifact-lineage.js';
3
- import { ReplayEngine, type ClassificationSummary, type ReplayReport } from '../replay-engine.js';
4
- import type { Implementation, ImplementationLifecycleState } from '../../types/principle-tree-schema.js';
5
-
6
- export interface LifecycleClassificationTotals {
7
- total: number;
8
- passed: number;
9
- failed: number;
10
- }
11
-
12
- export interface RuleReplayEvidence {
13
- reportCount: number;
14
- latestReports: ReplayReport[];
15
- painNegative: LifecycleClassificationTotals;
16
- successPositive: LifecycleClassificationTotals;
17
- principleAnchor: LifecycleClassificationTotals;
18
- passingImplementationIds: string[];
19
- failingImplementationIds: string[];
20
- needsReviewImplementationIds: string[];
21
- }
22
-
23
- export interface RuleLiveEvidence {
24
- activeCount: number;
25
- candidateCount: number;
26
- disabledCount: number;
27
- archivedCount: number;
28
- durablePenaltyCount: number;
29
- rollbackEvidenceCount: number;
30
- hasActiveImplementation: boolean;
31
- hasPassingActiveImplementation: boolean;
32
- }
33
-
34
- export interface RuleLineageEvidence {
35
- records: ArtifactLineageRecord[];
36
- distinctPainSignalCount: number;
37
- distinctGateBlockCount: number;
38
- repeatedErrorSignal: number;
39
- latestCreatedAt?: string;
40
- }
41
-
42
- export interface ImplementationLifecycleEvidence {
43
- implementation: Implementation;
44
- latestReplayReport: ReplayReport | null;
45
- replayHistoryCount: number;
46
- lineageRecords: ArtifactLineageRecord[];
47
- }
48
-
49
- export interface RuleLifecycleEvidence {
50
- rule: LedgerRule;
51
- implementations: ImplementationLifecycleEvidence[];
52
- replayEvidence: RuleReplayEvidence;
53
- liveEvidence: RuleLiveEvidence;
54
- lineageEvidence: RuleLineageEvidence;
55
- }
56
-
57
- export interface PrincipleLifecycleEvidence {
58
- principle: LedgerPrinciple;
59
- rules: RuleLifecycleEvidence[];
60
- summary: {
61
- replayReportCount: number;
62
- activeImplementationCount: number;
63
- candidateImplementationCount: number;
64
- disabledImplementationCount: number;
65
- archivedImplementationCount: number;
66
- distinctPainSignalCount: number;
67
- distinctGateBlockCount: number;
68
- repeatedErrorSignal: number;
69
- };
70
- }
71
-
72
- export interface LifecycleReadModel {
73
- generatedAt: string;
74
- principles: PrincipleLifecycleEvidence[];
75
- }
76
-
77
- function toClassificationTotals(summary: ClassificationSummary[]): LifecycleClassificationTotals {
78
- return summary.reduce<LifecycleClassificationTotals>(
79
- (totals, entry) => ({
80
- total: totals.total + entry.total,
81
- passed: totals.passed + entry.passed,
82
- failed: totals.failed + entry.failed,
83
- }),
84
- { total: 0, passed: 0, failed: 0 },
85
- );
86
- }
87
-
88
- function countByLifecycle(implementations: Implementation[], lifecycleState: ImplementationLifecycleState): number {
89
- return implementations.filter((implementation) => implementation.lifecycleState === lifecycleState).length;
90
- }
91
-
92
- function hasDurablePenalty(implementation: Implementation): boolean {
93
- if (implementation.lifecycleState === 'disabled' || implementation.lifecycleState === 'archived') {
94
- return true;
95
- }
96
-
97
- return typeof implementation.disabledReason === 'string' && implementation.disabledReason.trim().length > 0;
98
- }
99
-
100
- function hasRollbackEvidence(implementation: Implementation): boolean {
101
- return typeof implementation.previousActive === 'string' && implementation.previousActive.length > 0;
102
- }
103
-
104
- function createRuleReplayEvidence(reports: { implementationId: string; report: ReplayReport }[]): RuleReplayEvidence {
105
- return {
106
- reportCount: reports.length,
107
- latestReports: reports.map((entry) => entry.report),
108
- painNegative: toClassificationTotals(reports.map((entry) => entry.report.replayResults.painNegative)),
109
- successPositive: toClassificationTotals(reports.map((entry) => entry.report.replayResults.successPositive)),
110
- principleAnchor: toClassificationTotals(reports.map((entry) => entry.report.replayResults.principleAnchor)),
111
- passingImplementationIds: reports
112
- .filter((entry) => entry.report.overallDecision === 'pass')
113
- .map((entry) => entry.implementationId),
114
- failingImplementationIds: reports
115
- .filter((entry) => entry.report.overallDecision === 'fail')
116
- .map((entry) => entry.implementationId),
117
- needsReviewImplementationIds: reports
118
- .filter((entry) => entry.report.overallDecision === 'needs-review')
119
- .map((entry) => entry.implementationId),
120
- };
121
- }
122
-
123
- function createRuleLineageEvidence(records: ArtifactLineageRecord[]): RuleLineageEvidence {
124
- const painIds = new Set<string>();
125
- const gateBlockIds = new Set<string>();
126
-
127
- for (const record of records) {
128
- for (const painId of record.sourcePainIds) {
129
- painIds.add(painId);
130
- }
131
- for (const gateBlockId of record.sourceGateBlockIds) {
132
- gateBlockIds.add(gateBlockId);
133
- }
134
- }
135
-
136
- const latestCreatedAt =
137
- records.length > 0
138
- ? records
139
- .map((record) => record.createdAt)
140
- .sort((left, right) => new Date(right).getTime() - new Date(left).getTime())[0]
141
- : undefined;
142
-
143
- return {
144
- records,
145
- distinctPainSignalCount: painIds.size,
146
- distinctGateBlockCount: gateBlockIds.size,
147
- repeatedErrorSignal: painIds.size + gateBlockIds.size,
148
- latestCreatedAt,
149
- };
150
- }
151
-
152
- function createRuleLiveEvidence(
153
- implementations: Implementation[],
154
- replayEvidence: RuleReplayEvidence,
155
- ): RuleLiveEvidence {
156
- const activeImplementations = implementations.filter((implementation) => implementation.lifecycleState === 'active');
157
-
158
- return {
159
- activeCount: countByLifecycle(implementations, 'active'),
160
- candidateCount: countByLifecycle(implementations, 'candidate'),
161
- disabledCount: countByLifecycle(implementations, 'disabled'),
162
- archivedCount: countByLifecycle(implementations, 'archived'),
163
- durablePenaltyCount: implementations.filter((implementation) => hasDurablePenalty(implementation)).length,
164
- rollbackEvidenceCount: implementations.filter((implementation) => hasRollbackEvidence(implementation)).length,
165
- hasActiveImplementation: activeImplementations.length > 0,
166
- hasPassingActiveImplementation: activeImplementations.some((implementation) =>
167
- replayEvidence.passingImplementationIds.includes(implementation.id),
168
- ),
169
- };
170
- }
171
-
172
- export function buildLifecycleReadModel(workspaceDir: string, stateDir: string): LifecycleReadModel {
173
- const ledger = loadLedger(stateDir);
174
- const replayEngine = new ReplayEngine(workspaceDir, stateDir);
175
- const lineageRecords = listArtifactLineageRecords(workspaceDir, 'rule-implementation-candidate');
176
-
177
- const principles = Object.values(ledger.tree.principles)
178
- .map((principle): PrincipleLifecycleEvidence => {
179
- const rules = principle.ruleIds
180
- .map((ruleId) => ledger.tree.rules[ruleId])
181
- .filter((rule): rule is LedgerRule => rule !== undefined)
182
- .map((rule): RuleLifecycleEvidence => {
183
- const implementations = rule.implementationIds
184
- .map((implementationId) => ledger.tree.implementations[implementationId])
185
- .filter((implementation): implementation is Implementation => implementation !== undefined);
186
-
187
- const implementationEvidence: ImplementationLifecycleEvidence[] = implementations.map((implementation) => {
188
- const reports = replayEngine.listReports(implementation.id);
189
- const implementationLineage = lineageRecords.filter(
190
- (record) => record.ruleId === rule.id || record.implementationId === implementation.id,
191
- );
192
-
193
- return {
194
- implementation,
195
- latestReplayReport: reports[0] ?? null,
196
- replayHistoryCount: reports.length,
197
- lineageRecords: implementationLineage,
198
- };
199
- });
200
-
201
- const replayEvidence = createRuleReplayEvidence(
202
- implementationEvidence
203
- .filter((entry) => entry.latestReplayReport !== null)
204
- .map((entry) => ({
205
- implementationId: entry.implementation.id,
206
- report: entry.latestReplayReport as ReplayReport,
207
- })),
208
- );
209
- const ruleLineageRecords = lineageRecords.filter((record) => record.ruleId === rule.id);
210
- const lineageEvidence = createRuleLineageEvidence(ruleLineageRecords);
211
- const liveEvidence = createRuleLiveEvidence(implementations, replayEvidence);
212
-
213
- return {
214
- rule,
215
- implementations: implementationEvidence,
216
- replayEvidence,
217
- liveEvidence,
218
- lineageEvidence,
219
- };
220
- });
221
-
222
- return {
223
- principle,
224
- rules,
225
- summary: {
226
- replayReportCount: rules.reduce((sum, rule) => sum + rule.replayEvidence.reportCount, 0),
227
- activeImplementationCount: rules.reduce((sum, rule) => sum + rule.liveEvidence.activeCount, 0),
228
- candidateImplementationCount: rules.reduce((sum, rule) => sum + rule.liveEvidence.candidateCount, 0),
229
- disabledImplementationCount: rules.reduce((sum, rule) => sum + rule.liveEvidence.disabledCount, 0),
230
- archivedImplementationCount: rules.reduce((sum, rule) => sum + rule.liveEvidence.archivedCount, 0),
231
- distinctPainSignalCount: rules.reduce((sum, rule) => sum + rule.lineageEvidence.distinctPainSignalCount, 0),
232
- distinctGateBlockCount: rules.reduce((sum, rule) => sum + rule.lineageEvidence.distinctGateBlockCount, 0),
233
- repeatedErrorSignal: rules.reduce((sum, rule) => sum + rule.lineageEvidence.repeatedErrorSignal, 0),
234
- },
235
- };
236
- })
237
- .sort((left, right) => left.principle.id.localeCompare(right.principle.id));
238
-
239
- return {
240
- generatedAt: new Date().toISOString(),
241
- principles,
242
- };
1
+ /**
2
+ * Lifecycle read model re-export facade (PRI-56).
3
+ *
4
+ * All computation lives in @principles/core/runtime-v2.
5
+ * This file re-exports types, the core builder, and provides
6
+ * a backward-compatible path-based wrapper for existing consumers.
7
+ */
8
+
9
+ // Re-export lifecycle types from core (PRI-51)
10
+ export type {
11
+ LifecycleClassificationTotals,
12
+ RuleReplayEvidence,
13
+ RuleLiveEvidence,
14
+ RuleLineageEvidence,
15
+ ImplementationLifecycleEvidence,
16
+ RuleLifecycleEvidence,
17
+ PrincipleLifecycleEvidence,
18
+ LifecycleReadModel,
19
+ } from '@principles/core/runtime-v2';
20
+
21
+ // Re-export core builder (PRI-56)
22
+ export { buildLifecycleReadModel } from '@principles/core/runtime-v2';
23
+
24
+ // Re-export adapter interface (PRI-56)
25
+ export type { LifecycleDatasource } from '@principles/core/runtime-v2';
26
+
27
+ // Re-export filesystem implementation (PRI-56)
28
+ export { FilesystemLifecycleDatasource, LineageSourceRetiredError } from './filesystem-lifecycle-datasource.js';
29
+
30
+ import { buildLifecycleReadModel } from '@principles/core/runtime-v2';
31
+ import { FilesystemLifecycleDatasource } from './filesystem-lifecycle-datasource.js';
32
+
33
+ /**
34
+ * Backward-compatible wrapper — accepts directory paths like the original API.
35
+ * Existing consumers (lifecycle-refresh, evolution-status, nocturnal-service)
36
+ * continue using this without changes.
37
+ */
38
+ export function buildLifecycleReadModelFromPaths(workspaceDir: string, stateDir: string) {
39
+ return buildLifecycleReadModel(new FilesystemLifecycleDatasource(workspaceDir, stateDir));
243
40
  }