The bridge counted tool and model calls against fixed 100 and 50 caps, so CONFLUENCE_WEB_MAX_CONFLUENCE_CALLS / CONFLUENCE_WEB_MAX_MODEL_CALLS above the defaults were cut short inside the container, and the model cap failed the run outright. The backend now passes both values into the container at start, the supervisor forwards them to the bridge, and LIMITS reads them with the same 1-1000 validation as the backend, falling back to 100/50 when absent or invalid. Add a test that loads LIMITS in fresh processes with good and bad values for both budgets and the deadline.
Confluence pi runtime
This package wraps the unmodified pi SDK. It registers native Confluence tools and the SDK's shell/read/write/edit tools, and supplies a custom model stream function over revision-1 NDJSON. There are no provider credentials, remote Confluence clients, CLI stdout scraping, or modifications to pi dependencies.
From the repository root:
npm --prefix agent ci --ignore-scripts
npm --prefix agent run build
npm --prefix agent test
npm --prefix agent run proof
The host proof uses an explicit development supervisor, fresh temporary workspace
and home, and a deterministic model/backend substitute. It runs real local
commands. The supervisor signals only its own descendants and adopts orphaned
children with Linux PR_SET_CHILD_SUBREAPER. Ordinary host npm start refuses
to launch: production supervision requires PID 1 in a private container PID
namespace. Do not add Docker --init or share the host PID namespace.
Build and exercise the image against a rootless Docker daemon:
docker build -t confluence-pi-agent:rev1 agent
node agent/dist/dev/fake-backend.js --image confluence-pi-agent:rev1
node agent/dist/dev/image-checks.js
node agent/dist/dev/boundary-checks.js
The image-check suite includes a real, unchanged 180-second missing-start test. It prints progress every 30 seconds. Boundary checks generate large payloads on the host and send them to a runtime constrained to 1 GiB and one CPU. These test commands need access to Docker and local supervisor sockets; restrictive execution sandboxes can prevent them from running.
dev/fake-backend.ts is an independent host peer that uses the public wire
contract. Add --mode=... for no-artifacts, empty-file, skip, delayed,
background, spaces, confluence-error, upstream-failure, bad-reply, duplicate, eof-model,
eof-collection, eof-begin, eof-end, context-limit, output-limit,
zero-text, failure-during-collection, stalled-model, or stalled-collection. isolation and
stop-bridge require --image. --transcript records dummy wire traffic.
The default entrypoint is /usr/bin/python3 /opt/agent/supervisor; user/group
10001:10001, cwd /work, HOME /home/agent. Mount fresh owned tmpfs filesystems
at /work (256 MiB), /tmp (64 MiB), and /home/agent (32 MiB). Supply no bind
mounts or secret environment variables. dev/fake-backend.ts contains the complete
launch flags: read-only root, no network, no privileges/capabilities, default
seccomp, private namespaces, 1 GiB memory/no extra swap, 128 PIDs, one CPU, no TTY,
and no Docker logging. The backend owns launch, attachment, kill/removal, host
artifact storage, provider configuration, and upstream HTTP.
Shell tools use /bin/bash --noprofile --norc, a 30-second maximum per command,
and 1 MiB captured output per invocation. Excess output terminates the command
and becomes a model-visible tool failure; pi retains its normal 50 KiB/2000-line
presentation truncation and temporary output file. Native read/edit operations
require regular files up to 16 MiB; use shell ranges for larger files. The shared
model boundary supports text and tools, so read never creates image attachments.
Tool results and input arguments also obey shared serialized protocol limits.
Artifacts are collected only after the supervisor has killed and reaped local
descendants. Directory traversal uses verified directory descriptors through
Linux /proc/self/fd, with no-follow opens at each component. File descriptors
remain open through transfer; link/type/inode/size/time checks precede and follow
bounded reads. Names and Unicode-normalized duplicates are validated, file/count/
aggregate limits produce bounded warnings, and a traversal budget prevents
unbounded directory enumeration. The backend still receives untrusted bytes and
must independently validate paths, sizes, storage and attachment delivery.
Completion is committed only after the complete frame finishes writing. The bridge timer is then cleared and no further terminal error is emitted; the supervisor's independent lifetime remains armed. Failure exit allows up to one second for an active NDJSON frame and the terminal error to drain. Not-yet-started frames are cancelled, preserving complete lines rather than interleaving error bytes. If the stream breaks or remains blocked, nonzero exit/EOF conveys failure. Repeated warnings include occurrence counts; overflow is summarized within 100 entries.