@sema-agent/core
Version:
Stateless, task-oriented AI agent core
40 lines (39 loc) • 3.05 kB
TypeScript
import type { ParsedScopeKey } from "./scope-contract.js";
import type { HarvestReport } from "./types.js";
import type { MemoryInjection } from "./engine.js";
/** The personal plane's shared mount under the config root (ALL projects, one home — the plane is
* keyed by scope, not by repo: `user:alice` is the same disk from every checkout). */
export declare function derivePersonalMemoryDir(configRoot: string): string;
export declare function derivePersonalControlDir(configRoot: string): string;
export interface ScopePlanes {
/** proj:/legacy scopes — the repo/path-keyed plane (order preserved). */
project: string[];
/** user:/userproj:/org: scopes — the home-mount plane (order preserved). `org` is
* CENTRAL-authority (§2 表), so it routes with the personal keys — under a pinned in-repo File
* backend an org layer projected into the repo would leak tenant-shared memory into commit
* history. The mount is still the "personal" directory (one home plane; the plane is about
* WHERE-NOT-to-project, not about ownership — org's authority disk is the central DB anyway). */
personal: string[];
/** Which plane owns the write face (null = read-only layering everywhere). */
writePlane: "project" | "personal" | null;
}
/** Classify a v2 session's scopes into planes. writeScope routes by its OWN key kind (it need not
* be listed in scopes — normalizeMemorySpec contract). */
export declare function classifyScopePlanes(scopes: readonly string[], writeScope: string | null): ScopePlanes;
/** True when the classified session needs the dual-root assembly at all. */
export declare function needsDualRoots(planes: ScopePlanes): boolean;
/** Convenience for the placement gate: the parsed keys that stay on the PROJECT plane. */
export declare function parsedProjectPlane(planes: ScopePlanes, writeScope: string | null): ParsedScopeKey[];
/**
* Merge the two planes' injections into ONE block. Plane order is fixed: PROJECT first (the stable
* prefix — repo knowledge changes less often than personal notes), PERSONAL second; the instruction
* (trusted half, "where to write") comes from whichever plane owns the write face and leads the
* block, exactly like the single-root layout. v1 deliberately merges at BLOCK granularity — scope
* interleaving across planes is not reproduced (documented; the within-plane order is untouched).
*/
export declare function mergeInjections(project: MemoryInjection | undefined, personal: MemoryInjection | undefined): MemoryInjection;
/** Merge the two planes' harvest reports into the single report the runner surfaces. Counters add,
* lists concatenate, `ok` ANDs, the first incident wins the seat (both are still visible via the
* merged lists). 独立轨 F7: pass the WRITE plane's report as `a` — first-argument fields (incident
* seat, degraded seat) prefer `a`, and the write plane's degradation is the one that matters. */
export declare function mergeHarvestReports(a: HarvestReport, b: HarvestReport): HarvestReport;