@lmzhen/dsh-evolution-curator 0.24.0 → 0.25.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/lib/index.js +62 -6
- package/lib/types/index.d.ts +25 -1
- package/package.json +7 -7
package/lib/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { join } from "node:path";
|
|
|
4
4
|
import { BlockAssembler, createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
5
5
|
import z from "@deepseek-ai/schemastery";
|
|
6
6
|
import { preferProvider } from "@lmzhen/dsh-evolution-io";
|
|
7
|
-
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_REVIEW_TIMEOUT_MS, 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
|
+
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_REVIEW_TIMEOUT_MS, 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, lintSkill, 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";
|
|
8
8
|
//#region lib/types/index.js
|
|
9
9
|
/**
|
|
10
10
|
* Deterministic skill lifecycle curator with interval gate and archive.
|
|
@@ -33,6 +33,24 @@ function gateConsolidations(consolidations, gates) {
|
|
|
33
33
|
const gateSet = gates instanceof EvolutionGateSet ? gates : new EvolutionGateSet(gates);
|
|
34
34
|
return consolidations.filter((n) => !gateSet.isBlocked(n.from) && !gateSet.isBlocked(n.into));
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* G5 (in-use protection): which skills are POINTED AT by others, and by whom.
|
|
38
|
+
*
|
|
39
|
+
* Pure: derived from the bodies already in hand, using `relatedSkillNames` — the single reader of
|
|
40
|
+
* that frontmatter field — so this map can never disagree with the catalog or the audit. The value
|
|
41
|
+
* is a Set of SOURCES, not a boolean, because a refusal has to be able to name the referrers.
|
|
42
|
+
* @param contents - skill name to its whole SKILL.md text.
|
|
43
|
+
* @returns target name to the set of skills naming it; targets nobody names are absent.
|
|
44
|
+
*/
|
|
45
|
+
function referencedSkillNames(contents) {
|
|
46
|
+
const referencedBy = /* @__PURE__ */ new Map();
|
|
47
|
+
for (const [owner, text] of contents) for (const target of relatedSkillNames(text, owner)) {
|
|
48
|
+
const sources = referencedBy.get(target) ?? /* @__PURE__ */ new Set();
|
|
49
|
+
sources.add(owner);
|
|
50
|
+
referencedBy.set(target, sources);
|
|
51
|
+
}
|
|
52
|
+
return referencedBy;
|
|
53
|
+
}
|
|
36
54
|
var EvolutionCurator = class extends Service {
|
|
37
55
|
static inject = ["evolutionIo"];
|
|
38
56
|
static Config = z.object({
|
|
@@ -691,8 +709,9 @@ var EvolutionCurator = class extends Service {
|
|
|
691
709
|
const text = await this.skills.read(name);
|
|
692
710
|
if (text) contents.set(name, text);
|
|
693
711
|
}
|
|
712
|
+
const referencedBy = referencedSkillNames(contents);
|
|
694
713
|
const protectedNames = await this.protectedNameMap();
|
|
695
|
-
const dedupMembers = [...new Set(computeDedupGroups({ contents }).groups.filter((group) => group.length >= 2).flat())].filter((name) => !protectedNames.has(name));
|
|
714
|
+
const dedupMembers = [...new Set(computeDedupGroups({ contents }).groups.filter((group) => group.length >= 2).flat())].filter((name) => !protectedNames.has(name) && !referencedBy.has(name));
|
|
696
715
|
await this.scoreTree(usage, treeNames, contents);
|
|
697
716
|
const result = computeLifecycleTransitions(usage, {
|
|
698
717
|
staleAfterDays: lifecycle.staleAfterDays,
|
|
@@ -1219,10 +1238,47 @@ var EvolutionCurator = class extends Service {
|
|
|
1219
1238
|
patchCount: record.patch_count,
|
|
1220
1239
|
readCount: record.view_count
|
|
1221
1240
|
} : void 0);
|
|
1222
|
-
if (assessment
|
|
1241
|
+
if (assessment !== null) {
|
|
1242
|
+
rows.push({
|
|
1243
|
+
name: summary.name,
|
|
1244
|
+
verdict: assessment.verdict,
|
|
1245
|
+
dims: assessment.dims,
|
|
1246
|
+
findings: assessment.findings
|
|
1247
|
+
});
|
|
1248
|
+
continue;
|
|
1249
|
+
}
|
|
1250
|
+
const findings = lintSkill({
|
|
1251
|
+
skillName: summary.name,
|
|
1252
|
+
dims: {
|
|
1253
|
+
bodyChars: null,
|
|
1254
|
+
bodyTokens: null,
|
|
1255
|
+
stampDensityPerKb: null,
|
|
1256
|
+
stampHits: null,
|
|
1257
|
+
supportGroups: 0,
|
|
1258
|
+
supportFiles: null,
|
|
1259
|
+
churnPatches: null,
|
|
1260
|
+
churnReads: null
|
|
1261
|
+
},
|
|
1262
|
+
softLineChars: thresholds.softBodyChars,
|
|
1263
|
+
overSoftLine: false,
|
|
1264
|
+
overTwiceSoftLine: false,
|
|
1265
|
+
stampLimitPerKb: thresholds.stampDensityPerKb,
|
|
1266
|
+
churnMinPatches: thresholds.churnMinPatches,
|
|
1267
|
+
readable: false
|
|
1268
|
+
});
|
|
1269
|
+
rows.push({
|
|
1223
1270
|
name: summary.name,
|
|
1224
|
-
verdict:
|
|
1225
|
-
|
|
1271
|
+
verdict: "warn",
|
|
1272
|
+
dims: {
|
|
1273
|
+
bodyChars: null,
|
|
1274
|
+
bodyTokens: null,
|
|
1275
|
+
stampDensityPerKb: null,
|
|
1276
|
+
supportGroups: 0,
|
|
1277
|
+
supportFiles: null,
|
|
1278
|
+
churnPatches: null,
|
|
1279
|
+
churnReads: null
|
|
1280
|
+
},
|
|
1281
|
+
findings
|
|
1226
1282
|
});
|
|
1227
1283
|
}
|
|
1228
1284
|
return rows;
|
|
@@ -1426,4 +1482,4 @@ var EvolutionCurator = class extends Service {
|
|
|
1426
1482
|
}
|
|
1427
1483
|
};
|
|
1428
1484
|
//#endregion
|
|
1429
|
-
export { EvolutionCurator, EvolutionCurator as default, gateConsolidations, validateCuratorSettings };
|
|
1485
|
+
export { EvolutionCurator, EvolutionCurator as default, gateConsolidations, referencedSkillNames, validateCuratorSettings };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -148,6 +148,16 @@ export declare function gateConsolidations(consolidations: CuratorConsolidation[
|
|
|
148
148
|
referenced?: ReadonlySet<string>;
|
|
149
149
|
suppressed?: ReadonlySet<string>;
|
|
150
150
|
}): CuratorConsolidation[];
|
|
151
|
+
/**
|
|
152
|
+
* G5 (in-use protection): which skills are POINTED AT by others, and by whom.
|
|
153
|
+
*
|
|
154
|
+
* Pure: derived from the bodies already in hand, using `relatedSkillNames` — the single reader of
|
|
155
|
+
* that frontmatter field — so this map can never disagree with the catalog or the audit. The value
|
|
156
|
+
* is a Set of SOURCES, not a boolean, because a refusal has to be able to name the referrers.
|
|
157
|
+
* @param contents - skill name to its whole SKILL.md text.
|
|
158
|
+
* @returns target name to the set of skills naming it; targets nobody names are absent.
|
|
159
|
+
*/
|
|
160
|
+
export declare function referencedSkillNames(contents: ReadonlyMap<string, string>): Map<string, Set<string>>;
|
|
151
161
|
export declare class EvolutionCurator extends Service {
|
|
152
162
|
static inject: string[];
|
|
153
163
|
static Config: z<Schemastery.ObjectS<NoInfer<{
|
|
@@ -495,7 +505,21 @@ export declare class EvolutionCurator extends Service {
|
|
|
495
505
|
healthView(): Promise<Array<{
|
|
496
506
|
name: string;
|
|
497
507
|
verdict: SkillHealthVerdict;
|
|
498
|
-
|
|
508
|
+
dims: {
|
|
509
|
+
bodyChars: number | null;
|
|
510
|
+
bodyTokens: number | null;
|
|
511
|
+
stampDensityPerKb: number | null;
|
|
512
|
+
supportGroups: number;
|
|
513
|
+
supportFiles: number | null;
|
|
514
|
+
churnPatches: number | null;
|
|
515
|
+
churnReads: number | null;
|
|
516
|
+
};
|
|
517
|
+
findings: Array<{
|
|
518
|
+
severity: 'warn' | 'error';
|
|
519
|
+
rule: string;
|
|
520
|
+
message: string;
|
|
521
|
+
count: number;
|
|
522
|
+
}>;
|
|
499
523
|
}>>;
|
|
500
524
|
/** Whether the library has ANY observed read evidence (C observation-window gate for churn signals). */
|
|
501
525
|
usageObserved(): Promise<boolean>;
|
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.25.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.25.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.25.0",
|
|
37
|
+
"@lmzhen/dsh-evolution-state": "^0.25.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.25.0",
|
|
43
|
+
"@lmzhen/dsh-evolution-io": "^0.25.0",
|
|
44
|
+
"@lmzhen/dsh-evolution-state": "^0.25.0"
|
|
45
45
|
}
|
|
46
46
|
}
|