@lmzhen/dsh-evolution-core 0.3.56 → 0.3.58
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 -44
- package/lib/types/prompts.d.ts +3 -3
- package/lib/types/skill-store.d.ts +2 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -311,6 +311,10 @@ function nodeEvolutionIo(lockAttempts = 40) {
|
|
|
311
311
|
retryDelay: 100
|
|
312
312
|
}).catch(async () => {
|
|
313
313
|
const body = await readFile(lock, "utf8").catch(() => "");
|
|
314
|
+
if (pendingSelfCleanup.size >= 64) {
|
|
315
|
+
const oldest = pendingSelfCleanup.keys().next().value;
|
|
316
|
+
if (oldest !== void 0) pendingSelfCleanup.delete(oldest);
|
|
317
|
+
}
|
|
314
318
|
pendingSelfCleanup.set(lock, body);
|
|
315
319
|
});
|
|
316
320
|
}
|
|
@@ -428,7 +432,7 @@ function nodeEvolutionIo(lockAttempts = 40) {
|
|
|
428
432
|
},
|
|
429
433
|
async rename(path, destination) {
|
|
430
434
|
await mkdir(dirname(destination), { recursive: true });
|
|
431
|
-
await
|
|
435
|
+
await renameWithRetry(path, destination);
|
|
432
436
|
},
|
|
433
437
|
async copy(path, destination) {
|
|
434
438
|
await mkdir(dirname(destination), { recursive: true });
|
|
@@ -1207,8 +1211,8 @@ async function appendEvolutionEvent(io, path, event, rotateAt = EVENT_LOG_ROTATE
|
|
|
1207
1211
|
return current;
|
|
1208
1212
|
}
|
|
1209
1213
|
}
|
|
1210
|
-
const
|
|
1211
|
-
let maxSeq =
|
|
1214
|
+
const events = await rotateIfDue(io, path, v1EventRecords(parsedBody), rotateAt);
|
|
1215
|
+
let maxSeq = events.reduce((max, entry) => Math.max(max, entry.seq), 0);
|
|
1212
1216
|
if (maxSeq === 0) for (const name of await listEventArchives(io, path)) maxSeq = Math.max(maxSeq, Number.parseInt(name.slice(7, name.length - 5), 10));
|
|
1213
1217
|
const record = {
|
|
1214
1218
|
...event,
|
|
@@ -1218,7 +1222,7 @@ async function appendEvolutionEvent(io, path, event, rotateAt = EVENT_LOG_ROTATE
|
|
|
1218
1222
|
assigned = record.seq;
|
|
1219
1223
|
return JSON.stringify({
|
|
1220
1224
|
version: 1,
|
|
1221
|
-
events: [...
|
|
1225
|
+
events: [...events, record]
|
|
1222
1226
|
}, null, 2);
|
|
1223
1227
|
});
|
|
1224
1228
|
if (assigned === 0) throw new Error(`${refuseMessage || "evolution event log is malformed and was not touched"}: ${path}`);
|
|
@@ -1370,8 +1374,8 @@ function allowRowCollisions(env = process.env) {
|
|
|
1370
1374
|
* changes semantically: the bundle digest is the fail-closed signal for
|
|
1371
1375
|
* review workers, so a stale id across deployments must be distinguishable.
|
|
1372
1376
|
*/
|
|
1373
|
-
const PROMPT_BUNDLE_VERSION =
|
|
1374
|
-
const PROMPT_BUNDLE_ID = `dsh-evolution@
|
|
1377
|
+
const PROMPT_BUNDLE_VERSION = 16;
|
|
1378
|
+
const PROMPT_BUNDLE_ID = `dsh-evolution@16`;
|
|
1375
1379
|
const MEMORY_REVIEW_PROMPT = `[Auto-review — Memory]
|
|
1376
1380
|
Review the conversation above and consider saving to memory if appropriate.
|
|
1377
1381
|
|
|
@@ -1628,7 +1632,7 @@ D. 库·整合纪律(计划形态约束)
|
|
|
1628
1632
|
* fail-closed signal); PROMPT_BUNDLE_VERSION itself is owned by the core test
|
|
1629
1633
|
* pin and stays untouched in this batch.
|
|
1630
1634
|
*/
|
|
1631
|
-
const MAINTAIN_OUTPUT_INSTRUCTION = "按模板契约输出 JSON 维护计划(verdict/plan/notes
|
|
1635
|
+
const MAINTAIN_OUTPUT_INSTRUCTION = "按模板契约输出 JSON 维护计划(verdict/plan/notes);你有 skill 工具与维护模板;并在维护探针(maintenance_probe)挂载时可用它深挖细节。";
|
|
1632
1636
|
/**
|
|
1633
1637
|
* System-prompt guidance section (Hermes `SKILLS_GUIDANCE`, DSH-adapted).
|
|
1634
1638
|
* Registered as a system-prompt section by tool-skill-manage (it mounts
|
|
@@ -1658,12 +1662,12 @@ function sha256(text) {
|
|
|
1658
1662
|
function createPromptBundle(prompts) {
|
|
1659
1663
|
const canonical = JSON.stringify({
|
|
1660
1664
|
id: PROMPT_BUNDLE_ID,
|
|
1661
|
-
version:
|
|
1665
|
+
version: 16,
|
|
1662
1666
|
prompts: Object.fromEntries(Object.entries(prompts).sort())
|
|
1663
1667
|
});
|
|
1664
1668
|
return Object.freeze({
|
|
1665
1669
|
id: PROMPT_BUNDLE_ID,
|
|
1666
|
-
version:
|
|
1670
|
+
version: 16,
|
|
1667
1671
|
prompts: Object.freeze({ ...prompts }),
|
|
1668
1672
|
sha256: sha256(canonical)
|
|
1669
1673
|
});
|
|
@@ -1681,10 +1685,10 @@ const PROMPT_BUNDLE = createPromptBundle({
|
|
|
1681
1685
|
skillsGuidance: SKILLS_GUIDANCE
|
|
1682
1686
|
});
|
|
1683
1687
|
function verifyPromptBundle(bundle = PROMPT_BUNDLE) {
|
|
1684
|
-
if (bundle.id !== PROMPT_BUNDLE_ID || bundle.version !==
|
|
1688
|
+
if (bundle.id !== PROMPT_BUNDLE_ID || bundle.version !== 16) return false;
|
|
1685
1689
|
const canonical = JSON.stringify({
|
|
1686
1690
|
id: PROMPT_BUNDLE_ID,
|
|
1687
|
-
version:
|
|
1691
|
+
version: 16,
|
|
1688
1692
|
prompts: Object.fromEntries(Object.entries(bundle.prompts).sort())
|
|
1689
1693
|
});
|
|
1690
1694
|
return bundle.sha256 === sha256(canonical);
|
|
@@ -3109,9 +3113,11 @@ function observeEvent(signal, event) {
|
|
|
3109
3113
|
return;
|
|
3110
3114
|
}
|
|
3111
3115
|
if (event.type === "tool/call") {
|
|
3116
|
+
const data = event.data;
|
|
3117
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) return;
|
|
3112
3118
|
signal.toolCalls += 1;
|
|
3113
|
-
|
|
3114
|
-
if (
|
|
3119
|
+
const name = data.name;
|
|
3120
|
+
if (name === "skill" || name === "skill_manage") signal.skillSignal = true;
|
|
3115
3121
|
}
|
|
3116
3122
|
}
|
|
3117
3123
|
/** Compute review cadence after `turn/end`. */
|
|
@@ -4145,6 +4151,9 @@ var SkillLibrary = class {
|
|
|
4145
4151
|
}
|
|
4146
4152
|
async create(name, content, origin = "foreground") {
|
|
4147
4153
|
const normalized = name.trim();
|
|
4154
|
+
return await this.serial(() => this.createCore(normalized, content, origin));
|
|
4155
|
+
}
|
|
4156
|
+
async createCore(normalized, content, origin) {
|
|
4148
4157
|
const bad = this.badName(normalized);
|
|
4149
4158
|
if (bad) return {
|
|
4150
4159
|
ok: false,
|
|
@@ -4882,9 +4891,10 @@ var SkillLibrary = class {
|
|
|
4882
4891
|
*/
|
|
4883
4892
|
async restoreFromArchive(rawName) {
|
|
4884
4893
|
const name = rawName.trim();
|
|
4885
|
-
|
|
4894
|
+
const bad = this.badName(name);
|
|
4895
|
+
if (bad) return {
|
|
4886
4896
|
ok: false,
|
|
4887
|
-
message:
|
|
4897
|
+
message: bad
|
|
4888
4898
|
};
|
|
4889
4899
|
if (await this.io.exists(join(this.dirOf(name), "SKILL.md"))) return {
|
|
4890
4900
|
ok: false,
|
|
@@ -5013,6 +5023,9 @@ var SkillLibrary = class {
|
|
|
5013
5023
|
}
|
|
5014
5024
|
async removeSupportFile(rawName, filePath, origin = "foreground") {
|
|
5015
5025
|
const name = rawName.trim();
|
|
5026
|
+
return await this.serial(() => this.removeSupportFileCore(name, filePath, origin));
|
|
5027
|
+
}
|
|
5028
|
+
async removeSupportFileCore(name, filePath, origin) {
|
|
5016
5029
|
const badName = this.badName(name);
|
|
5017
5030
|
if (badName) return {
|
|
5018
5031
|
ok: false,
|
|
@@ -5064,36 +5077,41 @@ var SkillLibrary = class {
|
|
|
5064
5077
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
5065
5078
|
let dest = join(backupRoot, `skills-${stamp}`);
|
|
5066
5079
|
while (await this.io.exists(dest)) dest = join(backupRoot, `skills-${stamp}-${Math.random().toString(36).slice(2, 8)}`);
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
await
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
const
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
await this.io.
|
|
5081
|
-
|
|
5080
|
+
try {
|
|
5081
|
+
const names = await listNames(this.root, this.io);
|
|
5082
|
+
await Promise.all(names.map(async (name) => {
|
|
5083
|
+
await this.io.copy(this.dirOf(name), join(dest, name));
|
|
5084
|
+
}));
|
|
5085
|
+
const sidecars = [];
|
|
5086
|
+
for (const sidecar of [usageFile(this.root), suppressedFile(this.root)]) if (await this.io.exists(sidecar)) {
|
|
5087
|
+
const name = basename(sidecar);
|
|
5088
|
+
await this.io.copy(sidecar, join(dest, name));
|
|
5089
|
+
sidecars.push(name);
|
|
5090
|
+
}
|
|
5091
|
+
const archiveRoot = join(this.root, ".archive");
|
|
5092
|
+
let hasArchive = false;
|
|
5093
|
+
if (await this.io.exists(archiveRoot)) {
|
|
5094
|
+
await this.io.copy(archiveRoot, join(dest, ".archive"));
|
|
5095
|
+
hasArchive = true;
|
|
5096
|
+
}
|
|
5097
|
+
const validExtras = extras.filter((extra) => SNAPSHOT_EXTRA_NAME_RE.test(extra.name));
|
|
5098
|
+
const extraNames = validExtras.map((extra) => extra.name);
|
|
5099
|
+
await Promise.all(validExtras.map(async (extra) => {
|
|
5100
|
+
await this.io.writeText(join(dest, "extras", extra.name), extra.content);
|
|
5101
|
+
}));
|
|
5102
|
+
await this.io.writeText(join(dest, "manifest.json"), JSON.stringify({
|
|
5103
|
+
reason,
|
|
5104
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5105
|
+
skills: names,
|
|
5106
|
+
sidecars,
|
|
5107
|
+
hasArchive,
|
|
5108
|
+
extras: extraNames
|
|
5109
|
+
}, null, 2));
|
|
5110
|
+
await this.retainSnapshots(5);
|
|
5111
|
+
} catch (error) {
|
|
5112
|
+
await this.io.remove(dest).catch(() => {});
|
|
5113
|
+
throw error;
|
|
5082
5114
|
}
|
|
5083
|
-
const validExtras = extras.filter((extra) => SNAPSHOT_EXTRA_NAME_RE.test(extra.name));
|
|
5084
|
-
const extraNames = validExtras.map((extra) => extra.name);
|
|
5085
|
-
await Promise.all(validExtras.map(async (extra) => {
|
|
5086
|
-
await this.io.writeText(join(dest, "extras", extra.name), extra.content);
|
|
5087
|
-
}));
|
|
5088
|
-
await this.io.writeText(join(dest, "manifest.json"), JSON.stringify({
|
|
5089
|
-
reason,
|
|
5090
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5091
|
-
skills: names,
|
|
5092
|
-
sidecars,
|
|
5093
|
-
hasArchive,
|
|
5094
|
-
extras: extraNames
|
|
5095
|
-
}, null, 2));
|
|
5096
|
-
await this.retainSnapshots(5);
|
|
5097
5115
|
return dest;
|
|
5098
5116
|
}
|
|
5099
5117
|
/** Read and normalize a snapshot manifest; null when the file is missing or unparsable. */
|
package/lib/types/prompts.d.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* changes semantically: the bundle digest is the fail-closed signal for
|
|
4
4
|
* review workers, so a stale id across deployments must be distinguishable.
|
|
5
5
|
*/
|
|
6
|
-
export declare const PROMPT_BUNDLE_VERSION =
|
|
7
|
-
export declare const PROMPT_BUNDLE_ID = "dsh-evolution@
|
|
6
|
+
export declare const PROMPT_BUNDLE_VERSION = 16;
|
|
7
|
+
export declare const PROMPT_BUNDLE_ID = "dsh-evolution@16";
|
|
8
8
|
export declare const MEMORY_REVIEW_PROMPT = "[Auto-review \u2014 Memory]\nReview the conversation above and consider saving to memory if appropriate.\n\nFocus on:\n1. Has the user revealed things about themselves \u2014 persona, desires, preferences, or personal details worth remembering?\n2. Has the user expressed expectations about how you should behave, their work style, or ways they want you to operate?\n\nIf something stands out, save it using the memory tool.\nIf nothing is worth saving, just say \"Nothing to save.\" and stop.";
|
|
9
9
|
export declare const SKILL_REVIEW_PROMPT = "[Auto-review \u2014 Skills]\nReview the conversation above and update the skill library. Be ACTIVE \u2014 most sessions produce at least one skill update, even if small. A pass that does nothing is a missed learning opportunity, not a neutral outcome.\n\nTarget shape of the library: CLASS-LEVEL skills, each with a rich SKILL.md and a references/ directory for session-specific detail. Not a long flat list of narrow one-session-one-skill entries. This shapes HOW you update, not WHETHER you update.\n\nSignals to look for (any one of these warrants action):\n \u2022 User corrected your style, tone, format, legibility, or verbosity. Frustration signals like 'stop doing X', 'this is too verbose', 'don't format like this', 'why are you explaining', 'just give me the answer', 'you always do Y and I hate it', or an explicit 'remember this' are FIRST-CLASS skill signals, not just memory signals. Update the relevant skill(s) to embed the preference so the next session starts already knowing.\n \u2022 User corrected your workflow, approach, or sequence of steps. Encode the correction as a pitfall or explicit step in the skill that governs that class of task.\n \u2022 Non-trivial technique, fix, workaround, debugging path, or tool-usage pattern emerged that a future session would benefit from. Capture it.\n \u2022 A skill that got loaded or consulted this session turned out to be wrong, missing a step, or outdated. Patch it NOW.\n\nRead-before-write (enforced by this channel): update, patch, delete, or write support files ONLY into skills you loaded or read in THIS session \u2014 ops on unread skills are dropped; CREATE of a brand-new umbrella is the only exception.\n\nPreference order \u2014 prefer the earliest action that fits, but do pick one when a signal above fired:\n 1. UPDATE A CURRENTLY-LOADED SKILL. Look back through the conversation for skills the user loaded or you read. If any of them covers the territory of the new learning, PATCH that one first. It is the skill that was in play, so it's the right one to extend.\n 2. UPDATE AN EXISTING UMBRELLA. If no loaded skill fits but an existing class-level skill does, patch it. Add a subsection, a pitfall, or broaden a trigger.\n 3. ADD A SUPPORT FILE under an existing umbrella. Skills can be packaged with three kinds of support files \u2014 use the right directory per kind:\n \u2022 references/<topic>.md \u2014 session-specific detail (error transcripts, reproduction recipes, provider quirks) AND condensed knowledge banks: quoted research, API docs, external authoritative excerpts, or domain notes you found while working on the problem. Write it concise and for the value of the task, not as a full mirror of upstream docs.\n \u2022 templates/<name>.<ext> \u2014 starter files meant to be copied and modified (boilerplate configs, scaffolding, a known-good example the agent can reproduce with modifications).\n \u2022 scripts/<name>.<ext> \u2014 statically re-runnable actions the skill can invoke directly (verification scripts, fixture generators, deterministic probes, anything the agent should run rather than hand-type each time).\n Add support files via skill_manage action=write_file with file_path starting 'references/', 'templates/', or 'scripts/'. The umbrella's SKILL.md should gain a one-line pointer to any new support file so future agents know it exists.\n 4. RESTRUCTURE a loaded skill whose body grew log-like \u2014 rc/sha/date-dense sections, session-detail spirals, or a fat body with no support files. Use skill_manage action=restructure with restructure: [{\"heading\": \"<the exact ## heading text>\", \"to_file\": \"references/<topic>.md\"}] \u2014 the ENTIRE ## section (from that heading to the next heading) moves into the support file and its position becomes a pointer line. The skill's name and directory never change. Only propose headings that exist verbatim in the body; never invent one, and never restructure a healthy small skill.\n 5. CREATE A NEW CLASS-LEVEL UMBRELLA SKILL when no existing skill covers the class. The name MUST be at the class level. The name MUST NOT be a specific PR number, error string, feature codename, library-alone name, or 'fix-X / debug-Y / audit-Z-today' session artifact. If the proposed name only makes sense for today's task, it's wrong \u2014 fall back to (1), (2), or (3).\n\nUser-preference embedding (important): when the user expressed a style/format/workflow preference, the update belongs in the SKILL.md body, not just in memory. Memory captures 'who the user is and what the current situation and state of your operations are'; skills capture 'how to do this class of task for this user'. When they complain about how you handled a task, the skill that governs that task needs to carry the lesson.\n\nIf you notice two existing skills that overlap, note it in your reply \u2014 the background curator handles consolidation at scale.\n\nTwo-tier deposition discipline (DSH addition, same spirit as the umbrella rule): before writing, classify the knowledge:\n \u2022 PATTERN (reusable \u2014 symptom \u2192 mechanism \u2192 fix \u2192 verification, still valuable next session) belongs in the SKILL.md body.\n \u2022 LOG (one-off \u2014 commit SHAs, npm/profile states, what this release changed, this session's process narrative) belongs in a references/ file, never the body. Body density IS reuse rate. Keep new entries tight: a pattern fits in 2-8 physical lines; prefer changing the current-state pointer over appending history.\n\nProtected skills (DO NOT edit these):\n \u2022 Bundled skills (shipped with the platform).\n \u2022 Hub-installed skills (installed from a hub).\nPinned skills are read-only to THIS background review pass \u2014 the pinned write guard refuses background changes, so this pass may not update them. They also cannot be archived by any writer (the foreground included): remove the .pinned marker first. Foreground and delegated-subagent update/patch writes to pinned skills remain allowed.\nIf the only skills that need updating are protected, say 'Nothing to save.' and stop.\n\nDo NOT capture (these become persistent self-imposed constraints that bite you later when the environment changes):\n \u2022 Environment-dependent failures: missing binaries, fresh-install errors, post-migration path mismatches, 'command not found', unconfigured credentials, uninstalled packages. The user can fix these \u2014 they are not durable rules.\n \u2022 Negative claims about tools or features ('browser tools do not work', 'X tool is broken', 'cannot use Y'). These harden into refusals the agent cites against itself for months after the actual problem was fixed.\n \u2022 Session-specific transient errors that resolved before the conversation ended. If retrying worked, the lesson is the retry pattern, not the original failure.\n \u2022 One-off task narratives. A user asking 'summarize today's market' or 'analyze this PR' is not a class of work that warrants a skill.\n\nIf a tool failed because of setup state, capture the FIX (install command, config step, env var to set) under an existing setup or troubleshooting skill \u2014 never 'this tool does not work' as a standalone constraint.\n\n'Nothing to save.' is a real option but should NOT be the default. If the session ran smoothly with no corrections and produced no new technique, just say 'Nothing to save.' and stop. Otherwise, act.";
|
|
10
10
|
export declare const COMBINED_REVIEW_PROMPT = "[Auto-review]\nReview the conversation above and update two things:\n\n**Memory**: who the user is. Did the user reveal persona, desires, preferences, personal details, or expectations about how you should behave? Save facts about the user and durable preferences with the memory tool.\n\n**Skills**: how to do this class of task. Be ACTIVE \u2014 most sessions produce at least one skill update. A pass that does nothing is a missed learning opportunity, not a neutral outcome.\n\nTarget shape of the skill library: CLASS-LEVEL skills with a rich SKILL.md and a references/ directory for session-specific detail. Not a long flat list of narrow one-session-one-skill entries.\n\nSignals that warrant a skill update (any one is enough):\n \u2022 User corrected your style, tone, format, legibility, verbosity, or approach. Frustration is a FIRST-CLASS skill signal, not just a memory signal. 'stop doing X', 'don't format like this', 'I hate when you Y' \u2014 embed the lesson in the skill that governs that task so the next session starts fixed.\n \u2022 Non-trivial technique, fix, workaround, or debugging path emerged.\n \u2022 A skill that was loaded or consulted turned out wrong, missing, or outdated \u2014 patch it now.\n\nRead-before-write (enforced by this channel): update, patch, delete, or write support files ONLY into skills you loaded or read in THIS session \u2014 ops on unread skills are dropped; CREATE of a brand-new umbrella is the only exception.\n\nPreference order for skills \u2014 pick the earliest that fits:\n 1. UPDATE A CURRENTLY-LOADED SKILL. Check what skills were loaded or read in the conversation. If one of them covers the learning, PATCH it first. It was in play; it's the right place.\n 2. UPDATE AN EXISTING UMBRELLA. Patch it.\n 3. ADD A SUPPORT FILE under an existing umbrella via skill_manage action=write_file. Three kinds: references/<topic>.md for session-specific detail OR condensed knowledge banks (quoted research, API docs excerpts, domain notes) written concise and task-focused; templates/<name>.<ext> for starter files meant to be copied and modified; scripts/<name>.<ext> for statically re-runnable actions (verification, fixture generators, probes). Add a one-line pointer in SKILL.md so future agents find them.\n 4. RESTRUCTURE a loaded skill whose body grew log-like (rc/sha/date-dense sections, session-detail spirals, fat body with no support files) via skill_manage action=restructure with restructure: [{\"heading\": \"<the exact ## heading text>\", \"to_file\": \"references/<topic>.md\"}] \u2014 the ENTIRE ## section moves into the support file and its position becomes a pointer line; the skill's name and directory never change. Only propose headings that exist verbatim in the body.\n 5. CREATE A NEW CLASS-LEVEL UMBRELLA when nothing exists. Name at the class level \u2014 NOT a PR number, error string, codename, library-alone name, or 'fix-X / debug-Y' session artifact. If the name only fits today's task, fall back to (1), (2), or (3).\n\nTwo-tier deposition discipline (DSH addition): classify before writing \u2014 PATTERN (symptom \u2192 mechanism \u2192 fix \u2192 verification) goes in the SKILL.md body; LOG (commit SHAs, npm/profile states, this release's change list, this session's narrative) goes in a references/ file. Body density IS reuse rate; a pattern fits in 2-8 physical lines.\n\nUser-preference embedding: when the user complains about how you handled a task, update the skill that governs that task \u2014 memory alone isn't enough. Memory says 'who the user is and what the current situation and state of your operations are'; skills say 'how to do this class of task for this user'. Both should carry user-preference lessons when relevant.\n\nIf you notice overlapping existing skills, mention it \u2014 the background curator handles consolidation.\n\nProtected skills (DO NOT edit these):\n \u2022 Bundled skills (shipped with the platform).\n \u2022 Hub-installed skills (installed from a hub).\nPinned skills are read-only to THIS background review pass \u2014 the pinned write guard refuses background changes, so this pass may not update them. They also cannot be archived by any writer (the foreground included): remove the .pinned marker first. Foreground and delegated-subagent update/patch writes to pinned skills remain allowed.\nIf the only skills that need updating are protected, say 'Nothing to save.' and stop.\n\nDo NOT capture as skills (these become persistent self-imposed constraints that bite you later when the environment changes):\n \u2022 Environment-dependent failures: missing binaries, fresh-install errors, post-migration path mismatches, 'command not found', unconfigured credentials, uninstalled packages. The user can fix these \u2014 they are not durable rules.\n \u2022 Negative claims about tools or features ('browser tools do not work', 'X tool is broken', 'cannot use Y'). These harden into refusals the agent cites against itself for months after the actual problem was fixed.\n \u2022 Session-specific transient errors that resolved before the conversation ended. If retrying worked, the lesson is the retry pattern, not the original failure.\n \u2022 One-off task narratives. A user asking 'summarize today's market' or 'analyze this PR' is not a class of work that warrants a skill.\n\nIf a tool failed because of setup state, capture the FIX (install command, config step, env var to set) under an existing setup or troubleshooting skill \u2014 never 'this tool does not work' as a standalone constraint.\n\nAct on whichever of the two dimensions has real signal. If genuinely nothing stands out on either, say 'Nothing to save.' and stop \u2014 but don't reach for that conclusion as a default.";
|
|
@@ -30,7 +30,7 @@ export declare const MAINTAIN_PROMPT = "<<<MAINTAIN_PROMPT v={bundle_version} si
|
|
|
30
30
|
* fail-closed signal); PROMPT_BUNDLE_VERSION itself is owned by the core test
|
|
31
31
|
* pin and stays untouched in this batch.
|
|
32
32
|
*/
|
|
33
|
-
export declare const MAINTAIN_OUTPUT_INSTRUCTION = "\u6309\u6A21\u677F\u5951\u7EA6\u8F93\u51FA JSON \u7EF4\u62A4\u8BA1\u5212\uFF08verdict/plan/notes\uFF09\uFF1B\
|
|
33
|
+
export declare const MAINTAIN_OUTPUT_INSTRUCTION = "\u6309\u6A21\u677F\u5951\u7EA6\u8F93\u51FA JSON \u7EF4\u62A4\u8BA1\u5212\uFF08verdict/plan/notes\uFF09\uFF1B\u4F60\u6709 skill \u5DE5\u5177\u4E0E\u7EF4\u62A4\u6A21\u677F\uFF1B\u5E76\u5728\u7EF4\u62A4\u63A2\u9488\uFF08maintenance_probe\uFF09\u6302\u8F7D\u65F6\u53EF\u7528\u5B83\u6DF1\u6316\u7EC6\u8282\u3002";
|
|
34
34
|
/**
|
|
35
35
|
* System-prompt guidance section (Hermes `SKILLS_GUIDANCE`, DSH-adapted).
|
|
36
36
|
* Registered as a system-prompt section by tool-skill-manage (it mounts
|
|
@@ -321,6 +321,7 @@ export declare class SkillLibrary {
|
|
|
321
321
|
*/
|
|
322
322
|
setPinned(name: string, pinned: boolean, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
323
323
|
create(name: string, content: string, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
324
|
+
private createCore;
|
|
324
325
|
update(rawName: string, content: string, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
325
326
|
private updateCore;
|
|
326
327
|
patch(rawName: string, oldString: string, newString: string, filePath?: string, replaceAll?: boolean, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
@@ -378,6 +379,7 @@ export declare class SkillLibrary {
|
|
|
378
379
|
writeSupportFile(rawName: string, filePath: string, content: string, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
379
380
|
private writeSupportFileCore;
|
|
380
381
|
removeSupportFile(rawName: string, filePath: string, origin?: WriteOrigin): Promise<SkillActionResult>;
|
|
382
|
+
private removeSupportFileCore;
|
|
381
383
|
/**
|
|
382
384
|
* Snapshot the recoverable skills state: active tree, usage/suppression
|
|
383
385
|
* sidecars, `.archive/` and caller-supplied extras. `extras` are opaque
|
package/package.json
CHANGED