@lmzhen/dsh-evolution-core 0.1.0-rc.47 → 0.1.0-rc.49
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 +101 -11
- package/lib/types/curator.d.ts +6 -0
- package/lib/types/skill-store.d.ts +5 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -386,6 +386,39 @@ function buildCuratorRunReport(input) {
|
|
|
386
386
|
...input.llmReviewEnabled === void 0 ? {} : { llmReviewEnabled: input.llmReviewEnabled }
|
|
387
387
|
};
|
|
388
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Render a curator run report as a compact human-readable markdown digest
|
|
391
|
+
* (G6): run metadata first, then the notable sections (archived / failed /
|
|
392
|
+
* stale candidates / LLM nominations).
|
|
393
|
+
*/
|
|
394
|
+
function renderCuratorReportMarkdown(report) {
|
|
395
|
+
const lines = [
|
|
396
|
+
`# Curator run ${report.runId}`,
|
|
397
|
+
"",
|
|
398
|
+
`- **Started** ${report.startedAt}`,
|
|
399
|
+
`- **Finished** ${report.finishedAt}`,
|
|
400
|
+
`- **Stale candidates**: ${report.staleCandidates.length}`,
|
|
401
|
+
`- **LLM nominations**: ${report.llmNominations.length}`,
|
|
402
|
+
`- **Archived**: ${report.archived.length}`,
|
|
403
|
+
`- **Failed**: ${report.failed.length}`,
|
|
404
|
+
...report.snapshotPath === void 0 ? [] : [`- **Snapshot**: ${report.snapshotPath}`],
|
|
405
|
+
...report.llmReviewEnabled === void 0 ? [] : [`- **llmReview**: ${report.llmReviewEnabled}`]
|
|
406
|
+
];
|
|
407
|
+
const section = (title, items) => items.length === 0 ? [] : [
|
|
408
|
+
"",
|
|
409
|
+
`## ${title}`,
|
|
410
|
+
"",
|
|
411
|
+
...items.map((item) => `- ${item}`)
|
|
412
|
+
];
|
|
413
|
+
return [
|
|
414
|
+
...lines,
|
|
415
|
+
...section("Archived", report.archived.map((item) => `${item.name} (${item.reason})`)),
|
|
416
|
+
...section("Failed", report.failed.map((item) => `${item.name}: ${item.reason}`)),
|
|
417
|
+
...section("Stale candidates", report.staleCandidates),
|
|
418
|
+
...section("LLM nominations", report.llmNominations),
|
|
419
|
+
""
|
|
420
|
+
].join("\n");
|
|
421
|
+
}
|
|
389
422
|
const NOMINATION_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
390
423
|
/**
|
|
391
424
|
* Parse the curator LLM's YAML nomination block (consolidations + prunings).
|
|
@@ -1897,10 +1930,18 @@ var SkillLibrary = class {
|
|
|
1897
1930
|
root;
|
|
1898
1931
|
limits;
|
|
1899
1932
|
io;
|
|
1900
|
-
|
|
1933
|
+
onMutation;
|
|
1934
|
+
constructor(root = skillsRoot(), io = nodeEvolutionIo(), limits = DEFAULT_SKILL_LIMITS, onMutation) {
|
|
1901
1935
|
this.root = root;
|
|
1902
1936
|
this.io = io;
|
|
1903
1937
|
this.limits = limits;
|
|
1938
|
+
this.onMutation = onMutation;
|
|
1939
|
+
}
|
|
1940
|
+
/** Notify the mutation observer after a successful write; observers must never fail the mutation. */
|
|
1941
|
+
notifyMutation(event) {
|
|
1942
|
+
try {
|
|
1943
|
+
this.onMutation?.(event);
|
|
1944
|
+
} catch {}
|
|
1904
1945
|
}
|
|
1905
1946
|
async list() {
|
|
1906
1947
|
const summaries = [];
|
|
@@ -1909,14 +1950,18 @@ var SkillLibrary = class {
|
|
|
1909
1950
|
const md = await this.io.readText(join(dir, "SKILL.md"));
|
|
1910
1951
|
if (!md) continue;
|
|
1911
1952
|
const parsed = parseFrontmatter(md);
|
|
1912
|
-
|
|
1913
|
-
|
|
1953
|
+
let entries = [];
|
|
1954
|
+
try {
|
|
1955
|
+
entries = await this.io.list(dir);
|
|
1956
|
+
} catch {}
|
|
1957
|
+
const has = (marker) => entries.includes(marker);
|
|
1958
|
+
const protectedBy = has("bundled") ? "bundled" : has("hub-installed") ? "hub-installed" : has("pinned") ? "pinned" : null;
|
|
1914
1959
|
summaries.push({
|
|
1915
1960
|
name,
|
|
1916
1961
|
description: parsed?.frontmatter.description ?? "",
|
|
1917
1962
|
path: dir,
|
|
1918
1963
|
protectedBy,
|
|
1919
|
-
managed,
|
|
1964
|
+
managed: has("hermes-managed"),
|
|
1920
1965
|
archived: false
|
|
1921
1966
|
});
|
|
1922
1967
|
}
|
|
@@ -2087,6 +2132,11 @@ var SkillLibrary = class {
|
|
|
2087
2132
|
await this.io.writeText(join(dir, "SKILL.md"), content.trimEnd() + "\n");
|
|
2088
2133
|
if (origin !== "foreground") await this.io.writeText(markerPath(dir, "hermes-managed"), "");
|
|
2089
2134
|
await this.audit(normalized, "create", null, content, "created");
|
|
2135
|
+
this.notifyMutation({
|
|
2136
|
+
action: "create",
|
|
2137
|
+
name: normalized,
|
|
2138
|
+
filePath: dir
|
|
2139
|
+
});
|
|
2090
2140
|
return {
|
|
2091
2141
|
ok: true,
|
|
2092
2142
|
message: `Skill "${normalized}" created.`,
|
|
@@ -2123,6 +2173,11 @@ var SkillLibrary = class {
|
|
|
2123
2173
|
};
|
|
2124
2174
|
await this.io.writeText(join(dir, "SKILL.md"), content.trimEnd() + "\n");
|
|
2125
2175
|
await this.audit(name, "update", md, content, "updated");
|
|
2176
|
+
this.notifyMutation({
|
|
2177
|
+
action: "update",
|
|
2178
|
+
name,
|
|
2179
|
+
filePath: dir
|
|
2180
|
+
});
|
|
2126
2181
|
return {
|
|
2127
2182
|
ok: true,
|
|
2128
2183
|
message: `Skill "${name}" updated.`,
|
|
@@ -2190,6 +2245,11 @@ var SkillLibrary = class {
|
|
|
2190
2245
|
};
|
|
2191
2246
|
await this.io.writeText(target, patched.trimEnd() + "\n");
|
|
2192
2247
|
await this.audit(name, "patch", md, patched, `patched ${patchLabel}`);
|
|
2248
|
+
this.notifyMutation({
|
|
2249
|
+
action: "patch",
|
|
2250
|
+
name,
|
|
2251
|
+
filePath: dir
|
|
2252
|
+
});
|
|
2193
2253
|
return {
|
|
2194
2254
|
ok: true,
|
|
2195
2255
|
message: `Skill "${name}" patched (${patchLabel}).`,
|
|
@@ -2235,6 +2295,11 @@ var SkillLibrary = class {
|
|
|
2235
2295
|
const reason = options.reason ?? (options.absorbedInto ? `Consolidated into ${options.absorbedInto}` : "Archived by self-evolution curator");
|
|
2236
2296
|
await this.io.writeText(join(dest, ".archive-reason"), `${(/* @__PURE__ */ new Date()).toISOString()}: ${reason}\n`);
|
|
2237
2297
|
await this.audit(name, "archive", md, null, reason);
|
|
2298
|
+
this.notifyMutation({
|
|
2299
|
+
action: "archive",
|
|
2300
|
+
name,
|
|
2301
|
+
archivedPath: dest
|
|
2302
|
+
});
|
|
2238
2303
|
return {
|
|
2239
2304
|
ok: true,
|
|
2240
2305
|
message: `Skill "${name}" archived to .archive.`,
|
|
@@ -2314,6 +2379,11 @@ var SkillLibrary = class {
|
|
|
2314
2379
|
message: `Consolidation failed and was rolled back: ${error instanceof Error ? error.message : String(error)}`
|
|
2315
2380
|
};
|
|
2316
2381
|
}
|
|
2382
|
+
this.notifyMutation({
|
|
2383
|
+
action: "consolidate",
|
|
2384
|
+
name: targetName,
|
|
2385
|
+
filePath: targetDir
|
|
2386
|
+
});
|
|
2317
2387
|
return {
|
|
2318
2388
|
ok: true,
|
|
2319
2389
|
message: `Consolidated ${normalizedSources.join(", ")} into "${targetName}".`,
|
|
@@ -2359,6 +2429,11 @@ var SkillLibrary = class {
|
|
|
2359
2429
|
await this.io.remove(source);
|
|
2360
2430
|
}
|
|
2361
2431
|
if (await this.io.exists(join(dest, ".archive-reason"))) await this.io.remove(join(dest, ".archive-reason"));
|
|
2432
|
+
this.notifyMutation({
|
|
2433
|
+
action: "restore",
|
|
2434
|
+
name,
|
|
2435
|
+
filePath: dest
|
|
2436
|
+
});
|
|
2362
2437
|
return {
|
|
2363
2438
|
ok: true,
|
|
2364
2439
|
message: `Skill "${name}" restored from .archive.`,
|
|
@@ -2400,6 +2475,11 @@ var SkillLibrary = class {
|
|
|
2400
2475
|
const existing = await this.io.readText(target).catch(() => null);
|
|
2401
2476
|
await this.io.writeText(target, content);
|
|
2402
2477
|
await this.audit(name, "write_file", existing, content, `wrote ${filePath}`);
|
|
2478
|
+
this.notifyMutation({
|
|
2479
|
+
action: "write_file",
|
|
2480
|
+
name,
|
|
2481
|
+
filePath: target
|
|
2482
|
+
});
|
|
2403
2483
|
return {
|
|
2404
2484
|
ok: true,
|
|
2405
2485
|
message: `Support file "${filePath}" written to "${name}".`,
|
|
@@ -2436,6 +2516,11 @@ var SkillLibrary = class {
|
|
|
2436
2516
|
const before = await this.io.readText(target).catch(() => null);
|
|
2437
2517
|
await this.io.remove(target);
|
|
2438
2518
|
await this.audit(name, "remove_file", before, null, `removed ${filePath}`);
|
|
2519
|
+
this.notifyMutation({
|
|
2520
|
+
action: "remove_file",
|
|
2521
|
+
name,
|
|
2522
|
+
filePath: target
|
|
2523
|
+
});
|
|
2439
2524
|
return {
|
|
2440
2525
|
ok: true,
|
|
2441
2526
|
message: `Support file "${filePath}" removed from "${name}".`,
|
|
@@ -2454,7 +2539,9 @@ var SkillLibrary = class {
|
|
|
2454
2539
|
let dest = join(backupRoot, `skills-${stamp}`);
|
|
2455
2540
|
while (await this.io.exists(dest)) dest = join(backupRoot, `skills-${stamp}-${Math.random().toString(36).slice(2, 8)}`);
|
|
2456
2541
|
const names = await listNames(this.root, this.io);
|
|
2457
|
-
|
|
2542
|
+
await Promise.all(names.map(async (name) => {
|
|
2543
|
+
await this.io.copy(this.dirOf(name), join(dest, name));
|
|
2544
|
+
}));
|
|
2458
2545
|
const sidecars = [];
|
|
2459
2546
|
for (const sidecar of [usageFile(this.root), suppressedFile(this.root)]) if (await this.io.exists(sidecar)) {
|
|
2460
2547
|
const name = basename(sidecar);
|
|
@@ -2467,12 +2554,11 @@ var SkillLibrary = class {
|
|
|
2467
2554
|
await this.io.copy(archiveRoot, join(dest, ".archive"));
|
|
2468
2555
|
hasArchive = true;
|
|
2469
2556
|
}
|
|
2470
|
-
const
|
|
2471
|
-
|
|
2472
|
-
|
|
2557
|
+
const validExtras = extras.filter((extra) => SNAPSHOT_EXTRA_NAME_RE.test(extra.name));
|
|
2558
|
+
const extraNames = validExtras.map((extra) => extra.name);
|
|
2559
|
+
await Promise.all(validExtras.map(async (extra) => {
|
|
2473
2560
|
await this.io.writeText(join(dest, "extras", extra.name), extra.content);
|
|
2474
|
-
|
|
2475
|
-
}
|
|
2561
|
+
}));
|
|
2476
2562
|
await this.io.writeText(join(dest, "manifest.json"), JSON.stringify({
|
|
2477
2563
|
reason,
|
|
2478
2564
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -2578,6 +2664,10 @@ var SkillLibrary = class {
|
|
|
2578
2664
|
} else if (manifest.hasArchive === false) await this.io.remove(archiveRoot);
|
|
2579
2665
|
}
|
|
2580
2666
|
const snapshotExtras = await this.readSnapshotExtras(latest.path);
|
|
2667
|
+
this.notifyMutation({
|
|
2668
|
+
action: "restore",
|
|
2669
|
+
name: "snapshot"
|
|
2670
|
+
});
|
|
2581
2671
|
return {
|
|
2582
2672
|
ok: true,
|
|
2583
2673
|
message: `Restored skill tree from ${latest.path}`,
|
|
@@ -2652,4 +2742,4 @@ var JsonState = class JsonState {
|
|
|
2652
2742
|
}
|
|
2653
2743
|
};
|
|
2654
2744
|
//#endregion
|
|
2655
|
-
export { COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CONSOLIDATION_FAILURES, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MIN_IDLE_HOURS, DEFAULT_MUTATION_CAP, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_STALE_AFTER_DAYS, DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS, DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS, DEFAULT_SUBSTANTIVE_MIN_USER_CHARS, DEFAULT_USER_CHAR_LIMIT, DSH_AUTHORING_STANDARDS, ENTRY_DELIMITER, EvolutionGateSet, JsonState, LOW_QUALITY_THRESHOLD, MAX_DESCRIPTION_LENGTH, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MEMORY_REVIEW_PROMPT, MUTATIONS_FILE_VERSION, MemoryStore, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROMPT_BUNDLE_VERSION, PROTECTED_BUILTIN_SKILLS, QUALITY_WEIGHTS, SKILL_NAME_RE, SKILL_REVIEW_PROMPT, SNAPSHOT_EXTRA_NAME_RE, SUPPORT_DIRS, SUPPRESSED_FILE_VERSION, SkillLibrary, advanceReview, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, computeDedupGroups, computeLifecycleTransitions, computeQualityScores, computeScopeView, contentHash, createGateSet, emptyRecord, evaluateThreat, evolutionHome, evolutionIoAdapter, foldTurn, getRecord, latestActivityAt, lifecycleCandidate, loadMutations, loadSuppressedNames, loadUsage, markAgentCreated, memoryRoot, mutationsFile, nodeEvolutionIo, normalizeUsageRecord, observeEvent, parseCuratorNominations, parseFrontmatter, recordMutation, relatedSkillNames, resolveOrigins, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, usageFile, validateFrontmatter, verifyPromptBundle };
|
|
2745
|
+
export { COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CONSOLIDATION_FAILURES, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MIN_IDLE_HOURS, DEFAULT_MUTATION_CAP, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_STALE_AFTER_DAYS, DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS, DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS, DEFAULT_SUBSTANTIVE_MIN_USER_CHARS, DEFAULT_USER_CHAR_LIMIT, DSH_AUTHORING_STANDARDS, ENTRY_DELIMITER, EvolutionGateSet, JsonState, LOW_QUALITY_THRESHOLD, MAX_DESCRIPTION_LENGTH, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MEMORY_REVIEW_PROMPT, MUTATIONS_FILE_VERSION, MemoryStore, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROMPT_BUNDLE_VERSION, PROTECTED_BUILTIN_SKILLS, QUALITY_WEIGHTS, SKILL_NAME_RE, SKILL_REVIEW_PROMPT, SNAPSHOT_EXTRA_NAME_RE, SUPPORT_DIRS, SUPPRESSED_FILE_VERSION, SkillLibrary, advanceReview, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, computeDedupGroups, computeLifecycleTransitions, computeQualityScores, computeScopeView, contentHash, createGateSet, emptyRecord, evaluateThreat, evolutionHome, evolutionIoAdapter, foldTurn, getRecord, latestActivityAt, lifecycleCandidate, loadMutations, loadSuppressedNames, loadUsage, markAgentCreated, memoryRoot, mutationsFile, nodeEvolutionIo, normalizeUsageRecord, observeEvent, parseCuratorNominations, parseFrontmatter, recordMutation, relatedSkillNames, renderCuratorReportMarkdown, resolveOrigins, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, usageFile, validateFrontmatter, verifyPromptBundle };
|
package/lib/types/curator.d.ts
CHANGED
|
@@ -75,6 +75,12 @@ export interface CuratorReportInput {
|
|
|
75
75
|
llmReviewEnabled?: boolean;
|
|
76
76
|
}
|
|
77
77
|
export declare function buildCuratorRunReport(input: CuratorReportInput): CuratorRunReport;
|
|
78
|
+
/**
|
|
79
|
+
* Render a curator run report as a compact human-readable markdown digest
|
|
80
|
+
* (G6): run metadata first, then the notable sections (archived / failed /
|
|
81
|
+
* stale candidates / LLM nominations).
|
|
82
|
+
*/
|
|
83
|
+
export declare function renderCuratorReportMarkdown(report: CuratorRunReport): string;
|
|
78
84
|
/** One LLM-nominated consolidation: `from` merges into the umbrella `into`. */
|
|
79
85
|
export interface CuratorConsolidation {
|
|
80
86
|
from: string;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { type EvolutionIoLike } from './io.ts';
|
|
10
10
|
import { type MutationRecord } from './mutations.ts';
|
|
11
|
+
import type { EvolutionSkillMutatedEvent } from './events.ts';
|
|
11
12
|
export interface SkillLimits {
|
|
12
13
|
maxNameLength: number;
|
|
13
14
|
maxDescriptionLength: number;
|
|
@@ -97,7 +98,10 @@ export declare class SkillLibrary {
|
|
|
97
98
|
readonly root: string;
|
|
98
99
|
readonly limits: SkillLimits;
|
|
99
100
|
private readonly io;
|
|
100
|
-
|
|
101
|
+
private readonly onMutation;
|
|
102
|
+
constructor(root?: string, io?: EvolutionIoLike, limits?: SkillLimits, onMutation?: (event: EvolutionSkillMutatedEvent) => void);
|
|
103
|
+
/** Notify the mutation observer after a successful write; observers must never fail the mutation. */
|
|
104
|
+
private notifyMutation;
|
|
101
105
|
list(): Promise<SkillSummary[]>;
|
|
102
106
|
read(rawName: string): Promise<string | null>;
|
|
103
107
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-core",
|
|
3
3
|
"description": "Shared stores, prompts, signals and lifecycle logic for the dsh-evolution plugin family (community build)",
|
|
4
|
-
"version": "0.1.0-rc.
|
|
4
|
+
"version": "0.1.0-rc.49",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|