@lmzhen/dsh-evolution-replay 0.3.65 → 0.3.67
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 +45 -4
- package/lib/types/index.d.ts +27 -3
- package/package.json +5 -3
package/lib/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import z from "@deepseek-ai/schemastery";
|
|
2
|
-
import { clampedNumber } from "@lmzhen/dsh-evolution-core";
|
|
2
|
+
import { clampedNumber, evolutionHome, evolutionIoAdapter } from "@lmzhen/dsh-evolution-core";
|
|
3
|
+
import { loadActivity } from "@lmzhen/dsh-evolution-activity";
|
|
3
4
|
//#region lib/types/index.js
|
|
4
5
|
/**
|
|
5
6
|
* Replay/A-B evaluation for evolution plans.
|
|
@@ -8,9 +9,16 @@ import { clampedNumber } from "@lmzhen/dsh-evolution-core";
|
|
|
8
9
|
* driver records every `evolution/plan-applied` process event (payload v2,
|
|
9
10
|
* with sessionId) into an in-memory leaderboard and exposes `/evolution
|
|
10
11
|
* replay` (via the `/evolution` command family) for comparison, so a human can
|
|
11
|
-
* A/B review policy/prompt changes against real plan outcomes.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* A/B review policy/prompt changes against real plan outcomes.
|
|
13
|
+
*
|
|
14
|
+
* V24-13 (v24): the in-memory leaderboard is BACKFILLED at mount from the
|
|
15
|
+
* `evolution-activity` sidecar (`$DSH_HOME/evolution/activity.json`) — the
|
|
16
|
+
* header previously claimed "durability across restarts is the
|
|
17
|
+
* evolution-activity store's job" while nothing ever read the sidecar, so a
|
|
18
|
+
* restart emptied `/evolution replay` and the persisted history sat unread.
|
|
19
|
+
* Records are fed in sidecar order (oldest first); the driver's `maxPlans`
|
|
20
|
+
* window keeps the newest. Best-effort: a missing/unreadable sidecar starts
|
|
21
|
+
* the leaderboard empty, exactly as before.
|
|
14
22
|
* @module @lmzhen/dsh-evolution-replay
|
|
15
23
|
*/
|
|
16
24
|
const DEFAULT_WEIGHTS = {
|
|
@@ -83,6 +91,13 @@ function comparePlans(plans, weights = DEFAULT_WEIGHTS) {
|
|
|
83
91
|
var EvolutionReplayDriver = class {
|
|
84
92
|
plans = [];
|
|
85
93
|
maxPlans;
|
|
94
|
+
/** V25-01 (v25): backfill-once latch — see {@link EvolutionReplayDriver.backfill}. */
|
|
95
|
+
backfilled = false;
|
|
96
|
+
/** V26-05 (v25): plan ids recorded live BEFORE the backfill settled. A
|
|
97
|
+
* plan-applied landing inside the one-shot `loadActivity` read window is
|
|
98
|
+
* recorded live AND persisted into the sidecar the backfill is reading —
|
|
99
|
+
* `backfill()` drops those ids so the event is not counted twice. */
|
|
100
|
+
preBackfillIds = /* @__PURE__ */ new Set();
|
|
86
101
|
weights;
|
|
87
102
|
constructor(config = {}, warn = () => {}) {
|
|
88
103
|
const maxPlans = clampedNumber(config.maxPlans ?? 50, 50, { min: 1 });
|
|
@@ -96,6 +111,7 @@ var EvolutionReplayDriver = class {
|
|
|
96
111
|
}
|
|
97
112
|
}
|
|
98
113
|
record(plan) {
|
|
114
|
+
if (!this.backfilled) this.preBackfillIds.add(plan.planId);
|
|
99
115
|
const count = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
100
116
|
const countOr = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : fallback;
|
|
101
117
|
const memoryApplied = count(plan.memoryApplied);
|
|
@@ -114,6 +130,22 @@ var EvolutionReplayDriver = class {
|
|
|
114
130
|
if (this.plans.length > this.maxPlans) this.plans.shift();
|
|
115
131
|
}
|
|
116
132
|
/**
|
|
133
|
+
* V25-01 (v25): backfill the leaderboard from the activity sidecar, ONCE
|
|
134
|
+
* per driver instance. The inject callback that loads the sidecar re-runs
|
|
135
|
+
* whenever the `evolutionIo` dependency is replaced (cordis derived-fiber
|
|
136
|
+
* reload — plugin restart / HMR) while THIS driver survives at the apply
|
|
137
|
+
* scope, so the dedupe guard must live here, not in the callback: without
|
|
138
|
+
* it, every io reload doubled the leaderboard entries.
|
|
139
|
+
* @param items - activity records in sidecar order (oldest first).
|
|
140
|
+
*/
|
|
141
|
+
backfill(items) {
|
|
142
|
+
if (this.backfilled) return;
|
|
143
|
+
this.backfilled = true;
|
|
144
|
+
const fresh = items.filter((item) => !this.preBackfillIds.has(item.planId));
|
|
145
|
+
this.preBackfillIds.clear();
|
|
146
|
+
for (const item of fresh) this.record(item);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
117
149
|
* F-11: test-support API — no production consumer reads the raw
|
|
118
150
|
* plan list (the leaderboard path goes through `compare()`); tests use this
|
|
119
151
|
* as a read/inspection window. Kept by declaration (same posture as the
|
|
@@ -137,6 +169,15 @@ function apply(ctx, rawConfig = {}) {
|
|
|
137
169
|
ctx.on("evolution/plan-applied", (event) => {
|
|
138
170
|
driver.record(event);
|
|
139
171
|
});
|
|
172
|
+
ctx.inject(["evolutionIo"], (ioCtx) => {
|
|
173
|
+
const ioRegistry = ioCtx.evolutionIo;
|
|
174
|
+
const io = evolutionIoAdapter(() => ioRegistry.provider());
|
|
175
|
+
loadActivity(evolutionHome(), io).then((items) => {
|
|
176
|
+
driver.backfill(items);
|
|
177
|
+
}).catch((error) => {
|
|
178
|
+
ioCtx.logger.warn(`evolution-replay: activity sidecar backfill skipped (${error instanceof Error ? error.message : String(error)})`);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
140
181
|
}
|
|
141
182
|
//#endregion
|
|
142
183
|
export { Config, DEFAULT_WEIGHTS, EvolutionReplayDriver, apply, clampReplayWeights, comparePlans, name };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -5,9 +5,16 @@
|
|
|
5
5
|
* driver records every `evolution/plan-applied` process event (payload v2,
|
|
6
6
|
* with sessionId) into an in-memory leaderboard and exposes `/evolution
|
|
7
7
|
* replay` (via the `/evolution` command family) for comparison, so a human can
|
|
8
|
-
* A/B review policy/prompt changes against real plan outcomes.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* A/B review policy/prompt changes against real plan outcomes.
|
|
9
|
+
*
|
|
10
|
+
* V24-13 (v24): the in-memory leaderboard is BACKFILLED at mount from the
|
|
11
|
+
* `evolution-activity` sidecar (`$DSH_HOME/evolution/activity.json`) — the
|
|
12
|
+
* header previously claimed "durability across restarts is the
|
|
13
|
+
* evolution-activity store's job" while nothing ever read the sidecar, so a
|
|
14
|
+
* restart emptied `/evolution replay` and the persisted history sat unread.
|
|
15
|
+
* Records are fed in sidecar order (oldest first); the driver's `maxPlans`
|
|
16
|
+
* window keeps the newest. Best-effort: a missing/unreadable sidecar starts
|
|
17
|
+
* the leaderboard empty, exactly as before.
|
|
11
18
|
* @module @lmzhen/dsh-evolution-replay
|
|
12
19
|
*/
|
|
13
20
|
import type { Context } from '@deepseek-ai/cordis';
|
|
@@ -61,9 +68,26 @@ declare module '@deepseek-ai/cordis' {
|
|
|
61
68
|
export declare class EvolutionReplayDriver {
|
|
62
69
|
private readonly plans;
|
|
63
70
|
private readonly maxPlans;
|
|
71
|
+
/** V25-01 (v25): backfill-once latch — see {@link EvolutionReplayDriver.backfill}. */
|
|
72
|
+
private backfilled;
|
|
73
|
+
/** V26-05 (v25): plan ids recorded live BEFORE the backfill settled. A
|
|
74
|
+
* plan-applied landing inside the one-shot `loadActivity` read window is
|
|
75
|
+
* recorded live AND persisted into the sidecar the backfill is reading —
|
|
76
|
+
* `backfill()` drops those ids so the event is not counted twice. */
|
|
77
|
+
private readonly preBackfillIds;
|
|
64
78
|
private readonly weights;
|
|
65
79
|
constructor(config?: Config, warn?: (message: string) => void);
|
|
66
80
|
record(plan: EvolutionPlanAppliedEvent): void;
|
|
81
|
+
/**
|
|
82
|
+
* V25-01 (v25): backfill the leaderboard from the activity sidecar, ONCE
|
|
83
|
+
* per driver instance. The inject callback that loads the sidecar re-runs
|
|
84
|
+
* whenever the `evolutionIo` dependency is replaced (cordis derived-fiber
|
|
85
|
+
* reload — plugin restart / HMR) while THIS driver survives at the apply
|
|
86
|
+
* scope, so the dedupe guard must live here, not in the callback: without
|
|
87
|
+
* it, every io reload doubled the leaderboard entries.
|
|
88
|
+
* @param items - activity records in sidecar order (oldest first).
|
|
89
|
+
*/
|
|
90
|
+
backfill(items: ReadonlyArray<import('@lmzhen/dsh-evolution-activity').EvolutionActivityRecord>): void;
|
|
67
91
|
/**
|
|
68
92
|
* F-11: test-support API — no production consumer reads the raw
|
|
69
93
|
* plan list (the leaderboard path goes through `compare()`); tests use this
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-replay",
|
|
3
3
|
"description": "Replay/A-B evaluation primitives for evolution plans (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.67",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
34
|
-
"@lmzhen/dsh-evolution-
|
|
34
|
+
"@lmzhen/dsh-evolution-activity": "^0.3.67",
|
|
35
|
+
"@lmzhen/dsh-evolution-core": "^0.3.67"
|
|
35
36
|
},
|
|
36
37
|
"peerDependencies": {
|
|
37
38
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
42
|
-
"@lmzhen/dsh-evolution-
|
|
43
|
+
"@lmzhen/dsh-evolution-activity": "^0.3.67",
|
|
44
|
+
"@lmzhen/dsh-evolution-core": "^0.3.67"
|
|
43
45
|
}
|
|
44
46
|
}
|