@lmzhen/dsh-evolution-curator 0.19.3 → 0.21.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 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
@@ -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).volatile(),
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([]),
@@ -190,6 +190,22 @@ var EvolutionCurator = class extends Service {
190
190
  return clampOnce(this.clampedKeys, this.clampWarn, key, this.liveNumber(key), fallback, min, max);
191
191
  }
192
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);
207
+ }
208
+ /**
193
209
  * One live boolean row field at USE time.
194
210
  * @param key - the canonical registry id of the field.
195
211
  * @param fallback - the value used when the deployment supplied none.
@@ -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: number("qualityWarnStaleAfterDays", DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS, 1),
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),
@@ -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
- qualityWarnStaleAfterDays?: Volatile<number>;
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, "volatile-defined">;
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, "volatile-defined">;
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">;
@@ -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.19.3",
4
+ "version": "0.21.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.19.3"
30
+ "@lmzhen/dsh-evolution-core": "^0.21.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.19.3",
37
- "@lmzhen/dsh-evolution-state": "^0.19.3"
36
+ "@lmzhen/dsh-evolution-io": "^0.21.0",
37
+ "@lmzhen/dsh-evolution-state": "^0.21.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.19.3",
43
- "@lmzhen/dsh-evolution-io": "^0.19.3",
44
- "@lmzhen/dsh-evolution-state": "^0.19.3"
42
+ "@lmzhen/dsh-evolution-core": "^0.21.0",
43
+ "@lmzhen/dsh-evolution-io": "^0.21.0",
44
+ "@lmzhen/dsh-evolution-state": "^0.21.0"
45
45
  }
46
46
  }