@lmzhen/dsh-evolution-curator 0.32.4 → 0.32.6

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/README.md CHANGED
@@ -1,48 +1,17 @@
1
1
  # @lmzhen/dsh-evolution-curator
2
2
 
3
- Deterministic skill lifecycle and recovery
3
+ Skill lifecycle service for stale detection, archiving, optional LLM nomination, snapshots, history, restore, and unit undo.
4
4
 
5
- ## Model surface
5
+ Use `/evolution curator status`, `report`, or `run` for inspection and manual operation. Archive/restore/history/undo commands operate on the corresponding stored records; deleting a skill through curation means archiving, not hard deletion.
6
6
 
7
- - **Model-visible:** nothing of its own: it registers no prompt section and no tool schema; the packages that consume this service own the model-visible effects.
8
- - **Prompt prefix / KV cache:** independent of request-prefix construction — it does not alter the assembled prompt or tool list; family-level rules: `packages/README.md` §"Model-visible prompt prefix and the KV cache".
9
- - **Mount it?** yes — the `evolution-curator` row, carried by the `evolution-host`, `evolution-all` and one-click `evolution-preset` bundles; it provides the `evolutionCurator` service the `/evolution curator …` commands and doctor read.
7
+ ## Defaults and scheduling
10
8
 
11
- ## Known limitations
9
+ The plugin and `autoStart` default to enabled. An hourly timer checks due-ness; `curatorIntervalHours` defaults to 168 hours. Pause/resume overrides the startup schedule until that persisted override is cleared.
12
10
 
13
- - LLM nomination pass is advisory and disabled by default; deterministic lifecycle remains authoritative.
14
- - Consolidation is a REAL merger path: the LLM nomination (when enabled / via `recommend()`) proposes
15
- merge groups, the control plane gates them and applies the mutation — merged source bodies are appended
16
- verbatim rather than rewritten into a synthesized skill.
11
+ `staleAfterDays` defaults to 30 and `archiveAfterDays` to 90, with archive required to be at least the stale threshold. The optional `llmReview` pass defaults off. Idle activity gates, protected/referenced names, unmanaged/builtin scope, health thresholds, and model limits are listed in [PARAMETERS.md](../PARAMETERS.md).
17
12
 
18
- ## Recovery and consolidation
13
+ `root` must point at the same skill tree used by the catalog and write tools. `intervalHours` remains a readable deprecated alias of `curatorIntervalHours`; writes to the old name are refused (G0/S0.3).
19
14
 
20
- - `archive` never deletes: skills move to `.archive/` with a `.archive-reason` marker.
21
- - `restore(name)` (service) / `/evolution skill restore <name>` brings one archived skill back to the active root and resets its usage state.
22
- - `history(name)` (service) / `/evolution skill history <name>` lists one skill's content versions (number, time, action, characters, hash prefix) from the content history every write path maintains (`evolution-core/src/skill-history.ts`). An index that cannot be read, carries a foreign field layout, or was written by a NEWER reader all read as "no versions" (the module's never-guess posture) — the next successful write re-seeds the index with a baseline entry, so the record heals instead of staying invisible.
23
- - `undo(name, v?)` (service) / `/evolution skill undo <name> [--to v<N>]` restores one version's CONTENT through an ordinary anchored write: an omitted `v` means the newest version whose content differs from the live file, the anchor is the live hash (a concurrent writer is refused rather than overwritten, and a version the index lists but whose blob cannot be read is refused rather than guessed at), and the rollback itself becomes a new version. Content only: the pin marker, usage counters and curation state are not versions and do not move, which the result text says. A skill with no recorded versions, a target that is not in the active tree (use `skill restore` for an archived one), and a session that cannot replay the write each get their own refusal.
24
- - `consolidate(target, sources)` (service) / `/evolution consolidate` merges source bodies into the target, archives the sources with an absorbed-into marker, and folds their usage records into `archived` state. Both operations snapshot the full state first (`pre-consolidate` / `pre-restore`).
25
- - `restoreSnapshot` (service) / `/evolution restore` rolls the state back to the latest snapshot: active tree, usage/suppression sidecars, `.archive/` and the curator state carried in the snapshot (`curator-state.json`), so the interval gate does not immediately re-fire after a rollback. Skills that were skipped at snapshot time (a live writer held their lock; recorded in the manifest's `skipped` list) are NOT restored — the restore result names them, and `.backups` may hold a copy. The restore itself is undoable — the pre-rollback safety snapshot preserves the current tree plus its state.
15
+ ## Failure boundary
26
16
 
27
- ## Configuration
28
-
29
- - `autoStart` (default true) arms an HOURLY tick that only asks whether the due-ness interval (`curatorIntervalHours`, default 168 h) has elapsed — the tick is not the interval — plus a deferred catch-up check `bootGraceSeconds` (default 10) after host boot. Both decide due-ness from the **persisted** `lastRunAt`, so a restart with an overdue schedule runs the first pass within the boot grace instead of waiting a full interval. `bootGraceSeconds: 0` disables the deferral (not recommended: the check may run against a half-mounted host). All scheduling gates — interval, idle, first-run deferral, and the reentrancy guard — remain inside `run()`.
30
- - `autoStart: false` disables both automatic checks; `/evolution curator run` (manual, gate-skipping) still works.
31
- - `autoStart` is the STARTUP default. The runtime switch is `/evolution curator pause` / `resume`: the pause is persisted in curation state, survives restarts, and wins over `autoStart` until it is cleared — turning `autoStart` off keeps curation manual, it does not freeze a schedule that is already paused or running.
32
- - Deprecated name (G0/S0.3): `intervalHours` is the legacy spelling of the policy
33
- row's `curatorIntervalHours`, whose value the snapshot shadows. Reading it still
34
- works; writing it is refused. Removal was planned for 0.7.0 and is deferred: the alias still ships, so no later version is claimed here.
35
-
36
- **Runtime invariant:** No companion is published. The platform auto-assembles nothing and the family mounts no `<pkg>/invariant` cordis row, so a companion here would never execute (v37 S2.1 / I-3).
37
- ## Notes and history
38
-
39
- - The one-click `/evolution consolidate <target> <source...>` remains the direct manual path (P2-8, v11: the earlier "no LLM pass proposes merge groups" wording contradicted the tested nomination chain).
40
-
41
- ## 单元与撤销(对外契约摘要)
42
-
43
- - 一个单元 = 一次树改动(一个 unitId)。索引里只有一条记录带 unitHead,两形态互斥:代表片 { moves, sources }(全量清单 + 它写过哪些技能)/路标 { skill }(记录在别的技能里);判别式固定为 moves !== undefined。
44
- - undoUnit(name, unitId?):逐路径回该单元铸的基线;没有基线才回退到最早那条的 beforeHash;单元前不存在的路径删除并锚定(盘上字节被别人改过就拒绝,不覆盖)。决策在纯函数 src/unit-undo-plan.ts,IO 与主机不进决策层。
45
- - 跨技能单元:成员只按 sources[] 的已知 key 解析(禁止目录扫描);缺片/外来片/重复片一律拒绝并点名对象 —— 不得用剩下的片段拼一个撤销。
46
- - 路标的 undoable 是 undefined(wire 上不出现该键),绝不为 false;聚合时跳过路标,避免它的 hash 污染同单元兄弟片。
47
- - 剪枝按单元 all-or-nothing;保留窗口今天仍按条目计(切换条件见仓库文档)。
48
- - 完整说明(含回退与验证命令)见仓库 docs/units-and-undo.md;该目录不随 npm 发布,故在此摘要。
17
+ A mutating pass takes snapshots and supports explicit restore/undo. That is not a promise that every failed run automatically rolls back the whole tree; inspect the run report and use the explicit recovery operation when needed. Notifications may be incomplete, so an archived skill can disappear from the catalog without a conversation notice.
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
+ import { CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CURATOR_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MIN_IDLE_HOURS, DEFAULT_REVIEW_TIMEOUT_MS, DEFAULT_SKILL_LIMITS, DEFAULT_STALE_AFTER_DAYS, EXTRACT_PROMPT_HASH, EvolutionGateSet, INSTANCE_KEYS, MAX_TIMER_DELAY_MS, PROMPT_BUNDLE, SKILL_NAME_RE, acquireTreeWriteLock, authorityFrom, blobPath, buildCuratorRunReport, claimInstance, clampOnce, clampedNumber, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, emptyRecord, entryTarget, eventsFile, evolutionHome, evolutionIoAdapter, executeUnitUndo, foldCuratorFields, historyIndexFile, isPresent, isUnknown, lintSkill, liveBool, loadSuppressedNames, loadUsage, markerEntryName, mutateUsage, newSkillLibrary, paramRowId, parseCuratorNominations, parseFrontmatter, parseHistoryIndex, pickWithPolicy, planUnitUndoAcross, policyStageLimits, probeList, probeText, readEvolutionEvents, readNumberParam, registerOwnerSettings, relatedSkillNames, releaseInstance, renderCuratorReportMarkdown, reportTime, reportsSweepLockTarget, resolveUnitMembers, sessionLastEventTime, staleRouteStubs, sweepReports, transactIo, unitMembersAreComplete, unwrapLive, updateSuppressedNames, usageObserved, userSetKeys, verifyPromptBundle, withTreeWrite, writeProposalReport } from "@lmzhen/dsh-evolution-core";
1
2
  import { Service } from "@deepseek-ai/cordis";
2
- import { CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CURATOR_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MIN_IDLE_HOURS, DEFAULT_REVIEW_TIMEOUT_MS, DEFAULT_SKILL_LIMITS, DEFAULT_STALE_AFTER_DAYS, EXTRACT_PROMPT_HASH, EvolutionGateSet, INSTANCE_KEYS, MAX_TIMER_DELAY_MS, PROMPT_BUNDLE, SKILL_NAME_RE, acquireTreeWriteLock, authorityFrom, blobPath, buildCuratorRunReport, claimInstance, clampOnce, clampedNumber, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, emptyRecord, entryTarget, eventsFile, evolutionHome, evolutionIoAdapter, executeUnitUndo, foldCuratorFields, historyIndexFile, isPresent, isUnknown, lintSkill, liveBool, loadSuppressedNames, loadUsage, markerEntryName, mutateUsage, newSkillLibrary, paramRowId, parseCuratorNominations, parseFrontmatter, parseHistoryIndex, pickWithPolicy, planUnitUndoAcross, policyStageLimits, probeList, probeText, readEvolutionEvents, readNumberParam, relatedSkillNames, releaseInstance, renderCuratorReportMarkdown, reportTime, reportsSweepLockTarget, resolveUnitMembers, sessionLastEventTime, staleRouteStubs, sweepReports, transactIo, unitMembersAreComplete, unwrapLive, updateSuppressedNames, usageObserved, userSetKeys, verifyPromptBundle, withTreeWrite, writeProposalReport } from "@lmzhen/dsh-evolution-core";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { dirname, join } from "node:path";
5
5
  import { BlockAssembler, createUserMessage } from "@deepseek-ai/dsh-llm";
@@ -88,7 +88,7 @@ function referencedSkillNames(contents) {
88
88
  }
89
89
  return referencedBy;
90
90
  }
91
- var EvolutionCurator = class extends Service {
91
+ var EvolutionCurator = class EvolutionCurator extends Service {
92
92
  static inject = ["evolutionIo"];
93
93
  static Config = z.object({
94
94
  root: z.string().default(""),
@@ -172,6 +172,7 @@ var EvolutionCurator = class extends Service {
172
172
  instanceOwner = `evolution-curator[${process.pid}:${randomUUID().slice(0, 8)}]`;
173
173
  constructor(ctx, config = {}) {
174
174
  super(ctx, "evolutionCurator");
175
+ registerOwnerSettings(this.ctx, "evolution-curator", EvolutionCurator.Config);
175
176
  ctx.inject(["settings"], (injected) => {
176
177
  const settings = injected.settings;
177
178
  if (typeof settings?.configure !== "function") return;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-evolution-curator",
3
3
  "description": "Deterministic skill lifecycle and recovery (community build)",
4
- "version": "0.32.4",
4
+ "version": "0.32.6",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,21 +27,21 @@
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
29
  "@deepseek-ai/schemastery": "^3.18.5",
30
- "@lmzhen/dsh-evolution-core": "^0.32.4"
30
+ "@lmzhen/dsh-evolution-core": "^0.32.6"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "@deepseek-ai/cordis": "^4.0.5",
34
34
  "@deepseek-ai/dsh-llm": "^0.2.1-rc.2",
35
35
  "@deepseek-ai/dsh-session": "^0.2.1-rc.2",
36
- "@lmzhen/dsh-evolution-io": "^0.32.4",
37
- "@lmzhen/dsh-evolution-state": "^0.32.4"
36
+ "@lmzhen/dsh-evolution-io": "^0.32.6",
37
+ "@lmzhen/dsh-evolution-state": "^0.32.6"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@deepseek-ai/dsh-llm": "^0.2.1-rc.2",
41
41
  "@deepseek-ai/dsh-session": "^0.2.1-rc.2",
42
- "@lmzhen/dsh-evolution-core": "^0.32.4",
43
- "@lmzhen/dsh-evolution-io": "^0.32.4",
44
- "@lmzhen/dsh-evolution-state": "^0.32.4"
42
+ "@lmzhen/dsh-evolution-core": "^0.32.6",
43
+ "@lmzhen/dsh-evolution-io": "^0.32.6",
44
+ "@lmzhen/dsh-evolution-state": "^0.32.6"
45
45
  },
46
46
  "engines": {
47
47
  "dsh": ">=0.2.1-rc.2 <0.2.2-0"