Skip to content

Commit 061cb93

Browse files
author
Forge
committed
simplify goal-loop executor binding; add sandbox container placeholder
1 parent f95e7c2 commit 061cb93

48 files changed

Lines changed: 615 additions & 304 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Execution flow dialog with mode and model selection:
9090
## Features
9191

9292
- **Plans** — architect produces marked plans that are auto-captured to SQL storage
93-
- **Execution** — `New session`, `Execute here`, and `Loop` launch paths for approved plans; loops can also target a configured remote opencode server (see [Configuration](docs/configuration.md#remotes))
93+
- **Execution** — approved-plan launch paths plus direct `/execute-goal` loops in dedicated worktree sessions; plan loops can also target a configured remote opencode server (see [Configuration](docs/configuration.md#remotes))
9494
- **Loops** — iterative coding/auditing with isolated git worktree and optional Docker sandbox
9595
- **Review Findings** — persistent, loop-scoped review findings across loop sessions
9696
- **TUI** — sidebar and execution dialog
@@ -122,14 +122,15 @@ Forge provides these tool groups:
122122

123123
- **Plan tools** — `plan-read`, `section-read`
124124
- **Review tools** — `review-write`, `review-read`, `review-delete`
125-
- **Loop tools** — `execute-plan`, `loop-cancel`, `loop-status`
125+
- **Loop tools** — `execute-plan`, `execute-goal`, `loop-cancel`, `loop-status`
126126
- **Sandbox shell** — `sh` when a sandbox manager is available
127127

128128
Loops always run in an isolated git worktree; Docker sandbox is used automatically when available.
129129

130130
| Tool | Description |
131131
|------|-------------|
132132
| `execute-plan` | Execute a plan using an iterative development loop in an isolated git worktree, or `mode: new-session` to launch it in a fresh standalone session. Args: `title` required; `plan`, `loopName`, `hostSessionId`, `mode` optional. |
133+
| `execute-goal` | Execute a free-text goal in rotating dedicated code and auditor sessions inside an isolated git worktree. Args: `goal` required; `title`, `loopName`, `maxIterations`, `hostSessionId` optional. |
133134
| `loop-cancel` | Cancel an active loop by worktree name |
134135
| `loop-status` | List active/recent loops or get detailed status by worktree name, including cumulative token usage when available. Supports `restart=true` to restart any non-completed loop (`running`, `cancelled`, `errored`, `stalled`). Completed loops are history-only and cannot be restarted. |
135136

@@ -142,6 +143,7 @@ Loops always run in an isolated git worktree; Docker sandbox is used automatical
142143
| `/review` | Run a code review on current changes | auditor (subtask) |
143144
| `/review-plan` | Review a completed implementation against its original plan | auditor (subtask) |
144145
| `/execute-plan` | Start an iterative development loop in a worktree (or a fresh session with `mode: new-session`) | code |
146+
| `/execute-goal` | Execute a free-text goal in dedicated worktree sessions until an audit leaves no findings | code |
145147
| `/loop-status` | Check status of all active loops | code |
146148
| `/loop-cancel` | Cancel the active loop | code |
147149

@@ -490,6 +492,10 @@ Symptoms include:
490492

491493
The flag must be set before OpenCode starts — setting it inside an already-running session is too late. If OpenCode is launched by a desktop app, service manager, shell alias, terminal profile, or wrapper script, set the variable there and fully restart OpenCode.
492494

495+
### Workspace prerequisites
496+
497+
Worktree loops require a git repository with at least one commit. OpenCode scopes its instance to project `global` when started in a directory without a root commit, and worktree loop sessions created against a `global` project are invisible to the TUI. If you see a "No git commit in this project" error, create an initial commit and restart OpenCode.
498+
493499
## Docker Sandbox
494500

495501
Run loop iterations inside an isolated Docker container. Sandbox is optional: when Docker is available and configured, Forge provisions a loop container automatically; otherwise loops run in worktree-only mode.

‎container/Dockerfile‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,25 @@ RUN useradd -m -u 1000 forge \
6969
RUN corepack pnpm add -g fallow@2.101.0 --global-bin-dir /usr/local/bin \
7070
&& chmod -R 0777 /home/forge
7171

72+
# --- Optional: in-container browser testing (Chromium + Chrome DevTools MCP) ---
73+
# Lets loops drive a browser inside the sandbox against dev servers that also run
74+
# inside the sandbox (shared network namespace, plain localhost) with zero host
75+
# exposure. Opt-in per project via `loop.worktreeOpencodeConfig`; see
76+
# docs/sandbox.md "Browser testing". Delete this whole block to build a slimmer
77+
# image without browser support.
78+
#
79+
# Debian's chromium package is used because Google Chrome ships no linux/arm64
80+
# build (Apple Silicon hosts run linux/arm64 containers). The trailing chmod
81+
# re-asserts store permissions after a root pnpm install — see the fallow note
82+
# above; it applies to every root pnpm step.
83+
RUN apt-get update && apt-get install -y --no-install-recommends \
84+
chromium \
85+
fonts-liberation \
86+
&& rm -rf /var/lib/apt/lists/*
87+
RUN corepack pnpm add -g chrome-devtools-mcp@1.5.0 --global-bin-dir /usr/local/bin \
88+
&& chmod -R 0777 /home/forge
89+
# --- End optional browser testing block ---
90+
7291
# Docker Engine (daemon + CLI + buildx + compose) from Docker's official apt
7392
# repository. This enables Docker-in-Docker: when the container is launched with
7493
# FORGE_DIND=1 (privileged), the entrypoint starts a nested, isolated dockerd so

‎docs/agents-and-commands.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Source: [`AUDITOR_TOOL_EXCLUDES`](../src/agents/auditor.ts).
4141
| `/review` | Run a code review. | `auditor` | yes |
4242
| `/review-plan` | Review a completed implementation against its original plan. | `auditor` | yes |
4343
| `/execute-plan` | Start an iterative development loop in a worktree (or launch the plan in a fresh standalone session with `mode: new-session`). | `code` | no |
44-
| `/execute-goal` | Execute a goal directly in the invoking session inside an isolated worktree, with fresh auditor sessions until no findings remain. | `code` | no |
44+
| `/execute-goal` | Execute a goal in rotating dedicated code and auditor sessions inside an isolated worktree. | `code` | no |
4545
| `/loop-status` | Check status of all active loops. | `code` | no |
4646
| `/loop-cancel` | Cancel the active loop. | `code` | no |
4747

‎docs/api/README.md‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Execution flow dialog with mode and model selection:
9393
## Features
9494

9595
- **Plans** — architect produces marked plans that are auto-captured to SQL storage
96-
- **Execution** — approved-plan launch paths plus direct `/execute-goal` work in the invoking session; plan loops can also target a configured remote opencode server (see [Configuration](_media/configuration.md#remotes))
96+
- **Execution** — approved-plan launch paths plus direct `/execute-goal` loops in dedicated worktree sessions; plan loops can also target a configured remote opencode server (see [Configuration](_media/configuration.md#remotes))
9797
- **Loops** — iterative coding/auditing with isolated git worktree and optional Docker sandbox
9898
- **Review Findings** — persistent, loop-scoped review findings across loop sessions
9999
- **TUI** — sidebar and execution dialog
@@ -132,7 +132,7 @@ Loops always run in an isolated git worktree; Docker sandbox is used automatical
132132
| Tool | Description |
133133
|------|-------------|
134134
| `execute-plan` | Execute a plan using an iterative development loop in an isolated git worktree, or `mode: new-session` to launch it in a fresh standalone session. Args: `title` required; `plan`, `loopName`, `hostSessionId`, `mode` optional. |
135-
| `execute-goal` | Execute a non-empty goal in the invoking session inside an isolated worktree. Fresh auditors run on idle until no findings remain. |
135+
| `execute-goal` | Execute a free-text goal in rotating dedicated code and auditor sessions inside an isolated git worktree. Args: `goal` required; `title`, `loopName`, `maxIterations`, `hostSessionId` optional. |
136136
| `loop-cancel` | Cancel an active loop by worktree name |
137137
| `loop-status` | List active/recent loops or get detailed status by worktree name, including cumulative token usage when available. Supports `restart=true` to restart any non-completed loop (`running`, `cancelled`, `errored`, `stalled`). Completed loops are history-only and cannot be restarted. |
138138

@@ -145,7 +145,7 @@ Loops always run in an isolated git worktree; Docker sandbox is used automatical
145145
| `/review` | Run a code review on current changes | auditor (subtask) |
146146
| `/review-plan` | Review a completed implementation against its original plan | auditor (subtask) |
147147
| `/execute-plan` | Start an iterative development loop in a worktree (or a fresh session with `mode: new-session`) | code |
148-
| `/execute-goal` | Execute a goal directly in the invoking session inside a managed worktree loop | code |
148+
| `/execute-goal` | Execute a free-text goal in dedicated worktree sessions until an audit leaves no findings | code |
149149
| `/loop-status` | Check status of all active loops | code |
150150
| `/loop-cancel` | Cancel the active loop | code |
151151

@@ -494,6 +494,10 @@ Symptoms include:
494494

495495
The flag must be set before OpenCode starts — setting it inside an already-running session is too late. If OpenCode is launched by a desktop app, service manager, shell alias, terminal profile, or wrapper script, set the variable there and fully restart OpenCode.
496496

497+
### Workspace prerequisites
498+
499+
Worktree loops require a git repository with at least one commit. OpenCode scopes its instance to project `global` when started in a directory without a root commit, and worktree loop sessions created against a `global` project are invisible to the TUI. If you see a "No git commit in this project" error, create an initial commit and restart OpenCode.
500+
497501
## Docker Sandbox
498502

499503
Run loop iterations inside an isolated Docker container. Sandbox is optional: when Docker is available and configured, Forge provisions a loop container automatically; otherwise loops run in worktree-only mode.
@@ -503,6 +507,7 @@ See [Sandbox](_media/sandbox.md) for setup, Docker-in-Docker behavior, host netw
503507
### Prerequisites
504508

505509
- Docker running on your machine
510+
- OpenCode >= 1.15.5 — sandbox shell routing relies on the session-aware `shell.env` plugin hook. Enforced via `engines.opencode`, so older versions refuse to load the plugin rather than silently running sandbox commands on the host. (Loops additionally require OpenCode >= 1.17.8 for workspace integration, see [Requirements](#requirements).)
506511

507512
### Setup
508513

‎docs/api/_media/agents-and-commands.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Source: [`AUDITOR_TOOL_EXCLUDES`](../src/agents/auditor.ts).
4141
| `/review` | Run a code review. | `auditor` | yes |
4242
| `/review-plan` | Review a completed implementation against its original plan. | `auditor` | yes |
4343
| `/execute-plan` | Start an iterative development loop in a worktree (or launch the plan in a fresh standalone session with `mode: new-session`). | `code` | no |
44-
| `/execute-goal` | Execute a goal directly in the invoking session inside an isolated worktree, with fresh auditor sessions until no findings remain. | `code` | no |
44+
| `/execute-goal` | Execute a goal in rotating dedicated code and auditor sessions inside an isolated worktree. | `code` | no |
4545
| `/loop-status` | Check status of all active loops. | `code` | no |
4646
| `/loop-cancel` | Cancel the active loop. | `code` | no |
4747

‎docs/api/_media/configuration.md‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,10 @@ The written file is added to the worktree's git exclude so it never appears in `
100100

101101
Notes:
102102
- The written file is ephemeral. Forge deletes its own `opencode.jsonc` before any teardown commit (and the whole worktree is removed on completion), so it can never land in loop history — even if the git-exclude write failed. A repository-tracked `opencode.jsonc` is never deleted (forge did not write it). Because the file is removed at teardown, a restarted loop is rewritten from the current `loop.worktreeOpencodeConfig`, so edits take effect on the next run.
103-
- MCP servers declared here run as **host** processes from the worktree directory. When [Sandbox](sandbox.md) is enabled, only `bash`/`glob`/`grep` execute inside the container; the MCP commands themselves are not container-isolated.
103+
- MCP servers declared here run as **host** processes from the worktree directory. When [Sandbox](sandbox.md) is enabled, only `bash`/`glob`/`grep` execute inside the container; the MCP commands themselves are not container-isolated. To run an MCP server *inside* the loop's sandbox container, use the placeholder below with a `docker exec -i` command.
104+
- The string `{{FORGE_SANDBOX_CONTAINER}}` in any config value is replaced with the loop's sandbox container name (`forge-<loop>`) when the file is written. For loops without a sandbox, `mcp` entries referencing the placeholder are dropped instead, so the same config works with and without the sandbox.
104105

105-
Example — expose Chrome DevTools MCP inside every loop:
106+
Example — Chrome DevTools MCP running inside the loop's sandbox container (Chromium and `chrome-devtools-mcp` ship preinstalled in the sandbox image; see [Sandbox › Browser Testing](sandbox.md#browser-testing)):
106107

107108
```jsonc
108109
{
@@ -111,7 +112,12 @@ Example — expose Chrome DevTools MCP inside every loop:
111112
"mcp": {
112113
"chrome-devtools": {
113114
"type": "local",
114-
"command": ["npx", "chrome-devtools-mcp@latest", "--isolated"],
115+
"command": [
116+
"docker", "exec", "-i", "{{FORGE_SANDBOX_CONTAINER}}",
117+
"chrome-devtools-mcp", "--headless", "--isolated",
118+
"--executablePath=/usr/bin/chromium",
119+
"--chromeArg=--no-sandbox", "--chromeArg=--disable-dev-shm-usage"
120+
],
115121
"enabled": true
116122
}
117123
}
@@ -120,6 +126,8 @@ Example — expose Chrome DevTools MCP inside every loop:
120126
}
121127
```
122128

129+
Without the sandbox, a host-side server works too (Chrome runs on the host and cannot reach in-container dev servers): `"command": ["npx", "chrome-devtools-mcp@latest", "--isolated"]`.
130+
123131
## Group Launch
124132

125133
`groupLaunch` configures parallel feature orchestration (see the [`launch-group`](tools.md#group-tools) tool).

0 commit comments

Comments
 (0)