Skip to content

feat(ui,workbench): composer and timeline on attachment references - #516

Open
Zerlight wants to merge 9 commits into
ruocheng/code-625from
ruocheng/code-637
Open

feat(ui,workbench): composer and timeline on attachment references#516
Zerlight wants to merge 9 commits into
ruocheng/code-625from
ruocheng/code-637

Conversation

@Zerlight

@Zerlight Zerlight commented Sep 7, 2026

Copy link
Copy Markdown
Member

Summary

Phase 3 of CODE-627 — Conversation turn graph & immutable attachment store. Linear: https://linear.app/arcbox/issue/CODE-637/featuiworkbench-composer-and-timeline-on-attachment-references

Stack: #515this PR (ruocheng/code-637, base ruocheng/code-625) ← #517. Merge bottom-up; this PR's diff is only its own commits.

Against a capable daemon the composer uploads through the chunked protocol and sends attachment_ref blocks; the timeline resolves refs through attachment.read and the blob cache; affordances follow the daemon-declared capability and the ATTACHMENT_SUPPORT stub is deleted. Plain sends go through turn.submit, legacy inline images are stored as refs on the durable row, and the dev mock admits and ingests refs.

Commits

  • feat(client-core): add plain-send turn.submit and drop the echo overlay
  • feat(ui,workbench): composer and timeline on attachment references
  • fix(workbench): overlay live echo refs and stop revoking visible previews
  • fix(engine,schema): refuse commits over a swept lease and cap attachment names
  • fix(client-core): fail attachment calls typed against an old peer and cap the put size
  • fix(ui,workbench): resolve previews under the React Compiler and admit refs in the mock
  • fix(engine): store legacy inline images as attachment refs on the durable row
  • fix(workbench): sniff before upload, match the echo text, and ingest inline images in the mock
  • fix(engine,workbench): sniff legacy inline images before storing and refuse refs on capability-less harnesses early

Verification

Every commit passed pnpm check:ci and pnpm test at its own tip; the stack tip (1d942a62; the same tree as the originally gated 73fc5ff2 plus the two review fixes below on 628/629) is at pnpm check:ci 0 errors, pnpm test 3408 passed / 1 skipped. Adversarial reviewers (one per axis, isolated read-only worktrees) reviewed the branch; each P1/P2 was reproduced with a failing test or a probe step before its fix — the round-by-round record is in the Linear issue's comments. A headless-Chrome probe of dev:mock attaches an image, sends, and sees the ref-backed image render; frame sizes confirm no attachment base64 on the wire.

Checklist

  • pnpm check:ci and pnpm test both pass (no Rust changes)
  • I ran the affected surface and observed the change working — the compiled renderer against dev:mock in headless Chrome
  • Wire: no wire change (frames landed in the previous PRs)
  • New code and assets are my own work
  • Docs and comments are updated where behavior changed (AGENTS.md and module docs in this branch)

@pullfrog

pullfrog Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Your Claude subscription has hit its usage limit. It resets at 11:30am (UTC). Re-trigger Pullfrog after the reset, or add an ANTHROPIC_API_KEY repo secret — Pullfrog routes around an exhausted subscription automatically when one is present.

Add repo secret → · Model settings → · Setup docs → · Ask in Discord →

Pullfrog  | Rerun failed job ➔View workflow run | via Pullfrog | Using Claude Opus𝕏

@linear-code

linear-code Bot commented Sep 7, 2026

Copy link
Copy Markdown

CODE-637

@greptile-apps

greptile-apps Bot commented Sep 7, 2026

Copy link
Copy Markdown

Greptile Summary

This PR moves composer uploads and timeline rendering onto durable attachment references, adds plain turn.submit support, persists legacy inline images into the attachment store, and hardens upload and lease handling.

  • Adds chunked attachment staging and ref-backed composer submissions.
  • Resolves stored image references into cached timeline previews.
  • Adds durable ingestion for legacy inline images and session resources.
  • Enforces attachment capability, count, size, MIME, identifier, and lease constraints.
  • Extends the development mock and test suite across client, engine, schema, and UI paths.

Confidence Score: 4/5

The PR should not merge until attachment metadata exceeding the new limits fails locally or is introduced under a new wire version, rather than leaving compatible clients waiting indefinitely.

The attachment architecture and lease protections are well covered, but the unversioned wire-schema tightening creates a concrete hanging request for valid legacy metadata; the stale preview race additionally retains attachment bytes until a later switch.

Files Needing Attention: packages/foundation/schema/src/wire/attachment.ts, packages/foundation/schema/src/wire/resource.ts, packages/client/core/src/client/attachment-channel.ts, packages/client/workbench/src/surface/workbench.tsx

Important Files Changed

Filename Overview
packages/foundation/schema/src/wire/attachment.ts Adds metadata limits to attachment wire frames, but the breaking validation change lacks protocol-versioning or matching client-side guards.
packages/client/core/src/client/attachment-channel.ts Adds upload size protection and defensive byte caching, but does not guard newly constrained names or MIME types.
packages/client/workbench/src/surface/workbench.tsx Integrates ref-backed submission and timeline preview resolution; stale asynchronous resolutions can retain object URLs after a session switch.
packages/client/workbench/src/surface/prompt-attachments.ts Implements attachment staging, ref conversion, temporary timeline overlays, and object-URL ownership.
packages/host/engine/src/attachment/ingest.ts Stores daemon-held bytes as immutable attachment records and converts legacy inline images into durable prompt references.
packages/host/engine/src/session/lifecycle-service.ts Integrates attachment admission, ingestion, persistence, and materialization into turn submission and rewrite flows.
packages/presentation/ui/src/chat/attachment-preview.tsx Adds generation-aware preview resolution with bounded retries, though discarded results cannot release resolver-created resources.
apps/daemon/src/attachment-store.ts Makes attachment commit fail transactionally when its upload lease has already been swept.

Sequence Diagram

sequenceDiagram
  participant UI as Composer
  participant Client as LinkCodeClient
  participant Host as Engine
  participant Store as Attachment Store
  participant Agent as Harness

  UI->>Client: putAttachment(bytes, metadata)
  Client->>Host: upload.begin + chunks + commit
  Host->>Store: Persist blob, record, and lease
  Store-->>Client: attachmentId
  UI->>Client: turn.submit(attachment_ref)
  Client->>Host: Prompt blocks with attachmentId
  Host->>Store: Admit and root attachment
  Host->>Store: Read immutable bytes
  Host->>Agent: Materialized inline image/file
  Host-->>UI: Text-only live echo
  UI->>Host: conversation.read
  Host-->>UI: Durable attachment resource_link
  UI->>Client: attachment.read
  Client-->>UI: Cached bytes / preview URL
Loading

Reviews (1): Last reviewed commit: "fix(engine,workbench): sniff legacy inli..." | Re-trigger Greptile

Comment thread packages/foundation/schema/src/wire/attachment.ts
Comment thread packages/client/workbench/src/surface/workbench.tsx

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile has paused reviews on this repository — it used its 100 free open-source review credits for this billing period. Reviews resume automatically on September 23. To continue before then, an organization admin can keep reviews running past the free credits — those bill as normal usage.

@pullfrog

pullfrog Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Your Claude subscription has hit its usage limit. It resets at 11:30am (UTC). Re-trigger Pullfrog after the reset, or add an ANTHROPIC_API_KEY repo secret — Pullfrog routes around an exhausted subscription automatically when one is present.

Add repo secret → · Model settings → · Setup docs → · Ask in Discord →

Pullfrog  | Rerun failed job ➔View workflow run | via Pullfrog | Using Claude Opus𝕏

Copilot AI lite review requested due to automatic review settings September 7, 2026 07:25
@pullfrog

pullfrog Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Your Claude subscription has hit its usage limit. It resets at 11:30am (UTC). Re-trigger Pullfrog after the reset, or add an ANTHROPIC_API_KEY repo secret — Pullfrog routes around an exhausted subscription automatically when one is present.

Add repo secret → · Model settings → · Setup docs → · Ask in Discord →

Pullfrog  | Rerun failed job ➔View workflow run | via Pullfrog | Using Claude Opus𝕏

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@Zerlight

Zerlight commented Sep 8, 2026

Copy link
Copy Markdown
Member Author

Review round on this PR (Greptile, two inline threads), fixed on the top of the stack. 795f0b3resource.source.upload keeps its released v79 wire shape (unbounded name and MIME type) so no older client's frame is dropped unanswered; the handler caps the name to 255 and refuses a MIME type over 128 with a typed invalid_request. bcd5805 — the client refuses an over-long name or MIME type before an attachment.upload.begin leaves (the local guard put already had for size), and 9176938 caps File.name in the composer so a long filename still uploads. 9176938 also moves the preview resolver next to the URL cache and makes it generation-aware: a read that outlives a session switch mints no object URL. Gates at 9176938: check:ci 0 errors, 3427 tests. Detail on the threads; PR body unchanged.

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.

2 participants