Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

## Unreleased

### Features and behavior changes

- Give writable Pi nodes built-in shell tools for dependency installation, builds,
tests, and repair. Shell calls participate in cancellation and the workspace
write barrier before checkpointing; prompts describe workspace boundaries and
shared resources. Read-only nodes still have no shell, and parent extension/MCP
tools are not inherited.
- Checkpoint tracked changes and non-ignored new files using normal Git staging
semantics. Ignored dependencies, caches, and build outputs are no longer
automatically archived or passed to successors; already tracked and deliberately
force-added files remain tracked.

These changes require the next minor release under the compatibility policy.
See [migration guidance](docs/compatibility.md#upcoming-workspace-capability-changes)
for callers relying on shell-free workers or preservation of ignored outputs.

## 0.2.1 — 2026-10-04

### Maintenance
Expand Down
27 changes: 17 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,10 +416,11 @@ provides `request.merge.sources` and `request.merge.finish(dispositions)` to
merge agents. Adapters must enforce workspace capabilities and wrap mutating
file tools in `request.withWorkspaceWrite(operation)`, so cleanup waits for
in-flight writes and rejects later writes. Core Git mutations use this barrier.
The included Pi adapter provides guarded `write`/`edit` alongside its read tools.
The included Pi adapter provides guarded `write`/`edit` and Pi shell tools alongside its read tools.
For read-only workspaces, adapters must omit mutating tools; the core write
barrier also rejects writes. This includes all nodes outside Git. Pi never provides
`bash`, `powershell`, or a test runner to nodes.
barrier also rejects writes. This includes all nodes outside Git. Writable Pi nodes
can use `bash` (and `powershell` on Windows) to build and run tests. Shell calls
participate in the write barrier and forward cancellation to their processes.

`request.predecessors` contains direct active predecessors in incoming-edge
order, including failures on unconditional edges with an `error` field. Each source appears once:
Expand Down Expand Up @@ -467,7 +468,10 @@ The model-facing Git tool separates `command` from `args`, for example
accepts the complete argument array. Duplicate command prefixes, network Git,
branch switching, and filesystem-boundary overrides are rejected.

Instances checkpoint before downstream admission. All source checkpoints remain
Instances checkpoint tracked changes and non-ignored new files before downstream
admission. Ignored dependencies, caches, and build products are discarded on cleanup;
files already tracked or explicitly force-added remain tracked under normal Git rules.
All source checkpoints remain
reusable; no merge consumes or deletes a predecessor's result. Job cleanup
archives and removes owned worktrees, retaining refs under
`refs/braid/checkpoints/`. Integration additionally captures a pre-write
Expand All @@ -489,19 +493,22 @@ isolated from those source edits. See [execution control](docs/execution-control

**The adapter is a trust boundary, not a security sandbox.** It must avoid shared
conversation state, expose only its declared capabilities, and forward `signal` to its provider.
The core never gives the model arbitrary code execution or a recursive Braid
tool. An optional Pi adapter translates this same contract without changing the
runtime; the core package does not depend on Pi. See
The core does not supply shell tools or a recursive Braid tool; adapters choose
their tool capabilities. The Pi adapter supplies shell tools to writable nodes
without changing the runtime; the core package does not depend on Pi. See
[`integrations/pi/README.md`](integrations/pi/README.md) for installation and testing.

The included OpenAI-compatible adapter uses fresh Chat Completions contexts,
a strict `decide({ choice })` tool and one tool-free continuation for decisions.
Merge/integrate nodes use a local `git` / `finish_merge` tool loop; ordinary OpenAI nodes
have no filesystem tools. Pi exposes read and guarded write tools plus these
core Git/merge tools. Tool errors go back to merge agents for recovery. Both
have no filesystem tools. Pi exposes read, guarded write, and shell tools plus
these core Git/merge tools. Tool errors go back to nodes for recovery. Both
adapters sum usage across their model calls and forward cancellation.
Pi writes reject external paths, Git metadata, symlinks, hard links, and special
files. These checks are not an OS sandbox against concurrent filesystem attacks.
files. Shell tools can bypass these checks and run with host permissions; prompts
require nodes to respect workspace boundaries, shared Git state, and external
resources. Parent extension/MCP tools and hooks are not inherited. These checks
and cooperation rules are not an OS sandbox.
See the [Pi filesystem capabilities](integrations/pi/README.md#node-filesystem-capabilities).

Pi tool and time budgets are unlimited by default. Its `options.maxToolRounds`
Expand Down
15 changes: 12 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,21 @@ answer that question.
- Braid isolates invocation context; it is not a process or filesystem sandbox.
A custom runner is trusted code with the host process's permissions.
- The core manages Git snapshots, worktrees, checkpoint refs, and merge tools.
Pi workers can write/edit their assigned Git worktree. Integrate agents can apply
Writable Pi workers can write/edit and run shell commands in their assigned Git
worktree. Shells run with host permissions; prompts constrain workspace writes,
shared Git state, and external side effects. Integrate agents can apply
changes to the source checkout; merge agents use isolated worktrees; they are not restricted to read-only analysis.
Outside Git, Pi file tools stay read-only. Read paths can expose files outside
the checkout and disclose content to a model provider.
- Execute/decision nodes can request `workspace: "read-only"` inside Git. Pi
omits write/edit tools, and core rejects write-barrier operations. Git inspection
omits write/edit and shell tools, and core rejects write-barrier operations. Git inspection
remains available. These nodes read an isolated predecessor
snapshot; custom runners must honor this capability themselves.
- Guarded write tools reject external paths, Git metadata, symlinks, hard links,
and special files, but are not an OS sandbox against concurrent filesystem
attacks. Avoid concurrent external source edits while integrate agents run. A
attacks. Shell commands can bypass these guards. Parent extension/MCP tools and
their interception policies are not inherited by nodes. Avoid concurrent external
source edits while integrate agents run. A
cancellation or failed merge can leave partial integration/conflicts for review;
checkpoint and backup refs support recovery.
- Prompts, predecessor outputs, tool results, errors, and model answers may be
Expand All @@ -68,6 +72,11 @@ answer that question.
- Cancellation and timeout cannot stop synchronous JavaScript or remote work
that ignores the abort signal. Enforce provider quotas and host-side admission
limits for untrusted callers. See [resource limits](docs/resource-limits.md).
Pi shell calls are drained before checkpointing and stop their process group
(Windows uses `taskkill /T`); daemonized processes outside that group and external
services can outlive a call. Windows cleanup after parent exit is best effort.
Ignored new files are excluded from checkpoints and discarded with the worktree;
explicitly staged files still follow Git tracking semantics.

The OpenAI-compatible adapter sends its API key only to the configured base URL.
Treat that URL as trusted configuration. Keep credentials out of graphs, logs,
Expand Down
25 changes: 25 additions & 0 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,31 @@ separate gate reminder; when both preferences are enabled it supplies the single
completion reminder for that instance. Cancellation still sends failure reminders
for opted-in running instances.

## Upcoming workspace capability changes

The Unreleased changes target the next minor release; they are not part of 0.2.1:

- Writable Pi nodes now receive `bash` and, on Windows, `powershell`, allowing
dependency installation, builds, and tests within a node. If a graph relies on
workers having no shell, set execute/decision nodes to `workspace: "read-only"`
(which also disables file writes), or use a custom runner with the required
capability policy. Writable shell access uses host permissions and prompt-based
cooperation rules; worktrees are not a security sandbox. Parent extension/MCP
tools and their hooks are not inherited.
- Core checkpoints now follow `git add --all` semantics instead of force-adding
every output. Move artifacts needed by successors or for recovery to non-ignored
paths, or deliberately track them. Already tracked files, including files
explicitly staged with `git add --force`, remain tracked even when they match
ignore rules. Untracked ignored outputs are discarded when worktrees are removed,
including after failed or cancelled executions. This applies to every adapter.
- Shell commands must run in the foreground. On POSIX, Braid stops remaining
children in the command's process group even on normal completion; Windows uses
best-effort process-tree cleanup. Run a temporary server and its checks within
one foreground command and clean it up before returning. Detached daemons and
external services are not contained by this lifecycle.

No graph field, result shape, or event schema changes are required.

## Versioning

Core and Pi release together with matching versions. During 0.x, patch releases
Expand Down
43 changes: 32 additions & 11 deletions integrations/pi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ an explicit per-turn planning policy to Pi's system prompt and tool metadata:
changes spanning multiple files, call Braid first when two or more concerns
can be handled independently; use `workspace: "read-only"` for analysis,
review, routing, and synthesis, and worktrees for implementation;
- do not use Braid for simple one-step answers, trivial direct edits, or shell
work; keep tests and shell commands in the parent agent;
- do not use Braid for simple one-step answers, trivial direct edits, or a single
shell command; writable nodes can implement, test, and fix their own work;
- the user does not need to say “Braid” or design the graph;
- when Braid fits, the model should submit a graph and refine it with live updates when needed, continue independent work, and retrieve the terminal outputs after
the completion reminder.
Expand All @@ -142,16 +142,18 @@ or strengthen the project/system prompt for that model. The adapter explicitly
asks the model to make the delegation choice before directly inspecting the
repository. Do not add a generic `always call braid` rule: that would waste
model calls and bypass direct tools.
Merge nodes combine snapshots; integrate nodes apply selected changes to the caller; the parent reviews results and runs tests.
Merge nodes combine and validate snapshots; integrate nodes apply selected changes to the caller; the parent reviews results and performs any remaining validation.
Each node gets a new Pi AI context containing only the Braid goal, its node prompt,
labelled direct predecessor outputs, and workspace metadata. It receives Pi's
`read` and `ls`, plus `grep` when local `rg` is available and `find` when
local `fd`/`fdfind` is available. Missing search dependencies are reported in the
node prompt, with `ls`/`read` as alternatives. Dependencies are checked before
exposing search tools and again before executing them; missing tools are not
installed by Braid. Git worktrees additionally receive `write` and `edit`.
It receives no parent transcript, shell tools, test runner, skills, or arbitrary
code execution. Decision nodes additionally receive `decide`. Git nodes receive
installed automatically by Braid. Writable workspaces additionally receive `write`,
`edit`, and Pi's `bash` tool (`powershell` is also exposed on Windows), so nodes
can install local dependencies, build, and run tests. Read-only nodes have no shell.
Nodes receive no parent transcript, skills, or inherited extension/MCP tools.
Decision nodes additionally receive `decide`. Git nodes receive
local Git inspection; merge/integrate nodes also receive Git integration commands and
`finish_merge`. Merge agents receive bounded changed-file lists, diff statistics
and previews; integrate also receives the source checkout's dirty status. The model-facing `git`
Expand Down Expand Up @@ -237,7 +239,8 @@ Root executions use the initial job snapshot, including tracked and non-ignored
untracked caller edits. Later loop rounds get new worktrees; they never reuse a
previous invocation's workspace. `workspace: "read-only"` disables write/edit
while retaining an isolated snapshot. Outside Git, all filesystem access is
read-only. Search tools require installed `rg`/`fd`; shell/tests are unavailable.
read-only, including no shell tools. Search tools require installed `rg`/`fd`.
Writable nodes can run shell commands and tests in their assigned working directory.

`merge` combines predecessor results into a new isolated worktree. `integrate`
applies selected changes to the invoking checkout and preserves user edits. Both
Expand All @@ -261,17 +264,35 @@ results, explicitly connect them to an integrate node:
}
```

Checkpoints save tracked changes and non-ignored new files, following normal
`git add --all` semantics. Existing tracked files remain tracked even when they
match ignore rules. Ignored dependencies, caches, and build outputs are discarded
with the worktree and are not carried to successors; keep required outputs in
non-ignored paths. Files deliberately staged with `git add --force` remain tracked.

`braid_status` retains execution-keyed workspace paths, checkpoint refs, and target
merge dispositions. Cleanup removes worktrees while keeping immutable checkpoints.
Inspect with `git show <checkpointRef>:path`. Integration additionally saves a
pre-write backup ref. A failed integration can leave partial source changes or
conflicts; core does not reset the caller's checkout. Integrations serialize
within the process, without locking parent edits or other processes.

Pi's guarded writes reject external paths, Git metadata, symlinks, hard links,
and special files. This is a capability boundary, not an OS sandbox. A custom
runner must honor the core write barrier so cancellation can drain writes before
cleanup. Calling the Pi runner without an assigned workspace stays read-only.
Pi's guarded `write`/`edit` reject external paths, Git metadata, symlinks, hard links,
and special files. Shell tools run with host permissions and can bypass those
checks. Prompts require writes to stay in the assigned workspace, reserve source
checkout changes for integrate nodes, and protect shared Git refs/configuration,
other nodes, ports, databases, caches, and external services. These are cooperation
rules, not an OS sandbox. Shell tools are created for each invocation; parent
extension/MCP tools and their hooks are not inherited.

Shell calls join the core write barrier: cancellation/timeout stops the process
group (Windows uses `taskkill /T`), and checkpointing waits for the call to settle.
On POSIX, remaining children in the command's process group are also stopped on
normal command exit. Windows cleanup after the parent process exits is best effort.
Run commands in the foreground; do not daemonize or leave servers/watchers running.
Processes that detach from the group and external services are not contained by
this mechanism. A custom runner must honor the core write barrier as well.
Calling the Pi runner without an assigned workspace stays read-only.

Tool and time budgets are unlimited by default in Pi. To set finite hard limits,
pass any of these fields in the `braid` tool's `options`:
Expand Down
Loading
Loading