@lmzhen/dsh-evolution-curator 0.18.1 → 0.19.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 +21 -57
- package/lib/types/index.d.ts +5 -3
- 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_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MIN_IDLE_HOURS, 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, loadSuppressedNames, loadUsage, markerEntryName, mutateUsage, newSkillLibrary, paramRowId, parseCuratorNominations, parseFrontmatter, pickWithPolicy, policyStageLimits, probeList,
|
|
6
|
+
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_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, loadSuppressedNames, loadUsage, markerEntryName, mutateUsage, newSkillLibrary, paramRowId, parseCuratorNominations, parseFrontmatter, pickWithPolicy, policyStageLimits, probeList, probeText, readNumberParam, relatedSkillNames, releaseInstance, renderCuratorReportMarkdown, reportTime, reportsSweepLockTarget, sessionLastEventTime, sweepReports, transactIo, updateSuppressedNames, usageObserved, userSetKeys, verifyPromptBundle } 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.
|
|
@@ -1096,51 +1096,27 @@ var EvolutionCurator = class extends Service {
|
|
|
1096
1096
|
});
|
|
1097
1097
|
}
|
|
1098
1098
|
/** The sweep `retainReports` holds the per-home lock for. A caller MUST hold
|
|
1099
|
-
* that lock: the listing and the deletions are not atomic on their own.
|
|
1099
|
+
* that lock: the listing and the deletions are not atomic on their own.
|
|
1100
|
+
* 0.19.0 (S2): the sweep itself now lives in core (`sweepReports`) — the
|
|
1101
|
+
* maintenance run reports added in 0.19.0 need the same window, and a second
|
|
1102
|
+
* copy of "list, order, delete beyond the window" is the near-duplicate class
|
|
1103
|
+
* this family treats as a defect. The lock and the two windows stay here. */
|
|
1100
1104
|
async sweepReports(keep, errorKeep) {
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
const mtime = isPresent(probed) ? probed.value : null;
|
|
1117
|
-
if (startedAt !== null) (name.startsWith("curator-error-") ? errors : real).push({
|
|
1118
|
-
name,
|
|
1119
|
-
startedAt,
|
|
1120
|
-
mtime
|
|
1121
|
-
});
|
|
1122
|
-
else if (!unorderableWarned) {
|
|
1123
|
-
unorderableWarned = true;
|
|
1124
|
-
this.ctx.logger.warn(`evolution-curator: report "${name}" carries no usable timestamp and this backend has no mtime probe - it is kept outside the retention window`);
|
|
1125
|
-
}
|
|
1126
|
-
} catch {}
|
|
1127
|
-
const newestFirst = (a, b) => b.startedAt - a.startedAt || (b.mtime ?? 0) - (a.mtime ?? 0) || b.name.localeCompare(a.name);
|
|
1128
|
-
real.sort(newestFirst);
|
|
1129
|
-
errors.sort(newestFirst);
|
|
1130
|
-
await this.pruneReportList(reportsRoot, real, keep);
|
|
1131
|
-
await this.pruneReportList(reportsRoot, errors, errorKeep);
|
|
1132
|
-
}
|
|
1133
|
-
/** Remove the oldest reports beyond `keep` (each with its `.md` digest, best-effort). */
|
|
1134
|
-
async pruneReportList(reportsRoot, dated, keep) {
|
|
1135
|
-
for (const oldReport of dated.slice(keep)) {
|
|
1136
|
-
const stem = oldReport.name.replace(/\.json$/, "");
|
|
1137
|
-
try {
|
|
1138
|
-
await this.io.remove(join(reportsRoot, oldReport.name));
|
|
1139
|
-
} catch {}
|
|
1140
|
-
try {
|
|
1141
|
-
await this.io.remove(join(reportsRoot, `${stem}.md`));
|
|
1142
|
-
} catch {}
|
|
1143
|
-
}
|
|
1105
|
+
await sweepReports({
|
|
1106
|
+
io: this.io,
|
|
1107
|
+
dir: join(evolutionHome(), "reports"),
|
|
1108
|
+
buckets: [{
|
|
1109
|
+
prefix: "curator-error-",
|
|
1110
|
+
keep: errorKeep
|
|
1111
|
+
}, {
|
|
1112
|
+
prefix: "curator-",
|
|
1113
|
+
keep
|
|
1114
|
+
}],
|
|
1115
|
+
warn: (message) => {
|
|
1116
|
+
this.ctx.logger.warn(message);
|
|
1117
|
+
},
|
|
1118
|
+
owner: "evolution-curator"
|
|
1119
|
+
});
|
|
1144
1120
|
}
|
|
1145
1121
|
async latestReport() {
|
|
1146
1122
|
const reportsRoot = join(evolutionHome(), "reports");
|
|
@@ -1438,17 +1414,5 @@ var EvolutionCurator = class extends Service {
|
|
|
1438
1414
|
}
|
|
1439
1415
|
}
|
|
1440
1416
|
};
|
|
1441
|
-
/**
|
|
1442
|
-
* v43 FLOW2-1: the per-home lock target for the report retention sweep.
|
|
1443
|
-
* `transactIo` takes the IO write lock on THIS path (minting `<path>.lock` with
|
|
1444
|
-
* the io protocol's `pid:token` body) and holds it for the whole task; nothing
|
|
1445
|
-
* ever writes the target, because the sweep's exclusion is the point. It lives
|
|
1446
|
-
* inside `<home>/reports` next to the directory it protects: the sweep's own
|
|
1447
|
-
* name filter (`curator-*.json`) ignores it, and the lock file is removed on
|
|
1448
|
-
* release.
|
|
1449
|
-
*/
|
|
1450
|
-
function reportsSweepLockTarget() {
|
|
1451
|
-
return join(evolutionHome(), "reports", ".retention");
|
|
1452
|
-
}
|
|
1453
1417
|
//#endregion
|
|
1454
1418
|
export { EvolutionCurator, EvolutionCurator as default, gateConsolidations, validateCuratorSettings };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -450,10 +450,12 @@ export declare class EvolutionCurator extends Service {
|
|
|
450
450
|
*/
|
|
451
451
|
private retainReports;
|
|
452
452
|
/** The sweep `retainReports` holds the per-home lock for. A caller MUST hold
|
|
453
|
-
* that lock: the listing and the deletions are not atomic on their own.
|
|
453
|
+
* that lock: the listing and the deletions are not atomic on their own.
|
|
454
|
+
* 0.19.0 (S2): the sweep itself now lives in core (`sweepReports`) — the
|
|
455
|
+
* maintenance run reports added in 0.19.0 need the same window, and a second
|
|
456
|
+
* copy of "list, order, delete beyond the window" is the near-duplicate class
|
|
457
|
+
* this family treats as a defect. The lock and the two windows stay here. */
|
|
454
458
|
private sweepReports;
|
|
455
|
-
/** Remove the oldest reports beyond `keep` (each with its `.md` digest, best-effort). */
|
|
456
|
-
private pruneReportList;
|
|
457
459
|
latestReport(): Promise<CuratorRunReport | null>;
|
|
458
460
|
/**
|
|
459
461
|
* Read-only lifecycle scope classification: which skills are in scope,
|
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.19.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.19.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.19.0",
|
|
37
|
+
"@lmzhen/dsh-evolution-state": "^0.19.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.19.0",
|
|
43
|
+
"@lmzhen/dsh-evolution-io": "^0.19.0",
|
|
44
|
+
"@lmzhen/dsh-evolution-state": "^0.19.0"
|
|
45
45
|
}
|
|
46
46
|
}
|