@lmzhen/dsh-evolution-curator 0.1.0 → 0.2.0-rc.2

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 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, computePrefixClusters, computeQualityScores, computeScopeView, emptyRecord, evolutionHome, evolutionIoAdapter, foldCuratorFields, loadSuppressedNames, loadUsage, mutateUsage, parseCuratorNominations, relatedSkillNames, renderCuratorReportMarkdown, updateSuppressedNames } 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, 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.
@@ -38,7 +38,10 @@ var EvolutionCurator = class extends Service {
38
38
  referencedSkillNames: z.array(z.string()).default([]),
39
39
  autoStart: z.boolean().default(true),
40
40
  bootGraceSeconds: z.number().default(10),
41
- curatorReviewMaxTokens: z.number().default(2048)
41
+ curatorReviewMaxTokens: z.number().default(2048),
42
+ healthSoftBodyChars: z.number().default(DEFAULT_HEALTH_THRESHOLDS.softBodyChars),
43
+ healthStampDensityPerKb: z.number().default(DEFAULT_HEALTH_THRESHOLDS.stampDensityPerKb),
44
+ healthChurnMinPatches: z.number().default(DEFAULT_HEALTH_THRESHOLDS.churnMinPatches)
42
45
  });
43
46
  skills;
44
47
  io;
@@ -56,6 +59,9 @@ var EvolutionCurator = class extends Service {
56
59
  referencedSkillNames;
57
60
  bootGraceSeconds;
58
61
  curatorReviewMaxTokens;
62
+ healthSoftBodyChars;
63
+ healthStampDensityPerKb;
64
+ healthChurnMinPatches;
59
65
  lastRun = 0;
60
66
  timer;
61
67
  bootCheck;
@@ -80,6 +86,9 @@ var EvolutionCurator = class extends Service {
80
86
  this.referencedSkillNames = new Set(config.referencedSkillNames ?? []);
81
87
  this.bootGraceSeconds = config.bootGraceSeconds ?? 10;
82
88
  this.curatorReviewMaxTokens = config.curatorReviewMaxTokens ?? 2048;
89
+ this.healthSoftBodyChars = config.healthSoftBodyChars ?? DEFAULT_HEALTH_THRESHOLDS.softBodyChars;
90
+ this.healthStampDensityPerKb = config.healthStampDensityPerKb ?? DEFAULT_HEALTH_THRESHOLDS.stampDensityPerKb;
91
+ this.healthChurnMinPatches = config.healthChurnMinPatches ?? DEFAULT_HEALTH_THRESHOLDS.churnMinPatches;
83
92
  this.lastRun = Date.now();
84
93
  this.ctx.effect(() => {
85
94
  return () => {
@@ -545,7 +554,7 @@ var EvolutionCurator = class extends Service {
545
554
  errors.push(`${nomination.from}: consolidation nomination outside the candidate pool — refused (advisory text has no executability authority)`);
546
555
  continue;
547
556
  }
548
- const consolidated = await this.skills.consolidate(nomination.into, [nomination.from], "background_review");
557
+ const consolidated = await this.skills.consolidate(nomination.into, [nomination.from], "background_review", { ...nomination.mode === void 0 ? {} : { mode: nomination.mode } });
549
558
  if (!consolidated.ok) {
550
559
  errors.push(`${nomination.from}: ${consolidated.message}`);
551
560
  continue;
@@ -691,6 +700,39 @@ var EvolutionCurator = class extends Service {
691
700
  bundledNames
692
701
  }, await this.protectedNameMap(), gates);
693
702
  }
703
+ /**
704
+ * Structure-health view (rc.73 A1, 008 design): degraded skills only,
705
+ * derived on demand — never persisted. Signals for review/curate proposals;
706
+ * the deterministic assessment stays here, refinement stays in the judgment
707
+ * layer.
708
+ */
709
+ async healthView() {
710
+ const thresholds = {
711
+ softBodyChars: this.healthSoftBodyChars,
712
+ stampDensityPerKb: this.healthStampDensityPerKb,
713
+ churnMinPatches: this.healthChurnMinPatches
714
+ };
715
+ const usage = await loadUsage(this.skills.root, this.io);
716
+ const observed = usageObserved(usage);
717
+ const rows = [];
718
+ for (const summary of await this.skills.list()) {
719
+ const record = usage.get(summary.name);
720
+ const assessment = await this.skills.assessHealth(summary.name, thresholds, observed && record ? {
721
+ patchCount: record.patch_count,
722
+ readCount: record.view_count
723
+ } : void 0);
724
+ if (assessment && assessment.verdict !== "healthy") rows.push({
725
+ name: summary.name,
726
+ verdict: assessment.verdict,
727
+ reasons: assessment.reasons
728
+ });
729
+ }
730
+ return rows;
731
+ }
732
+ /** Whether the library has ANY observed read evidence (C observation-window gate for churn signals). */
733
+ async usageObserved() {
734
+ return usageObserved(await loadUsage(this.skills.root, this.io));
735
+ }
694
736
  /** marker info (pinned/bundled/hub-installed) per skill, from the library list. */
695
737
  async protectedNameMap() {
696
738
  const map = /* @__PURE__ */ new Map();
@@ -5,7 +5,7 @@
5
5
  import { Context, Service } from '@deepseek-ai/cordis';
6
6
  import type Schema from '@deepseek-ai/schemastery';
7
7
  import { EvolutionGateSet, SkillLibrary } from '@deepseek-ai/dsh-evolution-core';
8
- import { type CuratorConsolidation, type CuratorNominations, type CuratorRunReport, type ScopeView, type SkillActionResult } from '@deepseek-ai/dsh-evolution-core';
8
+ import { type CuratorConsolidation, type CuratorNominations, type CuratorRunReport, type ScopeView, type SkillActionResult, type SkillHealthVerdict } from '@deepseek-ai/dsh-evolution-core';
9
9
  declare module '@deepseek-ai/cordis' {
10
10
  interface Context {
11
11
  evolutionCurator: EvolutionCurator;
@@ -37,6 +37,12 @@ export interface Config {
37
37
  bootGraceSeconds?: number;
38
38
  /** Max tokens for the optional LLM nomination pass. */
39
39
  curatorReviewMaxTokens?: number;
40
+ /** Structure-health soft body limit (chars) — see DEFAULT_HEALTH_THRESHOLDS (rc.73 A1). */
41
+ healthSoftBodyChars?: number;
42
+ /** Structure-health stamp-density ceiling per KB — see DEFAULT_HEALTH_THRESHOLDS. */
43
+ healthStampDensityPerKb?: number;
44
+ /** Structure-health write-ghost floor: patches at/above with zero reads (A2). */
45
+ healthChurnMinPatches?: number;
40
46
  }
41
47
  /** Outcome of one curator run pass. */
42
48
  export interface CuratorRunOutcome {
@@ -86,6 +92,9 @@ export declare class EvolutionCurator extends Service {
86
92
  private readonly referencedSkillNames;
87
93
  private readonly bootGraceSeconds;
88
94
  private readonly curatorReviewMaxTokens;
95
+ private readonly healthSoftBodyChars;
96
+ private readonly healthStampDensityPerKb;
97
+ private readonly healthChurnMinPatches;
89
98
  private lastRun;
90
99
  private timer;
91
100
  private bootCheck;
@@ -201,6 +210,19 @@ export declare class EvolutionCurator extends Service {
201
210
  * so the view always predicts what a curator pass may touch.
202
211
  */
203
212
  scopeView(): Promise<ScopeView>;
213
+ /**
214
+ * Structure-health view (rc.73 A1, 008 design): degraded skills only,
215
+ * derived on demand — never persisted. Signals for review/curate proposals;
216
+ * the deterministic assessment stays here, refinement stays in the judgment
217
+ * layer.
218
+ */
219
+ healthView(): Promise<Array<{
220
+ name: string;
221
+ verdict: SkillHealthVerdict;
222
+ reasons: string[];
223
+ }>>;
224
+ /** Whether the library has ANY observed read evidence (C observation-window gate for churn signals). */
225
+ usageObserved(): Promise<boolean>;
204
226
  /** marker info (pinned/bundled/hub-installed) per skill, from the library list. */
205
227
  private protectedNameMap;
206
228
  /**
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",
4
+ "version": "0.2.0-rc.2",
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"
36
+ "@lmzhen/dsh-evolution-core": "^0.2.0-rc.2"
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",
43
- "@lmzhen/dsh-evolution-state": "^0.1.0"
42
+ "@lmzhen/dsh-evolution-io": "^0.2.0-rc.2",
43
+ "@lmzhen/dsh-evolution-state": "^0.2.0-rc.2"
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",
49
- "@lmzhen/dsh-evolution-io": "^0.1.0",
50
- "@lmzhen/dsh-evolution-state": "^0.1.0"
48
+ "@lmzhen/dsh-evolution-core": "^0.2.0-rc.2",
49
+ "@lmzhen/dsh-evolution-io": "^0.2.0-rc.2",
50
+ "@lmzhen/dsh-evolution-state": "^0.2.0-rc.2"
51
51
  }
52
52
  }