import type { ExtensionFactory } from "@earendil-works/pi-coding-agent"; /** Retention intent the model declares for a prior tool result. */ export type RetainTier = "pin" | "ref" | "drop"; /** One parsed verdict: a reference + the tier the model assigned it. */ export interface RetainVerdict { /** `prev` | `prev[k]` | an explicit toolCallId. */ ref: string; tier: RetainTier; } /** * System-prompt addendum instructing the model to emit the in-band signal. * * Compliance-tuned (Phase A finding: glm-5.1 emitted 0/15 with the soft, fenced * phrasing). Changes: imperative/MANDATORY framing, a low-friction bare `RETAIN:` * line as the primary format (weak models emit a line far more reliably than a * fenced block), an explicit worked example, and "every turn, no exceptions". */ export declare const FORGE_RETAIN_PROTOCOL = "\n\n## MANDATORY \u2014 Context Retention (every turn, no exceptions)\n\nYou run inside a token-managed loop. After each tool result you MUST begin your reply\nwith ONE retain line telling the harness what to keep, then continue working normally:\n\nRETAIN: prev=drop\n\n- `prev` = the result(s) you just received.\n- Tier: `pin` (you will reuse it) | `ref` (you might) | `drop` (you are done with it).\n- Multiple results this turn: `RETAIN: prev[0]=pin, prev[1]=drop` (tool-call order).\n- Emit it EVERY turn, even for trivial results (use `ref`). It is one short line.\n Never skip it. Then do your actual work as usual.\n\nWorked example \u2014 after reading a file you are finished with:\n\nRETAIN: prev=ref\nGot the store schema. Next I'll read the handler that uses it.\n"; /** True when the RETAIN signal is enabled for this process. */ export declare function isRetainEnabled(): boolean; /** * Extract the retain directive body from an assistant message's content blocks. * Scans thinking blocks first (preferred channel), then text blocks. Returns the * raw body string of the first match, or null if none. */ export declare function extractRetainBody(content: unknown): string | null; /** Parse a directive body into verdicts. Unknown tokens are ignored (tolerant). */ export declare function parseRetainBody(body: string | null): RetainVerdict[]; /** * Bind verdicts to concrete toolCallIds, given the ordered ids of the tool * results received immediately before this assistant turn (positional binding). * `prev` → all of them; `prev[k]` → the kth; an explicit id → itself. */ export declare function bindVerdicts(verdicts: RetainVerdict[], priorIds: string[]): Map; export interface RetainFactoryOptions { /** Label for logs — typically the export tag (`__`). */ label: string; } /** * Build the observe-only RETAIN extension. Registered in runForgeSubagent when * FORGE_RETAIN=1, so every phase of every orchestration carries it. * * Phase A behaviour: * - `context` → parse the newest assistant turn's retain block, bind it to the * prior result batch, record tier → retention map, LOG. Returns * undefined (pure pass-through — evicts nothing, rewrites nothing). * - `turn_end` → feed usage to the cache-mode tracker; log mode + compliance. */ export declare function buildRetainFactory(opts: RetainFactoryOptions): ExtensionFactory;