A Request Becomes a Change: Tools, Paths, and Permission Boundaries
In PI-Desktop, the difficult part of a coding-agent request is not sending text to a model; it is deciding when that request may become a real file change or command. This chapter follows one tool call from a project-bound session through path resolution, permission policy, execution, and review. The result is a practical test for the product's control model: local work should be convenient enough to continue, but every meaningful crossing should remain tied to the right session, root, decision, and record.
The path is part of the permission decision
Imagine a developer has two repositories open in PI-Desktop. A session in repository A is investigating a failing test while the developer switches the visible sidebar to repository B. The Agent in A then asks to read a source file and edit a test. The safe answer is not “use the folder currently on screen.” The safe answer is to resolve the project attached to the originating session and keep the work there.
PI-Desktop makes that session identity part of the host request. For a durable session, host-core looks up the session's persisted project binding. The visible project tab is a presentation choice; it is not a replacement for the session's execution root. This distinction prevents an asynchronous result from being interpreted in the wrong repository, and it makes background work behave like the work the user started rather than like work belonging to whichever screen happens to be active later.
Once the correct project is known, the host resolves the requested path. A relative path is joined to the workspace and normalized lexically. That first pass handles . and .. before the filesystem is consulted, so a traversal hidden behind directories that do not yet exist cannot appear harmless. The host then canonicalizes the deepest existing part of the path and reattaches any not-yet-created tail. This second pass matters because a path can look inside the project as text while a symlink inside the project points somewhere else.
The two checks answer different questions. Lexical normalization asks whether the spelling tries to climb outside the root. Canonicalization asks where the filesystem would actually take the operation. PI-Desktop requires the result to remain within the project root. It applies the same logic after a permission decision, so approving a path does not skip the canonicalization step. A user can explicitly authorize an outside path when the policy allows that capability, but an outside path is then visible as an exceptional access rather than being mistaken for an ordinary project-relative operation.
The built-in tools have different path shapes because their risks and meanings differ. Read expects an existing regular file. If the Agent points it at a directory, the host returns an argument error with a search suggestion instead of guessing what should be listed. Glob searches from a directory root. Grep can search a file or a tree, and a directly named file does not silently turn into a walk through its siblings. Write and Edit change content. Bash runs a non-interactive command. These distinctions prevent a vague “filesystem tool” from hiding different authority levels behind one interface.
A second root handles temporary work. Each session can have a scratch directory outside the user's project for one-off scripts, pasted material, drafts, spill output, and other intermediate files. The purpose is practical: a diagnostic script or downloaded intermediate should not dirty the repository or appear as an accidental deliverable in its Git status. In a path-less temporary session, that scratch directory becomes the session's workspace instead of inheriting the last visible project.
A scratch write can skip a permission card because it cannot touch the project, but that shortcut is not a shortcut around security. The host still resolves the path with the same containment and symlink checks. A symlink planted in scratch cannot be used to reach the project or another directory. Plan and Goal do not expose Write or Edit at all, so the scratch convenience rule cannot turn those tools into contract-mode capabilities. Bash may still create scratch data when the selected permission mode permits it; the distinction is between where the data lands and whether a command is authorized.
The execution root is therefore a relationship, not a string. It joins a session to a project, a project-relative path to a canonical filesystem target, and a temporary file to a disposable session area. If any of those relationships cannot be resolved safely, the host returns a structured failure instead of redirecting the request to a convenient default.
The order is the point of the diagram. Host-core does not ask the model to police its own path, and it does not let a permission card substitute for path resolution. The user decides whether a request may proceed when a decision is required; the host still decides where the request would land and whether the operation is within the session's allowed boundary.
A tool result is not just output
Path safety answers “where?” Permission policy answers “under what user-authorized posture?” PI-Desktop separates the risk of a tool from the mode the user chooses for high-risk work. Read, Glob, and Grep inside the session's workspace or scratch roots are treated as low-risk. Write, Edit, and Bash are high-risk because they can change state or run code. The system can also classify plugin tools and other operations separately rather than assuming that every tool has the same consequence.
The default posture is ask. In that mode, a high-risk operation produces an inline permission card. The user can allow only the current call, allow that tool for the session, or deny it. The session grant is deliberately scoped by tool name: approving Bash does not automatically approve Edit, and a grant in one session is not inherited by another. A developer who wants less interruption can choose accept-edits, which allows workspace Write and Edit without a card but still asks about Bash. auto allows the high-risk calls without confirmation.
These modes are not interchangeable labels for trust. They describe how often the user must answer, while the host continues to enforce the path and contract rules. An explicit path outside the workspace and scratch roots is an additional capability. In ask or accept-edits, it still reaches the ordinary permission decision; in auto, the user has selected the posture that permits it. A denied, cancelled, or timed-out request does not execute as a partial compromise.
A permission card also has a lifecycle. It is keyed to the session and request rather than to the order in which cards happen to appear. It shows the tool, risk, short reason, bounded argument preview, and workspace context. After 120 seconds without an answer, the host denies the request. That timeout is not just a user-interface convenience. An Agent that can remain blocked forever would hold open a turn, an application resource, and potentially a user's attention without a defined outcome. Failing closed gives the model a tool error that it can interpret rather than leaving the system in an ambiguous waiting state.
The host records the decision and the operation. Audit data includes the session, turn, and tool-call identity, a bounded preview or argument hash, the decision, duration, success state, and error code. This is useful for two reasons. It lets a user understand what happened during a long task, and it gives the product a durable account of sensitive operations even when the final answer is brief. A successful command is not proof that the command was safe; the audit trail preserves the fact that it ran and under which session context.
Write and Edit add a review boundary. When a workspace mutation succeeds, host-core can capture bounded evidence of the previous file and describe the change in a message-owned review record. The renderer displays that record with the tool message rather than recomputing a global Git diff. The result stays associated with the session and message that produced it, so a later commit does not erase the historical explanation of what the Agent changed.
Rollback is guarded rather than unconditional. The host restores the captured previous bytes, or removes a newly created file, only if the current file still matches the post-tool hash. If someone has edited the file after the Agent's change, rollback reports a conflict instead of overwriting the newer work. This is an important limit: review is not a magical undo button. It is a conditional recovery path that protects the user from replacing a later change with an older snapshot.
The same bounded thinking applies to tool output. A model that receives every line of a large search result or build log can spend its context on material that is difficult to use. PI-Desktop gives Read, Glob, and Grep a bounded result window and gives Bash separate bounds for standard output and error output. A truncated result carries explicit metadata or a marker explaining what was kept and how to continue. A Bash spill can preserve a fuller bounded copy in session scratch, but the system does not promise to retain unlimited raw output forever.
The direction of truncation is chosen for meaning. Search results can be narrowed or paged, so the host can stop at a bounded window and report the next step. Shell standard output may keep the beginning while error output may keep the tail, because the final diagnostic lines often explain why a command failed. A line clipped by a character limit is not treated as fully displayed source. That detail protects the Edit contract: an Agent cannot claim it saw and safely anchor a change to the part of a line that the host deliberately cut away.
This makes bounded output part of the action boundary, not merely a performance optimization. The model needs enough information to act, the UI needs enough information to remain responsive, and the edit mechanism needs to know which content was actually shown. A result that says only “some output was omitted” would invite blind retries or edits. A result that states what was bounded and how to obtain the next portion gives the Agent a controlled recovery path.
A real change therefore has several checkpoints: the session root is resolved, the path is canonicalized, the permission posture is evaluated, the tool runs under a timeout, the result is bounded and structured, and the audit or review record is associated with the same session. That chain explains why PI-Desktop can offer local action without reducing the user's role to clicking a vague “allow everything” button.
There are still limits to this design. Host policy does not prove that a user-authorized command is benign. Bash and its child processes run with the user's operating-system privileges, so the boundary is an application-level containment and approval system, not a kernel sandbox. An explicit auto choice can reduce friction precisely by giving the Agent more authority. The product's control claim is strongest when the user understands that trade-off and uses review and audit as part of the workflow rather than treating them as guarantees that eliminate judgment.
The result is a deliberately layered answer to a simple request. A model may suggest “edit this file,” but PI-Desktop does not let that sentence decide the target, the authority, or the record. The session determines whose project is involved; the resolver determines where the path leads; the permission layer determines whether the chosen posture permits the action; and the review system shows what changed. The next question is what happens when the user wants to approve an intended course of work before any such change begins.