Skip to content

feat(paseo): package the headless assistant and record turns on Buzz - #153

Draft
tee8z wants to merge 3 commits into
mainfrom
tee8z/paseo-daemon-image
Draft

tee8z wants to merge 3 commits into
mainfrom
tee8z/paseo-daemon-image

Conversation

@tee8z

@tee8z tee8z commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

Problem and behavior

Paseo clients need an always-on personal assistant that delegates coding and system access to Buzz remote agents.
This image keeps the upstream Paseo daemon unmodified and packages the Buzz CLI, native assistant runtimes, relay configuration, and turn recording.

Boundary Behavior
Assistant Claude Code 2.1.246 when its token exists; otherwise Codex 0.159.3. No token starts without an assistant.
Remote sessions One ACP provider per configured Buzz agent; missing agent configuration starts without remote providers.
Identity Narrow manager-owned Kubernetes Secret; gateway delegation and channel membership remain separate requirements.
Network WSS for both relays; clients connect through the separate Paseo relay at /ws. No sandbox tunnel.
Recording Native turns become Buzz messages with prompt, final answer, and tool names/statuses; remote providers are excluded.
Host tools Off by default. Opt-in terminal profile and snapshots directory prepare for the forthcoming sandbox-attach PR.
Publishing Independent amd64/arm64 CI lanes test and publish voltage-paseo-daemon-staging on main.
flowchart LR
  Client[Paseo desktop, mobile, web] <-->|WSS| Relay[Paseo relay]
  Relay <--> Daemon[Personal daemon]
  Daemon <-->|WSS, signed events| Buzz[Buzz relay]
  Buzz <--> Sandbox[Isolated agent sandbox]
Loading

The assistant receives no GitHub, cloud, Kubernetes, or sandbox credentials.
Claude's project and web tools are disabled; non-Buzz shell commands require approval.
The wrapper blocks local terminals and Git by default.
Paired clients retain owner control over daemon settings; these defaults are not a client authorization boundary.

The recording plugin uses upstream agent.turn.after and canonical timeline reads through the plugin API.
It writes retry intents before reads/publication, bounds spool size and subprocess lifetime, and deletes records only after relay acknowledgement.
Known environment credentials and conservative token patterns omit the entire affected field.
Raw tool outputs and reasoning never enter records.

The review follow-up bounds pending captures before serialization, coalesces
in-flight flushes, enforces five-second upstream timeline requests, and caps
multilingual text by UTF-8 bytes. Observer bursts cannot bypass retry backoff.

Validation

  • Full Docker build succeeded with the musl Buzz CLI and pinned native runtimes.
  • Full contract suite passed with no network, UID 1000, read-only root, dropped capabilities, and a one-GiB memory limit.
  • The suite checks malformed-input/TLS refusal, pairing identity, optional missing values, provider preference, actual native launch, filtered MCP tools, blocked terminals, running plugin, and filesystem writes.
  • Recorder production tests pass for native-only selection, redaction, turn fencing, failure/restart retry, explicit acknowledgement, and capacity refusal.
  • Removing the native-provider filter, redaction guard, or acknowledgement guard makes its regression assertions fail.
  • The pinned upstream plugin compiler accepts the actual plugin.
  • BuildKit checks report no warnings. CI matrix selection passes all, agent-only, empty, and Paseo-only scenarios.
  • Final follow-up runtime used an overlay on the already-built image, copying only the changed recorder and assistant instructions. The hardened full contract suite passed again at 247.7 MiB / 1 GiB; no Rust or upstream runtime dependency changed.
  • Guard mutations for pending admission, flush coalescing, and UTF-8 budgets each failed the expected regression assertion.
  • Original full-build idle memory: 341.1 MiB / 1 GiB. Local amd64 image size: approximately 1.39 GB.

No paid model request, real client pairing, staging deployment, arm64 runtime, or repository-wide just ci ran locally.
CI provides the architecture-specific image gates; human pairing confirmation remains outstanding.

Dependencies and rollout

  1. Apply the ECR repository and GitHub push grant from voltage-terraform #1029.
  2. Merge ACP bridge #149 and gateway CLI support before merging this image.
  3. Merge this PR; take the published manifest digest from the images workflow summary.
  4. Deploy the manager from #150, then set paseo_daemon_image in the Terraform developer-daemon configuration.
  5. Enroll through #158, grant the gateway key, admit it to the relay and needed channels, and pair a client.

The separate Paseo relay and ingress route must serve buzz.voltage.cloud/ws before pairing.
Pairing URLs target https://app.paseo.sh independently of the disabled daemon-local web UI.
The image pins Paseo 0.15.3 by digest; no fork is included.

Limits

  • Sandbox attachment is forthcoming. The opt-in terminal profile cannot attach until that CLI is merged and rebuilt.
  • The file explorer is not jailed to snapshots; upstream profiles select commands rather than restricting all client commands.
  • Recording is opt-in through BUZZ_PASEO_RECORD_CHANNEL and requires gateway membership in that channel.
  • The spool survives container restarts while the home emptyDir survives; pod replacement loses unpublished local records.
  • Pending timeline reads resume after an agent opens or finishes a turn; ambiguous acknowledgements can duplicate records with the same stable ID.
  • Token-pattern filtering cannot recognize every secret. Use a suitable membership-gated recording channel.

Independent agent review was completed; its recording blockers are fixed in 90015f1 and rechecked.
This PR stays draft pending human workflow confirmation. No review completion marker attestation is present.

CI follow-up 503eb20 makes the provider-stub directory traversable by the
daemon UID. A different-UID container probe reproduces the hosted-runner
permission boundary; the full hardened suite passes again (341.1 MiB / 1 GiB).
Independent review found no blocker in this test correction.

@tee8z tee8z self-assigned this Nov 10, 2026
@coderabbitai

coderabbitai Bot commented Nov 10, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@tee8z

tee8z commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

Independent review of a9c4b41f1 against the headless assistant and relay-recording goal.

Blocking: the recorder bounds files after enqueueing, but its in-memory work queue has no bound.

In recorder/server/recorder.mjs, capture() immediately chains another closure onto queue. The MAX_JOBS/MAX_BYTES checks run only when that closure reaches the front. flush() shares that queue and may spend up to ten 60-second timeline queries, followed by eight 15-second publisher attempts. During an outage or slow timeline, completed turns can keep adding closures and retained payload/context objects without a limit. The configured disk spool cap does not protect the daemon's memory. This contradicts the bounded recorder requirement and Review-Proven Rule 4.

Bound capture admission before chaining work, retain only the minimal turn identity in queued closures, and reject excess captures visibly. Add a journey that blocks timeline retrieval, fills the queue, and verifies the next capture rejects promptly without dropping existing retry files. Explicitly bound timeline fetch time as well.

Optional: delivery is at least once. A relay acceptance followed by a lost acknowledgement or crash before unlink() causes buzz messages send to mint another message on retry. The stable turn ID in the content permits downstream deduplication, but the channel can show duplicates. Document this or persist/reuse a signed event identity.

Optional: files() deletes complete-looking .json.tmp records after a crash. Consider recovering a valid temporary intent when its committed counterpart is absent. The current emptyDir/node-loss durability limit is documented.

Evidence: read the wrapper, Dockerfile, recorder, tests, and pinned Paseo client/lifecycle implementation. Verified the real pinned Codex binary recognizes CODEX_ACCESS_TOKEN by attempting account metadata validation without network; no credentials were used. The provided hardened runtime evidence covers native Claude, permission filtering, and the recorder plugin. No live model call or deployment was performed in this review.

Minimalism: 9/10. Elegance: 8/10 until admission bounds live at the queue entry. Correctness: 8/10 until the blocking queue defect is fixed. The optional findings do not gate readiness.

Signed-off-by: Tee8z <tee8z@protonmail.com>
@tee8z

tee8z commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

Independent review of 90015f19b: both recorder blockers are fixed.

  • Flush requests coalesce while a flush is queued or running. Agent-open bursts preserve retry backoff. The production-module probe previously produced 42 immediate publishes from 40 observations; the regression now verifies one attempt.
  • Prompt, answer, and tool-name truncation uses UTF-8 byte budgets and preserves character boundaries. The multilingual journey publishes one record below 24 KiB and removes its acknowledged retry intent.
  • Capture admission caps pending identities before appending closures to the queue. Existing spool records survive capacity refusal.
  • The pinned upstream client forwards the five-second timeline timeout to sendRequest.

Validation: node voltage/images/paseo-daemon/test-recorder.mjs passes against the published recorder source. Review scope covers the queue and byte-budget follow-up. Client pairing and model-backed execution remain deployment validation.

Minimalism 9/10, elegance 9/10, correctness 9/10. No remaining concrete blockers in this follow-up.

Signed-off-by: Tee8z <tee8z@protonmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant