@lmzhen/dsh-evolution-curator 0.1.0-rc.62 → 0.1.0-rc.64

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.
Files changed (2) hide show
  1. package/lib/index.js +30 -7
  2. 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_MIN_IDLE_HOURS, DEFAULT_STALE_AFTER_DAYS, EvolutionGateSet, SkillLibrary, buildCuratorRunReport, computeDedupGroups, computeLifecycleTransitions, computeQualityScores, computeScopeView, emptyRecord, evolutionHome, evolutionIoAdapter, loadSuppressedNames, loadUsage, parseCuratorNominations, relatedSkillNames, renderCuratorReportMarkdown, saveUsage, updateSuppressedNames } from "@lmzhen/dsh-evolution-core";
6
+ import { CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_MIN_IDLE_HOURS, DEFAULT_STALE_AFTER_DAYS, EvolutionGateSet, SkillLibrary, buildCuratorRunReport, computeDedupGroups, computeLifecycleTransitions, computeQualityScores, computeScopeView, emptyRecord, evolutionHome, evolutionIoAdapter, loadSuppressedNames, loadUsage, mutateUsage, parseCuratorNominations, relatedSkillNames, renderCuratorReportMarkdown, saveUsage, updateSuppressedNames } 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.
@@ -196,7 +196,7 @@ var EvolutionCurator = class extends Service {
196
196
  const parsed = parseCuratorNominations(assembler.blocks().filter((block) => block.type === "text").map((block) => block.text).join("\n"));
197
197
  return {
198
198
  prunings: parsed.prunings.filter((name) => candidates.includes(name)),
199
- consolidations: parsed.consolidations
199
+ consolidations: parsed.consolidations.filter((item) => candidates.includes(item.from))
200
200
  };
201
201
  } catch {
202
202
  return empty;
@@ -352,12 +352,14 @@ var EvolutionCurator = class extends Service {
352
352
  suppressedNames,
353
353
  referencedSkillNames: this.referencedSkillNames
354
354
  }, /* @__PURE__ */ new Date(), gates);
355
- const nominations = this.llmReview ? await this.recommend([...new Set([...result.markStale, ...dedupMembers])], { dryRun }) : {
355
+ const recommendPool = [...new Set([...result.markStale, ...dedupMembers])];
356
+ const nominations = this.llmReview ? await this.recommend(recommendPool, { dryRun }) : {
356
357
  prunings: [],
357
358
  consolidations: []
358
359
  };
359
360
  const gatedNominations = {
360
361
  ...nominations,
362
+ prunings: nominations.prunings.filter((name) => result.markStale.includes(name)),
361
363
  consolidations: gateConsolidations(nominations.consolidations, gates)
362
364
  };
363
365
  const llmNominations = gatedNominations.prunings;
@@ -371,6 +373,7 @@ var EvolutionCurator = class extends Service {
371
373
  bundledNames,
372
374
  suppressedNames,
373
375
  root,
376
+ recommendPool: new Set(recommendPool),
374
377
  failedFrom: new Map(result.transitions.filter((t) => t.to === "archived").map((t) => [t.name, t.from]))
375
378
  });
376
379
  if (!dryRun) this.lastRun = Date.now();
@@ -527,6 +530,10 @@ var EvolutionCurator = class extends Service {
527
530
  errors.push(`${nomination.from}: consolidation target or source missing from the skill tree`);
528
531
  continue;
529
532
  }
533
+ if (!input.recommendPool.has(nomination.from)) {
534
+ errors.push(`${nomination.from}: consolidation nomination outside the candidate pool — refused (advisory text has no executability authority)`);
535
+ continue;
536
+ }
530
537
  const consolidated = await this.skills.consolidate(nomination.into, [nomination.from], "background_review");
531
538
  if (!consolidated.ok) {
532
539
  errors.push(`${nomination.from}: ${consolidated.message}`);
@@ -556,7 +563,9 @@ var EvolutionCurator = class extends Service {
556
563
  this.ctx.logger.warn("evolution-curator: failed to persist suppressed names; archived built-ins may re-enter the lifecycle");
557
564
  }
558
565
  try {
559
- await saveUsage(root, usage, this.io);
566
+ await mutateUsage(root, this.io, (disk) => {
567
+ for (const [name, record] of usage) disk.set(name, record);
568
+ });
560
569
  } catch {
561
570
  this.ctx.logger.warn("evolution-curator: failed to persist usage sidecar");
562
571
  }
@@ -620,9 +629,23 @@ var EvolutionCurator = class extends Service {
620
629
  }
621
630
  async latestReport() {
622
631
  const reportsRoot = join(evolutionHome(), "reports");
623
- const latest = (await this.io.list(reportsRoot)).filter((name) => name.startsWith("curator-") && name.endsWith(".json")).sort().reverse()[0];
624
- if (!latest) return null;
625
- const raw = await this.io.readText(join(reportsRoot, latest));
632
+ const names = (await this.io.list(reportsRoot)).filter((name) => name.startsWith("curator-") && name.endsWith(".json")).sort();
633
+ let latest = null;
634
+ for (const name of names) {
635
+ const raw = await this.io.readText(join(reportsRoot, name));
636
+ if (raw === null) continue;
637
+ try {
638
+ const parsed = JSON.parse(raw);
639
+ const startedAt = typeof parsed.startedAt === "string" ? Date.parse(parsed.startedAt) : 0;
640
+ if (!Number.isFinite(startedAt)) continue;
641
+ if (latest === null || startedAt > latest.startedAt) latest = {
642
+ name,
643
+ startedAt
644
+ };
645
+ } catch {}
646
+ }
647
+ if (latest === null) return null;
648
+ const raw = await this.io.readText(join(reportsRoot, latest.name));
626
649
  if (raw === null) return null;
627
650
  try {
628
651
  return JSON.parse(raw);
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.1.0-rc.62",
4
+ "version": "0.1.0-rc.64",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -33,20 +33,20 @@
33
33
  "license": "MIT",
34
34
  "dependencies": {
35
35
  "@deepseek-ai/schemastery": "^3.18.1",
36
- "@lmzhen/dsh-evolution-core": "^0.1.0-rc.62"
36
+ "@lmzhen/dsh-evolution-core": "^0.1.0-rc.64"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@deepseek-ai/cordis": "^4.0.1",
40
40
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
41
41
  "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
42
- "@lmzhen/dsh-evolution-io": "^0.1.0-rc.62",
43
- "@lmzhen/dsh-evolution-state": "^0.1.0-rc.62"
42
+ "@lmzhen/dsh-evolution-io": "^0.1.0-rc.64",
43
+ "@lmzhen/dsh-evolution-state": "^0.1.0-rc.64"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
47
47
  "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
48
- "@lmzhen/dsh-evolution-core": "^0.1.0-rc.62",
49
- "@lmzhen/dsh-evolution-io": "^0.1.0-rc.62",
50
- "@lmzhen/dsh-evolution-state": "^0.1.0-rc.62"
48
+ "@lmzhen/dsh-evolution-core": "^0.1.0-rc.64",
49
+ "@lmzhen/dsh-evolution-io": "^0.1.0-rc.64",
50
+ "@lmzhen/dsh-evolution-state": "^0.1.0-rc.64"
51
51
  }
52
52
  }