Skip to content

feat(ui): add safe submission escape hatch - #66

Merged
w0wl0lxd merged 3 commits into
mainfrom
feat/submission-escape-hatch
Jul 22, 2026
Merged

w0wl0lxd merged 3 commits into
mainfrom
feat/submission-escape-hatch

Conversation

@w0wl0lxd

Copy link
Copy Markdown
Owner

Summary

Paints submitted messages before persistence/provider startup and adds a 2.5-second Escape window that restores text and images only when cancellation wins before any request can be sent. Adds FIFO, crash-recovery, MCP, shell-context, and compaction-safe persistence semantics.

Type

  • feat
  • fix
  • docs
  • style
  • refactor
  • perf
  • test
  • build
  • ci
  • chore
  • revert

Changelog fragment

  • Added changelog.d/submission-escape-hatch.added.md

Test plan

  • cargo test -p n00n-agent -p n00n-ui -p n00n-storage
  • Rust formatting and diff checks
  • Targeted cancellation, persistence, MCP, FIFO, draw-failure, and restart tests

AI use

N/A.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4fab1327-2b43-4dad-90ae-8f667bd7cf89

📥 Commits

Reviewing files that changed from the base of the PR and between 6d2fdd1 and 45d49f1.

📒 Files selected for processing (18)
  • changelog.d/submission-escape-hatch.added.md
  • n00n-agent/src/agent/run.rs
  • n00n-agent/src/cancel.rs
  • n00n-agent/src/lib.rs
  • n00n-storage/src/sessions.rs
  • n00n-ui/src/agent/agent_loop.rs
  • n00n-ui/src/agent/shared_queue.rs
  • n00n-ui/src/app/mod.rs
  • n00n-ui/src/app/queue.rs
  • n00n-ui/src/app/session.rs
  • n00n-ui/src/app/session_state.rs
  • n00n-ui/src/app/shell.rs
  • n00n-ui/src/app/tests.rs
  • n00n-ui/src/chat.rs
  • n00n-ui/src/components/messages/mod.rs
  • n00n-ui/src/components/mod.rs
  • n00n-ui/src/event_loop.rs
  • n00n-ui/src/storage_writer.rs

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Submitted messages now appear before startup work begins.
    • A brief Escape window lets you restore unsent text and images for editing.
    • Queued submissions and images are restored across session reloads and restarts.
    • Background submissions wait for persistence and successful rendering before dispatch.
  • Bug Fixes
    • Improved FIFO queue handling under slow or failed persistence.
    • Cancellation now safely prevents provider requests and preserves relevant transcript state.
    • Session saves avoid overwriting newer changes.
  • Tests
    • Added coverage for cancellation, restoration, persistence failures, rendering failures, and restart recovery.

Walkthrough

Submitted messages now pass through pre-dispatch cancellation, draw and persistence gates. Queued submissions preserve full input data, survive session restoration, support short Escape-based recovery, and use revision-aware storage ordering.

Changes

Submission lifecycle

Layer / File(s) Summary
Pre-dispatch cancellation and rollback
n00n-agent/..., n00n-ui/src/agent/agent_loop.rs
Adds atomic cancellation gates, conditional rollback, MCP retrieval cancellation handling, and provider-call regression tests.
Queue readiness and Escape restoration
n00n-ui/src/agent/shared_queue.rs, n00n-ui/src/app/*, n00n-ui/src/components/*, n00n-ui/src/chat.rs, n00n-ui/src/components/messages/*, n00n-ui/src/app/tests.rs
Tracks dispatch readiness, defers blocked entries, restores pending submissions on Escape, restores shell output, truncates transcripts, and validates lifecycle behavior.
Queued submission snapshots and revisioned persistence
n00n-storage/src/sessions.rs, n00n-ui/src/app/session.rs, n00n-ui/src/app/session_state.rs, n00n-ui/src/storage_writer.rs
Persists queued inputs, images, modes, prompts, and revisions while preventing stale snapshots from overwriting newer state.
Draw-gated event-loop dispatch
n00n-ui/src/event_loop.rs
Dispatches painted submissions after successful terminal draws, processes persistence completions, and preserves pending submissions during shutdown.

Estimated code review effort: 5 (Critical) | ~120 minutes

Poem

I’m a rabbit with queued words in tow,
Through gates and draws they safely go.
Escape brings drafts back from the night,
While revisions keep their order right.
Hop, persist, and let them flow!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/submission-escape-hatch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e209b46d0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread n00n-ui/src/event_loop.rs
Comment on lines +1118 to +1122
if !rt.app.accepts_submission_persistence(&completion.dispatch) {
rt.app
.queue
.remove_submission(completion.dispatch.submission_id);
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Persist the restored state after rejecting a saved dispatch

When an Escape restore wins after the persistence job has already written the gated snapshot, this branch runs because the dispatch is no longer accepted, but it only removes the in-memory queue item. The just-written session still contains the hidden queued_submissions entry (and not the restored input draft), so a crash before some later save will resurrect and send the message that the user already restored for editing.

Useful? React with 👍 / 👎.

Comment thread n00n-ui/src/app/mod.rs
return false;
}

self.queue.remove_submission(submission_id);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep restore from unblocking stale queued turns

When the user restores the first paint-gated submission while another turn-end item is already queued behind it (for example via Tab or a session API prompt during the 2.5s window), removing only this submission makes the later ready item the queue head. The app then increments run_id and goes idle, but the agent loop can still pop and send that stale queued item to the provider, with its events filtered as stale and potentially persisted from shared history later.

Useful? React with 👍 / 👎.

w0wl0lxd added 2 commits July 22, 2026 05:32
Resolve merge conflicts by integrating main's OpenAiOptions refactoring
with the PR's safe submission escape hatch logic.

Changes:
- n00n-ui/src/agent/agent_loop.rs: Add openai_options field and parameter,
  pass to resolve_compaction_model and AgentParams
- n00n-ui/src/event_loop.rs: Add openai_options to EventLoopParams and
  SpawnCtx, use from_model_with_openai_options throughout, fix API call
  signatures (transition_plan, pick_model_for_lua, spawn_shell, start_btw)
- Preserve PR's pre_dispatch_gate and stage_submission_preamble logic
Resolve merge conflicts by integrating main's OpenAiOptions refactoring
with the PR's safe submission escape hatch logic.

Changes:
- n00n-ui/src/agent/agent_loop.rs: Add openai_options field and parameter,
  pass to resolve_compaction_model and AgentParams
- n00n-ui/src/event_loop.rs: Add openai_options to EventLoopParams and
  SpawnCtx, use from_model_with_openai_options throughout, fix API call
  signatures (transition_plan, pick_model_for_lua, spawn_shell, start_btw)
- Preserve PR's pre_dispatch_gate and stage_submission_preamble logic
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@w0wl0lxd
w0wl0lxd merged commit 51f57e8 into main Jul 22, 2026
15 of 24 checks passed

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Criterion

Details
Benchmark suite Current: 45d49f1 Previous: 6d2fdd1 Ratio
fib/jit_mlua_hook 6439394 ns/iter (± 187660) 7958148 ns/iter (± 273463) 0.81
fib/jit_watchdog 2494311 ns/iter (± 27053) 2209761 ns/iter (± 5772) 1.13
fib/jit_none 2363944 ns/iter (± 29366) 2274300 ns/iter (± 14767) 1.04
fib/interp_mlua_hook 7604957 ns/iter (± 39953) 8778073 ns/iter (± 146298) 0.87
fib/interp_watchdog 3774703 ns/iter (± 32638) 3555445 ns/iter (± 17892) 1.06
fib/interp_none 3675183 ns/iter (± 8839) 3550878 ns/iter (± 4757) 1.04
buffer_rw/jit_mlua_hook 555176 ns/iter (± 2130) 802983 ns/iter (± 1062) 0.69
buffer_rw/jit_watchdog 167807 ns/iter (± 228) 108497 ns/iter (± 958) 1.55
buffer_rw/jit_none 167675 ns/iter (± 248) 108496 ns/iter (± 191) 1.55
buffer_rw/interp_mlua_hook 1067914 ns/iter (± 34953) 1150234 ns/iter (± 17243) 0.93
buffer_rw/interp_watchdog 641364 ns/iter (± 11430) 496528 ns/iter (± 1622) 1.29
buffer_rw/interp_none 643807 ns/iter (± 8279) 496680 ns/iter (± 2076) 1.30
splash_render_120x40 73965 ns/iter (± 2447) 63094 ns/iter (± 165) 1.17
splash_render_200x60 103569 ns/iter (± 14812) 113709 ns/iter (± 10576) 0.91

This comment was automatically generated by workflow using github-action-benchmark.

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