@lmzhen/dsh-evolution-curator 0.3.24 → 0.3.25
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/lib/index.js +40 -23
- package/package.json +7 -7
package/lib/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { randomUUID } from "node:crypto";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { BlockAssembler, createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
5
5
|
import z from "@deepseek-ai/schemastery";
|
|
6
|
-
import { CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MIN_IDLE_HOURS, DEFAULT_STALE_AFTER_DAYS, EvolutionGateSet, SkillLibrary, buildCuratorRunReport, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, emptyRecord, evolutionHome, evolutionIoAdapter, foldCuratorFields, loadSuppressedNames, loadUsage, mutateUsage, parseCuratorNominations, relatedSkillNames, renderCuratorReportMarkdown, updateSuppressedNames, usageObserved } from "@lmzhen/dsh-evolution-core";
|
|
6
|
+
import { CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MIN_IDLE_HOURS, DEFAULT_STALE_AFTER_DAYS, EvolutionGateSet, SkillLibrary, buildCuratorRunReport, clampedNumber, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, emptyRecord, evolutionHome, evolutionIoAdapter, foldCuratorFields, loadSuppressedNames, loadUsage, mutateUsage, parseCuratorNominations, relatedSkillNames, renderCuratorReportMarkdown, updateSuppressedNames, usageObserved } from "@lmzhen/dsh-evolution-core";
|
|
7
7
|
//#region lib/types/index.js
|
|
8
8
|
/**
|
|
9
9
|
* Deterministic skill lifecycle curator with interval gate and archive.
|
|
@@ -25,24 +25,24 @@ var EvolutionCurator = class extends Service {
|
|
|
25
25
|
static inject = ["evolutionIo"];
|
|
26
26
|
static Config = z.object({
|
|
27
27
|
enabled: z.boolean().default(true),
|
|
28
|
-
intervalHours: z.number().default(DEFAULT_CURATOR_INTERVAL_HOURS),
|
|
29
|
-
staleAfterDays: z.number().default(DEFAULT_STALE_AFTER_DAYS),
|
|
30
|
-
archiveAfterDays: z.number().default(DEFAULT_ARCHIVE_AFTER_DAYS),
|
|
28
|
+
intervalHours: z.number().min(1).default(DEFAULT_CURATOR_INTERVAL_HOURS),
|
|
29
|
+
staleAfterDays: z.number().min(1).default(DEFAULT_STALE_AFTER_DAYS),
|
|
30
|
+
archiveAfterDays: z.number().min(1).default(DEFAULT_ARCHIVE_AFTER_DAYS),
|
|
31
31
|
llmReview: z.boolean().default(false),
|
|
32
32
|
curatorProvider: z.string().default("deepseek-official"),
|
|
33
|
-
qualityWarnStaleAfterDays: z.number().default(DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS),
|
|
34
|
-
minIdleHours: z.number().default(DEFAULT_MIN_IDLE_HOURS),
|
|
33
|
+
qualityWarnStaleAfterDays: z.number().min(1).default(DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS),
|
|
34
|
+
minIdleHours: z.number().min(0).default(DEFAULT_MIN_IDLE_HOURS),
|
|
35
35
|
minIdleFailOpen: z.boolean().default(true),
|
|
36
36
|
excludeSkillNames: z.array(z.string()).default([]),
|
|
37
37
|
manageUnmanaged: z.boolean().default(false),
|
|
38
38
|
pruneBuiltins: z.boolean().default(false),
|
|
39
39
|
referencedSkillNames: z.array(z.string()).default([]),
|
|
40
40
|
autoStart: z.boolean().default(true),
|
|
41
|
-
bootGraceSeconds: z.number().default(10),
|
|
42
|
-
curatorReviewMaxTokens: z.number().default(2048),
|
|
43
|
-
healthSoftBodyChars: z.number().default(DEFAULT_HEALTH_THRESHOLDS.softBodyChars),
|
|
44
|
-
healthStampDensityPerKb: z.number().default(DEFAULT_HEALTH_THRESHOLDS.stampDensityPerKb),
|
|
45
|
-
healthChurnMinPatches: z.number().default(DEFAULT_HEALTH_THRESHOLDS.churnMinPatches)
|
|
41
|
+
bootGraceSeconds: z.number().min(0).default(10),
|
|
42
|
+
curatorReviewMaxTokens: z.number().min(1).default(2048),
|
|
43
|
+
healthSoftBodyChars: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.softBodyChars),
|
|
44
|
+
healthStampDensityPerKb: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.stampDensityPerKb),
|
|
45
|
+
healthChurnMinPatches: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.churnMinPatches)
|
|
46
46
|
});
|
|
47
47
|
skills;
|
|
48
48
|
io;
|
|
@@ -79,23 +79,30 @@ var EvolutionCurator = class extends Service {
|
|
|
79
79
|
this.ctx.emit("evolution/skill-mutated", event);
|
|
80
80
|
});
|
|
81
81
|
this.enabled = config.enabled ?? true;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
const clamped = [];
|
|
83
|
+
const field = (name, value, fallback, min) => {
|
|
84
|
+
const result = clampedNumber(value, fallback, { min });
|
|
85
|
+
if (value !== void 0 && result !== value) clamped.push(name);
|
|
86
|
+
return result;
|
|
87
|
+
};
|
|
88
|
+
this.intervalHours = field("intervalHours", config.intervalHours, DEFAULT_CURATOR_INTERVAL_HOURS, 1);
|
|
89
|
+
this.staleAfterDays = field("staleAfterDays", config.staleAfterDays, DEFAULT_STALE_AFTER_DAYS, 1);
|
|
90
|
+
this.archiveAfterDays = field("archiveAfterDays", config.archiveAfterDays, DEFAULT_ARCHIVE_AFTER_DAYS, 1);
|
|
85
91
|
this.llmReview = config.llmReview ?? false;
|
|
86
92
|
this.curatorProvider = config.curatorProvider ?? "deepseek-official";
|
|
87
|
-
this.qualityWarnStaleAfterDays = config.qualityWarnStaleAfterDays
|
|
88
|
-
this.minIdleHours = config.minIdleHours
|
|
93
|
+
this.qualityWarnStaleAfterDays = field("qualityWarnStaleAfterDays", config.qualityWarnStaleAfterDays, DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS, 1);
|
|
94
|
+
this.minIdleHours = field("minIdleHours", config.minIdleHours, DEFAULT_MIN_IDLE_HOURS, 0);
|
|
89
95
|
this.minIdleFailOpen = config.minIdleFailOpen ?? true;
|
|
90
96
|
this.excludeSkillNames = new Set(config.excludeSkillNames ?? []);
|
|
91
97
|
this.manageUnmanaged = config.manageUnmanaged ?? false;
|
|
92
98
|
this.pruneBuiltins = config.pruneBuiltins ?? false;
|
|
93
99
|
this.referencedSkillNames = new Set(config.referencedSkillNames ?? []);
|
|
94
|
-
this.bootGraceSeconds = config.bootGraceSeconds
|
|
95
|
-
this.curatorReviewMaxTokens = config.curatorReviewMaxTokens
|
|
96
|
-
this.healthSoftBodyChars = config.healthSoftBodyChars
|
|
97
|
-
this.healthStampDensityPerKb = config.healthStampDensityPerKb
|
|
98
|
-
this.healthChurnMinPatches = config.healthChurnMinPatches
|
|
100
|
+
this.bootGraceSeconds = field("bootGraceSeconds", config.bootGraceSeconds, 10, 0);
|
|
101
|
+
this.curatorReviewMaxTokens = field("curatorReviewMaxTokens", config.curatorReviewMaxTokens, 2048, 1);
|
|
102
|
+
this.healthSoftBodyChars = field("healthSoftBodyChars", config.healthSoftBodyChars, DEFAULT_HEALTH_THRESHOLDS.softBodyChars, 1);
|
|
103
|
+
this.healthStampDensityPerKb = field("healthStampDensityPerKb", config.healthStampDensityPerKb, DEFAULT_HEALTH_THRESHOLDS.stampDensityPerKb, 1);
|
|
104
|
+
this.healthChurnMinPatches = field("healthChurnMinPatches", config.healthChurnMinPatches, DEFAULT_HEALTH_THRESHOLDS.churnMinPatches, 1);
|
|
105
|
+
if (clamped.length > 0) this.ctx.logger.warn(`evolution-curator: ${clamped.join(", ")} provided an invalid value; falling back to the default`);
|
|
99
106
|
this.lastRun = Date.now();
|
|
100
107
|
this.ctx.effect(() => {
|
|
101
108
|
return () => {
|
|
@@ -378,7 +385,8 @@ var EvolutionCurator = class extends Service {
|
|
|
378
385
|
const text = await this.skills.read(name);
|
|
379
386
|
if (text) contents.set(name, text);
|
|
380
387
|
}
|
|
381
|
-
const
|
|
388
|
+
const protectedNames = await this.protectedNameMap();
|
|
389
|
+
const dedupMembers = [...new Set(computeDedupGroups({ contents }).filter((group) => group.length >= 2).flat())].filter((name) => !protectedNames.has(name));
|
|
382
390
|
await this.scoreTree(usage, treeNames);
|
|
383
391
|
const result = computeLifecycleTransitions(usage, {
|
|
384
392
|
staleAfterDays: lifecycle.staleAfterDays,
|
|
@@ -546,6 +554,11 @@ var EvolutionCurator = class extends Service {
|
|
|
546
554
|
record.archived_at = record.archived_at ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
547
555
|
stateOwned.add(name);
|
|
548
556
|
}
|
|
557
|
+
if (bundledNames.has(name)) {
|
|
558
|
+
suppressedNames.add(name);
|
|
559
|
+
suppressedAdded.add(name);
|
|
560
|
+
suppressedChanged = true;
|
|
561
|
+
}
|
|
549
562
|
continue;
|
|
550
563
|
}
|
|
551
564
|
const archived = await this.skills.archive(name, {
|
|
@@ -668,7 +681,11 @@ var EvolutionCurator = class extends Service {
|
|
|
668
681
|
const raw = await this.io.readText(join(reportsRoot, name));
|
|
669
682
|
if (raw === null) continue;
|
|
670
683
|
const parsed = JSON.parse(raw);
|
|
671
|
-
|
|
684
|
+
let startedAt = typeof parsed.startedAt === "string" ? Date.parse(parsed.startedAt) : NaN;
|
|
685
|
+
if (!Number.isFinite(startedAt)) {
|
|
686
|
+
const mtime = await this.io.mtime?.(join(reportsRoot, name)) ?? null;
|
|
687
|
+
if (mtime !== null) startedAt = mtime;
|
|
688
|
+
}
|
|
672
689
|
if (Number.isFinite(startedAt)) dated.push({
|
|
673
690
|
name,
|
|
674
691
|
startedAt
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-curator",
|
|
3
3
|
"description": "Deterministic skill lifecycle and recovery (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.25",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,20 +31,20 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
34
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
34
|
+
"@lmzhen/dsh-evolution-core": "^0.3.25"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
38
38
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
39
39
|
"@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
|
|
40
|
-
"@lmzhen/dsh-evolution-io": "^0.3.
|
|
41
|
-
"@lmzhen/dsh-evolution-state": "^0.3.
|
|
40
|
+
"@lmzhen/dsh-evolution-io": "^0.3.25",
|
|
41
|
+
"@lmzhen/dsh-evolution-state": "^0.3.25"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
45
45
|
"@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
|
|
46
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
47
|
-
"@lmzhen/dsh-evolution-io": "^0.3.
|
|
48
|
-
"@lmzhen/dsh-evolution-state": "^0.3.
|
|
46
|
+
"@lmzhen/dsh-evolution-core": "^0.3.25",
|
|
47
|
+
"@lmzhen/dsh-evolution-io": "^0.3.25",
|
|
48
|
+
"@lmzhen/dsh-evolution-state": "^0.3.25"
|
|
49
49
|
}
|
|
50
50
|
}
|