@lmzhen/dsh-evolution-feedback 0.1.0-rc.64 → 0.1.0-rc.66

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
@@ -281,8 +281,10 @@ var EvolutionFeedback = class {
281
281
  };
282
282
  chain = Promise.resolve();
283
283
  path;
284
+ io;
284
285
  constructor(io, home = process.env.DSH_HOME ?? join(homedir(), ".dsh"), pathOverride) {
285
286
  if (io) this.path = pathOverride ?? join(home, "evolution", "feedback.json");
287
+ this.io = io;
286
288
  }
287
289
  mutate(task) {
288
290
  const run = this.chain.then(task, task);
@@ -311,7 +313,8 @@ var EvolutionFeedback = class {
311
313
  });
312
314
  }
313
315
  record(target, rating, note, kind = "session", io) {
314
- const table = kind === "skill" ? this.state.skills : this.state.sessions;
316
+ const mode = kind === "skill" ? "skills" : "sessions";
317
+ const table = this.state[mode];
315
318
  const current = table[target] ?? {
316
319
  positive: 0,
317
320
  negative: 0
@@ -319,7 +322,31 @@ var EvolutionFeedback = class {
319
322
  current[rating] += 1;
320
323
  if (note !== void 0) current.lastNote = note;
321
324
  table[target] = current;
322
- if (io && this.path) this.flush(io);
325
+ const recordIo = io ?? this.io;
326
+ const path = this.path;
327
+ if (!recordIo || !path) return;
328
+ this.mutate(async () => {
329
+ try {
330
+ await transactIo(recordIo, path, (raw) => {
331
+ if (raw !== null) try {
332
+ JSON.parse(raw);
333
+ } catch {
334
+ return Promise.resolve(raw);
335
+ }
336
+ const diskState = parseState(raw);
337
+ const diskTable = diskState[mode];
338
+ const diskRec = diskTable[target] ?? {
339
+ positive: 0,
340
+ negative: 0
341
+ };
342
+ diskRec[rating] += 1;
343
+ if (note !== void 0) diskRec.lastNote = note;
344
+ diskTable[target] = diskRec;
345
+ this.state = diskState;
346
+ return Promise.resolve(JSON.stringify(diskState, null, 2));
347
+ });
348
+ } catch (error) {}
349
+ });
323
350
  }
324
351
  score(target, kind = "session") {
325
352
  const record = (kind === "skill" ? this.state.skills : this.state.sessions)[target];
@@ -334,16 +361,9 @@ var EvolutionFeedback = class {
334
361
  sessions: { ...this.state.sessions }
335
362
  };
336
363
  }
337
- async flush(io) {
338
- const path = this.path;
339
- if (!path || !io) return;
340
- await this.mutate(async () => {
341
- await transactIo(io, path, (current) => {
342
- const merged = mergeStates(parseState(current), this.state);
343
- this.state = merged;
344
- return Promise.resolve(JSON.stringify(merged, null, 2));
345
- });
346
- });
364
+ /** Await the pending record-task chain (unload safety; rc.66). */
365
+ waitIdle() {
366
+ return this.chain;
347
367
  }
348
368
  };
349
369
  /** Parse a raw feedback sidecar; malformed reads as empty (best-effort). */
@@ -365,19 +385,6 @@ function parseState(raw) {
365
385
  };
366
386
  }
367
387
  }
368
- /** Deep-merge two feedback states: union by target, in-memory values win on conflict. */
369
- function mergeStates(disk, memory) {
370
- return {
371
- skills: {
372
- ...disk.skills,
373
- ...memory.skills
374
- },
375
- sessions: {
376
- ...disk.sessions,
377
- ...memory.sessions
378
- }
379
- };
380
- }
381
388
  const name = "evolution-feedback";
382
389
  const Config = z.object({
383
390
  qualityWarnThreshold: z.number().default(-.25),
@@ -406,8 +413,8 @@ function apply(ctx, rawConfig = {}) {
406
413
  };
407
414
  }
408
415
  ctx.effect(() => () => {
409
- if (io) return feedback.flush(io);
410
- }, "evolution-feedback.flush");
416
+ return feedback.waitIdle();
417
+ }, "evolution-feedback.records");
411
418
  }
412
419
  //#endregion
413
420
  export { Config, EvolutionFeedback, apply, name };
@@ -28,13 +28,15 @@ export declare class EvolutionFeedback {
28
28
  private state;
29
29
  private chain;
30
30
  private readonly path?;
31
+ private readonly io;
31
32
  constructor(io?: IoLike, home?: string, pathOverride?: string);
32
33
  private mutate;
33
34
  restore(io: IoLike): Promise<void>;
34
35
  record(target: string, rating: 'positive' | 'negative', note?: string, kind?: 'skill' | 'session', io?: IoLike): void;
35
36
  score(target: string, kind?: 'skill' | 'session'): number;
36
37
  snapshot(): FeedbackState;
37
- flush(io?: IoLike): Promise<void>;
38
+ /** Await the pending record-task chain (unload safety; rc.66). */
39
+ waitIdle(): Promise<unknown>;
38
40
  }
39
41
  export declare const name = "evolution-feedback";
40
42
  export interface Config {
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.1.0-rc.64",
4
+ "version": "0.1.0-rc.66",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -37,13 +37,13 @@
37
37
  "peerDependencies": {
38
38
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
39
39
  "@deepseek-ai/cordis": "^4.0.1",
40
- "@lmzhen/dsh-evolution-io": "^0.1.0-rc.64",
41
- "@lmzhen/dsh-skill-usage": "^0.1.0-rc.64"
40
+ "@lmzhen/dsh-evolution-io": "^0.1.0-rc.66",
41
+ "@lmzhen/dsh-skill-usage": "^0.1.0-rc.66"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
45
- "@lmzhen/dsh-evolution-io": "^0.1.0-rc.64",
46
- "@lmzhen/dsh-evolution-io-node": "^0.1.0-rc.64",
47
- "@lmzhen/dsh-skill-usage": "^0.1.0-rc.64"
45
+ "@lmzhen/dsh-evolution-io": "^0.1.0-rc.66",
46
+ "@lmzhen/dsh-evolution-io-node": "^0.1.0-rc.66",
47
+ "@lmzhen/dsh-skill-usage": "^0.1.0-rc.66"
48
48
  }
49
49
  }