@lmzhen/dsh-evolution-curator 0.20.0 → 0.22.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/README.md +1 -0
- package/lib/index.js +24 -8
- package/lib/types/index.d.ts +21 -4
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -28,6 +28,7 @@ Deterministic skill lifecycle and recovery
|
|
|
28
28
|
|
|
29
29
|
- `autoStart` (default true) arms an HOURLY tick that only asks whether the due-ness interval (`curatorIntervalHours`, default 168 h) has elapsed — the tick is not the interval — plus a deferred catch-up check `bootGraceSeconds` (default 10) after host boot. Both decide due-ness from the **persisted** `lastRunAt`, so a restart with an overdue schedule runs the first pass within the boot grace instead of waiting a full interval. `bootGraceSeconds: 0` disables the deferral (not recommended: the check may run against a half-mounted host). All scheduling gates — interval, idle, first-run deferral, and the reentrancy guard — remain inside `run()`.
|
|
30
30
|
- `autoStart: false` disables both automatic checks; `/evolution curator run` (manual, gate-skipping) still works.
|
|
31
|
+
- `autoStart` is the STARTUP default. The runtime switch is `/evolution curator pause` / `resume`: the pause is persisted in curation state, survives restarts, and wins over `autoStart` until it is cleared — turning `autoStart` off keeps curation manual, it does not freeze a schedule that is already paused or running.
|
|
31
32
|
- Deprecated name (G0/S0.3): `intervalHours` is the legacy spelling of the policy
|
|
32
33
|
row's `curatorIntervalHours`, whose value the snapshot shadows. Reading it still
|
|
33
34
|
works; writing it is refused. Removal was planned for 0.7.0 and is deferred: the alias still ships, so no later version is claimed here.
|
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_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MIN_IDLE_HOURS, DEFAULT_SKILL_LIMITS, DEFAULT_STALE_AFTER_DAYS, EvolutionGateSet, INSTANCE_KEYS, MAX_TIMER_DELAY_MS, PROMPT_BUNDLE, SKILL_NAME_RE, buildCuratorRunReport, claimInstance, clampOnce, clampedNumber, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, emptyRecord, entryTarget, evolutionHome, evolutionIoAdapter, foldCuratorFields, isPresent, isUnknown, loadSuppressedNames, loadUsage, markerEntryName, mutateUsage, newSkillLibrary, paramRowId, parseCuratorNominations, parseFrontmatter, pickWithPolicy, policyStageLimits, probeList, probeText, readNumberParam, relatedSkillNames, releaseInstance, renderCuratorReportMarkdown, reportTime, reportsSweepLockTarget, sessionLastEventTime, sweepReports, transactIo, updateSuppressedNames, usageObserved, userSetKeys, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
|
|
6
|
+
import { CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CURATOR_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MIN_IDLE_HOURS, DEFAULT_SKILL_LIMITS, DEFAULT_STALE_AFTER_DAYS, EvolutionGateSet, INSTANCE_KEYS, MAX_TIMER_DELAY_MS, PROMPT_BUNDLE, SKILL_NAME_RE, buildCuratorRunReport, claimInstance, clampOnce, clampedNumber, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, emptyRecord, entryTarget, evolutionHome, evolutionIoAdapter, foldCuratorFields, isPresent, isUnknown, liveBool, loadSuppressedNames, loadUsage, markerEntryName, mutateUsage, newSkillLibrary, paramRowId, parseCuratorNominations, parseFrontmatter, pickWithPolicy, policyStageLimits, probeList, probeText, readNumberParam, relatedSkillNames, releaseInstance, renderCuratorReportMarkdown, reportTime, reportsSweepLockTarget, sessionLastEventTime, sweepReports, transactIo, unwrapLive, updateSuppressedNames, usageObserved, userSetKeys, verifyPromptBundle } 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.
|
|
@@ -49,7 +49,7 @@ var EvolutionCurator = class extends Service {
|
|
|
49
49
|
archiveAfterDays: z.number().min(1).default(DEFAULT_ARCHIVE_AFTER_DAYS).volatile(),
|
|
50
50
|
llmReview: z.boolean().default(false).volatile(),
|
|
51
51
|
curatorProvider: z.string().default("deepseek-official"),
|
|
52
|
-
qualityWarnStaleAfterDays: z.number().min(1).default(DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS)
|
|
52
|
+
qualityWarnStaleAfterDays: z.number().min(1).default(DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS),
|
|
53
53
|
minIdleHours: z.number().min(0).default(DEFAULT_MIN_IDLE_HOURS).volatile(),
|
|
54
54
|
minIdleFailOpen: z.boolean().default(true).volatile(),
|
|
55
55
|
excludeSkillNames: z.array(z.string()).default([]),
|
|
@@ -174,9 +174,9 @@ var EvolutionCurator = class extends Service {
|
|
|
174
174
|
* @param key - the canonical registry id of the field.
|
|
175
175
|
* @returns the current plain value, or undefined when nothing supplied one.
|
|
176
176
|
*/
|
|
177
|
-
|
|
178
|
-
if (key === "curatorIntervalHours") return this.config.curatorIntervalHours
|
|
179
|
-
return this.config[key]
|
|
177
|
+
rowValue(key) {
|
|
178
|
+
if (key === "curatorIntervalHours") return unwrapLive(this.config.curatorIntervalHours) ?? this.config.intervalHours;
|
|
179
|
+
return unwrapLive(this.config[key]);
|
|
180
180
|
}
|
|
181
181
|
/**
|
|
182
182
|
* One live numeric row field, clamped and warned once (G3.1).
|
|
@@ -187,7 +187,23 @@ var EvolutionCurator = class extends Service {
|
|
|
187
187
|
* @returns the value the engine may use.
|
|
188
188
|
*/
|
|
189
189
|
rowNumber(key, fallback, min, max) {
|
|
190
|
-
return clampOnce(this.clampedKeys, this.clampWarn, key, this.
|
|
190
|
+
return clampOnce(this.clampedKeys, this.clampWarn, key, this.rowValue(key), fallback, min, max);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* One DEPLOYMENT numeric row field, clamped and warned once.
|
|
194
|
+
*
|
|
195
|
+
* The sibling of {@link rowNumber} for a field with no user layer (no `.volatile()`): it reads
|
|
196
|
+
* the config directly, because unwrapping a reference that never arrives would answer undefined
|
|
197
|
+
* and quietly fall back to the default. The clamp rule is the same one — a malformed value must
|
|
198
|
+
* not reach a comparison or a timer.
|
|
199
|
+
* @param key - the registry id of the field.
|
|
200
|
+
* @param fallback - the package default a corrected value falls back to.
|
|
201
|
+
* @param min - the smallest value the engine can act on.
|
|
202
|
+
* @param max - the largest value the carrier can hold, when bounded.
|
|
203
|
+
* @returns the value the engine may use.
|
|
204
|
+
*/
|
|
205
|
+
plainNumber(key, fallback, min, max) {
|
|
206
|
+
return clampOnce(this.clampedKeys, this.clampWarn, key, this.config[key], fallback, min, max);
|
|
191
207
|
}
|
|
192
208
|
/**
|
|
193
209
|
* One live boolean row field at USE time.
|
|
@@ -196,7 +212,7 @@ var EvolutionCurator = class extends Service {
|
|
|
196
212
|
* @returns the current value.
|
|
197
213
|
*/
|
|
198
214
|
rowBoolean(key, fallback) {
|
|
199
|
-
return this.config[key]
|
|
215
|
+
return liveBool(this.config[key], fallback);
|
|
200
216
|
}
|
|
201
217
|
/**
|
|
202
218
|
* This row's resolved values — the base layer of the precedence chain (G1 §8.3).
|
|
@@ -209,7 +225,7 @@ var EvolutionCurator = class extends Service {
|
|
|
209
225
|
curatorIntervalHours: number("curatorIntervalHours", DEFAULT_CURATOR_INTERVAL_HOURS, 1),
|
|
210
226
|
staleAfterDays: number("staleAfterDays", DEFAULT_STALE_AFTER_DAYS, 1),
|
|
211
227
|
archiveAfterDays: number("archiveAfterDays", DEFAULT_ARCHIVE_AFTER_DAYS, 1),
|
|
212
|
-
qualityWarnStaleAfterDays:
|
|
228
|
+
qualityWarnStaleAfterDays: this.plainNumber("qualityWarnStaleAfterDays", DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS, 1),
|
|
213
229
|
minIdleHours: number("minIdleHours", DEFAULT_MIN_IDLE_HOURS, 0),
|
|
214
230
|
minIdleFailOpen: this.rowBoolean("minIdleFailOpen", true),
|
|
215
231
|
llmReview: this.rowBoolean("llmReview", false),
|
package/lib/types/index.d.ts
CHANGED
|
@@ -42,7 +42,10 @@ export interface Config {
|
|
|
42
42
|
llmReview?: Volatile<boolean>;
|
|
43
43
|
curatorProvider?: string;
|
|
44
44
|
/** Quality-warned skills may turn stale after this many idle days. */
|
|
45
|
-
|
|
45
|
+
/** Deployment face since 0.21.0/G5: the quality-warning pair (this window and feedback's
|
|
46
|
+
* threshold) moved to the deployment rows together, so the field is a plain number — no
|
|
47
|
+
* `.volatile()`, no user layer, and the reader must not unwrap a reference that never arrives. */
|
|
48
|
+
qualityWarnStaleAfterDays?: number | undefined;
|
|
46
49
|
/** Skip automatic runs while any session was active within this many hours (0 disables). */
|
|
47
50
|
minIdleHours?: Volatile<number>;
|
|
48
51
|
/** When true (default), a missing `agents` service is treated as "no active
|
|
@@ -151,7 +154,7 @@ export declare class EvolutionCurator extends Service {
|
|
|
151
154
|
archiveAfterDays: z<number, number, "volatile-defined">;
|
|
152
155
|
llmReview: z<boolean, boolean, "volatile-defined">;
|
|
153
156
|
curatorProvider: z<string, string, "defined">;
|
|
154
|
-
qualityWarnStaleAfterDays: z<number, number, "
|
|
157
|
+
qualityWarnStaleAfterDays: z<number, number, "defined">;
|
|
155
158
|
minIdleHours: z<number, number, "volatile-defined">;
|
|
156
159
|
minIdleFailOpen: z<boolean, boolean, "volatile-defined">;
|
|
157
160
|
excludeSkillNames: z<string[], string[], "defined">;
|
|
@@ -174,7 +177,7 @@ export declare class EvolutionCurator extends Service {
|
|
|
174
177
|
archiveAfterDays: z<number, number, "volatile-defined">;
|
|
175
178
|
llmReview: z<boolean, boolean, "volatile-defined">;
|
|
176
179
|
curatorProvider: z<string, string, "defined">;
|
|
177
|
-
qualityWarnStaleAfterDays: z<number, number, "
|
|
180
|
+
qualityWarnStaleAfterDays: z<number, number, "defined">;
|
|
178
181
|
minIdleHours: z<number, number, "volatile-defined">;
|
|
179
182
|
minIdleFailOpen: z<boolean, boolean, "volatile-defined">;
|
|
180
183
|
excludeSkillNames: z<string[], string[], "defined">;
|
|
@@ -241,7 +244,7 @@ export declare class EvolutionCurator extends Service {
|
|
|
241
244
|
* @param key - the canonical registry id of the field.
|
|
242
245
|
* @returns the current plain value, or undefined when nothing supplied one.
|
|
243
246
|
*/
|
|
244
|
-
private
|
|
247
|
+
private rowValue;
|
|
245
248
|
/**
|
|
246
249
|
* One live numeric row field, clamped and warned once (G3.1).
|
|
247
250
|
* @param key - the canonical registry id of the field.
|
|
@@ -251,6 +254,20 @@ export declare class EvolutionCurator extends Service {
|
|
|
251
254
|
* @returns the value the engine may use.
|
|
252
255
|
*/
|
|
253
256
|
private rowNumber;
|
|
257
|
+
/**
|
|
258
|
+
* One DEPLOYMENT numeric row field, clamped and warned once.
|
|
259
|
+
*
|
|
260
|
+
* The sibling of {@link rowNumber} for a field with no user layer (no `.volatile()`): it reads
|
|
261
|
+
* the config directly, because unwrapping a reference that never arrives would answer undefined
|
|
262
|
+
* and quietly fall back to the default. The clamp rule is the same one — a malformed value must
|
|
263
|
+
* not reach a comparison or a timer.
|
|
264
|
+
* @param key - the registry id of the field.
|
|
265
|
+
* @param fallback - the package default a corrected value falls back to.
|
|
266
|
+
* @param min - the smallest value the engine can act on.
|
|
267
|
+
* @param max - the largest value the carrier can hold, when bounded.
|
|
268
|
+
* @returns the value the engine may use.
|
|
269
|
+
*/
|
|
270
|
+
private plainNumber;
|
|
254
271
|
/**
|
|
255
272
|
* One live boolean row field at USE time.
|
|
256
273
|
* @param key - the canonical registry id of the field.
|
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.
|
|
4
|
+
"version": "0.22.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,20 +27,20 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@deepseek-ai/schemastery": "^3.18.4",
|
|
30
|
-
"@lmzhen/dsh-evolution-core": "^0.
|
|
30
|
+
"@lmzhen/dsh-evolution-core": "^0.22.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
34
34
|
"@deepseek-ai/dsh-llm": "^0.2.0-rc.1",
|
|
35
35
|
"@deepseek-ai/dsh-session": "^0.2.0-rc.1",
|
|
36
|
-
"@lmzhen/dsh-evolution-io": "^0.
|
|
37
|
-
"@lmzhen/dsh-evolution-state": "^0.
|
|
36
|
+
"@lmzhen/dsh-evolution-io": "^0.22.0",
|
|
37
|
+
"@lmzhen/dsh-evolution-state": "^0.22.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@deepseek-ai/dsh-llm": "^0.2.0-rc.1",
|
|
41
41
|
"@deepseek-ai/dsh-session": "^0.2.0-rc.1",
|
|
42
|
-
"@lmzhen/dsh-evolution-core": "^0.
|
|
43
|
-
"@lmzhen/dsh-evolution-io": "^0.
|
|
44
|
-
"@lmzhen/dsh-evolution-state": "^0.
|
|
42
|
+
"@lmzhen/dsh-evolution-core": "^0.22.0",
|
|
43
|
+
"@lmzhen/dsh-evolution-io": "^0.22.0",
|
|
44
|
+
"@lmzhen/dsh-evolution-state": "^0.22.0"
|
|
45
45
|
}
|
|
46
46
|
}
|