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

@me2seeksme2seeks 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
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch from ed745fb to 032d77fCompareAugust 31, 2026 17:56
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from 36ec70c to 295d562CompareAugust 31, 2026 17:56
@me2seeks
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch from 032d77f to d8bae9fCompareAugust 31, 2026 19:00
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch 2 times, most recently from 87d4bd7 to e07c040CompareAugust 31, 2026 19:11
@github-actionsgithub-actionsBot added the effort/XL Under 2500 readable lines label Sep 1, 2026

@Astro-HanAstro-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
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch from d8bae9f to 1fba905CompareSeptember 1, 2026 08:26
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from e07c040 to eeb37b8CompareSeptember 1, 2026 08:26
@me2seeks

Copy link
Copy Markdown
ContributorAuthor

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
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch from 1fba905 to 4609622CompareSeptember 1, 2026 15:04
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from eeb37b8 to 6254710CompareSeptember 1, 2026 15:05
@me2seeks
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch 3 times, most recently from f1744f3 to cd16fd6CompareSeptember 2, 2026 07:41
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from 6254710 to 5949e03CompareSeptember 2, 2026 14:07
@me2seeks

Copy link
Copy Markdown
ContributorAuthor

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
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from 5949e03 to 9ff82bfCompareSeptember 3, 2026 02:28
@me2seeks

Copy link
Copy Markdown
ContributorAuthor

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
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch from 3dd69e7 to 51bacd2CompareSeptember 3, 2026 05:58
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from 9ff82bf to 042d203CompareSeptember 3, 2026 06:12
@me2seeks

Copy link
Copy Markdown
ContributorAuthor

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
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch from 51bacd2 to 9ec0c5fCompareSeptember 3, 2026 06:55
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from 042d203 to 62d04e3CompareSeptember 3, 2026 07:10
@me2seeks

Copy link
Copy Markdown
ContributorAuthor

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
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch from 9ec0c5f to 0b141e9CompareSeptember 3, 2026 09:16
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from 62d04e3 to 3f53e26CompareSeptember 3, 2026 09:17
@me2seeks
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch from 0b141e9 to 94d9d5eCompareSeptember 3, 2026 09:32
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from 3f53e26 to 9a870c5CompareSeptember 3, 2026 09:32
@me2seeks
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch from 94d9d5e to b65d7ffCompareSeptember 3, 2026 10:56
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from 9a870c5 to ea8ad52CompareSeptember 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
me2seeksforce-pushed the feat/4364-runtime-form-interactions branch from b65d7ff to b3b1072CompareSeptember 3, 2026 14:18
@me2seeks
me2seeksforce-pushed the feat/4364-client-capability-form-interactions branch from ea8ad52 to e27d47dCompareSeptember 3, 2026 14:19

@M4n5terM4n5ter 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-interactionsSep 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
ggbdpq pushed a commit to ggbdpq/maka that referenced this pull request Sep 4, 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 apache#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 apache#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 (apache#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 apache#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 apache#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 apache#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 (apache#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 apache#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
Generated-by: GLM-5.3-Flash (ZCode)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XLUnder 2500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@me2seeks@M4n5ter@Astro-Han