Skip to content

feat(engine): declare per-harness content-block support and reject unsupported input - #515

Open
Zerlight wants to merge 10 commits into
ruocheng/code-636from
ruocheng/code-625
Open

feat(engine): declare per-harness content-block support and reject unsupported input#515
Zerlight wants to merge 10 commits into
ruocheng/code-636from
ruocheng/code-625

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-625/featengine-declare-per-harness-content-block-support-and-reject

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

AttachmentCapability per harness (effective = host limits ∩ adapter declaration) with typed unsupported_attachment refusals at the admit step, before anything is persisted, and the PreparedPrompt materializer — the only place bytes leave the store — producing inline images or read-only file projections per declared representation. Admitted refs are persisted and projected without bytes.

Commits

  • feat(schema): declare optional attachment capabilities and typed refusal
  • feat(agent-adapter): declare per-harness attachment support and refuse undeclared blocks
  • feat(engine): admit attachment refs against harness capability
  • feat(engine): materialize prompt attachments for adapters
  • feat(engine): persist admitted refs and project them without bytes
  • fix(engine): refuse unsupported resource_link before persist
  • fix(schema): keep the attachment representation list open on the wire
  • fix(engine): charge every attachment ref occurrence against the prompt caps
  • fix(engine): materialize a repeated ref once and log cleanup failures
  • fix(engine): project the attachment kind off the resource_link title

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.

Checklist

  • pnpm check:ci and pnpm test both pass (no Rust changes)
  • I ran the affected surface and observed the change working — engine exercised through its harness tests and the dev-mock parity suite; the live-daemon run against real providers is recorded per issue in Linear (the claude edit path still needs a paid turn, opencode its binary)
  • Wire: optional capability fields under the still-unshipped wire 80
  • 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-625

@greptile-apps

greptile-apps Bot commented Sep 7, 2026

Copy link
Copy Markdown

Greptile Summary

This PR introduces per-harness attachment capabilities, typed attachment refusals, attachment-reference admission, durable reference projection, and last-hop prompt materialization.

  • Intersects adapter declarations with host attachment limits.
  • Admits stored references before persistence and materializes supported images for adapters.
  • Projects persisted references as byte-free resource_link blocks.
  • Adds run/session cleanup for materialized files and extensive schema and engine coverage.
  • The legacy inline-input path still omits the declared image-count limit, and the readonly-file conversion remains incomplete.

Confidence Score: 4/5

The PR should not merge until direct inline prompts enforce the advertised per-harness image-count limit; readonly-file conversion should also be completed or withheld.

A reachable agent.input prompt can exceed the declared 16-image capability because the new inline admission path never counts images, while readonly-file capability support is internally incomplete but not active in the current harness matrix.

Files Needing Attention: packages/host/engine/src/attachment/admit.ts, packages/host/engine/src/attachment/materializer.ts

Important Files Changed

Filename Overview
packages/foundation/schema/src/model/attachment.ts Defines attachment capability limits, open representation values, host intersections, and attachment URI helpers.
packages/foundation/schema/src/model/agent/input.ts Adds the per-agent attachment capability matrix and effective host/adapter intersection.
packages/host/engine/src/attachment/admit.ts Adds stored-reference and inline-content admission, but the reachable inline path does not enforce the declared image-count limit.
packages/host/engine/src/attachment/materializer.ts Materializes inline images and readonly hardlinks, although readonly blocks cannot yet cross the final ContentBlock conversion.
packages/host/engine/src/session/lifecycle-service.ts Integrates attachment admission before intent persistence and materialization before adapter dispatch.
packages/host/engine/src/session/session-input-dispatcher.ts Applies inline capability checks and supports separate echo and materialized adapter inputs.
packages/host/engine/src/conversation/turn-service.ts Projects durable attachment references into byte-free conversation resource links.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  C[Client prompt] --> G{Input path}
  G -->|turn.submit| A[Load and admit attachment refs]
  G -->|agent.input| I[Validate inline blocks]
  A --> P[Persist prompt refs]
  P --> M[Materialize stored bytes]
  I --> D[Session dispatcher]
  M --> D
  D --> B[Agent adapter]
  P --> R[conversation.read projection]
  R --> L[resource_link without bytes]
  B --> X[Run ends]
  X --> K[Clean materialized files]
Loading

Reviews (1): Last reviewed commit: "fix(engine): project the attachment kind..." | Re-trigger Greptile

Comment thread packages/host/engine/src/attachment/admit.ts
Comment thread packages/host/engine/src/attachment/materializer.ts

@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𝕏

A closed enum inside capabilities-update makes the whole agent.event frame invalid-payload for a peer that has not learned a newer representation, dropping the session's capability stream. Kinds were already open; representations now match, and the host intersection drops what it cannot materialize.
…t caps

Admit deduped ids before accounting while the materializer converts one block per ref, so a repeated ref escaped the 12 MiB aggregate: 500 refs to one 8 MiB image admitted at '8 MiB, 1 image' and materialized 4 GiB. The caps now bound what actually leaves the store. A projected attachment: link is also refused by name instead of as a file attachment.
A prompt may name one attachment twice in a run, and the destination is content-addressed, so an existing hardlink is already the same bytes; EEXIST was failing the turn as a filesystem error. Cleanup failures no longer vanish into a bare noop.
Both shipped resource_link renderers prefer title over name, so carrying the kind there labelled every attachment chip 'image' instead of its filename. The projection assertions also sat behind an early return that let them skip silently.
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 7, 2026

Copy link
Copy Markdown
Member Author

Review round on this PR (Greptile, two inline threads), both fixed on the top of the stack in a8c1bb4: legacy agent.input prompts now count inline images against the harness maxCount (reproduced first; a ref submit was already counted), and a readonly_file projection is handed to the adapter as a file:// resource link instead of failing in toContentBlocks — unreachable today, since no shipped harness declares that representation, but the pipeline now agrees end to end. Gates at a8c1bb4: check:ci 0 errors, 3423 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