@lmzhen/dsh-evolution-curator 0.3.68 → 0.3.70
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 +41 -11
- package/lib/types/index.d.ts +3 -1
- package/package.json +13 -11
package/lib/index.js
CHANGED
|
@@ -408,7 +408,9 @@ var EvolutionCurator = class extends Service {
|
|
|
408
408
|
* mover refuses a directory whose writer lock is alive), so a collision
|
|
409
409
|
* degrades to a recorded failed op + snapshot rollback, never a torn
|
|
410
410
|
* write. Automatic passes are kept out of the session-active window by the
|
|
411
|
-
* min-idle gate
|
|
411
|
+
* min-idle gate — checked pre-run AND re-checked at the commit boundary
|
|
412
|
+
* (v28 G4.2: a session activating mid-run no longer slips past it); a
|
|
413
|
+
* manual run (`ignoreGates`) bypasses both checks and is
|
|
412
414
|
* the one realistic interleave window — documented, accepted (plan v20
|
|
413
415
|
* C-3①). The same statement lives on evolution-review's `reviewInFlight`.
|
|
414
416
|
*/
|
|
@@ -496,14 +498,13 @@ var EvolutionCurator = class extends Service {
|
|
|
496
498
|
skipped: "disposed"
|
|
497
499
|
};
|
|
498
500
|
}
|
|
499
|
-
const snapshotPath = dryRun ? void 0 : await this.snapshotFull("pre-curator-run");
|
|
500
501
|
const suppressedNames = new Set(await loadSuppressedNames(root, this.io));
|
|
501
502
|
const gates = new EvolutionGateSet({
|
|
502
503
|
exclude: this.excludeSkillNames,
|
|
503
504
|
referenced: this.referencedSkillNames,
|
|
504
505
|
suppressed: suppressedNames
|
|
505
506
|
});
|
|
506
|
-
const { bundledNames, treeNames } = await this.seedBaseline(usage);
|
|
507
|
+
const { bundledNames, treeNames, resetToActive } = await this.seedBaseline(usage);
|
|
507
508
|
const contents = /* @__PURE__ */ new Map();
|
|
508
509
|
for (const name of treeNames) {
|
|
509
510
|
const text = await this.skills.read(name);
|
|
@@ -536,6 +537,23 @@ var EvolutionCurator = class extends Service {
|
|
|
536
537
|
};
|
|
537
538
|
const llmNominations = gatedNominations.prunings;
|
|
538
539
|
const archiveCandidates = [...new Set([...result.archive, ...llmNominations])];
|
|
540
|
+
if (!ignoreGates && this.minIdleHours > 0 && this.recentSessionActive()) {
|
|
541
|
+
if (!dryRun) try {
|
|
542
|
+
await mutateUsage(root, this.io, (map) => {
|
|
543
|
+
for (const [name, record] of usage) if (!map.has(name)) map.set(name, { ...record });
|
|
544
|
+
});
|
|
545
|
+
} catch (error) {
|
|
546
|
+
this.ctx.logger.warn(`evolution-curator: failed to persist the seeded usage baseline on a session-blocked run (${error instanceof Error ? error.message : String(error)})`);
|
|
547
|
+
}
|
|
548
|
+
return {
|
|
549
|
+
stale: [],
|
|
550
|
+
archived: [],
|
|
551
|
+
errors: [],
|
|
552
|
+
report: this.skippedReport(runId, startedAt),
|
|
553
|
+
skipped: "active-session"
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
const snapshotPath = dryRun ? void 0 : await this.snapshotFull("pre-curator-run");
|
|
539
557
|
const { archivedSkills, errors, consolidated } = await this.applyMutations({
|
|
540
558
|
dryRun,
|
|
541
559
|
archiveCandidates,
|
|
@@ -546,11 +564,16 @@ var EvolutionCurator = class extends Service {
|
|
|
546
564
|
suppressedNames,
|
|
547
565
|
root,
|
|
548
566
|
recommendPool: new Set(recommendPool),
|
|
549
|
-
stateOwned: new Set([
|
|
567
|
+
stateOwned: new Set([
|
|
568
|
+
...result.transitions.map((t) => t.name),
|
|
569
|
+
...archiveCandidates,
|
|
570
|
+
...resetToActive
|
|
571
|
+
]),
|
|
550
572
|
runStartStates,
|
|
551
573
|
failedFrom: new Map(result.transitions.filter((t) => t.to === "archived").map((t) => [t.name, t.from]))
|
|
552
574
|
});
|
|
553
|
-
|
|
575
|
+
const runAborted = errors.some((error) => error.startsWith("run aborted"));
|
|
576
|
+
if (!dryRun && !runAborted) this.lastRun = Date.now();
|
|
554
577
|
const report = buildCuratorRunReport({
|
|
555
578
|
runId,
|
|
556
579
|
startedAt,
|
|
@@ -594,8 +617,8 @@ var EvolutionCurator = class extends Service {
|
|
|
594
617
|
const pausedNow = current?.paused ?? false;
|
|
595
618
|
return {
|
|
596
619
|
schemaVersion: 1,
|
|
597
|
-
lastRunAt: dryRun ? persisted?.lastRunAt ?? this.lastRun : Date.now(),
|
|
598
|
-
runCount: dryRun ? persisted?.runCount ?? 0 : (current?.runCount ?? 0) + 1,
|
|
620
|
+
lastRunAt: dryRun || runAborted ? persisted?.lastRunAt ?? this.lastRun : Date.now(),
|
|
621
|
+
runCount: dryRun || runAborted ? persisted?.runCount ?? 0 : (current?.runCount ?? 0) + 1,
|
|
599
622
|
lastSummary: summary,
|
|
600
623
|
paused: pausedNow
|
|
601
624
|
};
|
|
@@ -620,16 +643,23 @@ var EvolutionCurator = class extends Service {
|
|
|
620
643
|
async seedBaseline(usage) {
|
|
621
644
|
const bundledNames = /* @__PURE__ */ new Set();
|
|
622
645
|
const treeNames = /* @__PURE__ */ new Set();
|
|
646
|
+
const resetToActive = /* @__PURE__ */ new Set();
|
|
623
647
|
for (const summary of await this.skills.list()) {
|
|
624
648
|
treeNames.add(summary.name);
|
|
625
649
|
if (!usage.has(summary.name)) usage.set(summary.name, emptyRecord());
|
|
626
650
|
if (await this.skills.isBundled(summary.name)) bundledNames.add(summary.name);
|
|
627
651
|
const record = usage.get(summary.name);
|
|
652
|
+
if (record?.state === "archived") {
|
|
653
|
+
record.state = "active";
|
|
654
|
+
record.archived_at = null;
|
|
655
|
+
resetToActive.add(summary.name);
|
|
656
|
+
}
|
|
628
657
|
if (record) record.pinned = await this.skills.isPinned(summary.name);
|
|
629
658
|
}
|
|
630
659
|
return {
|
|
631
660
|
bundledNames,
|
|
632
|
-
treeNames
|
|
661
|
+
treeNames,
|
|
662
|
+
resetToActive
|
|
633
663
|
};
|
|
634
664
|
}
|
|
635
665
|
/**
|
|
@@ -707,6 +737,7 @@ var EvolutionCurator = class extends Service {
|
|
|
707
737
|
record.state = "archived";
|
|
708
738
|
record.archived_at = record.archived_at ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
709
739
|
stateOwned.add(name);
|
|
740
|
+
this.ctx.logger.warn(`evolution-curator: skill "${name}" left the tree without an archive move - its usage record was folded to archived; if the directory is still on disk, repair or remove it manually (it will not re-enter the lifecycle while the record is archived)`);
|
|
710
741
|
}
|
|
711
742
|
let wasBundled = false;
|
|
712
743
|
try {
|
|
@@ -801,8 +832,7 @@ var EvolutionCurator = class extends Service {
|
|
|
801
832
|
});
|
|
802
833
|
archivedSkills.push({
|
|
803
834
|
name: nomination.from,
|
|
804
|
-
|
|
805
|
-
reason: `Consolidated into ${nomination.into}`
|
|
835
|
+
reason: `Consolidated into ${nomination.into} (exact archive path: the evolution/skill-mutated event, archivedPath)`
|
|
806
836
|
});
|
|
807
837
|
}
|
|
808
838
|
if (suppressedChanged) try {
|
|
@@ -835,7 +865,7 @@ var EvolutionCurator = class extends Service {
|
|
|
835
865
|
if (!agents) return !this.minIdleFailOpen;
|
|
836
866
|
let latest = 0;
|
|
837
867
|
for (const agent of agents.list()) {
|
|
838
|
-
const events = agent.session.
|
|
868
|
+
const events = agent.session.snapshotEvents();
|
|
839
869
|
const last = events.length === 0 ? 0 : events[events.length - 1]?.time ?? 0;
|
|
840
870
|
latest = Math.max(latest, last);
|
|
841
871
|
}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -222,7 +222,9 @@ export declare class EvolutionCurator extends Service {
|
|
|
222
222
|
* mover refuses a directory whose writer lock is alive), so a collision
|
|
223
223
|
* degrades to a recorded failed op + snapshot rollback, never a torn
|
|
224
224
|
* write. Automatic passes are kept out of the session-active window by the
|
|
225
|
-
* min-idle gate
|
|
225
|
+
* min-idle gate — checked pre-run AND re-checked at the commit boundary
|
|
226
|
+
* (v28 G4.2: a session activating mid-run no longer slips past it); a
|
|
227
|
+
* manual run (`ignoreGates`) bypasses both checks and is
|
|
226
228
|
* the one realistic interleave window — documented, accepted (plan v20
|
|
227
229
|
* C-3①). The same statement lives on evolution-review's `reviewInFlight`.
|
|
228
230
|
*/
|
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.3.
|
|
4
|
+
"version": "0.3.70",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,20 +31,22 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
34
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
34
|
+
"@lmzhen/dsh-evolution-core": "^0.3.70"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
38
|
-
"@deepseek-ai/dsh-invariants": "^0.1.
|
|
39
|
-
"@deepseek-ai/dsh-llm": "^0.1.
|
|
40
|
-
"@
|
|
41
|
-
"@lmzhen/dsh-evolution-
|
|
38
|
+
"@deepseek-ai/dsh-invariants": "^0.1.5-rc.2",
|
|
39
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-rc.2",
|
|
40
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.2",
|
|
41
|
+
"@lmzhen/dsh-evolution-io": "^0.3.70",
|
|
42
|
+
"@lmzhen/dsh-evolution-state": "^0.3.70"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
|
-
"@deepseek-ai/dsh-invariants": "^0.1.
|
|
45
|
-
"@deepseek-ai/dsh-llm": "^0.1.
|
|
46
|
-
"@
|
|
47
|
-
"@lmzhen/dsh-evolution-
|
|
48
|
-
"@lmzhen/dsh-evolution-
|
|
45
|
+
"@deepseek-ai/dsh-invariants": "^0.1.5-rc.2",
|
|
46
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-rc.2",
|
|
47
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.2",
|
|
48
|
+
"@lmzhen/dsh-evolution-core": "^0.3.70",
|
|
49
|
+
"@lmzhen/dsh-evolution-io": "^0.3.70",
|
|
50
|
+
"@lmzhen/dsh-evolution-state": "^0.3.70"
|
|
49
51
|
}
|
|
50
52
|
}
|