@lmzhen/dsh-evolution-review 0.30.23 → 0.30.25

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
@@ -1,9 +1,9 @@
1
- import { COMPLETION_SKILL_REVIEW_PROMPT, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MEMORY_REVIEW_MODEL, DEFAULT_REVIEW_CONTEXT_MESSAGES, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_MESSAGE_CHARS, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_REVIEW_TIMEOUT_MS, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_MODEL, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS, DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS, DEFAULT_SUBSTANTIVE_MIN_USER_CHARS, DEFAULT_USER_CHAR_LIMIT, MAX_TIMER_DELAY_MS, PROMPT_BUNDLE, advanceReview, assertSkillsRootAliasRetired, authorityFrom, clampOnce, classifySessionEvent, clearReviewChannel, contentHash, createSubagentChannel, evolutionIoAdapter, filterUnreadSkillOps, filterUnreadSkillOps as filterUnreadSkillOps$1, foldUntrustedLines, isPresent, isUnknown, liveBool, markReviewChannel, newSkillLibrary, paramRowId, payloadText, pickWithPolicy, policyStageLimits, readDispatchSignal, redactSecrets, resolveOrigins, resolveRootConfig, reviewPrompt, sessionAudited, sessionEvidenceIndex, sessionReadNames, sessionTurnSignals, sweepReviewChannelSessions, unwrapLive, userSetKeys, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
1
+ import { COMPLETION_SKILL_REVIEW_PROMPT, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MEMORY_REVIEW_MODEL, DEFAULT_REVIEW_CONTEXT_MESSAGES, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_MESSAGE_CHARS, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_REVIEW_TIMEOUT_MS, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_MODEL, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS, DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS, DEFAULT_SUBSTANTIVE_MIN_USER_CHARS, DEFAULT_USER_CHAR_LIMIT, MAX_TIMER_DELAY_MS, PROMPT_BUNDLE, advanceReview, assertSkillsRootAliasRetired, authorityFrom, clampOnce, classifySessionEvent, clearReviewChannel, contentHash, createSubagentChannel, ensureSkillFrontmatter, evolutionIoAdapter, filterUnreadSkillOps, filterUnreadSkillOps as filterUnreadSkillOps$1, foldUntrustedLines, isPresent, isUnknown, liveBool, markReviewChannel, newSkillLibrary, paramRowId, payloadText, pickWithPolicy, policyStageLimits, readDispatchSignal, redactSecrets, resolveOrigins, resolveRootConfig, reviewPrompt, sessionAudited, sessionEvidenceIndex, sessionReadNames, sessionTurnSignals, sweepReviewChannelSessions, unwrapLive, userSetKeys, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
2
2
  import { createHash, randomUUID } from "node:crypto";
3
3
  import z from "@deepseek-ai/schemastery";
4
4
  import { createUserMessage } from "@deepseek-ai/dsh-llm";
5
5
  import { SessionId } from "@deepseek-ai/dsh-session";
6
- import { validateEvolutionPlan } from "@lmzhen/dsh-evolution-plan-validator";
6
+ import { planContractPrompt, validateEvolutionPlan } from "@lmzhen/dsh-evolution-plan-validator";
7
7
  /**
8
8
  * Whether a message is a notice this plugin delivered, judged only by durable source fields.
9
9
  *
@@ -143,6 +143,10 @@ function emitReviewScheduled(ctx, event) {
143
143
  /** Error name marking the S2-6 watchdog expiry (see the catch in trySubagentReview). */
144
144
  const name = "evolution-review";
145
145
  const inject = ["agents"];
146
+ /** Result notices are optional; a review PROMPT is the review itself in inject mode. */
147
+ function noticeAllowed(reviewPrompt, notice) {
148
+ return reviewPrompt || notice;
149
+ }
146
150
  const Config = z.object({
147
151
  reviewEnabled: z.boolean().default(true).volatile(),
148
152
  reviewMode: z.union([z.const("subagent"), z.const("inject")]).default("inject").volatile(),
@@ -162,6 +166,7 @@ const Config = z.object({
162
166
  z.const("both")
163
167
  ]).default(DEFAULT_SKILL_REVIEW_TRIGGER).volatile(),
164
168
  reviewWakeInject: z.boolean().default(true).volatile(),
169
+ reviewNotice: z.boolean().default(true).volatile(),
165
170
  sessionScoped: z.boolean().default(false),
166
171
  skillReviewCompletionMinToolCalls: z.number().min(1).default(DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS).volatile(),
167
172
  root: z.string().default(""),
@@ -235,7 +240,8 @@ function resolveReviewRowSettings(rawConfig, warn) {
235
240
  skillReviewCompletionMinToolCalls: clampOnce(warned, warn, "skillReviewCompletionMinToolCalls", rawConfig.skillReviewCompletionMinToolCalls, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, 1),
236
241
  reviewEnabled: liveBool(rawConfig.reviewEnabled, true),
237
242
  reviewMode: unwrapLive(rawConfig.reviewMode) ?? "inject",
238
- reviewWakeInject: liveBool(rawConfig.reviewWakeInject, true)
243
+ reviewWakeInject: liveBool(rawConfig.reviewWakeInject, true),
244
+ reviewNotice: liveBool(rawConfig.reviewNotice, true)
239
245
  };
240
246
  }
241
247
  function apply(ctx, rawConfig = {}) {
@@ -289,7 +295,8 @@ function apply(ctx, rawConfig = {}) {
289
295
  skillReviewCompletionMinToolCalls: row.skillReviewCompletionMinToolCalls,
290
296
  reviewEnabled: row.reviewEnabled,
291
297
  reviewMode: mode(),
292
- reviewWakeInject: row.reviewWakeInject
298
+ reviewWakeInject: row.reviewWakeInject,
299
+ reviewNotice: row.reviewNotice
293
300
  };
294
301
  };
295
302
  const schemaDefaults = Config["~standard"].validate({}).value;
@@ -639,6 +646,10 @@ function apply(ctx, rawConfig = {}) {
639
646
  const deliverMessage = (agent, text, summary, reviewPrompt = false) => {
640
647
  const wake = agent;
641
648
  const inbox = agent.inbox;
649
+ if (!noticeAllowed(reviewPrompt, params().reviewNotice)) {
650
+ ctx.logger.info(`dsh-evolution-review: suppressed a result notice (${summary}) — reviewNotice is off`);
651
+ return true;
652
+ }
642
653
  if (reviewPrompt && noticeIsOutstanding(agent.session.id, inbox)) {
643
654
  if (!reviewNoticeOutstandingWarned) {
644
655
  reviewNoticeOutstandingWarned = true;
@@ -982,6 +993,13 @@ function apply(ctx, rawConfig = {}) {
982
993
  ...op,
983
994
  evidence: op.evidence
984
995
  };
996
+ if ((args.action === "create" || args.action === "edit" || args.action === "update") && typeof args.content === "string" && typeof args.name === "string") {
997
+ const repaired = ensureSkillFrontmatter(args.content, args.name, args.description);
998
+ if (repaired.repaired) {
999
+ args.content = repaired.content;
1000
+ ctx.logger.warn(`dsh-evolution-review: synthesized missing SKILL.md frontmatter for ${args.name}`);
1001
+ }
1002
+ }
985
1003
  let stagedBytes;
986
1004
  if ((args.action === "update" || args.action === "edit") && hashLibrary && typeof args.name === "string" && args.name !== "") {
987
1005
  const probe = await hashLibrary.readSkillProbe(args.name);
@@ -1256,6 +1274,7 @@ function appendDispatchFrame(digest, id, event) {
1256
1274
  const frames = digest.get(id) ?? [];
1257
1275
  frames.push({
1258
1276
  type: event.type,
1277
+ ...event.seq === void 0 ? {} : { seq: event.seq },
1259
1278
  ...event.data === void 0 ? {} : { data: event.data }
1260
1279
  });
1261
1280
  if (frames.length > DISPATCH_DIGEST_FRAMES) frames.splice(0, frames.length - DISPATCH_DIGEST_FRAMES);
@@ -1321,7 +1340,7 @@ function resultCallIdOf(event) {
1321
1340
  * keeps the call identity its `[call]` line would have had. Budget: 500 chars
1322
1341
  * per line (the 12-line cap lives in buildReviewRequest and is unchanged).
1323
1342
  */
1324
- function renderToolResultLine(data, identity) {
1343
+ function renderToolResultLine(data, identity, seq) {
1325
1344
  const shape = data;
1326
1345
  const nativeContent = shape?.message?.content;
1327
1346
  const resultBlocks = Array.isArray(nativeContent) ? nativeContent.filter((block) => block.type === "tool-result") : [];
@@ -1338,7 +1357,8 @@ function renderToolResultLine(data, identity) {
1338
1357
  failed = false;
1339
1358
  }
1340
1359
  const head = identity === void 0 ? "" : `${foldUntrustedLines(identity.name, 0)} ${foldUntrustedLines(identity.argsRaw, 200)} → `;
1341
- return `[result]${failed ? " [ERROR]" : ""} ${head}${foldUntrustedLines(output, 500)}`;
1360
+ const failure = failed ? " [ERROR]" : "";
1361
+ return (seq === void 0 ? "" : "seq=" + String(seq) + " ") + "[result]" + failure + " " + head + foldUntrustedLines(output, 500);
1342
1362
  }
1343
1363
  /** Text of a PTC settle `content` payload (the logged ContentBlock list):
1344
1364
  * text blocks and plain strings joined, anything else skipped. */
@@ -1402,14 +1422,15 @@ function buildReviewRequest(session, kind, signal, maxMessages, maxMessageChars,
1402
1422
  name: settleData.name,
1403
1423
  argsRaw: typeof settleData.arguments === "string" ? settleData.arguments : JSON.stringify(settleData.arguments ?? {})
1404
1424
  } : callIdentity.get(answeredCallId);
1405
- toolLines.push(renderToolResultLine(event?.data, identity));
1425
+ toolLines.push(renderToolResultLine(event?.data, identity, event?.seq));
1406
1426
  continue;
1407
1427
  }
1408
1428
  const opened = readDispatchSignal(event);
1409
1429
  if (opened === null || openedCallIds.has(opened.callId)) continue;
1410
1430
  openedCallIds.add(opened.callId);
1411
1431
  const argsRaw = typeof opened.arguments === "string" ? opened.arguments : JSON.stringify(opened.arguments ?? {});
1412
- toolLines.push(`[call] ${foldUntrustedLines(opened.name, 0)} ${foldUntrustedLines(argsRaw, 500)}`);
1432
+ const seq = typeof event?.seq === "number" ? "seq=" + String(event.seq) + " " : "";
1433
+ toolLines.push(seq + "[call] " + foldUntrustedLines(opened.name, 0) + " " + foldUntrustedLines(argsRaw, 500));
1413
1434
  }
1414
1435
  toolLines.reverse();
1415
1436
  return [
@@ -1418,9 +1439,10 @@ function buildReviewRequest(session, kind, signal, maxMessages, maxMessageChars,
1418
1439
  `Recent tool activity (${toolLines.length}):`,
1419
1440
  ...toolLines,
1420
1441
  "Return ONLY the structured JSON plan. Evidence is mandatory for every op.",
1442
+ planContractPrompt(),
1421
1443
  "",
1422
1444
  ...messages
1423
1445
  ].join("\n");
1424
1446
  }
1425
1447
  //#endregion
1426
- export { Config, REVIEW_OUTPUT_SCHEMA, apply, buildReviewRequest, clampReviewConfig, filterUnreadSkillOps, inject, name, renderToolResultLine, resolveReviewRowSettings, shouldCompletionReview, sweepDeadSessionEntries };
1448
+ export { Config, REVIEW_OUTPUT_SCHEMA, apply, buildReviewRequest, clampReviewConfig, filterUnreadSkillOps, inject, name, noticeAllowed, renderToolResultLine, resolveReviewRowSettings, shouldCompletionReview, sweepDeadSessionEntries };
@@ -25,6 +25,8 @@ export { filterUnreadSkillOps } from '@lmzhen/dsh-evolution-core';
25
25
  /** Error name marking the S2-6 watchdog expiry (see the catch in trySubagentReview). */
26
26
  export declare const name = "evolution-review";
27
27
  export declare const inject: string[];
28
+ /** Result notices are optional; a review PROMPT is the review itself in inject mode. */
29
+ export declare function noticeAllowed(reviewPrompt: boolean, notice: boolean): boolean;
28
30
  export interface Config {
29
31
  reviewEnabled?: Volatile<boolean>;
30
32
  /** How the flush delivers the review: `'inject'` (default since 0.3.74) hands
@@ -85,6 +87,10 @@ export interface Config {
85
87
  * differs). Default true; false degrades to the non-waking inject (the
86
88
  * summary then waits for the next driver wake). */
87
89
  reviewWakeInject?: Volatile<boolean>;
90
+ /** Deliver result notices into the parent conversation. Default true. A review PROMPT is the
91
+ * review itself in inject mode, so this never suppresses prompt delivery — only the result
92
+ * notice (and late/zero-landing notices) that wakes a turn just to report a count. */
93
+ reviewNotice?: Volatile<boolean>;
88
94
  /** V10-11 (P2-7): skill tree root for the review's direct skill writes.
89
95
  * Empty (the default) resolves through `resolveSkillsRoot` to the shared
90
96
  * default root — the historical behavior. A custom root keeps review-created
@@ -119,6 +125,7 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
119
125
  reviewProvider: z<string, string, "plain">;
120
126
  skillReviewTrigger: z<"cadence" | "completion" | "both", "cadence" | "completion" | "both", "volatile-defined">;
121
127
  reviewWakeInject: z<boolean, boolean, "volatile-defined">;
128
+ reviewNotice: z<boolean, boolean, "volatile-defined">;
122
129
  sessionScoped: z<boolean, boolean, "defined">;
123
130
  skillReviewCompletionMinToolCalls: z<number, number, "volatile-defined">;
124
131
  root: z<string, string, "defined">;
@@ -138,6 +145,7 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
138
145
  reviewProvider: z<string, string, "plain">;
139
146
  skillReviewTrigger: z<"cadence" | "completion" | "both", "cadence" | "completion" | "both", "volatile-defined">;
140
147
  reviewWakeInject: z<boolean, boolean, "volatile-defined">;
148
+ reviewNotice: z<boolean, boolean, "volatile-defined">;
141
149
  sessionScoped: z<boolean, boolean, "defined">;
142
150
  skillReviewCompletionMinToolCalls: z<number, number, "volatile-defined">;
143
151
  root: z<string, string, "defined">;
@@ -208,6 +216,8 @@ export interface ReviewSettings {
208
216
  reviewMode: 'subagent' | 'inject';
209
217
  /** Deliver the deferred review as a waking follow-up message. */
210
218
  reviewWakeInject: boolean;
219
+ /** Deliver result notices (not review prompts). */
220
+ reviewNotice: boolean;
211
221
  }
212
222
  /**
213
223
  * This row's review knobs as they stand RIGHT NOW (G1 §8.3) — the base layer of the
@@ -228,6 +238,8 @@ export declare function shouldCompletionReview(reason: {
228
238
  /** One dispatch frame the review digest can render (a native call/result or a PTC sub-dispatch). */
229
239
  interface ReviewDispatchFrame {
230
240
  readonly type: string;
241
+ /** Session seq of the frame, so a plan can cite a real `event_seq`. */
242
+ readonly seq?: number;
231
243
  readonly data?: unknown;
232
244
  }
233
245
  /**
@@ -260,7 +272,7 @@ export declare function sweepDeadSessionEntries<K>(entries: Map<K, unknown> | Se
260
272
  export declare function renderToolResultLine(data: unknown, identity?: {
261
273
  name: string;
262
274
  argsRaw: string;
263
- }): string;
275
+ }, seq?: number): string;
264
276
  export declare function buildReviewRequest(session: Session, kind: ReviewKind, signal: {
265
277
  toolCalls: number;
266
278
  userChars: number;
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.30.23",
4
+ "version": "0.30.25",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,9 +27,9 @@
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
29
  "@deepseek-ai/schemastery": "^3.18.5",
30
- "@lmzhen/dsh-evolution-approval": "^0.30.23",
31
- "@lmzhen/dsh-evolution-core": "^0.30.23",
32
- "@lmzhen/dsh-evolution-plan-validator": "^0.30.23"
30
+ "@lmzhen/dsh-evolution-approval": "^0.30.25",
31
+ "@lmzhen/dsh-evolution-core": "^0.30.25",
32
+ "@lmzhen/dsh-evolution-plan-validator": "^0.30.25"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "@deepseek-ai/cordis": "^4.0.5",
@@ -37,8 +37,8 @@
37
37
  "@deepseek-ai/dsh-llm": "^0.2.1-rc.1",
38
38
  "@deepseek-ai/dsh-session": "^0.2.1-rc.1",
39
39
  "@deepseek-ai/dsh-tools": "^0.2.1-rc.1",
40
- "@lmzhen/dsh-evolution-policy": "^0.30.23",
41
- "@lmzhen/dsh-evolution-state": "^0.30.23"
40
+ "@lmzhen/dsh-evolution-policy": "^0.30.25",
41
+ "@lmzhen/dsh-evolution-state": "^0.30.25"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@deepseek-ai/dsh-agent": "^0.2.1-rc.1",
@@ -48,11 +48,11 @@
48
48
  "@deepseek-ai/dsh-session-persistence": "^0.2.1-rc.1",
49
49
  "@deepseek-ai/dsh-session-persistence-jsonl": "^0.2.1-rc.1",
50
50
  "@deepseek-ai/dsh-tools": "^0.2.1-rc.1",
51
- "@lmzhen/dsh-evolution-approval": "^0.30.23",
52
- "@lmzhen/dsh-evolution-core": "^0.30.23",
53
- "@lmzhen/dsh-evolution-curator": "^0.30.23",
54
- "@lmzhen/dsh-evolution-plan-validator": "^0.30.23",
55
- "@lmzhen/dsh-evolution-state": "^0.30.23"
51
+ "@lmzhen/dsh-evolution-approval": "^0.30.25",
52
+ "@lmzhen/dsh-evolution-core": "^0.30.25",
53
+ "@lmzhen/dsh-evolution-curator": "^0.30.25",
54
+ "@lmzhen/dsh-evolution-plan-validator": "^0.30.25",
55
+ "@lmzhen/dsh-evolution-state": "^0.30.25"
56
56
  },
57
57
  "engines": {
58
58
  "dsh": ">=0.2.1-rc.1 <0.2.2-0"