@lmzhen/dsh-evolution-curator 0.31.1 → 0.32.0

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
@@ -1,5 +1,5 @@
1
1
  import { Service } from "@deepseek-ai/cordis";
2
- import { BASELINE_ACTION, 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";
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";
@@ -8,17 +8,8 @@ import z from "@deepseek-ai/schemastery";
8
8
  /**
9
9
  * G3a: the pure half of `undoUnit` — deciding WHAT to write back, with no io and no host.
10
10
  *
11
- * Kept apart from the curator so it can be tested in isolation (the curator module needs a cordis
12
- * host; this file needs nothing but the version records). The rules are the storage seat’s:
13
- *
14
- * - one path is described by the triple (baseline, oldest after, newest after): the bytes to write
15
- * back are the BASELINE this unit minted for that path, and only when there is no baseline do we
16
- * fall back to the OLDEST after’s `beforeHash`. Using the NEWEST one’s `beforeHash` would roll the
17
- * file back to a state from the middle of the unit — the half-split file this contract exists to
18
- * avoid;
19
- * - a path with no baseline at all did not exist before the unit ⇒ it is REMOVED, and the removal is
20
- * anchored on the newest after-entry’s hash so a hand edit refuses instead of being deleted;
21
- * - anything the plan cannot resolve is a refusal, and the caller writes nothing (pre-flight).
11
+ * The slot rules live in core (`planUnitUndoAcross`); this adapter keeps the curator’s
12
+ * single-skill call shape and splits the body op out of the support ops.
22
13
  */
23
14
  /** The newest unit the index carries, or undefined when no entry has a unit id yet. */
24
15
  function newestUnitId(versions) {
@@ -28,51 +19,26 @@ function newestUnitId(versions) {
28
19
  }
29
20
  }
30
21
  /**
31
- * Decide the whole unit rollback. Pure: the caller resolves the hashes to bytes afterwards.
32
- * @param members - the unit’s entries (any order from the index; oldest first is what it emits).
33
- * @param versions - the whole index, so `entryTarget` can classify an entry the way the faces do.
34
- * @returns the operations and the refusals.
22
+ * Decide the whole single-skill unit rollback.
23
+ * @param members - the unit’s entries for one skill, oldest first.
24
+ * @param _versions - the whole index; kept for parity with the previous signature.
25
+ * @returns the support ops, the body baseline, and the refusals.
35
26
  */
36
- function planUnitUndo(members, versions) {
37
- const slots = /* @__PURE__ */ new Map();
38
- const refusals = [];
39
- const body = {};
40
- for (const entry of members) {
41
- const path = entry.path;
42
- if (!(path !== void 0 && entryTarget(entry, versions) === "support")) {
43
- if (entry.action === BASELINE_ACTION) body.baseline ??= entry;
44
- else {
45
- body.oldest ??= entry;
46
- body.newest = entry;
47
- }
48
- continue;
49
- }
50
- const slot = slots.get(path) ?? {};
51
- slots.set(path, slot);
52
- if (entry.action === BASELINE_ACTION) slot.baseline ??= entry;
53
- else {
54
- slot.oldest ??= entry;
55
- slot.newest = entry;
56
- }
57
- }
58
- const ops = [];
59
- for (const [path, slot] of slots) {
60
- if (slot.newest === void 0) {
61
- refusals.push(`${path}(单元里没有该路径的 after 条目)`);
62
- continue;
63
- }
64
- const preUnitHash = slot.baseline !== void 0 ? slot.baseline.hash : slot.oldest?.beforeHash;
65
- ops.push({
66
- remove: preUnitHash === void 0,
67
- path,
68
- preUnitHash,
69
- expectedHash: slot.newest.hash
70
- });
71
- }
27
+ function planUnitUndo(members, _versions) {
28
+ const plan = planUnitUndoAcross([{
29
+ skill: "",
30
+ entries: members,
31
+ status: "live"
32
+ }]);
72
33
  return {
73
- ops,
74
- bodyPreUnitHash: body.baseline !== void 0 ? body.baseline.hash : body.oldest?.beforeHash,
75
- refusals
34
+ ops: plan.ops.filter((op) => op.path !== "").map((op) => ({
35
+ remove: op.remove,
36
+ path: op.path,
37
+ preUnitHash: op.preUnitHash,
38
+ expectedHash: op.expectedHash
39
+ })),
40
+ bodyPreUnitHash: plan.ops.find((op) => op.path === "")?.preUnitHash,
41
+ refusals: [...plan.refusals]
76
42
  };
77
43
  }
78
44
  //#endregion
@@ -1,20 +1,11 @@
1
1
  /**
2
2
  * G3a: the pure half of `undoUnit` — deciding WHAT to write back, with no io and no host.
3
3
  *
4
- * Kept apart from the curator so it can be tested in isolation (the curator module needs a cordis
5
- * host; this file needs nothing but the version records). The rules are the storage seat’s:
6
- *
7
- * - one path is described by the triple (baseline, oldest after, newest after): the bytes to write
8
- * back are the BASELINE this unit minted for that path, and only when there is no baseline do we
9
- * fall back to the OLDEST after’s `beforeHash`. Using the NEWEST one’s `beforeHash` would roll the
10
- * file back to a state from the middle of the unit — the half-split file this contract exists to
11
- * avoid;
12
- * - a path with no baseline at all did not exist before the unit ⇒ it is REMOVED, and the removal is
13
- * anchored on the newest after-entry’s hash so a hand edit refuses instead of being deleted;
14
- * - anything the plan cannot resolve is a refusal, and the caller writes nothing (pre-flight).
4
+ * The slot rules live in core (`planUnitUndoAcross`); this adapter keeps the curator’s
5
+ * single-skill call shape and splits the body op out of the support ops.
15
6
  */
16
7
  import { type SkillVersion } from '@lmzhen/dsh-evolution-core';
17
- /** One path’s action inside a unit undo. */
8
+ /** One support path’s action inside a unit undo. */
18
9
  export interface UnitUndoOp {
19
10
  /** True when the unit created the file (no pre-unit bytes) ⇒ remove it, anchored. */
20
11
  remove: boolean;
@@ -36,10 +27,10 @@ export interface UnitUndoPlan {
36
27
  /** The newest unit the index carries, or undefined when no entry has a unit id yet. */
37
28
  export declare function newestUnitId(versions: SkillVersion[]): string | undefined;
38
29
  /**
39
- * Decide the whole unit rollback. Pure: the caller resolves the hashes to bytes afterwards.
40
- * @param members - the unit’s entries (any order from the index; oldest first is what it emits).
41
- * @param versions - the whole index, so `entryTarget` can classify an entry the way the faces do.
42
- * @returns the operations and the refusals.
30
+ * Decide the whole single-skill unit rollback.
31
+ * @param members - the unit’s entries for one skill, oldest first.
32
+ * @param _versions - the whole index; kept for parity with the previous signature.
33
+ * @returns the support ops, the body baseline, and the refusals.
43
34
  */
44
- export declare function planUnitUndo(members: SkillVersion[], versions: SkillVersion[]): UnitUndoPlan;
35
+ export declare function planUnitUndo(members: SkillVersion[], _versions: SkillVersion[]): UnitUndoPlan;
45
36
  //# sourceMappingURL=unit-undo-plan.d.ts.map
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.31.1",
4
+ "version": "0.32.0",
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.31.1"
30
+ "@lmzhen/dsh-evolution-core": "^0.32.0"
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.31.1",
37
- "@lmzhen/dsh-evolution-state": "^0.31.1"
36
+ "@lmzhen/dsh-evolution-io": "^0.32.0",
37
+ "@lmzhen/dsh-evolution-state": "^0.32.0"
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.31.1",
43
- "@lmzhen/dsh-evolution-io": "^0.31.1",
44
- "@lmzhen/dsh-evolution-state": "^0.31.1"
42
+ "@lmzhen/dsh-evolution-core": "^0.32.0",
43
+ "@lmzhen/dsh-evolution-io": "^0.32.0",
44
+ "@lmzhen/dsh-evolution-state": "^0.32.0"
45
45
  },
46
46
  "engines": {
47
47
  "dsh": ">=0.2.1-rc.2 <0.2.2-0"