@lmzhen/dsh-evolution-learning-graph 0.3.62 → 0.3.64
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 +1 -1
- package/lib/index.js +62 -12
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ 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`
|
|
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.
|
|
14
14
|
|
|
15
15
|
## Model Experience
|
|
16
16
|
|
package/lib/index.js
CHANGED
|
@@ -183,14 +183,13 @@ async function resolveGraphNode(parsed, repository) {
|
|
|
183
183
|
message: content
|
|
184
184
|
};
|
|
185
185
|
}
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
return entry === void 0 ? {
|
|
189
|
-
ok: false,
|
|
190
|
-
message: `Memory ${parsed.source}[${parsed.index}] does not exist (${entries.length} entries).`
|
|
191
|
-
} : {
|
|
186
|
+
const check = readMemoryIndex(parsed, await repository.readMemory(parsed.source));
|
|
187
|
+
return check.ok ? {
|
|
192
188
|
ok: true,
|
|
193
|
-
message: entry
|
|
189
|
+
message: check.entry ?? ""
|
|
190
|
+
} : {
|
|
191
|
+
ok: false,
|
|
192
|
+
message: check.message ?? `Memory ${parsed.source}[${parsed.index}] is not available.`
|
|
194
193
|
};
|
|
195
194
|
}
|
|
196
195
|
/**
|
|
@@ -255,12 +254,14 @@ function apply(ctx, rawConfig = {}) {
|
|
|
255
254
|
const memoryEntries = await memory.read("memory");
|
|
256
255
|
const userEntries = await memory.read("user");
|
|
257
256
|
const skills = withSkills();
|
|
257
|
+
const names = [...usageMap.keys()];
|
|
258
|
+
const contents = await Promise.all(names.map((name) => skills.read(name)));
|
|
258
259
|
const related = /* @__PURE__ */ new Map();
|
|
259
|
-
|
|
260
|
-
const content =
|
|
261
|
-
if (content === null)
|
|
260
|
+
names.forEach((name, index) => {
|
|
261
|
+
const content = contents[index];
|
|
262
|
+
if (content === null || content === void 0) return;
|
|
262
263
|
related.set(name, relatedSkillNames(content, name));
|
|
263
|
-
}
|
|
264
|
+
});
|
|
264
265
|
const graph = buildLearningGraph(usageMap, memoryEntries, userEntries, related);
|
|
265
266
|
const nodeBlock = capRenderedLines(graph.nodes.map((node) => renderNodeLine(node)));
|
|
266
267
|
const edgeBlock = capRenderedLines(graph.edges.map((edge) => edge.from + " --" + edge.type + "--> " + edge.to));
|
|
@@ -289,7 +290,10 @@ function apply(ctx, rawConfig = {}) {
|
|
|
289
290
|
const approval = ctx.get("evolutionApproval");
|
|
290
291
|
const origins = resolveOrigins(session?.header?.origin);
|
|
291
292
|
if (approval) {
|
|
292
|
-
const
|
|
293
|
+
const sessionPolicyEdit = effectiveSessionPolicy(ctx, session);
|
|
294
|
+
const stagesForeground = approval.stageForeground !== false;
|
|
295
|
+
if (approval.isEnabled !== false && sessionPolicyEdit !== "never" && (origins.approval === "background_review" || stagesForeground) && !approval.hasRunner("skill")) return err("Graph skill write cannot be staged: no skill replay runner is registered — mount the tool-skill-manage row (evolution-agent preset) or disable evolution-approval.");
|
|
296
|
+
const sessionPolicy = sessionPolicyEdit;
|
|
293
297
|
const decision = await approval.request({
|
|
294
298
|
kind: "skill",
|
|
295
299
|
summary: `graph edit ${parsed.name}`,
|
|
@@ -315,6 +319,29 @@ function apply(ctx, rawConfig = {}) {
|
|
|
315
319
|
}
|
|
316
320
|
const check = readMemoryIndex(parsed, await memory.read(parsed.source));
|
|
317
321
|
if (!check.ok) return err(check.message ?? "Memory index check failed.");
|
|
322
|
+
const memoryApproval = ctx.get("evolutionApproval");
|
|
323
|
+
if (memoryApproval) {
|
|
324
|
+
const originsM = resolveOrigins(session?.header?.origin);
|
|
325
|
+
const sessionPolicyM = effectiveSessionPolicy(ctx, session);
|
|
326
|
+
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-host/evolution-all bundle) or disable evolution-approval.");
|
|
327
|
+
const decision = await memoryApproval.request({
|
|
328
|
+
kind: "memory",
|
|
329
|
+
summary: `graph edit memory:${parsed.source}:${parsed.index}`,
|
|
330
|
+
args: {
|
|
331
|
+
target: parsed.source,
|
|
332
|
+
operations: [{
|
|
333
|
+
action: "replace",
|
|
334
|
+
old_text: check.entry ?? "",
|
|
335
|
+
facts: content
|
|
336
|
+
}]
|
|
337
|
+
},
|
|
338
|
+
origin: originsM.approval,
|
|
339
|
+
...session?.id ? { sessionId: session.id } : {},
|
|
340
|
+
...session ? { session } : {},
|
|
341
|
+
...sessionPolicyM !== void 0 ? { sessionPolicy: sessionPolicyM } : {}
|
|
342
|
+
});
|
|
343
|
+
if (decision.action === "staged") return ok(decision.message);
|
|
344
|
+
}
|
|
318
345
|
const result = await memory.applyBatch(parsed.source, [{
|
|
319
346
|
action: "replace",
|
|
320
347
|
old_text: check.entry ?? "",
|
|
@@ -330,6 +357,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
330
357
|
if (approval) {
|
|
331
358
|
const origins = resolveOrigins(session?.header?.origin);
|
|
332
359
|
const sessionPolicy = effectiveSessionPolicy(ctx, session);
|
|
360
|
+
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.");
|
|
333
361
|
const decision = await approval.request({
|
|
334
362
|
kind: "skill",
|
|
335
363
|
summary: `graph delete ${parsed.name}`,
|
|
@@ -354,6 +382,28 @@ function apply(ctx, rawConfig = {}) {
|
|
|
354
382
|
}
|
|
355
383
|
const check = readMemoryIndex(parsed, await memory.read(parsed.source));
|
|
356
384
|
if (!check.ok) return err(check.message ?? "Memory index check failed.");
|
|
385
|
+
const memoryApproval = ctx.get("evolutionApproval");
|
|
386
|
+
if (memoryApproval) {
|
|
387
|
+
const origins = resolveOrigins(session?.header?.origin);
|
|
388
|
+
const sessionPolicy = effectiveSessionPolicy(ctx, session);
|
|
389
|
+
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-host/evolution-all bundle) or disable evolution-approval.");
|
|
390
|
+
const decision = await memoryApproval.request({
|
|
391
|
+
kind: "memory",
|
|
392
|
+
summary: `graph delete memory:${parsed.source}:${parsed.index}`,
|
|
393
|
+
args: {
|
|
394
|
+
target: parsed.source,
|
|
395
|
+
operations: [{
|
|
396
|
+
action: "remove",
|
|
397
|
+
old_text: check.entry ?? ""
|
|
398
|
+
}]
|
|
399
|
+
},
|
|
400
|
+
origin: origins.approval,
|
|
401
|
+
...session?.id ? { sessionId: session.id } : {},
|
|
402
|
+
...session ? { session } : {},
|
|
403
|
+
...sessionPolicy !== void 0 ? { sessionPolicy } : {}
|
|
404
|
+
});
|
|
405
|
+
if (decision.action === "staged") return ok(decision.message);
|
|
406
|
+
}
|
|
357
407
|
const result = await memory.applyBatch(parsed.source, [{
|
|
358
408
|
action: "remove",
|
|
359
409
|
old_text: check.entry ?? ""
|
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.
|
|
4
|
+
"version": "0.3.64",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
34
|
-
"@lmzhen/dsh-evolution-approval": "^0.3.
|
|
35
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
34
|
+
"@lmzhen/dsh-evolution-approval": "^0.3.64",
|
|
35
|
+
"@lmzhen/dsh-evolution-core": "^0.3.64"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|