You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 46567ea
Browse filesBrowse the repository at this point in the historyBrowse files
Keep no Docker daemon log of agent containers (#165) (#190)
* Keep no Docker daemon log of agent containers (#165)
The supervisor reads an agent's output through `docker start --attach` and
bounds it there. Agent containers now use `--log-driver=none`, so the daemon
keeps no copy that a fast writer could grow before the supervisor stops the
container, and validation refuses a container with any other log setting
before it starts.
Closes#165
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Accept the daemon's cache log options; test the no-log rule directly (#165)
Review round 1: a daemon copies its own cache-* log options into every
container, so an exact empty-options check would refuse every agent on such a
host. The rule is now keepsNoDaemonLog, with unit cases for the options only
the API can set.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Check the created container with the no-log rule; scope and wording (#165)
Review round 2: the inspect test accepts the daemon's cache-* options as the
validator does; the rule's unit test runs in the parallel project
(agent-daemon-log); docs record that only agent containers are covered.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Name the refusal test for what it shows; exact log wording (#165)
Review round 3 nits.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* List every container that keeps the default log (#165)
Review round 4.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/designs/codeboost-plan-indexed-review.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -239,6 +239,7 @@ Nothing else from your computer is inside. So `~/.ssh`, `~/.config/gh`, `~/.npmr
239
239
| Runs as a non-root user; all Linux capabilities dropped (`--cap-drop=ALL`); `--security-opt=no-new-privileges` | The agent cannot become root or use privileged system calls. |
240
240
| No `--privileged`, no `--device`, no host network, no Docker socket, and no host mounts other than the bounded worktree, separate read-only Git metadata, runner-prepared read-only schema input, and read-only sign-in file | Nothing on the host is reachable through the container. |
241
241
| Limits on processes, memory, and CPU (`--pids-limit`, `--memory`, `--cpus`) | Bound the agent's consumption of these resources; they do not guarantee zero host performance impact. |
242
+
| No Docker daemon log (`--log-driver=none`) | The supervisor reads the agent's output as it is written (`docker start --attach`) and bounds it there. The daemon keeps no copy that a fast writer could grow before the supervisor stops the container. |
242
243
| `/work` lives on a dedicated size-limited task filesystem with hard byte and inode limits, allocated before the invocation; never an unbounded host-directory bind | Large output and many tiny files fail inside the task filesystem instead of growing without limit on the host. |
243
244
244
245
**Output and time enforcement.** A trusted supervisor outside the invocation container incrementally captures every agent/check command with hard limits of 16 MiB stdout, 4 MiB stderr, and 20 MiB combined, including protocol envelopes. Host buffers, persisted logs, and UI forwarding obey the same per-invocation limits; task-log retention has a configured total byte cap and never accumulates unbounded output across retries. Before launch, require a finite wall deadline (default 10 minutes, capped by the remaining task budget; configured overrides must also be finite). On overflow/deadline or capture failure, stop consuming into retained buffers, terminate the entire container including descendants, escalate to forced container kill if graceful termination fails, and record a bounded failure diagnostic. Never wait indefinitely for EOF from an orphan child, silently treat truncated output as success, or run tests/commit after this failure. Container tests must exercise infinite stdout, infinite stderr, mixed streams, and a child ignoring SIGTERM, while measuring bounded host capture and completed termination. For structured vendor output, the transport cap includes envelope headroom; separately enforce the 1 MiB plan-document limit after extraction.
Copy file name to clipboardExpand all lines: docs/implementation/agent-isolation.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,6 +37,7 @@ Each row is a T9 requirement for the Docker suite. The suite fails if any row fa
37
37
| Planning and questions cannot run a process |`agent-policy`: tool sets exclude the command tool, and command dispatch refuses these phases |
38
38
| Codex runs in no phase, because it cannot read code without its shell (see [Codex is refused in every phase](#codex-is-refused-in-every-phase)) |`agent-policy`: the Codex command refuses all five phases; `agent-adapter`: the Codex start call refuses them and allocates nothing; `runner-execution`: an execute task with Codex is refused before task storage exists |
39
39
| A planning answer is checked against the mounted schema |`agent-policy`: only the Claude planning command passes `--json-schema`; `agent-container`: the profile refuses a command whose schema differs from the mounted file; `agent-adapter`: the answer is read from `structured_output`|
40
+
| The Docker daemon keeps no log of an agent container (#165): the supervisor's bounded capture through `docker start --attach` is the only copy of its output. This covers the agent container only. The runner's other containers keep the daemon's default log: the task-storage script containers (`docker run --rm`, `agents/container/storage.ts`), whose log is removed with the container while the client bounds what it reads, and the storage keeper and egress proxy, which write no output |`agent-container`: the created container's `LogConfig` is driver `none` with no option but `cache-*` ones; the validator refuses a container with a `json-file` log or a bounded `local` log; every probe that returns output shows the attach still delivers it. `agent-daemon-log`: the rule (`keepsNoDaemonLog`) also refuses driver `none` with a log option, which only the API can set, and accepts the `cache-*` options a daemon copies into every container |
40
41
| Task and scratch byte and inode limits hold |`agent-container`: task capacity; scratch capacity for Codex and Claude (`/tmp`, `HOME`, `CODEX_HOME`, output directory) |
41
42
| Hard links and alias writes from `.git/config` and objects fail, and metadata stays unchanged |`agent-container`: metadata alias probe in planning, review and execute, with a digest of `.git` before and after |
42
43
| Mountpoint replacement fails |`agent-container`: metadata and metadata alias probes (`mv` and `rm -rf` of `.git`) |
Copy file name to clipboardExpand all lines: docs/implementation/plan-library-alignment.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,12 +20,12 @@ Issue #6 tracked the v1 plan library contract and the runner obligations that ca
20
20
| Hostile repository, issue, lesson, feedback, previous-plan and continuation-context text in every authoring prompt |**This change** (revised drafts, suggestions and the continuation context) |`test/planning-author.test.ts`|
21
21
| Container mounts: Git metadata on its own filesystem, read-only, with no writable hard links or aliases into it | Done before this change |`agents/container/profile.ts`, probe `metadata-alias` in `agents/policy.ts`; `test/agent-container.test.ts` ("keeps Git metadata read-only, on another filesystem, and mounted against replacement", "keeps Git metadata unchanged under link, alias, truncation and replacement attempts during %s"), negative controls in `test/agent-gate.test.ts` (real Docker) |
22
22
| Process termination: output overflow, deadline and cancellation stop the whole container, including a process that ignores SIGTERM | Done before this change |`agents/adapters/supervisor.ts`; `test/agent-supervisor.test.ts` ("terminates %s at bounded output limits", "enforces a finite wall deadline and force-settles the container", "preserves the first cancellation reason until an ignored SIGTERM fully settles") (real Docker) |
23
-
| Output shown in the UI bounded: captured output comes only from the supervisor, which bounds stdout and stderr; when a planning run exits with an error, the provider's message quotes its output with whitespace collapsed, cut to at most 300 UTF-16 code units (`runner/planning-provider.ts`) | Done before this change; 300-unit quote tested in this change |`test/agent-supervisor.test.ts` output-limit cases (real Docker); `test/planning-provider.test.ts` ("quotes at most 300 code units of a failed run's output, with whitespace collapsed"). The Docker daemon's own log is #165|
23
+
| Output shown in the UI bounded: captured output comes only from the supervisor, which bounds stdout and stderr; when a planning run exits with an error, the provider's message quotes its output with whitespace collapsed, cut to at most 300 UTF-16 code units (`runner/planning-provider.ts`) | Done before this change; 300-unit quote tested in this change |`test/agent-supervisor.test.ts` output-limit cases (real Docker); `test/planning-provider.test.ts` ("quotes at most 300 code units of a failed run's output, with whitespace collapsed"). The Docker daemon's own log is #165(*later:* the daemon keeps none) |
24
24
| Output limits at the exact byte |**This change** (tests; the supervisor already enforced the limits) | Supervisor enforcement: `test/agent-supervisor.test.ts` (real Docker). Decoder behaviour only, not a limit: the Claude decoder handles an envelope of exactly the stdout ceiling, and the 1 MiB parser limit applies to the decoded answer at the exact byte: `test/agent-adapter.test.ts`. At #6 the decoder re-serialized the answer, so the limit applied to the re-encoded text. *Later:*#166 returns the exact text of `structured_output` in the CLI's envelope, so the limit applies to those bytes |
25
25
| Prompt byte budget before spawn | Done before this change |`MAX_PROMPT_BYTES` in `core/planning-author.ts`; `test/planning-author.test.ts` ("accepts exactly the prompt byte limit and rejects the next byte without truncation") |
26
26
| Model budget before spawn | Moved to #163| — |
27
27
| Planning profile probed at startup | Moved to #164| — |
28
-
| Docker daemon log limits | Moved to #165| —|
28
+
| Docker daemon log limits | Moved to #165. *Later:* fixed in #165 with `--log-driver=none`, checked before launch |`agents/container/profile.ts`, `agents/container/run.ts`; `test/agent-container.test.ts` ("creates the agent container with no Docker daemon log", "refuses an agent container with %s at validation") (real Docker), `test/agent-daemon-log.test.ts`. Agent containers only; the runner's other containers (task-storage scripts, the keeper, the egress proxy) keep the daemon's default log|
29
29
| Claude structured output under the v1 parsing contract | Moved to #166 (found during this change). *Later:* fixed in #166|`agents/adapters/claude.ts`; `test/agent-adapter.test.ts` ("lets draft validation refuse %s in a structured answer") |
0 commit comments