@lmzhen/dsh-evolution-maintenance 0.26.15 → 0.27.0
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 +180 -57
- package/lib/tools.js +2 -1
- package/lib/types/footprint.d.ts +30 -0
- package/lib/types/orchestrate.d.ts +19 -43
- package/lib/types/render-facts.d.ts +16 -0
- package/package.json +11 -8
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { a as snapshotFromLibrary, i as enrichmentSnapshotOptions, n as computeProbe, r as buildEnrichment, t as PROBE_SIGNALS } from "./probe-Bojb0piw.js";
|
|
2
|
-
import { AUTHORING_DESCRIPTION_BAR, DEFAULT_CURATOR_MODEL, DEFAULT_HEALTH_THRESHOLDS, DRIFT_MAX_LINE_CHARS, DRIFT_SIGNALS_VERSION, DRIFT_SIGNAL_NOUNS, LOW_QUALITY_THRESHOLD, MAINTAIN_OUTPUT_INSTRUCTION, MAINTAIN_PROMPT, MAX_TIMER_DELAY_MS, MIN_STAMP_BODY_CHARS, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, computeDriftSignals, findDriftSignal, isRecord, redactSecrets, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
|
|
2
|
+
import { AUTHORING_DESCRIPTION_BAR, DEFAULT_CURATOR_MODEL, DEFAULT_HEALTH_THRESHOLDS, DRIFT_MAX_LINE_CHARS, DRIFT_SIGNALS_VERSION, DRIFT_SIGNAL_NOUNS, LOW_QUALITY_THRESHOLD, MAINTAIN_OUTPUT_INSTRUCTION, MAINTAIN_PROMPT, MAX_TIMER_DELAY_MS, MIN_STAMP_BODY_CHARS, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, STORE_LEDGER, computeDriftSignals, evolutionHome, findDriftSignal, isRecord, redactSecrets, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
|
+
import { join } from "node:path";
|
|
4
5
|
//#region lib/types/render-facts.js
|
|
5
6
|
/**
|
|
6
7
|
* Mechanical-facts rendering for the maintenance subagent (011 §6).
|
|
@@ -23,6 +24,19 @@ function renderFacts(report, options) {
|
|
|
23
24
|
lines.push(`# skill=${sanitize(skill.name)} (${meta.join(" ")})`);
|
|
24
25
|
for (const signal of skill.signals) lines.push(...renderSignal(signal, redact));
|
|
25
26
|
}
|
|
27
|
+
for (const store of options.footprint ?? []) {
|
|
28
|
+
const parts = [
|
|
29
|
+
`${store.used === void 0 || store.skipped !== void 0 ? "[UNKNOWN]" : "[FACT]"} signal=store/${sanitize(store.id)}`,
|
|
30
|
+
`unit=${sanitize(store.unit)}`,
|
|
31
|
+
`bound=${sanitize(store.bound)}`,
|
|
32
|
+
`used=${store.used === void 0 ? "unknown" : String(store.used)}`,
|
|
33
|
+
`lastSweep=${sanitize(store.lastSweep ?? "never")}`,
|
|
34
|
+
`removed=${store.removed === void 0 ? "unknown" : String(store.removed)}`
|
|
35
|
+
];
|
|
36
|
+
if (store.skipped !== void 0) parts.push(`skipped=${sanitize(store.skipped)}`);
|
|
37
|
+
parts.push(`verdict=${store.used === void 0 || store.skipped !== void 0 ? "unknown" : "fact"}`);
|
|
38
|
+
lines.push(parts.join(" "));
|
|
39
|
+
}
|
|
26
40
|
lines.push("<<<END FACTS>>>");
|
|
27
41
|
return lines.join("\n");
|
|
28
42
|
}
|
|
@@ -285,6 +299,124 @@ function validateAndNormalizeMaintainPlan(raw, report, validSignals) {
|
|
|
285
299
|
};
|
|
286
300
|
}
|
|
287
301
|
//#endregion
|
|
302
|
+
//#region lib/types/footprint.js
|
|
303
|
+
/**
|
|
304
|
+
* G3/3.3: the footprint reading for one maintenance run.
|
|
305
|
+
*
|
|
306
|
+
* One line per REGISTERED store (STORE_LEDGER), never a line per store that happened to be readable: the
|
|
307
|
+
* auditor must be able to tell "measured zero" from "not measured" (I3: not-done must never read as
|
|
308
|
+
* nothing-to-do). This first cut reads the stores whose artifact needs only the home-relative path the
|
|
309
|
+
* runtime already knows; everything else renders UNKNOWN with the reason, so the block is honest today
|
|
310
|
+
* and becomes informative as each reader lands.
|
|
311
|
+
*/
|
|
312
|
+
/**
|
|
313
|
+
* Read what can be read, and say so for everything else.
|
|
314
|
+
* @param io - the runtime io, or undefined when the caller has none (every store then reads UNKNOWN).
|
|
315
|
+
* @returns one reading per registered store, in ledger order.
|
|
316
|
+
*/
|
|
317
|
+
async function reclamationFootprint(io) {
|
|
318
|
+
const out = [];
|
|
319
|
+
for (const store of STORE_LEDGER) {
|
|
320
|
+
if (io === void 0) {
|
|
321
|
+
out.push({
|
|
322
|
+
id: store.id,
|
|
323
|
+
unit: store.unit,
|
|
324
|
+
bound: store.bound,
|
|
325
|
+
skipped: "the maintenance runtime has no io; nothing was measured"
|
|
326
|
+
});
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
if (store.id === "reports") {
|
|
330
|
+
try {
|
|
331
|
+
const names = await io.list(join(evolutionHome(), "reports"));
|
|
332
|
+
out.push({
|
|
333
|
+
id: store.id,
|
|
334
|
+
unit: store.unit,
|
|
335
|
+
bound: store.bound,
|
|
336
|
+
used: names.length,
|
|
337
|
+
lastSweep: "see the curator run end",
|
|
338
|
+
removed: void 0
|
|
339
|
+
});
|
|
340
|
+
} catch {
|
|
341
|
+
out.push({
|
|
342
|
+
id: store.id,
|
|
343
|
+
unit: store.unit,
|
|
344
|
+
bound: store.bound,
|
|
345
|
+
skipped: "the reports directory could not be listed"
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
out.push({
|
|
351
|
+
id: store.id,
|
|
352
|
+
unit: store.unit,
|
|
353
|
+
bound: store.bound,
|
|
354
|
+
skipped: "no reader yet for this store"
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
return out;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* G3/3.4: the three reachability readings, folded into the footprint channel so the report has ONE shape.
|
|
361
|
+
*
|
|
362
|
+
* Paths come from the caller: the history root and the snapshot root live under the skills root, and the
|
|
363
|
+
* reports directory under the evolution home. A runtime that does not state its skills root gets UNKNOWN
|
|
364
|
+
* for the two rooted domains instead of a guess - the same three-state rule the rest of this file uses.
|
|
365
|
+
* @param io - the runtime io, or undefined when the caller has none.
|
|
366
|
+
* @param skillRoot - the configured skills root, or undefined when the runtime does not state one.
|
|
367
|
+
*/
|
|
368
|
+
async function reachabilityFootprint(io, skillRoot) {
|
|
369
|
+
const domains = [
|
|
370
|
+
"history.blobs",
|
|
371
|
+
"reports.files",
|
|
372
|
+
"backups.trees"
|
|
373
|
+
];
|
|
374
|
+
if (io === void 0) return domains.map((domain) => ({
|
|
375
|
+
id: domain,
|
|
376
|
+
unit: "files",
|
|
377
|
+
bound: "unmeasured",
|
|
378
|
+
skipped: "the maintenance runtime has no io; nothing was measured"
|
|
379
|
+
}));
|
|
380
|
+
const { historyReachability, reportsReachability, backupsReachability } = await import("@lmzhen/dsh-evolution-core");
|
|
381
|
+
const out = [];
|
|
382
|
+
if (skillRoot === void 0) for (const domain of ["history.blobs", "backups.trees"]) out.push({
|
|
383
|
+
id: domain,
|
|
384
|
+
unit: "files",
|
|
385
|
+
bound: "unmeasured",
|
|
386
|
+
skipped: "the runtime states no skills root; the reading was not attempted"
|
|
387
|
+
});
|
|
388
|
+
else {
|
|
389
|
+
const history = await historyReachability(io, join(skillRoot, ".history"));
|
|
390
|
+
out.push({
|
|
391
|
+
id: history.domain,
|
|
392
|
+
unit: history.unit,
|
|
393
|
+
bound: history.baseline,
|
|
394
|
+
used: history.unreachable,
|
|
395
|
+
lastSweep: "this run",
|
|
396
|
+
removed: void 0
|
|
397
|
+
});
|
|
398
|
+
const backups = await backupsReachability(io, join(skillRoot, ".backups"), []);
|
|
399
|
+
out.push({
|
|
400
|
+
id: backups.domain,
|
|
401
|
+
unit: backups.unit,
|
|
402
|
+
bound: backups.baseline,
|
|
403
|
+
used: backups.unreachable,
|
|
404
|
+
lastSweep: "this run",
|
|
405
|
+
removed: void 0
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
const reports = await reportsReachability(io, join(evolutionHome(), "reports"), [], []);
|
|
409
|
+
out.push({
|
|
410
|
+
id: reports.domain,
|
|
411
|
+
unit: reports.unit,
|
|
412
|
+
bound: reports.baseline,
|
|
413
|
+
used: reports.unreachable,
|
|
414
|
+
lastSweep: "this run",
|
|
415
|
+
removed: void 0
|
|
416
|
+
});
|
|
417
|
+
return out;
|
|
418
|
+
}
|
|
419
|
+
//#endregion
|
|
288
420
|
//#region lib/types/orchestrate.js
|
|
289
421
|
/**
|
|
290
422
|
* Maintain orchestration (011 §3/§7): snapshot → drift signals → facts
|
|
@@ -336,7 +468,7 @@ function jointSignature(template, signalsVersion) {
|
|
|
336
468
|
* rendered facts block (joint signature + redaction). Shared by `runMaintain`
|
|
337
469
|
* and the `--facts` preview so the preview can never disagree with the scan.
|
|
338
470
|
*/
|
|
339
|
-
function buildMaintainFacts(snapshots, usageObserved, redact) {
|
|
471
|
+
function buildMaintainFacts(snapshots, usageObserved, redact, footprint) {
|
|
340
472
|
const report = computeDriftSignals(snapshots.map((snapshot) => ({
|
|
341
473
|
...snapshot,
|
|
342
474
|
usageObserved
|
|
@@ -348,7 +480,8 @@ function buildMaintainFacts(snapshots, usageObserved, redact) {
|
|
|
348
480
|
facts: renderFacts(report, {
|
|
349
481
|
signalsVersion,
|
|
350
482
|
signature,
|
|
351
|
-
redact
|
|
483
|
+
redact,
|
|
484
|
+
footprint
|
|
352
485
|
}),
|
|
353
486
|
signalsVersion,
|
|
354
487
|
signature
|
|
@@ -395,7 +528,6 @@ function formatPlan(validated, runId) {
|
|
|
395
528
|
}
|
|
396
529
|
/** Run one maintenance scan and return display text plus validation metadata. */
|
|
397
530
|
async function runMaintain(runtime, options = {}) {
|
|
398
|
-
let abortSignal;
|
|
399
531
|
try {
|
|
400
532
|
if (!verifyPromptBundle(PROMPT_BUNDLE)) return {
|
|
401
533
|
ok: false,
|
|
@@ -430,7 +562,8 @@ async function runMaintain(runtime, options = {}) {
|
|
|
430
562
|
text: "维护扫描:技能库为空,无需处理。"
|
|
431
563
|
};
|
|
432
564
|
}
|
|
433
|
-
const
|
|
565
|
+
const footprint = [...await reclamationFootprint(runtime.io), ...await reachabilityFootprint(runtime.io, runtime.skillRoot)];
|
|
566
|
+
const { facts, report, signalsVersion, signature } = buildMaintainFacts(snapshots, enrichment?.usageObservedValue, options.redact, footprint);
|
|
434
567
|
const template = renderMaintainTemplate(MAINTAIN_PROMPT, PROMPT_BUNDLE_ID, signalsVersion, signature);
|
|
435
568
|
const probeRegistered = runtime.tools?.get("maintenance_probe") != null;
|
|
436
569
|
const probeDegraded = options.toolAllow === void 0 && !probeRegistered;
|
|
@@ -444,22 +577,18 @@ ${MAINTAIN_OUTPUT_INSTRUCTION}`;
|
|
|
444
577
|
recommendationCount: 0,
|
|
445
578
|
error: `maintain:--timeout 必须是以毫秒为单位的正整数,最大 ${MAX_TIMER_DELAY_MS};收到 ${String(timeoutMs)}`
|
|
446
579
|
};
|
|
447
|
-
const signal = options.signal !== void 0 ? AbortSignal.any([AbortSignal.timeout(timeoutMs), options.signal]) : AbortSignal.timeout(timeoutMs);
|
|
448
|
-
abortSignal = signal;
|
|
449
580
|
const agentOptions = { model: options.model ?? runtime.evolutionPolicy?.get()?.curatorModel ?? DEFAULT_CURATOR_MODEL };
|
|
450
581
|
if (options.provider) agentOptions.provider = options.provider;
|
|
451
|
-
const
|
|
452
|
-
label: "dsh-evolution-maintain",
|
|
453
|
-
prompt: [{
|
|
454
|
-
type: "text",
|
|
455
|
-
text: prompt
|
|
456
|
-
}],
|
|
582
|
+
const outcome = await runtime.channel.run({
|
|
457
583
|
parent: runtime.parent,
|
|
458
|
-
|
|
584
|
+
label: "dsh-evolution-maintain",
|
|
585
|
+
promptText: template + "\n\n" + prompt,
|
|
586
|
+
kind: "maintainer",
|
|
587
|
+
allow: [...toolAllow],
|
|
459
588
|
maxDepth: typeof options.maxDepth === "number" && Number.isFinite(options.maxDepth) && options.maxDepth >= 1 ? options.maxDepth : 1,
|
|
460
589
|
agentOptions,
|
|
461
|
-
|
|
462
|
-
|
|
590
|
+
timeoutMs,
|
|
591
|
+
...options.signal === void 0 ? {} : { signal: options.signal },
|
|
463
592
|
outputSchema: {
|
|
464
593
|
type: "object",
|
|
465
594
|
additionalProperties: false,
|
|
@@ -530,53 +659,47 @@ ${MAINTAIN_OUTPUT_INSTRUCTION}`;
|
|
|
530
659
|
}
|
|
531
660
|
}
|
|
532
661
|
});
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
try {
|
|
568
|
-
await run.dispose();
|
|
569
|
-
} catch (disposeError) {
|
|
570
|
-
runtime.logger?.warn(`dsh-evolution-maintenance: subagent dispose failed: ${disposeError instanceof Error ? disposeError.message : String(disposeError)}`);
|
|
571
|
-
}
|
|
572
|
-
}
|
|
662
|
+
if (outcome.kind === "unavailable") return {
|
|
663
|
+
ok: false,
|
|
664
|
+
recommendationCount: 0,
|
|
665
|
+
error: `维护扫描不可用(${outcome.code}):${outcome.reason}。请在已挂载 agentPresets/subagents 的宿主会话中重试。`
|
|
666
|
+
};
|
|
667
|
+
if (outcome.kind === "aborted") return {
|
|
668
|
+
ok: false,
|
|
669
|
+
recommendationCount: 0,
|
|
670
|
+
error: "维护扫描已中止(取消或超时),计划尚未产出 —— 在技能多、库大的场景下,请重试或提高超时(evolution-commands maintainTimeoutMs)。"
|
|
671
|
+
};
|
|
672
|
+
if (outcome.kind === "no-structured") return {
|
|
673
|
+
ok: false,
|
|
674
|
+
recommendationCount: 0,
|
|
675
|
+
error: "维护子智能体没有返回结构化计划(模型没有产出结构化计划,或运行在产出前结束):请重试;若反复出现,请提高 --timeout 或检查模型的输出结构。"
|
|
676
|
+
};
|
|
677
|
+
const raw = outcome.structured;
|
|
678
|
+
const validated = validateAndNormalizeMaintainPlan(raw, report, existingSignalIds(report));
|
|
679
|
+
if (!validated.ok) return {
|
|
680
|
+
ok: false,
|
|
681
|
+
recommendationCount: 0,
|
|
682
|
+
error: `维护计划被校验器拒绝:${validated.errors.slice(0, 5).join("; ")}`
|
|
683
|
+
};
|
|
684
|
+
const runId = options.runId ?? randomUUID();
|
|
685
|
+
return {
|
|
686
|
+
ok: true,
|
|
687
|
+
runId,
|
|
688
|
+
verdict: validated.plan.verdict,
|
|
689
|
+
forcedHuman: validated.forcedHuman,
|
|
690
|
+
items: validated.plan.plan,
|
|
691
|
+
notes: validated.plan.notes,
|
|
692
|
+
needsHumanCount: validated.plan.plan.filter((item) => item.needs_human).length,
|
|
693
|
+
recommendationCount: validated.plan.plan.length,
|
|
694
|
+
text: formatPlan(validated, runId)
|
|
695
|
+
};
|
|
573
696
|
} catch (error) {
|
|
574
697
|
const name = typeof error === "object" && error !== null ? error.name : void 0;
|
|
575
698
|
const message = error instanceof Error ? error.message : String(error);
|
|
576
699
|
return {
|
|
577
700
|
ok: false,
|
|
578
701
|
recommendationCount: 0,
|
|
579
|
-
error:
|
|
702
|
+
error: options.signal?.aborted === true || name === "AbortError" || message === "This operation was aborted" ? "维护扫描已中止(取消或超时),计划尚未产出 —— 在技能多、库大的场景下,请重试或提高超时(evolution-commands maintainTimeoutMs)。" : `Maintenance scan failed: ${message}`
|
|
580
703
|
};
|
|
581
704
|
}
|
|
582
705
|
}
|
package/lib/tools.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as snapshotFromLibrary, i as enrichmentSnapshotOptions, n as computeProbe, r as buildEnrichment, t as PROBE_SIGNALS } from "./probe-Bojb0piw.js";
|
|
2
|
-
import { DEFAULT_PROBE_TIMEOUT_MS, MAX_TIMER_DELAY_MS, assertSkillsRootAliasRetired, clampedNumber, newSkillLibrary, redactSecrets, resolveRootConfig } from "@lmzhen/dsh-evolution-core";
|
|
2
|
+
import { DEFAULT_PROBE_TIMEOUT_MS, MAX_TIMER_DELAY_MS, assertSkillsRootAliasRetired, authorityFrom, clampedNumber, newSkillLibrary, redactSecrets, resolveRootConfig } from "@lmzhen/dsh-evolution-core";
|
|
3
3
|
import z from "@deepseek-ai/schemastery";
|
|
4
4
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
5
5
|
//#region lib/types/tools.js
|
|
@@ -69,6 +69,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
69
69
|
...target ? { target } : {}
|
|
70
70
|
};
|
|
71
71
|
const library = newSkillLibrary({
|
|
72
|
+
authority: authorityFrom({ origin: "foreground" }),
|
|
72
73
|
config: rootConfig,
|
|
73
74
|
io: ioRegistry.provider()
|
|
74
75
|
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { StoreFootprint } from './render-facts.ts';
|
|
2
|
+
import type { ReachabilityIo } from '@lmzhen/dsh-evolution-core';
|
|
3
|
+
/**
|
|
4
|
+
* The io surface this reading needs; a runtime without it yields UNKNOWN for every store.
|
|
5
|
+
*
|
|
6
|
+
* It EXTENDS the reachability read surface instead of restating it: this module drives those readings,
|
|
7
|
+
* so the reads they need are the reads it needs. Restating them here is what produced the same
|
|
8
|
+
* "argument not assignable" error three times - the surface now has ONE owner (`ReachabilityIo`) and this
|
|
9
|
+
* adds only the probe the report sweep uses on top.
|
|
10
|
+
*/
|
|
11
|
+
export interface FootprintIo extends ReachabilityIo {
|
|
12
|
+
mtime?(path: string): Promise<number | null>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Read what can be read, and say so for everything else.
|
|
16
|
+
* @param io - the runtime io, or undefined when the caller has none (every store then reads UNKNOWN).
|
|
17
|
+
* @returns one reading per registered store, in ledger order.
|
|
18
|
+
*/
|
|
19
|
+
export declare function reclamationFootprint(io: FootprintIo | undefined): Promise<StoreFootprint[]>;
|
|
20
|
+
/**
|
|
21
|
+
* G3/3.4: the three reachability readings, folded into the footprint channel so the report has ONE shape.
|
|
22
|
+
*
|
|
23
|
+
* Paths come from the caller: the history root and the snapshot root live under the skills root, and the
|
|
24
|
+
* reports directory under the evolution home. A runtime that does not state its skills root gets UNKNOWN
|
|
25
|
+
* for the two rooted domains instead of a guess - the same three-state rule the rest of this file uses.
|
|
26
|
+
* @param io - the runtime io, or undefined when the caller has none.
|
|
27
|
+
* @param skillRoot - the configured skills root, or undefined when the runtime does not state one.
|
|
28
|
+
*/
|
|
29
|
+
export declare function reachabilityFootprint(io: FootprintIo | undefined, skillRoot: string | undefined): Promise<StoreFootprint[]>;
|
|
30
|
+
//# sourceMappingURL=footprint.d.ts.map
|
|
@@ -6,54 +6,24 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { type DriftReport, type DriftSkillSnapshot } from '@lmzhen/dsh-evolution-core';
|
|
8
8
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
9
|
+
import type { SubagentChannel } from '@lmzhen/dsh-evolution-core';
|
|
9
10
|
import { type SkillLibraryLike } from './drift-scan.ts';
|
|
10
11
|
import { type Enrichment } from './enrichment.ts';
|
|
12
|
+
import { type StoreFootprint } from './render-facts.ts';
|
|
13
|
+
import { type FootprintIo } from './footprint.ts';
|
|
11
14
|
import { type MaintainPlanItem } from './validate-plan.ts';
|
|
12
|
-
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
readonly prompt: readonly {
|
|
18
|
-
readonly type: 'text';
|
|
19
|
-
readonly text: string;
|
|
20
|
-
}[];
|
|
21
|
-
readonly parent: Agent;
|
|
22
|
-
readonly signal: AbortSignal;
|
|
23
|
-
readonly maxDepth: number;
|
|
24
|
-
readonly agentOptions: Record<string, string>;
|
|
25
|
-
readonly persona: string;
|
|
26
|
-
readonly toolFilter: {
|
|
27
|
-
readonly allow: readonly string[];
|
|
28
|
-
};
|
|
29
|
-
readonly outputSchema: Record<string, unknown>;
|
|
30
|
-
}
|
|
31
|
-
/** I-5 (v37): the platform's `SubagentResult` fields the outcome mapping reads. The
|
|
32
|
-
* index signature keeps a REAL platform result assignable (the platform type is
|
|
33
|
-
* wider than these three fields); the fields below are the ones this code relies on. */
|
|
34
|
-
export interface SubagentResultLike {
|
|
35
|
-
readonly structured?: unknown;
|
|
36
|
-
readonly diagnostic?: string;
|
|
37
|
-
readonly stopReason: string;
|
|
38
|
-
}
|
|
39
|
-
/** I-5 (v37): the platform's `SubagentRun` contract the orchestrator owns — `dispose` is
|
|
40
|
-
* NOT optional (the platform declares it required and every exit path here awaits it). */
|
|
41
|
-
export interface SubagentRunLike {
|
|
42
|
-
readonly result: Promise<SubagentResultLike>;
|
|
43
|
-
dispose(): Promise<void>;
|
|
44
|
-
}
|
|
15
|
+
/**
|
|
16
|
+
* W5 G3-S4: execution goes through evolution-core's Channel (the 0.2.1 startActivation contract +
|
|
17
|
+
* restricted preset). The former local views of the platform subagent request/result are gone — a
|
|
18
|
+
* structural copy would be the second definition the contract freeze forbids.
|
|
19
|
+
*/
|
|
45
20
|
export interface MaintainRuntime {
|
|
46
21
|
/** SkillLibrary-like reader for snapshot assembly. */
|
|
47
22
|
library: SkillLibraryLike;
|
|
48
|
-
/**
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
subagents: {
|
|
53
|
-
start(kind: 'spawn', options: SubagentStartRequestLike): Promise<SubagentRunLike>;
|
|
54
|
-
};
|
|
55
|
-
/** The spawning agent (platform `SubagentStartRequest.parent`, required: in-process
|
|
56
|
-
* providers derive workspace, lineage and delegation depth from its durable session). */
|
|
23
|
+
/** W5 G3-S4: the ONE execution path (capability probe, restricted preset, timeout/abort and
|
|
24
|
+
* exactly-one dispose live in the channel; this orchestrator only maps the outcome). */
|
|
25
|
+
channel: SubagentChannel;
|
|
26
|
+
/** The spawning agent (0.2.1 `SubagentStartRequest.parent`). */
|
|
57
27
|
parent: Agent;
|
|
58
28
|
/** Optional logger for dispose-failure traces; when absent the failure is
|
|
59
29
|
* swallowed without surfacing (the orchestrator is a pure function). */
|
|
@@ -83,6 +53,9 @@ export interface MaintainRuntime {
|
|
|
83
53
|
* probe the scan keeps the previous empty-library answer. */
|
|
84
54
|
rootExists?: (() => Promise<boolean>) | undefined;
|
|
85
55
|
/** V27 M-02: the root the probe above refers to, for the error message. */
|
|
56
|
+
/** G3/3.3: the runtime io the footprint reading needs. Optional: a caller without it gets UNKNOWN for
|
|
57
|
+
* every registered store instead of an invented zero. */
|
|
58
|
+
io?: FootprintIo | undefined;
|
|
86
59
|
skillRoot?: string | undefined;
|
|
87
60
|
}
|
|
88
61
|
export interface MaintainOptions {
|
|
@@ -138,7 +111,10 @@ export interface FactsBundle {
|
|
|
138
111
|
* rendered facts block (joint signature + redaction). Shared by `runMaintain`
|
|
139
112
|
* and the `--facts` preview so the preview can never disagree with the scan.
|
|
140
113
|
*/
|
|
141
|
-
export declare function buildMaintainFacts(snapshots: ReadonlyArray<DriftSkillSnapshot>, usageObserved: boolean | undefined, redact: ((text: string) => string) | undefined
|
|
114
|
+
export declare function buildMaintainFacts(snapshots: ReadonlyArray<DriftSkillSnapshot>, usageObserved: boolean | undefined, redact: ((text: string) => string) | undefined,
|
|
115
|
+
/** G3/3.3: one reading per registered bounded store, produced at this run's reclamation point.
|
|
116
|
+
* Optional so the preview and any older caller keep the exact block they had. */
|
|
117
|
+
footprint?: readonly StoreFootprint[]): FactsBundle;
|
|
142
118
|
/** Run one maintenance scan and return display text plus validation metadata. */
|
|
143
119
|
export declare function runMaintain(runtime: MaintainRuntime, options?: MaintainOptions): Promise<MaintainOutcome>;
|
|
144
120
|
//# sourceMappingURL=orchestrate.d.ts.map
|
|
@@ -9,11 +9,27 @@
|
|
|
9
9
|
* redactor and the delimiter/newline escaping before it leaves the session.
|
|
10
10
|
*/
|
|
11
11
|
import { type DriftReport } from '@lmzhen/dsh-evolution-core';
|
|
12
|
+
/** G3/3.3: what one footprint line reports about one registered store. */
|
|
13
|
+
export interface StoreFootprint {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly unit: string;
|
|
16
|
+
/** The reading, when one exists; undefined renders as UNKNOWN instead of an invented zero. */
|
|
17
|
+
readonly used?: number | undefined;
|
|
18
|
+
readonly bound: string;
|
|
19
|
+
readonly lastSweep?: string | undefined;
|
|
20
|
+
readonly removed?: number | undefined;
|
|
21
|
+
/** Set for a `manual` store that did not run: stated, never implied. */
|
|
22
|
+
readonly skipped?: string | undefined;
|
|
23
|
+
}
|
|
12
24
|
export interface RenderFactsOptions {
|
|
13
25
|
/** signals_version — changes whenever the signal set/thresholds change. */
|
|
14
26
|
signalsVersion: string;
|
|
15
27
|
/** Joint signature: sha256(template-text + signal-definitions) — shared with MAINTAIN_PROMPT head. */
|
|
16
28
|
signature: string;
|
|
29
|
+
/** G3/3.3: one reading per registered bounded store (STORE_LEDGER). Absent ⇒ no footprint lines at
|
|
30
|
+
* all, so an older caller keeps the exact block it had; a store with no reading renders as UNKNOWN
|
|
31
|
+
* and a manual-trigger store that did not run says so — "not done" must never read as "nothing to do". */
|
|
32
|
+
footprint?: readonly StoreFootprint[] | undefined;
|
|
17
33
|
/** Optional redactor; defaults to core `redactSecrets`. */
|
|
18
34
|
redact?: ((text: string) => string) | undefined;
|
|
19
35
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-maintenance",
|
|
3
3
|
"description": "Deterministic maintenance-scan surface: skill-library snapshot assembly, drift signals and mechanical-facts rendering (design 011) (community build)",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.27.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -30,16 +30,19 @@
|
|
|
30
30
|
],
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
34
|
-
"@lmzhen/dsh-evolution-core": "^0.
|
|
33
|
+
"@deepseek-ai/schemastery": "^3.18.5",
|
|
34
|
+
"@lmzhen/dsh-evolution-core": "^0.27.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@deepseek-ai/
|
|
38
|
-
"@deepseek-ai/
|
|
39
|
-
"@deepseek-ai/dsh-tools": "^0.2.
|
|
37
|
+
"@deepseek-ai/cordis": "^4.0.5",
|
|
38
|
+
"@deepseek-ai/dsh-agent": "^0.2.1-rc.1",
|
|
39
|
+
"@deepseek-ai/dsh-tools": "^0.2.1-rc.1"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@deepseek-ai/dsh-agent": "^0.2.
|
|
43
|
-
"@deepseek-ai/dsh-tools": "^0.2.
|
|
42
|
+
"@deepseek-ai/dsh-agent": "^0.2.1-rc.1",
|
|
43
|
+
"@deepseek-ai/dsh-tools": "^0.2.1-rc.1"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"dsh": ">=0.2.1-rc.1 <0.2.2-0"
|
|
44
47
|
}
|
|
45
48
|
}
|