principles-disciple 1.11.0 → 1.13.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 (233) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +66 -0
  3. package/esbuild.config.js +1 -1
  4. package/openclaw.plugin.json +4 -4
  5. package/package.json +2 -3
  6. package/run-nocturnal.mjs +30 -0
  7. package/scripts/db-migrate.mjs +170 -0
  8. package/scripts/sync-plugin.mjs +250 -6
  9. package/src/commands/archive-impl.ts +136 -0
  10. package/src/commands/capabilities.ts +4 -2
  11. package/src/commands/context.ts +5 -1
  12. package/src/commands/disable-impl.ts +151 -0
  13. package/src/commands/evolution-status.ts +64 -19
  14. package/src/commands/export.ts +8 -6
  15. package/src/commands/focus.ts +8 -20
  16. package/src/commands/nocturnal-review.ts +5 -7
  17. package/src/commands/nocturnal-rollout.ts +1 -12
  18. package/src/commands/nocturnal-train.ts +21 -47
  19. package/src/commands/pain.ts +10 -5
  20. package/src/commands/principle-rollback.ts +4 -2
  21. package/src/commands/promote-impl.ts +274 -0
  22. package/src/commands/rollback-impl.ts +234 -0
  23. package/src/commands/rollback.ts +6 -3
  24. package/src/commands/samples.ts +2 -0
  25. package/src/commands/thinking-os.ts +3 -4
  26. package/src/commands/workflow-debug.ts +2 -1
  27. package/src/config/errors.ts +1 -0
  28. package/src/core/AGENTS.md +34 -0
  29. package/src/core/adaptive-thresholds.ts +4 -3
  30. package/src/core/code-implementation-storage.ts +241 -0
  31. package/src/core/config.ts +5 -2
  32. package/src/core/control-ui-db.ts +29 -10
  33. package/src/core/detection-funnel.ts +12 -7
  34. package/src/core/diagnostician-task-store.ts +156 -0
  35. package/src/core/dictionary.ts +4 -4
  36. package/src/core/empathy-keyword-matcher.ts +7 -3
  37. package/src/core/empathy-types.ts +13 -2
  38. package/src/core/event-log.ts +14 -6
  39. package/src/core/evolution-engine.ts +27 -31
  40. package/src/core/evolution-logger.ts +3 -2
  41. package/src/core/evolution-reducer.ts +110 -31
  42. package/src/core/evolution-types.ts +10 -0
  43. package/src/core/external-training-contract.ts +1 -0
  44. package/src/core/focus-history.ts +38 -24
  45. package/src/core/hygiene/tracker.ts +10 -6
  46. package/src/core/init.ts +5 -2
  47. package/src/core/migration.ts +3 -3
  48. package/src/core/model-deployment-registry.ts +6 -4
  49. package/src/core/model-training-registry.ts +5 -3
  50. package/src/core/nocturnal-arbiter.ts +13 -14
  51. package/src/core/nocturnal-artifact-lineage.ts +117 -0
  52. package/src/core/nocturnal-artificer.ts +257 -0
  53. package/src/core/nocturnal-candidate-scoring.ts +4 -2
  54. package/src/core/nocturnal-compliance.ts +67 -19
  55. package/src/core/nocturnal-dataset.ts +95 -2
  56. package/src/core/nocturnal-executability.ts +2 -3
  57. package/src/core/nocturnal-export.ts +6 -3
  58. package/src/core/nocturnal-rule-implementation-validator.ts +245 -0
  59. package/src/core/nocturnal-trajectory-extractor.ts +10 -3
  60. package/src/core/nocturnal-trinity.ts +319 -61
  61. package/src/core/pain-context-extractor.ts +29 -15
  62. package/src/core/pain.ts +7 -5
  63. package/src/core/path-resolver.ts +16 -15
  64. package/src/core/paths.ts +2 -1
  65. package/src/core/pd-task-reconciler.ts +463 -0
  66. package/src/core/pd-task-service.ts +42 -0
  67. package/src/core/pd-task-store.ts +77 -0
  68. package/src/core/pd-task-types.ts +128 -0
  69. package/src/core/principle-internalization/deprecated-readiness.ts +91 -0
  70. package/src/core/principle-internalization/internalization-routing-policy.ts +208 -0
  71. package/src/core/principle-internalization/lifecycle-metrics.ts +149 -0
  72. package/src/core/principle-internalization/lifecycle-read-model.ts +243 -0
  73. package/src/core/principle-internalization/lifecycle-refresh.ts +11 -0
  74. package/src/core/principle-internalization/principle-lifecycle-service.ts +167 -0
  75. package/src/core/principle-training-state.ts +95 -370
  76. package/src/core/principle-tree-ledger.ts +733 -0
  77. package/src/core/principle-tree-migration.ts +195 -0
  78. package/src/core/profile.ts +3 -1
  79. package/src/core/promotion-gate.ts +14 -18
  80. package/src/core/replay-engine.ts +562 -0
  81. package/src/core/risk-calculator.ts +6 -4
  82. package/src/core/rule-host-helpers.ts +39 -0
  83. package/src/core/rule-host-types.ts +82 -0
  84. package/src/core/rule-host.ts +245 -0
  85. package/src/core/rule-implementation-runtime.ts +38 -0
  86. package/src/core/schema/db-types.ts +16 -0
  87. package/src/core/schema/index.ts +26 -0
  88. package/src/core/schema/migration-runner.ts +207 -0
  89. package/src/core/schema/migrations/001-init-trajectory.ts +211 -0
  90. package/src/core/schema/migrations/002-init-central.ts +122 -0
  91. package/src/core/schema/migrations/003-init-workflow.ts +55 -0
  92. package/src/core/schema/migrations/004-add-thinking-and-gfi.ts +74 -0
  93. package/src/core/schema/migrations/index.ts +31 -0
  94. package/src/core/schema/schema-definitions.ts +650 -0
  95. package/src/core/session-tracker.ts +6 -4
  96. package/src/core/shadow-observation-registry.ts +6 -3
  97. package/src/core/system-logger.ts +2 -2
  98. package/src/core/thinking-models.ts +182 -46
  99. package/src/core/thinking-os-parser.ts +156 -0
  100. package/src/core/training-program.ts +7 -7
  101. package/src/core/trajectory.ts +42 -36
  102. package/src/core/workspace-context.ts +77 -11
  103. package/src/core/workspace-dir-validation.ts +152 -0
  104. package/src/hooks/AGENTS.md +31 -0
  105. package/src/hooks/bash-risk.ts +3 -1
  106. package/src/hooks/edit-verification.ts +9 -5
  107. package/src/hooks/gate-block-helper.ts +5 -1
  108. package/src/hooks/gate.ts +152 -5
  109. package/src/hooks/gfi-gate.ts +9 -2
  110. package/src/hooks/lifecycle-routing.ts +124 -0
  111. package/src/hooks/lifecycle.ts +12 -12
  112. package/src/hooks/llm.ts +17 -109
  113. package/src/hooks/message-sanitize.ts +5 -3
  114. package/src/hooks/pain.ts +19 -15
  115. package/src/hooks/progressive-trust-gate.ts +7 -1
  116. package/src/hooks/prompt.ts +169 -60
  117. package/src/hooks/subagent.ts +5 -4
  118. package/src/hooks/thinking-checkpoint.ts +2 -0
  119. package/src/hooks/trajectory-collector.ts +15 -12
  120. package/src/http/principles-console-route.ts +31 -68
  121. package/src/i18n/commands.ts +2 -2
  122. package/src/index.ts +130 -40
  123. package/src/service/central-database.ts +131 -43
  124. package/src/service/central-health-service.ts +47 -0
  125. package/src/service/central-overview-service.ts +135 -0
  126. package/src/service/central-sync-service.ts +87 -0
  127. package/src/service/control-ui-query-service.ts +46 -36
  128. package/src/service/event-log-auditor.ts +261 -0
  129. package/src/service/evolution-query-service.ts +23 -22
  130. package/src/service/evolution-worker.ts +565 -261
  131. package/src/service/health-query-service.ts +213 -36
  132. package/src/service/nocturnal-runtime.ts +8 -4
  133. package/src/service/nocturnal-service.ts +503 -59
  134. package/src/service/nocturnal-target-selector.ts +5 -7
  135. package/src/service/runtime-summary-service.ts +2 -1
  136. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +25 -336
  137. package/src/service/subagent-workflow/dynamic-timeout.ts +30 -0
  138. package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +48 -386
  139. package/src/service/subagent-workflow/index.ts +2 -0
  140. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +169 -284
  141. package/src/service/subagent-workflow/runtime-direct-driver.ts +114 -16
  142. package/src/service/subagent-workflow/subagent-error-utils.ts +25 -0
  143. package/src/service/subagent-workflow/types.ts +9 -4
  144. package/src/service/subagent-workflow/workflow-manager-base.ts +573 -0
  145. package/src/service/subagent-workflow/workflow-store.ts +71 -11
  146. package/src/service/trajectory-service.ts +2 -1
  147. package/src/tools/critique-prompt.ts +1 -1
  148. package/src/tools/deep-reflect.ts +175 -209
  149. package/src/tools/model-index.ts +2 -1
  150. package/src/types/event-types.ts +2 -2
  151. package/src/types/principle-tree-schema.ts +29 -23
  152. package/src/utils/file-lock.ts +5 -3
  153. package/src/utils/io.ts +5 -2
  154. package/src/utils/nlp.ts +5 -46
  155. package/src/utils/node-vm-polyfill.ts +11 -0
  156. package/src/utils/plugin-logger.ts +2 -0
  157. package/src/utils/retry.ts +572 -0
  158. package/src/utils/subagent-probe.ts +1 -1
  159. package/templates/langs/en/core/AGENTS.md +0 -13
  160. package/templates/langs/en/core/SOUL.md +1 -31
  161. package/templates/langs/en/core/TOOLS.md +0 -4
  162. package/templates/langs/en/principles/THINKING_OS.md +77 -0
  163. package/templates/langs/en/skills/admin/SKILL.md +0 -1
  164. package/templates/langs/en/skills/evolution-framework-update/SKILL.md +1 -1
  165. package/templates/langs/en/skills/pd-diagnostician/SKILL.md +18 -5
  166. package/templates/langs/zh/core/AGENTS.md +0 -22
  167. package/templates/langs/zh/core/SOUL.md +1 -31
  168. package/templates/langs/zh/core/TOOLS.md +0 -4
  169. package/templates/langs/zh/principles/THINKING_OS.md +77 -0
  170. package/templates/langs/zh/skills/admin/SKILL.md +0 -1
  171. package/templates/langs/zh/skills/evolution-framework-update/SKILL.md +1 -1
  172. package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +25 -4
  173. package/tests/commands/evolution-status.test.ts +119 -0
  174. package/tests/commands/implementation-lifecycle.test.ts +362 -0
  175. package/tests/core/code-implementation-storage.test.ts +398 -0
  176. package/tests/core/evolution-reducer.detector-metadata.test.ts +28 -28
  177. package/tests/core/nocturnal-artifact-lineage.test.ts +53 -0
  178. package/tests/core/nocturnal-artificer.test.ts +241 -0
  179. package/tests/core/nocturnal-compliance-p-principles.test.ts +133 -0
  180. package/tests/core/nocturnal-rule-implementation-validator.test.ts +127 -0
  181. package/tests/core/pd-task-store.test.ts +126 -0
  182. package/tests/core/principle-internalization/deprecated-readiness.test.ts +193 -0
  183. package/tests/core/principle-internalization/internalization-routing-policy.test.ts +212 -0
  184. package/tests/core/principle-internalization/lifecycle-metrics.test.ts +350 -0
  185. package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +211 -0
  186. package/tests/core/principle-training-state.test.ts +228 -1
  187. package/tests/core/principle-tree-ledger.test.ts +423 -0
  188. package/tests/core/regression-v1-9-1.test.ts +265 -0
  189. package/tests/core/replay-engine.test.ts +234 -0
  190. package/tests/core/rule-host-helpers.test.ts +120 -0
  191. package/tests/core/rule-host.test.ts +389 -0
  192. package/tests/core/rule-implementation-runtime.test.ts +64 -0
  193. package/tests/core/workspace-context.test.ts +53 -0
  194. package/tests/core/workspace-dir-validation.test.ts +272 -0
  195. package/tests/hooks/gate-rule-host-pipeline.test.ts +385 -0
  196. package/tests/hooks/pain.test.ts +74 -10
  197. package/tests/hooks/prompt.test.ts +63 -1
  198. package/tests/integration/principle-lifecycle.e2e.test.ts +197 -0
  199. package/tests/integration/tool-hooks-workspace-dir.e2e.test.ts +211 -0
  200. package/tests/service/data-endpoints-regression.test.ts +834 -0
  201. package/tests/service/evolution-worker.test.ts +0 -123
  202. package/tests/service/nocturnal-service-code-candidate.test.ts +330 -0
  203. package/tests/utils/nlp.test.ts +1 -19
  204. package/tests/utils/retry.test.ts +327 -0
  205. package/ui/src/App.tsx +1 -1
  206. package/ui/src/api.ts +4 -0
  207. package/ui/src/charts.tsx +366 -0
  208. package/ui/src/components/WorkspaceConfig.tsx +107 -75
  209. package/ui/src/i18n/ui.ts +89 -31
  210. package/ui/src/pages/EvolutionPage.tsx +1 -1
  211. package/ui/src/pages/OverviewPage.tsx +441 -81
  212. package/ui/src/pages/ThinkingModelsPage.tsx +287 -69
  213. package/ui/src/styles.css +43 -0
  214. package/ui/src/types.ts +17 -1
  215. package/src/agents/nocturnal-dreamer.md +0 -152
  216. package/src/agents/nocturnal-philosopher.md +0 -138
  217. package/src/agents/nocturnal-reflector.md +0 -126
  218. package/src/agents/nocturnal-scribe.md +0 -164
  219. package/templates/workspace/.principles/00-kernel.md +0 -51
  220. package/templates/workspace/.principles/DECISION_POLICY.json +0 -44
  221. package/templates/workspace/.principles/PRINCIPLES.md +0 -20
  222. package/templates/workspace/.principles/PROFILE.json +0 -54
  223. package/templates/workspace/.principles/PROFILE.schema.json +0 -56
  224. package/templates/workspace/.principles/THINKING_OS.md +0 -64
  225. package/templates/workspace/.principles/THINKING_OS_ARCHIVE.md +0 -7
  226. package/templates/workspace/.principles/THINKING_OS_CANDIDATES.md +0 -9
  227. package/templates/workspace/.principles/models/_INDEX.md +0 -27
  228. package/templates/workspace/.principles/models/first_principles.md +0 -62
  229. package/templates/workspace/.principles/models/marketing_4p.md +0 -52
  230. package/templates/workspace/.principles/models/porter_five.md +0 -63
  231. package/templates/workspace/.principles/models/swot.md +0 -60
  232. package/templates/workspace/.principles/models/user_story_map.md +0 -63
  233. package/templates/workspace/.state/WORKBOARD.json +0 -4
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Principle-Tree Schema Design
3
- *
3
+ *
4
4
  * Concept: Principles are the root of a tree that branches into Rules
5
5
  * and eventually into concrete Implementations (code, skills, LoRA weights).
6
- *
6
+ *
7
7
  * A principle without supporting rules is an empty concept — LLM may ignore it.
8
8
  * A rule without a parent principle lacks strategic direction.
9
- *
9
+ *
10
10
  * Lifecycle:
11
11
  * Pain Signal → Diagnosis → Principle (root)
12
12
  * ↓
@@ -15,23 +15,20 @@
15
15
  * Implementation (leaf)
16
16
  * ↓
17
17
  * Rule 100% covered → Principle deprecated
18
- *
18
+ *
19
19
  * User Focus:
20
20
  * - Monitor new principles added by diagnostician
21
21
  * - Monitor principles deprecated (solidified into code/weights)
22
22
  * - Track principle value ranking (pain prevented, adherence rate)
23
23
  */
24
24
 
25
+ import type { PrincipleStatus } from '../core/evolution-types.js';
26
+ import type { PrincipleDetectorSpec } from '../core/evolution-types.js';
27
+
25
28
  // =========================================================================
26
29
  // 1. PRINCIPLE (Tree Root) — Highly abstract, cross-scenario, value-driven
27
30
  // =========================================================================
28
31
 
29
- export type PrincipleStatus =
30
- | 'candidate' // Just created, needs validation
31
- | 'probation' // Partially validated, under observation
32
- | 'active' // Fully validated, actively enforced
33
- | 'deprecated'; // Solidified into code/weights, no longer needed as a principle
34
-
35
32
  export type PrinciplePriority = 'P0' | 'P1' | 'P2';
36
33
 
37
34
  export type PrincipleScope = 'general' | 'domain';
@@ -48,6 +45,7 @@ export interface Principle {
48
45
 
49
46
  // Core content
50
47
  text: string; // One-line abstract principle statement
48
+ coreAxiomId?: string; // Associated core axiom (e.g., "T-01")
51
49
  triggerPattern: string; // Regex/keywords for auto-matching pain signals
52
50
  action: string; // What to do when triggered
53
51
 
@@ -135,6 +133,12 @@ export interface Rule {
135
133
  // 3. IMPLEMENTATION (Tree Leaf) — Concrete, executable
136
134
  // =========================================================================
137
135
 
136
+ export type ImplementationLifecycleState =
137
+ | 'candidate' // Newly created, awaiting replay evaluation
138
+ | 'active' // Currently active for this rule
139
+ | 'disabled' // Manually disabled (e.g., regression)
140
+ | 'archived'; // Permanently archived
141
+
138
142
  export type ImplementationType = 'code' | 'skill' | 'lora' | 'test' | 'prompt';
139
143
 
140
144
  export interface Implementation {
@@ -151,6 +155,20 @@ export interface Implementation {
151
155
  coversCondition: string; // What condition this implementation covers
152
156
  coveragePercentage: number; // 0-100, how much of the rule this covers
153
157
 
158
+ // Lifecycle state
159
+ lifecycleState: ImplementationLifecycleState;
160
+
161
+ // Rollback support: tracks which implementation was active before this one
162
+ previousActive?: string; // Implementation ID that was active before promotion
163
+
164
+ // Disable metadata
165
+ disabledAt?: string; // ISO timestamp of disable
166
+ disabledBy?: string; // Who disabled (session/user)
167
+ disabledReason?: string; // Human-readable reason
168
+
169
+ // Archive metadata
170
+ archivedAt?: string; // ISO timestamp of archive
171
+
154
172
  // Metadata
155
173
  createdAt: string;
156
174
  updatedAt: string;
@@ -193,19 +211,7 @@ export interface PrincipleValueMetrics {
193
211
  }
194
212
 
195
213
  // =========================================================================
196
- // 6. DETECTOR METADATA (For auto-training eligibility)
197
- // =========================================================================
198
-
199
- export interface PrincipleDetectorSpec {
200
- applicabilityTags: string[]; // Tags that identify when this principle applies
201
- positiveSignals: string[]; // Indicators that the principle should activate
202
- negativeSignals: string[]; // Indicators that the principle should NOT activate
203
- toolSequenceHints?: string[][]; // Expected tool call sequences
204
- confidence: 'high' | 'medium' | 'low';
205
- }
206
-
207
- // =========================================================================
208
- // 7. LIFECYCLE EVENTS (Event stream format for evolution.jsonl)
214
+ // 6. LIFECYCLE EVENTS (Event stream format for evolution.jsonl)
209
215
  // =========================================================================
210
216
 
211
217
  export type PrincipleEventType =
@@ -8,7 +8,7 @@
8
8
  * 4. 锁获取后二次验证
9
9
  * 5. 数据不丢失:失败时抛出异常而非静默返回
10
10
  */
11
-
11
+ /* global NodeJS */
12
12
  import * as fs from 'fs';
13
13
  import * as path from 'path';
14
14
 
@@ -237,7 +237,7 @@ function tryAcquireWithStaleCleanup(filePath: string, opts: Required<LockOptions
237
237
  */
238
238
  export function acquireLock(filePath: string, options: LockOptions = {}): LockContext {
239
239
  const opts = { ...DEFAULT_OPTIONS, ...options };
240
- const pid = process.pid;
240
+ const {pid} = process;
241
241
 
242
242
  for (let attempt = 0; attempt < opts.maxRetries; attempt++) {
243
243
  const ctx = tryAcquireWithStaleCleanup(filePath, opts, pid);
@@ -256,7 +256,7 @@ export function acquireLock(filePath: string, options: LockOptions = {}): LockCo
256
256
 
257
257
  export async function acquireLockAsync(filePath: string, options: LockOptions = {}): Promise<LockContext> {
258
258
  const opts = { ...DEFAULT_OPTIONS, ...options };
259
- const pid = process.pid;
259
+ const {pid} = process;
260
260
 
261
261
  for (let attempt = 0; attempt < opts.maxRetries; attempt++) {
262
262
  const ctx = tryAcquireWithStaleCleanup(filePath, opts, pid);
@@ -334,6 +334,7 @@ export async function withAsyncLock<T>(
334
334
  let queue = asyncLockQueues.get(lockPath);
335
335
 
336
336
  // 创建新的 Promise 链
337
+ // eslint-disable-next-line @typescript-eslint/init-declarations -- assigned in Promise executor before use
337
338
  let resolveRelease: () => void;
338
339
  const releasePromise = new Promise<void>(resolve => {
339
340
  resolveRelease = resolve;
@@ -350,6 +351,7 @@ export async function withAsyncLock<T>(
350
351
  try {
351
352
  return await fn();
352
353
  } finally {
354
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Reason: resolveRelease is assigned in Promise constructor before finally runs
353
355
  resolveRelease!();
354
356
  // 清理已完成的队列
355
357
  if (asyncLockQueues.get(lockPath) === currentQueue) {
package/src/utils/io.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as path from 'path';
2
2
  import * as fs from 'fs';
3
- import { PD_FILES, resolvePdPath } from '../core/paths.js';
3
+ import { resolvePdPath } from '../core/paths.js';
4
4
 
5
5
  export function normalizePath(filePath: string, projectDir: string): string {
6
6
  if (!filePath) return '';
@@ -16,6 +16,7 @@ export function normalizePath(filePath: string, projectDir: string): string {
16
16
  }
17
17
  }
18
18
 
19
+ // eslint-disable-next-line @typescript-eslint/init-declarations -- assigned in both if/else branches
19
20
  let rel: string;
20
21
  if (projectIsWin) {
21
22
  const projectAbs = path.resolve(projectDir);
@@ -73,6 +74,7 @@ export function parseKvLines(text: string): Record<string, string> {
73
74
  return result;
74
75
  }
75
76
 
77
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Reason: serializeKvLines handles arbitrary object shapes for kv line serialization
76
78
  export function serializeKvLines(data: Record<string, any>): string {
77
79
  const lines: string[] = [];
78
80
  const keys = Object.keys(data).sort();
@@ -103,7 +105,8 @@ export function planStatus(projectDir: string): string {
103
105
  }
104
106
  }
105
107
  }
106
- } catch (e) {
108
+ /* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars -- Reason: Error is intentionally ignored for graceful degradation */
109
+ } catch (_e) {
107
110
  // Ignore read errors
108
111
  }
109
112
  return '';
package/src/utils/nlp.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Extracts common phrases (N-grams) that appear in a majority of the given samples.
3
3
  */
4
- export function extractCommonPhrases(samples: string[], minOccurrence: number = 3): string[] {
4
+ export function extractCommonPhrases(samples: string[], minOccurrence = 3): string[] {
5
5
  if (samples.length < minOccurrence) return [];
6
6
 
7
7
  const phrases = new Map<string, number>();
@@ -10,7 +10,7 @@ export function extractCommonPhrases(samples: string[], minOccurrence: number =
10
10
  for (const sample of samples) {
11
11
  // Keep all words, lowercased, remove basic punctuation
12
12
  const words = sample.toLowerCase().replace(/[.,!?;:()]/g, '').split(/\s+/).filter(w => w.length > 0);
13
-
13
+
14
14
  for (let i = 0; i <= words.length - n; i++) {
15
15
  const ngram = words.slice(i, i + n).join(' ');
16
16
  phrases.set(ngram, (phrases.get(ngram) || 0) + 1);
@@ -19,48 +19,7 @@ export function extractCommonPhrases(samples: string[], minOccurrence: number =
19
19
 
20
20
  // Filter phrases that meet the threshold
21
21
  return Array.from(phrases.entries())
22
- .filter(([_, count]) => count >= minOccurrence)
23
- .map(([phrase, _]) => phrase);
24
- }
25
-
26
- /**
27
- * Extracts the longest common substring present in a high percentage of samples.
28
- * Suitable for Chinese or languages without clear word boundaries.
29
- */
30
- export function extractCommonSubstring(samples: string[], minLen: number = 4): string[] {
31
- if (samples.length < 2) return [];
32
-
33
- const requiredMatches = Math.ceil(samples.length * 0.8); // Must appear in 80% of samples
34
- const baseStr = samples[0];
35
- let bestSubstrings: string[] = [];
36
- let maxLength = 0;
37
-
38
- // Generate all possible substrings from the first sample
39
- for (let i = 0; i < baseStr.length; i++) {
40
- for (let j = i + minLen; j <= baseStr.length; j++) {
41
- const sub = baseStr.substring(i, j);
42
-
43
- // If we already found a longer one, we only care if this one can beat it
44
- if (sub.length < maxLength) continue;
45
-
46
- // Check how many other samples contain this substring
47
- let matchCount = 1; // It's in the first sample
48
- for (let k = 1; k < samples.length; k++) {
49
- if (samples[k].includes(sub)) {
50
- matchCount++;
51
- }
52
- }
53
-
54
- if (matchCount >= requiredMatches) {
55
- if (sub.length > maxLength) {
56
- maxLength = sub.length;
57
- bestSubstrings = [sub];
58
- } else if (sub.length === maxLength && !bestSubstrings.includes(sub)) {
59
- bestSubstrings.push(sub);
60
- }
61
- }
62
- }
63
- }
64
-
65
- return bestSubstrings;
22
+ /* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars -- Reason: Destructuring with _placeholder for unused array element */
23
+ .filter(([_elem, count]) => count >= minOccurrence)
24
+ .map(([phrase, _count]) => phrase);
66
25
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Node VM Polyfill — Thin wrapper around node:vm module
3
+ *
4
+ * PURPOSE: Provide a single import point for vm compilation functionality
5
+ * used by the Rule Host. Isolates the node:vm dependency so it can be
6
+ * easily mocked in tests.
7
+ */
8
+
9
+ import * as vm from 'node:vm';
10
+
11
+ export const nodeVm = vm;
@@ -2,10 +2,12 @@ import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
 
4
4
  export interface PluginLogger {
5
+ /* eslint-disable no-unused-vars -- Reason: interface method params are type signatures, implementations use actual values */
5
6
  info(message: string, meta?: Record<string, unknown>): void;
6
7
  warn(message: string, meta?: Record<string, unknown>): void;
7
8
  error(message: string, meta?: Record<string, unknown>): void;
8
9
  debug(message: string, meta?: Record<string, unknown>): void;
10
+ /* eslint-enable no-unused-vars */
9
11
  }
10
12
 
11
13
  export interface PluginLoggerConfig {