@lmzhen/dsh-evolution-feedback 0.3.73 → 0.3.76
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 +2 -0
- package/lib/index.js +54 -22
- package/package.json +7 -13
- package/lib/invariant.js +0 -8
- package/lib/types/invariant.d.ts +0 -5
package/README.md
CHANGED
|
@@ -23,3 +23,5 @@ Independent of request-prefix construction. This package does not alter the asse
|
|
|
23
23
|
|
|
24
24
|
- Persists through the IO seam; quality propagation into skill usage requires the `skillUsage` service.
|
|
25
25
|
- P1-1 (v15): feedback writes the FEEDBACK-OWNED `feedback_score`/`feedback_warn` usage fields. The lifecycle engine and the scope view read the union `quality_warn || feedback_warn`, so a negative feedback shortens the stale window even though the curator's six-factor run always recomputes `quality_warn` itself.
|
|
26
|
+
|
|
27
|
+
**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
|
@@ -97,7 +97,9 @@ var EvolutionFeedback = class EvolutionFeedback {
|
|
|
97
97
|
await migrateFeedbackEvents(io, eventsPath, aggregate, this.warn);
|
|
98
98
|
} catch {}
|
|
99
99
|
}
|
|
100
|
-
const
|
|
100
|
+
const initial = await readEvolutionTimeline(io, eventsPath, archiveNames);
|
|
101
|
+
const lateArchives = (await listEventArchives(io, eventsPath)).filter((name) => !archiveNames.includes(name));
|
|
102
|
+
const events = lateArchives.length === 0 ? initial.events : (await readEvolutionTimeline(io, eventsPath, [...archiveNames, ...lateArchives])).events;
|
|
101
103
|
const cache = parseCache(rawCache, this.warn);
|
|
102
104
|
const maxSeq = events.reduce((max, event) => Math.max(max, event.seq), 0);
|
|
103
105
|
const floor = events[0]?.seq ?? 0;
|
|
@@ -256,10 +258,19 @@ var EvolutionFeedback = class EvolutionFeedback {
|
|
|
256
258
|
const { events } = await readEvolutionTimeline(recordIo, eventsPath);
|
|
257
259
|
const maxSeq = events.reduce((max, event) => Math.max(max, event.seq), 0);
|
|
258
260
|
if (maxSeq === 0) return;
|
|
261
|
+
let rawCache;
|
|
262
|
+
try {
|
|
263
|
+
rawCache = await recordIo.readText(path);
|
|
264
|
+
} catch {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const cache = parseCache(rawCache, this.warn);
|
|
268
|
+
const floor = events[0]?.seq ?? 0;
|
|
269
|
+
const state = cache && cache.lastSeq >= floor - 1 ? foldWithDelta(cache, events, this.warn) : foldFeedbackState(events, this.warn);
|
|
259
270
|
const body = JSON.stringify({
|
|
260
271
|
version: CACHE_VERSION,
|
|
261
272
|
lastSeq: maxSeq,
|
|
262
|
-
...
|
|
273
|
+
...state
|
|
263
274
|
}, null, 2);
|
|
264
275
|
await recordIo.writeText(path, body);
|
|
265
276
|
} catch {}
|
|
@@ -272,27 +283,44 @@ var EvolutionFeedback = class EvolutionFeedback {
|
|
|
272
283
|
});
|
|
273
284
|
}
|
|
274
285
|
};
|
|
275
|
-
/**
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
286
|
+
/** Semantic identity of one event: `seq` and `at` are excluded (a merge
|
|
287
|
+
* shifts seqs, a re-synthesis stamps a different `at`), so type/kind/target/
|
|
288
|
+
* rating/note is everything a fold can see. */
|
|
289
|
+
function sameSemantics(a, b) {
|
|
290
|
+
return a.type === b.type && a.kind === b.kind && a.target === b.target && a.rating === b.rating && a.note === b.note;
|
|
291
|
+
}
|
|
292
|
+
/** True when `existing` already carries the WHOLE legacy batch (the skip case).
|
|
293
|
+
* P1-8 (v37): counted as a MULTISET, never as a contiguous run — the
|
|
294
|
+
* synthesizer emits "all positives, then all negatives" per target while the
|
|
295
|
+
* real log is in temporal order, so the run-based gate read an already-migrated
|
|
296
|
+
* log as unmigrated and re-appended the whole history (3 events became 6, and
|
|
297
|
+
* every further boot doubled it again). */
|
|
298
|
+
function containsLegacyMultiset(existing, expected) {
|
|
282
299
|
if (expected.length === 0) return true;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
300
|
+
const pool = [...existing];
|
|
301
|
+
for (const event of expected) {
|
|
302
|
+
const at = pool.findIndex((candidate) => sameSemantics(candidate, event));
|
|
303
|
+
if (at < 0) return false;
|
|
304
|
+
pool.splice(at, 1);
|
|
305
|
+
}
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
/** True when the body the migration transact just read may be written over:
|
|
309
|
+
* absent or blank (the append path's own "missing" definition), or a v1 body
|
|
310
|
+
* this reader can actually interpret. `parseEvolutionEvents` maps a corrupt or
|
|
311
|
+
* future-version body to an EMPTY timeline, so without this gate a read failure
|
|
312
|
+
* would be folded as "nothing was ever migrated" and the synthesized log would
|
|
313
|
+
* overwrite bytes the append path refuses to touch. */
|
|
314
|
+
function isReadableEventBody(current) {
|
|
315
|
+
if (current === null || current.trim() === "") return true;
|
|
316
|
+
try {
|
|
317
|
+
const parsed = JSON.parse(current);
|
|
318
|
+
if (!isRecord(parsed)) return false;
|
|
319
|
+
if (parsed.version !== void 0 && parsed.version !== EVENT_LOG_VERSION) return false;
|
|
320
|
+
return Array.isArray(parsed.events);
|
|
321
|
+
} catch {
|
|
322
|
+
return false;
|
|
294
323
|
}
|
|
295
|
-
return false;
|
|
296
324
|
}
|
|
297
325
|
/**
|
|
298
326
|
* Merge a legacy aggregate into the event log (rc.69): the expected synthetic
|
|
@@ -311,8 +339,12 @@ async function migrateFeedbackEvents(io, eventsPath, aggregate, warn = () => {})
|
|
|
311
339
|
return;
|
|
312
340
|
}
|
|
313
341
|
await transactIo(io, eventsPath, (current) => {
|
|
342
|
+
if (!isReadableEventBody(current)) {
|
|
343
|
+
warn("evolution-feedback: migration left unreadable event-log bytes untouched (neither migrated nor overwritten)");
|
|
344
|
+
return Promise.resolve(current);
|
|
345
|
+
}
|
|
314
346
|
const existing = parseEvolutionEvents(current);
|
|
315
|
-
if (
|
|
347
|
+
if (containsLegacyMultiset(existing, expected)) return Promise.resolve(current);
|
|
316
348
|
const maxSeq = existing.reduce((max, event) => Math.max(max, event.seq), 0);
|
|
317
349
|
const merged = [...existing, ...expected.map((event, index) => ({
|
|
318
350
|
...event,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-feedback",
|
|
3
3
|
"description": "Feedback-to-quality scoring for self-evolution (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.76",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -18,10 +18,6 @@
|
|
|
18
18
|
"types": "./lib/types/index.d.ts",
|
|
19
19
|
"default": "./lib/index.js"
|
|
20
20
|
},
|
|
21
|
-
"./invariant": {
|
|
22
|
-
"types": "./lib/types/invariant.d.ts",
|
|
23
|
-
"default": "./lib/invariant.js"
|
|
24
|
-
},
|
|
25
21
|
"./package.json": "./package.json"
|
|
26
22
|
},
|
|
27
23
|
"files": [
|
|
@@ -31,18 +27,16 @@
|
|
|
31
27
|
"license": "MIT",
|
|
32
28
|
"dependencies": {
|
|
33
29
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
34
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
30
|
+
"@lmzhen/dsh-evolution-core": "^0.3.76"
|
|
35
31
|
},
|
|
36
32
|
"peerDependencies": {
|
|
37
|
-
"@deepseek-ai/dsh-invariants": "^0.1.5-rc.2",
|
|
38
33
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
39
|
-
"@lmzhen/dsh-evolution-io": "^0.3.
|
|
40
|
-
"@lmzhen/dsh-skill-usage": "^0.3.
|
|
34
|
+
"@lmzhen/dsh-evolution-io": "^0.3.76",
|
|
35
|
+
"@lmzhen/dsh-skill-usage": "^0.3.76"
|
|
41
36
|
},
|
|
42
37
|
"devDependencies": {
|
|
43
|
-
"@
|
|
44
|
-
"@lmzhen/dsh-evolution-io": "^0.3.
|
|
45
|
-
"@lmzhen/dsh-
|
|
46
|
-
"@lmzhen/dsh-skill-usage": "^0.3.73"
|
|
38
|
+
"@lmzhen/dsh-evolution-io": "^0.3.76",
|
|
39
|
+
"@lmzhen/dsh-evolution-io-node": "^0.3.76",
|
|
40
|
+
"@lmzhen/dsh-skill-usage": "^0.3.76"
|
|
47
41
|
}
|
|
48
42
|
}
|
package/lib/invariant.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
//#region lib/types/invariant.js
|
|
2
|
-
const PACKAGE_NAME = "@lmzhen/dsh-evolution-feedback";
|
|
3
|
-
const name = "evolution-feedback-invariant";
|
|
4
|
-
const inject = ["invariants"];
|
|
5
|
-
const install = () => {};
|
|
6
|
-
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
7
|
-
//#endregion
|
|
8
|
-
export { apply, inject, name };
|
package/lib/types/invariant.d.ts
DELETED