@lmzhen/dsh-evolution-review 0.3.39 → 0.3.40

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,6 +23,7 @@ const Config = z.object({
23
23
  reviewMaxDepth: z.number().min(1).default(1),
24
24
  reviewProvider: z.string(),
25
25
  skillReviewTrigger: z.string().default(DEFAULT_SKILL_REVIEW_TRIGGER),
26
+ reviewWakeInject: z.boolean().default(true),
26
27
  skillReviewCompletionMinToolCalls: z.number().min(1).default(DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS)
27
28
  });
28
29
  let statelessReviewStateWarned = false;
@@ -114,28 +115,35 @@ function apply(ctx, rawConfig) {
114
115
  skillInterval: snapshot?.reviewSkillInterval ?? config.skillInterval,
115
116
  substantiveMinToolCalls: snapshot?.substantiveMinToolCalls ?? 3,
116
117
  substantiveMinUserChars: snapshot?.substantiveMinUserChars ?? 200,
117
- substantiveMinAgentChars: snapshot?.substantiveMinAgentChars ?? 500
118
+ substantiveMinAgentChars: snapshot?.substantiveMinAgentChars ?? 500,
119
+ resetOnFire: false
118
120
  });
119
121
  await stateService?.saveReviewState(session.id, state);
120
122
  const cumulative = (cumulativeToolCalls.get(session.id) ?? 0) + signal.toolCalls;
121
123
  cumulativeToolCalls.set(session.id, cumulative);
124
+ const deliverReview = (text) => {
125
+ const message = createUserMessage({
126
+ content: [{
127
+ type: "text",
128
+ text
129
+ }],
130
+ source: {
131
+ kind: "plugin",
132
+ plugin: "dsh-evolution-review",
133
+ form: "notice",
134
+ summary: "auto-review"
135
+ }
136
+ });
137
+ const followup = agent.followup;
138
+ if (config.reviewWakeInject && typeof followup === "function") followup(message);
139
+ else agent.inject(message);
140
+ };
122
141
  if (event.data.reason.kind === "completed") {
123
- const pendingKind = pendingCadenceReviews.get(session.id);
142
+ const pendingKind = pendingCadenceReviews.get(session.id) ?? kind ?? void 0;
124
143
  if (pendingKind !== void 0) {
125
144
  pendingCadenceReviews.delete(session.id);
126
145
  if ((policy()?.reviewMode ?? config.reviewMode) === "inject") try {
127
- agent.inject(createUserMessage({
128
- content: [{
129
- type: "text",
130
- text: reviewPrompt(pendingKind)
131
- }],
132
- source: {
133
- kind: "plugin",
134
- plugin: "dsh-evolution-review",
135
- form: "notice",
136
- summary: "auto-review"
137
- }
138
- }));
146
+ deliverReview(reviewPrompt(pendingKind));
139
147
  } catch (injectError) {
140
148
  ctx.logger.warn(`dsh-evolution-review: deferred review inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
141
149
  }
@@ -147,24 +155,16 @@ function apply(ctx, rawConfig) {
147
155
  assistantChars: signal.assistantChars
148
156
  });
149
157
  else try {
150
- agent.inject(createUserMessage({
151
- content: [{
152
- type: "text",
153
- text: reviewPrompt(pendingKind)
154
- }],
155
- source: {
156
- kind: "plugin",
157
- plugin: "dsh-evolution-review",
158
- form: "notice",
159
- summary: "auto-review"
160
- }
161
- }));
158
+ deliverReview(reviewPrompt(pendingKind));
162
159
  } catch (injectError) {
163
160
  ctx.logger.warn(`dsh-evolution-review: deferred review inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
164
161
  }
162
+ state.turnsSinceMemory = 0;
163
+ state.turnsSinceSkill = 0;
164
+ await stateService?.saveReviewState(session.id, state);
165
165
  }
166
166
  }
167
- if (kind) {
167
+ if (kind && event.data.reason.kind !== "completed") {
168
168
  pendingCadenceReviews.set(session.id, kind);
169
169
  if (!pendingCadenceWarned.has(session.id)) {
170
170
  pendingCadenceWarned.add(session.id);
@@ -267,7 +267,7 @@ function apply(ctx, rawConfig) {
267
267
  });
268
268
  const acceptedSkillOps = validation.accepted.skillOps ?? [];
269
269
  const skippedUnread = filterUnreadSkillOps(acceptedSkillOps, new Set([...collectReadSkillNames(session), ...childReads]));
270
- const executed = await executePlan(validation.accepted, session.id);
270
+ const executed = await executePlan(validation.accepted, session);
271
271
  const actions = executed.actions;
272
272
  const evidenceQuotes = [...validation.accepted.memoryOps ?? [], ...acceptedSkillOps].reduce((total, op) => total + (Array.isArray(op.evidence) ? op.evidence.length : 0), 0);
273
273
  if (actions.length > 0) {
@@ -345,7 +345,8 @@ function apply(ctx, rawConfig) {
345
345
  reviewInFlight = false;
346
346
  }
347
347
  }
348
- async function executePlan(plan, sessionId) {
348
+ async function executePlan(plan, session) {
349
+ const sessionId = session?.id;
349
350
  const memory = ctx.get("memory");
350
351
  const approval = ctx.get("evolutionApproval");
351
352
  const origins = resolveOrigins(void 0, true);
@@ -361,7 +362,7 @@ function apply(ctx, rawConfig) {
361
362
  facts: op.facts ?? op.content,
362
363
  old_text: op.old_text
363
364
  };
364
- const result = approval ? await runApproved("memory", `memory ${normalized.target} ${normalized.action}`, normalized, normalized) : await memory?.applyBatch(normalized.target, [normalized]);
365
+ const result = approval ? await runApproved("memory", `memory ${normalized.target} ${normalized.action}`, normalized, normalized, session) : await memory?.applyBatch(normalized.target, [normalized]);
365
366
  if (result?.ok) actions.push("Memory updated");
366
367
  else {
367
368
  ok = false;
@@ -378,7 +379,7 @@ function apply(ctx, rawConfig) {
378
379
  operation: args,
379
380
  origin: origins.library
380
381
  };
381
- const result = approval ? await runApproved("skill", `skill ${op.action ?? "patch"} ${op.name}`, runnerArgs, runnerArgs) : await executeSkillDirect(args);
382
+ const result = approval ? await runApproved("skill", `skill ${op.action ?? "patch"} ${op.name}`, runnerArgs, runnerArgs, session) : await executeSkillDirect(args);
382
383
  if (result?.ok) actions.push(`Skill ${op.name} ${op.action ?? "patch"}`);
383
384
  else {
384
385
  ok = false;
@@ -401,7 +402,7 @@ function apply(ctx, rawConfig) {
401
402
  aborted: reason
402
403
  };
403
404
  }
404
- async function runApproved(kind, summary, stored, runnerArgs) {
405
+ async function runApproved(kind, summary, stored, runnerArgs, approvalSession) {
405
406
  if (!approval) return void 0;
406
407
  if (approval.isEnabled === true && !approval.hasRunner(kind)) {
407
408
  ctx.logger.warn(`dsh-evolution-review: approval enabled but no replay runner registered for kind "${kind}" - skipping write (${summary})`);
@@ -415,7 +416,8 @@ function apply(ctx, rawConfig) {
415
416
  summary,
416
417
  args: stored,
417
418
  origin: origins.approval,
418
- ...sessionId ? { sessionId } : {}
419
+ ...sessionId ? { sessionId } : {},
420
+ ...approvalSession ? { session: approvalSession } : {}
419
421
  });
420
422
  if (decision.action === "staged") return {
421
423
  ok: false,
@@ -32,6 +32,11 @@ export interface Config {
32
32
  skillReviewTrigger?: string;
33
33
  /** Cumulative session tool calls before a session counts as proven-long for the completion channel. */
34
34
  skillReviewCompletionMinToolCalls?: number;
35
+ /** 0.3.40: deliver the deferred review with a WAKING inject for a summary the
36
+ * model starts immediately (agent.followup — same send() queue, wakeup bit
37
+ * differs). Default true; false degrades to the non-waking inject (the
38
+ * summary then waits for the next driver wake). */
39
+ reviewWakeInject?: boolean;
35
40
  }
36
41
  export declare const Config: z<Config>;
37
42
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-evolution-review",
3
3
  "description": "Background review orchestration (community build)",
4
- "version": "0.3.39",
4
+ "version": "0.3.40",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -31,9 +31,9 @@
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
33
  "@deepseek-ai/schemastery": "^3.18.1",
34
- "@lmzhen/dsh-evolution-approval": "^0.3.39",
35
- "@lmzhen/dsh-evolution-core": "^0.3.39",
36
- "@lmzhen/dsh-evolution-plan-validator": "^0.3.39"
34
+ "@lmzhen/dsh-evolution-approval": "^0.3.40",
35
+ "@lmzhen/dsh-evolution-core": "^0.3.40",
36
+ "@lmzhen/dsh-evolution-plan-validator": "^0.3.40"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@deepseek-ai/cordis": "^4.0.1",
@@ -42,8 +42,8 @@
42
42
  "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
43
43
  "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
44
44
  "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
45
- "@lmzhen/dsh-evolution-state": "^0.3.39",
46
- "@lmzhen/dsh-evolution-policy": "^0.3.39"
45
+ "@lmzhen/dsh-evolution-state": "^0.3.40",
46
+ "@lmzhen/dsh-evolution-policy": "^0.3.40"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
@@ -54,9 +54,9 @@
54
54
  "@deepseek-ai/dsh-session-persistence": "^0.1.1-rc.2",
55
55
  "@deepseek-ai/dsh-session-persistence-jsonl": "^0.1.1-rc.2",
56
56
  "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
57
- "@lmzhen/dsh-evolution-approval": "^0.3.39",
58
- "@lmzhen/dsh-evolution-core": "^0.3.39",
59
- "@lmzhen/dsh-evolution-plan-validator": "^0.3.39",
60
- "@lmzhen/dsh-evolution-state": "^0.3.39"
57
+ "@lmzhen/dsh-evolution-approval": "^0.3.40",
58
+ "@lmzhen/dsh-evolution-core": "^0.3.40",
59
+ "@lmzhen/dsh-evolution-plan-validator": "^0.3.40",
60
+ "@lmzhen/dsh-evolution-state": "^0.3.40"
61
61
  }
62
62
  }