Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
148d56c
Sign Kimi accounts in on kimi.ai or kimi.com and copy sign-in links
justrach Oct 24, 2026
9461d77
Quiet terminal startup and expose live thinking controls
justrach Oct 26, 2026
15383f8
Include the current release-branch baseline
justrach Oct 26, 2026
dd72985
Prepare v0.302.53 terminal UX release
justrach Oct 26, 2026
54162e9
Prepare v0.302.53 release
justrach Oct 26, 2026
9a247af
Allow native file tools to follow in-root symlinks
justrach Oct 26, 2026
3599836
Carry the terminal fixes onto the released baseline
justrach Oct 26, 2026
938e134
Assemble v0.302.54 release candidate
justrach Oct 26, 2026
9819a0d
Prepare v0.302.55 without rewriting the existing release tag
justrach Oct 26, 2026
f5a081a
Include #1754 in v0.302.56
justrach Oct 26, 2026
0b8e3c6
Align the confinement ADR heading with its release index
justrach Oct 26, 2026
2ada87e
Don't count polls of a subagent that is still running (#1706)
justrach Oct 27, 2026
72af0af
Merge fix/1706-identical-tool-batch-guard into release/v0.302.57
justrach Oct 27, 2026
461e45a
Type staged images by their bytes, not their file extension
justrach Oct 27, 2026
6c14f36
Settle a failed turn so resending its prompt makes a new request
justrach Oct 27, 2026
557d39d
Merge fix/1762-image-type-from-bytes into release/v0.302.57
justrach Oct 27, 2026
659d677
Merge fix/1729-retry-after-failed-request into release/v0.302.57
justrach Oct 27, 2026
dfe5b0c
Surface error-only SSE bodies on every streaming wire
justrach Oct 27, 2026
6b00c4b
Report a workspace switch to the ACP client when it happens
justrach Oct 27, 2026
fd1f733
Merge fix/748-error-only-sse into release/v0.302.57
justrach Oct 27, 2026
eed09bb
Find retained worker checkpoints after the parent changes folder
justrach Oct 27, 2026
5f62df6
Merge fix/1737-1724-workspace-image-retained-worker into release/v0.3…
justrach Oct 27, 2026
5bf0598
todos: cancelled items carry a required reason; ask_user answers coun…
justrach Oct 27, 2026
03e13f0
Merge fix/1520-withdrawn-checklist-items into release/v0.302.57
justrach Oct 27, 2026
882a4ed
Let a resumed session re-list items it cancelled before reasons exist…
justrach Oct 27, 2026
7aa7c30
Prepare v0.302.57 release
justrach Oct 27, 2026
df0155b
Model catalogs never hold startup or graff/models past a budget
justrach Oct 29, 2026
19c3d12
note_constraint advertises its byte ceiling (#1764)
justrach Oct 29, 2026
15b0f5d
Prepare v0.302.58 release
justrach Oct 29, 2026
ab9ba5b
Catalog workers leave the process signal handlers alone
justrach Oct 29, 2026
cef6657
fix(stream): prevent false stalls during partial SSE events (#1765)
yxlyx Oct 29, 2026
9c207e4
Prepare v0.302.59 streaming reliability release
yxlyx Oct 29, 2026
147dc8e
Resumed sessions keep their compaction-state count (#1686)
justrach Oct 29, 2026
703af5d
WebSocket accepts the same event size as SSE; chatgpt-new takes a moc…
justrach Oct 29, 2026
8e3e1c4
Learn the compaction-state count from chained replies too (#1686)
justrach Oct 29, 2026
3cf0e22
Merge fix/1686-reload-opaque-calibration into release/v0.302.60 (#1766)
justrach Oct 29, 2026
a279612
Prepare v0.302.60 release
justrach Oct 29, 2026
338d7ea
release: merge v0.302.60 back to main (#1767)
justrach Oct 29, 2026
fe4e383
Catalog tests wait for the workers they abandon
justrach Oct 30, 2026
d1ad993
Claude Agent provider: drive the user's own claude (ADR 0309)
justrach Oct 31, 2026
49fcbe9
claude-agent login: no terminal means sign in with claude first
justrach Oct 31, 2026
813df36
lean: keep a folded native the turn loaded
justrach Oct 31, 2026
82b4ae5
claude-agent: a prompt followed by notices stays the prompt
justrach Oct 31, 2026
0758553
test: an ACP exit names its status and stderr
justrach Oct 31, 2026
82edf8e
Merge pull request #1772 from justrach/fix/catalog-bounded-sigio
justrach Oct 31, 2026
18bb00f
Merge remote-tracking branch 'origin/release/v0.302.61' into feat/cla…
justrach Oct 31, 2026
fc715e3
Merge pull request #1773 from justrach/feat/claude-agent-provider
justrach Oct 31, 2026
c9b5540
Claude Agent is the Claude plan once chosen
justrach Oct 31, 2026
e34bdb8
Merge pull request #1774 from justrach/feat/claude-agent-plan-models
justrach Oct 31, 2026
9fb5c7e
Prepare v0.302.61 release
justrach Oct 31, 2026
86413da
Merge pull request #1776 from justrach/release/v0.302.61
justrach Oct 31, 2026
abaec32
claude-agent: run rlm llm_query on a throwaway claude process
justrach Oct 31, 2026
4c6b178
Merge pull request #1777 from justrach/fix/claude-agent-llm-query
justrach Oct 31, 2026
9c2c134
Prepare v0.302.62 release
justrach Oct 31, 2026
0144389
Merge pull request #1778 from justrach/release/v0.302.62
justrach Oct 31, 2026
3a978d8
Name the rejected credential in auth failure text
justrach Oct 31, 2026
82bd237
Merge pull request #1779 from justrach/fix/auth-failure-names-credential
justrach Oct 31, 2026
49edc7f
Prepare v0.302.63 release
justrach Oct 31, 2026
1f638fd
Merge pull request #1780 from justrach/release/v0.302.63
justrach Oct 31, 2026
32f1de7
Skip an expired Console sign-in that ant cannot renew
justrach Oct 31, 2026
78dafb9
Merge pull request #1781 from justrach/fix/console-expired-token
justrach Oct 31, 2026
5f22163
Prepare v0.302.64 release
justrach Oct 31, 2026
a4a47d0
Merge pull request #1782 from justrach/release/v0.302.64
justrach Oct 31, 2026
453179c
Claude Agent models get their 1M context window
justrach Nov 1, 2026
d667a04
Prepare v0.302.65 release
justrach Nov 1, 2026
48d88af
Merge pull request #1784 from justrach/release/v0.302.65
justrach Nov 1, 2026
17544d9
Keep a hosted-search answer instead of bouncing it as a described cha…
justrach Nov 1, 2026
37eedfc
Merge pull request #1787 from justrach/fix/oneshot-nudge-truncates-reply
justrach Nov 1, 2026
dbd264e
Prepare v0.302.66 release
justrach Nov 1, 2026
278fbd6
Merge pull request #1788 from justrach/release/v0.302.66
justrach Nov 1, 2026
8756562
claude-agent: refresh tools in place; addressed mail wakes a finished…
justrach Nov 1, 2026
2c23d86
Prepare v0.302.67 release
justrach Nov 1, 2026
4270a2e
Merge pull request #1790 from justrach/release/v0.302.67
justrach Nov 1, 2026
064cecf
Claude Agent: keep a prompt's images when it follows a tool result (#…
justrach Nov 1, 2026
15bb83a
Merge pull request #1793 from justrach/fix/1792-claude-agent-images
justrach Nov 1, 2026
5e4f0de
test: Claude Agent compaction sends its summary request as the prompt
justrach Nov 2, 2026
e04741e
Prepare v0.302.68 release
justrach Nov 2, 2026
26ce314
Merge pull request #1798 from justrach/release/v0.302.68
justrach Nov 2, 2026
05dcd98
Merge remote-tracking branch 'origin/main' into pr-1733
justrach Nov 2, 2026
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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ jobs:
- name: Embedder mode resumable serve streams (#330)
run: python3 scripts/test-serve-resume.py zig-out/bin/graff

- name: A reloaded session keeps its compaction-state count (#1686)
run: python3 scripts/test-acp-reload-compaction-count.py zig-out/bin/graff

- name: Over-cap tool output spills to a session artifact (#409)
run: python3 scripts/test-spill-artifact.py zig-out/bin/graff

Expand Down
105 changes: 105 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,111 @@ The release workflow uses a tag's section here as its release notes (a
hand-written `docs/releases/<tag>.md` wins if present), so keeping this file
current is part of cutting a release.

## v0.302.68

- Claude Agent compaction sends its summary request as the request. Cut mid tool loop, the request was folded into the conversation checkpoint and followed by "Continue from where the checkpoint ends.", so in a long chat the model carried on with the task or asked a question, and that reply was installed as the summary (#1792, #1793, #1797).
- Claude Agent: a prompt sent after a turn that ended on a tool call keeps its text and images instead of joining the checkpoint as text (#1792, #1793).
- Retains all changes from v0.302.67.

## v0.302.67

- Claude Agent refreshes a changed tool list in place. Removing and re-adding graff's tools (to make Claude Code re-read them) failed the `load_tool_schemas` call that caused the change with "Connection closed", and the model often ended its turn or got "No such tool available"; graff now sends `tools/list_changed` and keeps the connection (#1789, ADR 0311).
- A turn started by unread peer mail has `peer_message` loaded with its first request (#1789).
- A task that ended with `attempt_completion` still hears mail addressed to it, as a task that ended with an ordinary answer does; room mail still waits for the next prompt (#1789).
- Retains all changes from v0.302.66.

## v0.302.66

- A one-shot (`-p`) answer built on the provider's hosted search is kept. Hosted search runs inside the model call and never counted as a local tool call, so graff took a search-backed answer for a described change, printed "[described a change with no tool call — asking once more]", and the follow-up reply replaced the answer (#1786, #1787).
- Retains all changes from v0.302.65.

## v0.302.65

- Claude Agent models report and use their 1M context window. Claude Code runs the current Claude models at 1M natively, but graff listed every `claude-agent` model at 200k, so it compacted at a fifth of the window and clients showed "200k context". A `<id>[1m]` name now resolves to 1M as well (#1783).
- Retains all changes from v0.302.64.

## v0.302.64

- An expired Anthropic Console sign-in that can't be renewed is skipped instead of sent. With no refresh token stored, `ant auth print-credentials` exits 0 and prints the same expired token; graff took that as a refresh, so the dead token was used (or kept as the fallback behind a Claude plan) and every request came back 401. Errors now say "Anthropic Console sign-in has expired: run `graff login console` again", including after a plan handoff, and a spent plan whose fallback was skipped says why (#1781, ADR 0310).
- Retains all changes from v0.302.63.

## v0.302.63

- An authentication failure names the credential that was rejected. A sign-in says "<Provider> sign-in was rejected: sign in again (<login command>)"; an API key says "<Provider> API key was rejected (<source>): replace or remove the key. Your sign-in is not affected."; and a key graff fell back to after a plan ran out says "<Provider> plan is out of usage, and the fallback API key was rejected (<source>)". Before, every case read "provider authentication failed: sign in again or check the API key", so a client showed "Log in" when the key was the problem (#1779, ADR 0310).
- Over ACP a rejected key carries `{"kind":"api_key_rejected","provider":"<id>"}` (v1 error data on -32603; v2 `_meta["graff/recovery"]`), so clients can offer "Update key" instead of a sign-in. `reauth_required` is unchanged.
- Retains all changes from v0.302.62.

## v0.302.62

- `rlm`'s `llm_query` works on Claude Agent. Each sub-query runs on its own short-lived, tools-off `claude` process, the way titles and recaps do, so the chat's `claude` process and its prompt cache carry on untouched. Before, it answered "llm_query is not available on Claude Agent" (#1777, ADR 0309).
- Retains all changes from v0.302.61.

## v0.302.61

- Claude Agent: Claude models through your own Claude Code (`claude`) and its login. Sign in with `graff login claude-agent` (or `/login claude-agent`); graff checks `claude auth status`, never reads Claude Code's credentials, and runs your installed `claude` with graff's tools, prompt, history and loop. Calls are flat-rate on a Claude plan (#1773, ADR 0309).
- Once chosen it is your Claude plan: `/model` lists `claude-opus-5-5`, `claude-fable-5-1`, `claude-sonnet-5-5` and `claude-haiku-5-5` under Claude Agent, and those names route to it. `anthropic/<model>` still reaches the API route (#1774).
- Without a terminal (a client such as the desktop app), `graff login claude-agent` says to run `claude auth login` instead of starting it.
- Lean mode keeps `agent_output` once a subagent request loads it, so a turn that starts background workers can wait for them instead of ending early.
- Catalog tests wait for the workers they abandon, which crashed the Linux test job with SIGIO (#1772).
- Retains all changes from v0.302.60.

## v0.302.60

- A resumed session keeps the provider's count of its Responses compaction state. A restart no longer re-estimates that opaque state from its size, which could show the context meter far over 100% and force a compaction the session did not need. The count is saved with the session and reapplied only to the same state, provider and model (#1686).
- The count is learned from chained (WebSocket) replies as well as full requests, so chatgpt-new sessions are counted during normal use.
- WebSocket accepts events as large as SSE does (128 MiB). A large compaction item over WebSocket previously failed, retried, and fell back to SSE, re-running the turn each time.
- `GRAFF_CHATGPT_URL` points chatgpt-new at a local mock for testing.
- Retains all changes from v0.302.59.

## v0.302.59

- Large, steadily arriving SSE events no longer trigger false stream stalls or replay a request merely because the next newline has not arrived (#1765).
- Genuine stalled streams still time out. Unfinished events have bounded assembly time and size, and local assembly-limit failures are not retried.
- Retains all changes from v0.302.58.

## v0.302.58

- ACP startup and `graff/models` no longer wait on slow model-catalog requests. A cached catalog, fresh or stale, loads immediately and refreshes in the background; only a provider with no cache waits, at most 800ms in total. A cold DNS lookup or slow host can no longer make a client report that model discovery timed out. The Kimi account catalog is now cached for 6 hours.
- `note_constraint` states its 240-byte limit in the tool description and the `text` field, so a model learns it before writing a rule rather than from a rejection (#1764).
- Retains all changes from v0.302.57.

## v0.302.57

- Images are typed by their bytes rather than their file extension. A WebP saved as `.png` is sent as WebP, and a file that is not PNG, JPEG, GIF, or WebP is refused before it reaches the transcript instead of failing every later turn (#1762).
- A turn that fails before any reply records the failure in history, so resending the same prompt makes a new request instead of being skipped as a duplicate. The boundary is saved with the session (#1729).
- Streams that carry only an error event surface the provider's error type and message on every wire instead of being retried as truncated bodies; deterministic invalid-request errors are no longer retried (#748).
- Checklist items the user withdrew or delegated can be marked `cancelled` with a required, visible reason, and the completion gate accepts them without counting them as verified. An `ask_user` answer counts as the user's scope change (#1520).
- ACP clients receive `session_info_update` as soon as `workspace use` moves the session, with the new folder as `_meta["graff/cwd"]`, so client-served tools can follow the switch within the same turn (#1737).
- Retained workers remember the folder their checkpoint was saved under, so `subagent_resume` still finds it after a workspace switch; refusals now explain what happened and what to do (#1724).
- The repeated-tool-call guard no longer counts polls of a background subagent that is still running (#1706).
- Retains all changes from v0.302.56.

## v0.302.56

- Native file tools can follow dependency symlinks whose targets remain inside their selected tool root. Reads, directory listings, edits, and writes share the same confinement policy.
- Escaping, dangling, and cyclic links remain denied. Missing ordinary paths remain available for new writes, and explicitly allowed extra roots keep their own boundaries.
- Retains all changes from v0.302.55.

## v0.302.55

- Command-line help, release history, and bundled playbooks are compressed until requested, reducing duplicated runtime text without removing content or changing the build's safety settings.
- Long home paths no longer prevent installation of the macOS background-launch shim.
- Includes the quiet terminal startup and live thinking controls from v0.302.54, and retains all changes from v0.302.53.

## v0.302.54

- Normal terminal startup keeps background connection receipts and legacy-listener diagnostics behind `GRAFF_REPL_DEBUG=1`; boot timing stays behind `GRAFF_BOOT_DEBUG=1`. Explicit `/mcp` and `graff servers` inspection remains available, and listener ownership protections are unchanged.
- Live thinking shows `Ctrl+T collapse` and `Ctrl+T expand` beside its header. Enable it with `/thinking on`; completed terminal scrollback remains read-only.
- Retains all changes from v0.302.53.

## v0.302.53

- Embedded runtime resources are compressed, prompt variants share their common text, and optional tool catalogs are built on first use to keep release binaries smaller without changing their contents.
- Release builds retain runtime safety checks while sharing library code more efficiently. Local learning remains available in development builds rather than being included in release binaries.
- Routed requests use stable session affinity, and usage prices follow the router's published catalog.
- Workflow synthesis preserves its tool catalog at the final report-only boundary while refusing further tool execution.
- Retains all changes from v0.302.52.

## v0.302.52

- The terminal REPL has a clearer session strip, a subtle divider, and distinct styling for active and completed checklist items. The bare prompt, scrollback, and plain output remain intact; no native window or graphical toolkit is required.
Expand Down
3 changes: 3 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ pub fn build(b: *std.Build) void {
const usage_trace_test = b.addSystemCommand(&.{ "python3", "scripts/test-usage-trace.py" });
usage_trace_test.addArtifactArg(exe);
test_step.dependOn(&usage_trace_test.step);
const claude_agent_test = b.addSystemCommand(&.{ "python3", "scripts/test-claude-agent.py" });
claude_agent_test.addArtifactArg(exe);
test_step.dependOn(&claude_agent_test.step);
const acp_view_meta_test = b.addSystemCommand(&.{ "python3", "scripts/test-acp-view-meta.py" });
acp_view_meta_test.addArtifactArg(exe);
test_step.dependOn(&acp_view_meta_test.step);
Expand Down
2 changes: 1 addition & 1 deletion docs/acp-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ optional feature or draft extension is enabled.
| Initialization | Return protocol version 1 and explicit capabilities. Clients must reject a version they cannot speak. | `src/acp_protocol.zig`, `scripts/test-acp-startup.py`, `sdk/ts/acp.test.ts` |
| Authentication | Credential-free initialization is available. Operations requiring a live agent remain authentication-gated. | `scripts/test-acp-preauth.py` |
| Sessions | Create a session in its selected workspace. A live process owns one session; duplicate creation cannot replace its history. Load is advertised only when the live implementation can replay saved history. | `scripts/test-acp-session-load.py`, `scripts/test-acp-released-fixes.py` |
| Workspace and worktrees | `session/new` and `session/load` adopt the client's absolute `cwd`; naming the checkout that owns a `-w` or auto-isolated tree keeps that tree. Replies carry `_meta["graff/worktree"]` (`name`, `path`, `branch`, `base`, `baseSha`, `root`, `generated`, or `null` in a main checkout). A workspace switch emits `session_info_update` with the same `_meta`. | `scripts/test-acp-workspace.py`, `src/acp_workspace.zig`, ADR 0202 |
| Workspace and worktrees | `session/new` and `session/load` adopt the client's absolute `cwd`; naming the checkout that owns a `-w` or auto-isolated tree keeps that tree. Replies carry `_meta["graff/worktree"]` (`name`, `path`, `branch`, `base`, `baseSha`, `root`, `generated`, or `null` in a main checkout). A workspace switch emits `session_info_update` with the same `_meta` plus `graff/cwd`, right after the `workspace` tool result (before the next call), or before the reply for `/workspace use`. | `scripts/test-acp-workspace.py`, `src/acp_workspace.zig`, ADR 0202 |
| Prompt lifecycle | Stream session-scoped updates and return the terminal stop reason. Cancellation interrupts the active turn and cannot grant a pending permission. | `scripts/test-acp-failure.py`, `scripts/test-acp-permissions.py` |
| Tool calls | Preserve call identity, status and terminal results. Tool-like prose is not execution evidence. | `src/acp_stream.zig`, `src/agent_steps_tests.zig` |
| Questions (`ask_user`) | A client that advertises `clientCapabilities.elicitation.form` gets a standard `elicitation/create` form request (one required `answer` string, an `enum` when the model offered choices); `accept` returns the answer, `decline`/`cancel` end the question. A client that opts in with `_meta["graff/askUser"]` gets graff's `gui_ask_user` and answers with `session/answer`. Any other client cannot show the question, so `ask_user` returns at once and tells the model to assume or ask in its reply; it never waits on a client that cannot answer. | `scripts/test-acp-ask-user.py`, `src/acp_elicit.zig` |
Expand Down
10 changes: 8 additions & 2 deletions docs/adr/0202-acp-sessions-adopt-client-cwd.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,14 @@ build. The top-level `cwd` field is removed.
No other folder is searched.

When `/workspace use` or the `workspace` tool moves the root session, the
prompt reply is preceded by `session_info_update` whose `_meta` carries the
new value.
client gets `session_info_update` whose `_meta` carries the new
`graff/worktree` value and `graff/cwd`, the session's absolute working
directory (so a switch into a main checkout or a non-graff tree is still
addressable). The tool's switch is reported right after its tool result,
before the model's next call, not at turn end: a client that serves tools
resolving paths against the session's folder (image attachment) must follow
it within the turn (#1737). A slash switch is reported before the prompt
reply. Each switch is reported once.

`graff worktree` exits 1 when it refuses or fails and 2 when it does nothing
(`kept`), so hosts can branch on the status instead of the text.
Expand Down
16 changes: 10 additions & 6 deletions docs/adr/0230-mcp-connects-in-the-background.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ ahead without a server that is not ready, and reports each server's startup.
- No model request waits for a handshake. Each request merges the starts
that have finished (ADR 0035, 0221), and the catalog rebuilds when one
joined.
- The root request reports what changed: "MCP still connecting — native
tools this turn" on the first request that goes out while servers connect,
then "mcp: NAME connected (N tool(s))" or "mcp: NAME did not connect" when
a start finishes. The registry queues the notices under its lock; the root
agent's request emits them through the agent's own sink, which is what the
TUI shows.
- The root request drains connection receipts after each merge. Normal
interactive sessions keep these diagnostics quiet, avoiding startup chatter
interleaved with the prompt. `GRAFF_REPL_DEBUG=1` exposes "MCP still
connecting — native tools this turn", followed by each server's connection
result. The registry's existing diagnostic switch gates emission, not
connection, catalog updates, consent, or the explicit `/mcp` status view.
Companion auto-connect receipts and legacy-listener startup probes use the
same opt-in; `graff servers` remains available and no ownership or stop
authority is inferred from a marker. Boot timing remains in the trace;
`GRAFF_BOOT_DEBUG=1` opts into phase lines on stderr, even for slow phases.
- ACP `session/new` and `session/load` wait at most 250 ms for the servers
the client named: enough for one restored from the tool cache, never a
real handshake.
Expand Down
38 changes: 38 additions & 0 deletions docs/adr/0302-sse-idle-watchdogs-follow-body-byte-progress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 0302. SSE idle watchdogs follow body-byte progress

Status: accepted

## Context

An SSE event can contain a large completed output item rather than small text
fragments. Racing a whole newline-delimited read against an inactivity timer
mistakes a steadily arriving partial event for a silent connection (#1686).
Reconnect then discards progress and repeats the request. The existing prose,
reasoning and reconnect policies choose the idle allowance; they do not make a
missing newline evidence of missing bytes.

## Decision

Keep those allowances and cancellation rules. During each line read, publish
body progress through an atomic timestamp and expire inactivity only when that
progress stops. The HTTP/1 delimiter reader uses an unbuffered forwarding writer;
the HTTP/2 reader consumes `LineStream.readChunk`, preserving bytes after a
newline for its next read. HTTP/2 control traffic is not response-body progress.
Buffers remain owned by the read task, and cancellation joins it before cleanup.

Bound an unfinished event separately: at most 128 MiB and fifteen minutes of
assembly. An explicitly longer idle allowance also raises the assembly deadline,
so the new deadline does not shorten an explicit silence setting. These bounds
prevent oversized events and indefinitely dripping partial lines from disabling
recovery. Event-size and assembly-deadline failures have distinct errors and are
not replayed as transient network failures. Normal completion, delayed usage
trailers, and genuine silence retain their existing outcomes.

## Consequences

A large event may take longer than one idle allowance while its body continues
to arrive, without reconnecting. HTTP/2 reports body progress at DATA-chunk
boundaries exposed by the pinned transport; no dependency change or raw
connection/control-frame activity is needed. Synthetic HTTP/1 and HTTP/2 tests
cover flowing and stopped partial events; `sse-partial-line-byte-progress` runs
the actual engine against a fragmented scripted response and asserts one request.
Loading
Loading