@lmzhen/dsh-evolution-core 0.1.0-rc.61 → 0.1.0-rc.63

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
@@ -685,8 +685,8 @@ function computeLifecycleTransitions(usage, config, now = /* @__PURE__ */ new Da
685
685
  * changes semantically: the bundle digest is the fail-closed signal for
686
686
  * review workers, so a stale id across deployments must be distinguishable.
687
687
  */
688
- const PROMPT_BUNDLE_ID = "dsh-evolution@5";
689
- const PROMPT_BUNDLE_VERSION = 5;
688
+ const PROMPT_BUNDLE_ID = "dsh-evolution@6";
689
+ const PROMPT_BUNDLE_VERSION = 6;
690
690
  const MEMORY_REVIEW_PROMPT = `[Auto-review — Memory]
691
691
  Review the conversation above and consider saving to memory if appropriate.
692
692
 
@@ -810,15 +810,7 @@ How to work:
810
810
  4. Flag skills whose NAME is too narrow (contains a PR number, a feature codename, a specific error string, an 'audit'/'diagnosis'/'salvage' session artifact) — they almost always belong as a subsection or support file under a class-level umbrella.
811
811
  5. Iterate. After one consolidation round, scan the remaining set and look for the NEXT umbrella opportunity. Don't stop after 3 merges.
812
812
 
813
- Your toolset:
814
- - skill_manage action=list / review — read the current landscape.
815
- - skill_manage action=patch — add sections to the umbrella.
816
- - skill_manage action=create — create a new umbrella SKILL.md.
817
- - skill_manage action=write_file — add a references/, templates/, or scripts/ file under an existing skill (the skill must already exist).
818
- - skill_manage action=delete — archive a skill. MUST pass absorbed_into=<umbrella> when you've merged its content into another skill, or absorbed_into="" when you're truly pruning with no forwarding target.
819
- - skill_manage action=consolidate — merge source bodies into a target and archive the sources when patching by hand is error-prone.
820
- - skill_manage action=restore — bring one archived skill back (recoverability is the archive's contract).
821
- - For moving support files, keep it inside the skill tree: support files move via reading and writing through skill_manage write_file/remove_file.
813
+ You are a NOMINATOR, not an executor: this channel has NO tools. Your single deliverable is the structured YAML block below. Never narrate actions you did not take ("merged", "patched", "archived") — you are proposing, and the deterministic engine executes only names from the candidate pool it gave you. (A future execution view would expose skill_manage; today it does not.)
822
814
 
823
815
  'keep' is a legitimate decision ONLY when the skill is already a class-level umbrella and none of the proposed merges would improve discoverability. 'This is narrow but distinct from its siblings' is NOT a reason to keep — it's a reason to move it under an umbrella as a subsection or support file.
824
816
 
@@ -826,7 +818,7 @@ Expected output: real umbrella-ification. Process every obvious cluster. If you
826
818
 
827
819
  Keep the umbrella body tight and scannable: exact commands, verbatim paths, ~100-200 lines; never invent flags or APIs.
828
820
 
829
- When done, write a human summary AND a structured machine-readable block so downstream tooling can distinguish consolidation from pruning. Format EXACTLY:
821
+ When done, write a human summary THEN the structured machine-readable block. The block is the contract: every skill you would move to .archive/ MUST appear in exactly one of the two lists. Return ONLY the YAML block after the summary — no post-block prose. Format EXACTLY:
830
822
 
831
823
  ## Structured summary (required)
832
824
  \`\`\`yaml
@@ -839,7 +831,7 @@ prunings:
839
831
  reason: <one short sentence — why archived with no merge target>
840
832
  \`\`\`
841
833
 
842
- Every skill you moved to .archive/ MUST appear in exactly one of the two lists. If you consolidated X into umbrella Y (patched Y, wrote a references file to Y, or created Y with X's content absorbed), X goes under consolidations with into: Y. If you archived X with no absorption — truly stale, irrelevant, or obsolete — X goes under prunings. Leave a list empty (consolidations: []) if none. Do not omit the block. The block comes AFTER your human-readable summary of clusters processed, patches made, and decisions left alone.`;
834
+ Every skill you would move to .archive/ MUST appear in exactly one of the two lists. If you consolidated X into umbrella Y (patched Y, wrote a references file to Y, or created Y with X's content absorbed), X goes under consolidations with into: Y. If you archived X with no absorption — truly stale, irrelevant, or obsolete — X goes under prunings. Leave a list empty (consolidations: []) if none. Do not omit the block. The block comes AFTER your human-readable summary of clusters processed, patches made, and decisions left alone.`;
843
835
  const CURATOR_DRY_RUN_BANNER = `═══════════════════════════════════════════════════════════════
844
836
  DRY-RUN — REPORT ONLY. DO NOT MUTATE THE SKILL LIBRARY.
845
837
  ═══════════════════════════════════════════════════════════════
@@ -867,8 +859,16 @@ Do NOT modify output files or re-run the task. If you are still mid-task, ignore
867
859
  const SKILLS_GUIDANCE = `Skills guidance:
868
860
  • After completing a complex task (5+ tool calls), fixing a tricky error, or discovering a non-trivial workflow, save the approach as a skill with skill_manage so you can reuse it next time.
869
861
  • When using a skill and finding it outdated, incomplete, or wrong, patch it immediately with skill_manage (action='patch') — don't wait to be asked. Skills that aren't maintained become liabilities.`;
870
- function reviewPrompt(kind) {
862
+ const PLAN_CHANNEL_NOTE = `
863
+
864
+ CHANNEL (subagent): this review channel mounts only the read-only \`skill\` tool — you have NO \`skill_manage\`, NO \`memory\`. Your deliverable is the structured JSON plan below (outputSchema). Describe the patches/creates you RECOMMEND in the plan; never narrate actions you took.`;
865
+ /** Subagent-channel variant: same review policy, channel-limited deliverable (M-2). */
866
+ const SKILL_REVIEW_PLAN_PROMPT = `${SKILL_REVIEW_PROMPT}${PLAN_CHANNEL_NOTE}`;
867
+ /** Subagent-channel variant of the combined review (M-2). */
868
+ const COMBINED_REVIEW_PLAN_PROMPT = `${COMBINED_REVIEW_PROMPT}${PLAN_CHANNEL_NOTE}`;
869
+ function reviewPrompt(kind, channel = "agent") {
871
870
  if (kind === "memory") return MEMORY_REVIEW_PROMPT;
871
+ if (channel === "plan") return kind === "skill" ? SKILL_REVIEW_PLAN_PROMPT : COMBINED_REVIEW_PLAN_PROMPT;
872
872
  if (kind === "skill") return SKILL_REVIEW_PROMPT;
873
873
  return COMBINED_REVIEW_PROMPT;
874
874
  }
@@ -878,12 +878,12 @@ function sha256(text) {
878
878
  function createPromptBundle(prompts) {
879
879
  const canonical = JSON.stringify({
880
880
  id: PROMPT_BUNDLE_ID,
881
- version: 5,
881
+ version: 6,
882
882
  prompts: Object.fromEntries(Object.entries(prompts).sort())
883
883
  });
884
884
  return Object.freeze({
885
885
  id: PROMPT_BUNDLE_ID,
886
- version: 5,
886
+ version: 6,
887
887
  prompts: Object.freeze({ ...prompts }),
888
888
  sha256: sha256(canonical)
889
889
  });
@@ -892,15 +892,17 @@ const PROMPT_BUNDLE = createPromptBundle({
892
892
  memory: MEMORY_REVIEW_PROMPT,
893
893
  skill: SKILL_REVIEW_PROMPT,
894
894
  combined: COMBINED_REVIEW_PROMPT,
895
+ skillPlan: SKILL_REVIEW_PLAN_PROMPT,
896
+ combinedPlan: COMBINED_REVIEW_PLAN_PROMPT,
895
897
  curator: CURATOR_PROMPT,
896
898
  completion: COMPLETION_SKILL_REVIEW_PROMPT,
897
899
  skillsGuidance: SKILLS_GUIDANCE
898
900
  });
899
901
  function verifyPromptBundle(bundle = PROMPT_BUNDLE) {
900
- if (bundle.id !== "dsh-evolution@5" || bundle.version !== 5) return false;
902
+ if (bundle.id !== "dsh-evolution@6" || bundle.version !== 6) return false;
901
903
  const canonical = JSON.stringify({
902
904
  id: PROMPT_BUNDLE_ID,
903
- version: 5,
905
+ version: 6,
904
906
  prompts: Object.fromEntries(Object.entries(bundle.prompts).sort())
905
907
  });
906
908
  return bundle.sha256 === sha256(canonical);
@@ -935,7 +937,13 @@ Quality bar:
935
937
  - Prefer verbatim flags, paths, and APIs from the source. Never invent them.
936
938
  - Keep it tight: ~100 lines simple, ~200 complex.
937
939
  - No router/index/hub skills that only point at other skills.
938
- - References go in \`references/\`, templates in \`templates/\`.`;
940
+ - References go in \`references/\`, templates in \`templates/\`.
941
+
942
+ Learn workflow (when the user asks you to learn a reusable skill, or you decide to turn a source/request into one):
943
+ 1. Gather every source named (files, URLs, "what we just did", pasted notes) with the tools you already have — and treat prose after a source as authoring requirements, not noise.
944
+ 2. Apply every requirement and constraint from the request to the SKILL.md you author.
945
+ 3. Author exactly ONE SKILL.md and save it with \`skill_manage\` (action=create); non-trivial scripts go under \`scripts/\`.
946
+ 4. When done, tell the user the skill name, its category, and a one-line summary of what it captured.`;
939
947
  //#endregion
940
948
  //#region lib/types/learn-prompt.js
941
949
  /**
@@ -1372,59 +1380,103 @@ var MemoryStore = class {
1372
1380
  };
1373
1381
  }
1374
1382
  async add(target, facts) {
1375
- const refusal = await this.oversizedRefusal(target);
1376
- if (refusal) return refusal;
1377
- if (await this.detectDrift(target)) {
1378
- const backup = await this.backupFile(target);
1379
- return {
1380
- ok: false,
1381
- message: `External drift detected in memory file.${backup ? ` A backup was saved to ${basename(backup)}.` : ""} Resolve the drift before retrying.`,
1382
- entries: [],
1383
- chars: 0,
1384
- limit: this.limitFor(target)
1385
- };
1386
- }
1387
- const content = facts.trim();
1388
- if (!content) return {
1383
+ if (!facts.trim()) return {
1389
1384
  ok: false,
1390
1385
  message: "Content cannot be empty.",
1391
1386
  entries: [],
1392
1387
  chars: 0,
1393
1388
  limit: this.limitFor(target)
1394
1389
  };
1390
+ const path = fileFor(this.root, target);
1391
+ let outcome;
1392
+ await transactIo(this.io, path, async (current) => {
1393
+ const core = await this.addCore(target, facts, current ?? "");
1394
+ outcome = core.result;
1395
+ return core.write ?? current ?? null;
1396
+ });
1397
+ return outcome;
1398
+ }
1399
+ /**
1400
+ * Single-entry add inside the transaction: shared checks (oversized,
1401
+ * drift, threat) and the content computation. `raw` is the locked view
1402
+ * (`current`) — never a second IO read. `write: null` means "no change".
1403
+ */
1404
+ async addCore(target, facts, raw) {
1405
+ const content = facts.trim();
1406
+ if (!content) return {
1407
+ result: this.failure(target, "Content cannot be empty.", []),
1408
+ write: null
1409
+ };
1410
+ const refusal = await this.oversizedRefusal(target);
1411
+ if (refusal) return {
1412
+ result: refusal,
1413
+ write: null
1414
+ };
1415
+ if (this.driftFromRaw(target, raw)) {
1416
+ const backup = await this.backupFile(target);
1417
+ return {
1418
+ result: {
1419
+ ok: false,
1420
+ message: `External drift detected in memory file.${backup ? ` A backup was saved to ${basename(backup)}.` : ""} Resolve the drift before retrying.`,
1421
+ entries: [],
1422
+ chars: 0,
1423
+ limit: this.limitFor(target)
1424
+ },
1425
+ write: null
1426
+ };
1427
+ }
1395
1428
  const threat = scanMemoryThreats(content);
1396
1429
  if (threat) return {
1397
- ok: false,
1398
- message: threat,
1399
- entries: [],
1400
- chars: 0,
1401
- limit: this.limitFor(target)
1430
+ result: {
1431
+ ok: false,
1432
+ message: threat,
1433
+ entries: [],
1434
+ chars: 0,
1435
+ limit: this.limitFor(target)
1436
+ },
1437
+ write: null
1402
1438
  };
1403
- const entries = await this.read(target);
1439
+ const entries = [...new Set(normalizeEntries(raw))];
1404
1440
  if (entries.some((entry) => stripDatePrefix(entry) === content)) {
1405
1441
  this.resetFailures();
1406
1442
  return {
1407
- ok: true,
1408
- message: `Entry already exists (no duplicate added).${this.storageHint(target, entries.join(ENTRY_DELIMITER).length)}`,
1409
- entries,
1410
- chars: entries.join(ENTRY_DELIMITER).length,
1411
- limit: this.limitFor(target)
1443
+ result: {
1444
+ ok: true,
1445
+ message: `Entry already exists (no duplicate added).${this.storageHint(target, entries.join(ENTRY_DELIMITER).length)}`,
1446
+ entries,
1447
+ chars: entries.join(ENTRY_DELIMITER).length,
1448
+ limit: this.limitFor(target)
1449
+ },
1450
+ write: null
1412
1451
  };
1413
1452
  }
1414
1453
  const next = [...entries, this.addDatePrefix ? `## ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}\n${content}` : content];
1415
1454
  const total = next.join(ENTRY_DELIMITER).length;
1416
1455
  const addLimit = this.limitFor(target);
1417
- if (addLimit > 0 && total > addLimit) return this.failure(target, `Adding this entry would exceed the ${addLimit} char limit. Consolidate or remove stale entries, then retry.`, entries);
1418
- await this.write(target, next);
1456
+ if (addLimit > 0 && total > addLimit) return {
1457
+ result: this.failure(target, `Adding this entry would exceed the ${addLimit} char limit. Consolidate or remove stale entries, then retry.`, entries),
1458
+ write: null
1459
+ };
1419
1460
  this.resetFailures();
1420
1461
  return {
1421
- ok: true,
1422
- message: `Entry added.${this.storageHint(target, total)}`,
1423
- entries: next,
1424
- chars: total,
1425
- limit: this.limitFor(target)
1462
+ result: {
1463
+ ok: true,
1464
+ message: `Entry added.${this.storageHint(target, total)}`,
1465
+ entries: next,
1466
+ chars: total,
1467
+ limit: this.limitFor(target)
1468
+ },
1469
+ write: render(next)
1426
1470
  };
1427
1471
  }
1472
+ /** Canonical-form drift check derived from the locked view (same formula as `detectDrift`, no second read). */
1473
+ driftFromRaw(target, raw) {
1474
+ if (raw.trim() === "") return false;
1475
+ const entries = normalizeEntries(raw);
1476
+ const limit = this.limitFor(target);
1477
+ if (limit > 0 && entries.some((entry) => entry.length > limit)) return true;
1478
+ return render(entries) !== raw;
1479
+ }
1428
1480
  async applyBatch(target, operations) {
1429
1481
  if (operations.length === 0) return {
1430
1482
  ok: false,
@@ -1433,95 +1485,138 @@ var MemoryStore = class {
1433
1485
  chars: 0,
1434
1486
  limit: this.limitFor(target)
1435
1487
  };
1488
+ const path = fileFor(this.root, target);
1489
+ let outcome;
1490
+ await transactIo(this.io, path, async (current) => {
1491
+ const core = await this.applyBatchCore(target, operations, current ?? "");
1492
+ outcome = core.result;
1493
+ return core.write ?? current ?? null;
1494
+ });
1495
+ return outcome;
1496
+ }
1497
+ /** Batch RMW inside the transaction. `write: null` = failure/no-op, disk untouched. */
1498
+ async applyBatchCore(target, operations, raw) {
1436
1499
  const refusal = await this.oversizedRefusal(target);
1437
- if (refusal) return refusal;
1438
- if (await this.detectDrift(target)) {
1500
+ if (refusal) return {
1501
+ result: refusal,
1502
+ write: null
1503
+ };
1504
+ if (this.driftFromRaw(target, raw)) {
1439
1505
  const backup = await this.backupFile(target);
1440
1506
  return {
1441
- ok: false,
1442
- message: `External drift detected in memory file.${backup ? ` A backup was saved to ${basename(backup)}.` : ""} Resolve the drift before retrying.`,
1443
- entries: [],
1444
- chars: 0,
1445
- limit: this.limitFor(target)
1507
+ result: {
1508
+ ok: false,
1509
+ message: `External drift detected in memory file.${backup ? ` A backup was saved to ${basename(backup)}.` : ""} Resolve the drift before retrying.`,
1510
+ entries: [],
1511
+ chars: 0,
1512
+ limit: this.limitFor(target)
1513
+ },
1514
+ write: null
1446
1515
  };
1447
1516
  }
1448
- const entries = await this.read(target);
1517
+ const entries = [...new Set(normalizeEntries(raw))];
1449
1518
  const working = [...entries];
1450
1519
  for (const [index, op] of operations.entries()) {
1451
1520
  const position = index + 1;
1452
1521
  if (op.action === "add") {
1453
1522
  const body = (op.facts ?? "").trim();
1454
1523
  if (!body) return {
1455
- ok: false,
1456
- message: `Operation ${position} (add): facts is required. No operations were applied.${previewEntries(entries)}`,
1457
- entries,
1458
- chars: entries.join(ENTRY_DELIMITER).length,
1459
- limit: this.limitFor(target)
1524
+ result: {
1525
+ ok: false,
1526
+ message: `Operation ${position} (add): facts is required. No operations were applied.${previewEntries(entries)}`,
1527
+ entries,
1528
+ chars: entries.join(ENTRY_DELIMITER).length,
1529
+ limit: this.limitFor(target)
1530
+ },
1531
+ write: null
1460
1532
  };
1461
1533
  const threat = scanMemoryThreats(body);
1462
1534
  if (threat) return {
1463
- ok: false,
1464
- message: `Operation ${position}: ${threat}`,
1465
- entries,
1466
- chars: entries.join(ENTRY_DELIMITER).length,
1467
- limit: this.limitFor(target)
1535
+ result: {
1536
+ ok: false,
1537
+ message: `Operation ${position}: ${threat}`,
1538
+ entries,
1539
+ chars: entries.join(ENTRY_DELIMITER).length,
1540
+ limit: this.limitFor(target)
1541
+ },
1542
+ write: null
1468
1543
  };
1469
1544
  if (!working.some((entry) => stripDatePrefix(entry) === body)) working.push(this.addDatePrefix ? `## ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}\n${body}` : body);
1470
1545
  continue;
1471
1546
  }
1472
1547
  const needle = (op.old_text ?? "").trim();
1473
1548
  if (!needle) return {
1474
- ok: false,
1475
- message: `Operation ${position} (${op.action}): old_text is required. No operations were applied.${previewEntries(entries)}`,
1476
- entries,
1477
- chars: entries.join(ENTRY_DELIMITER).length,
1478
- limit: this.limitFor(target)
1549
+ result: {
1550
+ ok: false,
1551
+ message: `Operation ${position} (${op.action}): old_text is required. No operations were applied.${previewEntries(entries)}`,
1552
+ entries,
1553
+ chars: entries.join(ENTRY_DELIMITER).length,
1554
+ limit: this.limitFor(target)
1555
+ },
1556
+ write: null
1479
1557
  };
1480
1558
  const matches = working.map((entry, matchIndex) => ({
1481
1559
  entry,
1482
1560
  matchIndex
1483
1561
  })).filter(({ entry }) => entry.includes(needle));
1484
- if (matches.length === 0) return this.failure(target, `Operation ${position}: no entry matching "${needle}" found. No operations were applied.`, entries);
1562
+ if (matches.length === 0) return {
1563
+ result: this.failure(target, `Operation ${position}: no entry matching "${needle}" found. No operations were applied.`, entries),
1564
+ write: null
1565
+ };
1485
1566
  if (new Set(matches.map((m) => m.entry)).size > 1) return {
1486
- ok: false,
1487
- message: `Operation ${position}: "${needle}" matched multiple distinct entries. No operations were applied.${previewEntries(entries)}`,
1488
- entries,
1489
- chars: entries.join(ENTRY_DELIMITER).length,
1490
- limit: this.limitFor(target)
1567
+ result: {
1568
+ ok: false,
1569
+ message: `Operation ${position}: "${needle}" matched multiple distinct entries. No operations were applied.${previewEntries(entries)}`,
1570
+ entries,
1571
+ chars: entries.join(ENTRY_DELIMITER).length,
1572
+ limit: this.limitFor(target)
1573
+ },
1574
+ write: null
1491
1575
  };
1492
1576
  const matchIndex = matches[0]?.matchIndex ?? -1;
1493
1577
  if (op.action === "remove") working.splice(matchIndex, 1);
1494
1578
  else {
1495
1579
  const body = (op.facts ?? "").trim();
1496
1580
  if (!body) return {
1497
- ok: false,
1498
- message: `Operation ${position} (replace): facts is required.${previewEntries(entries)}`,
1499
- entries,
1500
- chars: entries.join(ENTRY_DELIMITER).length,
1501
- limit: this.limitFor(target)
1581
+ result: {
1582
+ ok: false,
1583
+ message: `Operation ${position} (replace): facts is required.${previewEntries(entries)}`,
1584
+ entries,
1585
+ chars: entries.join(ENTRY_DELIMITER).length,
1586
+ limit: this.limitFor(target)
1587
+ },
1588
+ write: null
1502
1589
  };
1503
1590
  const threat = scanMemoryThreats(body);
1504
1591
  if (threat) return {
1505
- ok: false,
1506
- message: `Operation ${position}: ${threat}`,
1507
- entries,
1508
- chars: entries.join(ENTRY_DELIMITER).length,
1509
- limit: this.limitFor(target)
1592
+ result: {
1593
+ ok: false,
1594
+ message: `Operation ${position}: ${threat}`,
1595
+ entries,
1596
+ chars: entries.join(ENTRY_DELIMITER).length,
1597
+ limit: this.limitFor(target)
1598
+ },
1599
+ write: null
1510
1600
  };
1511
1601
  working[matchIndex] = body;
1512
1602
  }
1513
1603
  }
1514
1604
  const total = working.join(ENTRY_DELIMITER).length;
1515
1605
  const batchLimit = this.limitFor(target);
1516
- if (batchLimit > 0 && total > batchLimit) return this.failure(target, `Batch result (${total} chars) exceeds the ${batchLimit} limit. Remove or shorten more entries in the same batch.`, entries);
1517
- await this.write(target, working);
1606
+ if (batchLimit > 0 && total > batchLimit) return {
1607
+ result: this.failure(target, `Batch result (${total} chars) exceeds the ${batchLimit} limit. Remove or shorten more entries in the same batch.`, entries),
1608
+ write: null
1609
+ };
1518
1610
  this.resetFailures();
1519
1611
  return {
1520
- ok: true,
1521
- message: `Applied ${operations.length} operation(s).${this.storageHint(target, total)}`,
1522
- entries: working,
1523
- chars: total,
1524
- limit: this.limitFor(target)
1612
+ result: {
1613
+ ok: true,
1614
+ message: `Applied ${operations.length} operation(s).${this.storageHint(target, total)}`,
1615
+ entries: working,
1616
+ chars: total,
1617
+ limit: this.limitFor(target)
1618
+ },
1619
+ write: render(working)
1525
1620
  };
1526
1621
  }
1527
1622
  async renderContext() {
@@ -2857,4 +2952,4 @@ function evolutionHome(env = process.env) {
2857
2952
  return join(env.DSH_HOME ?? join(homedir(), ".dsh"), "evolution");
2858
2953
  }
2859
2954
  //#endregion
2860
- export { AUTHORING_DESCRIPTION_BAR, 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, 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, SKILLS_GUIDANCE, SKILL_NAME_RE, SKILL_REVIEW_PROMPT, SNAPSHOT_EXTRA_NAME_RE, SUPPORT_DIRS, SUPPRESSED_FILE_VERSION, SkillLibrary, advanceReview, authoringFeedback, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, computeDedupGroups, computeLifecycleTransitions, computeQualityScores, computeScopeView, contentHash, createGateSet, emptyRecord, evaluateThreat, evolutionHome, evolutionIoAdapter, foldTurn, getRecord, latestActivityAt, lifecycleCandidate, loadMutations, loadSuppressedNames, loadUsage, markAgentCreated, memoryRoot, mutateUsage, mutationsFile, nodeEvolutionIo, normalizeUsageRecord, observeEvent, parseCuratorNominations, parseFrontmatter, recordMutation, relatedSkillNames, renderCuratorReportMarkdown, resolveOrigins, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, transactIo, updateSuppressedNames, usageFile, validateFrontmatter, verifyPromptBundle };
2955
+ export { AUTHORING_DESCRIPTION_BAR, COMBINED_REVIEW_PLAN_PROMPT, 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, 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, SKILLS_GUIDANCE, SKILL_NAME_RE, SKILL_REVIEW_PLAN_PROMPT, SKILL_REVIEW_PROMPT, SNAPSHOT_EXTRA_NAME_RE, SUPPORT_DIRS, SUPPRESSED_FILE_VERSION, SkillLibrary, advanceReview, authoringFeedback, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, computeDedupGroups, computeLifecycleTransitions, computeQualityScores, computeScopeView, contentHash, createGateSet, emptyRecord, evaluateThreat, evolutionHome, evolutionIoAdapter, foldTurn, getRecord, latestActivityAt, lifecycleCandidate, loadMutations, loadSuppressedNames, loadUsage, markAgentCreated, memoryRoot, mutateUsage, mutationsFile, nodeEvolutionIo, normalizeUsageRecord, observeEvent, parseCuratorNominations, parseFrontmatter, recordMutation, relatedSkillNames, renderCuratorReportMarkdown, resolveOrigins, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, transactIo, updateSuppressedNames, usageFile, validateFrontmatter, verifyPromptBundle };
@@ -72,7 +72,17 @@ export declare class MemoryStore {
72
72
  */
73
73
  private oversizedRefusal;
74
74
  add(target: MemoryTarget, facts: string): Promise<MemoryApplyResult>;
75
+ /**
76
+ * Single-entry add inside the transaction: shared checks (oversized,
77
+ * drift, threat) and the content computation. `raw` is the locked view
78
+ * (`current`) — never a second IO read. `write: null` means "no change".
79
+ */
80
+ private addCore;
81
+ /** Canonical-form drift check derived from the locked view (same formula as `detectDrift`, no second read). */
82
+ private driftFromRaw;
75
83
  applyBatch(target: MemoryTarget, operations: MemoryOperation[]): Promise<MemoryApplyResult>;
84
+ /** Batch RMW inside the transaction. `write: null` = failure/no-op, disk untouched. */
85
+ private applyBatchCore;
76
86
  renderContext(): Promise<string>;
77
87
  /**
78
88
  * Detect on-disk drift: true when the file is not in the canonical
@@ -3,12 +3,12 @@
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_ID = "dsh-evolution@5";
7
- export declare const PROMPT_BUNDLE_VERSION = 5;
6
+ export declare const PROMPT_BUNDLE_ID = "dsh-evolution@6";
7
+ export declare const PROMPT_BUNDLE_VERSION = 6;
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\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. 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 only the foreground may update or archive them. Foreground and delegated-subagent 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\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. 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 only the foreground may update or archive them. Foreground and delegated-subagent 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.";
11
- export declare const CURATOR_PROMPT = "You are the skill curator. Maintain a healthy, class-level skill library, not a flat pile of narrow one-session skills.\n\nThis is an UMBRELLA-BUILDING consolidation pass, not a passive audit and not a duplicate-finder.\n\nThe goal is a LIBRARY OF CLASS-LEVEL INSTRUCTIONS. A skill collection of many narrow skills where each captures one session's specific bug is a FAILURE of the library. An agent searching skills matches on descriptions, not exact names; one broad umbrella with labeled subsections beats five narrow siblings for discoverability.\n\nRight target shape: class-level skills with rich SKILL.md + references/, templates/, scripts/ support files for session-specific detail.\n\nHard rules:\n1. NEVER hard-delete a skill. Archive (moving to .archive/) is the maximum destructive action; archives are recoverable, deletion is not.\n2. Do not touch bundled, hub-installed, pinned, or scheduled-task-referenced (referenced) skills. Referenced skills MAY be consolidated into an umbrella \u2014 but only because the curator rewrites scheduled-task skill references to follow consolidations; never simply prune them.\n3. Do not archive recently-created or never-used skills without strong evidence. \"use=0\" is NOT evidence either way \u2014 it only means the trigger has not come up yet. Never archive a never-used skill unless it is at least 30 days old AND its content is genuinely obsolete or fully absorbed elsewhere.\n4. Do NOT reject consolidation on the grounds that \"each skill has a distinct trigger\". The right bar is: would a human maintainer write this as N separate skills, or one skill with N labeled subsections? When the answer is the latter, merge.\n5. Judge overlap on CONTENT, not on usage counters.\n6. Before archiving a merged skill, ensure its unique content was preserved in the umbrella.\n\nHow to work:\n1. Scan the candidate list. Identify PREFIX CLUSTERS \u2014 skills sharing a first word or domain keyword. Expected cluster count scales with the library: a large collection may show 10-25 prefix clusters, a small one often has none \u2014 a clean \"nothing to consolidate\" summary is the correct small-library outcome, not a shortage of ambition.\n2. For each cluster with 2+ members, ask \"what is the UMBRELLA CLASS these skills serve?\" and consolidate:\n a. MERGE INTO AN EXISTING UMBRELLA (patch a labeled section for each sibling's unique insight, then archive the siblings).\n b. CREATE A NEW UMBRELLA SKILL.md covering the shared workflow with short labeled subsections, then archive the absorbed siblings.\n c. DEMOTE session-specific detail to references/, templates/, or scripts/ under the umbrella. Use the right directory per kind:\n \u2022 references/<topic>.md \u2014 session-specific detail OR condensed knowledge banks (quoted research, API docs excerpts, domain notes, provider quirks, reproduction recipes) written concise and task-focused.\n \u2022 templates/<name>.<ext> \u2014 starter files meant to be copied and modified.\n \u2022 scripts/<name>.<ext> \u2014 statically re-runnable actions (verification scripts, fixture generators, probes).\n3. Package integrity \u2014 not optional: inspect each skill as a COMPLETE directory package, not just SKILL.md. A skill root may include references/, templates/, scripts/, and assets/. If the source skill has support files OR its SKILL.md contains relative links to them, DO NOT flatten only SKILL.md into <umbrella>/references/<old>.md. Choose one safe path instead: keep it as a standalone skill, OR fully merge by re-homing every needed support file into the umbrella's canonical directories AND rewriting the destination instructions to the new paths, OR archive the entire original skill package unchanged. Never leave demoted instructions pointing at files left behind under the old skill directory.\n4. Flag skills whose NAME is too narrow (contains a PR number, a feature codename, a specific error string, an 'audit'/'diagnosis'/'salvage' session artifact) \u2014 they almost always belong as a subsection or support file under a class-level umbrella.\n5. Iterate. After one consolidation round, scan the remaining set and look for the NEXT umbrella opportunity. Don't stop after 3 merges.\n\nYour toolset:\n - skill_manage action=list / review \u2014 read the current landscape.\n - skill_manage action=patch \u2014 add sections to the umbrella.\n - skill_manage action=create \u2014 create a new umbrella SKILL.md.\n - skill_manage action=write_file \u2014 add a references/, templates/, or scripts/ file under an existing skill (the skill must already exist).\n - skill_manage action=delete \u2014 archive a skill. MUST pass absorbed_into=<umbrella> when you've merged its content into another skill, or absorbed_into=\"\" when you're truly pruning with no forwarding target.\n - skill_manage action=consolidate \u2014 merge source bodies into a target and archive the sources when patching by hand is error-prone.\n - skill_manage action=restore \u2014 bring one archived skill back (recoverability is the archive's contract).\n - For moving support files, keep it inside the skill tree: support files move via reading and writing through skill_manage write_file/remove_file.\n\n'keep' is a legitimate decision ONLY when the skill is already a class-level umbrella and none of the proposed merges would improve discoverability. 'This is narrow but distinct from its siblings' is NOT a reason to keep \u2014 it's a reason to move it under an umbrella as a subsection or support file.\n\nExpected output: real umbrella-ification. Process every obvious cluster. If you end the pass with obvious clusters still untouched, you stopped too early \u2014 go back and look at the clusters you left alone.\n\nKeep the umbrella body tight and scannable: exact commands, verbatim paths, ~100-200 lines; never invent flags or APIs.\n\nWhen done, write a human summary AND a structured machine-readable block so downstream tooling can distinguish consolidation from pruning. Format EXACTLY:\n\n## Structured summary (required)\n```yaml\nconsolidations:\n - from: <old-skill-name>\n into: <umbrella-skill-name>\n reason: <one short sentence \u2014 why merged, not just 'similar'>\nprunings:\n - name: <skill-name>\n reason: <one short sentence \u2014 why archived with no merge target>\n```\n\nEvery skill you moved to .archive/ MUST appear in exactly one of the two lists. If you consolidated X into umbrella Y (patched Y, wrote a references file to Y, or created Y with X's content absorbed), X goes under consolidations with into: Y. If you archived X with no absorption \u2014 truly stale, irrelevant, or obsolete \u2014 X goes under prunings. Leave a list empty (consolidations: []) if none. Do not omit the block. The block comes AFTER your human-readable summary of clusters processed, patches made, and decisions left alone.";
11
+ export declare const CURATOR_PROMPT = "You are the skill curator. Maintain a healthy, class-level skill library, not a flat pile of narrow one-session skills.\n\nThis is an UMBRELLA-BUILDING consolidation pass, not a passive audit and not a duplicate-finder.\n\nThe goal is a LIBRARY OF CLASS-LEVEL INSTRUCTIONS. A skill collection of many narrow skills where each captures one session's specific bug is a FAILURE of the library. An agent searching skills matches on descriptions, not exact names; one broad umbrella with labeled subsections beats five narrow siblings for discoverability.\n\nRight target shape: class-level skills with rich SKILL.md + references/, templates/, scripts/ support files for session-specific detail.\n\nHard rules:\n1. NEVER hard-delete a skill. Archive (moving to .archive/) is the maximum destructive action; archives are recoverable, deletion is not.\n2. Do not touch bundled, hub-installed, pinned, or scheduled-task-referenced (referenced) skills. Referenced skills MAY be consolidated into an umbrella \u2014 but only because the curator rewrites scheduled-task skill references to follow consolidations; never simply prune them.\n3. Do not archive recently-created or never-used skills without strong evidence. \"use=0\" is NOT evidence either way \u2014 it only means the trigger has not come up yet. Never archive a never-used skill unless it is at least 30 days old AND its content is genuinely obsolete or fully absorbed elsewhere.\n4. Do NOT reject consolidation on the grounds that \"each skill has a distinct trigger\". The right bar is: would a human maintainer write this as N separate skills, or one skill with N labeled subsections? When the answer is the latter, merge.\n5. Judge overlap on CONTENT, not on usage counters.\n6. Before archiving a merged skill, ensure its unique content was preserved in the umbrella.\n\nHow to work:\n1. Scan the candidate list. Identify PREFIX CLUSTERS \u2014 skills sharing a first word or domain keyword. Expected cluster count scales with the library: a large collection may show 10-25 prefix clusters, a small one often has none \u2014 a clean \"nothing to consolidate\" summary is the correct small-library outcome, not a shortage of ambition.\n2. For each cluster with 2+ members, ask \"what is the UMBRELLA CLASS these skills serve?\" and consolidate:\n a. MERGE INTO AN EXISTING UMBRELLA (patch a labeled section for each sibling's unique insight, then archive the siblings).\n b. CREATE A NEW UMBRELLA SKILL.md covering the shared workflow with short labeled subsections, then archive the absorbed siblings.\n c. DEMOTE session-specific detail to references/, templates/, or scripts/ under the umbrella. Use the right directory per kind:\n \u2022 references/<topic>.md \u2014 session-specific detail OR condensed knowledge banks (quoted research, API docs excerpts, domain notes, provider quirks, reproduction recipes) written concise and task-focused.\n \u2022 templates/<name>.<ext> \u2014 starter files meant to be copied and modified.\n \u2022 scripts/<name>.<ext> \u2014 statically re-runnable actions (verification scripts, fixture generators, probes).\n3. Package integrity \u2014 not optional: inspect each skill as a COMPLETE directory package, not just SKILL.md. A skill root may include references/, templates/, scripts/, and assets/. If the source skill has support files OR its SKILL.md contains relative links to them, DO NOT flatten only SKILL.md into <umbrella>/references/<old>.md. Choose one safe path instead: keep it as a standalone skill, OR fully merge by re-homing every needed support file into the umbrella's canonical directories AND rewriting the destination instructions to the new paths, OR archive the entire original skill package unchanged. Never leave demoted instructions pointing at files left behind under the old skill directory.\n4. Flag skills whose NAME is too narrow (contains a PR number, a feature codename, a specific error string, an 'audit'/'diagnosis'/'salvage' session artifact) \u2014 they almost always belong as a subsection or support file under a class-level umbrella.\n5. Iterate. After one consolidation round, scan the remaining set and look for the NEXT umbrella opportunity. Don't stop after 3 merges.\n\nYou are a NOMINATOR, not an executor: this channel has NO tools. Your single deliverable is the structured YAML block below. Never narrate actions you did not take (\"merged\", \"patched\", \"archived\") \u2014 you are proposing, and the deterministic engine executes only names from the candidate pool it gave you. (A future execution view would expose skill_manage; today it does not.)\n\n'keep' is a legitimate decision ONLY when the skill is already a class-level umbrella and none of the proposed merges would improve discoverability. 'This is narrow but distinct from its siblings' is NOT a reason to keep \u2014 it's a reason to move it under an umbrella as a subsection or support file.\n\nExpected output: real umbrella-ification. Process every obvious cluster. If you end the pass with obvious clusters still untouched, you stopped too early \u2014 go back and look at the clusters you left alone.\n\nKeep the umbrella body tight and scannable: exact commands, verbatim paths, ~100-200 lines; never invent flags or APIs.\n\nWhen done, write a human summary THEN the structured machine-readable block. The block is the contract: every skill you would move to .archive/ MUST appear in exactly one of the two lists. Return ONLY the YAML block after the summary \u2014 no post-block prose. Format EXACTLY:\n\n## Structured summary (required)\n```yaml\nconsolidations:\n - from: <old-skill-name>\n into: <umbrella-skill-name>\n reason: <one short sentence \u2014 why merged, not just 'similar'>\nprunings:\n - name: <skill-name>\n reason: <one short sentence \u2014 why archived with no merge target>\n```\n\nEvery skill you would move to .archive/ MUST appear in exactly one of the two lists. If you consolidated X into umbrella Y (patched Y, wrote a references file to Y, or created Y with X's content absorbed), X goes under consolidations with into: Y. If you archived X with no absorption \u2014 truly stale, irrelevant, or obsolete \u2014 X goes under prunings. Leave a list empty (consolidations: []) if none. Do not omit the block. The block comes AFTER your human-readable summary of clusters processed, patches made, and decisions left alone.";
12
12
  export declare const CURATOR_DRY_RUN_BANNER = "\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nDRY-RUN \u2014 REPORT ONLY. DO NOT MUTATE THE SKILL LIBRARY.\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nThis is a PREVIEW pass. Follow every instruction above EXCEPT:\n \u2022 Do NOT call skill_manage with action=create, update, patch, delete, write_file, or remove_file.\n \u2022 Do NOT move, copy, or rewrite any file under the skills tree.\n\nYour output IS the deliverable: produce the exact same human-readable summary and YAML block you would on a live run, describing the actions you WOULD take. A reviewer will decide whether to approve a live run.\n\nIf you accidentally take a mutating action, say so explicitly in the summary.";
13
13
  export declare const COMPLETION_SKILL_REVIEW_PROMPT = "[Auto-review \u2014 Skills \u00B7 task complete]\nYour current task now appears complete. Before wrapping up, review the approach and update the skill library via skill_manage.\n\nFollow the skills review policy: be ACTIVE, prefer class-level umbrellas, patch ONLY skills loaded or read this session, and capture non-trivial techniques and user corrections. Do NOT capture environment-dependent failures, negative claims about tools, or one-off task narratives.\n\nDo NOT modify output files or re-run the task. If you are still mid-task, ignore this.";
14
14
  /**
@@ -19,7 +19,11 @@ export declare const COMPLETION_SKILL_REVIEW_PROMPT = "[Auto-review \u2014 Skill
19
19
  * model to save/repair skills on its own initiative.
20
20
  */
21
21
  export declare const SKILLS_GUIDANCE = "Skills guidance:\n\u2022 After completing a complex task (5+ tool calls), fixing a tricky error, or discovering a non-trivial workflow, save the approach as a skill with skill_manage so you can reuse it next time.\n\u2022 When using a skill and finding it outdated, incomplete, or wrong, patch it immediately with skill_manage (action='patch') \u2014 don't wait to be asked. Skills that aren't maintained become liabilities.";
22
- export declare function reviewPrompt(kind: 'memory' | 'skill' | 'combined'): string;
22
+ /** Subagent-channel variant: same review policy, channel-limited deliverable (M-2). */
23
+ export declare const SKILL_REVIEW_PLAN_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\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. 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 only the foreground may update or archive them. Foreground and delegated-subagent 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.\n\nCHANNEL (subagent): this review channel mounts only the read-only `skill` tool \u2014 you have NO `skill_manage`, NO `memory`. Your deliverable is the structured JSON plan below (outputSchema). Describe the patches/creates you RECOMMEND in the plan; never narrate actions you took.";
24
+ /** Subagent-channel variant of the combined review (M-2). */
25
+ export declare const COMBINED_REVIEW_PLAN_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\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. 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 only the foreground may update or archive them. Foreground and delegated-subagent 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.\n\nCHANNEL (subagent): this review channel mounts only the read-only `skill` tool \u2014 you have NO `skill_manage`, NO `memory`. Your deliverable is the structured JSON plan below (outputSchema). Describe the patches/creates you RECOMMEND in the plan; never narrate actions you took.";
26
+ export declare function reviewPrompt(kind: 'memory' | 'skill' | 'combined', channel?: 'agent' | 'plan'): string;
23
27
  export interface PromptBundle {
24
28
  id: string;
25
29
  version: number;
@@ -28,5 +32,5 @@ export interface PromptBundle {
28
32
  }
29
33
  export declare const PROMPT_BUNDLE: PromptBundle;
30
34
  export declare function verifyPromptBundle(bundle?: PromptBundle): boolean;
31
- export declare const DSH_AUTHORING_STANDARDS = "Follow the Hermes skill-authoring standards, translated to DSH tools.\n\nFrontmatter:\n- name: lowercase-hyphenated, <=64 chars, no spaces.\n- description: ONE sentence, <=60 characters, ends with a period. State the capability, not the implementation. No marketing words. Do NOT repeat the skill name. Count the characters before saving. If the description contains a colon, wrap the whole value in double quotes.\n- version: 0.1.0\n- author: always the literal value \"Hermes\". NEVER fill it from the environment, git config, or any identity you can probe \u2014 an environment-derived name is a privacy leak the user never opted into (skills get shared and published), and the skill names itself as Hermes.\n- platforms: declare [macos], [linux], and/or [windows] only when the skill is genuinely OS-bound (osascript/apt/systemctl => the matching OS; /proc, signal.SIGKILL => linux; fcntl/termios => POSIX). Prefer fixing it cross-platform first (tempdir, pathlib, pure-Node); omit the field for portable skills.\n- metadata.hermes.tags: a few Capitalized, Relevant, Tags.\n- metadata.hermes.related_skills: [a, b] \u2014 name sibling skills this one builds on or is referenced by (optional; feeds the quality references factor).\n\nBody section order (omit only when empty):\n1. \"# <Human Title>\" then a 2-3 sentence intro: what it does, what it does NOT do, key dependency stance.\n2. \"## When to Use\" \u2014 concrete trigger phrases.\n3. \"## Prerequisites\" \u2014 exact env vars, install steps, credentials.\n4. \"## How to Run\" \u2014 canonical invocation framed through DSH tools.\n5. \"## Quick Reference\" \u2014 flat command/endpoint list.\n6. \"## Procedure\" \u2014 numbered steps with copy-paste-exact commands.\n7. \"## Pitfalls\" \u2014 known limits and rate limits.\n8. \"## Verification\" \u2014 one check proving the skill worked.\n\nDSH-tool framing:\n- Reference DSH tools by name in backticks: `bash`, `str_replace_editor`, `write`, `skill`, `skill_manage`, `memory`.\n- Do not name wrapped shell utilities when a DSH tool already covers them.\n- Larger scripts belong under `scripts/` (written with `skill_manage write_file`) and are referenced from SKILL.md by relative path.\n\nQuality bar:\n- Prefer verbatim flags, paths, and APIs from the source. Never invent them.\n- Keep it tight: ~100 lines simple, ~200 complex.\n- No router/index/hub skills that only point at other skills.\n- References go in `references/`, templates in `templates/`.";
35
+ export declare const DSH_AUTHORING_STANDARDS = "Follow the Hermes skill-authoring standards, translated to DSH tools.\n\nFrontmatter:\n- name: lowercase-hyphenated, <=64 chars, no spaces.\n- description: ONE sentence, <=60 characters, ends with a period. State the capability, not the implementation. No marketing words. Do NOT repeat the skill name. Count the characters before saving. If the description contains a colon, wrap the whole value in double quotes.\n- version: 0.1.0\n- author: always the literal value \"Hermes\". NEVER fill it from the environment, git config, or any identity you can probe \u2014 an environment-derived name is a privacy leak the user never opted into (skills get shared and published), and the skill names itself as Hermes.\n- platforms: declare [macos], [linux], and/or [windows] only when the skill is genuinely OS-bound (osascript/apt/systemctl => the matching OS; /proc, signal.SIGKILL => linux; fcntl/termios => POSIX). Prefer fixing it cross-platform first (tempdir, pathlib, pure-Node); omit the field for portable skills.\n- metadata.hermes.tags: a few Capitalized, Relevant, Tags.\n- metadata.hermes.related_skills: [a, b] \u2014 name sibling skills this one builds on or is referenced by (optional; feeds the quality references factor).\n\nBody section order (omit only when empty):\n1. \"# <Human Title>\" then a 2-3 sentence intro: what it does, what it does NOT do, key dependency stance.\n2. \"## When to Use\" \u2014 concrete trigger phrases.\n3. \"## Prerequisites\" \u2014 exact env vars, install steps, credentials.\n4. \"## How to Run\" \u2014 canonical invocation framed through DSH tools.\n5. \"## Quick Reference\" \u2014 flat command/endpoint list.\n6. \"## Procedure\" \u2014 numbered steps with copy-paste-exact commands.\n7. \"## Pitfalls\" \u2014 known limits and rate limits.\n8. \"## Verification\" \u2014 one check proving the skill worked.\n\nDSH-tool framing:\n- Reference DSH tools by name in backticks: `bash`, `str_replace_editor`, `write`, `skill`, `skill_manage`, `memory`.\n- Do not name wrapped shell utilities when a DSH tool already covers them.\n- Larger scripts belong under `scripts/` (written with `skill_manage write_file`) and are referenced from SKILL.md by relative path.\n\nQuality bar:\n- Prefer verbatim flags, paths, and APIs from the source. Never invent them.\n- Keep it tight: ~100 lines simple, ~200 complex.\n- No router/index/hub skills that only point at other skills.\n- References go in `references/`, templates in `templates/`.\n\nLearn workflow (when the user asks you to learn a reusable skill, or you decide to turn a source/request into one):\n1. Gather every source named (files, URLs, \"what we just did\", pasted notes) with the tools you already have \u2014 and treat prose after a source as authoring requirements, not noise.\n2. Apply every requirement and constraint from the request to the SKILL.md you author.\n3. Author exactly ONE SKILL.md and save it with `skill_manage` (action=create); non-trivial scripts go under `scripts/`.\n4. When done, tell the user the skill name, its category, and a one-line summary of what it captured.";
32
36
  //# sourceMappingURL=prompts.d.ts.map
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.61",
4
+ "version": "0.1.0-rc.63",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },