Skip to content

feat(runtime-host): broker nested capability forms - #4397

Merged
me2seeks merged 9 commits into
feat/4364-runtime-form-interactionsfrom
feat/4364-client-capability-form-interactions
Sep 3, 2026
Merged

feat(runtime-host): broker nested capability forms#4397
me2seeks merged 9 commits into
feat/4364-runtime-form-interactionsfrom
feat/4364-client-capability-form-interactions

Conversation

@me2seeks

@me2seeks me2seeks commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add strict Client Capability interaction request/result frames and expose a provider-neutral requestInteraction(form) callback after invocation admission
  • route nested forms through the existing Runtime-owned form callback and exact hosted Run authority instead of creating Client Capability-owned durable state
  • let a hosted Run withdraw only the exact producer-owned form when the provider fails or disconnects
  • pause provider execution time only while the canonical form is pending, bound answer delivery, and rearm a fresh execution timeout after delivery

Why

#4379 establishes the durable, provider-neutral form interaction contract. Client Capability providers still need a bounded way to pause an admitted tool call, collect structured user input through the active Maka surface, and continue the same invocation.

The Runtime Host remains the only canonical Interaction authority. The Client channel owns only provider-local correlation, while the invocation broker owns the transient execution timer and ensures provider failure, cancellation, release, and connection loss close the nested form before the outer call settles.

This PR is a sibling of the Desktop adapter in #4384 and the TUI adapter in #4392. All three depend directly on #4379; none of the siblings depends on another.

Part of #4364.

Compatibility

  • advance the Runtime Host compatibility epoch to 84 because older peers cannot decode the nested Client Capability request/result frames
  • keep MCP/provider-specific mapping outside this protocol layer; a later adapter can translate its native interaction request into the same provider-neutral form contract

Screenshots

No visual changes. Desktop and TUI rendering are covered by the sibling surface PRs #4384 and #4392.

Test plan

  • npx biome check on all changed files
  • npm run build
  • 131 focused Runtime and Runtime Host tests covering canonical form withdrawal, strict frame decoding, one-pending correlation, timeout pause/rearm, delivery races, provider failure, cancellation, and connection loss

Generated-by: OpenAI Codex

@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch from ed745fb to 032d77f Compare August 31, 2026 17:56
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from 36ec70c to 295d562 Compare August 31, 2026 17:56
@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch from 032d77f to d8bae9f Compare August 31, 2026 19:00
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch 2 times, most recently from 87d4bd7 to e07c040 Compare August 31, 2026 19:11
@github-actions github-actions Bot added the effort/XL Under 2500 readable lines label Sep 1, 2026

@Astro-Han Astro-Han 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.

PR #4397e07c040 — blind review sealed

Summary: Runtime Host brokering for nested capability forms (tail of #4379 stack). Exact head e07c040759c6483ac52e5bb2a6bdefbb8d4a092d frozen, stacked-base CLEAN, 0 checks/0 reviews/0 threads on stacked base. Source is approvable with comments; inherits #4379's 2×P2+1×P3. No simplify finding. Directly affected tests 141/141, Runtime 3121/7/0, Runtime Host 1501/12 (1 transient timing case isolated) all green.

Findings (reproducible production seams):

  • P2 — cancellation-before-admission ghost form — if producer cancellation publishes before form admission, withdraw succeeds early (“no record”), later admission still publishes and leaves ghost pending form of a failed provider until Run close. Deferred-admission seam: expected 0 pending, actual 1. Fix: share ordered fence between admission/cancellation or re-withdraw after successful admission.
  • P2 — HostClientCapabilityCoordinator.close() drops cleanup promise — new async releaseConnection() interaction-cleanup promise is discarded, only registry mutation awaited; pending form withdrawal slightly slower → broker.close() early with active invocation. Deferred-withdrawal coordinator seam: expected wait, actual early failure. Fix: collect and await all connection-release promises in coordinator close.

Gating: current-main da84f88de merge tree has only explicitly ignored epoch conflict; stacked-base CLEAN.

Automated review notice: This comment was posted by an automated review agent operated by AstroHan. It is not an independent human review and does not replace one.


简体中文

本条结论来自 @捣蛋鬼 在 exact head e07c040 的独立盲审,已按 @me2seeks 指示排除 compatibility epoch 冲突的计分。编排仅核对 head 未漂移与 CI 状态。

@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch from d8bae9f to 1fba905 Compare September 1, 2026 08:26
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from e07c040 to eeb37b8 Compare September 1, 2026 08:26
@me2seeks

me2seeks commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Fixed both findings across f07fe90 and eeb37b8. Producer cancellation now orders withdrawal after successful Host admission, and connection release/close waits for nested interaction cleanup, including a release that started before coordinator shutdown.

While rebasing, I also preserved main's accepted → admitted grant boundary and added a prepared-execution regression so forms are forwarded only after admission (4ac7785). Added deferred-admission and close-barrier coverage.

@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch from 1fba905 to 4609622 Compare September 1, 2026 15:04
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from eeb37b8 to 6254710 Compare September 1, 2026 15:05
@me2seeks
me2seeks requested a review from Astro-Han September 1, 2026 15:10
@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch 3 times, most recently from f1744f3 to cd16fd6 Compare September 2, 2026 07:41
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from 6254710 to 5949e03 Compare September 2, 2026 14:07
@me2seeks

me2seeks commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto the updated parent head (cd16fd613d) in 5949e0368.

The parent now owns epoch 94 for the provider-neutral form contract, so the nested Client Capability interaction round trip advances to epoch 95; the epoch history comments are retained. A style commit reformats three nested-form files whose formatting predates the rules now on main — no semantic change.

Validation on 5949e0368: full npm run build; focused Runtime Host suites 134/134 (capability channel, coordinator, interaction broker, protocol, interaction coordinator); focused Runtime suites 253/253 (interaction authority, kernel interaction, session manager, tool runtime form/sandbox); Desktop capability tests 50/50; CLI capability provider command 3/3.

@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from 5949e03 to 9ff82bf Compare September 3, 2026 02:28
@me2seeks

me2seeks commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto the updated parent head (3dd69e776, answer-envelope byte-domain fix) in 9ff82bfdb. No conflicts; the nested-form lifecycle fixes are patch-equivalent to the previously reviewed head, and the compatibility epoch remains 95 on top of the parent's 94. Validation: full build; focused Runtime Host suites 108/108; Runtime form suites 14/14.

@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch from 3dd69e7 to 51bacd2 Compare September 3, 2026 05:58
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from 9ff82bf to 042d203 Compare September 3, 2026 06:12
@me2seeks

me2seeks commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto the updated parent head (51bacd210, strict escaped-envelope admission) in 042d203b7.

Nested-form fixtures now declare an explicit maxLength, matching the contract admission enforces at the protocol seam: an unconstrained string form frame is rejected as an invalid Client Capability form request instead of stranding the invocation, while a bounded one publishes and settles normally (verified against the built protocol decoder). Validation: full build; Runtime Host coordinator/broker 35/35; Runtime MCP tools 9/9; biome clean.

@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch from 51bacd2 to 9ec0c5f Compare September 3, 2026 06:55
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from 042d203 to 62d04e3 Compare September 3, 2026 07:10
@me2seeks

me2seeks commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto the current parent head (9ec0c5f9a) in 62d04e317. The only conflict was the compatibility epoch: the nested Client Capability form round trip now owns 103 on top of the parent's 102. Validation: full build; Runtime Host focused suites 136/136; Runtime form suites 23/23; biome clean.

@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch from 9ec0c5f to 0b141e9 Compare September 3, 2026 09:16
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from 62d04e3 to 3f53e26 Compare September 3, 2026 09:17
@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch from 0b141e9 to 94d9d5e Compare September 3, 2026 09:32
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from 3f53e26 to 9a870c5 Compare September 3, 2026 09:32
@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch from 94d9d5e to b65d7ff Compare September 3, 2026 10:56
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from 9a870c5 to ea8ad52 Compare September 3, 2026 10:56
Let an exact hosted Run withdraw one form without closing its surrounding Turn. Commit producer cancellation through the existing InteractionStore authority, preserve an already-claimed Run closure, and compose provider-local cancellation with the Tool invocation signal.

Part of #4364.

Generated-by: OpenAI Codex
Add strict request/result frames and expose one provider-neutral requestInteraction callback for admitted Client Capability invocations. Keep correlation inside the client channel and publish a new compatibility epoch for peers that understand the round trip.\n\nPart of #4364.\n\nGenerated-by: OpenAI Codex
Route Client Capability interaction requests through the Runtime-owned form callback. Pause provider execution time only while the canonical form is pending, bound result delivery, and rearm a fresh execution timeout after delivery.\n\nClose the exact producer-owned form before settling provider failure, cancellation, or connection loss, while preserving Runtime Host as the only Interaction authority.\n\nPart of #4364.\n\nGenerated-by: OpenAI Codex
The nested capability form sources predate the formatter rules now on
main; rebase onto the current parent and reformat so the changed-file
biome gate passes again. No semantic change.
Admission now proves every legal answer serializes, so a string field
without maxLength is no longer admissible. Bound the fixtures to keep
them representative of forms a provider can actually publish.
@me2seeks
me2seeks force-pushed the feat/4364-runtime-form-interactions branch from b65d7ff to b3b1072 Compare September 3, 2026 14:18
@me2seeks
me2seeks force-pushed the feat/4364-client-capability-form-interactions branch from ea8ad52 to e27d47d Compare September 3, 2026 14:19

@M4n5ter M4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewed at exact commit e27d47d363584428e35e29c81afcf3f675adbf4c.

Nested Client Capability forms now join their exact admission before cancellation can withdraw them, and connection/Host shutdown waits for interaction withdrawal before closing the invocation broker. The current affected builds and lifecycle tests pass, including cancellation-before-admission and delayed-cleanup regressions, and I found no blocking correctness or design issue in this change.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

@me2seeks
me2seeks merged commit bd323f3 into feat/4364-runtime-form-interactions Sep 3, 2026
@me2seeks
me2seeks deleted the feat/4364-client-capability-form-interactions branch September 3, 2026 15:41
me2seeks added a commit that referenced this pull request Sep 3, 2026
* feat(runtime): establish durable form interactions

Define a bounded provider-neutral primitive form contract and carry its request and acknowledgement facts through the Runtime Event Log. Broker pending forms through the existing InteractionStore authority so schema-invalid answers remain pending, concurrent equivalent answers converge on one canonical outcome, and Turn closure or Host restart closes the exact continuation.

Part of #4364.

Generated-by: OpenAI Codex

* fix(runtime): complete form interaction adapter seam

Expose one closed decoder for renderer-to-runtime form responses so surface adapters do not copy protocol validation. Queue the same canonical continuity refresh for form requests that user questions already receive.

Refs #4364.

Generated-by: OpenAI Codex

* fix(runtime): harden structured form boundaries

* fix(desktop): accept form interactions in composer region

* fix(runtime): complete form interaction lifecycle

Generated-by: OpenAI Codex

* fix(desktop): keep unsupported forms out of composer queue

Generated-by: OpenAI Codex

* fix(runtime-host): publish form graph activity

Generated-by: OpenAI Codex

* style(runtime-host): format form graph regression

Generated-by: OpenAI Codex

* fix(core): preserve projected form default semantics

Generated-by: OpenAI Codex

* fix(core): prove the escaped answer envelope at admission

Admission reserved the answer envelope with four raw bytes per code
point, but enforcement measures post-serialization bytes, where JSON
escaping inflates a code point to as much as six. A schema-legal answer
of backslashes, newlines, or control characters could pass admission yet
be rejected at decode, stranding the pending interaction.

Keep the schema semantics — maxLength stays a code-point count and each
value stays bounded at INTERACTION_FORM_VALUE_MAX_BYTES raw bytes — and
prove serializability at admission: the string envelope is now all
control characters (one code point and one raw byte each, six serialized
bytes after escaping), and select envelopes pick the serialized-longest
option rather than the raw-longest. A form whose limits permit an
undeliverable answer is rejected up front instead of stranding the
interaction after the user submits.

Regressions pin the preserved character semantics (2,048 plain
characters or 1,024 backslashes still satisfy a maxLength: 2048 field),
admission rejection for limits that cannot guarantee delivery, and
escape-heavy answers that decode and deliver for admissible forms.

* fix(core): reserve date and date-time envelopes in their legal language

A string field without maxLength reserved 2,048 control characters even
when the format was date or date-time — an estimate that can never pass
the format check yet inflates to 12 KiB, so a form asking for a calendar
day was rejected before publication while its whole legal answer is 64
bytes.

Compute the worst value inside each format's legal language instead:
date is fixed-length over [0-9-], and date-time adds only characters
that never JSON-escape, with fractional seconds bounding length at the
field caps. Other formats and unconstrained strings keep the
six-bytes-per-code-point worst case, since control characters remain
legal there.

Regressions cover date and date-time fields admitted with no maxLength,
their canonical answers decoding, and the fractional-seconds worst case
staying deliverable.

* feat(runtime-host): broker nested capability forms (#4397)

* feat(runtime): withdraw producer-owned forms

Let an exact hosted Run withdraw one form without closing its surrounding Turn. Commit producer cancellation through the existing InteractionStore authority, preserve an already-claimed Run closure, and compose provider-local cancellation with the Tool invocation signal.

Part of #4364.

Generated-by: OpenAI Codex

* feat(runtime-host): carry nested capability forms

Add strict request/result frames and expose one provider-neutral requestInteraction callback for admitted Client Capability invocations. Keep correlation inside the client channel and publish a new compatibility epoch for peers that understand the round trip.\n\nPart of #4364.\n\nGenerated-by: OpenAI Codex

* feat(runtime-host): broker nested capability forms

Route Client Capability interaction requests through the Runtime-owned form callback. Pause provider execution time only while the canonical form is pending, bound result delivery, and rearm a fresh execution timeout after delivery.\n\nClose the exact producer-owned form before settling provider failure, cancellation, or connection loss, while preserving Runtime Host as the only Interaction authority.\n\nPart of #4364.\n\nGenerated-by: OpenAI Codex

* fix(runtime-host): order nested form cleanup

* test(desktop): complete capability interaction fake

* fix(runtime-host): forward forms after capability admission

* fix(runtime-host): await prior capability releases

* style: format nested capability form files

The nested capability form sources predate the formatter rules now on
main; rebase onto the current parent and reformat so the changed-file
biome gate passes again. No semantic change.

* test: give nested form fixtures an explicit string bound

Admission now proves every legal answer serializes, so a string field
without maxLength is no longer admissible. Bound the fixtures to keep
them representative of forms a provider can actually publish.

* feat(tui): answer structured form interactions (#4392)

* feat(tui): answer structured form interactions

Review and edit Host-owned forms in the existing TUI interaction queue, preserving optional omission and all six primitive field kinds. Route accepted, declined, and cancelled responses through the generic Runtime Host interaction operation, while non-interactive runs stop the exact Turn instead of dropping the request.

Keep requester provenance and sensitive-data guidance visible, validate with the shared Core contract, and retire stale overlays when authoritative transcript state changes.

Part of #4364.

Generated-by: OpenAI Codex

* fix(tui): retain reconnecting form drafts

* test(tui): cover form constraint copy variables

* style(tui): format form interaction sources

The TUI form sources predate the formatter rules now on main; rebase
onto the current parent and reformat so the changed-file biome gate
passes. Reflow and trailing commas only, no semantic change.

* fix(cli): cover the form interaction TUI under copy boundaries
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XL Under 2500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants