pi: who decides what

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

The pi coding agent (its command-line agent, agent loop, model layer, code mode and MCP client) in earendil-works/pi, read at commit 1ce44bed. Claims about how the code behaves refer to that commit. Their code is MIT-licensed; this page quotes short identifiers and cites files and lines at that commit.

How to read this page

A seat is a judgment the agent makes over and over: which model a name means, what the model sees, may this action run, is the work done. Each card records the question, how it is answered, and who or what holds it, with the code that implements or exposes that decision. Seat ids (A1, B12 …) are links.

Each answer describes what pi does by default. Exceptions named are the main ones, not a complete list.

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 or (323) means lines in the file named just before it.

Counts

112 seats across 9 stages: A 17, B 19, C 10, D 17, E 26, F 14, G 4, H 0, I 5.

Kind of question · holderSeats
RULE · code45
RULING · code42
RULING · human9
RULING · external8
RULING · llm8

What this edition does not have

There is no list of gaps. No coverage figure: this edition does not say how many of pi's model calls and decision points the seats leave out. Each card shows the question, the answer and its holder; for most seats we also recorded what checks the judgment and how it has failed, but those notes are not shown here.

What is left out of this edition

1 of the 112 cards is left out of this edition. The counts above include it.

A. Intake and routing (17 seats)

A1 Which run mode does this invocation take (interactive TUI, print, JSON stream or RPC)? RULE · code
Answered how

Code picks the mode at startup: --mode rpc and --mode json select those modes; --print, or a stdin or stdout that is not a terminal, selects print; otherwise the interactive terminal UI.

Held by

packages/coding-agent/src/main.ts:112-123 resolveAppMode, called once at packages/coding-agent/src/main.ts:665 with process.stdin.isTTY / process.stdout.isTTY; the later interactive-to-print switch at packages/coding-agent/src/main.ts:910-915 cannot fire (see reason).

A2 Which earlier conversation does this run continue, fork or open (--continue, --resume, --session, --fork, --session-id)? RULE · code
Answered how

Code checks the session flags in a fixed order (--fork, --session, --resume, --continue, --session-id); with none of them it starts a new saved session (--no-session keeps it in memory). A --session or --fork value can be a path, an id or the start of an id.

Held by

packages/coding-agent/src/main.ts:358-449 createSessionManager, with resolveSessionPath packages/coding-agent/src/main.ts:252-283; flag conflicts refused at packages/coding-agent/src/main.ts:299-336.

A3 When the session named by --session belongs to another project folder, should it be forked into this folder? RULING · human
Answered how

The person, at a [y/N] prompt, when --session names a session saved under another project folder: yes forks it into this folder, anything else exits. The prompt is asked in every run mode.

Held by

packages/coding-agent/src/main.ts:399-407 promptConfirm (packages/coding-agent/src/main.ts:286-297, a readline [y/N])

A4 When a resumed session's recorded working directory no longer exists, where should it run? RULING · human
Answered how

In the interactive terminal the person chooses Continue (run in a fallback folder) or Cancel; in the other modes pi exits with an error.

Held by

packages/coding-agent/src/main.ts:708-720 (interactive: promptForMissingSessionCwd packages/coding-agent/src/main.ts:560-568 offers Continue in the fallback cwd, or Cancel)

A5 Does this folder hold project-local resources that need a trust decision before they load? RULE · code
Answered how

Code says yes when any of eight settings or resource entries exists in the folder's .pi/, or a .agents/skills folder exists in it or any parent folder other than the one in the home folder.

Held by

packages/coding-agent/src/core/trust-manager.ts:186-208 hasTrustRequiringProjectResources (list TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES packages/coding-agent/src/core/trust-manager.ts:30-39)

A7 In print, JSON, RPC, help and list-models runs, can the trust question be put to a person at all? RULE · code
Answered how

No. Outside an interactive start nobody is asked, so a folder that needs trust and has no flag, extension answer, saved decision or defaultProjectTrust setting is treated as untrusted.

Held by

packages/coding-agent/src/main.ts:737 (help/list-models forced to print), packages/coding-agent/src/main.ts:784 (hasUI only for the initial runtime in interactive mode), packages/coding-agent/src/cli/project-trust.ts:18-53 (every UI call returns undefined/false outside interactive)

A8 Which model answers the first turn of a new or resumed session? RULE · code
Answered how

Code uses --model if given. Otherwise a new session uses the --models (or enabledModels) list when set, and a resumed one keeps its recorded model if it still exists with credentials; failing those, the saved default model, then a known provider's default, then the first available model.

Held by

packages/coding-agent/src/core/model-resolver.ts:450-534 resolveCliModel, applied at packages/coding-agent/src/main.ts:475-498; scoped models packages/coding-agent/src/main.ts:500-520; session restore packages/coding-agent/src/core/sdk.ts:219-232; findInitialModel packages/coding-agent/src/core/model-resolver.ts:548-615 (order list packages/coding-agent/src/core/model-resolver.ts:20-62)

A9 Which catalog model does a typed model reference (--model, /model <text>, --models) mean? RULING · code
Answered how

For --model: code matches the text against the model catalog by id or name, exactly or partly, and uses the provider the text names and which providers have credentials to choose between candidates; a tie it cannot settle is an error, and an unknown id under a known provider becomes a custom model, with a warning. /model and --models use their own matching.

Held by

packages/coding-agent/src/core/model-resolver.ts:149-299 resolveModelReference (selectReference packages/coding-agent/src/core/model-resolver.ts:235-265, selectFuzzy/bestFuzzyMatch packages/coding-agent/src/core/model-resolver.ts:274-299); CLI handling packages/coding-agent/src/core/model-resolver.ts:486-533. /model: handleModelCommand, packages/coding-agent/src/modes/interactive/interactive-mode.ts:5302. --models: resolveModelScopeFromModels, packages/coding-agent/src/core/model-resolver.ts:326-332.

A10 When a person submits text in the interactive editor, is it a built-in command, a user shell command, or a prompt for the agent? RULE · code
Answered how

Code checks the text in order: a built-in /command runs; text starting with ! runs as a shell command; while the agent is working, the text is sent as a steering message (queued during a compaction; extension commands run at once); otherwise it is a new prompt.

Held by

packages/coding-agent/src/modes/interactive/interactive-mode.ts:3268-3466 setupEditorSubmitHandler (built-ins :3274-3413; !/!! :3416-3431; compaction queue :3434-3443; streaming steer :3447-3454; input loop :3460-3464). Names: packages/coding-agent/src/core/slash-commands.ts:19-44.

A11 Is a /name ... prompt an extension command, a skill invocation, a prompt template, or plain text for the model? RULE · code
Answered how

Code runs a matching extension command first; otherwise the text passes the extensions' input hooks, then /skill:name is replaced by that skill's file and /name by a matching prompt template, and anything else goes to the model as typed.

Held by

packages/coding-agent/src/core/agent-session.ts:2106-2113 (extension command first, _tryExecuteExtensionCommand packages/coding-agent/src/core/agent-session.ts:2185-2209), then the input hook (:2122-2131, A12), then _expandSkillCommand (:2216-2240), then expandPromptTemplate (packages/coding-agent/src/core/prompt-templates.ts:309-325). Queued input: packages/coding-agent/src/core/agent-session.ts:2242-2268.

A12 Should an extension's input hook swallow, rewrite or pass through what the person typed? RULING · external
Answered how

Only when an extension registers an input handler: each handler in turn may swallow the input, rewrite it, or let it pass. With none, the text passes unchanged.

Held by

packages/coding-agent/src/core/agent-session.ts:2046-2064 _runInputHandlers -> ExtensionRunner.emitInput (packages/coding-agent/src/core/extensions/runner.ts:1525-1564)

A13 When the person sends a message while the agent is still working, does it interrupt (steer) or wait (follow-up)? RULE · code
Answered how

In the terminal, Enter while the agent works sends a steering message and the follow-up key queues a follow-up; programs driving pi over RPC choose per message. Queued messages are delivered one at a time by default.

Held by

packages/coding-agent/src/modes/interactive/interactive-mode.ts:3450 (interactive always steers); RPC packages/coding-agent/src/modes/rpc/rpc-mode.ts:394-417; no behaviour while streaming raises at packages/coding-agent/src/core/agent-session.ts:2142-2147; delivery modes packages/coding-agent/src/core/sdk.ts:433-434 (defaults packages/coding-agent/src/core/settings-defaults.ts:7-8)

A14 Is a prompt admitted to start a run (a model is selected, its provider has credentials, no compaction is running)? RULE · code
Answered how

Code refuses a new prompt while a compaction runs, and refuses to start a run with no model selected or no credentials for its provider; a prompt sent while the agent is working is queued instead, without those checks.

Held by

packages/coding-agent/src/core/agent-session.ts:2115-2119 (compaction), packages/coding-agent/src/core/agent-session.ts:2157-2175 (no model; no configured auth and checkAuth fails)

A15 In a one-shot run, what single prompt does the agent get from piped stdin, @file arguments and the first message argument? RULE · code
Answered how

Code joins piped stdin, the text of @file arguments and the first message into one prompt, with no separator between them, and attaches any images; each further message argument is sent as its own prompt.

Held by

packages/coding-agent/src/main.ts:80-97 readPipedStdin; packages/coding-agent/src/cli/file-processor.ts:25-88 processFileArguments; packages/coding-agent/src/cli/initial-message.ts:20-43 buildInitialMessage; remaining messages packages/coding-agent/src/modes/print-mode.ts:131-137

A16 Does a one-shot text run report success, and what is printed? RULE · code
Answered how

Code looks only at the last message: an error or abort prints the error and exits 1; otherwise the reply's text is printed, and a reply cut off at its output limit also exits 1 (a last message that is not a reply prints nothing).

Held by

packages/coding-agent/src/modes/print-mode.ts:139-160 (last message only; error/aborted => exit 1; length => text printed, exit 1; else exit 0)

A17 Which tools does this session make available, given --tools, --exclude-tools, --no-tools, --no-builtin-tools and the defaultTools setting? RULE · code
Answered how

Code starts from the defaultTools setting (else read, bash, edit and write); --tools either edits that list with +name/-name or replaces it, --no-tools allows no tools, --no-builtin-tools drops the built-in ones (extension tools still load), and --exclude-tools removes tools last.

Held by

packages/coding-agent/src/core/sdk.ts:280-294 (initial active list and allowlist); flag mapping packages/coding-agent/src/main.ts:540-551; flags parsed packages/coding-agent/src/cli/args.ts:147-166

A18 When the selected model is a virtual model, which physical model and thinking level answer this request? RULING · external
Answered how

Only for a virtual model an extension registered: on each request the extension's router picks a physical model and thinking level, and code accepts it only if that model is in the catalog and has credentials.

Held by

packages/coding-agent/src/core/model-runtime.ts:1011-1042 ModelRuntime.resolveModel, calling the extension's route() (packages/coding-agent/src/core/extensions/types.ts:1937, wired at packages/coding-agent/src/core/extensions/loader.ts:503-511); reasons packages/coding-agent/src/core/virtual-models.ts:43-50

B. Context: what the model sees (19 seats)

B1 Which base system prompt does the model get: pi's default, a --system-prompt, or a SYSTEM.md? RULE · code
Answered how

Code uses --system-prompt if given, else the project's .pi/SYSTEM.md (only in a trusted project), else ~/.pi/agent/SYSTEM.md, else pi's built-in prompt. A custom prompt replaces pi's own opening, tool list and rules; appended text, instruction files, skills and the working folder still follow.

Held by

packages/coding-agent/src/core/resource-loader.ts:688-692 (--system-prompt source, else discoverSystemPromptFile packages/coding-agent/src/core/resource-loader.ts:1248-1260); resolvePromptInput packages/coding-agent/src/core/resource-loader.ts:194-209; custom prompt handling packages/coding-agent/src/core/system-prompt.ts:152-170

B2 What extra text is appended after the base prompt (--append-system-prompt, APPEND_SYSTEM.md)? RULE · code
Answered how

Code appends the --append-system-prompt texts if given, else the project's .pi/APPEND_SYSTEM.md (only in a trusted project), else ~/.pi/agent/APPEND_SYSTEM.md. The appended text is kept even when a custom system prompt replaces pi's own.

Held by

packages/coding-agent/src/core/resource-loader.ts:694-707 (CLI sources replace discovery; else discoverAppendSystemPromptFile packages/coding-agent/src/core/resource-loader.ts:1262-1274); rendered as addendum at packages/coding-agent/src/core/system-prompt.ts:172

B3 Which instruction files (AGENTS.md, CLAUDE.md) are put in front of the model, and in what order? RULE · code
Answered how

Unless --no-context-files is given, code loads one instruction file per folder (AGENTS.md or CLAUDE.md, among a few name variants) from pi's own config folder and from every folder from the filesystem root down to the working folder, in that order, with no trust check.

Held by

packages/coding-agent/src/core/resource-loader.ts:211-230 loadContextFileFromDir; loadProjectContextFiles packages/coding-agent/src/core/resource-loader.ts:259-301 (shadowing packages/coding-agent/src/core/resource-loader.ts:241-257); --no-context-files packages/coding-agent/src/core/resource-loader.ts:677-684; rendered packages/coding-agent/src/core/system-prompt.ts:79-86, :173

B4 Which skills are listed to the model as available, and with what hint for loading them? RULE · code
Answered how

Code lists every loaded skill that has a description and is not marked disable-model-invocation, with its name, description and file path, and tells the model to open the file when a task matches. The list appears only when read or bash is selected; when two skills share a name, the first found wins.

Held by

packages/coding-agent/src/core/skills.ts:414-514 loadSkills (called with includeDefaults: false from packages/coding-agent/src/core/resource-loader.ts:875-896; paths packages/coding-agent/src/core/resource-loader.ts:630-635); listing formatSkillsForPrompt packages/coding-agent/src/core/skills.ts:358-388; section gate packages/coding-agent/src/core/system-prompt.ts:175-182

B5 Should an extension rewrite this run's system prompt options, replace the whole prompt, or add messages before the run starts (before_agent_start)? RULING · external
Answered how

Only when an extension registers a before_agent_start handler: before each run, each handler may edit the prompt options, add a message to the run, or replace the whole system prompt for that run (the last replacement wins, and it is not saved in the transcript).

Held by

packages/coding-agent/src/core/agent-session.ts:1939-1947 (emitBeforeAgentStart, packages/coding-agent/src/core/extensions/runner.ts:1427-1477; explicit selectedTools edit wins), added messages packages/coding-agent/src/core/agent-session.ts:1967-1977, forced prompt projected onto every request of the run (_installAgentForcedPromptProjection packages/coding-agent/src/core/agent-session.ts:1812-1827)

B6 Should an extension rewrite the message list sent on each request (context hook)? RULING · external
Answered how

Only when an extension registers a context handler: on every request each handler may rewrite the message list the model will see. The change is not saved, so what the model saw and what the transcript records can differ.

Held by

packages/coding-agent/src/core/sdk.ts:428-432 (transformContext -> ExtensionRunner.emitContext, packages/coding-agent/src/core/extensions/runner.ts:1305-1360), chained before the hidden-declarations and forced-prompt projections (packages/coding-agent/src/core/agent-session.ts:1792-1827)

B7 Which part of the saved conversation is replayed to the model on this branch (tree path, latest compaction, kept entries, edits)? RULE · code
Answered how

Code replays the current branch from its start; when the branch holds a compaction, only the latest one counts: its summary, then the messages it kept, then everything after it. Recorded edits replace or drop single messages.

Held by

packages/coding-agent/src/core/session-manager.ts:476-512 buildContextEntries; edits projectContextEntry packages/coding-agent/src/core/session-manager.ts:519-540; entry projection sessionEntryToContextMessages packages/coding-agent/src/core/session-manager.ts:439-466

B8 Which recorded message kinds reach the model, and as what role? RULE · code
Answered how

Code sends system, user, assistant and tool-result messages as they are, and turns shell runs, extension messages and summaries into user messages; a shell run the person marked with !! is left out.

Held by

packages/coding-agent/src/core/messages.ts:148-196 convertToLlm; wrapped by the image block (B10) at packages/coding-agent/src/core/sdk.ts:297-331

B9 Does a shell command the person runs with ! enter the model's context? RULING · human
Answered how

The person decides per command: !cmd puts the command and its output into the model's context, !!cmd keeps it out (programs driving pi over RPC set the same flag).

Held by

packages/coding-agent/src/modes/interactive/interactive-mode.ts:3416-3418 (the person's prefix choice ! vs !!), honoured at packages/coding-agent/src/core/messages.ts:152-156; RPC excludeFromContext packages/coding-agent/src/modes/rpc/rpc-mode.ts:561-566

B10 Are images replaced by a placeholder before they reach the model? RULE · code
Answered how

Only when the images.blockImages setting is on (default off): every image in user and tool-result messages is replaced with "Image reading is disabled." before sending; the transcript keeps the images.

Held by

packages/coding-agent/src/core/sdk.ts:297-331 (convertToLlmWithBlockImages; setting read per request packages/coding-agent/src/core/sdk.ts:300)

B11 Are prompt images resized or refused for the request model before they are sent? RULE · code
Answered how

Code resizes each attached image to the model's image limits (with images.autoResize, on by default); an image it cannot process is dropped and a note saying so is added to the prompt.

Held by

packages/coding-agent/src/core/agent-session.ts:2066-2086 _normalizePromptImages, called at packages/coding-agent/src/core/agent-session.ts:1953-1957 (after before_agent_start)

B12 Which tools are declared to the model on this request? RULE · code
Answered how

Code declares the active tools: those selected that are registered and not hidden, keeping their order; a tool hook (codemode's, for example) may then rewrite descriptions or hide some declarations.

Held by

packages/coding-agent/src/core/agent-session.ts:1598-1645 _applyToolLoadout (activatable packages/coding-agent/src/core/agent-session.ts:1569-1572); per run _preparePromptAndToolLoadout packages/coding-agent/src/core/agent-session.ts:1763-1775; resume _restoreToolsFromTranscript packages/coding-agent/src/core/agent-session.ts:1835-1866

B13 Should a tool's prepareLoadout hook rewrite tool descriptions or hide declarations (codemode folding direct tools into scripts)? RULING · code
Answered how

Only while the codemode tool is active (it starts inactive): its hook lists the script-callable tools in its own description and, by default, rewrites each declared callable tool's description into a script-call form; with codemode.mode: only it hides the direct tools' declarations instead.

Held by

packages/coding-agent/src/extensions/codemode/tool.ts:343-379 prepareCodemodeLoadout; mode read packages/coding-agent/src/extensions/codemode/index.ts:23-25, registered inactive packages/coding-agent/src/extensions/codemode/index.ts:34-45; applied at packages/coding-agent/src/core/agent-session.ts:1605-1641, hidden ones filtered from every request packages/coding-agent/src/core/agent-session.ts:1792-1810

B14 How is each MCP tool exposed to the model: declared, deferred behind tool_search, callable only from codemode, or hidden? RULE · code
Answered how

Code uses the server config's per-tool toolExposure setting (an exact name, else a * pattern), else the server's exposure, else codemode.

Held by

packages/coding-agent/src/core/mcp-servers.ts:234-242 getMcpToolExposure; allowlist interplay packages/coding-agent/src/core/agent-session.ts:1557-1572

B15 Which MCP servers, and what one-line description of each, does the system prompt list? RULE · code
Answered how

When the built-in MCP extension is on, each run's system prompt lists the enabled servers whose tools are not declared directly, with how to reach them and a one-line summary when there is one; the section is capped at 4,096 characters.

Held by

packages/coding-agent/src/extensions/mcp/index.ts:195-221 renderServersSection (summary packages/coding-agent/src/extensions/mcp/index.ts:185-188; limits packages/coding-agent/src/extensions/mcp/index.ts:157-163); set on every before_agent_start packages/coding-agent/src/extensions/mcp/index.ts:1178-1184

B16 Do MCP resources enter the model's context without the model asking? RULE · code
Answered how

No: resource content reaches the model only through tool calls the model makes (the resource tools, or a tool result that carries a resource).

Held by

packages/coding-agent/src/extensions/mcp/resources.ts:194-197 createMcpResourceToolDefinitions; registered by syncResourceTools packages/coding-agent/src/extensions/mcp/index.ts:466-490

B17 Which deferred tools does tool_search load into the declared set for the next request? RULING · code
Answered how

Code ranks the tools that are not yet active and are exposed as deferred or through codemode against the model's query (BM25, exact name matches first) and activates the top results (8 by default) for the next request.

Held by

packages/coding-agent/src/extensions/tool-search/tool.ts:217-234 searchAndLoad (ranker Bm25Ranker.rank packages/coding-agent/src/extensions/tool-search/tool.ts:149-181); limit checks packages/coding-agent/src/extensions/tool-search/tool.ts:255-259

B18 When the prompt, tools or context change mid-conversation, how does the model learn of it? RULE · code
Answered how

At the start of each run, code compares the prompt sections with those the model last received and sends only the changed ones as a new system message ahead of the run's messages; tool changes are declared separately.

Held by

packages/coding-agent/src/core/agent-session.ts:1763-1775 _preparePromptAndToolLoadout (diff diffSystemPromptSections packages/coding-agent/src/core/system-prompt.ts:217-229; patch put first packages/coding-agent/src/core/agent-session.ts:1978-1980)

B19 Which extra messages ride along with the starting message of a run (pending "next turn" messages, extension-added messages)? RULE · code
Answered how

Code starts a run with, in order: any prompt update (B18), the prompt itself, any pending "next turn" messages, then messages extensions added before the run.

Held by

packages/coding-agent/src/core/agent-session.ts:1964-1977 (pending nextTurn messages consumed; before_agent_start messages appended as custom messages), patch put first packages/coding-agent/src/core/agent-session.ts:1978-1980

C. Choosing the next action (10 seats)

C1 Given the conversation and the tools it can see, what does the agent do next: answer, or call which tools with which arguments? RULING · llm
Answered how

The session model decides each turn: it sees the conversation and the declared tools and replies with text, tool calls, or both. Before any call runs, code checks the tool name, repairs and validates the arguments, and runs any tool-call hooks.

Held by

the session model (person's model choice, routed per request), called at packages/agent/src/agent-loop.ts:412 (streamAssistantResponse), tool calls read back at packages/agent/src/agent-loop.ts:268.

C2 When the model's tool-call arguments arrive as text, what object do they mean (including malformed JSON)? RULING · code
Answered how

Code parses the finished argument text as JSON; if that fails, it repairs two common string errors (raw control characters, bad backslash escapes) and tries once more. Arguments that still fail go back to the model as an error result for that call.

Held by

packages/ai/src/utils/json-parse.ts:106 (parseToolCallArguments, via ToolCallArgumentsStream.finish() packages/ai/src/utils/streaming-json.ts:485-487), with repairJson json-parse.ts:33-84 (escapes raw control chars, doubles backslashes before invalid escapes).

C3 Are the model's arguments acceptable for this tool, and if not quite, should they be coerced into shape? RULING · code
Answered how

Code validates the arguments against the tool's schema after light conversion (a numeric string becomes a number, for example, and for tools with plain JSON schemas null can become 0, "" or false). A failure goes back to the model as an error listing each problem.

Held by

packages/ai/src/utils/validation.ts:317-353 (validateToolArguments): optional nulls removed by normalizeOptionalNulls (packages/ai/src/utils/validation.ts:240-269), TypeBox Value.Convert (323), then for non-TypeBox schemas coerceWithJsonSchema (194-238) applying coercePrimitiveByType (60-131).

C4 If the model's response was cut off by the output-token limit, may its tool calls run? RULING · code
Answered how

No: when the reply was cut off at the output-token limit, none of its tool calls run; each gets an error result asking the model to re-issue it, and the run continues.

Held by

packages/agent/src/agent-loop.ts:276-279 -> failToolCallsFromTruncatedMessage (488-513).

C5 Does the tool the model named exist for this run? RULE · code
Answered how

Code looks the name up among the tools that can run in this session; an unknown name gets a "Tool not found" error result. A tool hidden from the model's list but still runnable is found (#10426).

Held by

packages/agent/src/agent-loop.ts:726-733 (lookup in context.tools, the EXECUTABLE set, not the declared set).

C6 When the model sends edit arguments in a near-miss shape (JSON string, single object, legacy top-level oldText/newText), should they be repaired before validation? RULING · code
Answered how

Code repairs a few near-miss shapes of the edit tool's arguments before validation (edits sent as a JSON string, a single edit not in a list, the older top-level oldText/newText); anything else is left for validation to judge.

Held by

packages/coding-agent/src/core/tools/edit.ts:103-134 (prepareEditArguments), applied at packages/agent/src/agent-loop.ts:704-716 before validation.

C7 Should the provider be told to force this tool call to match its schema (strict JSON schema or a grammar), and what if the provider refuses? RULING · code
Answered how

Code asks the provider to enforce the tool's schema (strict mode) when the provider supports it and the schema allows it; otherwise bash, read, edit and write are sent without it, and the codemode tool asks for a grammar where the provider supports one. If Claude rejects the request for too many strict tools, it is sent once more without them.

Held by

packages/ai/src/api/constrained-sampling.ts:261-285 (resolveJsonSchemaStrictSampling), makeStrictJsonSchema 127-140, grammar 287-320; fallback on provider limit errors packages/ai/src/api/anthropic-messages.ts:670-690 (and bedrock-converse-stream.ts:310-318).

C8 After this turn, is the run over, or does the agent take another turn? RULE · code
Answered how

Code, after each turn: an error or abort ends the run; otherwise the run goes on while the model called tools or a steering message waits, then for queued follow-ups or an extension's request for one more turn; else it ends.

Held by

packages/agent/src/agent-loop.ts:298-326 (after each turn: finishTurn end returns at once; the inner loop repeats while more tool calls or steering are pending; follow-ups restart it; an explicit continuation gives one context-only turn); inputs from :268-281 (tool calls and the batch's terminate) and the session's finishTurn (packages/coding-agent/src/core/agent-session.ts:886-895).

C9 While the agent is working, should the person redirect it (steer now) or queue a follow-up for after it stops? RULING · human
Answered how

The person, while the agent works: Enter sends the text as a steering message, and the follow-up key (alt+enter, ctrl+q on Windows) queues it for after the agent stops.

Held by

the person at the interactive prompt: packages/coding-agent/src/modes/interactive/interactive-mode.ts:3450 (streamingBehavior: "steer") and 4600 ("followUp"); key app.message.followUp packages/coding-agent/src/core/keybindings.ts:67; session side packages/coding-agent/src/core/agent-session.ts:2141-2151.

C10 When does a message the person typed mid-run reach the model, and how many at once? RULE · code
Answered how

Code delivers steering messages at the start of a run and after each completed turn, and follow-ups only when the agent would otherwise stop; by default one message at a time.

Held by

packages/agent/src/agent-loop.ts:185, 213-215, 304 (steering polled at start, after next-turn preparation, and after every turn), 311-316 (follow-ups only when the agent would stop); queue mode packages/agent/src/agent.ts:165-175, 255-256.

D. Gatekeeping: may this action run? (17 seats)

D1 May a tool call the model issued run, without a person being asked? RULING · code
Answered how

Yes: by pi's stated design nobody is asked. A call runs once its tool is found and its arguments are valid, unless an installed extension blocks it.

Held by

packages/coding-agent/src/core/agent-session.ts:658-681 (_beforeToolCall; no handlers at :663-665 means undefined) feeding packages/agent/src/agent-loop.ts:718-787 (prepareToolCall: tool lookup :726-733, argument validation :737, hook :738-766, then kind: "prepared" :774-779).

D2 Should this tool call be blocked by an installed policy extension? RULING · external
Answered how

Only when an installed extension handles tool calls: the first handler that says block stops the call, and the model gets the handler's reason as an error. pi ships no blocking policy; the two in its repository are examples.

Held by

packages/coding-agent/src/core/extensions/runner.ts:1249-1267 (emitToolCall runs installed extensions' tool_call handlers in load order; first block: true wins :1259-1261), installed by packages/coding-agent/src/core/agent-session.ts:652-655 and consumed at packages/agent/src/agent-loop.ts:755-765. Shipped policies are examples only: packages/coding-agent/examples/extensions/permission-gate.ts:13-33, packages/coding-agent/examples/extensions/protected-paths.ts:13-25.

D3 Allow this action? (the person's answer to a policy extension's prompt in the terminal UI) RULING · human
Answered how

The person, only when an installed extension asks: its question appears as a dialog in the terminal, and the extension turns the answer into allow or block.

Held by

person at the TUI; the prompt goes through packages/coding-agent/src/core/extensions/runner.ts:577-587 (wrapUIPromptContext, select/confirm), bound by setUIContext (packages/coding-agent/src/core/extensions/runner.ts:572-575) from packages/coding-agent/src/core/agent-session.ts:3402.

D4 Allow this action? (when the policy extension asks and there is no UI: print and JSON modes) RULING · code
Answered how

No person is asked: in print and JSON modes the extension's question gets an immediate empty answer ("no" for a yes/no question), and the extension decides what that means.

Held by

packages/coding-agent/src/core/extensions/runner.ts:331-334 (noOpUIContext: select → undefined, confirm → false), kept when no UI context is bound (packages/coding-agent/src/core/extensions/runner.ts:572-575, :628-630 hasUI); print/JSON mode binds none (packages/coding-agent/src/modes/print-mode.ts:76-77).

D5 Allow this action? (when the policy extension asks in RPC mode: the client program answers) RULING · external
Answered how

The program driving pi over RPC answers the extension's question; pi waits for its reply with no time limit unless the extension set one.

Held by

the RPC client; packages/coding-agent/src/modes/rpc/rpc-mode.ts:90-145 emits extension_ui_request and resolves on the client's reply (confirm: cancelled → false, else confirmed, :142-145; optional timeout :115-119 resolves to the default).

D6 Is this project trusted to load its settings, extensions, skills, MCP servers and packages? RULING · code
Answered how

Code, in order: a --approve/--no-approve flag; a folder with no project settings or resources is trusted; then an extension's answer, the saved decision for the folder or a parent, and the defaultProjectTrust setting. If still unanswered, the person is asked in the terminal (D7); without a terminal the folder is untrusted.

Held by

packages/coding-agent/src/core/project-trust.ts:47-97 (resolveProjectTrusted: CLI override :48-50 → no protected resources means trusted :51-53 → project_trust extension :55-71 → saved decision :73-76 → defaultProjectTrust :78-85 → no UI means untrusted :87-89 → prompt D7 :91-96), called from packages/coding-agent/src/main.ts:771-790 and packages/coding-agent/src/package-manager-cli.ts:797-811. What needs trust: packages/coding-agent/src/core/trust-manager.ts:30-39,186-208.

D7 Trust this project folder? (the person's choice at startup) RULING · human
Answered how

The person, at startup in the terminal, when nothing earlier answered (D6): Trust, Trust parent folder, Do not trust, or either answer for this session only; a lasting choice is saved, and /trust can change it (from the next start).

Held by

person at the startup selector: packages/coding-agent/src/core/project-trust.ts:25-45 (formatProjectTrustPrompt, selectProjectTrustOption, save), options from packages/coding-agent/src/core/trust-manager.ts:67-97, shown by packages/coding-agent/src/cli/project-trust.ts:18-30 (showStartupSelector, interactive mode with hasUI only). Changed later with /trust (packages/coding-agent/src/modes/interactive/interactive-mode.ts:5425-5448, takes effect after restart).

D8 Should a folder that had nothing needing trust at startup become trusted when it gains such files during the session? RULING · code
Answered how

Yes: a session that started with nothing needing trust treats its folder as trusted, so settings, extensions or MCP servers added during the session load on /reload, and in the terminal pi then saves that folder as trusted without asking, unless a saved decision for it or a parent already applies.

Held by

packages/coding-agent/src/main.ts:733-736 (autoTrustOnReloadCwd when the cwd had no protected resources and no CLI override) and packages/coding-agent/src/main.ts:757-761 (such a session runs with projectTrusted = true); packages/coding-agent/src/core/agent-session.ts:3741 (/reload calls this._resourceLoader.reload() with no trust options, so packages/coding-agent/src/core/resource-loader.ts:548-555 keeps projectTrusted); packages/coding-agent/src/modes/interactive/interactive-mode.ts:5399-5416 (maybeSaveImplicitProjectTrustAfterReload writes trust.json = true), called after reload at packages/coding-agent/src/modes/interactive/interactive-mode.ts:6608.

D9 Is the project trusted when pi runs as an SDK library? RULING · code
Answered how

Yes by default: unless the program embedding pi passes its own settings with trust turned off, project settings, extensions and MCP config load with no trust check.

Held by

packages/coding-agent/src/core/sdk.ts:200 and packages/coding-agent/src/core/agent-session-services.ts:147 (SettingsManager.create(cwd, agentDir) with no options) → packages/coding-agent/src/core/settings-manager.ts:335 (options.projectTrusted ?? true); packages/coding-agent/src/core/sdk.ts:203-205 reloads resources with no resolveProjectTrust (packages/coding-agent/src/core/resource-loader.ts:548-552 skipped).

D10 May a configured but missing package be installed (running its package-manager install, including lifecycle scripts) at startup? RULING · code
Answered how

Yes by default: on each load, a configured npm package that is missing or at the wrong version is installed with the configured package manager, install scripts included, unless offline mode is on. A project's packages are installed only for a trusted project.

Held by

packages/coding-agent/src/core/package-manager.ts:1351-1371 (installMissing: skipped only when PI_OFFLINE is set :1352, package-manager.ts:61-65, or an onMissing callback says skip :1353-1357), triggered for npm when missing or version-mismatched (packages/coding-agent/src/core/package-manager.ts:1373-1379); the resource loader passes no callback (packages/coding-agent/src/core/resource-loader.ts:556, packageManager.resolve()); project scope requires trust (packages/coding-agent/src/core/package-manager.ts:1834-1837). Install commands: packages/coding-agent/src/core/package-manager.ts:1877-1934 (no --ignore-scripts; Grep ignore-scripts over the file: no hit).

D11 Is the tool the model called one this session may call at all? RULE · code
Answered how

Code allows the tools left after --tools, --exclude-tools and the defaults (A17, B12); any other name gets a "Tool not found" error. A tool hidden from the model's list can still be called by name (#10426).

Held by

packages/coding-agent/src/core/agent-session.ts:1557-1561 (_isAllowedTool: denylist, then allowlist; MCP tools stay registered unless the allowlist is empty or names mcp__ entries, :504-505) applied at registry build packages/coding-agent/src/core/agent-session.ts:3569-3579; active set at packages/coding-agent/src/core/agent-session.ts:1598-1604, stored as agent.state.tools :1643; then packages/agent/src/agent-loop.ts:726-733 ("Tool X not found" for anything not in the agent's tools). Lists come from --tools, --exclude-tools, --no-tools and the defaultTools setting (packages/coding-agent/src/core/sdk.ts:280-294).

D12 May a model-written codemode script call this name? RULE · code
Answered how

Code lets a script call any tool the session can call (the active ones plus every tool exposed as deferred or through codemode), never the codemode tool itself; each call gets the same checks and hooks as a model's call.

Held by

packages/codemode/src/runtime/execution.ts:389-390 (host looks the name up in its tool or globals table; unknown → error); the table is built from ctx.tools minus codemode (packages/coding-agent/src/extensions/codemode/execute.ts:519-552, packages/coding-agent/src/extensions/codemode/tool.ts:158-161), and ctx.tools is _getCallableTools (packages/coding-agent/src/core/extensions/runner.ts:972-975 → packages/coding-agent/src/core/agent-session.ts:1582-1587). Each call goes to ctx.executeTool (packages/coding-agent/src/extensions/codemode/execute.ts:540), which reaches D1/D2 via packages/coding-agent/src/core/agent-session.ts:730-763.

D13 May a codemode script call a paid model (classifier, image generation) on the user's credentials? RULING · code
Answered how

Yes, whenever the codemode tool is active: scripts can call classifier and image models through a models object on the user's credentials, up to 4 at a time. These calls do not pass the tool-call hooks one by one (a policy extension can only block the whole script), and the terminal lists them as they run.

Held by

packages/coding-agent/src/extensions/codemode/execute.ts:588-590 (model globals added when options.models and a session context), packages/coding-agent/src/extensions/codemode/index.ts:37 (models: options.models ?? true), calls run at packages/coding-agent/src/extensions/codemode/execute.ts:757-811 (runModelCall) on the session's model registry, with a concurrency limit only (MAX_CONCURRENT_MODEL_CALLS = 4, packages/coding-agent/src/extensions/codemode/execute.ts:50, applied at :750, :801).

D14 May a script send the user's model credentials to an endpoint the script chose? RULE · code
Answered how

No: a script names a model only by provider and id; pi looks up the registered model and calls it, so an address or headers the script supplies are never used.

Held by

packages/coding-agent/src/extensions/codemode/execute.ts:753-801 (runModelCall resolves by provider and id only, :776-779, and runs with the resolved model, :801: "A script-supplied baseUrl or headers must never receive the credentials"); packages/coding-agent/src/extensions/codemode/execute.ts:145-150 (catalog entries drop headers).

D15 May an MCP server config send a pi provider credential to its URL? RULE · code
Answered how

Only a server in the user's own global mcp.json may name a pi provider credential, and only for an https address (or http on this machine); a project's mcp.json cannot.

Held by

packages/coding-agent/src/extensions/mcp/config.ts:134-137 (auth refused in a project mcp.json); packages/coding-agent/src/core/mcp-servers.ts:281-288 (auth.provider required; https, or http on loopback only); project overrides may set only enabled, exposure, toolExposure (packages/coding-agent/src/extensions/mcp/config.ts:75, :109-121).

D16 May a configured MCP server be started or connected (a local process or a remote session)? RULING · code
Answered how

Yes, with no prompt: at session start every enabled server in the user's global mcp.json, and in a trusted project's .pi/mcp.json, is started or connected; --no-mcp turns this off.

Held by

packages/coding-agent/src/extensions/mcp/config.ts:146-157 (global mcp.json always; project mcp.json only when trusted, :149), read at session_start (packages/coding-agent/src/extensions/mcp/index.ts:1114-1151, trust from ctx.isProjectTrusted() :1344); enabled !== false filter (packages/coding-agent/src/extensions/mcp/index.ts:132, :1133); built-in MCP disabled by --no-mcp (packages/coding-agent/src/main.ts:799).

D17 Does a command the person typed with ! run locally, or does an extension take it over? RULING · code
Answered how

Locally, unless an installed extension handles ! commands: the first extension that answers either supplies the result or runs the command its own way.

Held by

packages/coding-agent/src/core/extensions/runner.ts:1269-1298 (emitUserBash: first valid handler result wins; none → local execution), called from packages/coding-agent/src/modes/interactive/interactive-mode.ts:7101 and packages/coding-agent/src/modes/rpc/rpc-mode.ts:562.

E. Execution and observation (26 seats)

E1 When a model call fails, does the failure look temporary enough to try the turn again? RULING · code
Answered how

Code retries a failed model call when its error text looks temporary (overload, rate limit, server or network trouble) and not like a quota or billing limit: up to 3 times by default, waiting 2, 4, then 8 seconds. A context overflow goes to compaction instead (F2, F3).

Held by

packages/ai/src/utils/retry.ts:266-271 (isRetryableAssistantError: a free-text regex over errorMessage, RETRYABLE_PROVIDER_ERROR_PATTERN 33-121 minus NON_RETRYABLE_PROVIDER_LIMIT_ERROR_PATTERN 7-31), called from packages/coding-agent/src/core/agent-session.ts:3774-3778 (context overflow excluded, goes to compaction) and acted on at 1993-1997 / _prepareRetry 3827-3867.

E2 When the provider's HTTP request itself fails, which statuses are retried inside the request, and how long may the provider ask us to wait? RULING · code
Answered how

Off by default: only when retry.provider.maxRetries is set does the provider layer retry a failed HTTP request (status 408, 409, 429, 5xx, or none), waiting as long as the server asks or a short growing delay; a requested wait over 60 seconds fails instead.

Held by

packages/ai/src/utils/provider-retry.ts:25-37 (408/409/429/5xx, x-should-retry header wins), delay cap 39-51 (60 s), loop 107-128; called per adapter (e.g. packages/ai/src/api/anthropic-messages.ts:661-668).

E3 May the tool calls of one response run at the same time, or one after another? RULING · code
Answered how

By default code runs the tool calls of one reply at the same time, after preparing each one in order (lookup, validation, hooks); results come back in order. A tool, or the agent, set to sequential makes them run one by one.

Held by

packages/agent/src/agent-loop.ts:518-533 (parallel unless config.toolExecution === "sequential" or any called tool has executionMode: "sequential"); default parallel packages/agent/src/agent.ts:261.

E4 Must two file changes aimed at the same file wait for each other? RULE · code
Answered how

Yes for edit and write: changes to the same file wait for each other, changes to different files do not. Read and bash do not wait.

Held by

packages/coding-agent/src/core/tools/file-mutation-queue.ts:32-61 (per real path), used by edit (edit.ts:163) and write (write.ts:67).

E5 Did this tool call succeed or fail, as the model will be told? RULE · code
Answered how

Code marks a call failed when the tool throws or reports an error itself (bash does for a non-zero exit), or when it was refused before running (unknown tool, bad arguments, blocked by a hook); the run itself continues.

Held by

packages/agent/src/agent-loop.ts:831-867 (executePreparedToolCall: a thrown error becomes an error result with the error message; result.isError === true otherwise), createToolResultMessage 940-954.

E6 Before the model sees a tool's result, should it be rewritten (content, details, structured content, usage replaced, or the error flag flipped)? RULING · external
Answered how

Only when an extension registers a tool_result handler: each handler may replace the result's content or details, or flip its error flag, before the model sees it.

Held by

an installed extension's tool_result handler, called at packages/coding-agent/src/core/agent-session.ts:689-702, applied by packages/agent/src/agent-loop.ts:880-907.

E7 Should the person stop what the agent is doing right now (stream, tool, retry wait, compaction)? RULING · human
Answered how

The person, by pressing Escape: while the agent is answering it stops the run and kills a running shell command; while a compaction, retry wait or branch summary runs, Escape cancels only that.

Held by

the person, key app.interrupt (Escape) packages/coding-agent/src/core/keybindings.ts:26; escape handler packages/coding-agent/src/modes/interactive/interactive-mode.ts:3139-3141 -> restoreQueuedMessagesToEditor 4852, 4862 (also 5730 on tree navigation) call session.abort() (packages/coding-agent/src/core/agent-session.ts:2503-2513); a running shell gets its process tree killed (packages/coding-agent/src/core/tools/bash.ts:126-128, 142-145).

E8 Where in the file does the model's oldText match, and is a near match (whitespace, quotes, dashes, Unicode forms) good enough? RULING · code
Answered how

Code tries an exact match first; if there is none, it matches again after normalizing line-end spaces, quotes, dashes, special spaces and Unicode forms. The match must be unique; when a near match was used, the lines it touches are written back in normalized form.

Held by

packages/coding-agent/src/core/tools/edit-diff.ts:300-362 (applyEditsToNormalizedContent), exact then fuzzy fuzzyFindText 207-245 with normalizeForFuzzyMatch 34-55 (NFKC, trailing whitespace, smart quotes, dashes, special spaces); uniqueness 328-331, overlap 341-350, no-op 357-359.

E9 How long may a shell command run before it is killed? RULING · llm
Answered how

The model, by passing a timeout in seconds or leaving it out; with none, the command can run until the person stops it. On expiry, code kills the command and everything it started.

Held by

the model, through the optional timeout argument (packages/coding-agent/src/core/tools/bash.ts:42, "optional, no default timeout"); enforced at bash.ts:132-137, bounds-checked 27-38.

E10 What did the shell command's exit tell us: success, failure, or killed? RULE · code
Answered how

Code treats exit code 0 as success and any other code as an error the model is told about; a command killed by a signal reports 128 plus the signal number.

Held by

packages/coding-agent/src/core/tools/bash.ts:155-158 (signal -> 128 + signal number, null -> 1), 386-407 (non-zero -> error result with "Command exited with code N"; null -> raise).

E11 How much of a shell command's output does the model see, and which part? RULING · code
Answered how

The model sees the last 2,000 lines or 50 KB of the output, whichever is smaller, with a note saying which lines it sees and where the full output was saved.

Held by

packages/coding-agent/src/core/tools/output-accumulator.ts:91-119 (snapshot: tail truncation via truncateTail, 2000 lines / 50 KB packages/coding-agent/src/core/tools/truncate.ts:11-12; full output spilled to a temp file, 239-256), message assembly packages/coding-agent/src/core/tools/bash.ts:338-356; structured output for scripts up to 1 MB head+tail (packages/coding-agent/src/core/tools/bash.ts:24, readFullOutput output-accumulator.ts:149-176).

E12 How much of a person's own ! shell command output goes into the conversation? RULING · code
Answered how

Code keeps the tail of the output (up to 2,000 lines or 50 KB, from a rolling buffer of about 100 KB) with colour codes and binary noise removed; its "truncated" flag can read false after older output was dropped (#10164).

Held by

packages/coding-agent/src/core/bash-executor.ts:48-146 (rolling buffer of 2 x 50 KB by text.length 92-98, then truncateTail 132; ANSI stripped, binary sanitized 78).

E13 How much of a file does the model see on one read, and where does the next read start? RULING · code
Answered how

The model chooses where to start and how many lines to read; code caps one read at 2,000 lines or 50 KB and says which offset to read next.

Held by

packages/coding-agent/src/core/tools/read.ts:153-205 (head truncation 2000 lines / 50 KB via truncateHead, continuation notices with the next offset 184-199; a first line over 50 KB is replaced by a sed hint 179-183).

E14 Which file does the path the model wrote actually mean (macOS NFD names, narrow no-break space before AM/PM, curly apostrophes)? RULING · code
Answered how

For the read tool and @file arguments only: if the path does not exist, code tries a few macOS spellings of it (a special space before AM/PM, decomposed accents, curly apostrophes) and uses the first that exists.

Held by

packages/coding-agent/src/core/tools/path-utils.ts:86-118 (resolveReadPathAsync), used by read only (read.ts:124); edit/write use plain resolveToCwd (edit.ts:161).

E15 Is this tool-result image sent to the model, and resized to what? RULING · code
Answered how

Code resizes images from the read tool, and images in any tool result, to the model's limits (with images.autoResize, on by default); an image it cannot process becomes a text note.

Held by

packages/coding-agent/src/core/tools/read.ts:133-152 (processImage with autoResizeImages, model inputLimits.images.resize), plus every tool's result through normalizeToolResultImages at packages/coding-agent/src/core/agent-session.ts:706-710; non-vision note read.ts:79-84.

E16 How much of a search, find or listing result does the model see? RULING · code
Answered how

Only when the opt-in grep, find or ls tools are enabled: they return up to 100 matches, 1,000 paths or 500 entries by default (the model may ask for more), and the output is cut at 50 KB with a note.

Held by

packages/coding-agent/src/core/tools/grep.ts:136, 211-296 (100 matches, 50 KB, 500 chars per line); packages/coding-agent/src/core/tools/find.ts:41, 112, 145-156 (1000 results); packages/coding-agent/src/core/tools/ls.ts:23, 84, 141-151 (500 entries).

E19 How much of an MCP result's text does the model see? RULING · code
Answered how

When an MCP result's text is over 20 KB, the model sees its start and end with the middle cut out, a warning, and the path of a file holding the full text; scripts get the full result.

Held by

packages/coding-agent/src/extensions/mcp/tools.ts:180-201 (limitMcpContent: 20 KB MCP_OUTPUT_MAX_BYTES line 51, middle cut, full text to a temp file).

E20 How long may one MCP call take before it is abandoned? RULING · code
Answered how

Each MCP request may wait the server's timeout (60 seconds by default) since its last progress update; the clock restarts on every progress update. A configured timeout must be above 0.

Held by

packages/coding-agent/src/extensions/mcp/runtime.ts:48, 210-212 (per-server timeout, default 60 s), passed via packages/coding-agent/src/extensions/mcp/index.ts:425 and packages/coding-agent/src/extensions/mcp/tools.ts:339-347; enforced by packages/mcp/src/client.ts:553-559 (armTimeout), re-armed on progress at 538-541.

E21 Before a call runs, which MCP servers must it wait for, so the tools it may reach exist? RULING · code
Answered how

Before a tool runs, code waits for the MCP servers it may need that are still connecting: all of them for tool search, the resource tools and scripts that look tools up, otherwise the servers a script names or the tool's own server.

Held by

packages/coding-agent/src/extensions/mcp/index.ts:1191-1209 (tool_call handler), reachesServer 227-231 (a word of the script contains the server's namespace), script reach packages/coding-agent/src/extensions/codemode/tool.ts:389-392 (getScriptReach: discovery globals -> all, else the words of the source).

E22 When the model's script calls a tool, what value does the script get back (structured object, text, or a thrown error)? RULE · code
Answered how

Code runs a script's tool call through the same checks and hooks as a model's call; the script gets the tool's structured result when it has one (even for a failed call), else its text, and a failed call without one throws in the script.

Held by

packages/coding-agent/src/extensions/codemode/execute.ts:480-486 (toScriptValue), call path 525-552 through ctx.executeTool -> packages/coding-agent/src/core/agent-session.ts:730-764 -> runToolCall (packages/agent/src/agent-loop.ts:821-829, same validation and hooks as a direct call).

E23 May two nested calls from scripts run at once? RULING · code
Answered how

By default yes: calls a script starts without waiting for each other run at the same time, except edits and writes to the same file; calls the script awaits one by one run one by one.

Held by

packages/coding-agent/src/core/nested-tool-calls.ts:202-218 (exclusive queue when the agent is sequential or the tool is sequential; a call holding the queue does not wait on its own nested calls).

E24 When is a model-written script stopped: by its own deadline, by a wait for a free worker, or never? RULING · llm
Answered how

The model, by an optional first-line timeout_ms option; without it a script has no deadline. A script first waits up to 60 seconds for one of two shared workers and fails if none frees; calls it already made are not undone.

Held by

the model, through the optional // @options: {"timeout_ms": ...} first line (packages/codemode/src/source.ts:13, 85-92), applied at packages/coding-agent/src/extensions/codemode/execute.ts:555-557, 592; absent -> Number.POSITIVE_INFINITY (555). Worker admission: 2 workers shared by every session (execute.ts:58-64), 60 s wait (69), reserveCodemodeWorker 78-98.

E25 How much of a script's output does the model see? RULING · code
Answered how

The model sees up to max_output_tokens (10,000 by default, counted as about 4 characters each) of the script's text, as its start and end with the middle cut out, plus where the full text was saved when saving succeeded.

Held by

packages/coding-agent/src/extensions/codemode/execute.ts:449-472 (truncateOutput: 10,000 estimated tokens at 4 chars each, head and tail kept, full text to a temp file), default 306; the model may change it with max_output_tokens (source.ts:79-84).

E26 When an extension runs a command through pi, did it succeed? RULE · code
Answered how

Code returns the command's exit code to the extension, but reports 0 when the command was killed by a signal from outside pi; an error starting the command is reported as code 1.

Held by

packages/coding-agent/src/core/exec.ts:96-104 (resolve({ ..., code: code ?? 0, killed })), reached from the extension API at packages/coding-agent/src/core/extensions/loader.ts:416.

E27 When an MCP server sends pi a request of its own (ask the model to sample, ask the person a question, list roots), does pi answer it? RULE · code
Answered how

No, apart from two requests: pi answers only ping and the list of its working folders (roots/list); a server asking pi to run its model or to ask the person a question gets a "Method not found" error.

Held by

packages/mcp/src/client.ts:492-505 (handleRequest: a method with no registered handler is answered with JSON-RPC "Method not found"); handlers registered at packages/mcp/src/client.ts:175-181 (ping, and roots/list only when the client was given roots); the coding agent builds each client with roots set to the session folder and nothing else (packages/coding-agent/src/extensions/mcp/runtime.ts:359-365), so it advertises only the roots capability (packages/mcp/src/client.ts:217-218).

F. Limits and memory (14 seats)

F1 Has the conversation grown close enough to the model's window that it must be compacted now? RULING · code
Answered how

Code compacts when the conversation's estimated size passes the model's window minus a reserve (16,384 tokens by default), checking before each request and after each run; compaction is on by default. The estimate is the provider's last reported size plus about one token per 4 characters since.

Held by

packages/coding-agent/src/core/compaction/compaction.ts:267-270 (shouldCompact); estimate packages/coding-agent/src/core/compaction/compaction.ts:196-262, packages/coding-agent/src/core/compaction/compaction.ts:298-349; call sites packages/coding-agent/src/core/agent-session.ts:3114-3149, packages/coding-agent/src/core/agent-session.ts:776-785, packages/coding-agent/src/core/agent-session.ts:904-905, packages/coding-agent/src/core/agent-session.ts:838-841, packages/coding-agent/src/core/agent-session.ts:1932-1937.

F2 Did this provider error or reply mean the context overflowed, so compaction (not a plain retry) is the fix? RULING · code
Answered how

Code treats an error as overflow when its text matches one of the known provider messages for an over-long prompt (and is not a rate-limit message); a reply whose reported input exceeds a known window also counts. Overflow wording the list does not know is missed and treated as an ordinary error.

Held by

packages/ai/src/utils/overflow.ts:144-178 (isContextOverflow), patterns packages/ai/src/utils/overflow.ts:39-86, isRecoverableLength packages/ai/src/utils/overflow.ts:186-188; consumed packages/coding-agent/src/core/agent-session.ts:3068-3074; retry exclusion packages/coding-agent/src/core/agent-session.ts:3774-3777.

F3 After an overflow or a cut-short reply, should pi compact and retry the turn, compact and keep the reply, or give up? RULE · code
Answered how

Code, when compaction is on: an overflowing reply that completed is compacted and kept; an overflow error or a reply cut off early is compacted and retried once, and a second failure ends the run with an error.

Held by

packages/coding-agent/src/core/agent-session.ts:3075-3112; once-only flag packages/coding-agent/src/core/agent-session.ts:3084, packages/coding-agent/src/core/agent-session.ts:3107, reset packages/coding-agent/src/core/agent-session.ts:1123, packages/coding-agent/src/core/agent-session.ts:1173-1175; omission packages/coding-agent/src/core/agent-session.ts:1244-1269.

F4 Where does the summarised part end, and which recent messages are kept word for word beside the summary? RULING · code
Answered how

Code keeps the most recent messages, about 20,000 tokens by default, word for word, and summarizes what comes before; the cut never falls on a tool result, and a cut inside a turn gets its own summary (F6).

Held by

packages/coding-agent/src/core/compaction/compaction.ts:789-857 (findProjectedCutPoint); cut-point roles packages/coding-agent/src/core/compaction/compaction.ts:351-364; assembled by prepareCompaction packages/coding-agent/src/core/compaction/compaction.ts:859-923; default packages/coding-agent/src/core/settings-defaults.ts:9-13.

F5 What does the checkpoint summary that replaces the older conversation say? RULING · llm
Answered how

The session's model writes it from the older messages (and any earlier summary) using a fixed prompt with six headed sections; code rejects an error, a cut-off reply or a tool call, and otherwise stores the text as returned, with lists of files read and changed. An extension may supply the summary instead.

Held by

packages/coding-agent/src/core/compaction/compaction.ts:696-753 (generateSummaryWithUsage), via completeSummarization packages/coding-agent/src/core/compaction/compaction.ts:618-638; model from _getSummarizationRequestAuth packages/coding-agent/src/core/agent-session.ts:572-609, called by _runDefaultCompaction packages/coding-agent/src/core/agent-session.ts:2788-2811.

F6 When the cut falls inside a turn, what does the summary of that turn's earlier half say? RULING · llm
Answered how

The same model summarizes the earlier half of that turn using a fixed prompt with three headed sections, and code adds it to the history summary under a fixed separator.

Held by

packages/coding-agent/src/core/compaction/compaction.ts:1062-1104 (generateTurnPrefixSummary), called packages/coding-agent/src/core/compaction/compaction.ts:980-1019; model as F5 (packages/coding-agent/src/core/agent-session.ts:2796-2799).

F7 How much of each tool result does a summarizer get to see? RULING · code
Answered how

Each tool result is cut to its first 2,000 characters; tool-call arguments are kept whole and the model's thinking is left out.

Held by

packages/coding-agent/src/core/compaction/utils.ts:93-104 (truncateForSummary), applied in serializeConversation packages/coding-agent/src/core/compaction/utils.ts:146-150.

F8 When the person leaves a branch of the session tree, should what happened on it be summarized and carried along? RULING · human
Answered how

The person, in the terminal: after picking where to go in the session tree they choose no summary, a summary, or a summary with their own instructions (a setting can skip the question, meaning no summary); other modes pass the choice in, defaulting to none.

Held by

packages/coding-agent/src/modes/interactive/interactive-mode.ts:5697-5725 ("Summarize branch?" selector), passed to navigateTree packages/coding-agent/src/modes/interactive/interactive-mode.ts:5756-5759; other callers packages/coding-agent/src/modes/rpc/rpc-mode.ts:330-331, packages/coding-agent/src/modes/print-mode.ts:86-87.

F9 What does the summary of the abandoned branch say? RULING · llm
Answered how

The session's model writes it from the abandoned branch with a fixed prompt of five headed sections, adding the person's own instructions when given; code rejects errors, cut-off replies and tool calls, and stores the text with a fixed preamble and file lists.

Held by

packages/coding-agent/src/core/compaction/branch-summarization.ts:295-386 (generateBranchSummary); called with the session model packages/coding-agent/src/core/agent-session.ts:4122-4134.

F10 When the abandoned branch is too long, which of its messages reach the summarizer? RULING · code
Answered how

Code keeps the newest messages of the branch that fit the model's window minus a reserve (16,384 tokens by default), leaving out tool results.

Held by

packages/coding-agent/src/core/compaction/branch-summarization.ts:197-249 (prepareBranchEntries); budget packages/coding-agent/src/core/compaction/branch-summarization.ts:315-318; tool results skipped packages/coding-agent/src/core/compaction/branch-summarization.ts:160-163.

F11 Is keeping the prompt cache warm worth paying for a refresh right now? RULING · code
Answered how

Code, unless cache warming is off: shortly before the provider's prompt cache would expire, it re-sends a one-token copy of the last request when the expected saving is at least $0.05; by default only while the agent is working.

Held by

packages/coding-agent/src/core/cache-warmer.ts:378-400 (evaluate); constants packages/coding-agent/src/core/cache-warmer.ts:15-26; eligibility start packages/coding-agent/src/core/cache-warmer.ts:205-243; settle packages/coding-agent/src/core/cache-warmer.ts:245-257; refresh packages/coding-agent/src/core/cache-warmer.ts:284-355; wired packages/coding-agent/src/core/sdk.ts:334-339.

F12 Was this turn's prompt-cache miss real waste worth telling the person about? RULING · code
Answered how

Code counts a miss when a reply re-paid for more than 1,024 tokens of the previous prompt after caching had been seen in the session; model switches count. The total shows in /session; per-turn notices are off by default.

Held by

packages/coding-agent/src/core/cache-stats.ts:56-90 (detectMiss), scan packages/coding-agent/src/core/cache-stats.ts:104-142; shown packages/coding-agent/src/modes/interactive/interactive-mode.ts:6805, per turn packages/coding-agent/src/modes/interactive/interactive-mode.ts:4290-4293; default packages/coding-agent/src/core/settings-defaults.ts:28.

F13 Has this session become a conversation worth writing to disk yet? RULE · code
Answered how

Code writes the session file only once the conversation has a user or assistant message, then adds each new entry as a line; sessions kept in memory are never written.

Held by

packages/coding-agent/src/core/session-manager.ts:1160-1189 (_hasConversation: the first user or assistant message creates the file).

F14 When a saved session file is read back, which lines are kept? RULE · code
Answered how

Code keeps every line that reads as JSON and silently drops the rest; a file whose first entry is not a session header reads as empty.

Held by

packages/coding-agent/src/core/session-manager.ts:616-670 (parseSessionEntryLine, loadEntriesFromFile); discovery packages/coding-agent/src/core/session-manager.ts:729-737.

G. Judging the result (4 seats)

G1 Is the work finished, so the run may stop? RULING · llm
Answered how

The model, implicitly: a reply with no tool call ends the run unless messages are queued or an extension asks for more; an error or abort ends it at once. Code adds no check of its own, so a reply cut off at its length limit also ends the run, unless the one compact-and-retry recovery applies (F3).

Held by

packages/agent/src/agent-loop.ts:267-271 (tool calls read from the reply); exit packages/agent/src/agent-loop.ts:303-326.

G2 After the model stopped, should the run keep going anyway? RULING · external
Answered how

Only when an extension handles turn_end or agent_before_settle: it may ask for another turn, which runs only if the conversation can continue. Without one, the run continues only for queued messages and pi's own retries (E1, F3).

Held by

packages/coding-agent/src/core/agent-session.ts:2022-2044 (agent_before_settle); turn_end packages/coding-agent/src/core/agent-session.ts:846-884; finishTurn wiring packages/coding-agent/src/core/agent-session.ts:886-896.

G3 Does this tool batch end the run? RULE · code
Answered how

Only when every result in the batch asks to stop (a tool or a hook can set this; no built-in tool does); queued messages or an extension can still continue the run.

Held by

packages/agent/src/agent-loop.ts:700-702 (shouldTerminateToolBatch), applied packages/agent/src/agent-loop.ts:592, packages/agent/src/agent-loop.ts:668, consumed packages/agent/src/agent-loop.ts:281; hints packages/agent/src/agent-loop.ts:757-758, packages/agent/src/agent-loop.ts:902, packages/coding-agent/src/core/extensions/types.ts:1468.

G4 Did the run end completed, in error, or aborted? RULE · code
Answered how

Code labels it from the last reply: error and aborted as such, and everything else, a reply cut off at its length limit included, as completed.

Held by

packages/coding-agent/src/core/agent-session.ts:850-851 (_lastActivityOutcome from stopReason: aborted / error / everything else "completed"); handed to extensions in turn_end (:874) and agent_before_settle (:2028).

H. Delegation (0 seats)

This map records no seats in this stage.

I. Learning and feedback (5 seats)

I1 Should a bug report go to the pi developers, and with the full transcript, a model-written summary instead, or neither? RULING · human
Answered how

The person, in the terminal's /bug flow: they add an optional description, choose whether to include the transcript (and if not, whether to attach a model-written summary instead), then upload, save as a zip, or cancel. Every choice comes before any summary is written.

Held by

packages/coding-agent/src/modes/interactive/bug-report.ts:107-147 (promptForOptions: the person's choices), run by reportBug packages/coding-agent/src/modes/interactive/bug-report.ts:50-105.

I2 What does the model-written bug report say when the person withholds the transcript? RULING · llm
Answered how

The session's model writes a four-section report from the newest messages that fit and the person's description, and is told to leave out secrets. Code rejects failed or empty replies and attaches the text unchecked; the person does not see it before it is uploaded or saved.

Held by

packages/coding-agent/src/core/bug-report.ts:330-375 (generateBugReportSummary), called by summarizeForBugReport packages/coding-agent/src/core/agent-session.ts:4387-4401.

I3 When the bug report's transcript budget is exceeded, which messages does the summarizer see? RULING · code
Answered how

Code takes messages newest first until they would pass 60% of the model's window (always at least the newest one), and the prompt says when earlier messages were left out.

Held by

packages/coding-agent/src/core/bug-report.ts:302-313 (selectMessages); budget packages/coding-agent/src/core/bug-report.ts:332-333.

I4 Which settings, URLs and identifiers count as secrets and are stripped before a report leaves the machine? RULING · code
Answered how

Code drops the tracking and device ids, replaces values whose names look secret (api key, token, secret, password, credential, authorization, cookie) in the settings and model fields, strips passwords and secret-named parameters from URLs, and sends only the names of model and provider headers and of PI_* environment variables; the description, extension error messages and provider error messages are sent as they are.

Held by

packages/coding-agent/src/core/bug-report.ts:20-64 (SENSITIVE_KEY, redactUrl, redactJsonValue, redactSettings); names-only collection packages/coding-agent/src/core/bug-report.ts:86-89, packages/coding-agent/src/core/bug-report.ts:107, packages/coding-agent/src/core/bug-report.ts:119; description and extension errors packages/coding-agent/src/core/bug-report.ts:154-179 (:155, :174); provider error messages packages/coding-agent/src/core/bug-report.ts:183-222 (:211).

I5 Is an uploaded bug report tied to the person's Radius account? RULE · code
Answered how

Yes when the person is signed in to Radius: the upload carries their sign-in token, with no question asked; otherwise it is anonymous.

Held by

packages/coding-agent/src/modes/interactive/bug-report.ts:180-186; sent packages/coding-agent/src/core/bug-report-upload.ts:20-24.

How this map was made

Four readers each took a part of the agent and wrote seat cards from the source. The map's author then re-read every seat against the cited lines and corrected what the source did not support, and rewrote each answer in a short form that describes the default. Reviews by a model from another family (read-only, at the same commit) checked the answers against the code, and each of their findings was checked against the code before anything changed. 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.