/** * Maintain orchestration (011 §3/§7): snapshot → drift signals → facts * render → subagent (template M + facts) → validate/normalize → display * text. Deterministic parts stay pure; the subagent call is the only * external dependency (injected, fake-able in tests). */ import { type DriftReport, type DriftSkillSnapshot } from '@lmzhen/dsh-evolution-core'; import type { Agent } from '@deepseek-ai/dsh-agent'; import type { SubagentChannel } from '@lmzhen/dsh-evolution-core'; import { type SkillLibraryLike } from './drift-scan.ts'; import { type Enrichment } from './enrichment.ts'; import { type StoreFootprint } from './render-facts.ts'; import { type FootprintIo } from './footprint.ts'; import { type MaintainPlanItem } from './validate-plan.ts'; /** * W5 G3-S4: execution goes through evolution-core's Channel (the 0.2.1 startActivation contract + * restricted preset). The former local views of the platform subagent request/result are gone — a * structural copy would be the second definition the contract freeze forbids. */ export interface MaintainRuntime { /** SkillLibrary-like reader for snapshot assembly. */ library: SkillLibraryLike; /** W5 G3-S4: the ONE execution path (capability probe, restricted preset, timeout/abort and * exactly-one dispose live in the channel; this orchestrator only maps the outcome). */ channel: SubagentChannel; /** The spawning agent (0.2.1 `SubagentStartRequest.parent`). */ parent: Agent; /** Optional logger for dispose-failure traces; when absent the failure is * swallowed without surfacing (the orchestrator is a pure function). */ logger?: { warn(message: string): void; } | undefined; /** Evolution-policy reader for model routing (same source as the curator: * `policy.get().curatorModel`). Optional — a missing service falls back to * the default model (E-55). `get()` may RESOLVE to undefined (a soft probe * can return nothing), hence the type carries it. */ evolutionPolicy?: { get(): { curatorModel?: string | undefined; } | undefined; } | undefined; /** F-02: tools-registry soft probe, wired from the host context * (`ctx.get('tools')`) with the platform's `get(name)` accessor shape. * Optional — an absent accessor means the tools service is not mounted at * all, so no tool beyond `skill` can be assumed registered. */ tools?: { get(name: string): unknown; } | undefined; /** V27 M-02: does the configured skill root EXIST? The io seam maps a missing * directory to an empty listing, so "the scan found no skills" could not be * told apart from "the configured root is not there" (an unexpanded `~`, a * typo — INSTALL.md routes users to absolute paths). Optional: without the * probe the scan keeps the previous empty-library answer. */ rootExists?: (() => Promise) | undefined; /** V27 M-02: the root the probe above refers to, for the error message. */ /** G3/3.3: the runtime io the footprint reading needs. Optional: a caller without it gets UNKNOWN for * every registered store instead of an invented zero. */ io?: FootprintIo | undefined; skillRoot?: string | undefined; } export interface MaintainOptions { timeoutMs?: number; /** 0.19.0 (S2): the run id chosen by the run registry, so the registry record, * the persisted event and the report file all name ONE run. Absent under the * legacy synchronous call sites, which keep generating their own. */ runId?: string | undefined; /** E-6 (v18): external cancel signal (session/UI); combined with timeoutMs. */ signal?: AbortSignal | undefined; maxDepth?: number; model?: string; provider?: string; toolAllow?: readonly string[]; redact?: ((text: string) => string) | undefined; /** T3-02/A30: the measured enrichment, read through {@link enrichmentSnapshotOptions} — one * mapping shared with the `--facts` preview and the probe tool. A closure per field was a second * account of the same facts and drifted (the probe's copy lost `liveness`). */ enrichment?: (() => Enrichment) | undefined; } export interface MaintainOutcome { ok: boolean; error?: string | undefined; runId?: string | undefined; verdict?: 'issues' | 'no_issues' | undefined; text?: string | undefined; forcedHuman?: string[] | undefined; /** G1 (0.20.0): the VALIDATED plan entries in render order — the report's machine-readable * ledger. `formatPlan` numbers this same array with stable `[n]` ids, and * `needsHumanCount` below is derived from it here, so no reader re-derives either. */ items?: MaintainPlanItem[] | undefined; /** The validated plan's notes, carried beside `items` so a reader never infers them. */ notes?: string[] | undefined; /** How many entries need the operator's confirmation (`needs_human`, gate included). */ needsHumanCount?: number | undefined; /** V10-09 (F-05): structured count of recommendations in the VALIDATED plan * (plan entries, never notes). Consumers must read this field instead of * parsing the rendered `text` — the text is display-only. 0 on every * non-success outcome. */ recommendationCount: number; } /** Render template-M placeholders from the signal vocabulary (011 single-source rule). */ export declare function renderMaintainTemplate(template: string, bundleVersion: string, signalsVersion: string, signature: string): string; /** Facts bundle shared by the full scan and the `--facts` 0-token preview. */ export interface FactsBundle { report: DriftReport; facts: string; signalsVersion: string; signature: string; } /** * Deterministic half of a maintenance scan: snapshots → drift report → * rendered facts block (joint signature + redaction). Shared by `runMaintain` * and the `--facts` preview so the preview can never disagree with the scan. */ export declare function buildMaintainFacts(snapshots: ReadonlyArray, usageObserved: boolean | undefined, redact: ((text: string) => string) | undefined, /** G3/3.3: one reading per registered bounded store, produced at this run's reclamation point. * Optional so the preview and any older caller keep the exact block they had. */ footprint?: readonly StoreFootprint[]): FactsBundle; /** Run one maintenance scan and return display text plus validation metadata. */ export declare function runMaintain(runtime: MaintainRuntime, options?: MaintainOptions): Promise; //# sourceMappingURL=orchestrate.d.ts.map