@sema-agent/core
Version:
Stateless, task-oriented AI agent core
59 lines (58 loc) • 4.23 kB
TypeScript
/**
* The WRITE-HOME NAME rule: one predicate, four existing read seats (index rows, search, listing,
* bare-slug resolution). When the session's write home already carries an entry by a given NAME,
* the read-only layers' same-named entries leave the DEFAULT read face. Nothing is written, moved
* or deleted — the shadowed entry stays fully readable as evidence by id and through the
* `includeShadowed` faces, the write home's own entries are never affected, read-only layers never
* shadow each other, and a session with no write home derives the empty set (byte-identical
* behaviour to a tree without this module).
*
* It lands at the seats the supersession derivation in `consolidation.ts` lands at, in the same
* shape: a second answer to "what is on the default face" would be a drift seam. The two are
* orthogonal and compose — supersession is a same-scope data fact carried by consolidation edges,
* shadowing a cross-layer session fact that depends on where this session writes — so an entry can
* be both, and each is separately disclosed.
*
* TWO LAWS AUTHORIZE A SHADOW. (1) The NAME SOURCE is a committed header face: an in-session
* `name:` edit retires nothing before the harvest boundary admits it. (2) The CARRIER must itself
* STAND ON THE SEAT'S OWN DEFAULT FACE — withheld, superseded and undeliverable are not three
* conditions but three ways of not standing there, which is how the caller passes them (one
* `excluded` predicate, plus a delivery probe for the one part a header listing cannot answer).
* Stating it as three independent conditions is what a counterexample punched through: a
* write-home entry replaced by a consolidation product is committed, unchallenged and deliverable,
* yet it is not on the default face, and letting it shadow took BOTH same-named answers off every
* enumeration at once. The write home's answer and the shadowed one never vanish together.
*/
import type { MemoryEntryHeader } from "./types.js";
/** The name an entry is known by on the read faces: its frontmatter `name`, else the last segment
* of its slug — the expression the index row's own title is built from, so "same name" means what
* a reader of the injected index would call the same name. Exact equality: no case folding (the
* frontmatter parse already trimmed), no type or scope participation. */
export declare function shadowKeyOf(h: Pick<MemoryEntryHeader, "name" | "slug">): string;
/** The NAMES the session's write home carries, each mapped to the id carrying it (lowest id wins
* when the home holds several under one name — deterministic, never a scan order). A read-only
* layering (`writeScope: null`) carries nothing. */
export declare function shadowNamesOf(headers: readonly MemoryEntryHeader[], writeScope: string | null, opts?: {
excluded?: (id: string) => boolean;
}): Map<string, string>;
/**
* Derive the SHADOWED set from a header listing: shadowed entry id → the write-home entry id whose
* name retires it from the default face.
*
* `opts.shadowNames`, when given, IS the name map (the caller computed it — across planes, or from
* a listing this one does not contain); absent, the map is derived from these same headers through
* {@link shadowNamesOf}. One rule either way.
*
* @contract memory.read_face.write_home_name_wins — a read-only layer's entry whose name the
* session's write home already carries leaves the default read face (index row, search hit,
* listing row, bare-slug resolution) and stays fully readable as evidence by id; nothing is
* written, moved or deleted, and the write home's own entries are never affected.
*/
export declare function deriveShadowedSet(headers: readonly MemoryEntryHeader[], writeScope: string | null, opts?: {
excluded?: (id: string) => boolean;
shadowNames?: ReadonlyMap<string, string>;
}): Map<string, string>;
/** memory_get head note for a shadowed entry (delivery proceeds — disclosure, never refusal). */
export declare function memoryShadowedNote(shadowingId: string): string;
/** The tag suffixed to a search hit / listing row when a shadowed entry is retrieved explicitly. */
export declare const MEMORY_SEARCH_SHADOWED_TAG = "[shadowed]";