@lmzhen/dsh-evolution-core 0.1.0-rc.17 → 0.1.0-rc.19

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 CHANGED
@@ -155,7 +155,9 @@ function latestActivityAt(record) {
155
155
  * Curator suppression sidecar: built-in skills the curator has archived stay
156
156
  * suppressed across re-seeds, so the lifecycle never fights a re-created
157
157
  * bundled skill. Best-effort load/save, mirroring the usage sidecar posture.
158
+ * Versioned shape ({ version, names }) with legacy plain-array compat.
158
159
  */
160
+ const SUPPRESSED_FILE_VERSION = 1;
159
161
  function suppressedFile(root) {
160
162
  return join(root, ".curator-suppressed.json");
161
163
  }
@@ -164,14 +166,17 @@ async function loadSuppressedNames(root, io = nodeEvolutionIo()) {
164
166
  if (raw === null) return /* @__PURE__ */ new Set();
165
167
  try {
166
168
  const parsed = JSON.parse(raw);
167
- if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
168
- return new Set(parsed.filter((entry) => typeof entry === "string"));
169
+ const names = Array.isArray(parsed) ? parsed : typeof parsed === "object" && parsed !== null && Array.isArray(parsed.names) ? parsed.names : [];
170
+ return new Set(names.filter((entry) => typeof entry === "string"));
169
171
  } catch {
170
172
  return /* @__PURE__ */ new Set();
171
173
  }
172
174
  }
173
175
  async function saveSuppressedNames(root, names, io = nodeEvolutionIo()) {
174
- await io.writeText(suppressedFile(root), JSON.stringify([...names].sort(), null, 2));
176
+ await io.writeText(suppressedFile(root), JSON.stringify({
177
+ version: 1,
178
+ names: [...names].sort()
179
+ }, null, 2));
175
180
  }
176
181
  //#endregion
177
182
  //#region lib/types/constants.js
@@ -238,6 +243,7 @@ const DEFAULT_SKILL_CONTENT_CHARS = 1e5;
238
243
  */
239
244
  function buildCuratorRunReport(input) {
240
245
  return {
246
+ schemaVersion: 1,
241
247
  runId: input.runId,
242
248
  startedAt: input.startedAt,
243
249
  finishedAt: input.finishedAt,
@@ -936,6 +942,8 @@ var MemoryStore = class {
936
942
  * @module @lmzhen/dsh-evolution-core
937
943
  */
938
944
  const DEFAULT_MUTATION_CAP = 500;
945
+ /** Version of the `.mutations.json` file shape; writers always emit the current one. */
946
+ const MUTATIONS_FILE_VERSION = 1;
939
947
  function mutationsFile(root) {
940
948
  return join(root, ".mutations.json");
941
949
  }
@@ -947,18 +955,20 @@ async function loadMutations(root, io = nodeEvolutionIo()) {
947
955
  if (raw === null) return [];
948
956
  try {
949
957
  const parsed = JSON.parse(raw);
950
- if (!Array.isArray(parsed)) return [];
951
- return parsed.filter((entry) => typeof entry === "object" && entry !== null && typeof entry.skillName === "string" && typeof entry.action === "string");
958
+ return (Array.isArray(parsed) ? parsed : typeof parsed === "object" && parsed !== null && Array.isArray(parsed.records) ? parsed.records : []).filter((entry) => typeof entry === "object" && entry !== null && typeof entry.skillName === "string" && typeof entry.action === "string");
952
959
  } catch {
953
960
  return [];
954
961
  }
955
962
  }
956
- /** Append one record, trim to `cap`, and write atomically. */
963
+ /** Append one record, trim to `cap`, and write atomically (versioned shape). */
957
964
  async function recordMutation(root, io, record, cap = 500) {
958
965
  const existing = await loadMutations(root, io);
959
966
  existing.push(record);
960
967
  const trimmed = existing.length > cap ? existing.slice(existing.length - cap) : existing;
961
- await io.writeText(mutationsFile(root), JSON.stringify(trimmed, null, 2));
968
+ await io.writeText(mutationsFile(root), JSON.stringify({
969
+ version: 1,
970
+ records: trimmed
971
+ }, null, 2));
962
972
  }
963
973
  //#endregion
964
974
  //#region lib/types/prompts.js
@@ -972,7 +982,13 @@ async function recordMutation(root, io, record, cap = 500) {
972
982
  * bundle digest before spending a model call, so a partially-patched
973
983
  * deployment fails closed instead of silently running a truncated prompt.
974
984
  */
975
- const PROMPT_BUNDLE_ID = "dsh-evolution@1";
985
+ /**
986
+ * Prompt bundle identity. Bump both id and version whenever a prompt's text
987
+ * changes semantically: the bundle digest is the fail-closed signal for
988
+ * review workers, so a stale id across deployments must be distinguishable.
989
+ */
990
+ const PROMPT_BUNDLE_ID = "dsh-evolution@2";
991
+ const PROMPT_BUNDLE_VERSION = 2;
976
992
  const MEMORY_REVIEW_PROMPT = `[Auto-review — Memory]
977
993
  Review the conversation above and consider saving to memory if appropriate.
978
994
 
@@ -1076,12 +1092,12 @@ function sha256(text) {
1076
1092
  function createPromptBundle(prompts) {
1077
1093
  const canonical = JSON.stringify({
1078
1094
  id: PROMPT_BUNDLE_ID,
1079
- version: 1,
1095
+ version: 2,
1080
1096
  prompts: Object.fromEntries(Object.entries(prompts).sort())
1081
1097
  });
1082
1098
  return Object.freeze({
1083
1099
  id: PROMPT_BUNDLE_ID,
1084
- version: 1,
1100
+ version: 2,
1085
1101
  prompts: Object.freeze({ ...prompts }),
1086
1102
  sha256: sha256(canonical)
1087
1103
  });
@@ -1984,4 +2000,4 @@ var JsonState = class JsonState {
1984
2000
  }
1985
2001
  };
1986
2002
  //#endregion
1987
- export { COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, 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, JsonState, LOW_QUALITY_THRESHOLD, MAX_DESCRIPTION_LENGTH, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MEMORY_REVIEW_PROMPT, MemoryStore, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROTECTED_BUILTIN_SKILLS, QUALITY_WEIGHTS, SKILL_NAME_RE, SKILL_REVIEW_PROMPT, SUPPORT_DIRS, SkillLibrary, advanceReview, buildCuratorRunReport, bumpPatch, bumpUse, bumpView, computeDedupGroups, computeLifecycleTransitions, computeQualityScores, contentHash, emptyRecord, evaluateThreat, evolutionHome, evolutionIoAdapter, foldTurn, getRecord, latestActivityAt, loadMutations, loadSuppressedNames, loadUsage, markAgentCreated, memoryRoot, mutationsFile, nodeEvolutionIo, observeEvent, parseCuratorNominations, parseFrontmatter, recordMutation, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, usageFile, validateFrontmatter, verifyPromptBundle };
2003
+ export { COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, 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, 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, SUPPORT_DIRS, SUPPRESSED_FILE_VERSION, SkillLibrary, advanceReview, buildCuratorRunReport, bumpPatch, bumpUse, bumpView, computeDedupGroups, computeLifecycleTransitions, computeQualityScores, contentHash, emptyRecord, evaluateThreat, evolutionHome, evolutionIoAdapter, foldTurn, getRecord, latestActivityAt, loadMutations, loadSuppressedNames, loadUsage, markAgentCreated, memoryRoot, mutationsFile, nodeEvolutionIo, observeEvent, parseCuratorNominations, parseFrontmatter, recordMutation, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, usageFile, validateFrontmatter, verifyPromptBundle };
@@ -44,6 +44,8 @@ export interface CuratorFailedSkill {
44
44
  reason: string;
45
45
  }
46
46
  export interface CuratorRunReport {
47
+ /** Report shape version; readers may ignore unknown fields on later versions. */
48
+ schemaVersion: 1;
47
49
  runId: string;
48
50
  startedAt: string;
49
51
  finishedAt: string;
@@ -14,9 +14,11 @@ export interface MutationRecord {
14
14
  at: string;
15
15
  }
16
16
  export declare const DEFAULT_MUTATION_CAP = 500;
17
+ /** Version of the `.mutations.json` file shape; writers always emit the current one. */
18
+ export declare const MUTATIONS_FILE_VERSION = 1;
17
19
  export declare function mutationsFile(root: string): string;
18
20
  export declare function contentHash(content: string): string;
19
21
  export declare function loadMutations(root: string, io?: EvolutionIoLike): Promise<MutationRecord[]>;
20
- /** Append one record, trim to `cap`, and write atomically. */
22
+ /** Append one record, trim to `cap`, and write atomically (versioned shape). */
21
23
  export declare function recordMutation(root: string, io: EvolutionIoLike, record: MutationRecord, cap?: number): Promise<void>;
22
24
  //# sourceMappingURL=mutations.d.ts.map
@@ -1,4 +1,10 @@
1
- export declare const PROMPT_BUNDLE_ID = "dsh-evolution@1";
1
+ /**
2
+ * Prompt bundle identity. Bump both id and version whenever a prompt's text
3
+ * changes semantically: the bundle digest is the fail-closed signal for
4
+ * review workers, so a stale id across deployments must be distinguishable.
5
+ */
6
+ export declare const PROMPT_BUNDLE_ID = "dsh-evolution@2";
7
+ export declare const PROMPT_BUNDLE_VERSION = 2;
2
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.";
3
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.\n\nTarget shape: CLASS-LEVEL skills with a rich SKILL.md and a references/ directory for session-specific detail. Not a flat list of narrow one-session skills.\n\nSignals that warrant action:\n- The user corrected your style, tone, format, verbosity, workflow, or approach.\n- A non-trivial technique, fix, workaround, or debugging path emerged.\n- A loaded skill turned out wrong, missing, or outdated \u2014 patch it now.\n\nPreference order:\n1. Patch a skill that was loaded or read this session.\n2. Patch an existing umbrella skill.\n3. Add references/, templates/, or scripts/ support under an existing skill.\n4. Create a new class-level umbrella skill only when nothing fits.\n\nProtected skills (bundled/hub-installed) must not be edited. Pinned skills may be patched but not archived.\n\nDo NOT capture:\n- Environment-dependent failures (missing binaries, unconfigured credentials).\n- Negative claims about tools (\"browser tools do not work\").\n- Transient errors that resolved during the session.\n- One-off task narratives.\n\nIf a tool failed because of setup state, capture the FIX under an existing setup 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.";
4
10
  export declare const COMBINED_REVIEW_PROMPT = "[Auto-review]\nReview the conversation above and update two things.\n\n**Memory**: who the user is. Save durable user preferences, personal details, and expectations with the memory tool.\n\n**Skills**: how to do this class of task. Be ACTIVE. Follow the same class-level umbrella policy, preference order, protected-skill rules, and do-not-capture list as a skill review.\n\nAct on whichever dimension 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.";
@@ -34,7 +34,9 @@ export declare function latestActivityAt(record: UsageRecord): string | null;
34
34
  * Curator suppression sidecar: built-in skills the curator has archived stay
35
35
  * suppressed across re-seeds, so the lifecycle never fights a re-created
36
36
  * bundled skill. Best-effort load/save, mirroring the usage sidecar posture.
37
+ * Versioned shape ({ version, names }) with legacy plain-array compat.
37
38
  */
39
+ export declare const SUPPRESSED_FILE_VERSION = 1;
38
40
  export declare function suppressedFile(root: string): string;
39
41
  export declare function loadSuppressedNames(root: string, io?: EvolutionIoLike): Promise<ReadonlySet<string>>;
40
42
  export declare function saveSuppressedNames(root: string, names: ReadonlySet<string>, io?: EvolutionIoLike): Promise<void>;
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.17",
4
+ "version": "0.1.0-rc.19",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },