Cline: who decides what

Read the one-page summary first · The gallery · Make a map of your own system · The repository

The Cline agent (its SDK, CLI, hub and VS Code extension) in cline/cline, read at commit d800bf82 (2026-10-19). Claims about how the code behaves refer to that commit. Their code is Apache-2.0; this page quotes short strings from it, and each card's "Held by" names the files and lines at that commit.

How to read this page

A seat is a judgment the agent makes over and over: which run path a command takes, what the model sees, is the work done. Each card gives the question, how the judgment is answered, and where in the code it is held. Seat ids (A1, B3 …) are links.

The chip on each card has two words. The first is about the question: a RULE has one right answer given its inputs, so a run that answers differently is a bug; a RULING is one that competent people could answer differently. Enforcing a limit someone set is a RULE; choosing what to keep, what to trust or when the work is done is a RULING, even when code holds it.

The second word is who holds it: llm = a language-model call; model = another learned model; code = code in their repository; human = a person; external = code outside the repository that the agent hands the decision to.

Paths are relative to the repository root. A bare :120-140 means lines in the file named just before it.

Counts

83 seats on this edition: A 12, B 17, C 11, E 16, F 13, G 8, H 5, I 1.

Kind of question · holderSeats
RULE · code43
RULING · code21
RULING · llm11
RULING · human6
RULING · external2

What this edition leaves out

31 decisions are left out of this edition.

Each card shows its question, how it is answered and where it is held. It does not show what checks each decision, its contract, what happens on error, or its failure history, because those parts were not each re-checked against the code. There is no list of gaps and no coverage figure: the readers' candidate gaps have not each been ruled against the code, and we have not counted, by stated searches, the model calls and approval points the seats leave out.

A. Intake and routing (12 on this edition)

A1 Which run path does a CLI invocation take (interactive TUI, one-shot, piped stdin, background hub "zen", ACP, kanban)? RULE · code
Answered how

Code routes on flags in a fixed order: after the --update and --kanban branches (each returns first) and argument checks, --acp enters the ACP stdio transport and returns before the remaining paths; then, when stdin is not a TTY, carries non-empty piped input and --tui is absent, the input is appended to the prompt and run one-shot (or handed to the background hub with --zen); otherwise --tui or a missing prompt opens the interactive TUI (--zen there is an error); otherwise the prompt runs one-shot, or goes to the hub with --zen.

Held by

apps/cli/src/main.ts:785-831 (argument conflicts: json needs a prompt or piped stdin apps/cli/src/main.ts:794-800; ACP exclusive, returns apps/cli/src/main.ts:802-820; --worktree with no prompt, no resume and no piped stdin needs a full TTY apps/cli/src/main.ts:822-831); apps/cli/src/main.ts:975-986 (the isHeadless / isInteractive flags, which gate OAuth and catalog loading); apps/cli/src/main.ts:1142-1170 (piped stdin, one-shot or zen); apps/cli/src/main.ts:1174-1219 (interactive); apps/cli/src/main.ts:1221-1244 (one-shot / zen).

A2 Should the agent be planning or acting right now? (the person's Plan/Act toggle) RULING · human
Answered how

The person flips the Plan/Act toggle. In VS Code the webview request is decoded to "plan"/"act" and handed to controller.togglePlanActMode; in the CLI TUI the choice is persisted at once and, if a turn is running, recorded as a pending change with source "ui" and the turn aborted, otherwise applied immediately, which swaps the mode, the plan-only switch_to_act_mode tool and the system prompt.

Held by

the person, through the VS Code Plan/Act toggle (apps/vscode/src/core/controller/state/togglePlanActModeProto.ts:13-35) or the CLI TUI mode toggle (apps/cli/src/runtime/run-interactive.ts:780-792, pending source "ui"). Applying a mode in the CLI rewrites mode, extra tools and system prompt (apps/cli/src/runtime/interactive/mode.ts:118-131); a plan-mode session also gets the command guard (sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:553-558).

A3 Has the person approved the plan, so execution may start? (CLI switch_to_act_mode) RULING · llm
Answered how

In a CLI plan-mode session the main model decides by calling switch_to_act_mode; the tool's execute records a pending switch to act with source "tool" without looking at the transcript, the run ends on the tool result, and if that turn finished "completed" the CLI rebuilds in act mode and sends the canned continuation prompt so execution starts with no further word from the person. Whether the tool call itself is put to the person first is a separate approval seat; CLI auto-approve defaults on.

Held by

the session's main model, via the tool built at apps/cli/src/runtime/interactive/mode.ts:31-68 (createInteractiveModeSwitchTool, tool name switch_to_act_mode), registered only in plan mode (apps/cli/src/runtime/interactive/mode.ts:124-125). Model = the session's provider/model (A5).

A4 Which provider and model serve this VS Code session (per mode)? RULE · code
Answered how

Code in buildSessionConfig takes the runtime's model selection if one is passed, else the provider stored for the current mode (plan or act) in StateManager and that provider's model for the mode; only when no provider resolved at all does it use the last-used providers.json entry that has an API key, then DEFAULT_PROVIDER_ID. A missing model id becomes the catalog default, except for local-model providers, which read providers.json and otherwise get an empty id (an explicit "select a model" state).

Held by

apps/vscode/src/sdk/cline-session-factory.ts:952-1050 (inside buildSessionConfig, which starts at apps/vscode/src/sdk/cline-session-factory.ts:919): runtime selection, else the mode's provider from StateManager (apps/vscode/src/sdk/cline-session-factory.ts:952-955); model from resolveModelId(providerId, mode, ...) (apps/vscode/src/sdk/cline-session-factory.ts:962); if no provider at all, the last-used providers.json entry with an API key (apps/vscode/src/sdk/cline-session-factory.ts:1010-1031); then DEFAULT_PROVIDER_ID and the catalog default (apps/vscode/src/sdk/cline-session-factory.ts:1035-1050), except local-model providers, which take the providers.json model or an empty id, never a catalog default (apps/vscode/src/sdk/cline-session-factory.ts:1036-1047).

A5 Which provider and model serve this CLI session? RULE · code
Answered how

Code picks the provider from -P/--provider, else the last-used provider, else "cline"; the model is --model, else that provider's saved model, else (Cline provider only) its curated default, else the first chat model in the resolved catalog, else CLINE_DEFAULT_MODEL_ID. The chosen provider and model are then saved back as the provider's settings.

Held by

apps/cli/src/main.ts:1056-1063 (--model > saved provider model > the Cline provider's curated default > first catalog chat model > CLINE_DEFAULT_MODEL_ID); provider from apps/cli/src/main.ts:944-946 (-P > last-used provider > "cline"; flag defined apps/cli/src/commands/program.ts:49); the choice is persisted back to provider settings (apps/cli/src/main.ts:1115-1137).

A6 Does a typed slash command in VS Code expand into instructions, and which one? RULE · code
Answered how

Code scans every slash token in the message, anywhere in it, and resolves each by exact name, then case-insensitively, then by workflow file basename; the first token that resolves to an enabled workflow or a builtin (such as /deep-planning) is replaced by that command's instructions and the rest are left as typed. Configured skills are never expanded here (the skills tool is expected to serve them); a disabled workflow is skipped; any error returns the raw text.

Held by

apps/vscode/src/sdk/SdkController.ts:1135-1163 (resolveSlashCommands) calling expandSlashCommands (apps/vscode/src/sdk/slash-command-expansion.ts:168-206): matches anywhere in the message, expands only the first token that resolves, honours workflow toggles (apps/vscode/src/sdk/slash-command-expansion.ts:185-190), never expands configured skills (apps/vscode/src/sdk/slash-command-expansion.ts:198-200), expands builtins such as /deep-planning (apps/vscode/src/sdk/builtin-slash-commands.ts:98-103).

A7 Does a typed slash command in the CLI / core expand into instructions? RULE · code
Answered how

In the interactive TUI, a whitespace-delimited /name that names a workflow or skill can be expanded first, anywhere in the message, skills only under the same skills-tool check (apps/cli/src/tui/commands/slash-command-registry.ts:259-299). The core resolver then looks only at a leading /name token, normalizes it and matches it exactly against the available commands, where a skill owns any name it shares with a workflow; a matched workflow is always replaced by its instructions (the rest of the message kept), while a matched skill expands only when the CLI judges the skills tool unavailable for the mode and the user's disabled-tools setting (or that check throws).

Held by

sdk/packages/core/src/extensions/config/runtime-commands.ts:133-162 (resolveRuntimeSlashCommandFromWatcher: leading /name only, skills own a name over workflows sdk/packages/core/src/extensions/config/runtime-commands.ts:100-119); CLI caller apps/cli/src/runtime/prompt.ts:104-119 with shouldExpandSkillSlashCommands (apps/cli/src/runtime/prompt.ts:93-102: expand skills only when the skills tool is unavailable).

A8 Which skill does this request call for, and should it be loaded now? RULING · llm
Answered how

When the skills tool is registered, the main model decides by calling it with a skill name, steered by a description that lists the enabled skills by name (or namespaced id) only; code then resolves the name by exact id, else a unique enabled suffix match, and returns the skill's instructions as the tool result, or an error string the model reads. When the tool is not registered, no model judgment is made here (CLI slash expansion, A7, is the only path).

Held by

the session's main model, via the tool built at sdk/packages/core/src/extensions/tools/definitions.ts:774-824 (createSkillsTool, tool name skills), registered when tools are on, the skills extension is on, configured skills exist, and the tool survives presets/policies (sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:521-534).

A9 May a VS Code session start when the organization's policy cannot be verified? RULE · code
Answered how

Before each session start, code waits for the initial remote-config load and tries a refresh. A successful refresh starts the session. If it failed: with no active organization, the session is blocked when the install carries a lastManagedOrganizationId marker and allowed otherwise; with an active organization, the session starts on the cached policy bundle when that bundle belongs to the same organization, and is blocked otherwise.

Held by

apps/vscode/src/sdk/SdkController.ts:911-973 (ensureRemoteConfigForSessionStart, wired as beforeStartSession at apps/vscode/src/sdk/SdkController.ts:978): refreshed → start; no org and a persisted lastManagedOrganizationId → block (apps/vscode/src/sdk/SdkController.ts:934-945); no org ever → start (apps/vscode/src/sdk/SdkController.ts:947-954); active org with a same-org cached bundle → start on last known-good (apps/vscode/src/sdk/SdkController.ts:957-965), else block (apps/vscode/src/sdk/SdkController.ts:967-972). Marker kept through offline cold starts (apps/vscode/src/core/storage/remote-config/sdk-control-plane.ts:238-251).

A11 Does this incoming automation event start a scheduled run? RULE · code
Answered how

Code logs the event and, if an event with that id was already logged, does nothing more; otherwise, for each event spec registered for the event type, it checks the spec's filters (every key must match by attribute, payload or dotted path; an array means any-of; an empty filter matches). A matching spec queues a run unless it is debounced onto an already-queued run for the same dedupe key, or suppressed by its dedupe window or cooldown; all three are off when the spec leaves them at 0.

Held by

sdk/packages/core/src/cron/events/cron-event-ingress.ts:163-171 (automationEventMatchesFilters) and sdk/packages/core/src/cron/events/cron-event-ingress.ts:213-360 (duplicate-event check, per-spec filter, debounce merge, dedupe-window and cooldown suppression; dedupe key default eventType:source:subject, or eventType:source:eventId when there is no subject, used only when the event carries no dedupeKey, sdk/packages/core/src/cron/events/cron-event-ingress.ts:87-89).

A13 When the person sends a message during a run, does it interrupt the current run or wait? RULE · code
Answered how

The person picks the delivery for each message: queue or steer. Code puts a steer entry at the front of the queue and, unless the session is aborting, notifies the running agent that a user message is pending; a queued entry waits at the back and is drained one at a time once the agent can start a run. A new prompt whose text equals one already queued replaces it (keeping steer if either was steer, otherwise moving to the back).

Held by

sdk/packages/core/src/runtime/turn-queue/pending-prompt-service.ts:137-190 (enqueue: identical prompt text merges; a steer entry jumps the queue; consumeSteer takes the first steer) and sdk/packages/core/src/runtime/turn-queue/pending-prompt-service.ts:256-290 (controller: steer notifies the running agent); drain runs one entry at a time and stops on a failing turn (sdk/packages/core/src/runtime/turn-queue/pending-prompt-service.ts:313-369).

A14 Which provider, model, workspace and working directory does a new Cline Hub dashboard session use? RULE · code
Answered how

Provider and model come from the browser's choice if sent. Otherwise they come from the most recently updated hub session of any client, then the last-used provider settings, then CLINE_PROVIDER/CLINE_MODEL. With neither, the send fails: "No provider/model available". The workspace is the caller's workspaceRoot if one is passed (whether the dashboard ever passes one was not read), else that same most-recent session's workspaceRoot/cwd, else the dashboard's configured workspace root. So a new dashboard session can open in whatever folder another client last touched.

Held by

apps/cline-hub/src/server/sessions.ts:43-76 (resolveLaunchContext); "most recent" set at apps/cline-hub/src/server/hub.ts:87-91 and on every hub session created/updated event apps/cline-hub/src/server/hub.ts:183-184, :201-202; fallback root apps/cline-hub/src/options.ts:89.

B. Context: what the model sees (17 on this edition)

B1 Which base system prompt does this session get (act, yolo, a caller override, or a host fallback)? RULE · code
Answered how

Code in buildClineSystemPrompt returns a non-empty caller override as is (adding workspace metadata for the Cline provider when given); otherwise it takes the yolo base prompt in yolo mode and the act base prompt in act and plan, then fills platform, cwd, date, IDE, Cline-only metadata and the rules slot (mode-tag and plan-mode sections plus caller rules). Each host decides what to pass: the CLI passes --system-prompt as the override, core bootstrap uses config.systemPrompt outright when set, and VS Code never sends yolo and falls back to a one-line prompt if assembly throws.

Held by

sdk/packages/shared/src/prompt/cline.ts:152-213 (buildClineSystemPrompt): a non-empty override wins (sdk/packages/shared/src/prompt/cline.ts:169-179); else DEFAULT_CLINE_SYSTEM_PROMPTS.YOLO for yolo, .ACT otherwise (sdk/packages/shared/src/prompt/cline.ts:181-184); placeholders filled (sdk/packages/shared/src/prompt/cline.ts:200-212). Callers, consolidated into this seat: CLI apps/cli/src/runtime/prompt.ts:14-38; VS Code apps/vscode/src/sdk/cline-session-factory.ts:1077-1110; core bootstrap sdk/packages/core/src/services/local-runtime-bootstrap.ts:167-186 (a config.systemPrompt wins); sub-agents sdk/packages/core/src/extensions/tools/team/subagent-prompts.ts:13,33. Registered rules are appended per run (sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:754-771, B3).

B2 Which workspace facts (path, git remotes, branch, latest commit) go into the system prompt? RULE · code
Answered how

Code includes workspace metadata only when the provider id is cline or cline-pass: the workspace root path as the key, its name hint, every git remote URL with any user:pass@ part removed, and the latest commit hash and branch. For other providers the metadata slot is left empty, even where the CLI and cron compute it; with a caller override prompt the metadata is still appended for the Cline provider unless the override already carries the marker.

Held by

sdk/packages/shared/src/prompt/cline.ts:79-120 (processWorkspaceInfo, buildWorkspaceMetadata) and sdk/packages/shared/src/prompt/cline.ts:205-210 (only when the provider is Cline, isClineProvider = cline or cline-pass, sdk/packages/shared/src/providers/utils.ts:1-3; override path sdk/packages/shared/src/prompt/cline.ts:169-177); credential userinfo stripped from remote URLs (sdk/packages/shared/src/prompt/cline.ts:55-77). VS Code builds the metadata only for the Cline provider (apps/vscode/src/sdk/cline-session-factory.ts:1066-1075).

B3 Which rule files reach the system prompt? RULE · code
Answered how

Code scans a fixed list of places: the workspace AGENTS.md, <workspace>/.clinerules and <workspace>/.cline/rules, the global ~/.agents/AGENTS.md, the global Cline rules directories, and rules.md under managed plugin roots in <workspace>/.cline. A rule marked disabled: true, or enabled: false with no disabled value, is dropped, the rest are sorted by name and appended under # Rules on each run, provided rules are enabled for the session.

Held by

search paths sdk/packages/shared/src/storage/paths.ts:586-601 (workspace AGENTS.md, .clinerules, .cline/rules via sdk/packages/shared/src/storage/paths.ts:536-543, global ~/.agents/AGENTS.md, global rules dirs); discovery sdk/packages/core/src/extensions/config/user-instruction-config-loader.ts:509-591 (markdown files plus a root AGENTS.md; managed .cline plugin rules.md :512-520), definition sdk/packages/core/src/extensions/config/user-instruction-config-loader.ts:673-698 (id = normalized rule name); selection sdk/packages/core/src/runtime/safety/rules.ts:40-70 (enabled = not disabled, sorted by name); registered sdk/packages/core/src/extensions/config/user-instruction-plugin.ts:255-261 (only with includeRules); appended per run sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:754-771. VS Code reaches the same service (apps/vscode/src/sdk/vscode-session-host.ts:168-174, apps/vscode/src/sdk/SdkController.ts:1112-1124).

B4 Which skills does the model learn exist? RULE · code
Answered how

Only when the skills tool is registered (tools on, skills extension on, configured skills exist, tool not removed by preset or policy) does the model learn of skills: the tool description lists every configured skill that passes the session's allowed-skill filter (matched by id, name or bare suffix) and is not disabled, by name, or by id when the id is namespaced. Descriptions are not listed.

Held by

sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:521-545 (skills tool only when tools on, skills extension on, skills configured and the tool survives presets/policies); sdk/packages/core/src/extensions/config/user-instruction-plugin.ts:101-130 (allowed-skill filter by id, name or bare suffix; disabled skills dropped from the list); listed names reach the model through the skills tool description (sdk/packages/core/src/extensions/tools/definitions.ts:809-818).

B5 What does a configured workflow or skill command expand to when it is typed? RULE · code
Answered how

Code substitutes the command's instruction body, with an agent-plugin skill's root prepended as a <skill-root> tag; the shape of the result depends on the path. The CLI/core leading-slash path returns the body followed directly by the rest of the typed text; a command registered through the user-instruction plugin returns the body, a blank line, and the trimmed remainder; VS Code replaces the token in place, keeping text on both sides. The core resolver expands a skill unless the host passes expandSkillCommands: false, which the CLI does when the skills tool is available (A7); VS Code expands only workflows and builtins (A6).

Held by

workflow and skill expansion text: sdk/packages/core/src/extensions/config/runtime-commands.ts:63-79 (resolveCommandInstructions; an agent-plugin skill gets its root prepended), used by the leading-slash resolver (sdk/packages/core/src/extensions/config/runtime-commands.ts:161, body + raw remainder) and by registered commands (sdk/packages/core/src/extensions/config/user-instruction-plugin.ts:275-292, body + blank line + trimmed remainder). VS Code in-place replacement incl. builtins: apps/vscode/src/sdk/slash-command-expansion.ts:201-203. Skill expansion when the skills tool is absent: apps/cli/src/runtime/prompt.ts:93-102.

B6 Which tools does the model get this turn? RULING · code
Answered how

At session build, code starts from the mode's preset (act, plan or yolo), then applies the model-routing rules (the defaults unless the caller supplies its own list; an empty list applies none): with the defaults, in act mode only, an openai-native provider or a model id containing "codex" or "gpt" gets apply_patch in place of editor. Tool policies (enabled: false) and global disables remove tools; provider-native web_search (not in yolo, when supported and globally enabled), image_generation, MCP tools and team/agent tools are added; and a final policy filter runs. Each turn, extension tools are merged in (config tools win on a name clash), and every tool is withheld when the model's capability list is populated without tools or the model uses a dedicated image-generation operation.

Held by

sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:141-182 (createBuiltinToolsList: mode preset sdk/packages/core/src/extensions/tools/presets.ts:20-128, model routing sdk/packages/core/src/extensions/tools/model-tool-routing.ts:60-134, policies and global disables sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:71-99); provider-native web_search (not in yolo) and image_generation (sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:419-439); MCP tools from settings and agent plugins (sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:583-598, loader :207-312); configured agents and team tools (:655-815); final filter :817; per turn, extension tools merged and all tools dropped when the model's capability list lacks tools or it uses dedicated image generation (sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:963-989; capability check fails open when the list is empty, sdk/packages/shared/src/llms/model-info.ts:231-241). VS Code swaps in its own terminal tool and MCP hub tools (apps/vscode/src/sdk/vscode-session-host.ts:120-160, not re-read).

B7 What does an @-mention pull into a VS Code message? RULE · code
Answered how

After slash-command expansion, code replaces each recognised mention with a short label and appends its content: a URL is opened in a browser and converted to markdown; a file is inlined as text (binary files get a placeholder); a folder lists its entries and inlines its immediate non-binary files, without recursing; @problems adds workspace diagnostics, @terminal the latest terminal output, @git-changes the working-tree state, and a 7-40 character hex token that commit's info. A bare / is skipped; with several workspace roots an unprefixed path is looked up in all of them and every hit is included.

Held by

apps/vscode/src/core/mentions/index.ts:58-332 (parseMentions: URLs fetched to markdown via a browser, files and folders inlined (one level, binaries skipped apps/vscode/src/core/mentions/index.ts:334-388), @problems diagnostics, @terminal latest output, @git-changes, commit hashes; bare / skipped apps/vscode/src/core/mentions/index.ts:117-123; multi-root search across all roots apps/vscode/src/core/mentions/index.ts:153-209). Called from apps/vscode/src/sdk/SdkController.ts:1194-1215, after slash-command expansion (:1195).

B8 What does a CLI @file mention attach (inline image, file attachment, or nothing)? RULE · code
Answered how

After slash-command resolution, code finds @ mentions that start with /, ~/, ./ or ../ (optionally quoted) and resolves each against the home directory for ~/ and against the process's working directory otherwise (so @/x is the filesystem path /x). An existing image file becomes a data-URL image and is replaced by [image: name]; any other existing file is replaced by [file: name] and attached by path, its text loaded later by the runtime's file loader; a missing path or a directory prints a warning and stays as typed.

Held by

apps/cli/src/runtime/prompt.ts:40-205 (buildUserInputMessage: @/, @~/, @./, @../ paths resolved by apps/cli/src/runtime/prompt.ts:77-82; images become data URLs, other files become attachments loaded later by buildUserFileContentBlock, sdk/packages/core/src/runtime/orchestration/user-input-builder.ts:118-159).

B9 How does the model learn which mode each message was sent in? RULE · code
Answered how

Code wraps each user message as <user_input mode="..."> with the mode it was sent in (default act), and, after a UI toggle, prepends a <mode_notice> to the next message saying which mode the person switched from and to; a toggle that returns to the starting mode before anything is sent cancels the notice. Outside yolo, the system prompt's mode-tag section tells the model how to read both tags and that the newest message's mode governs.

Held by

sdk/packages/shared/src/prompt/format.ts:5-10 (formatUserInputBlock), sdk/packages/shared/src/prompt/format.ts:41-80 (formatModeSwitchNotice, createModeSwitchNoticeTracker: a plan→act→plan round trip cancels; UI toggles only), explained to the model by MODE_TAG_INSTRUCTIONS (sdk/packages/shared/src/prompt/cline.ts:15-17, omitted in yolo sdk/packages/shared/src/prompt/cline.ts:188-198).

B10 Which earlier file reads does the model see as "outdated" instead of their content? RULE · code
Answered how

When building the provider request, code marks a successful read/read_files result as outdated for a path or line range when a different read or file block is the last recorded full-content owner of that path, or a different read is the last one of that exact range; error results are never marked. Marked reads are only rewritten to "[outdated - see the latest file content]" once the newly stale content adds up to at least 64 KB (env CLINE_MESSAGE_BUILDER_MIN_OUTDATED_REWRITE_BYTES, 0 = eager), and a rollback that makes a read current again un-marks it.

Held by

sdk/packages/core/src/session/services/message-builder.ts:371-454 (commitOutdatedRewrites: a read is outdated when a different read or file block is the last recorded full-content owner of its path, or a different read is the last one of that exact range sdk/packages/core/src/session/services/message-builder.ts:933-946; rewrites are batched until 64 KB is reclaimable sdk/packages/core/src/session/services/message-builder.ts:38-40, :440-442); replacement sdk/packages/core/src/session/services/message-builder.ts:948-1005.

B11 Is a tool call that never got a result repaired before the transcript is sent? RULE · code
Answered how

Yes, always, by code. When the request is built, every assistant tool_use with no matching tool_result anywhere in the history gets a synthesized error result "Tool execution was interrupted before a result was produced. Tool: <name>.", placed in the next tool-result message or in a new user message before the next non-tool turn. History migrated from the legacy VS Code extension gets a plain (not flagged as error) result reading "[migration] Tool result missing in legacy conversation history."

Held by

sdk/packages/core/src/session/services/message-builder.ts:538-747 (addMissingToolResults: synthesizes an is_error tool result "Tool execution was interrupted..." sdk/packages/core/src/session/services/message-builder.ts:51-52, :726-747); VS Code legacy migration inserts a result with "[migration]" text and no error flag (apps/vscode/src/sdk/initial-message-sanitizer.ts:48-57).

B12 What prior transcript does the model see when a task is resumed? RULE · code
Answered how

In VS Code, code reads the task's persisted SDK messages; for a task flagged as legacy it passes those to the legacy converter, which produces the seed, and otherwise seeds with the persisted messages as they are. The resumed session takes the task's original cwd but the current global Plan/Act mode. On every run the orchestrator then seeds the model with the whole stored conversation, which the message builder still rewrites per request (B10, B11).

Held by

apps/vscode/src/sdk/sdk-task-resume.ts:42-71 (persisted SDK messages; for a legacy task, getLegacyResumeInitialMessages with those messages passed in, apps/vscode/src/sdk/sdk-task-resume.ts:54-64); per run the orchestrator seeds the whole stored transcript (sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:993-1001).

B13 After a checkpoint restore, which part of the conversation does the model keep? RULE · code
Answered how

Code keeps every message up to and including the person's message that started the chosen run, dropping that run's replies and everything after, unless the caller sets restoreMessages: false; the checkpoint used is the latest one recorded at or before that run. A run folded inside a compacted summary message cannot be targeted and the restore throws, except the last run the summary represents; a fork 'before' a run keeps only the messages before its user message.

Held by

sdk/packages/core/src/session/checkpoint-restore.ts:245-264 (trimMessagesToCheckpoint, trimMessagesBeforeUserRun; run lookup sdk/packages/core/src/session/checkpoint-restore.ts:217-243) and sdk/packages/core/src/session/checkpoint-restore.ts:266-303 (createCheckpointRestorePlan; checkpoint = latest at or before the run, :202-215).

B14 Which organization-managed rules, workflows and skills reach the session? RULE · code
Answered how

When remote config is discovered for the organization and the org has not been opted out locally, code takes the org's rules, workflows and skills from it and drops each one the person has toggled off in their remote rule, workflow or skill toggles unless it is marked alwaysEnabled (via isInstructionEnabled); skills are carried as managed instructions rather than as part of the SDK remote config. With no org, no remote config, or an opt-out, none reach the session.

Held by

apps/vscode/src/core/storage/remote-config/sdk-control-plane.ts:202-222 (org rules and workflows filtered by the person's remote toggles via isInstructionEnabled; skills adapted to managed instructions and filtered by the remote skill toggles); returns nothing for no org, no config or opt-out (apps/vscode/src/core/storage/remote-config/sdk-control-plane.ts:179-191).

B15 What extra context do the person's hook scripts add to this turn? RULING · external
Answered how

In VS Code, when hooksEnabled is on and hook files exist, the person's scripts decide: before a run the TaskStart and UserPromptSubmit hooks run in turn, and any non-cancelling contextModification they return is joined and appended to the turn as context; PreToolUse and PostToolUse hooks can likewise append context around each tool call. A hook that sets cancel stops instead, and its text becomes the stop reason, never context. The CLI path goes through the core file-hook extension, not traced here.

Held by

the person's hook scripts (TaskStart, UserPromptSubmit, PreToolUse, PostToolUse), mapped at apps/vscode/src/sdk/hooks-adapter.ts:58-75 (mapStopOrContextResult: non-cancelling contextModification becomes appendContext; scripts run by HookFactory); TaskStart + UserPromptSubmit context joined (apps/vscode/src/sdk/hooks-adapter.ts:131-145); tool hooks apps/vscode/src/sdk/hooks-adapter.ts:147-252. CLI uses the core file-hook extension (sdk/packages/core/src/services/local-runtime-bootstrap.ts:433-446; not read in detail).

B17 What does the model see of a user-attached file? RULE · code
Answered how

Code builds the first user content as the message text, then one image block per attached image (a data: URL keeps its media type; any other non-empty string is taken as raw base64 PNG), then one file block per attached path holding the text the runtime's loader returns, or "Error fetching content: ..." if loading fails. With no images and no files the message is sent as plain text.

Held by

sdk/packages/core/src/runtime/orchestration/user-input-builder.ts:10-37 (buildInitialUserContent: text, then images, then file blocks); non-data-URL image strings are assumed PNG (sdk/packages/core/src/runtime/orchestration/user-input-builder.ts:110-115).

B18 Should the conversation (and workspace) roll back to this checkpoint? RULING · human
Answered how

The person decides by choosing a checkpoint's restore action in VS Code, picking the restore type the webview offers; code forwards the checkpoint's run number and that type to the controller's SDK restoreCheckpoint, and B13 carries it out. Nothing in the code initiates a rollback on its own.

Held by

the person, via the restore action (apps/vscode/src/core/controller/checkpoints/checkpointRestore.ts:6-23, forwarding checkpointRunCount and restoreType; CLI equivalent not traced), carried out by B13.

C. Choosing the next action (11 on this edition)

C1 What should the agent do next: which tools, with which arguments, or answer and stop? RULING · llm
Answered how

The session's main model answers it on every loop iteration: the runtime sends the system prompt, transcript and tool list, then processes the tool calls that come back and runs the eligible ones; a reply with no tool call ends the run as completed, unless a completion policy (set when submit_and_exit is among the tools, or for agent teams) injects a reminder and loops again. When the model's info says it cannot call tools (or it is a dedicated image-generation model), the session sends no tools and drops the completion policy, so no completion reminder can keep the run going; the interruption, error and output-limit paths still apply.

Held by

the session's main model, called on each loop iteration in sdk/packages/agents/src/agent-runtime.ts:836-1023 (AgentRuntime.execute; request built by prepareModelRequest, sdk/packages/agents/src/agent-runtime.ts:1656-1736); runtime and tool list built per user turn at sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:948-1028. Sub-agents run the same loop.

C2 Is a streamed tool call well formed enough to become a call: does it have a name, and do its arguments parse? RULE · code
Answered how

Code assembles streamed tool-call pieces per call id (or index) and, when the stream ends, drops any call with no tool name, recording it only in message metadata. A structured input from the adapter wins over text; empty argument text becomes {} with no error and goes on through the normal checks; text that JSON.parse rejects becomes a call with input {} and a parse error, which the runtime turns into an error result before any hook or approval. In an interrupted turn every tool call is dropped (C10).

Held by

sdk/packages/agents/src/agent-runtime.ts:1877-1937 (assembly per tool-call id or index), finalize sdk/packages/agents/src/agent-runtime.ts:2015-2057, parseToolInput and parseToolArguments (sdk/packages/agents/src/agent-runtime.ts:2814-2889); the AI SDK adapter emits whole calls (sdk/packages/llms/src/providers/ai-sdk.ts:1688-1709).

C3 When a provider streams a tool call's arguments in pieces, is each piece a continuation or a fresh copy of the whole? RULE · code
Answered how

Code guesses from the piece's shape: if text has already arrived and the new piece (after leading whitespace) begins with { or [, it replaces everything so far; otherwise it is appended. The first piece is always taken as is.

Held by

mergeToolInputText (sdk/packages/agents/src/agent-runtime.ts:2891-2900), called at sdk/packages/agents/src/agent-runtime.ts:1930-1935.

C4 Should a malformed tool payload be repaired, and into what? RULING · code
Answered how

On the AI SDK route, when the SDK rejects a call's argument text, code tries a repair: straight JSON.parse, then jsonrepair (skipped when a string is left unterminated, the truncation guard), then a one-key bare-value repair; valid JSON that failed the schema, unknown tool names and empty text are not repaired. Separately, after the stream, the runtime parses JSON-looking strings where the tool's schema expects an array or object, and read_files and run_commands accept several input shapes and re-join split pieces.

Held by

sdk/packages/llms/src/providers/ai-sdk.ts:919-946 (repairMalformedToolCall, wired as experimental_repairToolCall at sdk/packages/llms/src/providers/ai-sdk.ts:2447), using parseJsonStream (sdk/packages/shared/src/parse/json.ts:70-102; guard hasUnterminatedString :15-36; bare-object repair :38-68). Per-tool leniency on the same question: normalizeJsonLikeStringsForSchema (sdk/packages/shared/src/parse/json.ts:203-246, applied at sdk/packages/agents/src/agent-runtime.ts:2437); read_files shapes (sdk/packages/core/src/extensions/tools/definitions.ts:286-319, sdk/packages/core/src/extensions/tools/helpers.ts:117-135); run_commands shapes and heredoc re-join (sdk/packages/core/src/extensions/tools/helpers.ts:137-165, sdk/packages/core/src/extensions/tools/definitions.ts:116-178). No schema validation in the provider layer (comment ai-sdk.ts:872-876).

C5 Should a failed model request be re-sent inside the provider layer (request start, mid-stream, empty reply)? RULING · code
Answered how

Code re-sends inside the AI SDK call with fixed budgets: up to 5 retries of a failed request start, up to 3 retries of error parts after streaming began, and, outermost, up to 3 attempts when an attempt produced nothing at all and finished stop, other or unknown or its stream died on a network error before any output (each AI SDK vendor gets it unless its factory sets retryEmptyResponses: false; none in the checkout does). None of the numbers is a setting.

Held by

sdk/packages/llms/src/providers/ai-sdk.ts:2436-2476 (streamText options: maxRetries: MODEL_REQUEST_MAX_RETRIES, 5, and streamRetries: MODEL_STREAM_MAX_RETRIES, 3, constants at sdk/packages/llms/src/providers/ai-sdk.ts:1096-1097), and the outermost withEmptyResponseRetry (sdk/packages/llms/src/providers/ai-sdk.ts:2151-2166; middleware sdk/packages/llms/src/providers/middleware/retry-empty-response.ts, default 3 attempts at :97).

C6 Should the agent loop retry a turn that failed with a provider error, and how long should it wait? RULING · code
Answered how

Code retries the whole turn up to 3 times, waiting 1 s, 2 s, 4 s (cap 15 s), only when the turn finished with an error, produced no content and no provider tool activity, was not classed auth or context overflow, and was judged retryable: by the model boundary's own flag if it sent one, else by the classifier (the AI SDK's typed isRetryable, else a transient HTTP status, else the one message "provider returned error").

Held by

sdk/packages/agents/src/agent-runtime.ts:1242-1314 (withProviderErrorRetry, isRetryableProviderErrorTurn; constants sdk/packages/agents/src/agent-runtime.ts:87-91); retryability from the boundary's errorRetryable, else isRetryableProviderError (sdk/packages/llms/src/providers/error-classification.ts:425-437; statuses :319-321; message pattern :330, :409-412).

C7 A turn that ended with no recognized finish reason: continue it once, or fail? RULING · code
Answered how

Code continues once: when a turn ends with finish reason unknown, was not interrupted, and carried no tool calls and no provider tool activity, it records the partial reply, adds the fixed user-role line "Previous turn ended unexpectedly. Continue from where you left off." and re-issues the request. If that second attempt also ends unknown with no tool call the run fails; an unknown turn that did carry tool calls runs them and fails only if none of them succeeded. The once is per loop iteration, not per run.

Held by

sdk/packages/agents/src/agent-runtime.ts:1202-1233 (generateAssistantMessageWithProviderRetry; continuation literal sdk/packages/agents/src/agent-runtime.ts:1227-1230); failure checks sdk/packages/agents/src/agent-runtime.ts:920-923 and :984-996.

C8 A turn cut off at the model's output-token limit with no tool call: nudge the model to be shorter and try again, or fail? RULING · code
Answered how

Code first tries one forced compaction and retry per run (only when the runtime has a prepareTurn, the turn has no tool calls and no provider tool activity); if the turn still ends at the output limit with no tool call, it appends a fixed "be concise" user message and loops, up to 3 consecutive times, the count resetting whenever a turn yields a tool call. After that the run fails.

Held by

sdk/packages/agents/src/agent-runtime.ts:1163-1183 (recoverFromIncompleteMaxTokensTurn; limit MAX_TOKENS_RECOVERY_LIMIT at sdk/packages/agents/src/agent-runtime.ts:72; counter reset :943-946; called at :925-938). The forced-compaction retry that runs first (sdk/packages/agents/src/agent-runtime.ts:1369-1371, :1427-1447) belongs to compaction, a separate seat.

C9 A turn that came back empty or content-filtered: what does the run say, and does it end? RULE · code
Answered how

Code ends the run when a finished, uninterrupted turn has no content: finish error raises the recorded provider error (or "Model stream failed"), finish content-filter raises the content-filter message, anything else raises "Model returned empty response". Turns carrying only provider tool activity, or ending max-tokens or unknown, are kept for C7/C8; an interrupted empty turn just loops.

Held by

sdk/packages/agents/src/agent-runtime.ts:866-899 (empty-turn checks; CONTENT_FILTER_EMPTY_TURN_MESSAGE at sdk/packages/agents/src/agent-runtime.ts:98-99).

C10 When the person's new message interrupts a model reply mid-stream, what of the partial reply is kept? RULE · code
Answered how

When a new message arrives mid-reply, code aborts only the model request. The partial reply keeps its visible text and media and loses all tool calls (even fully streamed ones) and reasoning; an empty partial is not recorded. The loop then starts the next request, which picks up the queued message at the request boundary; tools already running finish normally.

Held by

sdk/packages/agents/src/agent-runtime.ts:632-635 (notifyPendingUserMessage); partial-reply filter sdk/packages/agents/src/agent-runtime.ts:2012-2022; loop sdk/packages/agents/src/agent-runtime.ts:854-862, :906-916; queued message read at sdk/packages/agents/src/agent-runtime.ts:1687-1695, :2302-2321 (queue policy is A13).

C11 Should a tool call the provider already executed (or marks provider-side) run again locally? RULE · code
Answered how

Code never runs a provider-executed call locally: a streamed call that arrives with an execution marker is recorded as model tool activity, not queued; a queued call whose metadata says toolSource.executionMode === "provider" gets an error result instead of running; and the provider-error retry, the unknown-finish continuation and the max-tokens compaction retry all refuse to replay a turn that had provider tool activity.

Held by

sdk/packages/agents/src/agent-runtime.ts:1878-1900 (provider-executed calls kept as modelToolActivities; emitted by sdk/packages/llms/src/providers/ai-sdk.ts:1672-1686); local refusal sdk/packages/agents/src/agent-runtime.ts:2422-2434; replay refusals :1214-1220, :1303-1306, :1444-1446.

E. Execution and observation (16 on this edition)

E1 Do the tool calls of one turn run one after another, or at the same time? RULE · code
Answered how

Code prepares every call of the turn first, in order (hooks and approvals), then runs them one after another unless the tool or the runtime says parallel, in which case adjacent parallel calls run together with no cap. The runtime is parallel only when maxParallelToolCalls is set to 2 or more; no non-test code in the checkout sets it (and the schema carrying a default of 8 is used by no non-test code), so built-in tools run in sequence and only the sub-agent tools overlap.

Held by

sdk/packages/agents/src/agent-runtime.ts:2343-2381 (executeToolCalls); runtime default sequential at sdk/packages/agents/src/agent-runtime.ts:614-617; mode from resolveToolExecution (sdk/packages/core/src/runtime/config/agent-runtime-config-builder.ts:187-198); sub-agent tools declare executionMode: "parallel" (sdk/packages/core/src/extensions/tools/team/spawn-agent-tool.ts:122, sdk/packages/core/src/extensions/tools/team/configured-agent-tool.ts:152).

E2 Are the commands inside one run_commands call run in order, or all at once? RULE · code
Answered how

Code runs every command in one run_commands call at the same time (Promise.all), each from the same cwd, after re-joining a heredoc that the model split across array elements. Nothing orders them; whether they are independent is left to the model, which the description asks to batch only independent commands.

Held by

sdk/packages/core/src/extensions/tools/definitions.ts:180-257 (executeShellCommands, Promise.all); heredoc re-join sdk/packages/core/src/extensions/tools/definitions.ts:116-178.

E3 When is a running shell command stopped (CLI, hub and SDK hosts)? RULING · code
Answered how

Code stops it on a 30 s timer or on abort, killing the whole process tree (taskkill /T /F on Windows, SIGKILL to the process group elsewhere). Neither the CLI nor the core runtime sets the timeout, so both the executor default and the tool wrapper's race stay at 30 s; a person can instead release a running command through a hub client's proceedWhileRunning, which the CLI TUI does not offer.

Held by

sdk/packages/core/src/extensions/tools/executors/bash.ts:717-1118 (spawnAndCollect: kill tree :773-817, timer :837-843, abort :820, :845-848); 30 s from the executor default (sdk/packages/core/src/extensions/tools/executors/bash.ts:1138) and the wrapper race (sdk/packages/core/src/extensions/tools/definitions.ts:515, :216-220); the core runtime passes only the execution controller (sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:165-167).

E4 Did the shell command succeed, and has it finished? RULE · code
Answered how

Code decides from the exit code alone: 0 resolves with the output, any other code (or a signal) rejects with the output attached. If the shell has exited but a background child still holds the pipes, it settles 1 s later with a trailing note; a spawn failure rejects; a command released to the background resolves at once with a log-path notice.

Held by

sdk/packages/core/src/extensions/tools/executors/bash.ts:968-1027 (completeCommand); exit-grace sdk/packages/core/src/extensions/tools/executors/bash.ts:1066-1096 (EXIT_STREAM_GRACE_MS :52; comment cites #12417); spawn failure :1098-1108; detached early resolve :850-897.

E5 Which part of a long command output does the model see? RULING · code
Answered how

Code keeps, per stream, the first half of a 48 000-character budget verbatim and rolls the rest so the newest output survives; at completion stdout and stderr are joined (stderr after a [stderr] marker) and, if anything was dropped or the join is over budget, middle-truncated to about the first and last 24 000 characters with a notice. The early notice for a command released to the background joins both streams without that final cut.

Held by

sdk/packages/core/src/extensions/tools/executors/bash.ts:457-506 (createRollingCollector), then truncateCommandOutput (sdk/packages/core/src/extensions/tools/executors/output-limits.ts:20-38, MAX_COMMAND_OUTPUT_CHARS :18; called at sdk/packages/core/src/extensions/tools/executors/bash.ts:992-997, :1014-1022); streams combined at :985-991, :1010-1012.

E6 In VS Code, did a command run in the visible terminal succeed? RULE · code
Answered how

In the default vscodeTerminal mode, code reads the terminal's completion details: a terminal closed mid-command, or a completion it could not observe, is a failure (exit code 1, with a message telling the model not to assume success); a non-zero exit code from shell integration is a failure; an observed completion with no exit code returns the output as success. A command detached by the person or the 300 s timer returns partial output instead (E7, E8). In backgroundExec mode the core executor decides (E4).

Held by

apps/vscode/src/sdk/vscode-run-commands-tool.ts:222-492 (executeForeground: closed apps/vscode/src/sdk/vscode-run-commands-tool.ts:446-452, unobserved :454-465, non-zero exit :474-481, no exit code :467-473, :483); background mode apps/vscode/src/sdk/vscode-run-commands-tool.ts:562-591 (E3/E4).

E7 Should the agent move on while a command is still running? (the person's "Proceed While Running") RULING · human
Answered how

In VS Code foreground mode the person answers by clicking "Proceed While Running", which detaches every in-flight foreground command; if nobody clicks, code answers after 300 s (E8). The tool call then returns partial output and a log path while the command keeps running. Through the hub, a client's proceedWhileRunning detaches the core executor's commands for a session (or one tool call), and only those whose process identity probe succeeded are detachable; the CLI TUI has no such control.

Held by

the person, through the VS Code button (apps/vscode/src/sdk/SdkController.ts:1605-1610 → apps/vscode/src/sdk/sdk-foreground-command-coordinator.ts:63-73, handle registered per command at apps/vscode/src/sdk/vscode-run-commands-tool.ts:266-268), or a hub client calling proceedWhileRunning (sdk/packages/core/src/hub/server/handlers/run-handlers.ts:385-399 → sdk/packages/core/src/extensions/tools/executors/run-command-execution-controller.ts:25-42; used by the desktop example, excluded).

E8 In VS Code, when does the agent stop waiting for a foreground command on its own? RULING · code
Answered how

In VS Code foreground mode, code detaches the command after 300 s if the person has not, returning partial output and a log path while the command keeps running in the terminal; the wrapper's own race is raised to 60 minutes for that mode, so the 300 s timer normally answers first. A cancelled task sends Ctrl+C to the terminal instead.

Held by

apps/vscode/src/sdk/vscode-run-commands-tool.ts:52 (FOREGROUND_COMMAND_AUTO_PROCEED_MS, timer at apps/vscode/src/sdk/vscode-run-commands-tool.ts:269); wrapper race 60 min (VSCODE_FOREGROUND_RUN_COMMANDS_TIMEOUT_MS, apps/vscode/src/sdk/vscode-run-commands-tool.ts:49; set at apps/vscode/src/sdk/vscode-runtime-builder.ts:105). A VS Code terminal cannot be killed, so the command keeps running (comment :48).

E9 Is a tool call that runs past its time limit stopped, or only reported as failed? RULE · code
Answered how

Only reported, for most tools: each built-in tool except ask_question (no timer at all) wraps its executor in withTimeout, a Promise.race whose timer rejects but never cancels the work, so the model gets a timed-out failure while the operation may still finish. Only the shell executor kills on its own timer (E3); web fetch aborts on its own timer only until response headers arrive, after which the body read has no executor timer; the editor and apply_patch executors have no timer and never check the abort signal, so a timed-out write can still land.

Held by

sdk/packages/core/src/extensions/tools/helpers.ts:48-59 (withTimeout), used by read_files (sdk/packages/core/src/extensions/tools/definitions.ts:333-337), search_codebase (:395-399), run_commands (:216-220), fetch_web_content (:593-597), apply_patch (:682-686), editor (:745-749), skills (:797-805) and submit_and_exit (:877-881). Own timers: shell (E3); web fetch sdk/packages/core/src/extensions/tools/executors/web-fetch.ts:130-132, cleared at :155. No timer or signal check: sdk/packages/core/src/extensions/tools/executors/editor.ts:230-267, sdk/packages/core/src/extensions/tools/executors/apply-patch.ts:404-425.

E10 How is an editor edit applied to the file? RULE · code
Answered how

Code: with insert_line, the new text is inserted at that one-based line boundary; otherwise a missing file is created with new_text (whatever old_text says), an existing file with no old_text is refused, and old_text must occur exactly once after line-ending normalization or nothing is written. Texts over the size limit are refused before the executor runs. A relative path is checked by path arithmetic to stay inside the cwd; absolute paths are accepted anywhere. In VS Code a read-only diff preview is shown around the same SDK write.

Held by

sdk/packages/core/src/extensions/tools/executors/editor.ts:221-268 (createEditorExecutor: insert sdk/packages/core/src/extensions/tools/executors/editor.ts:194-216, create :246-248, no-old_text refusal :249-258, exact-once replace :162-192); size guard sdk/packages/core/src/extensions/tools/helpers.ts:20-33. VS Code preview apps/vscode/src/sdk/sdk-diff-edit-coordinator.ts:59-144 (write is always the SDK executor, :65-67, :131).

E11 Where does an apply_patch hunk land when its context does not match the file exactly? RULING · code
Answered how

Code searches from the parser's current position (after the previous hunk), not from the file top: a canonicalized match, then trailing-space-trimmed (fuzz 1), then fully trimmed (fuzz 100), then the FIRST position whose Levenshtein similarity reaches 0.66 (fuzz 1000), not the best one; an end-of-file hunk first tries the file's tail and adds 10000 if it must fall back. At that position the hunk's old lines are replaced by count, without comparing them. A hunk that matches nowhere fails the whole patch; a fuzzy match reports success with a fuzz number.

Held by

sdk/packages/core/src/extensions/tools/executors/apply-patch-parser.ts:347-431 (findContext; threshold sdk/packages/core/src/extensions/tools/executors/apply-patch-parser.ts:404-412, end-of-file branch :421-428); applyChunks replaces delLines.length lines unchecked (sdk/packages/core/src/extensions/tools/executors/apply-patch.ts:162-193); unmatched hunk fails the patch (sdk/packages/core/src/extensions/tools/executors/apply-patch.ts:389-391).

E12 What does the model see when it reads a file? RULE · code
Answered how

Code: a .gif/.png/.jpg/.jpeg/.webp file becomes an image part when the model accepts images (else an error; images over 10 MB refuse); any other file over 100 MB refuses; everything else streams as UTF-8 text in a window of at most 2 000 lines and 48 000 characters, long lines cut at 2 000 characters, with a "Showing lines a-b of n" footer when more remains. cline:// paths read the oversized-result cache. There is no binary detection.

Held by

sdk/packages/core/src/extensions/tools/executors/file-read.ts:208-285 (createFileReadExecutor: images sdk/packages/core/src/extensions/tools/executors/file-read.ts:248-269, 100 MB refusal :271-276, cline:// cache :218-230); text window readTextWindow (sdk/packages/core/src/extensions/tools/executors/file-read.ts:82-193). The tool description says binaries are not supported (sdk/packages/core/src/extensions/tools/definitions.ts:280).

E15 Who answers the agent's clarifying question (ask_question)? RULING · human
Answered how

The person answers, through the host's prompt: in VS Code handleAskQuestion; in the interactive CLI the TUI's prompt handler; in one-shot CLI a terminal readline that takes an option number or free text. Code answers instead in two CLI cases, with the first option and no notice to the model: when stdin or stdout is not a TTY, and when the interactive TUI has no prompt handler mounted; an empty reply at the terminal prompt also yields the first option. The tool is absent when submit_and_exit is enabled (yolo).

Held by

the person: VS Code apps/vscode/src/sdk/SdkController.ts:425 (handleAskQuestion); CLI interactive TUI apps/cli/src/runtime/interactive/session-runtime.ts:171-176; CLI one-shot terminal prompt apps/cli/src/utils/approval.ts:120-164 (wired at apps/cli/src/runtime/run-agent.ts:167). Tool defined at sdk/packages/core/src/extensions/tools/definitions.ts:831-850; removed whenever submit_and_exit is on (sdk/packages/core/src/extensions/tools/definitions.ts:981-986).

E16 What does the model see when a tool throws, does not exist, was refused, or was blocked? RULE · code
Answered how

Code turns every non-run into an error result the model sees: a skip reason (invalid JSON arguments, provider-side tool, a hook's skip, a policy-disabled tool, or a refused approval, which carries the suffix "NOT a tool or system failure. Clarify with user before proceeding.") becomes { error }; an unknown name becomes "Unknown tool: <name>"; a thrown error becomes its message. A tool that needs approval with no approval callback configured, or whose callback throws, counts as refused. An afterTool hook may still replace the result (E17).

Held by

sdk/packages/agents/src/agent-runtime.ts:2543-2647 (executePreparedTool: skip sdk/packages/agents/src/agent-runtime.ts:2555-2559, unknown name :2560-2564, thrown error :2588-2595); skip reasons set in prepareToolExecution (sdk/packages/agents/src/agent-runtime.ts:2405-2501; TOOL_REJECTION_SUFFIX at sdk/packages/shared/src/llms/tools.ts:104-105); no-callback and throwing-callback refusals sdk/packages/agents/src/agent-runtime.ts:2509-2514, :2533-2540 (the gate itself is a separate seat).

E17 Can a hook or plugin rewrite or add to what the model sees from a tool? (PostToolUse / afterTool) RULING · external
Answered how

Partly, and it depends on who wrote the hook. The person's PostToolUse hook files (VS Code adapter, core hook-file hooks) can only add a context block or stop the run; their mappers return stop, reason or appendContext and never result. An in-process SDK plugin or extension afterTool hook can do that and also REPLACE the tool result. All run after every call to a known tool (not after an unknown tool name), and only when such hooks exist (in VS Code, also when hooks are enabled).

Held by

afterTool hooks, called after every tool in sdk/packages/agents/src/agent-runtime.ts:2601-2625 (appendContext queued :2613-2620; a returned result replaces the tool result :2622-2624); merged from config and extension hooks at sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:1152-1178 and :266-281. The person's hook files map to stop/context only: VS Code apps/vscode/src/sdk/hooks-adapter.ts:199-252; core sdk/packages/core/src/hooks/hook-file-hooks.ts:1043-1047 via stopOrContextResultFromControl (sdk/packages/core/src/hooks/hook-file-hooks.ts:610-627).

E18 When does an MCP tool call give up, and what comes back? RULE · code
Answered how

Code gives up when the MCP client's request timeout passes: the server's configured timeout in seconds (clamped to 1-3600), else 60 s; the error is rewritten to name the server and becomes an error result. The built-in tool withTimeout race does not wrap MCP tools. Arguments that are not a plain object are dropped, and the server receives {}.

Held by

sdk/packages/core/src/extensions/mcp/client.ts:874-895 (callTool with timeout: this.requestTimeoutMs, set at sdk/packages/core/src/extensions/mcp/client.ts:235-237 from resolveMcpRequestTimeoutMs, sdk/packages/core/src/extensions/mcp/timeout.ts:7-9; default 60 s at sdk/packages/shared/src/mcp.ts:10, :33-38; per-server timeout field sdk/packages/core/src/extensions/mcp/config-loader.ts:93, :101); non-object arguments sent as undefined (sdk/packages/core/src/extensions/mcp/tools.ts:41-44), then {} (client.ts:884). VS Code routes MCP through its own hub (vscode-session-host.ts:150, not read).

F. Limits and memory (13 on this edition)

F1 How many consecutive failing turns does a run tolerate before the limit fires? RULING · code
Answered how

At the end of each turn code counts the turn as a mistake only when at least one tool call failed and none succeeded; any turn with a successful tool resets the count, and a text-only turn neither counts nor resets. When the count reaches execution.maxConsecutiveMistakes (core default 6; CLI default 3 or --retries), the limit fires; a limit of 0 means it never fires (if (!max || next < max)).

Held by

sdk/packages/core/src/runtime/safety/mistake-tracker.ts:88-150 (MistakeTracker.record), fed by sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:1362-1383 (a turn counts as a mistake only when at least one tool failed AND none succeeded; any successful tool resets the count, :1378-1382). Limit config.execution.maxConsecutiveMistakes ?? 6 (session-runtime-orchestrator.ts:471); CLI default 3 (apps/cli/src/runtime/defaults.ts:15, applied apps/cli/src/main.ts:1073-1074, flag --retries apps/cli/src/commands/program.ts:64-65). VS Code sets no value, so 6 (grep of apps/vscode/src for maxConsecutiveMistakes: 0 non-test hits).

F2 When the mistake limit is reached, does the run stop or continue? (VS Code, yolo CLI, non-TTY CLI, sub-agents, scheduled runs) RULING · code
Answered how

Code decides by host. VS Code's handler always returns stop after posting an error row. The CLI one-shot and the TUI both return stop whenever the * tool policy is not autoApprove: false, which is the CLI default (apps/cli/src/main.ts:885-895; overridden only by --auto-approve false or a persisted toolAutoApprove); the one-shot also stops without a TTY. With no callback at all (sub-agents, teammates, hub runs whose client contributed none) the tracker stops.

Held by

VS Code always stops and asks the person to send a message (apps/vscode/src/sdk/sdk-interaction-coordinator.ts:96-116, wired apps/vscode/src/sdk/SdkController.ts:391); CLI one-shot stops in yolo (apps/cli/src/runtime/format.ts:30-36) or without a TTY (format.ts:41-46); CLI interactive stops in yolo (apps/cli/src/runtime/interactive/mistakes.ts:16-21); no callback configured → stop (mistake-tracker.ts:206-211), which is the path for sub-agents (delegated-agent.ts:129-146 passes no callback) and hub/cron runs unless a client contributes one (sdk/packages/core/src/hub/runtime-host/hub-runtime-host.ts:357-358).

F3 When the mistake limit is reached, does the run stop or continue? (interactive CLI with a person present) RULING · human
Answered how

Absent by default: the person is asked only when the CLI's * tool policy has auto-approve off (--auto-approve false or a persisted setting); otherwise code stops first (F2). When asked, "Stop this run" / "2" / "stop" / "n" / "no" stops, "Try a different approach" / "1" / an empty answer continues with a fixed guidance line, and any other text continues with that text appended as a user message; if the TUI ask is not wired the first option is chosen and the run continues.

Held by

the person answers "Try a different approach" / "Stop this run" or types guidance (apps/cli/src/runtime/interactive/mistakes.ts:22-58, TUI ask apps/cli/src/runtime/run-interactive.ts:270-273; one-shot TTY apps/cli/src/runtime/format.ts:47-78). Typed text becomes a user message (mistake-tracker.ts:129-135).

F4 Is the model repeating the same tool call, and when does repetition stop the run? RULING · code
Answered how

On every tool-started event (except calls carrying an execution field), code compares the tool name and key-sorted JSON input with the previous call; the 3rd identical call in a row appends a user-role "try a different approach" notice, and the 5th or later forces the mistake count to the limit, which then goes to the F2/F3 decision. On unless execution.loopDetection is exactly false; an unset value uses the 3/5 defaults.

Held by

sdk/packages/core/src/runtime/safety/loop-detection.ts:66-87 (checkRepeatedToolCall: identical name and key-sorted JSON input, consecutive), thresholds soft 3 / hard 5 (:113-116; CLI the same, apps/cli/src/runtime/defaults.ts:6-9); applied at session-runtime-orchestrator.ts:1465-1495 (soft → a user-role notice; hard → a forced mistake at the limit, forceAtLimit, which then goes through F2/F3).

F5 Is there an iteration or wall-clock cap on a run? RULING · code
Answered how

Code loops while config.maxIterations is undefined or not yet reached and raises "exceeded maxIterations" when it is; VS Code passes undefined and the CLI one-shot and TUI set none, so those runs have no iteration cap. A wall-clock cap exists only where a caller sets one: CLI --timeout (a positive timeoutSeconds arms an abort) and a schedule's optional timeoutSeconds; a schedule's maxIterations is passed through only when set.

Held by

sdk/packages/agents/src/agent-runtime.ts:836-839 (loop while maxIterations undefined or not reached; exceeded → raises :1025-1027). VS Code passes maxIterations: undefined (apps/vscode/src/sdk/cline-session-factory.ts:1206); the CLI one-shot and interactive paths set none (grep of apps/cli/src for maxIterations: schedule wizard only); CLI --timeout aborts a one-shot (apps/cli/src/runtime/run-agent.ts:320-331); cron spec.maxIterations and spec.timeoutSeconds (sdk/packages/core/src/cron/runner/cron-runner.ts:373-390, :743), both optional.

F6 Should the conversation be compacted before this request, and to what size? RULING · code
Answered how

Only when compaction.enabled === true (VS Code: per-task, else global useAutoCondense, default true; CLI: on unless the compaction mode is off), code estimates the request's tokens before each model call and compacts when they reach 0.9 of the model's input limit (128 000 when the model reports none), shrinking the limit by the provider's last real count when the char estimate under-counts (at most 4x). The auto target is 0.7 of the trigger, or 0.5 of the input limit once there are 5+ user/assistant pairs and the model reports an output cap below that limit; overflow recovery and manual compaction use their own targets.

Held by

sdk/packages/core/src/extensions/context/compaction.ts:303-409 (trigger at 0.9 of the effective input limit :355-362, compaction-shared.ts:19; default limit 128 000 when the model reports none compaction.ts:324-328, compaction-shared.ts:15; the char estimate scaled by the provider's last real count, capped at 4x :342-354; target 0.7 of trigger or 0.5 of the window for long conversations :210-228). Present only when compaction.enabled === true (:291-293): VS Code from useAutoCondense (default true, apps/vscode/src/shared/storage/state-keys.ts:281, read cline-session-factory.ts:1115-1118, :1193-1200); CLI on by default (apps/cli/src/utils/compaction-mode.ts:33-43), off available.

F7 What does the compacted history keep? (agentic strategy: the LLM summary) RULING · llm
Answered how

When F6 fires with the agentic strategy (the default), code cuts the history so the most recent ~20 000 estimated tokens stay verbatim, and so does the latest typed prompt unless it is the first message, then one LLM call (the session's model, or compaction.summarizer's, with thinking off) writes a summary, folded onto any previous summary. Whatever non-empty text comes back replaces the cut-away messages as a user-role "Context summary", with a ## Files section appended if the text has none; an empty reply skips compaction.

Held by

sdk/packages/core/src/extensions/context/agentic-compaction.ts:116-318 (runAgenticCompaction); the call generateSummary sdk/packages/core/src/extensions/context/agentic-compaction.ts:70-106; model = the session's model unless compaction.summarizer names another (sdk/packages/core/src/extensions/context/compaction-shared.ts:737-775), thinking off; output cap = an explicit maxOutputTokens as-is, else the lower of 8 192 and the model's reported maxTokens, and none for openai-codex (sdk/packages/core/src/extensions/context/compaction-shared.ts:34, :721-755). Cut point findCutIndex keeps ~20 000 recent tokens and never cuts away the latest typed prompt unless it is the first message (sdk/packages/core/src/extensions/context/compaction-shared.ts:352-385).

F8 What does the compacted history keep? (basic strategy: truncation) RULING · code
Answered how

When the basic strategy is chosen, or forced during overflow recovery, or used as the agentic fallback, code selects every typed user prompt (attachments only on the latest), keeps earlier compaction output untouched, then fills the token target with the newest messages after the latest prompt (snapped forward to an assistant message so no tool pair splits), then each older turn's final non-tool assistant answer, newest first, if it fits; everything else is dropped and summarised mechanically. A final budget pass can still trim what was selected.

Held by

sdk/packages/core/src/extensions/context/basic-compaction.ts:452 onward (runBasicCompaction): every typed user prompt kept (:472-498), the newest messages after the latest prompt that fit (:513-548), each older turn's final assistant answer when it fits (:550-), earlier compaction output frozen (:500-511); the last 3 assistant texts survive inside dropped-work summaries (:59-61).

F9 When a request overflows the context window or the reply hits the output-token limit, is it retried, and how? RULING · code
Answered how

Code, once per run each: a provider error classed context_window_exceeded on a turn with no tool calls forces a compaction and one retry (with no prepareTurn configured it raises at once, and a second overflow raises); a text-only turn cut at the output-token limit gets one forced-compaction retry when prepareTurn exists. After that, a text-only cut-off turn gets up to 3 consecutive "be concise" nudges, the count resetting on any turn with a tool call, and then the run raises with the partial answer kept.

Held by

sdk/packages/agents/src/agent-runtime.ts:1363-1408 (overflow: one forced compaction and retry per run; failure raises ContextWindowOverflowError), :1427-1447 and :1481-1595 (text-only truncated turn: one compaction retry), :1163-1183 (then up to 3 "be concise" nudges, MAX_TOKENS_RECOVERY_LIMIT :72), :925-938 (exhausted → raises with the partial answer kept).

F10 Is a failed model request retried? RULING · code
Answered how

Code retries a turn up to 3 times (4 requests), waiting 1 s, 2 s, 4 s (cap 15 s), only when the attempt finished error with no content and no provider-side tool activity, the error is not classed auth or context overflow, and the error is flagged retryable (the model boundary's typed flag, else a message classifier). An uninterrupted turn with an unknown finish reason and no tool activity gets one "continue from where you left off" continuation; every other turn goes back to the loop unchanged, which raises on a turn still error after retries or still unknown with no tool call (agent-runtime.ts:920-923, :939-942) and otherwise handles it normally.

Held by

sdk/packages/agents/src/agent-runtime.ts:1242-1314 (withProviderErrorRetry, isRetryableProviderErrorTurn): up to 3 retries (:87), backoff 1 s doubling to 15 s (:89-91), only when the failed attempt produced nothing and ran no provider-side tool, never for auth or overflow errors; retryability from the provider's typed flag, else isRetryableProviderError on the message (:2000-2004). An unknown finish with no tool activity gets one continuation prompt (:1212-1232).

F11 How much of a tool result, attachment or long assistant text is sent back to the model? RULING · code
Answered how

Code, every time a request is built: each text entry or string inside a tool result over 8 000 chars, user file attachment over 50 000, or assistant text over 200 000 is cut in the middle (head and tail kept, a marker in between), and if the messages' counted text (text, thinking, file content, tool arguments and tool-result strings; images not counted) still exceeds 6 MB a budget pass truncates further. For tools marked cache-oversized (MCP and Composio tools) an oversized result is still middle-truncated, plus, only when a cache URI exists (the cache refuses a result over 16 MB) and the notice fits under half the total budget, a notice naming that URI, which the model can read with read_files. Three of the limits can be overridden by CLINE_MESSAGE_BUILDER_* environment variables.

Held by

sdk/packages/core/src/session/services/message-builder.ts:29-43 (tool result 8 000 chars, attachment 50 000, assistant text 200 000, repeated tool-call markup 12 000 after 8 repeats, total 6 MB), middle truncation :1100-1197, total-budget pass :1199- ; cacheable tools can get a cache URI notice (:260-280, session-runtime-orchestrator.ts:441-444). Env overrides MESSAGE_BUILDER_LIMIT_ENV (message-builder.ts:44-48).

F12 Should a restorable snapshot of the workspace be taken before this user turn? RULE · code
Answered how

Only when checkpoint.enabled === true (CLI and VS Code on by default, core off): before the first model call of each root-agent run, code takes a snapshot when the run brings a new user turn or that turn number has no checkpoint in the session's history yet. A host-supplied createCheckpoint replaces the built-in one; otherwise, in a git repo, a stash-style commit of the worktree is stored under refs/cline/checkpoints/<session>/<run>, a clean tree records HEAD, and a non-repo gets none.

Held by

sdk/packages/core/src/hooks/checkpoint-hooks.ts:658-708 (beforeModel, root agent, first iteration, only when the run introduces a user turn or that turn has no checkpoint yet), snapshot :535-649 (stash commit under refs/cline/checkpoints/<session>/<run>; a clean tree records HEAD; not a git repo → none). Present when checkpoint.enabled === true (sdk/packages/core/src/services/local-runtime-bootstrap.ts:578-583): CLI on (apps/cli/src/runtime/defaults.ts:22-24), VS Code enableCheckpointsSetting default true (cline-session-factory.ts:1117, :1188-1190), core off by default (defaults.ts:19-20 comment).

F13 Which earlier tool results stay cached for later reads after truncation? RULING · code
Answered how

Code caches a tool's full result only when the tool declares resultPolicy: "cache-oversized" (MCP and Composio tools) and its text preview exceeds the tool-result cap (8 000 chars by default). The cache is per session, 16 MiB in all with oldest-first eviction, drops an entry after 5 iterations without an explicit read, and is cleared at a conversation boundary.

Held by

sdk/packages/core/src/session/services/tool-result-cache.ts:17-98 (ToolResultCache: 16 MiB cap :5, idle eviction after 5 iterations :6, :75-84); filled by the afterTool wrapper sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:1161-1178; which tools: resultPolicy === "cache-oversized" (sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:1002-1006; set by sdk/packages/core/src/extensions/mcp/tools.ts:31 and sdk/packages/core/src/extensions/composio/composio-tools-extension.ts:176); URI lookup sdk/packages/core/src/runtime/orchestration/session-runtime-orchestrator.ts:441-444.

G. Judging the result (8 on this edition)

G1 Is the task done? (act and plan mode) RULING · llm
Answered how

The main model decides by replying without a tool call. Code then finishes the run completed with that reply as the answer, unless the completion policy yields reminder messages (a required completion tool, G2, or the team guard, G3), in which case the reminders are appended and the loop continues. A cut-off or unknown-finish reply goes to the error or recovery paths instead (F9, F10); a content-filtered reply that has text and no tool call completes like any other; nothing checks whether the work is done.

Held by

the session's main model, by replying without a tool call; code accepts that turn as completed (sdk/packages/agents/src/agent-runtime.ts:949-971) unless a completion policy adds reminders (:956-963).

G2 Is the task done and verified? (yolo, headless and scheduled runs: submit_and_exit) RULING · llm
Answered how

Where the tool list includes submit_and_exit (yolo preset, and only when the host supplies a submit executor), the main model decides by calling it with a summary (10+ chars) and a verified boolean. Code ends the run completed as soon as that call's result is not an error, even if other tool calls in the same turn failed; both executors read (CLI and hub schedules) return a non-error result whatever verified says. Every no-tool turn that reaches completion handling (not interrupted, empty, failed, cut off or of unknown finish) instead gets the "not complete until you call" reminder and the loop continues, with no counter.

Held by

the main model calling submit_and_exit (sdk/packages/core/src/extensions/tools/definitions.ts:852-884, lifecycle.completesRun), registered by the yolo preset only (presets.ts:98-110); when present the runtime requires a completion tool (runtime-builder.ts:817-822, :855-864) and re-prompts after every no-tool turn (agent-runtime.ts:754-762, :956-963). Run ends when the tool's result is not an error (agent-runtime.ts:1005-1022, :2383-2403).

G3 Has the team finished its work? (team completion guard) RULING · code
Answered how

Only when agent teams are enabled (CLI act/plan by default, enableAgentTeams: !isYoloMode at apps/cli/src/main.ts:1092; off in VS Code and ACP): after every lead turn with no tool call, code lists the team's tasks and runs, and if any task is pending/in_progress or any run is queued/running it appends a "[SYSTEM] You still have team obligations ... Do NOT stop" reminder and the lead continues; otherwise the turn may complete. The guard reads task and run statuses only; whoever marked the task decided it is done.

Held by

sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:823-854 (teamCompletionGuard: any task pending/in_progress or any run queued/running → a reminder and the lead continues), consumed at agent-runtime.ts:764-769, :956-963.

G4 Did a CLI one-shot run succeed? (exit code) RULE · code
Answered how

Code maps the run's finish reason to the process exit code: completed → 0; any other non-aborted reason → 1 with the error text; aborted (or a local abort request) → 1 only when the --timeout fired, otherwise the code stays 0 and the CLI prints "aborted" for a local abort or "aborted by another client" for anything else, which is what a mistake-limit or loop-detector stop produces. A thrown error → 1.

Held by

apps/cli/src/runtime/run-agent.ts:382-423: aborted → exit code set to 1 only on timeout (:383-385), otherwise the code stays 0 from :147 and the text "aborted by another client" is printed (format.ts:4-15); !== completed → 1 (:401-412); completed → 0 (:423).

G5 Did a scheduled run succeed? RULE · code
Answered how

Code: when the hub's turn resolves, a finish reason of error becomes a thrown error and the run is recorded failed; any other finish reason (completed, aborted) records status: "done", telemetry outcome success, and publishes schedule.execution.completed. A thrown error or the schedule's own timeout (the cron runner's abort signal) records failed (telemetry outcome failed or timeout), a cancellation records cancelled, and both publish schedule.execution.failed; that report file carries the error and its context instead of the final text.

Held by

sdk/packages/core/src/cron/runner/cron-runner.ts:440-491 (finishReason === "error" → failed :445-447; everything else → status: "done", outcome success, schedule.execution.completed published); catch path :492-553.

G6 Is a sub-agent's result good enough to use? RULING · llm
Answered how

Where spawn_agent exists (CLI act/plan by default; not in VS Code, which sets enableSpawnAgent: false, nor in CLI yolo mode), the parent model judges the result: the tool returns { text, iterations, finishReason, usage } as a normal, non-error tool result for every finish, so a sub-agent that failed on a provider error comes back with finishReason: "error" and the error message as text, and one stopped by its mistake limit comes back aborted. Only a thrown exception becomes a tool error.

Held by

the parent model reading the spawn_agent output { text, iterations, finishReason, usage } (sdk/packages/core/src/extensions/tools/team/spawn-agent-tool.ts:159-183). A sub-agent stopped by the mistake limit returns normally with finishReason: "aborted"; only a thrown error becomes a tool error (:184-199).

G7 Is a teammate's outcome fragment acceptable? (team review) RULING · llm
Answered how

Only in agent teams (G3's condition): any team member holding the management tools, the lead or any teammate, calls team_review_outcome_fragment with a fragment id and approved; code sets the fragment to reviewed or rejected and records the caller as reviewer, with no criteria, no check that the reviewer is not the fragment's author, and no guard against re-reviewing a fragment already reviewed.

Held by

whichever team agent calls team_review_outcome_fragment with approved (sdk/packages/core/src/extensions/tools/team/team-tools.ts:801-825); stored by reviewOutcomeFragment (multi-agent.ts:1713-1728).

G8 May a team outcome be finalized? RULE · code
Answered how

Code: when a team agent asks to finalize an outcome, every one of the outcome's required sections must have at least one fragment whose status is reviewed; otherwise it raises naming the first missing section, and on success the outcome is marked finalized. Rejected or draft fragments beside a reviewed one do not block it.

Held by

sdk/packages/core/src/extensions/tools/team/multi-agent.ts:1736-1760 (finalizeOutcome: every required section needs at least one reviewed fragment).

H. Delegation (5 on this edition)

H1 Should this work go to a sub-agent, and with what instructions? RULING · llm
Answered how

Where spawn_agent is registered (enableSpawnAgent: CLI act/plan by default, off in VS Code and in CLI yolo mode), the main model decides when to delegate and writes both the sub-agent's system prompt and its task as free strings; code accepts any strings. For the Cline provider the written prompt becomes the overridePrompt of the Cline system prompt; for any other provider it is the sub-agent's base system prompt.

Held by

the main model calling spawn_agent (sdk/packages/core/src/extensions/tools/team/spawn-agent-tool.ts:117-204), built for sessions by createSessionSpawnTool (sdk/packages/core/src/runtime/host/local/spawn-tool.ts:121-188) and registered at runtime-builder.ts:802-811.

H2 Which configured sub-agent should take this task? RULING · llm
Answered how

Only when spawning is enabled and the person has configured at least one agent: the main model picks one of the subagent_<name> tools, each described as Use the "<name>" subagent: <description>, and sends a non-empty prompt. Code then runs that agent's own systemPrompt with its configured provider, model and iteration cap (falling back to the parent's), with built-in tools filtered for that agent.

Held by

the main model choosing among subagent_<name> tools (sdk/packages/core/src/extensions/tools/team/configured-agent-tool.ts:145-247), one per configured agent, registered at sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:655-693.

H3 What tools and approval posture does a sub-agent get? RULE · code
Answered how

Code: a spawn_agent sub-agent gets the built-in tools of the parent's mode preset (plus its own spawn_agent when spawning is on, minus disabled tools, no MCP tools); a configured agent gets built-in tools filtered for it. Neither receives tool policies or an approval callback, and the runtime asks only when a policy says autoApprove === false, so every tool the sub-agent calls runs without asking the person, unless an inherited beforeTool hook (such as the plan-mode command guard) blocks it.

Held by

sdk/packages/core/src/runtime/host/local/spawn-tool.ts:132-147 (built-in tools of the parent's mode preset, plus another spawn_agent when spawning is on, minus globally disabled tools; no MCP tools), sdk/packages/core/src/runtime/host/local/spawn-tool.ts:149-187 (no toolPolicies, no requestToolApproval passed); configured agents: sdk/packages/core/src/extensions/tools/team/configured-agent-tool.ts:160-175 with the comment "child tools run autonomously ... Do not inherit approval policy" (:163-164); the runtime asks for approval only when a policy says autoApprove === false (sdk/packages/agents/src/agent-runtime.ts:2476-2492, resolveToolPolicy :216-224), so with no policy every tool runs. Extensions and hooks are inherited (sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:632-654), including the plan-mode command guard (:553-566).

H4 What does a sub-agent know of the parent's conversation? RULE · code
Answered how

Code gives the sub-agent a fresh session with no copy of the parent's conversation: its only input is the task string the parent model wrote (for a configured agent, the prompt string), under the system prompt from H1/H2. Project rules reach it through the inherited user-instruction extension, not through the parent's history.

Held by

sdk/packages/core/src/extensions/tools/team/spawn-agent-tool.ts:159 (subAgent.run(input.task): only the task text; a fresh SessionRuntime, sdk/packages/core/src/extensions/tools/team/delegated-agent.ts:149-158); rules arrive through the inherited user-instruction extension (sdk/packages/core/src/runtime/orchestration/runtime-builder.ts:559-566).

H5 How should the team's work be split, assigned and marked done? (agent teams) RULING · llm
Answered how

Only in agent teams (CLI act/plan by default; off in VS Code, ACP and CLI yolo mode): the lead model alone decides who joins the team (spawn, shutdown and cleanup check for the lead role), while the lead and every teammate model can create, claim, complete or block tasks and route work to a teammate, since those tools carry no role check. Code marks a task completed for whoever calls complete with a non-empty summary, assignee or not, and a blocked task no longer counts as unfinished for G3.

Held by

the lead model through team_spawn_teammate (lead only, sdk/packages/core/src/extensions/tools/team/team-tools.ts:304-345), and the lead or any teammate model through team_task create/claim/complete/block (sdk/packages/core/src/extensions/tools/team/team-tools.ts:394-488) and team_run_task sync or async (sdk/packages/core/src/extensions/tools/team/team-tools.ts:495-), none of which checks the caller's role; teammates are themselves delegated agents (sdk/packages/core/src/extensions/tools/team/delegated-agent.ts:124-127, buildTeammateSystemPrompt sdk/packages/core/src/extensions/tools/team/subagent-prompts.ts:4-21).

I. Learning and feedback (1 on this edition)

I1 What should the agent learn from the person's rejection of a tool call? RULING · human
Answered how

Only in VS Code and only when the person is actually asked (the tool's policy is not auto-approve and the host's auto-approver did not approve first): if the person clicks Reject and types text, code appends that text inside <feedback> tags to a fixed denial line (for edit tools, one saying the file was NOT modified) and the model receives it in the skipped tool call's result. Typing a chat message instead of clicking leaves the approval pending and routes the message as a follow-up.

Held by

the person's optional feedback text on a rejection, wrapped as <feedback> in the denial reason (apps/vscode/src/sdk/tool-approval-denial.ts:18-25, built at apps/vscode/src/sdk/sdk-interaction-coordinator.ts:256-278) and returned to the model as the skipped tool's result (agent-runtime.ts:2488-2491).

How this map was made

Four readers each took a part of the agent and wrote seat cards from the source. Fresh readers then re-read those seats against the cited lines, filled in how each is answered, and corrected what the source did not support; each correction is recorded with the lines opened. Another reader searched the Cline Hub app, which no card covered yet, and drafted 6 cards; the map's author opened each card's holding lines before adding it, and checked a sample of 8 re-read claims against the source. Models from another family (read-only, at the same commit) reviewed the seat data once, checked an earlier, fuller edition's wording twice, then checked this edition's wording; each finding was checked at source before anything changed, and a sentence or card that could not be settled was narrowed or cut. A checker confirms that each seat's holder line exists at the pinned commit and carries its anchor text. Nothing on this page was produced by running their code.