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.
- package/CHANGELOG.md +26 -0
- package/README.md +66 -0
- package/esbuild.config.js +1 -1
- package/openclaw.plugin.json +4 -4
- package/package.json +2 -3
- package/run-nocturnal.mjs +30 -0
- package/scripts/db-migrate.mjs +170 -0
- package/scripts/sync-plugin.mjs +250 -6
- package/src/commands/archive-impl.ts +136 -0
- package/src/commands/capabilities.ts +4 -2
- package/src/commands/context.ts +5 -1
- package/src/commands/disable-impl.ts +151 -0
- package/src/commands/evolution-status.ts +64 -19
- package/src/commands/export.ts +8 -6
- package/src/commands/focus.ts +8 -20
- package/src/commands/nocturnal-review.ts +5 -7
- package/src/commands/nocturnal-rollout.ts +1 -12
- package/src/commands/nocturnal-train.ts +21 -47
- package/src/commands/pain.ts +10 -5
- package/src/commands/principle-rollback.ts +4 -2
- package/src/commands/promote-impl.ts +274 -0
- package/src/commands/rollback-impl.ts +234 -0
- package/src/commands/rollback.ts +6 -3
- package/src/commands/samples.ts +2 -0
- package/src/commands/thinking-os.ts +3 -4
- package/src/commands/workflow-debug.ts +2 -1
- package/src/config/errors.ts +1 -0
- package/src/core/AGENTS.md +34 -0
- package/src/core/adaptive-thresholds.ts +4 -3
- package/src/core/code-implementation-storage.ts +241 -0
- package/src/core/config.ts +5 -2
- package/src/core/control-ui-db.ts +29 -10
- package/src/core/detection-funnel.ts +12 -7
- package/src/core/diagnostician-task-store.ts +156 -0
- package/src/core/dictionary.ts +4 -4
- package/src/core/empathy-keyword-matcher.ts +7 -3
- package/src/core/empathy-types.ts +13 -2
- package/src/core/event-log.ts +14 -6
- package/src/core/evolution-engine.ts +27 -31
- package/src/core/evolution-logger.ts +3 -2
- package/src/core/evolution-reducer.ts +110 -31
- package/src/core/evolution-types.ts +10 -0
- package/src/core/external-training-contract.ts +1 -0
- package/src/core/focus-history.ts +38 -24
- package/src/core/hygiene/tracker.ts +10 -6
- package/src/core/init.ts +5 -2
- package/src/core/migration.ts +3 -3
- package/src/core/model-deployment-registry.ts +6 -4
- package/src/core/model-training-registry.ts +5 -3
- package/src/core/nocturnal-arbiter.ts +13 -14
- package/src/core/nocturnal-artifact-lineage.ts +117 -0
- package/src/core/nocturnal-artificer.ts +257 -0
- package/src/core/nocturnal-candidate-scoring.ts +4 -2
- package/src/core/nocturnal-compliance.ts +67 -19
- package/src/core/nocturnal-dataset.ts +95 -2
- package/src/core/nocturnal-executability.ts +2 -3
- package/src/core/nocturnal-export.ts +6 -3
- package/src/core/nocturnal-rule-implementation-validator.ts +245 -0
- package/src/core/nocturnal-trajectory-extractor.ts +10 -3
- package/src/core/nocturnal-trinity.ts +319 -61
- package/src/core/pain-context-extractor.ts +29 -15
- package/src/core/pain.ts +7 -5
- package/src/core/path-resolver.ts +16 -15
- package/src/core/paths.ts +2 -1
- package/src/core/pd-task-reconciler.ts +463 -0
- package/src/core/pd-task-service.ts +42 -0
- package/src/core/pd-task-store.ts +77 -0
- package/src/core/pd-task-types.ts +128 -0
- package/src/core/principle-internalization/deprecated-readiness.ts +91 -0
- package/src/core/principle-internalization/internalization-routing-policy.ts +208 -0
- package/src/core/principle-internalization/lifecycle-metrics.ts +149 -0
- package/src/core/principle-internalization/lifecycle-read-model.ts +243 -0
- package/src/core/principle-internalization/lifecycle-refresh.ts +11 -0
- package/src/core/principle-internalization/principle-lifecycle-service.ts +167 -0
- package/src/core/principle-training-state.ts +95 -370
- package/src/core/principle-tree-ledger.ts +733 -0
- package/src/core/principle-tree-migration.ts +195 -0
- package/src/core/profile.ts +3 -1
- package/src/core/promotion-gate.ts +14 -18
- package/src/core/replay-engine.ts +562 -0
- package/src/core/risk-calculator.ts +6 -4
- package/src/core/rule-host-helpers.ts +39 -0
- package/src/core/rule-host-types.ts +82 -0
- package/src/core/rule-host.ts +245 -0
- package/src/core/rule-implementation-runtime.ts +38 -0
- package/src/core/schema/db-types.ts +16 -0
- package/src/core/schema/index.ts +26 -0
- package/src/core/schema/migration-runner.ts +207 -0
- package/src/core/schema/migrations/001-init-trajectory.ts +211 -0
- package/src/core/schema/migrations/002-init-central.ts +122 -0
- package/src/core/schema/migrations/003-init-workflow.ts +55 -0
- package/src/core/schema/migrations/004-add-thinking-and-gfi.ts +74 -0
- package/src/core/schema/migrations/index.ts +31 -0
- package/src/core/schema/schema-definitions.ts +650 -0
- package/src/core/session-tracker.ts +6 -4
- package/src/core/shadow-observation-registry.ts +6 -3
- package/src/core/system-logger.ts +2 -2
- package/src/core/thinking-models.ts +182 -46
- package/src/core/thinking-os-parser.ts +156 -0
- package/src/core/training-program.ts +7 -7
- package/src/core/trajectory.ts +42 -36
- package/src/core/workspace-context.ts +77 -11
- package/src/core/workspace-dir-validation.ts +152 -0
- package/src/hooks/AGENTS.md +31 -0
- package/src/hooks/bash-risk.ts +3 -1
- package/src/hooks/edit-verification.ts +9 -5
- package/src/hooks/gate-block-helper.ts +5 -1
- package/src/hooks/gate.ts +152 -5
- package/src/hooks/gfi-gate.ts +9 -2
- package/src/hooks/lifecycle-routing.ts +124 -0
- package/src/hooks/lifecycle.ts +12 -12
- package/src/hooks/llm.ts +17 -109
- package/src/hooks/message-sanitize.ts +5 -3
- package/src/hooks/pain.ts +19 -15
- package/src/hooks/progressive-trust-gate.ts +7 -1
- package/src/hooks/prompt.ts +169 -60
- package/src/hooks/subagent.ts +5 -4
- package/src/hooks/thinking-checkpoint.ts +2 -0
- package/src/hooks/trajectory-collector.ts +15 -12
- package/src/http/principles-console-route.ts +31 -68
- package/src/i18n/commands.ts +2 -2
- package/src/index.ts +130 -40
- package/src/service/central-database.ts +131 -43
- package/src/service/central-health-service.ts +47 -0
- package/src/service/central-overview-service.ts +135 -0
- package/src/service/central-sync-service.ts +87 -0
- package/src/service/control-ui-query-service.ts +46 -36
- package/src/service/event-log-auditor.ts +261 -0
- package/src/service/evolution-query-service.ts +23 -22
- package/src/service/evolution-worker.ts +565 -261
- package/src/service/health-query-service.ts +213 -36
- package/src/service/nocturnal-runtime.ts +8 -4
- package/src/service/nocturnal-service.ts +503 -59
- package/src/service/nocturnal-target-selector.ts +5 -7
- package/src/service/runtime-summary-service.ts +2 -1
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +25 -336
- package/src/service/subagent-workflow/dynamic-timeout.ts +30 -0
- package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +48 -386
- package/src/service/subagent-workflow/index.ts +2 -0
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +169 -284
- package/src/service/subagent-workflow/runtime-direct-driver.ts +114 -16
- package/src/service/subagent-workflow/subagent-error-utils.ts +25 -0
- package/src/service/subagent-workflow/types.ts +9 -4
- package/src/service/subagent-workflow/workflow-manager-base.ts +573 -0
- package/src/service/subagent-workflow/workflow-store.ts +71 -11
- package/src/service/trajectory-service.ts +2 -1
- package/src/tools/critique-prompt.ts +1 -1
- package/src/tools/deep-reflect.ts +175 -209
- package/src/tools/model-index.ts +2 -1
- package/src/types/event-types.ts +2 -2
- package/src/types/principle-tree-schema.ts +29 -23
- package/src/utils/file-lock.ts +5 -3
- package/src/utils/io.ts +5 -2
- package/src/utils/nlp.ts +5 -46
- package/src/utils/node-vm-polyfill.ts +11 -0
- package/src/utils/plugin-logger.ts +2 -0
- package/src/utils/retry.ts +572 -0
- package/src/utils/subagent-probe.ts +1 -1
- package/templates/langs/en/core/AGENTS.md +0 -13
- package/templates/langs/en/core/SOUL.md +1 -31
- package/templates/langs/en/core/TOOLS.md +0 -4
- package/templates/langs/en/principles/THINKING_OS.md +77 -0
- package/templates/langs/en/skills/admin/SKILL.md +0 -1
- package/templates/langs/en/skills/evolution-framework-update/SKILL.md +1 -1
- package/templates/langs/en/skills/pd-diagnostician/SKILL.md +18 -5
- package/templates/langs/zh/core/AGENTS.md +0 -22
- package/templates/langs/zh/core/SOUL.md +1 -31
- package/templates/langs/zh/core/TOOLS.md +0 -4
- package/templates/langs/zh/principles/THINKING_OS.md +77 -0
- package/templates/langs/zh/skills/admin/SKILL.md +0 -1
- package/templates/langs/zh/skills/evolution-framework-update/SKILL.md +1 -1
- package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +25 -4
- package/tests/commands/evolution-status.test.ts +119 -0
- package/tests/commands/implementation-lifecycle.test.ts +362 -0
- package/tests/core/code-implementation-storage.test.ts +398 -0
- package/tests/core/evolution-reducer.detector-metadata.test.ts +28 -28
- package/tests/core/nocturnal-artifact-lineage.test.ts +53 -0
- package/tests/core/nocturnal-artificer.test.ts +241 -0
- package/tests/core/nocturnal-compliance-p-principles.test.ts +133 -0
- package/tests/core/nocturnal-rule-implementation-validator.test.ts +127 -0
- package/tests/core/pd-task-store.test.ts +126 -0
- package/tests/core/principle-internalization/deprecated-readiness.test.ts +193 -0
- package/tests/core/principle-internalization/internalization-routing-policy.test.ts +212 -0
- package/tests/core/principle-internalization/lifecycle-metrics.test.ts +350 -0
- package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +211 -0
- package/tests/core/principle-training-state.test.ts +228 -1
- package/tests/core/principle-tree-ledger.test.ts +423 -0
- package/tests/core/regression-v1-9-1.test.ts +265 -0
- package/tests/core/replay-engine.test.ts +234 -0
- package/tests/core/rule-host-helpers.test.ts +120 -0
- package/tests/core/rule-host.test.ts +389 -0
- package/tests/core/rule-implementation-runtime.test.ts +64 -0
- package/tests/core/workspace-context.test.ts +53 -0
- package/tests/core/workspace-dir-validation.test.ts +272 -0
- package/tests/hooks/gate-rule-host-pipeline.test.ts +385 -0
- package/tests/hooks/pain.test.ts +74 -10
- package/tests/hooks/prompt.test.ts +63 -1
- package/tests/integration/principle-lifecycle.e2e.test.ts +197 -0
- package/tests/integration/tool-hooks-workspace-dir.e2e.test.ts +211 -0
- package/tests/service/data-endpoints-regression.test.ts +834 -0
- package/tests/service/evolution-worker.test.ts +0 -123
- package/tests/service/nocturnal-service-code-candidate.test.ts +330 -0
- package/tests/utils/nlp.test.ts +1 -19
- package/tests/utils/retry.test.ts +327 -0
- package/ui/src/App.tsx +1 -1
- package/ui/src/api.ts +4 -0
- package/ui/src/charts.tsx +366 -0
- package/ui/src/components/WorkspaceConfig.tsx +107 -75
- package/ui/src/i18n/ui.ts +89 -31
- package/ui/src/pages/EvolutionPage.tsx +1 -1
- package/ui/src/pages/OverviewPage.tsx +441 -81
- package/ui/src/pages/ThinkingModelsPage.tsx +287 -69
- package/ui/src/styles.css +43 -0
- package/ui/src/types.ts +17 -1
- package/src/agents/nocturnal-dreamer.md +0 -152
- package/src/agents/nocturnal-philosopher.md +0 -138
- package/src/agents/nocturnal-reflector.md +0 -126
- package/src/agents/nocturnal-scribe.md +0 -164
- package/templates/workspace/.principles/00-kernel.md +0 -51
- package/templates/workspace/.principles/DECISION_POLICY.json +0 -44
- package/templates/workspace/.principles/PRINCIPLES.md +0 -20
- package/templates/workspace/.principles/PROFILE.json +0 -54
- package/templates/workspace/.principles/PROFILE.schema.json +0 -56
- package/templates/workspace/.principles/THINKING_OS.md +0 -64
- package/templates/workspace/.principles/THINKING_OS_ARCHIVE.md +0 -7
- package/templates/workspace/.principles/THINKING_OS_CANDIDATES.md +0 -9
- package/templates/workspace/.principles/models/_INDEX.md +0 -27
- package/templates/workspace/.principles/models/first_principles.md +0 -62
- package/templates/workspace/.principles/models/marketing_4p.md +0 -52
- package/templates/workspace/.principles/models/porter_five.md +0 -63
- package/templates/workspace/.principles/models/swot.md +0 -60
- package/templates/workspace/.principles/models/user_story_map.md +0 -63
- 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.
|
|
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 =
|
package/src/utils/file-lock.ts
CHANGED
|
@@ -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
|
|
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
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
23
|
-
.
|
|
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 {
|