Skip to content

fix(react-core): route turn-2 Enter to send during interrupt-resume#5195

Merged
jpr5 merged 1 commit into
mainfrom
fix/gen-ui-interrupt-minimal
Jun 3, 2026
Merged

fix(react-core): route turn-2 Enter to send during interrupt-resume#5195
jpr5 merged 1 commit into
mainfrom
fix/gen-ui-interrupt-minimal

Conversation

@jpr5

@jpr5 jpr5 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the consecutive-interrupt regression: after picking turn-1's interrupt option, the resume run is still streaming, so pressing Enter to send turn-2 was routed to STOP and aborted the in-flight run — the second interrupt's card never surfaced.

Two-part fix in @copilotkit/react-core v2 chat:

  • CopilotChatInput — Enter now routes to send whenever the composer holds sendable text (isProcessing && !canSend → stop). Stop stays reachable via Enter only when the composer is empty. The send/stop button is unchanged (always stops during a run).
  • CopilotChat.onSubmitInput — awaits the in-flight run's activeRunCompletionPromise before dispatching the new message, instead of pre-empting it via runAgent/detachActiveRun. The two turns serialize: the resume finishes before the new message starts a fresh run. Typed text is optimistically cleared and restored on a blocked send.

Scope is intentionally the react-core fix only (4 files).

Verification

  • Isolated-D6 e2e (dist-overlay): both pills green — langgraph-typescript and langgraph-python, each turnsCompleted: 2, state: green.
  • react-core suite: 1201 passed (95 files). Red-green confirmed for the Enter-routing + queuing tests (they fail without the fix).
  • Typecheck: zero new errors in touched files. Build: publishable dist.
  • 7-agent code review converged to zero subject-scoped findings.

Follow-ups (separate PRs)

  • Send-queue serialization + suggestion-path in-flight guard (robust completion-promise via core RunHandler).
  • gen-ui-interrupt demo matrix: DRY the duplicated demo pages into a shared component (thin per-hook adapters), migrate non-LangGraph integrations off the dead-on-Strategy-B useInterrupt to useHumanInTheLoop, and minimize the strands/langroid backends.

Release: standard release / create-pr → merge → release / publish (OIDC) flow — no changeset.

🤖 Generated with Claude Code

…nstead of aborting the run

On consecutive interrupts, pressing Enter for the second turn (turn-2) while
the resumed run from turn-1 was still in flight routed the keystroke to the
STOP action, aborting the in-flight resume instead of sending the new message.

The fix gates the Enter handler on `canSend` so a pending/running state no
longer maps Enter to STOP, and `onSubmitInput` now awaits the in-flight run's
completion before dispatching the queued message — the message is sent after
the current run finishes rather than aborting it.

Also hardens the queuing and attachment tests to cover the consecutive-
interrupt path and the send-after-run-completes behavior.
@vercel

vercel Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
chat-with-your-data Ready Ready Preview, Comment Jun 3, 2026 8:32pm
docs Ready Ready Preview, Comment Jun 3, 2026 8:32pm
form-filling Ready Ready Preview, Comment Jun 3, 2026 8:32pm
research-canvas Ready Ready Preview, Comment Jun 3, 2026 8:32pm
travel Ready Ready Preview, Comment Jun 3, 2026 8:32pm

Request Review

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

📣 Social Copy Generator

Generate social media copies (Twitter/X, LinkedIn, Blog Post) for this PR using Claude.

  • Generate social media copies

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Production Digest-Pinning Audit

All 27 services digest-pinned.

Run 2026-06-03 13:26:24 PDT — 0 finding(s).

@pkg-pr-new

pkg-pr-new Bot commented Jun 3, 2026

Copy link
Copy Markdown

Open in StackBlitz

@copilotkit/a2ui-renderer

pnpm add https://pkg.pr.new/@copilotkit/a2ui-renderer@5195

@copilotkit/agentcore-runner

pnpm add https://pkg.pr.new/@copilotkit/agentcore-runner@5195

@copilotkitnext/angular

pnpm add https://pkg.pr.new/@copilotkitnext/angular@5195

@copilotkit/core

pnpm add https://pkg.pr.new/@copilotkit/core@5195

@copilotkit/react-core

pnpm add https://pkg.pr.new/@copilotkit/react-core@5195

@copilotkit/react-native

pnpm add https://pkg.pr.new/@copilotkit/react-native@5195

@copilotkit/react-textarea

pnpm add https://pkg.pr.new/@copilotkit/react-textarea@5195

@copilotkit/react-ui

pnpm add https://pkg.pr.new/@copilotkit/react-ui@5195

@copilotkit/runtime

pnpm add https://pkg.pr.new/@copilotkit/runtime@5195

@copilotkit/runtime-client-gql

pnpm add https://pkg.pr.new/@copilotkit/runtime-client-gql@5195

@copilotkit/sdk-js

pnpm add https://pkg.pr.new/@copilotkit/sdk-js@5195

@copilotkit/shared

pnpm add https://pkg.pr.new/@copilotkit/shared@5195

@copilotkit/sqlite-runner

pnpm add https://pkg.pr.new/@copilotkit/sqlite-runner@5195

@copilotkit/voice

pnpm add https://pkg.pr.new/@copilotkit/voice@5195

@copilotkit/vue

pnpm add https://pkg.pr.new/@copilotkit/vue@5195

@copilotkit/web-inspector

pnpm add https://pkg.pr.new/@copilotkit/web-inspector@5195

commit: cd0e145

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Size Change: +484 B (+0.05%)

Total Size: 980 kB

📦 View Changed
Filename Size Change
packages/react-core/dist/copilotkit-B5RsC6la.mjs 0 B -88.4 kB (removed) 🏆
packages/react-core/dist/copilotkit-BRNy5UvX.mjs 88.6 kB +88.6 kB (new file) 🆕
packages/react-core/dist/copilotkit-DhONbYmz.cjs 89.7 kB +89.7 kB (new file) 🆕
packages/react-core/dist/copilotkit-IQO0VDZb.cjs 0 B -89.6 kB (removed) 🏆
packages/react-core/dist/index.cjs 16.9 kB -2 B (-0.01%)
packages/react-core/dist/v2/index.mjs 889 B +2 B (+0.23%)
packages/react-core/dist/v2/index.umd.js 89.5 kB +195 B (+0.22%)
ℹ️ View Unchanged
Filename Size
packages/a2ui-renderer/dist/_virtual/_rolldown/runtime.cjs 516 B
packages/a2ui-renderer/dist/a2ui-types.cjs 172 B
packages/a2ui-renderer/dist/a2ui-types.mjs 171 B
packages/a2ui-renderer/dist/index.cjs 842 B
packages/a2ui-renderer/dist/index.mjs 563 B
packages/a2ui-renderer/dist/index.umd.js 12.2 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/A2uiSurface.cjs 1.49 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/A2uiSurface.mjs 1.43 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/adapter.cjs 1.07 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/adapter.mjs 1.01 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/AudioPlayer.cjs 904 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/AudioPlayer.mjs 492 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Button.cjs 1 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Button.mjs 596 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Card.cjs 829 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Card.mjs 419 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/CheckBox.cjs 1.1 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/CheckBox.mjs 1.02 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/ChildList.cjs 799 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/ChildList.mjs 737 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/ChoicePicker.cjs 1.63 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/ChoicePicker.mjs 1.57 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Column.cjs 856 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Column.mjs 802 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/DateTimeInput.cjs 1.12 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/DateTimeInput.mjs 1.05 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Divider.cjs 842 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Divider.mjs 432 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Icon.cjs 877 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Icon.mjs 469 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Image.cjs 995 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Image.mjs 587 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/List.cjs 920 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/List.mjs 508 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Modal.cjs 1.19 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Modal.mjs 1.13 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Row.cjs 855 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Row.mjs 801 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Slider.cjs 1.06 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Slider.mjs 984 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Tabs.cjs 1.1 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Tabs.mjs 1.04 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Text.cjs 903 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Text.mjs 489 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/TextField.cjs 1.21 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/TextField.mjs 1.14 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Video.cjs 788 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Video.mjs 378 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/index.cjs 928 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/index.mjs 855 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/utils.cjs 579 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/utils.mjs 556 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Button.cjs 982 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Button.mjs 580 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/ChildList.cjs 800 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/ChildList.mjs 735 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Column.cjs 1.08 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Column.mjs 1.02 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Row.cjs 1.07 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Row.mjs 1.01 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Text.cjs 894 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Text.mjs 839 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/TextField.cjs 1.21 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/TextField.mjs 802 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/index.cjs 849 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/index.mjs 804 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/index.cjs 310 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/index.mjs 325 B
packages/a2ui-renderer/dist/react-renderer/catalog-utils.cjs 1.59 kB
packages/a2ui-renderer/dist/react-renderer/catalog-utils.mjs 1.52 kB
packages/a2ui-renderer/dist/react-renderer/core/A2UIProvider.cjs 1.5 kB
packages/a2ui-renderer/dist/react-renderer/core/A2UIProvider.mjs 1.42 kB
packages/a2ui-renderer/dist/react-renderer/core/A2UIRenderer.cjs 728 B
packages/a2ui-renderer/dist/react-renderer/core/A2UIRenderer.mjs 671 B
packages/a2ui-renderer/dist/react-renderer/create-catalog.cjs 1.35 kB
packages/a2ui-renderer/dist/react-renderer/create-catalog.mjs 1.28 kB
packages/a2ui-renderer/dist/react-renderer/hooks/useA2UI.cjs 316 B
packages/a2ui-renderer/dist/react-renderer/hooks/useA2UI.mjs 309 B
packages/a2ui-renderer/dist/react-renderer/index.cjs 399 B
packages/a2ui-renderer/dist/react-renderer/index.mjs 515 B
packages/a2ui-renderer/dist/react-renderer/lib/utils.cjs 236 B
packages/a2ui-renderer/dist/react-renderer/lib/utils.mjs 188 B
packages/a2ui-renderer/dist/react-renderer/styles/index.cjs 239 B
packages/a2ui-renderer/dist/react-renderer/styles/index.mjs 231 B
packages/a2ui-renderer/dist/react-renderer/theme/ThemeContext.cjs 436 B
packages/a2ui-renderer/dist/react-renderer/theme/ThemeContext.mjs 381 B
packages/core/dist/index.cjs 31.6 kB
packages/core/dist/index.mjs 31.4 kB
packages/core/dist/index.umd.js 34.5 kB
packages/react-core/dist/index.mjs 16.9 kB
packages/react-core/dist/index.umd.js 61.9 kB
packages/react-core/dist/v2/context.cjs 1.53 kB
packages/react-core/dist/v2/context.mjs 1.46 kB
packages/react-core/dist/v2/headless.cjs 10.3 kB
packages/react-core/dist/v2/headless.mjs 9.73 kB
packages/react-core/dist/v2/index.cjs 1.06 kB
packages/react-textarea/dist/index.cjs 18.1 kB
packages/react-textarea/dist/index.mjs 17.4 kB
packages/react-textarea/dist/index.umd.js 18.8 kB
packages/react-ui/dist/index.cjs 24.8 kB
packages/react-ui/dist/index.mjs 24.1 kB
packages/react-ui/dist/index.umd.js 26 kB
packages/runtime-client-gql/dist/_virtual/_rolldown/runtime.cjs 516 B
packages/runtime-client-gql/dist/client/conversion.cjs 1.52 kB
packages/runtime-client-gql/dist/client/conversion.mjs 1.45 kB
packages/runtime-client-gql/dist/client/CopilotRuntimeClient.cjs 1.48 kB
packages/runtime-client-gql/dist/client/CopilotRuntimeClient.mjs 1.44 kB
packages/runtime-client-gql/dist/client/types.cjs 701 B
packages/runtime-client-gql/dist/client/types.mjs 642 B
packages/runtime-client-gql/dist/graphql/@generated/gql.cjs 850 B
packages/runtime-client-gql/dist/graphql/@generated/gql.mjs 850 B
packages/runtime-client-gql/dist/graphql/@generated/graphql.cjs 2.4 kB
packages/runtime-client-gql/dist/graphql/@generated/graphql.mjs 2.36 kB
packages/runtime-client-gql/dist/graphql/definitions/mutations.cjs 740 B
packages/runtime-client-gql/dist/graphql/definitions/mutations.mjs 732 B
packages/runtime-client-gql/dist/graphql/definitions/queries.cjs 316 B
packages/runtime-client-gql/dist/graphql/definitions/queries.mjs 304 B
packages/runtime-client-gql/dist/index.cjs 679 B
packages/runtime-client-gql/dist/index.mjs 495 B
packages/runtime-client-gql/dist/index.umd.js 9.46 kB
packages/runtime-client-gql/dist/message-conversion/agui-to-gql.cjs 1.7 kB
packages/runtime-client-gql/dist/message-conversion/agui-to-gql.mjs 1.67 kB
packages/runtime-client-gql/dist/message-conversion/gql-to-agui.cjs 1.56 kB
packages/runtime-client-gql/dist/message-conversion/gql-to-agui.mjs 1.53 kB
packages/runtime-client-gql/dist/package.cjs 181 B
packages/runtime-client-gql/dist/package.mjs 116 B
packages/shared/dist/_virtual/_rolldown/runtime.cjs 516 B
packages/shared/dist/a2ui-prompts.cjs 2.85 kB
packages/shared/dist/a2ui-prompts.mjs 2.85 kB
packages/shared/dist/attachments/utils.cjs 1.74 kB
packages/shared/dist/attachments/utils.mjs 1.7 kB
packages/shared/dist/constants/index.cjs 362 B
packages/shared/dist/constants/index.mjs 345 B
packages/shared/dist/debug.cjs 454 B
packages/shared/dist/debug.mjs 452 B
packages/shared/dist/finalize-events.cjs 1.09 kB
packages/shared/dist/finalize-events.mjs 1.05 kB
packages/shared/dist/index.cjs 1.76 kB
packages/shared/dist/index.mjs 1.46 kB
packages/shared/dist/index.umd.js 20.2 kB
packages/shared/dist/logger.cjs 112 B
packages/shared/dist/logger.mjs 112 B
packages/shared/dist/package.cjs 181 B
packages/shared/dist/package.mjs 116 B
packages/shared/dist/standard-schema.cjs 740 B
packages/shared/dist/standard-schema.mjs 737 B
packages/shared/dist/telemetry/lambda-client.cjs 1.15 kB
packages/shared/dist/telemetry/lambda-client.mjs 1.14 kB
packages/shared/dist/telemetry/telemetry-client.cjs 1.33 kB
packages/shared/dist/telemetry/telemetry-client.mjs 1.28 kB
packages/shared/dist/telemetry/utils.cjs 321 B
packages/shared/dist/telemetry/utils.mjs 277 B
packages/shared/dist/transcription-errors.cjs 951 B
packages/shared/dist/transcription-errors.mjs 944 B
packages/shared/dist/utils/clipboard.cjs 407 B
packages/shared/dist/utils/clipboard.mjs 405 B
packages/shared/dist/utils/conditions.cjs 540 B
packages/shared/dist/utils/conditions.mjs 536 B
packages/shared/dist/utils/console-styling.cjs 1.24 kB
packages/shared/dist/utils/console-styling.mjs 1.22 kB
packages/shared/dist/utils/errors.cjs 4.51 kB
packages/shared/dist/utils/errors.mjs 4.41 kB
packages/shared/dist/utils/index.cjs 1.39 kB
packages/shared/dist/utils/index.mjs 1.65 kB
packages/shared/dist/utils/json-schema.cjs 1.97 kB
packages/shared/dist/utils/json-schema.mjs 1.91 kB
packages/shared/dist/utils/random-id.cjs 618 B
packages/shared/dist/utils/random-id.mjs 559 B
packages/shared/dist/utils/requests.cjs 706 B
packages/shared/dist/utils/requests.mjs 704 B
packages/shared/dist/utils/types.cjs 161 B
packages/shared/dist/utils/types.mjs 160 B
packages/voice/dist/_virtual/_rolldown/runtime.cjs 516 B
packages/voice/dist/index.cjs 175 B
packages/voice/dist/index.mjs 95 B
packages/voice/dist/index.umd.js 1.5 kB
packages/voice/dist/transcription/transcription-service-openai.cjs 495 B
packages/voice/dist/transcription/transcription-service-openai.mjs 434 B
packages/web-inspector/dist/assets/inspector-logo-icon.cjs 499 B
packages/web-inspector/dist/assets/inspector-logo-icon.mjs 434 B
packages/web-inspector/dist/assets/inspector-logo.cjs 4.32 kB
packages/web-inspector/dist/assets/inspector-logo.mjs 4.23 kB
packages/web-inspector/dist/index.cjs 43.3 kB
packages/web-inspector/dist/index.mjs 43.2 kB
packages/web-inspector/dist/index.umd.js 59.6 kB
packages/web-inspector/dist/lib/context-helpers.cjs 862 B
packages/web-inspector/dist/lib/context-helpers.mjs 830 B
packages/web-inspector/dist/lib/persistence.cjs 1.2 kB
packages/web-inspector/dist/lib/persistence.mjs 1.16 kB
packages/web-inspector/dist/lib/telemetry.cjs 1.67 kB
packages/web-inspector/dist/lib/telemetry.mjs 1.63 kB
packages/web-inspector/dist/styles/generated.cjs 6.41 kB
packages/web-inspector/dist/styles/generated.mjs 6.35 kB

compressed-size-action

@jpr5
jpr5 merged commit 63fd2f0 into main Jun 3, 2026
39 checks passed
@jpr5
jpr5 deleted the fix/gen-ui-interrupt-minimal branch June 3, 2026 21:36
jpr5 added a commit that referenced this pull request Jun 4, 2026
…e the suggestion send path

Replace the brittle `"activeRunCompletionPromise" in agent` probe + double
`as unknown as` casts in CopilotChat with a typed `RunCompletionAware`
contract plus an `isRunCompletionAware` type guard, both exported from core.
IntelligenceAgent now declares the property and implements the interface, so
the in-flight-run await is reachable without a cast and non-Intelligence
agents still degrade safely. Cast sites in the attachments/e2e tests and the
MockStepwiseAgent helper are updated to the typed accessor.

Factor the await-then-send logic into a shared `waitForActiveRunToSettle`
helper and call it from BOTH onSubmitInput and handleSelectSuggestion. This
closes the suggestion-path in-flight gap: selecting a suggestion mid-run no
longer pre-empts/aborts the active run (e.g. an interrupt RESUME) — the same
regression PR #5195 fixed for the typed-Enter path. Adds a red-green
regression test that parks the suggestion send on the in-flight promise.
jpr5 added a commit that referenced this pull request Jun 4, 2026
CopilotChatInput intentionally diverges while a run is in flight: Enter with
sendable text routes to SEND (the consecutive-interrupt unblock from #5195),
while the send/stop button always routes to STOP. Only a comment bound these
two behaviors together. Add a regression test asserting BOTH at once so a
future refactor cannot silently re-converge them (verified red against both a
button-sends-while-running and an Enter-also-stops mutation).
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.

1 participant