Documents

A document is the sixth thing this framework persists, and none of the other five fits: it changes (so not a file ref), it outlives its thread (so not the transcript), and for a document the diff is the product, because it is what the user approves. Storage stays the host's — the framework owns the model, the edit protocol and the approval surface.

The previewer

It renders, it selects, and it shows diffs. No toolbar, no caret, no contentEditable — changes go through the conversation and land via an approved diff. That boundary is what keeps this a component rather than the visual builder the framework rules out.

Vendor reviewv1

Vendor review

Two suppliers, scored against the March criteria.

Findings

The cheaper option fails SSO. On a three-year horizon that is not a saving.

SupplierAnnualSSONotice
Northwind42,000yes60 days
Contoso31,500no90 days

Contoso's contract has no cap on the renewal uplift.

Recommendation

  1. Award to Northwind.
  2. Ask Contoso for a capped renewal and re-score in September.
renewal = 2027-03-01
notice  = 90d

Quoting

A quote is part of the user's message, not app-state. App-state is re-read every turn, goes stale the moment the selection changes, and is droppable under budget pressure — and dropping a paragraph the user deliberately highlighted loses part of what they said.

Select any text in the document above and press Ask about this. The quote resolves to a block range and the SOURCE markdown — not the rendered text, because the same span has to work as an edit anchor later.

The outline the model reads

Editing is directed — "the third section", "the bit about renewal" — not a similarity search, so the model navigates rather than retrieves. One line per block, and never the body.

[
  {
    "block": 0,
    "kind": "text",
    "level": 1,
    "preview": "# Vendor review",
    "chars": 15
  },
  {
    "block": 1,
    "kind": "text",
    "preview": "Two suppliers, scored against the March criteria.",
    "chars": 49
  },
  {
    "block": 2,
    "kind": "text",
    "level": 2,
    "preview": "## Findings",
    "chars": 11
  },
  {
    "block": 3,
    "kind": "text",
    "preview": "The cheaper option fails SSO. On a three-year horizon that is not a saving.",
    "chars": 75
  },
  {
    "block": 4,
    "kind": "text",
    "preview": "| Supplier | Annual | SSO | Notice |",
    "chars": 151
  },
  {
    "block": 5,
    "kind": "text",
    "preview": "> Contoso's contract has no cap on the renewal uplift.",
    "chars": 54
  },
  {
    "block": 6,
    "kind": "text",
    "level": 2,
    "preview": "## Recommendation",
    "chars": 17
  },
  {
    "block": 7,
    "kind": "text",
    "preview": "1. Award to Northwind.",
    "chars": 85
  },
  {
    "block": 8,
    "kind": "fence",
    "preview": "```",
    "chars": 42
  }
]

The edit protocol, including its refusals

Half of applyEdits is refusal, and that half is the reason the feature is safe. First-match-wins is the tempting fallback and the dangerous one: it puts a change somewhere nobody asked for and then presents it for approval as though it were intended. The diff reads fine, so the user says yes.

Anchored on text that occurs once. Applies.

[
  {
    "find": "## Recommendation",
    "replace": "## What we recommend"
  }
]
Vendor review v1
1/1 selected

Rename a heading

  • ## Recommendation
    ## What we recommend

The document above is live: accept a hunk and it rewrites, and the revision goes up. A refusal writes nothing and hands the model a reason it can act on — not-found means re-read, ambiguous means widen the anchor.

The way out

.eml is the exit and mailto: is the shortcut, and the card says so in that order — past roughly 2,000 characters a mail client truncates a mailto silently. Nothing here sends: that needs a credential, and the framework holding one would break the rule Transport keeps. A host that wants a send button passes onSend.

The generated .eml
To: counsel@example.com
Subject: =?UTF-8?B?VmVuZG9yIHJldmlldyDigJQgcmVjb21tZW5kYXRpb24=?=
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

Hi,

Summary of the vendor review:

- Vendor review
- Findings
- Recommendation

Full document attached.

Thanks