@lmzhen/dsh-evolution-replay 0.18.0 → 0.18.1
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 +1 -1
- package/lib/index.js +26 -4
- package/lib/types/index.d.ts +20 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -13,6 +13,6 @@ replay`.
|
|
|
13
13
|
## Known limitations
|
|
14
14
|
|
|
15
15
|
- No known durable consumer gaps at this time. Runtime contracts are covered by package and boundary tests.
|
|
16
|
-
- **The activity-sidecar verdict is per read
|
|
16
|
+
- **The activity-sidecar verdict is per read, and an unanswered read is its own state.** When `apply()` meets bytes this build cannot read as the current format, every `compare()` result carries `sourceCorrupt: true` and its report states the leaderboard is NOT the recorded history (an empty list does not mean nothing happened); a later successful read clears the qualification (a repaired sidecar plus an io reload (HMR / plugin restart)), while the corruption stays observable through the one warn `apply()` emits at mark time. A read that **THREW** (the io failed, or no state could be produced at all) is neither verdict: `compare()` then carries `sourceReadFailure: <message>` and its report says the read FAILED — never "nothing was recorded". Any ANSWERED read (clean or corrupt) retires that failure, so both qualifications describe the current read rather than latching.
|
|
17
17
|
|
|
18
18
|
**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).
|
package/lib/index.js
CHANGED
|
@@ -101,6 +101,12 @@ var EvolutionReplayDriver = class EvolutionReplayDriver {
|
|
|
101
101
|
* clears it on a later clean read, so the qualification reflects the present
|
|
102
102
|
* instead of latching for the driver lifetime. */
|
|
103
103
|
sourceCorrupt = false;
|
|
104
|
+
/** 0.18.1 (S3): the backfill READ itself failed — held as its message. A
|
|
105
|
+
* thrown read used to skip both markers, so `sourceCorrupt` kept whatever
|
|
106
|
+
* the previous read said and a failed read presented as a clean one. Cleared
|
|
107
|
+
* by any ANSWERED read; never sets `sourceCorrupt` (a failed read is not
|
|
108
|
+
* evidence that the bytes are corrupt). */
|
|
109
|
+
sourceReadFailure = null;
|
|
104
110
|
/** V26-05 (v25): plan ids recorded live BEFORE the backfill settled. A
|
|
105
111
|
* plan-applied landing inside the one-shot `loadActivityState` read window is
|
|
106
112
|
* recorded live AND persisted into the sidecar the backfill is reading —
|
|
@@ -203,6 +209,7 @@ var EvolutionReplayDriver = class EvolutionReplayDriver {
|
|
|
203
209
|
*/
|
|
204
210
|
markSourceUnreadable() {
|
|
205
211
|
this.sourceCorrupt = true;
|
|
212
|
+
this.sourceReadFailure = null;
|
|
206
213
|
}
|
|
207
214
|
/**
|
|
208
215
|
* PLAN S5.1 (2026-09-16, audit P2-18): the counterpart clear — `apply()` calls
|
|
@@ -218,17 +225,30 @@ var EvolutionReplayDriver = class EvolutionReplayDriver {
|
|
|
218
225
|
*/
|
|
219
226
|
markSourceReadable() {
|
|
220
227
|
this.sourceCorrupt = false;
|
|
228
|
+
this.sourceReadFailure = null;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* 0.18.1 (S3): the backfill read THREW (io error, or a state the reader could
|
|
232
|
+
* not produce at all). Neither verdict applies — the bytes were never judged.
|
|
233
|
+
* Before this the throw skipped both markers and `compare()` returned an
|
|
234
|
+
* unqualified leaderboard, presenting a failed read as an answered one.
|
|
235
|
+
* @param reason - the failure's message, as thrown.
|
|
236
|
+
*/
|
|
237
|
+
markSourceReadFailed(reason) {
|
|
238
|
+
this.sourceReadFailure = reason;
|
|
221
239
|
}
|
|
222
240
|
compare(weights = this.weights) {
|
|
223
241
|
const result = comparePlans([...this.plans], clampReplayWeights(weights, this.weights));
|
|
224
|
-
|
|
242
|
+
const failure = this.sourceReadFailure === null ? "" : `The activity sidecar read FAILED (${this.sourceReadFailure}) — this leaderboard carries no history from the sidecar, and a failed read is NOT "nothing was recorded".\n`;
|
|
243
|
+
if (!this.sourceCorrupt && this.sourceReadFailure === null) return {
|
|
225
244
|
...result,
|
|
226
245
|
sourceCorrupt: false
|
|
227
246
|
};
|
|
228
247
|
return {
|
|
229
248
|
...result,
|
|
230
|
-
sourceCorrupt:
|
|
231
|
-
|
|
249
|
+
sourceCorrupt: this.sourceCorrupt,
|
|
250
|
+
...this.sourceReadFailure === null ? {} : { sourceReadFailure: this.sourceReadFailure },
|
|
251
|
+
report: failure + (this.sourceCorrupt ? "The activity sidecar could not be read as an activity envelope (unparsable bytes, or no items array) — this leaderboard is NOT the recorded history, and an empty list does not mean nothing happened.\n" : "") + result.report
|
|
232
252
|
};
|
|
233
253
|
}
|
|
234
254
|
};
|
|
@@ -254,7 +274,9 @@ function apply(ctx, rawConfig = {}) {
|
|
|
254
274
|
}
|
|
255
275
|
driver.backfill(loaded.records);
|
|
256
276
|
}).catch((error) => {
|
|
257
|
-
|
|
277
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
278
|
+
driver.markSourceReadFailed(reason);
|
|
279
|
+
ioCtx.logger.warn(`evolution-replay: activity sidecar backfill skipped (${reason}) — this leaderboard carries no history from the sidecar, and a failed read is not "nothing was recorded"`);
|
|
258
280
|
});
|
|
259
281
|
});
|
|
260
282
|
}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -51,6 +51,12 @@ export interface ReplayResult {
|
|
|
51
51
|
* was repaired and an io reload re-read it) clears the qualification —
|
|
52
52
|
* it never outlives the condition it describes. */
|
|
53
53
|
sourceCorrupt?: boolean | undefined;
|
|
54
|
+
/** 0.18.1 (S3): the most recent backfill READ threw (io error, or a state the
|
|
55
|
+
* reader could not produce at all) — no verdict was reached, which is a
|
|
56
|
+
* different fact from `sourceCorrupt` (the bytes WERE read and are not an
|
|
57
|
+
* activity envelope). Carries the failure's message; a later ANSWERED read
|
|
58
|
+
* clears it (see {@link EvolutionReplayDriver.markSourceReadFailed}). */
|
|
59
|
+
sourceReadFailure?: string | undefined;
|
|
54
60
|
}
|
|
55
61
|
export interface ReplayWeights {
|
|
56
62
|
accepted: number;
|
|
@@ -90,6 +96,12 @@ export declare class EvolutionReplayDriver {
|
|
|
90
96
|
* clears it on a later clean read, so the qualification reflects the present
|
|
91
97
|
* instead of latching for the driver lifetime. */
|
|
92
98
|
private sourceCorrupt;
|
|
99
|
+
/** 0.18.1 (S3): the backfill READ itself failed — held as its message. A
|
|
100
|
+
* thrown read used to skip both markers, so `sourceCorrupt` kept whatever
|
|
101
|
+
* the previous read said and a failed read presented as a clean one. Cleared
|
|
102
|
+
* by any ANSWERED read; never sets `sourceCorrupt` (a failed read is not
|
|
103
|
+
* evidence that the bytes are corrupt). */
|
|
104
|
+
private sourceReadFailure;
|
|
93
105
|
/** V26-05 (v25): plan ids recorded live BEFORE the backfill settled. A
|
|
94
106
|
* plan-applied landing inside the one-shot `loadActivityState` read window is
|
|
95
107
|
* recorded live AND persisted into the sidecar the backfill is reading —
|
|
@@ -155,6 +167,14 @@ export declare class EvolutionReplayDriver {
|
|
|
155
167
|
* `apply()` emits at mark time.
|
|
156
168
|
*/
|
|
157
169
|
markSourceReadable(): void;
|
|
170
|
+
/**
|
|
171
|
+
* 0.18.1 (S3): the backfill read THREW (io error, or a state the reader could
|
|
172
|
+
* not produce at all). Neither verdict applies — the bytes were never judged.
|
|
173
|
+
* Before this the throw skipped both markers and `compare()` returned an
|
|
174
|
+
* unqualified leaderboard, presenting a failed read as an answered one.
|
|
175
|
+
* @param reason - the failure's message, as thrown.
|
|
176
|
+
*/
|
|
177
|
+
markSourceReadFailed(reason: string): void;
|
|
158
178
|
compare(weights?: ReplayWeights): ReplayResult;
|
|
159
179
|
}
|
|
160
180
|
export declare const name = "evolution-replay";
|
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.18.
|
|
4
|
+
"version": "0.18.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@deepseek-ai/schemastery": "^3.18.4",
|
|
30
|
-
"@lmzhen/dsh-evolution-activity": "^0.18.
|
|
31
|
-
"@lmzhen/dsh-evolution-core": "^0.18.
|
|
30
|
+
"@lmzhen/dsh-evolution-activity": "^0.18.1",
|
|
31
|
+
"@lmzhen/dsh-evolution-core": "^0.18.1"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@deepseek-ai/cordis": "^4.0.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@lmzhen/dsh-evolution-activity": "^0.18.
|
|
38
|
-
"@lmzhen/dsh-evolution-core": "^0.18.
|
|
37
|
+
"@lmzhen/dsh-evolution-activity": "^0.18.1",
|
|
38
|
+
"@lmzhen/dsh-evolution-core": "^0.18.1"
|
|
39
39
|
}
|
|
40
40
|
}
|