/** * design/133 §R3 — turn-boundary attachment seam: the PURE producer layer (CC `getContextAttachments` * parity). This module is the single home of the CC-parity cadence judgment + reminder copy (提示词主权批: * harness 语料归 core); it holds NO harness handle, does NO I/O, and never injects anything itself — the * run loop (runtask onTurnBoundary) is the ONLY steerer. That split exists so every trigger window is * offline-testable and the injection gate/ordering stays at the one arbitration point the engine already has. * * F3 (wrapper semantics): a {@link TurnAttachment} carries the BODY ONLY — no `` shell. * The steerer wraps each body exactly once at a single call site, so double-wrap/no-wrap can't drift * per-producer. */ /** CC-verbatim cadence constants (CC attachments.ts:254-262). */ export declare const TODO_REMINDER_CONFIG: { readonly TURNS_SINCE_WRITE: 10; readonly TURNS_BETWEEN_REMINDERS: 10; }; export declare const PLAN_MODE_ATTACHMENT_CONFIG: { readonly TURNS_BETWEEN_ATTACHMENTS: 5; readonly FULL_REMINDER_EVERY_N_ATTACHMENTS: 5; }; /** F5: per-boundary stat scan upper bound — at most this many most-recently-read files are stat'ed. */ export declare const CHANGED_FILES_MAX = 20; /** * F5 (记档 known limitation): `ReadEntry.lastReadAt` is wall-clock (Date.now) while `FileInfo.mtimeMs` * is the fs clock — a cross-clock comparison (CC getChangedFiles is the same shape: its readFileState * timestamp is also wall-clock). The 2s epsilon absorbs ordinary skew/mtime granularity; git-checkout / * formatter storms remain a documented false-positive source (hash-confirm 抗假阳 = v2). */ export declare const CHANGED_FILES_MTIME_EPS_MS = 2000; /** Per-boundary payload byte cap over the whole bundle (weak-model context economics). */ export declare const ATTACHMENT_BYTE_CAP: number; export type AttachmentSource = "todo_reminder" | "task_reminder" | "changed_files" | "plan_mode" | "budget_usd" | "background_tasks" | "tools_delta" | "agent_listing" | "mcp_instructions"; /** G1 续批 — one agent type on the delegation tool's roster (ToolSpec.agentListing, filled by * createSubagentTool: defined agents + the built-in fork when offered). */ export interface AgentListingEntry { name: string; description: string; /** Pre-rendered tool-boundary note for the `(Tools: …)` line tail (CC `gHm`, pretty.js:453014-453027: * "All tools" / "All tools except X, Y" / an explicit list / "None"). Computed by the producer * (createSubagentTool → {@link import("../../agents/subagent.js").agentToolsNote}); omitted ⇒ the line * renders without a tail (pre-F3 shape, kept for hand-built deployments). */ tools?: string; } /** G1 通告层 (黑板 [482]): a background task visible to THIS run, snapshotted at the boundary by the * runtask-side getter (registry ground truth — the producer never touches the registry itself). */ export interface BackgroundTaskSnapshot { id: string; description?: string; status: string; } /** One due reminder. `body` is the inner text — the steerer adds the `` wrapper (F3). */ export interface TurnAttachment { source: AttachmentSource; body: string; } /** H4 — the thin projection of a todo list kept run-local (NEVER the wire-capped structuredFrom card). * Pure CONTENT memory: the write-window anchor lives on {@link AttachmentState.todoLastWriteTurn} * (task #51 F3 — the window resets on tool-call INITIATION, which may precede/outlive any ingest). */ export interface ListProjection { /** status → count over the FULL list (uncapped counts stay honest when items are clipped). */ statusCounts: Record; /** ≤{@link PROJECTION_ITEMS_MAX} items, content clipped to {@link PROJECTION_CONTENT_MAX} chars. */ items: Array<{ content: string; status: string; }>; } /** * Run-local mutable producer state, owned by the run loop (one per run, torn down with it). Mutated by * {@link reduceToolEnd} (ingest) and {@link collectDueAttachments} (window bookkeeping on fire) — both * synchronous and deterministic, so the state stays offline-testable despite the mutation. */ export interface AttachmentState { /** TodoWrite family snapshot; undefined = TodoWrite never used this run (CC still reminds: the * gentle "hasn't been used recently" nudge with no list section). */ todo?: ListProjection; /** Task family (TaskCreate/TaskUpdate/TaskGet/TaskList) — keyed by task id so per-task updates from a * PARALLEL tool batch commute (F10: distinct ids reduce to the same map in either completion order). */ taskItems?: Map; /** Cadence-clock value AT the last task WRITE anchor block, INCLUSIVE (task #51 F1 block units — see * {@link advanceCadenceClock}). 口径① (CC 198 pretty.js:480254): CC's `qFm` counter resets ONLY on a * TaskCreate/TaskUpdate tool_use (`a.name === bD || a.name === hF`) — a TaskGet/TaskList READ is NOT * engagement and leaves the 10-unit window running. F3: stamped on tool-call INITIATION (the tool_use * block existing in the transcript IS CC's anchor — qFm never checks execution outcome, so a failed or * policy-blocked write still resets the window), via {@link stampWriteAnchor} from the message walk. */ taskLastWriteTurn?: number; /** TodoWrite counterpart of {@link taskLastWriteTurn} (same block coordinate, same initiation-anchor * semantics — CC BFm :480217-480219 matches the TodoWrite tool_use block by name only). */ todoLastWriteTurn?: number; lastTodoReminderTurn: number; lastTaskReminderTurn: number; /** plan_mode attachments emitted so far — drives CC's full/sparse rotation (1st, 6th, 11th… = full). * 0 also encodes "never attached": CC always attaches on the FIRST plan-mode boundary, then throttles. */ planAttachmentCount: number; lastPlanReminderTurn: number; /** changed_files per-path dedup: the last mtime already surfaced for a path — the same (path, mtime) * is never reported twice. Evicted alongside readFileState's ENOENT eviction (LOW-9: bounded by it). */ surfacedMtime: Map; /** G1 backgroundTasks ([482], CC /compact parity): SET by the run loop when a compaction LANDS, * CONSUMED at the next boundary the collector actually runs (a steered-away boundary carries it * forward untouched — the collector is never called there). One-shot: post-compact announce once, * never per-boundary nagging. A cap-starved bundle loses this one snapshot (documented trade-off, * same class as the truncated changed_files batch): the next compaction re-arms it. */ postCompactPending: boolean; /** G1 续批 agent_listing (CC `agent_listing_delta`): name → description of the agent types already * ANNOUNCED this leg. `undefined` = the initial full-roster announcement is still pending (CC * isInitial). Advanced ONLY by {@link commitAgentListing} (run-loop-owned, on intact cap survival — * MED-3①). A durable-resume leg is SEEDED by the run loop ONLY when the prior leg's transcript * actually carries a listing reminder (MED-3② conservative seed — a first leg that suspended * before its first clean boundary never announced, so the resume leg re-announces; cross-leg * roster drift is deliberately not delta-announced, static-registry assumption recorded). */ announcedAgentTypes?: Map; } export declare function createAttachmentState(): AttachmentState; /** * H4 — thin-projection reducer over a tool's RAW `result.details` (NOT the wire `structuredFrom` * projection and its 4×16K caps: a huge todo list must shrink into a bounded snapshot here, never * disarm the reminder by being dropped wholesale). Only the first-party discriminants `todo` / * `task` / `task-list` are recognized — every other card type (subagent `agent`/`fork`/`task-output`, * bash, fs, mcp, …) is structurally ignored, which is also the child-isolation contract: a subagent's * own todo state never reaches the parent's onToolEnd, and its delegation-card types don't parse here. * * task #51 F3 (窗口复位/投影摄入拆分, 复审 confirmed): this reducer is PROJECTION INGEST ONLY — it * never touches the write windows. CC's window anchor is the tool_use block's PRESENCE in the * transcript (qFm/BFm match the block by name, :480217-480219/:480253-480254, with no execution- * outcome check), so the run loop stamps the windows on INITIATION via {@link stampWriteAnchor} * (inside {@link advanceCadenceClock}'s message walk); ingest stays success-only — a failed write * has no trustworthy `details`, exactly like CC's reminder body rendering from the authoritative * store rather than from tool results. * * Idempotent (same event twice ⇒ same state) and commutative across DISTINCT task ids (F10); two * whole-list writes (TodoWrite / TaskList) racing in one batch are last-write-wins by nature — the * later list IS the truer snapshot, documented rather than fought. */ export declare function reduceToolEnd(state: AttachmentState, details: unknown): void; /** task #51 F2/F3 — which reminder window a WRITE tool resets. Resolved by the run loop (alias-aware: * ToolSpec.aliases + canonicalToolName); the producers here never inspect tool names themselves. */ export type WriteFamily = "todo" | "task"; /** * task #51 F3 (发起锚) — reset a write window at the cadence-clock value of the write tool_use block * (INCLUSIVE of that block). CC's qFm/BFm anchor is the tool_use block's presence in the transcript * (:480217-480219/:480253-480254) with NO execution-outcome check — a failed, policy-blocked, or * suspended call still resets the 10-unit window. Callers: {@link advanceCadenceClock}'s message walk * (the transcript-anchor moment) and the durable-resume gated-write replay (leg-local clock). */ export declare function stampWriteAnchor(state: AttachmentState, family: WriteFamily, clock: number): void; /** * 口径④ cadence clock, task #51 F1 (复审 HIGH, 锚核坐实 2026-07-10) — CC's cadence unit is the * per-content-block assistant TRANSCRIPT ENTRY, not the physical turn. CC 198 mints ONE * `{type:"assistant"}` entry PER content block: the streaming layer at `content_block_stop` * (pretty.js:593011-593038 — `content: pnn([Pr],…)` single-block array, `rn.push` per block) and the * `tgf` normalizer (:597284 — `content.map` → one single-block entry each). The reminder counters * BFm/qFm (:480210-480226/:480246-480262) then tick `r++`/`o++` once per non-`_or` entry, and `_or` * (:599513-599517) applied to a single-block entry degenerates to "is this block thinking/ * redacted_thinking" — so the 10/10 windows consume ONE unit per NON-THINKING CONTENT BLOCK. A * `[text, tool_use]` turn costs 2 units, a parallel-k tool batch costs k(+lead) — live probe * (bench/probes/task51-cadence-live, real CC 2.1.198 + stub API): `[text, tool_use]×N` fires the * task_reminder at request #7, block-exact, where a turn-level clock predicts #11-12. * * Applied by the run loop once per completed assistant MESSAGE; returns the advanced clock. CC edge * semantics kept verbatim: non-array content → `_or` false → counted as ONE entry; an empty array is * vacuously all-thinking (`.every`) → 0. sema folds `redacted_thinking` into `{type:"thinking", * redacted:true}` (brain/anthropic.ts B2) so matching "thinking" covers both; the literal * "redacted_thinking" arm serves CC-shape inputs. `stats.turns` is untouched — it has unrelated * consumers (limits/budget/telemetry) whose physical-turn semantics must not drift. * * F3 write anchors ride the SAME walk: a toolCall block whose name resolves (alias-aware, F2) to a * write family stamps that window at the block's inclusive clock value — CC-exact: same-message * leading text blocks sit BEFORE the anchor (they consumed budget but are not part of the * since-write distance), later sibling blocks count toward it; the LAST write block wins, matching * qFm's tail-first scan. */ export declare function advanceCadenceClock(state: AttachmentState, clock: number, content: unknown, writeFamilyOf: (toolName: string) => WriteFamily | undefined): number; /** * task #51 F4 (压缩交互, 复审 confirmed) — rebase every reminder window to the CURRENT cadence clock * when a compaction LANDS. CC's windows are recomputed per request by BACKWARD TRANSCRIPT SCAN * (BFm/qFm): compaction removes the write tool_use anchors and the reminder attachment entries, so * both counters find nothing (t=-1/n=-1) and only count post-compaction entries — the windows * effectively RESET, needing another 10 non-thinking entries before the next fire. sema's stateful * windows would otherwise survive compaction and fire at the first post-compact boundary where CC * stays silent. Setting all four fields to `clock` makes each window measure distance from the * compaction point — arithmetic-identical to CC's anchor loss. (If a messagesToKeep-style preserved * segment is ever implemented, a recent anchor inside the kept tail would survive in CC — refine * this to check the preserved segment then; recorded caveat.) */ export declare function rebaseCadenceWindows(state: AttachmentState, clock: number): void; export interface AttachmentInputs { /** COMPLETED assistant turns at this boundary (`stats.turns`). */ turn: number; /** 口径④/F1 — the BLOCK-level cadence clock at this boundary: total NON-THINKING content blocks * across all completed assistant messages ({@link advanceCadenceClock}, CC per-block transcript * entries :593011/:597284 ticked by BFm/qFm :480210-480226/:480246-480262). This is the todo/task * reminder-cadence clock — thinking blocks never consume 10/10 budget (`_or` :599513), and a * multi-block turn consumes one unit PER block, so the windows run 2-3× faster than physical * turns on real transcripts (text+tool_use is the norm). Write anchors ({@link stampWriteAnchor}) * are stamped in this SAME coordinate. Omitted ⇒ falls back to `turn` (correct only for the * degenerate one-non-thinking-block-per-turn transcript). plan_mode keeps `turn` (its cadence is * a recorded sema deviation already — assistant turns, not CC human turns). */ cadenceTurn?: number; /** Whether TodoWrite is mounted (CC gate: no tool ⇒ no reminder, ever). */ todoMounted: boolean; /** Whether the task-family tools are mounted. Both mounted ⇒ task_reminder wins (CC isTodoV2 branch). */ taskListMounted: boolean; /** Live plan-mode flag (planModeRef.active). One-way in sema: exit re-prepares the run, so a false * here simply stops the producer — no re-entry cycle reset is needed (documented deviation from CC's * countPlanModeAttachmentsSinceLastExit, which sema's lifecycle makes unreachable). */ planActive: boolean; /** SR-3 budget_usd lane (CC 198 `QFm` producer :480424-480428 + renderer :600225): the run's cost * progress against its $ ceiling, in USD. Only passed when `config.budgetUsd` opted in AND the task * actually carries a ceiling (CC gate `e === void 0 → []` — no `maxBudgetUsd`, no lane). CC computes * `used = sy()` (session-cumulative totalCostUSD) and `remaining = total − used`, both raw JS numbers; * sema feeds the SAME coordinate its budget gate enforces (`stats.costMicroUsd`/`maxCostMicroUsd`, * ÷1e6 → USD) so the model-visible numbers can never disagree with the `budget.exceeded` verdict. */ budgetUsd?: { used: number; total: number; }; config: { todoReminder: boolean; /** 口径③ — CC `r2o()` kill-switch parity (pretty.js:479167-479171; consumed by both producers at * :480232/:480268 as `if (r2o() === "off") return []`). CC resolves the mode from env * `CLAUDE_CODE_TODO_REMINDER_MODE` (highest precedence) else the `tengu_soft_slate_nudge` gate; * `"off"` silences BOTH the todo and task reminder lanes even when otherwise wired on, any other * value (or absence) = CC `"baseline"` (on). sema keeps env resolution at the deployment shell * (sema-tb `TB_TODOREMIND=off`) and carries only the resolved mode here — core reads no env. */ todoReminderMode?: "baseline" | "off"; changedFiles: boolean; planModeReminder: boolean; /** SR-3: budget_usd progressive reminder lane (opt-in, default OFF like every 133 member). CC 198 * fires it on EVERY attachment cycle of the MAIN agent while `maxBudgetUsd` is set (mount * :479243-479245, gated `d = !t.agentId` :479177 — subagents never see it); there is NO threshold * ladder and no throttle window in CC (QFm is unconditional) — the "progression" is the numbers * advancing with spend. sema mirrors that: one line per collected clean boundary, no window state * here; the run loop adds a continuation gate (tool-calling turns only — a boundary steer must * never EXTEND a finished run, see runtask's `lastTurnHadToolCalls`). */ budgetUsd?: boolean; /** G1 [482]: post-compact background-task announce (opt-in, default OFF like the 133 members). */ backgroundTasks?: boolean; /** G1: deferred-tool materialization announce (design/36 setTools delta → boundary notice). */ toolsDelta?: boolean; /** G1 续批: agent-type roster announce (CC `agent_listing_delta`). */ agentListing?: boolean; /** G1 续批: MCP server-instruction delta announce (CC `mcp_instructions_delta`). */ mcpInstructions?: boolean; }; /** Boundary-time scan result (already stat'ed + EPS-filtered by the prepare-task closure). Only * passed when `changedFiles` is opted in — OFF must mean zero stat calls upstream. */ changedFiles?: ReadonlyArray<{ path: string; mtimeMs: number; }>; /** G1 backgroundTasks: registry snapshot (pending/running only, filtered by the runtask getter). * Only fetched when opted in AND `state.postCompactPending` — OFF means zero registry reads. */ backgroundTasks?: ReadonlyArray; /** G1 toolsDelta: deferred tools MATERIALIZED since the last announcement (prepare-task's * rematerialize diff — already newly-added-only, resume-seeded actives never appear here). The * CALLER owns consumption: drain its pending list only when the returned capped bundle actually * retained the `tools_delta` block (cap starvation must not lose the announcement forever). */ newTools?: readonly string[]; /** G1 续批 agent_listing: the boundary-time roster snapshot of the mounted delegation tool * (prepare-time static in practice; the producer's delta path serves dynamic-registration * deployments and tests). Only passed when `config.agentListing` opted in. */ agentListing?: ReadonlyArray; /** The delegation tool's mounted name — interpolated into the CC-verbatim headers ("…for the * Agent tool:"); byte-identical to CC under the default name "Agent". */ agentToolName?: string; /** G1 续批 mcp_instructions: pending deltas snapshotted from `MaterializedMcp.instructionsDelta`. * CALLER-owned consumption on intact cap survival (same `newTools` discipline). */ mcpInstructions?: { added: ReadonlyArray<{ server: string; text: string; }>; removed: readonly string[]; }; } /** * Compute every reminder due at this clean turn boundary. Pure decision + render — no I/O; the only * mutation is the window bookkeeping on the state the caller owns (reminder turns, surfacedMtime), * done HERE because the caller only invokes this once per boundary after its injection gate passed — * splitting "decide" from "mark sent" would just invite a drift between the two. * * Returns attachments in EVIDENCE-STRENGTH order (todo/task → plan_mode → budget_usd → * background_tasks → tools_delta → agent_listing → mcp_instructions → changed_files), which is also the §R3 MED-6 * truncation order read backwards: under the 8KB cap changed_files is sacrificed first, the todo/task * list last. The G1 members ([482] + 续批) are registry/engine ground truth (strong), but the * todo/plan lane keeps priority: it carries the run's own work-tracking state, which the model can * least afford to lose. */ export declare function collectDueAttachments(state: AttachmentState, inp: AttachmentInputs): readonly TurnAttachment[]; /** * SR-3 — CC 2.1.198 VERBATIM template (bundle pretty.js:600225, the `budget_usd` attachment renderer): * `USD budget: $${used}/$${total}; $${remaining} remaining` * `remaining = total − used` is computed producer-side in CC (QFm :480427 `n = e - t`) and re-derived * here from the two inputs — one fewer number to drift. CC interpolates RAW JS numbers (sy() is a * float accumulator; no rounding anywhere in QFm or the renderer), kept verbatim: sema's inputs come * from integer micro-USD ÷ 1e6, so they render with ≤6 decimals by construction. */ export declare function renderBudgetUsd(used: number, total: number): string; /** * SR-7 — CC 2.1.198 VERBATIM inner text (bundle pretty.js:698391-698398, `F6c`): the aggregated * orphaned-background-task notice a restarted/resumed leg injects ONCE (CC's own `` * wrapper is added by the caller — sema's single-wrap-point discipline, F3). Line shape CC-exact: * `- ${description || "(no description)"} (task ${id})` — `||` kept (an EMPTY description also reads * "(no description)", CC-same). Consumed by the runtask durable-resume path, NOT a boundary producer: * the trigger is the resume itself (CC gate `CLAUDE_CODE_RESUME_INTERRUPTED_TURN`, :707384), not a * cadence window. */ export declare function renderOrphanedBackgroundTasks(tasks: ReadonlyArray<{ id: string; description?: string; }>): string; /** * G1 — deferred-tool materialization announce (design/36 boundary notice). CC 2.1.198 template * (bundle pretty.js:599148, `deferred_tools_delta` case) verbatim reads: "The following deferred * tools are now available via ${ToolSearch}. Their schemas are NOT loaded — calling them directly * will fail with InputValidationError. Use ${ToolSearch} with query \"select:[,...]\" to load * tool schemas before calling them:" — but CC announces DISCOVERABLE tools (schemas still deferred), * while sema announces MATERIALIZED tools (tool_search already ran setTools; schemas ARE live), so * the middle clause is inverted to match sema's actual contract. Same CC shape: lead sentence + * name list. */ export declare function renderToolsDelta(names: readonly string[]): string; /** CC 2.1.198 verbatim (bundle pretty.js:599221, `agent_listing_delta` isInitial+showConcurrencyNote arm). */ export declare const AGENT_CONCURRENCY_NOTE = "When you launch multiple agents for independent work, send them in a single message with multiple tool uses so they run concurrently."; /** CC-verbatim ambient-context tail (CC 2.1.198 `Emr`, pretty.js:599992 — resolved by the 2026-07-10 * parity spot audit, PARITY-SPOT-AGENT-TYPES F5 / PARITY-SPOT-REMINDERS SR-V1). CC appends it after BOTH * removal lists (agent types :599211, mcp instructions :599240) so the model treats the drift notice as * background, not something to announce. */ export declare const AMBIENT_CONTEXT_NOTE = "This is ambient context \u2014 do not narrate it to the user unless they ask or it is directly relevant to their request."; /** CC-verbatim initial-roster header (interpolated tool name) — single-sourced here for the renderer * AND the run loop's resume transcript probe (MED-3②: "was the listing ever delivered?"). */ export declare function agentListingInitialHeader(toolName: string): string; /** CC-verbatim roster-drift header — same single-source rationale as {@link agentListingInitialHeader}. */ export declare function agentListingDeltaHeader(toolName: string): string; /** * G1 续批 — agent-type roster announce (CC 2.1.198 `agent_listing_delta`, bundle pretty.js:599199-599223, * headers VERBATIM with the tool name interpolated — byte-identical to CC under the default "Agent"). * First call (no announced map) = CC `isInitial`: full roster under "Available agent types…", plus the * concurrency note when more than one type is offered (考据档 showConcurrencyNote semantics). Later * calls announce only drift: adds under "New agent types are now available…", removals under "The * following agent types are no longer available:" + `- ` lines, followed by the CC-verbatim * {@link AMBIENT_CONTEXT_NOTE} (CC `Emr`, pretty.js:599211/599992). Name-keyed like CC: a description * change on an existing name is not re-announced. Lines carry a `(Tools: …)` tail when the entry * provides one (CC `tIl`/`gHm`, pretty.js:453014-453031 — the model needs each type's tool boundary * to pick a type; PARITY-SPOT-AGENT-TYPES F3). * * 1.256 复审 MED-3①: PURE — never mutates `state`. The announced-set advance is CALLER-owned via * {@link commitAgentListing}, committed ONLY when the rendered block survived the byte cap INTACT * (tools_delta/mcp_instructions discipline — a cap-clipped/dropped block previously advanced the * announced map anyway, losing the roster announcement forever). */ export declare function renderAgentListingDelta(state: AttachmentState, entries: ReadonlyArray, toolName: string): string | undefined; /** * MED-3① commit half of {@link renderAgentListingDelta}: mark the CURRENT roster as announced. The run * loop calls this only when the `agent_listing` block survived the capped bundle INTACT (body equality * against a re-render — same predicate as the tools_delta drain); a clipped/dropped block leaves the * announced map untouched so the next quiet boundary re-announces. Snapshotting `entries` wholesale is * equivalent to add/remove bookkeeping (the diff is name-keyed; descriptions are never re-diffed). */ export declare function commitAgentListing(state: AttachmentState, entries: ReadonlyArray): void; /** * G1 续批 — MCP server-instruction delta (CC 2.1.198 `mcp_instructions_delta`, bundle * pretty.js:599225-599248, headers VERBATIM). Deliberate CC deviations (recorded): * - added instruction text is UNTRUSTED server-controlled text → each block rides inside a * `delimitUntrusted` fence (CC injects the raw block; sema's external-inlet posture is fencing — * the text is additionally already `sanitizeUntrustedText`-neutralized at the mcp.ts producer). * The disconnect list is followed by the CC-verbatim {@link AMBIENT_CONTEXT_NOTE} (CC `Emr`, * pretty.js:599240/599992 — resolved by the 2026-07-10 parity spot audit). * Removal names are `\n`-joined WITHOUT a `- ` prefix (CC-exact; the agent-listing removal list DOES * carry the prefix — the asymmetry is CC's, kept verbatim). Exported for the run loop's * intact-survival consumption check (tools_delta discipline). */ export declare function renderMcpInstructionsDelta(added: ReadonlyArray<{ server: string; text: string; }>, removed: readonly string[]): string | undefined; //# sourceMappingURL=turn-attachments.d.ts.map