@lmzhen/dsh-evolution-review 0.3.27 → 0.3.28

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 CHANGED
@@ -32,3 +32,5 @@ Independent of request-prefix construction. This package does not alter the asse
32
32
  ## Configuration
33
33
 
34
34
  `reviewProvider` selects the LLM provider for review subagents. When omitted, the subagent inherits the deployment default route instead of a hardcoded provider name. Model selection stays on the policy (`memoryReviewModel` / `skillReviewModel`).
35
+
36
+ `reviewTimeoutMs` bounds each review subagent run (an `AbortSignal.timeout`; `0` aborts immediately). `executionTimeoutMs` is a leftover declaration and is **not consumed** — it is kept only as a code comment and has no effect; configure `reviewTimeoutMs` instead.
package/lib/index.js CHANGED
@@ -138,18 +138,24 @@ function apply(ctx, rawConfig) {
138
138
  if (completionInjected.has(session.id)) return;
139
139
  if (!shouldCompletionReview(event.data.reason, cumulative, config.skillReviewCompletionMinToolCalls)) return;
140
140
  completionInjected.add(session.id);
141
- agent.inject(createUserMessage({
142
- content: [{
143
- type: "text",
144
- text: COMPLETION_SKILL_REVIEW_PROMPT
145
- }],
146
- source: {
147
- kind: "plugin",
148
- plugin: "dsh-evolution-review",
149
- form: "notice",
150
- summary: "completion review"
151
- }
152
- }));
141
+ try {
142
+ agent.inject(createUserMessage({
143
+ content: [{
144
+ type: "text",
145
+ text: COMPLETION_SKILL_REVIEW_PROMPT
146
+ }],
147
+ source: {
148
+ kind: "plugin",
149
+ plugin: "dsh-evolution-review",
150
+ form: "notice",
151
+ summary: "completion review"
152
+ }
153
+ }));
154
+ } catch (injectError) {
155
+ completionInjected.delete(session.id);
156
+ ctx.logger.warn(`dsh-evolution-review: completion review inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
157
+ return;
158
+ }
153
159
  ctx.emit("evolution/review-scheduled", {
154
160
  sessionId: session.id,
155
161
  kind: "skill",
@@ -272,34 +278,42 @@ function apply(ctx, rawConfig) {
272
278
  const origins = resolveOrigins(void 0, true);
273
279
  const actions = [];
274
280
  let ok = true;
275
- for (const op of plan.memoryOps ?? []) {
276
- if (!Array.isArray(op.evidence) || op.evidence.length === 0) continue;
277
- const normalized = {
278
- target: op.target === "user" ? "user" : "memory",
279
- action: op.action ?? "add",
280
- facts: op.facts ?? op.content,
281
- old_text: op.old_text
282
- };
283
- if ((approval ? await runApproved("memory", `memory ${normalized.target} ${normalized.action}`, normalized, normalized) : await memory?.applyBatch(normalized.target, [normalized]))?.ok) actions.push("Memory updated");
284
- else ok = false;
285
- }
286
- for (const op of plan.skillOps ?? []) {
287
- if (!Array.isArray(op.evidence) || op.evidence.length === 0 || !op.name) continue;
288
- const args = {
289
- ...op,
290
- evidence: op.evidence
281
+ try {
282
+ for (const op of plan.memoryOps ?? []) {
283
+ if (!Array.isArray(op.evidence) || op.evidence.length === 0) continue;
284
+ const normalized = {
285
+ target: op.target === "user" ? "user" : "memory",
286
+ action: op.action ?? "add",
287
+ facts: op.facts ?? op.content,
288
+ old_text: op.old_text
289
+ };
290
+ if ((approval ? await runApproved("memory", `memory ${normalized.target} ${normalized.action}`, normalized, normalized) : await memory?.applyBatch(normalized.target, [normalized]))?.ok) actions.push("Memory updated");
291
+ else ok = false;
292
+ }
293
+ for (const op of plan.skillOps ?? []) {
294
+ if (!Array.isArray(op.evidence) || op.evidence.length === 0 || !op.name) continue;
295
+ const args = {
296
+ ...op,
297
+ evidence: op.evidence
298
+ };
299
+ const runnerArgs = {
300
+ operation: args,
301
+ origin: origins.library
302
+ };
303
+ if ((approval ? await runApproved("skill", `skill ${op.action ?? "patch"} ${op.name}`, runnerArgs, runnerArgs) : await executeSkillDirect(args))?.ok) actions.push(`Skill ${op.name} ${op.action ?? "patch"}`);
304
+ else ok = false;
305
+ }
306
+ return {
307
+ actions,
308
+ ok
291
309
  };
292
- const runnerArgs = {
293
- operation: args,
294
- origin: origins.library
310
+ } catch (error) {
311
+ ctx.logger.warn(`dsh-evolution-review: executePlan aborted mid-way after ${actions.length} ops landed: ${error instanceof Error ? error.message : String(error)}`);
312
+ return {
313
+ actions,
314
+ ok: false
295
315
  };
296
- if ((approval ? await runApproved("skill", `skill ${op.action ?? "patch"} ${op.name}`, runnerArgs, runnerArgs) : await executeSkillDirect(args))?.ok) actions.push(`Skill ${op.name} ${op.action ?? "patch"}`);
297
- else ok = false;
298
316
  }
299
- return {
300
- actions,
301
- ok
302
- };
303
317
  async function runApproved(kind, summary, stored, runnerArgs) {
304
318
  if (!approval) return void 0;
305
319
  if (approval.isEnabled === true && !approval.hasRunner(kind)) {
@@ -511,4 +525,4 @@ function buildReviewRequest(session, kind, signal, maxMessages, maxMessageChars)
511
525
  ].join("\n");
512
526
  }
513
527
  //#endregion
514
- export { Config, apply, filterUnreadSkillOps, inject, name, shouldCompletionReview, sweepDeadSessionEntries };
528
+ export { Config, apply, clampReviewConfig, filterUnreadSkillOps, inject, name, shouldCompletionReview, sweepDeadSessionEntries };
@@ -34,6 +34,18 @@ export interface Config {
34
34
  skillReviewCompletionMinToolCalls?: number;
35
35
  }
36
36
  export declare const Config: z<Config>;
37
+ /**
38
+ * G3.1 (0.3.23): clamp the numeric review config at assembly so a 0/negative/
39
+ * NaN/±Infinity value falls back to the package default instead of folding as a
40
+ * "disabled" special value (a 0 interval would fire a review every turn; NaN
41
+ * folds as NaN into the cadence/timeout). The schema `.min(1)` guards the
42
+ * loader path; this clamp also covers NaN/±Infinity (which schemastery lets a
43
+ * bare number schema through) and direct construction. `reviewMaxDepth` clamps
44
+ * to at least 1 because 0 is the historical 0.3.1 maximum-depth defect (a 0
45
+ * rejects the spawn outright). Warn once when a user-supplied value had to be
46
+ * corrected.
47
+ */
48
+ export declare function clampReviewConfig(rawConfig: Config, ctx: Context): Required<Config>;
37
49
  export declare function apply(ctx: Context, rawConfig: Config): void;
38
50
  /** Completion-channel decision: task finished normally AND the session is proven long. */
39
51
  export declare function shouldCompletionReview(reason: {
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.27",
4
+ "version": "0.3.28",
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.27",
35
- "@lmzhen/dsh-evolution-core": "^0.3.27",
36
- "@lmzhen/dsh-evolution-plan-validator": "^0.3.27"
34
+ "@lmzhen/dsh-evolution-approval": "^0.3.28",
35
+ "@lmzhen/dsh-evolution-core": "^0.3.28",
36
+ "@lmzhen/dsh-evolution-plan-validator": "^0.3.28"
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.27",
46
- "@lmzhen/dsh-evolution-policy": "^0.3.27"
45
+ "@lmzhen/dsh-evolution-state": "^0.3.28",
46
+ "@lmzhen/dsh-evolution-policy": "^0.3.28"
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.27",
58
- "@lmzhen/dsh-evolution-core": "^0.3.27",
59
- "@lmzhen/dsh-evolution-plan-validator": "^0.3.27",
60
- "@lmzhen/dsh-evolution-state": "^0.3.27"
57
+ "@lmzhen/dsh-evolution-approval": "^0.3.28",
58
+ "@lmzhen/dsh-evolution-core": "^0.3.28",
59
+ "@lmzhen/dsh-evolution-plan-validator": "^0.3.28",
60
+ "@lmzhen/dsh-evolution-state": "^0.3.28"
61
61
  }
62
62
  }