@lmzhen/dsh-evolution-learning-graph 0.3.83 → 0.4.1

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.
Files changed (3) hide show
  1. package/README.md +11 -14
  2. package/lib/index.js +16 -10
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -10,25 +10,22 @@ Memory node ids carry a trailing snapshot token (`memory:<source>:<index>:<snaps
10
10
 
11
11
  Memory→skill edges are word-level, not substring: the entry is tokenized on non-letter/digit/hyphen runs and a skill name links only when it is a whole token. This prevents a skill named `run` from linking the words `running`/`grunt`.
12
12
 
13
- `graph edit`/`graph delete` route through the evolution approval seam when it is mounted (soft-probed; the write executes directly when it is absent) — for BOTH skill nodes and memory nodes (P2-6, v15; memory staged args mirror the `memory` tool runner's replay shape). Before staging, the seam's `hasRunner` is checked (P2-7, v15): with approval enabled, a session policy that is not `never`, and the write actually staging (foreground stages per approval `stageForeground`; subagent origins always stage), a missing replay runner's row (tool-skill-manage / tool-memory) refuses the write; allow-direct combinations execute unchanged instead of creating a pending record no approver could replay. Each approved/executed edit bumps the skill's patch counter and a delete archives it, matching `skill_manage` — including the no-op gate: an edit whose content is byte-equivalent to the current file (`noop`) writes nothing and does not bump the patch counter, exactly as `skill_manage` treats an unchanged update/patch. The command invocation's session rides the approval request (v12 N1), so a `never`-policy session stages nothing instead of deriving every graph write as foreground.
13
+ **`graph edit`/`graph delete` route through the evolution approval seam** when mounted (soft-probed: the write executes directly when absent) — for BOTH skill nodes and memory nodes. Each approved/executed edit bumps the skill's patch counter and a delete archives it, matching `skill_manage` — including the no-op gate: an edit whose content is byte-equivalent to the current file (`noop`) writes nothing and does not bump the patch counter, exactly as `skill_manage` treats an unchanged update/patch.
14
14
 
15
- ## Model Experience
15
+ ## Model surface
16
16
 
17
- ### Indirect model surface
17
+ - **Model-visible:** nothing of its own: no prompt section and no tool schema; `/graph` is a human command, and consumers own the model-visible effects.
18
+ - **Prompt prefix / KV cache:** independent of request-prefix construction — it does not alter the assembled prompt or tool list; family-level rules: `packages/README.md` §"Model-visible prompt prefix and the KV cache".
19
+ - **Mount it?** yes — the `evolution-learning-graph` row, carried by the `evolution-host`, `evolution-all` and one-click `evolution-preset` bundles.
18
20
 
19
- `@lmzhen/dsh-evolution-learning-graph` registers no direct prompt or tool schema itself. Model-visible effects are owned by the packages that consume this service.
20
-
21
- #### Token effect
22
-
23
- Zero direct token effect from this package; consumers add any model-visible tokens.
24
-
25
- #### KV Cache effect
26
-
27
- Independent of request-prefix construction. This package does not alter the assembled prompt or tool list.
28
-
29
- ## Known Limitations and Deferred Work
21
+ ## Known limitations
30
22
 
31
23
  - The memory drift snapshot covers only the node label (first line, first 80 chars): a change confined to a later line of the same entry is not detected, because the rendered node label is the comparison anchor.
32
24
  - A hand-typed bare `memory:<source>:<index>` id has no snapshot and skips the drift check (legacy path; the rendered ids always carry the snapshot).
33
25
 
34
26
  **Runtime invariant:** No companion is published. The platform auto-assembles nothing and the family mounts no `<pkg>/invariant` cordis row, so a companion here would never execute (v37 S2.1 / I-3).
27
+ ## Notes and history
28
+
29
+ - `graph edit`/`graph delete` route through the evolution approval seam when it is mounted (soft-probed; the write executes directly when it is absent): for BOTH skill nodes and memory nodes (P2-6, v15; memory staged args mirror the `memory` tool runner's replay shape).
30
+ - Before staging, the seam's `hasRunner` is checked (P2-7, v15): with approval enabled, a session policy that is not `never`, and the write actually staging (foreground stages per approval `stageForeground`; subagent origins always stage), a missing replay runner's row (tool-skill-manage / tool-memory) refuses the write; allow-direct combinations execute unchanged instead of creating a pending record no approver could replay.
31
+ - The command invocation's session rides the approval request (v12 N1), so a `never`-policy session stages nothing instead of deriving every graph write as foreground.
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { effectiveSessionPolicy } from "@lmzhen/dsh-evolution-approval";
2
2
  import z from "@deepseek-ai/schemastery";
3
- import { SKILL_NAME_RE, contentHash, evolutionIoAdapter, newSkillLibrary, relatedSkillNames, resolveOrigins } from "@lmzhen/dsh-evolution-core";
3
+ import { SKILL_NAME_RE, contentHash, evolutionIoAdapter, newSkillLibrary, relatedSkillNames, resolveExecOrigins } from "@lmzhen/dsh-evolution-core";
4
4
  //#region lib/types/index.js
5
5
  /**
6
6
  * Learning graph over skills and memory, plus node-level commands
@@ -243,12 +243,16 @@ function apply(ctx, rawConfig = {}) {
243
243
  const usage = usageService;
244
244
  const memory = memoryService;
245
245
  const io = ioService;
246
- const session = invocation.agent.session;
246
+ const invocationAgent = invocation.agent;
247
+ const session = invocationAgent?.session;
248
+ const sessionMissing = (need) => session === void 0 ? err(`E-305: this invocation carries no agent — \`${need}\` needs a session-backed call (run it from a session in the GUI or the CLI).`) : void 0;
247
249
  const input = invocation.rawInput.trim();
248
250
  const detail = /^detail\s+(\S+)$/.exec(input);
249
251
  if (detail && detail[1]) return await nodeDetail(detail[1]);
250
252
  const edit = /^edit\s+(\S+)\s+([\s\S]+)$/.exec(input);
251
253
  if (edit && edit[1] && edit[2] !== void 0) {
254
+ const gated = sessionMissing("/graph edit");
255
+ if (gated) return gated;
252
256
  if (!edit[1].startsWith("memory:")) {
253
257
  const stageRead = await probeSkillForStaging(edit[1]);
254
258
  if (stageRead !== null) return err(stageRead);
@@ -257,6 +261,8 @@ function apply(ctx, rawConfig = {}) {
257
261
  }
258
262
  const remove = /^delete\s+(\S+)$/.exec(input);
259
263
  if (remove && remove[1]) {
264
+ const gated = sessionMissing("/graph delete");
265
+ if (gated) return gated;
260
266
  if (!remove[1].startsWith("memory:")) {
261
267
  const stageRead = await probeSkillForStaging(remove[1]);
262
268
  if (stageRead !== null) return err(stageRead);
@@ -333,7 +339,7 @@ function apply(ctx, rawConfig = {}) {
333
339
  if (parsed === null) return err(`Invalid node id "${id}". Skill names or memory:<source>:<index> expected.`);
334
340
  if (parsed.kind === "skill") {
335
341
  const approval = ctx.get("evolutionApproval");
336
- const origins = resolveOrigins(session.header.origin);
342
+ const origins = resolveExecOrigins(invocationAgent && { agent: invocationAgent });
337
343
  if (approval) {
338
344
  const sessionPolicyEdit = effectiveSessionPolicy(ctx, session);
339
345
  const stagesForeground = approval.stageForeground !== false;
@@ -354,7 +360,7 @@ function apply(ctx, rawConfig = {}) {
354
360
  libraryOrigin: origins.library
355
361
  },
356
362
  origin: origins.approval,
357
- ...session.id ? { sessionId: session.id } : {},
363
+ ...session?.id ? { sessionId: session.id } : {},
358
364
  session,
359
365
  ...sessionPolicy !== void 0 ? { sessionPolicy } : {}
360
366
  });
@@ -368,7 +374,7 @@ function apply(ctx, rawConfig = {}) {
368
374
  if (!check.ok) return err(check.message ?? "Memory index check failed.");
369
375
  const memoryApproval = ctx.get("evolutionApproval");
370
376
  if (memoryApproval) {
371
- const originsM = resolveOrigins(session.header.origin);
377
+ const originsM = resolveExecOrigins(invocationAgent && { agent: invocationAgent });
372
378
  const sessionPolicyM = effectiveSessionPolicy(ctx, session);
373
379
  if (memoryApproval.isEnabled !== false && sessionPolicyM !== "never" && (originsM.approval === "background_review" || memoryApproval.stageForeground !== false) && !memoryApproval.hasRunner("memory")) return err("Graph memory write cannot be staged: no memory replay runner is registered — mount the tool-memory row (evolution-all bundle, or the evolution-preset overlay; the host bundle does not carry it) or disable evolution-approval.");
374
380
  const decision = await memoryApproval.request({
@@ -383,7 +389,7 @@ function apply(ctx, rawConfig = {}) {
383
389
  }]
384
390
  },
385
391
  origin: originsM.approval,
386
- ...session.id ? { sessionId: session.id } : {},
392
+ ...session?.id ? { sessionId: session.id } : {},
387
393
  session,
388
394
  ...sessionPolicyM !== void 0 ? { sessionPolicy: sessionPolicyM } : {}
389
395
  });
@@ -402,7 +408,7 @@ function apply(ctx, rawConfig = {}) {
402
408
  if (parsed.kind === "skill") {
403
409
  const approval = ctx.get("evolutionApproval");
404
410
  if (approval) {
405
- const origins = resolveOrigins(session.header.origin);
411
+ const origins = resolveExecOrigins(invocationAgent && { agent: invocationAgent });
406
412
  const sessionPolicy = effectiveSessionPolicy(ctx, session);
407
413
  if (approval.isEnabled !== false && sessionPolicy !== "never" && (origins.approval === "background_review" || approval.stageForeground !== false) && !approval.hasRunner("skill")) return err("Graph skill delete cannot be staged: no skill replay runner is registered — mount the tool-skill-manage row (evolution-agent preset) or disable evolution-approval.");
408
414
  const decision = await approval.request({
@@ -417,7 +423,7 @@ function apply(ctx, rawConfig = {}) {
417
423
  libraryOrigin: origins.library
418
424
  },
419
425
  origin: origins.approval,
420
- ...session.id ? { sessionId: session.id } : {},
426
+ ...session?.id ? { sessionId: session.id } : {},
421
427
  session,
422
428
  ...sessionPolicy !== void 0 ? { sessionPolicy } : {}
423
429
  });
@@ -431,7 +437,7 @@ function apply(ctx, rawConfig = {}) {
431
437
  if (!check.ok) return err(check.message ?? "Memory index check failed.");
432
438
  const memoryApproval = ctx.get("evolutionApproval");
433
439
  if (memoryApproval) {
434
- const origins = resolveOrigins(session.header.origin);
440
+ const origins = resolveExecOrigins(invocationAgent && { agent: invocationAgent });
435
441
  const sessionPolicy = effectiveSessionPolicy(ctx, session);
436
442
  if (memoryApproval.isEnabled !== false && sessionPolicy !== "never" && (origins.approval === "background_review" || memoryApproval.stageForeground !== false) && !memoryApproval.hasRunner("memory")) return err("Graph memory delete cannot be staged: no memory replay runner is registered — mount the tool-memory row (evolution-all bundle, or the evolution-preset overlay; the host bundle does not carry it) or disable evolution-approval.");
437
443
  const decision = await memoryApproval.request({
@@ -445,7 +451,7 @@ function apply(ctx, rawConfig = {}) {
445
451
  }]
446
452
  },
447
453
  origin: origins.approval,
448
- ...session.id ? { sessionId: session.id } : {},
454
+ ...session?.id ? { sessionId: session.id } : {},
449
455
  session,
450
456
  ...sessionPolicy !== void 0 ? { sessionPolicy } : {}
451
457
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-evolution-learning-graph",
3
3
  "description": "Learning graph over skills and memory (community build)",
4
- "version": "0.3.83",
4
+ "version": "0.4.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,8 +27,8 @@
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
29
  "@deepseek-ai/schemastery": "^3.18.1",
30
- "@lmzhen/dsh-evolution-approval": "^0.3.83",
31
- "@lmzhen/dsh-evolution-core": "^0.3.83"
30
+ "@lmzhen/dsh-evolution-approval": "^0.4.1",
31
+ "@lmzhen/dsh-evolution-core": "^0.4.1"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "@deepseek-ai/dsh-commands": "^0.1.5-rc.2",