@lmzhen/dsh-evolution-curator 0.3.56 → 0.3.58

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
@@ -22,7 +22,11 @@ Independent of request-prefix construction. This package does not alter the asse
22
22
 
23
23
 
24
24
  - LLM nomination pass is advisory and disabled by default; deterministic lifecycle remains authoritative.
25
- - Consolidation is control-plane only (`/evolution consolidate <target> <source...>`): no LLM pass proposes merge groups yet, and merged source bodies are appended verbatim rather than rewritten into a synthesized skill.
25
+ - Consolidation is a REAL merger path: the LLM nomination (when enabled / via `recommend()`) proposes
26
+ merge groups, the control plane gates them and applies the mutation — merged source bodies are appended
27
+ verbatim rather than rewritten into a synthesized skill. The one-click `/evolution consolidate
28
+ <target> <source...>` remains the direct manual path (P2-8, v11: the earlier "no LLM pass proposes
29
+ merge groups" wording contradicted the tested nomination chain).
26
30
 
27
31
  ## Recovery and consolidation
28
32
 
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, clampedNumber, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, emptyRecord, evolutionHome, evolutionIoAdapter, foldCuratorFields, loadSuppressedNames, loadUsage, markerEntryName, mutateUsage, parseCuratorNominations, parseFrontmatter, 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, SKILL_NAME_RE, SkillLibrary, buildCuratorRunReport, clampedNumber, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, emptyRecord, evolutionHome, evolutionIoAdapter, foldCuratorFields, loadSuppressedNames, loadUsage, markerEntryName, mutateUsage, parseCuratorNominations, parseFrontmatter, relatedSkillNames, renderCuratorReportMarkdown, resolveSkillsRoot, 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.
@@ -75,7 +75,7 @@ var EvolutionCurator = class extends Service {
75
75
  constructor(ctx, config = {}) {
76
76
  super(ctx, "evolutionCurator");
77
77
  this.io = evolutionIoAdapter(() => ctx.evolutionIo.provider());
78
- this.skills = new SkillLibrary(void 0, this.io, void 0, (event) => {
78
+ this.skills = new SkillLibrary(resolveSkillsRoot({ root: config.root }), this.io, void 0, (event) => {
79
79
  this.ctx.emit("evolution/skill-mutated", event);
80
80
  });
81
81
  this.enabled = config.enabled ?? true;
@@ -166,11 +166,10 @@ var EvolutionCurator = class extends Service {
166
166
  return await this.curatorStateService()?.loadCuratorState() ?? null;
167
167
  }
168
168
  /**
169
- * One automatic schedule check: run a pass when the persisted curator state
170
- * (falling back to the in-memory clock for state-less compositions) is at
171
- * least one interval old. All gates interval, idle, first-run defer,
172
- * reentrancy stay inside `run()`, so this method only decides whether to
173
- * wake it, and never duplicates gate logic.
169
+ * One automatic schedule check. P2-11 (v11): the interval gate is exercised
170
+ * HERE as a cheap pre-check (persisted or in-memory clock) AND again inside
171
+ * run() as the authoritative gatethe docstring no longer claims the two
172
+ * never duplicate; a future interval change must update both.
174
173
  */
175
174
  async autoCheck() {
176
175
  try {
@@ -578,6 +577,7 @@ var EvolutionCurator = class extends Service {
578
577
  if (!wasBundled) {
579
578
  const archiveEntries = await this.io.list(join(this.skills.root, ".archive"));
580
579
  for (const entry of archiveEntries) {
580
+ if (!SKILL_NAME_RE.test(name)) continue;
581
581
  if (!new RegExp(`^${name}-\\d{14}(-[0-9a-z]{1,6})?$`).test(entry)) continue;
582
582
  wasBundled = await this.io.exists(join(this.skills.root, ".archive", entry, markerEntryName("bundled")));
583
583
  if (wasBundled) {
@@ -679,7 +679,9 @@ var EvolutionCurator = class extends Service {
679
679
  const usageRegistry = this.ctx.get("skillUsage");
680
680
  try {
681
681
  await usageRegistry?.invalidate?.();
682
- } catch {}
682
+ } catch (error) {
683
+ this.ctx.logger.warn(`evolution-curator: skillUsage cache invalidate failed after curation: ${error instanceof Error ? error.message : String(error)}`);
684
+ }
683
685
  return {
684
686
  archivedSkills,
685
687
  errors,
@@ -17,6 +17,11 @@ export interface Config {
17
17
  intervalHours?: number;
18
18
  staleAfterDays?: number;
19
19
  archiveAfterDays?: number;
20
+ /** Skill-tree root for curator scope/snapshot/archive (D2, v11) — a custom
21
+ * root deployment (review/tool-skill-manage write another tree) must point
22
+ * the curator at the SAME tree or lifecycle decisions land on the default
23
+ * tree and never see the deployed skills. Empty uses skillsRoot(). */
24
+ root?: string;
20
25
  /** Spend one LLM review pass on stale candidates before the deterministic archive step. */
21
26
  llmReview?: boolean;
22
27
  curatorProvider?: string;
@@ -130,11 +135,10 @@ export declare class EvolutionCurator extends Service {
130
135
  /** Current persisted curator state (read-only view for /evolution curator status). */
131
136
  status(): Promise<CuratorStateRecordShape | null>;
132
137
  /**
133
- * One automatic schedule check: run a pass when the persisted curator state
134
- * (falling back to the in-memory clock for state-less compositions) is at
135
- * least one interval old. All gates interval, idle, first-run defer,
136
- * reentrancy stay inside `run()`, so this method only decides whether to
137
- * wake it, and never duplicates gate logic.
138
+ * One automatic schedule check. P2-11 (v11): the interval gate is exercised
139
+ * HERE as a cheap pre-check (persisted or in-memory clock) AND again inside
140
+ * run() as the authoritative gatethe docstring no longer claims the two
141
+ * never duplicate; a future interval change must update both.
138
142
  */
139
143
  private autoCheck;
140
144
  /**
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.56",
4
+ "version": "0.3.58",
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.56"
34
+ "@lmzhen/dsh-evolution-core": "^0.3.58"
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.56",
41
- "@lmzhen/dsh-evolution-state": "^0.3.56"
40
+ "@lmzhen/dsh-evolution-io": "^0.3.58",
41
+ "@lmzhen/dsh-evolution-state": "^0.3.58"
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.56",
47
- "@lmzhen/dsh-evolution-io": "^0.3.56",
48
- "@lmzhen/dsh-evolution-state": "^0.3.56"
46
+ "@lmzhen/dsh-evolution-core": "^0.3.58",
47
+ "@lmzhen/dsh-evolution-io": "^0.3.58",
48
+ "@lmzhen/dsh-evolution-state": "^0.3.58"
49
49
  }
50
50
  }