@lmzhen/dsh-evolution-feedback 0.3.30 → 0.3.31

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
@@ -39,6 +39,14 @@ var EvolutionFeedback = class {
39
39
  * unpersisted note there, and reverting to it resurrects a value the log
40
40
  * never held). Seeded from the fold truth, updated on successful appends. */
41
41
  durableNote = /* @__PURE__ */ new Map();
42
+ /** V5-32 (0.3.31): fire-and-forget append failures are warn-once per unique
43
+ * message — a persistent refusal (e.g. a future-version log) must not spam
44
+ * the log on every user feedback entry (family posture: process-level once). */
45
+ warnedMessages = /* @__PURE__ */ new Set();
46
+ /** V5-29 (0.3.31): invoked after a FAILED append rolled back, so a caller
47
+ * holding derived state (skillUsage quality score) can re-push it instead of
48
+ * keeping an optimistic value that never landed. */
49
+ onRollback;
42
50
  constructor(io, home = evolutionRoot(), pathOverride, warn = () => {}) {
43
51
  this.path = pathOverride ?? join(home, "evolution", "feedback.json");
44
52
  this.eventsPath = eventsFile(home);
@@ -134,7 +142,13 @@ var EvolutionFeedback = class {
134
142
  }
135
143
  }
136
144
  }
137
- this.warn(`evolution-feedback: failed to append feedback event for ${kind} "${target}": ${error instanceof Error ? error.message : String(error)}`);
145
+ const message = `evolution-feedback: failed to append feedback event for ${kind} "${target}": ${error instanceof Error ? error.message : String(error)}`;
146
+ const cause = error instanceof Error ? error.message : String(error);
147
+ if (!this.warnedMessages.has(cause)) {
148
+ this.warnedMessages.add(cause);
149
+ this.warn(message);
150
+ }
151
+ if (rollback) this.onRollback?.(target, kind);
138
152
  }
139
153
  });
140
154
  }
@@ -416,15 +430,20 @@ function apply(ctx, rawConfig = {}) {
416
430
  if (qualityWired) return;
417
431
  qualityWired = true;
418
432
  const skillUsage = skillCtx.skillUsage;
433
+ const pushQuality = (target, kind) => {
434
+ if (kind !== "skill") return;
435
+ const score = feedback.score(target, "skill");
436
+ const warn = score < qualityWarnThreshold;
437
+ skillUsage.setQuality(target, score, warn).catch((error) => {
438
+ skillCtx.logger.warn(error);
439
+ });
440
+ };
441
+ feedback.onRollback = (target, kind) => {
442
+ pushQuality(target, kind);
443
+ };
419
444
  feedback.record = (target, rating, note, kind) => {
420
445
  baseRecord(target, rating, note, kind ?? "session");
421
- if (kind === "skill") {
422
- const score = feedback.score(target, "skill");
423
- const warn = score < qualityWarnThreshold;
424
- skillUsage.setQuality(target, score, warn).catch((error) => {
425
- skillCtx.logger.warn(error);
426
- });
427
- }
446
+ pushQuality(target, kind ?? "session");
428
447
  };
429
448
  });
430
449
  ctx.effect(() => () => {
@@ -43,6 +43,14 @@ export declare class EvolutionFeedback {
43
43
  * unpersisted note there, and reverting to it resurrects a value the log
44
44
  * never held). Seeded from the fold truth, updated on successful appends. */
45
45
  private readonly durableNote;
46
+ /** V5-32 (0.3.31): fire-and-forget append failures are warn-once per unique
47
+ * message — a persistent refusal (e.g. a future-version log) must not spam
48
+ * the log on every user feedback entry (family posture: process-level once). */
49
+ private readonly warnedMessages;
50
+ /** V5-29 (0.3.31): invoked after a FAILED append rolled back, so a caller
51
+ * holding derived state (skillUsage quality score) can re-push it instead of
52
+ * keeping an optimistic value that never landed. */
53
+ onRollback?: (target: string, kind: 'skill' | 'session') => void;
46
54
  constructor(io?: IoLike, home?: string, pathOverride?: string, warn?: (message: string) => void);
47
55
  /** Bind the evolution IO backend after construction (S6.4 deferred binding). */
48
56
  attachIo(io: IoLike): void;
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.30",
4
+ "version": "0.3.31",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -31,18 +31,18 @@
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
33
  "@deepseek-ai/schemastery": "^3.18.1",
34
- "@lmzhen/dsh-evolution-core": "^0.3.30"
34
+ "@lmzhen/dsh-evolution-core": "^0.3.31"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
38
38
  "@deepseek-ai/cordis": "^4.0.1",
39
- "@lmzhen/dsh-evolution-io": "^0.3.30",
40
- "@lmzhen/dsh-skill-usage": "^0.3.30"
39
+ "@lmzhen/dsh-evolution-io": "^0.3.31",
40
+ "@lmzhen/dsh-skill-usage": "^0.3.31"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
44
- "@lmzhen/dsh-evolution-io": "^0.3.30",
45
- "@lmzhen/dsh-evolution-io-node": "^0.3.30",
46
- "@lmzhen/dsh-skill-usage": "^0.3.30"
44
+ "@lmzhen/dsh-evolution-io": "^0.3.31",
45
+ "@lmzhen/dsh-evolution-io-node": "^0.3.31",
46
+ "@lmzhen/dsh-skill-usage": "^0.3.31"
47
47
  }
48
48
  }