@lmzhen/dsh-evolution-feedback 0.3.57 → 0.3.59

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
@@ -23,7 +23,7 @@ const CACHE_VERSION = 2;
23
23
  * live in the ACTIVE log (bounded by `EVENT_LOG_ROTATE_AT`), so the next fold
24
24
  * is complete. Package-private tunable, not a config surface. */
25
25
  const CACHE_SNAP_EVERY = 1024;
26
- var EvolutionFeedback = class {
26
+ var EvolutionFeedback = class EvolutionFeedback {
27
27
  state = {
28
28
  skills: {},
29
29
  sessions: {}
@@ -39,10 +39,15 @@ 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
+ /** P2-32 (v11): process-level bound — every feedbacked session would
43
+ * otherwise keep one entry for the whole process lifetime (a name + note
44
+ * string per session); cap both maps and drop the oldest on overflow. */
45
+ static NOTE_CAP = 512;
42
46
  /** V5-32 (0.3.31): fire-and-forget append failures are warn-once per unique
43
47
  * message — a persistent refusal (e.g. a future-version log) must not spam
44
48
  * the log on every user feedback entry (family posture: process-level once). */
45
49
  warnedMessages = /* @__PURE__ */ new Set();
50
+ WARNED_CAP = 512;
46
51
  /** V5-29 (0.3.31): invoked after a FAILED append rolled back, so a caller
47
52
  * holding derived state (skillUsage quality score) can re-push it instead of
48
53
  * keeping an optimistic value that never landed. */
@@ -97,6 +102,11 @@ var EvolutionFeedback = class {
97
102
  };
98
103
  for (const [target, record] of Object.entries(truth.skills)) this.durableNote.set(this.noteKey("skills", target), record.lastNote);
99
104
  for (const [target, record] of Object.entries(truth.sessions)) this.durableNote.set(this.noteKey("sessions", target), record.lastNote);
105
+ while (this.durableNote.size > EvolutionFeedback.NOTE_CAP) {
106
+ const oldest = this.durableNote.keys().next().value;
107
+ if (oldest === void 0) break;
108
+ this.durableNote.delete(oldest);
109
+ }
100
110
  if (maxSeq > 0 && (!cache || cache.lastSeq < maxSeq)) try {
101
111
  await io.writeText(path, JSON.stringify({
102
112
  version: CACHE_VERSION,
@@ -128,7 +138,13 @@ var EvolutionFeedback = class {
128
138
  rating,
129
139
  note
130
140
  });
131
- if (note !== void 0) this.durableNote.set(this.noteKey(mode, target), note);
141
+ if (note !== void 0) {
142
+ if (this.durableNote.size >= EvolutionFeedback.NOTE_CAP) {
143
+ const oldest = this.durableNote.keys().next().value;
144
+ if (oldest !== void 0) this.durableNote.delete(oldest);
145
+ }
146
+ this.durableNote.set(this.noteKey(mode, target), note);
147
+ }
132
148
  if (seq % CACHE_SNAP_EVERY === 0) await this.writeCacheNow();
133
149
  } catch (error) {
134
150
  const rollback = table[target];
@@ -145,6 +161,10 @@ var EvolutionFeedback = class {
145
161
  const message = `evolution-feedback: failed to append feedback event for ${kind} "${target}": ${error instanceof Error ? error.message : String(error)}`;
146
162
  const cause = error instanceof Error ? error.message : String(error);
147
163
  if (!this.warnedMessages.has(cause)) {
164
+ if (this.warnedMessages.size >= this.WARNED_CAP) {
165
+ const oldest = this.warnedMessages.values().next().value;
166
+ if (oldest !== void 0) this.warnedMessages.delete(oldest);
167
+ }
148
168
  this.warnedMessages.add(cause);
149
169
  this.warn(message);
150
170
  }
@@ -43,10 +43,15 @@ 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
+ /** P2-32 (v11): process-level bound — every feedbacked session would
47
+ * otherwise keep one entry for the whole process lifetime (a name + note
48
+ * string per session); cap both maps and drop the oldest on overflow. */
49
+ private static readonly NOTE_CAP;
46
50
  /** V5-32 (0.3.31): fire-and-forget append failures are warn-once per unique
47
51
  * message — a persistent refusal (e.g. a future-version log) must not spam
48
52
  * the log on every user feedback entry (family posture: process-level once). */
49
53
  private readonly warnedMessages;
54
+ private readonly WARNED_CAP;
50
55
  /** V5-29 (0.3.31): invoked after a FAILED append rolled back, so a caller
51
56
  * holding derived state (skillUsage quality score) can re-push it instead of
52
57
  * keeping an optimistic value that never landed. */
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.57",
4
+ "version": "0.3.59",
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.57"
34
+ "@lmzhen/dsh-evolution-core": "^0.3.59"
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.57",
40
- "@lmzhen/dsh-skill-usage": "^0.3.57"
39
+ "@lmzhen/dsh-evolution-io": "^0.3.59",
40
+ "@lmzhen/dsh-skill-usage": "^0.3.59"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
44
- "@lmzhen/dsh-evolution-io": "^0.3.57",
45
- "@lmzhen/dsh-evolution-io-node": "^0.3.57",
46
- "@lmzhen/dsh-skill-usage": "^0.3.57"
44
+ "@lmzhen/dsh-evolution-io": "^0.3.59",
45
+ "@lmzhen/dsh-evolution-io-node": "^0.3.59",
46
+ "@lmzhen/dsh-skill-usage": "^0.3.59"
47
47
  }
48
48
  }