@lmzhen/dsh-evolution-core 0.3.69 → 0.3.71
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 +125 -26
- package/lib/types/constants.d.ts +4 -0
- package/lib/types/evolution-events.d.ts +1 -1
- package/lib/types/skill-store.d.ts +44 -4
- package/package.json +5 -5
package/lib/index.js
CHANGED
|
@@ -1045,6 +1045,10 @@ const MAX_TIMER_DELAY_MS = 2147483647;
|
|
|
1045
1045
|
const DEFAULT_MEMORY_REVIEW_MODEL = "deepseek-v4-flash";
|
|
1046
1046
|
const DEFAULT_SKILL_REVIEW_MODEL = "deepseek-v4-pro";
|
|
1047
1047
|
const DEFAULT_CURATOR_MODEL = "deepseek-v4-pro";
|
|
1048
|
+
/** Order of the `evolution:memory-guidance` section (before the skills one). */
|
|
1049
|
+
const MEMORY_GUIDANCE_SECTION_ORDER = 11e3;
|
|
1050
|
+
/** Order of the `evolution-skills-guidance` section (last of the two). */
|
|
1051
|
+
const SKILLS_GUIDANCE_SECTION_ORDER = 11100;
|
|
1048
1052
|
//#endregion
|
|
1049
1053
|
//#region lib/types/gates.js
|
|
1050
1054
|
/**
|
|
@@ -1643,11 +1647,11 @@ async function readEvolutionEvents(io, path) {
|
|
|
1643
1647
|
* malformed (or unreadable) ARCHIVE is skipped — it never bricks the boot and
|
|
1644
1648
|
* it is still flagged.
|
|
1645
1649
|
*/
|
|
1646
|
-
async function readEvolutionTimeline(io, path) {
|
|
1650
|
+
async function readEvolutionTimeline(io, path, archives) {
|
|
1647
1651
|
const dir = dirname(path);
|
|
1648
1652
|
let malformed = false;
|
|
1649
1653
|
const bySeq = /* @__PURE__ */ new Map();
|
|
1650
|
-
for (const name of await listEventArchives(io, path)) {
|
|
1654
|
+
for (const name of archives ?? await listEventArchives(io, path)) {
|
|
1651
1655
|
const read = await readEvolutionEvents(io, join(dir, name));
|
|
1652
1656
|
if (read.malformed) malformed = true;
|
|
1653
1657
|
for (const event of read.events) bySeq.set(event.seq, event);
|
|
@@ -3698,8 +3702,9 @@ function foldTurn(session, fromSeq) {
|
|
|
3698
3702
|
memorySignal: false,
|
|
3699
3703
|
skillSignal: false
|
|
3700
3704
|
};
|
|
3701
|
-
|
|
3702
|
-
|
|
3705
|
+
const events = session.snapshotEvents();
|
|
3706
|
+
for (let index = Math.max(0, fromSeq); index < events.length; index += 1) {
|
|
3707
|
+
const event = events[index];
|
|
3703
3708
|
if (event) observeEvent(signal, event);
|
|
3704
3709
|
}
|
|
3705
3710
|
return signal;
|
|
@@ -3883,6 +3888,65 @@ const DEFAULT_SKILL_LIMITS = {
|
|
|
3883
3888
|
maxSkillContentChars: MAX_SKILL_CONTENT_CHARS,
|
|
3884
3889
|
maxSkillFileBytes: MAX_SKILL_FILE_BYTES
|
|
3885
3890
|
};
|
|
3891
|
+
/**
|
|
3892
|
+
* Evaluate a stage-time anchor against the bytes a locked read observed.
|
|
3893
|
+
* @param anchor - the caller's anchor, or `undefined` for an unanchored write.
|
|
3894
|
+
* @param current - the bytes the write lock read (`null` = the target is absent).
|
|
3895
|
+
* @returns `match` when the write may proceed, otherwise the refusal verdict.
|
|
3896
|
+
*/
|
|
3897
|
+
function anchorVerdict(anchor, current) {
|
|
3898
|
+
if (anchor === void 0) return "match";
|
|
3899
|
+
if ("absent" in anchor) return current === null ? "match" : "drift";
|
|
3900
|
+
if (current === null) return "missing";
|
|
3901
|
+
return contentHash(current) === anchor.sha256 ? "match" : "drift";
|
|
3902
|
+
}
|
|
3903
|
+
/**
|
|
3904
|
+
* Build the refusal for a skill write whose anchor did not hold. The wording is
|
|
3905
|
+
* the library's own; a caller with staged-replay wording (the skill tool, the
|
|
3906
|
+
* review plan) re-words it from {@link SkillActionResult.anchor}.
|
|
3907
|
+
* @param name - the skill name the refusal names.
|
|
3908
|
+
* @param verdict - the non-matching verdict.
|
|
3909
|
+
* @returns the refusal result (nothing was written).
|
|
3910
|
+
*/
|
|
3911
|
+
function anchorRefusal(name, verdict) {
|
|
3912
|
+
return {
|
|
3913
|
+
ok: false,
|
|
3914
|
+
stale: true,
|
|
3915
|
+
anchor: verdict,
|
|
3916
|
+
message: verdict === "missing" ? `Skill "${name}" not found.` : `Skill "${name}" changed since it was read; the write was refused to avoid overwriting newer content.`
|
|
3917
|
+
};
|
|
3918
|
+
}
|
|
3919
|
+
/**
|
|
3920
|
+
* Build the refusal for a support-file write/remove whose anchor did not hold.
|
|
3921
|
+
* @param name - the owning skill name.
|
|
3922
|
+
* @param filePath - the support-file path inside the skill.
|
|
3923
|
+
* @param verdict - the non-matching verdict.
|
|
3924
|
+
* @returns the refusal result (nothing was written or removed).
|
|
3925
|
+
*/
|
|
3926
|
+
/**
|
|
3927
|
+
* Refusal for a target the locked read could not verify at all (EISDIR, an
|
|
3928
|
+
* unreadable file). A staged replay reports "could not be verified" instead of
|
|
3929
|
+
* propagating an exception: nothing was read, so nothing can have been written.
|
|
3930
|
+
* @param name - the owning skill name.
|
|
3931
|
+
* @param filePath - the support-file path, or `null` for the skill body.
|
|
3932
|
+
* @returns the refusal result.
|
|
3933
|
+
*/
|
|
3934
|
+
function anchorUnverifiable(name, filePath) {
|
|
3935
|
+
return {
|
|
3936
|
+
ok: false,
|
|
3937
|
+
stale: true,
|
|
3938
|
+
anchor: "drift",
|
|
3939
|
+
message: filePath === null ? `Skill "${name}" could not be read to verify the staged content.` : `Support file "${filePath}" of "${name}" could not be read to verify the staged content.`
|
|
3940
|
+
};
|
|
3941
|
+
}
|
|
3942
|
+
function anchorRefusalFile(name, filePath, verdict) {
|
|
3943
|
+
return {
|
|
3944
|
+
ok: false,
|
|
3945
|
+
stale: true,
|
|
3946
|
+
anchor: verdict,
|
|
3947
|
+
message: verdict === "missing" ? `File "${filePath}" not found in skill "${name}".` : `Support file "${filePath}" of "${name}" changed since it was read; the write was refused to avoid overwriting newer content.`
|
|
3948
|
+
};
|
|
3949
|
+
}
|
|
3886
3950
|
/** Upper bound of moves per restructure proposal (validator and core agree). */
|
|
3887
3951
|
const MAX_RESTRUCTURE_MOVES = 5;
|
|
3888
3952
|
/** Restructure targets are plain markdown files under references/ — no
|
|
@@ -4642,9 +4706,11 @@ var SkillLibrary = class {
|
|
|
4642
4706
|
* mutation event are issued ONLY when a write actually lands, so a no-op
|
|
4643
4707
|
* never inflates the mutation-maturity counter.
|
|
4644
4708
|
*/
|
|
4645
|
-
async runSingleWrite(path, task) {
|
|
4709
|
+
async runSingleWrite(path, task, readFailure) {
|
|
4646
4710
|
let outcome;
|
|
4711
|
+
const progress = { entered: false };
|
|
4647
4712
|
const run = async (current) => {
|
|
4713
|
+
progress.entered = true;
|
|
4648
4714
|
const o = await task(current ?? null);
|
|
4649
4715
|
outcome = {
|
|
4650
4716
|
...o,
|
|
@@ -4657,11 +4723,18 @@ var SkillLibrary = class {
|
|
|
4657
4723
|
if (this.transact) try {
|
|
4658
4724
|
await this.transact(this.io, path, run);
|
|
4659
4725
|
} catch (error) {
|
|
4726
|
+
if (!progress.entered && readFailure !== void 0) return readFailure;
|
|
4660
4727
|
if (!committedOnly(error)) throw error;
|
|
4661
4728
|
durabilityWarning = error instanceof Error ? error.message : String(error);
|
|
4662
4729
|
}
|
|
4663
4730
|
else {
|
|
4664
|
-
|
|
4731
|
+
let current;
|
|
4732
|
+
try {
|
|
4733
|
+
current = await this.io.readText(path);
|
|
4734
|
+
} catch (error) {
|
|
4735
|
+
if (readFailure !== void 0) return readFailure;
|
|
4736
|
+
throw error;
|
|
4737
|
+
}
|
|
4665
4738
|
const next = await run(current);
|
|
4666
4739
|
if (next !== null && next !== current) try {
|
|
4667
4740
|
await this.io.writeText(path, next);
|
|
@@ -4740,7 +4813,14 @@ var SkillLibrary = class {
|
|
|
4740
4813
|
throw error;
|
|
4741
4814
|
}
|
|
4742
4815
|
}
|
|
4743
|
-
|
|
4816
|
+
/**
|
|
4817
|
+
* Summarize the skill tree.
|
|
4818
|
+
* @param options - `withContent` attaches each skill's whole SKILL.md body to
|
|
4819
|
+
* its summary (v35 C11): the read this listing already performs is the one the
|
|
4820
|
+
* body would cost again, so a content-consuming caller pays no second pass.
|
|
4821
|
+
* @returns one summary per readable skill directory.
|
|
4822
|
+
*/
|
|
4823
|
+
async list(options = {}) {
|
|
4744
4824
|
const summaries = [];
|
|
4745
4825
|
for (const name of await listNames(this.root, this.io)) {
|
|
4746
4826
|
const dir = this.dirOf(name);
|
|
@@ -4788,7 +4868,8 @@ var SkillLibrary = class {
|
|
|
4788
4868
|
hermesManaged
|
|
4789
4869
|
].some((value) => value === null),
|
|
4790
4870
|
managed: hermesManaged === true,
|
|
4791
|
-
...typeof parsedWhenToUse === "string" && parsedWhenToUse.trim() !== "" ? { whenToUse: parsedWhenToUse } : {}
|
|
4871
|
+
...typeof parsedWhenToUse === "string" && parsedWhenToUse.trim() !== "" ? { whenToUse: parsedWhenToUse } : {},
|
|
4872
|
+
...options.withContent === true ? { content: md } : {}
|
|
4792
4873
|
});
|
|
4793
4874
|
}
|
|
4794
4875
|
return summaries;
|
|
@@ -5140,11 +5221,11 @@ var SkillLibrary = class {
|
|
|
5140
5221
|
...norm.changed ? { normalizedFrontmatterFields: norm.fields } : {}
|
|
5141
5222
|
};
|
|
5142
5223
|
}
|
|
5143
|
-
async update(rawName, content, origin = "foreground") {
|
|
5224
|
+
async update(rawName, content, origin = "foreground", anchor) {
|
|
5144
5225
|
const name = rawName.trim();
|
|
5145
|
-
return await this.serial(() => this.updateCore(name, content, origin));
|
|
5226
|
+
return await this.serial(() => this.updateCore(name, content, origin, anchor));
|
|
5146
5227
|
}
|
|
5147
|
-
async updateCore(name, content, origin) {
|
|
5228
|
+
async updateCore(name, content, origin, anchor) {
|
|
5148
5229
|
const badName = this.badName(name);
|
|
5149
5230
|
if (badName) return {
|
|
5150
5231
|
ok: false,
|
|
@@ -5181,6 +5262,11 @@ var SkillLibrary = class {
|
|
|
5181
5262
|
message: threat
|
|
5182
5263
|
};
|
|
5183
5264
|
return await this.runSingleWrite(path, (current) => {
|
|
5265
|
+
const verdict = anchorVerdict(anchor, current);
|
|
5266
|
+
if (verdict !== "match") return {
|
|
5267
|
+
result: anchorRefusal(name, verdict),
|
|
5268
|
+
write: null
|
|
5269
|
+
};
|
|
5184
5270
|
if (current === null) return {
|
|
5185
5271
|
result: {
|
|
5186
5272
|
ok: false,
|
|
@@ -5219,7 +5305,7 @@ var SkillLibrary = class {
|
|
|
5219
5305
|
skillDir: dir
|
|
5220
5306
|
}
|
|
5221
5307
|
};
|
|
5222
|
-
});
|
|
5308
|
+
}, anchor !== void 0 ? anchorRefusal(name, "missing") : void 0);
|
|
5223
5309
|
}
|
|
5224
5310
|
async patch(rawName, oldString, newString, filePath = "", replaceAll = false, origin = "foreground") {
|
|
5225
5311
|
const name = rawName.trim();
|
|
@@ -6076,11 +6162,11 @@ var SkillLibrary = class {
|
|
|
6076
6162
|
path: dest
|
|
6077
6163
|
};
|
|
6078
6164
|
}
|
|
6079
|
-
async writeSupportFile(rawName, filePath, content, origin = "foreground") {
|
|
6165
|
+
async writeSupportFile(rawName, filePath, content, origin = "foreground", anchor) {
|
|
6080
6166
|
const name = rawName.trim();
|
|
6081
|
-
return await this.serial(() => this.writeSupportFileCore(name, filePath, content, origin));
|
|
6167
|
+
return await this.serial(() => this.writeSupportFileCore(name, filePath, content, origin, anchor));
|
|
6082
6168
|
}
|
|
6083
|
-
async writeSupportFileCore(name, filePath, content, origin) {
|
|
6169
|
+
async writeSupportFileCore(name, filePath, content, origin, anchor) {
|
|
6084
6170
|
const badName = this.badName(name);
|
|
6085
6171
|
if (badName) return {
|
|
6086
6172
|
ok: false,
|
|
@@ -6112,6 +6198,11 @@ var SkillLibrary = class {
|
|
|
6112
6198
|
};
|
|
6113
6199
|
const target = join(dir, ...filePath.replace(/\\/g, "/").split("/").filter(Boolean));
|
|
6114
6200
|
return await this.runSingleWrite(target, (current) => {
|
|
6201
|
+
const verdict = anchorVerdict(anchor, current);
|
|
6202
|
+
if (verdict !== "match") return {
|
|
6203
|
+
result: anchorRefusalFile(name, filePath, verdict),
|
|
6204
|
+
write: null
|
|
6205
|
+
};
|
|
6115
6206
|
if (current !== null && content.trimEnd() === current.trimEnd()) return {
|
|
6116
6207
|
result: {
|
|
6117
6208
|
ok: true,
|
|
@@ -6142,13 +6233,13 @@ var SkillLibrary = class {
|
|
|
6142
6233
|
file: target
|
|
6143
6234
|
}
|
|
6144
6235
|
};
|
|
6145
|
-
});
|
|
6236
|
+
}, anchor !== void 0 ? anchorUnverifiable(name, filePath) : void 0);
|
|
6146
6237
|
}
|
|
6147
|
-
async removeSupportFile(rawName, filePath, origin = "foreground") {
|
|
6238
|
+
async removeSupportFile(rawName, filePath, origin = "foreground", anchor) {
|
|
6148
6239
|
const name = rawName.trim();
|
|
6149
|
-
return await this.serial(() => this.removeSupportFileCore(name, filePath, origin));
|
|
6240
|
+
return await this.serial(() => this.removeSupportFileCore(name, filePath, origin, anchor));
|
|
6150
6241
|
}
|
|
6151
|
-
async removeSupportFileCore(name, filePath, origin) {
|
|
6242
|
+
async removeSupportFileCore(name, filePath, origin, anchor) {
|
|
6152
6243
|
const badName = this.badName(name);
|
|
6153
6244
|
if (badName) return {
|
|
6154
6245
|
ok: false,
|
|
@@ -6170,17 +6261,25 @@ var SkillLibrary = class {
|
|
|
6170
6261
|
message: validation
|
|
6171
6262
|
};
|
|
6172
6263
|
const target = join(dir, ...filePath.replace(/\\/g, "/").split("/").filter(Boolean));
|
|
6173
|
-
if (!await this.io.exists(target))
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6264
|
+
if (!await this.io.exists(target)) {
|
|
6265
|
+
if (anchor !== void 0) return anchorRefusalFile(name, filePath, "missing");
|
|
6266
|
+
return {
|
|
6267
|
+
ok: false,
|
|
6268
|
+
message: `File "${filePath}" not found in skill "${name}".`
|
|
6269
|
+
};
|
|
6270
|
+
}
|
|
6177
6271
|
const before = await this.io.readText(target).catch(() => null);
|
|
6178
6272
|
if (before === null) return {
|
|
6179
6273
|
ok: false,
|
|
6180
6274
|
message: `"${filePath}" is not a readable regular file — remove the files inside it one by one.`
|
|
6181
6275
|
};
|
|
6182
|
-
|
|
6183
|
-
|
|
6276
|
+
let verdict = anchorVerdict(anchor, before);
|
|
6277
|
+
if (verdict === "match" && this.transact) await this.transact(this.io, target, (current) => {
|
|
6278
|
+
verdict = anchorVerdict(anchor, current);
|
|
6279
|
+
return verdict === "match" ? null : current;
|
|
6280
|
+
});
|
|
6281
|
+
else if (verdict === "match") await this.io.remove(target);
|
|
6282
|
+
if (verdict !== "match") return anchorRefusalFile(name, filePath, verdict);
|
|
6184
6283
|
await this.audit(name, "remove_file", before, null, `removed ${filePath}`);
|
|
6185
6284
|
this.notifyMutation({
|
|
6186
6285
|
action: "remove_file",
|
|
@@ -6515,4 +6614,4 @@ var SkillLibrary = class {
|
|
|
6515
6614
|
}
|
|
6516
6615
|
};
|
|
6517
6616
|
//#endregion
|
|
6518
|
-
export { AUTHORING_DESCRIPTION_BAR, COMBINED_REVIEW_PLAN_PROMPT, COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEAD_LOCK_TAKEOVER_MS, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CONSOLIDATION_FAILURES, DEFAULT_CURATOR_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MEMORY_REVIEW_MODEL, DEFAULT_MIN_IDLE_HOURS, DEFAULT_MUTATION_CAP, DEFAULT_REVIEW_CONTEXT_MESSAGES, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_MESSAGE_CHARS, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_REVIEW_TIMEOUT_MS, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_MODEL, 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, DRIFT_MAX_LINE_CHARS, DRIFT_SIGNALS_VERSION, DRIFT_SIGNAL_NOUNS, DSH_AUTHORING_STANDARDS, EMPTY_LOCK_TAKEOVER_MS, ENTRY_DELIMITER, EVENT_ARCHIVE_PREFIX, EVENT_LOG_RETAIN_ARCHIVES, EVENT_LOG_ROTATE_AT, EVENT_LOG_VERSION, EVOLUTION_WRITE_TOOLS, EvolutionGateSet, FORBIDDEN_CONTROL_KEYS, HEALTH_STAMP_RE, LOCK_BODY_RE, LOCK_SUFFIX, LOCK_TEAR_TAKEOVER_MS, LOW_QUALITY_THRESHOLD, LostWriteLock, MAINTAIN_OUTPUT_INSTRUCTION, MAINTAIN_PROMPT, MAX_DESCRIPTION_LENGTH, MAX_RESTRUCTURE_MOVES, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MAX_TIMER_DELAY_MS, MEMORY_REVIEW_PROMPT, MIN_STAMP_BODY_CHARS, MUTATIONS_FILE_VERSION, MemoryStore, PATTERN_OVERLAP, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROMPT_BUNDLE_VERSION, PROTECTED_BUILTIN_SKILLS, QUALITY_WEIGHTS, RESTRUCTURE_TARGET_RE, SKILLS_GUIDANCE, SKILL_NAME_RE, SKILL_REVIEW_PLAN_PROMPT, SKILL_REVIEW_PROMPT, SNAPSHOT_EXTRA_NAME_RE, SUPPORT_DIRS, SUPPRESSED_FILE_VERSION, SkillLibrary, THREAT_EXEMPTION_HINT, advanceReview, allowRowCollisions, appendEvolutionEvent, applyCuratorFields, applyCuratorLifecycleFields, applyCuratorMetaFields, assertSkillsRootAliasRetired, assessStructureHealth, authoringFeedback, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, clampedNumber, composePresetComposition, computeDedupGroups, computeDriftSignals, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, createGateSet, decideTakeover, duplicateHeadings, emptyRecord, evaluateThreat, eventsFile, evolutionEventPayloadIssue, evolutionHome, evolutionIoAdapter, evolutionRoot, findDriftSignal, foldCuratorFields, foldTurn, frontmatterBlock, frontmatterCatalogInvalid, getRecord, isCommittedWarning, isProcessAlive, latestActivityAt, lifecycleCandidate, listEventArchives, loadMutations, loadSuppressedNames, loadUsage, makeSerialQueue, markAgentCreated, markerEntryName, memoryRoot, missingSupportPointers, mutateUsage, mutationsFile, narrowNameMatches, nodeEvolutionIo, normalizeFrontmatter, normalizeUsageRecord, observeEvent, overlongLines, parseCuratorNominations, parseEvolutionEvents, parseFrontmatter, parseLockBody, pendingSelfCleanup, readEvolutionEvents, readEvolutionTimeline, recordMutation, redactSecrets, relatedSkillNames, renameWithRetry, renderCuratorReportMarkdown, resolveOrigins, resolveRootConfig, resolveSkillsRoot, retainEventArchives, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, transactIo, updateSuppressedNames, usageFile, usageObserved, validateFrontmatter, validateRestructureTarget, verifyPromptBundle, writeDurableTmp, yamlPlainScalarNeedsQuotes };
|
|
6617
|
+
export { AUTHORING_DESCRIPTION_BAR, COMBINED_REVIEW_PLAN_PROMPT, COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEAD_LOCK_TAKEOVER_MS, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CONSOLIDATION_FAILURES, DEFAULT_CURATOR_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MEMORY_REVIEW_MODEL, DEFAULT_MIN_IDLE_HOURS, DEFAULT_MUTATION_CAP, DEFAULT_REVIEW_CONTEXT_MESSAGES, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_MESSAGE_CHARS, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_REVIEW_TIMEOUT_MS, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_MODEL, 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, DRIFT_MAX_LINE_CHARS, DRIFT_SIGNALS_VERSION, DRIFT_SIGNAL_NOUNS, DSH_AUTHORING_STANDARDS, EMPTY_LOCK_TAKEOVER_MS, ENTRY_DELIMITER, EVENT_ARCHIVE_PREFIX, EVENT_LOG_RETAIN_ARCHIVES, EVENT_LOG_ROTATE_AT, EVENT_LOG_VERSION, EVOLUTION_WRITE_TOOLS, EvolutionGateSet, FORBIDDEN_CONTROL_KEYS, HEALTH_STAMP_RE, LOCK_BODY_RE, LOCK_SUFFIX, LOCK_TEAR_TAKEOVER_MS, LOW_QUALITY_THRESHOLD, LostWriteLock, MAINTAIN_OUTPUT_INSTRUCTION, MAINTAIN_PROMPT, MAX_DESCRIPTION_LENGTH, MAX_RESTRUCTURE_MOVES, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MAX_TIMER_DELAY_MS, MEMORY_GUIDANCE_SECTION_ORDER, MEMORY_REVIEW_PROMPT, MIN_STAMP_BODY_CHARS, MUTATIONS_FILE_VERSION, MemoryStore, PATTERN_OVERLAP, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROMPT_BUNDLE_VERSION, PROTECTED_BUILTIN_SKILLS, QUALITY_WEIGHTS, RESTRUCTURE_TARGET_RE, SKILLS_GUIDANCE, SKILLS_GUIDANCE_SECTION_ORDER, SKILL_NAME_RE, SKILL_REVIEW_PLAN_PROMPT, SKILL_REVIEW_PROMPT, SNAPSHOT_EXTRA_NAME_RE, SUPPORT_DIRS, SUPPRESSED_FILE_VERSION, SkillLibrary, THREAT_EXEMPTION_HINT, advanceReview, allowRowCollisions, appendEvolutionEvent, applyCuratorFields, applyCuratorLifecycleFields, applyCuratorMetaFields, assertSkillsRootAliasRetired, assessStructureHealth, authoringFeedback, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, clampedNumber, composePresetComposition, computeDedupGroups, computeDriftSignals, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, createGateSet, decideTakeover, duplicateHeadings, emptyRecord, evaluateThreat, eventsFile, evolutionEventPayloadIssue, evolutionHome, evolutionIoAdapter, evolutionRoot, findDriftSignal, foldCuratorFields, foldTurn, frontmatterBlock, frontmatterCatalogInvalid, getRecord, isCommittedWarning, isProcessAlive, latestActivityAt, lifecycleCandidate, listEventArchives, loadMutations, loadSuppressedNames, loadUsage, makeSerialQueue, markAgentCreated, markerEntryName, memoryRoot, missingSupportPointers, mutateUsage, mutationsFile, narrowNameMatches, nodeEvolutionIo, normalizeFrontmatter, normalizeUsageRecord, observeEvent, overlongLines, parseCuratorNominations, parseEvolutionEvents, parseFrontmatter, parseLockBody, pendingSelfCleanup, readEvolutionEvents, readEvolutionTimeline, recordMutation, redactSecrets, relatedSkillNames, renameWithRetry, renderCuratorReportMarkdown, resolveOrigins, resolveRootConfig, resolveSkillsRoot, retainEventArchives, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, transactIo, updateSuppressedNames, usageFile, usageObserved, validateFrontmatter, validateRestructureTarget, verifyPromptBundle, writeDurableTmp, yamlPlainScalarNeedsQuotes };
|
package/lib/types/constants.d.ts
CHANGED
|
@@ -97,4 +97,8 @@ export declare const MAX_TIMER_DELAY_MS = 2147483647;
|
|
|
97
97
|
export declare const DEFAULT_MEMORY_REVIEW_MODEL = "deepseek-v4-flash";
|
|
98
98
|
export declare const DEFAULT_SKILL_REVIEW_MODEL = "deepseek-v4-pro";
|
|
99
99
|
export declare const DEFAULT_CURATOR_MODEL = "deepseek-v4-pro";
|
|
100
|
+
/** Order of the `evolution:memory-guidance` section (before the skills one). */
|
|
101
|
+
export declare const MEMORY_GUIDANCE_SECTION_ORDER = 11000;
|
|
102
|
+
/** Order of the `evolution-skills-guidance` section (last of the two). */
|
|
103
|
+
export declare const SKILLS_GUIDANCE_SECTION_ORDER = 11100;
|
|
100
104
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -140,5 +140,5 @@ export declare function readEvolutionEvents(io: EvolutionIoLike, path: string):
|
|
|
140
140
|
* malformed (or unreadable) ARCHIVE is skipped — it never bricks the boot and
|
|
141
141
|
* it is still flagged.
|
|
142
142
|
*/
|
|
143
|
-
export declare function readEvolutionTimeline(io: EvolutionIoLike, path: string): Promise<EventLogRead>;
|
|
143
|
+
export declare function readEvolutionTimeline(io: EvolutionIoLike, path: string, archives?: readonly string[]): Promise<EventLogRead>;
|
|
144
144
|
//# sourceMappingURL=evolution-events.d.ts.map
|
|
@@ -31,7 +31,32 @@ export interface SkillSummary {
|
|
|
31
31
|
* platform catalog keeps it while this provider shadows the upstream
|
|
32
32
|
* filesystem provider. Absent when the frontmatter has none. */
|
|
33
33
|
whenToUse?: string;
|
|
34
|
+
/** v35 C11: the whole SKILL.md body, present only for
|
|
35
|
+
* {@link SkillLibrary.list} calls that pass `{ withContent: true }`. A consumer
|
|
36
|
+
* that needs both the summary fields and the body (tree hashing, enrichment,
|
|
37
|
+
* drift scans) saves the second per-skill read; the default stays body-free so
|
|
38
|
+
* the common listing does not hold a whole tree in memory. */
|
|
39
|
+
content?: string;
|
|
34
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Stage-time anchor for a full-content write (v35 C9): the sha256 the caller read
|
|
43
|
+
* when it staged the plan, or `absent` when the target did not exist then. The
|
|
44
|
+
* library compares it against the bytes it reads INSIDE the write's own lock — the
|
|
45
|
+
* same read the write commits — so a concurrent writer landing between staging and
|
|
46
|
+
* commit is refused instead of silently overwritten.
|
|
47
|
+
*/
|
|
48
|
+
export type WriteAnchor = {
|
|
49
|
+
readonly sha256: string;
|
|
50
|
+
} | {
|
|
51
|
+
readonly absent: true;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* What the write lock observed about an anchor target.
|
|
55
|
+
* - `match`: the anchor holds; the write proceeds.
|
|
56
|
+
* - `drift`: the target exists with different bytes.
|
|
57
|
+
* - `missing`: the target does not exist (an `absent` anchor `match`es this).
|
|
58
|
+
*/
|
|
59
|
+
export type AnchorVerdict = 'match' | 'drift' | 'missing';
|
|
35
60
|
export interface SkillActionResult {
|
|
36
61
|
ok: boolean;
|
|
37
62
|
message: string;
|
|
@@ -42,6 +67,12 @@ export interface SkillActionResult {
|
|
|
42
67
|
/** 0.3.18 (E-68): patch produced byte-identical content (old===new) — no
|
|
43
68
|
* write, no audit, no mutation event; callers must not count a patch. */
|
|
44
69
|
noop?: boolean;
|
|
70
|
+
/** Set when the caller passed a {@link WriteAnchor} that the locked read did
|
|
71
|
+
* not satisfy: nothing was written. Carries {@link SkillActionResult.anchor}
|
|
72
|
+
* so a caller with staged-replay wording can translate it (v35 C9). */
|
|
73
|
+
stale?: true;
|
|
74
|
+
/** The locked read's verdict for the caller's anchor. */
|
|
75
|
+
anchor?: AnchorVerdict;
|
|
45
76
|
}
|
|
46
77
|
/**
|
|
47
78
|
* One section move of a restructure proposal (008 batch B): a body section
|
|
@@ -369,7 +400,16 @@ export declare class SkillLibrary {
|
|
|
369
400
|
* last-writer-wins.
|
|
370
401
|
*/
|
|
371
402
|
readSupportFile(name: string, filePath: string): Promise<string | null>;
|
|
372
|
-
|
|
403
|
+
/**
|
|
404
|
+
* Summarize the skill tree.
|
|
405
|
+
* @param options - `withContent` attaches each skill's whole SKILL.md body to
|
|
406
|
+
* its summary (v35 C11): the read this listing already performs is the one the
|
|
407
|
+
* body would cost again, so a content-consuming caller pays no second pass.
|
|
408
|
+
* @returns one summary per readable skill directory.
|
|
409
|
+
*/
|
|
410
|
+
list(options?: {
|
|
411
|
+
withContent?: boolean;
|
|
412
|
+
}): Promise<SkillSummary[]>;
|
|
373
413
|
read(rawName: string): Promise<string | null>;
|
|
374
414
|
/**
|
|
375
415
|
|
|
@@ -439,7 +479,7 @@ export declare class SkillLibrary {
|
|
|
439
479
|
private setPinnedCore;
|
|
440
480
|
create(name: string, content: string, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
441
481
|
private createCore;
|
|
442
|
-
update(rawName: string, content: string, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
482
|
+
update(rawName: string, content: string, origin?: WriteOrigin, anchor?: WriteAnchor): Promise<SkillActionResult>;
|
|
443
483
|
private updateCore;
|
|
444
484
|
patch(rawName: string, oldString: string, newString: string, filePath?: string, replaceAll?: boolean, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
445
485
|
private patchCore;
|
|
@@ -546,9 +586,9 @@ export declare class SkillLibrary {
|
|
|
546
586
|
* path back. The `.archive-reason` marker is dropped on restore.
|
|
547
587
|
*/
|
|
548
588
|
restoreFromArchive(rawName: string): Promise<SkillActionResult>;
|
|
549
|
-
writeSupportFile(rawName: string, filePath: string, content: string, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
589
|
+
writeSupportFile(rawName: string, filePath: string, content: string, origin?: WriteOrigin, anchor?: WriteAnchor): Promise<SkillActionResult>;
|
|
550
590
|
private writeSupportFileCore;
|
|
551
|
-
removeSupportFile(rawName: string, filePath: string, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
591
|
+
removeSupportFile(rawName: string, filePath: string, origin?: WriteOrigin, anchor?: WriteAnchor): Promise<SkillActionResult>;
|
|
552
592
|
private removeSupportFileCore;
|
|
553
593
|
/**
|
|
554
594
|
* v23 (ML-1): `.archive` retention. Archived skills are recoverable history,
|
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.3.
|
|
4
|
+
"version": "0.3.71",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -33,14 +33,14 @@
|
|
|
33
33
|
"js-yaml": "^4.2.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@deepseek-ai/dsh-invariants": "^0.1.
|
|
36
|
+
"@deepseek-ai/dsh-invariants": "^0.1.5-rc.2",
|
|
37
37
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
38
|
-
"@deepseek-ai/dsh-session": "^0.1.
|
|
38
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.2"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/js-yaml": "^4.0.9",
|
|
42
|
-
"@deepseek-ai/dsh-invariants": "^0.1.
|
|
42
|
+
"@deepseek-ai/dsh-invariants": "^0.1.5-rc.2",
|
|
43
43
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
44
|
-
"@deepseek-ai/dsh-session": "^0.1.
|
|
44
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.2"
|
|
45
45
|
}
|
|
46
46
|
}
|