Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
547 changes: 547 additions & 0 deletions docs/designs/compass/agent/compass-comms-file-sharing/design.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions docs/designs/compass/decisions/agent/DL-480.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: DL-480
decision: "Comms attachment bytes go through the existing `ObjectStore` seam under the content-addressed key `blobs/<sha256>`, indexed by a new tenant-RLS `comms_attachments` table (server-minted id, uploader, nullable bound `message_id`, sha256, size, content type, filename, partial index on unbound rows), because `agent_session_blobs` is keyed by session and a UI or CLI upload has none; a new directory-backed `DirObjectStore` (`--object-dir`, defaulted by compass-stack to `<StateDir>/objects` when S3 is absent and by devenv to its state directory) gives local stacks the seam; with no object store at all, upload is FailedPrecondition (the DL-426 rule)"
status: "Active (proposed, pending Matt, 2026-10-11)"
record: ../../agent/compass-comms-file-sharing/design.md#d1-storage-reuses-the-objectstore-seam
---
6 changes: 6 additions & 0 deletions docs/designs/compass/decisions/agent/DL-481.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: DL-481
decision: "Two-phase attach: a file is uploaded first (`CommsService.UploadAttachment`, server-validated filename and media type, optional client sha256) and posted second as a new `MessageBlock.attachment = 4` (`AttachmentBlock`) arm; inside `AppendMessage` the store fills the block from the uploader's row, inserts, and on a fresh insert only binds the row with `message_id IS NULL` as the single gate, so an idempotent replay succeeds and a held or stale post can re-bind the same id; an update cannot add, drop or change an attachment; the agent call arms are `upload_attachment = 16` and `get_attachment = 17`"
status: "Active (proposed, pending Matt, 2026-10-11)"
record: ../../agent/compass-comms-file-sharing/design.md#d2-the-wire-is-an-upload-rpc-and-a-block-arm
---
6 changes: 6 additions & 0 deletions docs/designs/compass/decisions/agent/DL-482.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: DL-482
decision: "An unbound attachment is readable only by its uploader; a bound one is readable when `Store.IsTopicChannelMember` (the `TopicChannelParticipant` probe that gates `MessagePosted` delivery) is true for its message's topic, so it is readable exactly where its block was delivered, with no new `participating` CTE copy and a pgtest pinning parity with `ListMessages` visibility; unknown, unbound-foreign and unreadable ids all return NotFound (the D9 merge), and the tenant-RLS row lookup runs before any object read"
status: "Active (proposed, pending Matt, 2026-10-11)"
record: ../../agent/compass-comms-file-sharing/design.md#d3-read-access-is-message-read-access
---
6 changes: 6 additions & 0 deletions docs/designs/compass/decisions/agent/DL-483.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: DL-483
decision: "One file per unary upload, capped at `agentmsg.MaxAttachmentBytes = MaxBytes - 1<<20` (15 MiB), checked in the store and mirrored by the agent, with the socket and dev CommsService mount gaining `WithReadMaxBytes(siblingServiceMaxReadBytes)`; on the network door, `UploadAttachment`, `RelayCommsCall` and `RelaySessionBlob` get a body-read deadline of 30 s plus 1 s per 64 KiB of Content-Length (the read cap when unknown), never above 10 minutes, instead of the flat 30 s; an uploader holding 8 unbound uploads from the last 24 hours gets ResourceExhausted (a capability bound, not a quota); an attachment lives as long as its message, nothing is deleted, and GC and erasure of attachments and session blobs are deferred to one follow-up"
status: "Active (proposed, pending Matt, 2026-10-11)"
record: ../../agent/compass-comms-file-sharing/design.md#d4-size-cap-and-retention
---
6 changes: 6 additions & 0 deletions docs/designs/compass/decisions/agent/DL-484.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: DL-484
decision: "Agents get two native tools: `comms_attach_file` (reads a workdir-relative path, reuses an unbound id for the same path and digest, uploads, then posts through the same held and stale handling as `comms_post_message`) and `comms_read_file` (an image part only for magic-byte-sniffed PNG/JPEG/GIF/WebP up to 5 MiB, inline UTF-8 text up to 32 KiB, else a saved path outside the git workdir); `comms_list_messages` renders an attachment as one fenced marker line, and `formatDeliversForPrompt` renders it unfenced as a known limit"
status: "Active (proposed, pending Matt, 2026-10-11)"
record: ../../agent/compass-comms-file-sharing/design.md#d5-agent-tools-attach-and-read
---
6 changes: 6 additions & 0 deletions docs/designs/compass/decisions/agent/DL-485.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: DL-485
decision: "The operator downloads through `CommsService.GetAttachment`: the UI renders an attachment chip with no inline preview and, in a browser, always saves an `application/octet-stream` Blob and never opens a blob URL; the native shell gains `fileService.SaveAttachment`, registered in every non-setup mode (the embedded connection keeps its Unix target), which fetches in Go and opens a save dialog so the bytes never cross the JS bridge; the CLI gains `compass message attach` and `compass message get`, which refuses an unsafe default filename and never overwrites; the UI does not upload in this record"
status: "Active (proposed, pending Matt, 2026-10-11)"
record: ../../agent/compass-comms-file-sharing/design.md#d6-the-operator-downloads-from-the-ui-and-the-cli
---
Loading