confluence_web/agent/README.md
Artur Mukhamadiev 38a8ca67f7 agent: pi runtime track handoff (contract revision 1)
Pinned pi SDK 0.85.1 bridge, Python supervisor, artifact exporter,
scripted backend peer, image checks and boundary checks under agent/**.
Review findings F1-F3 are recorded in docs/implementation/PI_AGENT_REVIEW.md.
2026-09-14 21:57:54 +03:00

82 lines
4.5 KiB
Markdown

# 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:
```sh
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:
```sh
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.
See [HANDOFF.md](HANDOFF.md) for evidence, exact pins and outstanding integration
checks, and [REVIEW.md](REVIEW.md) for problems corrected in the initial code.
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.