Skip to content

Fix shell UX edge cases#199

Merged
Nek-12 merged 16 commits into
mainfrom
fixes-1.2
May 5, 2026
Merged

Fix shell UX edge cases#199
Nek-12 merged 16 commits into
mainfrom
fixes-1.2

Conversation

@Nek-12

@Nek-12 Nek-12 commented May 5, 2026

Copy link
Copy Markdown
Member

Summary

  • clarify shell/RPC cancellation messages
  • render ask_question Markdown correctly
  • drain queued messages after idle and preserve queue order
  • ring terminal bell only when eligible completions need attention
  • add file-read line count context for direct partial reads

Verification

  • ./scripts/test.sh ./...
  • ./scripts/build.sh --output /Users/nek/Developer/builder-cli/bin/builder
  • push preflight: formatting, go vet, go build, tests

Summary by CodeRabbit

  • New Features

    • Terminal focus tracking to suppress or defer notification bells and expose focus state in the UI
    • Better multi-line/Markdown rendering for ask-question prompts
    • Notifications for compaction completion and smarter queued-input handling
    • File-read context: shows total line counts for partial file reads
  • Bug Fixes

    • Normalized/corrected cancellation messages
    • Improved macOS service restart/recovery when bootstrap fails
  • Documentation

    • Updated command post-processing and skill-creation guidance

@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@Nek-12 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 22 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d380f745-4fb9-41ec-9aa1-793290c443b0

📥 Commits

Reviewing files that changed from the base of the PR and between 55d579c and afab0af.

📒 Files selected for processing (4)
  • cli/app/ui_input_submission.go
  • cli/app/ui_turn_completion_bell_test.go
  • server/tools/shell/postprocess/file_read_context.go
  • server/tools/shell/postprocess/runner_test.go
📝 Walkthrough

Walkthrough

This PR adds terminal-focus tracking and focus-aware bell/compaction notifications; extends UI queued-input and compaction flow (pre-submit/front/back queuing, deferred compaction notifications); improves ask-question multi-line/markdown rendering; adds a file-read context post-processor; normalizes cancellation error messages across tool/manager/gateway/client; and changes macOS launchd bootstrap recovery to replace stale loaded services.

Changes

Terminal focus, bell hooks, UI wiring & queued-input / compaction flow

Layer / File(s) Summary
Data Shape
cli/app/terminal_focus.go, cli/app/ui_state.go
New terminalFocusState with thread-safe known/focused flags; uiPresentationFeatureState stores terminalFocus; uiInputFeatureState adds compactionOrigin.
Hook Interface
cli/app/turn_queue_hooks.go
Added OnUserCompactionCompleted(queueDrained bool) to turnQueueHook.
Bell Implementation
cli/app/terminal_bell.go, cli/app/terminal_bell_test.go
bellHooks accepts optional focused func() bool, tracks pendingCompaction/lastCompletionMessage, uses notifyIfUnfocused, and adds compaction completion handling and tests (including focused/unfocused and defer-until-drain cases).
Runtime / Wiring
cli/app/runtime_factory.go, cli/app/embedded_server.go
terminalFocus instantiated and wired into runtimeWiring; newBellHooks receives terminalFocus.FocusedForAttention.
UI Model / Focus Events
cli/app/ui.go, cli/app/ui_focus_test.go
UI option WithUITerminalFocusState, uiModel.Update handles tea.FocusMsg/tea.BlurMsg, exposes TerminalFocused()/TerminalFocusKnown(); unit test added.
Queued Input & Compaction Flow
cli/app/ui_input_queue.go, cli/app/ui_input_submission.go, cli/app/ui_input_controller_commands.go, cli/app/ui_input_controller_keys.go
Added resumeQueuedInputsAfterIdleRuntime(), pre-submit queue-position (front/back) support, uiCompactionOrigin tracking, routes /compact through queued compaction paths, notifies turnQueueHook on compaction completion (conditional on origin and queueDrained), and updates Enter-key/queue flush behavior.
UI Loop / Options
cli/app/ui_loop.go, cli/app/ui_terminal_cursor_test.go
Wires terminalFocus into model construction and enables tea.WithReportFocus(); tests updated to expect additional option.
Integration Tests
cli/app/ui_part4_test.go, cli/app/ui_turn_completion_bell_test.go
Extensive tests added/updated to cover queued-drain hydration, pre-submit compaction ordering, bell deferral semantics, and compaction failure/cancel paths.

Ask-question multi-line and markdown rendering

Layer / File(s) Summary
Prompt text normalization
cli/app/ui_ask_controller.go
Added askQuestionPromptTextLines to preserve multi-line questions and normalize newline variants; prompt rendering now uses per-line entries.
TUI markdown gating
cli/tui/markdown_renderer.go
Expanded isMarkdownRole to include RenderIntentToolQuestion and RenderIntentToolQuestionError.
TUI rendering
cli/tui/model_rendering_tools.go, cli/tui/model_test.go
renderAskQuestionMarkdownLines attempts markdown rendering (falls back to wrapping); flattenAskQuestionEntryWithSymbol uses it; TUI test added for large markdown question snapshot.
Tests
cli/app/ui_test.go
Added test verifying logical-line preservation and wrapping for large Markdown prompts.

File-read context post-processing (shell tools)

Layer / File(s) Summary
New processor
server/tools/shell/postprocess/file_read_context.go
Adds fileReadContextProcessor that classifies certain direct file-read commands (sed, head, tail, PowerShell Get-Content), counts lines for small regular files (≤1 MiB, rejects NUL), and prepends "[Total line count: N]\n" for partial/uncertain reads.
Processor registration
server/tools/shell/postprocess/runner.go
NewRunner registers fileReadContextProcessor{} alongside existing builtins.
Tests
server/tools/shell/postprocess/runner_test.go
New tests cover partial vs full reads, large/binary-file skipping, pipeline/composed-command skipping, and helpers for test setup.

Cancellation/error messaging across manager, tools, gateway, and client

Layer / File(s) Summary
Manager / error type
server/tools/shell/manager_types.go, server/tools/shell/manager.go
Introduced exported PollingCanceledError{SessionID, Active} with Unwrap() errorcontext.Canceled; Manager.WriteStdin returns PollingCanceledError when polling is canceled.
Tool error formatting
server/tools/shell/tool.go, server/tools/shell/exec_command_tool.go, server/tools/shell/write_stdin_tool.go
Added formatToolCallError and cancellationMessage helpers; tools use formatToolCallError(...) for consistent messages.
Gateway mapping
server/transport/gateway.go, server/transport/gateway_test.go
protocolError normalizes context.Canceled to "request canceled by client" when appropriate; tests validate mapping and round-trip over websocket RPC.
Client-side normalization
shared/client/remote_rpc.go, shared/client/remote_test.go
Added requestCanceledError (normalizes message and unwraps to context.Canceled) and changed protocolError to return it for canceled requests; tests added.
Tests / Tool coverage
server/tools/shell/tool_test.go
Added tests verifying write_stdin cancellation behavior and that cancellation messages do not leak raw context.Canceled text; helper for waiting on background entry interaction and shell-quoting added.

Launchd service bootstrap/reload recovery (macOS)

Layer / File(s) Summary
Implementation
cli/builder/service_backend_darwin.go
On transient launchctl bootstrap error code 5, replace stale loaded service via launchctl bootout, wait for old server shutdown (waitForLaunchdServiceShutdown), then retry bootstrap; removed prior kickstart fallback; added tunables and polling loop.
Tests
cli/builder/service_backend_darwin_test.go
Updated/added tests to expect bootout+retry behavior for start/restart flows, reload waiting-for-shutdown semantics, and integration-gated restart test; helpers added for test scaffolding.

Minor updates & docs

Layer / File(s) Summary
Docs
docs/src/content/docs/command-postprocessing.md
Added Built-ins section documenting go test collapsing and file-read total-line-count behavior and applicability rules.
Prompts
prompts/skills/skill-creator/SKILL.md, prompts/worktree_mode_prompt.md
Rewrote skill-creator guidance and adjusted worktree prompt placeholder wording.
Tests expectation updates
cli/app/ui_terminal_cursor_test.go
Updated expected UI program options count reflecting focus-reporting option.

Sequence Diagram(s)

sequenceDiagram
    participant Terminal
    participant UI as UI Model
    participant Focus as Terminal Focus
    participant Bell as Bell Hooks
    participant Runtime as Turn Queue Hook

    Terminal->>UI: tea.FocusMsg / tea.BlurMsg
    UI->>Focus: MarkFocused / MarkBlurred
    Focus-->>UI: Focus State Updated

    UI->>UI: dispatchQueuedInput (queued /compact)
    UI->>UI: startQueuedCompaction
    UI->>Runtime: Notify compaction started

    Runtime-->>Bell: OnTurnQueueDrained
    Bell->>Focus: FocusedForAttention?

    alt Terminal Focused
        Bell-->>UI: Suppress Notification
    else Terminal Unfocused
        Bell->>Terminal: notifyIfUnfocused (Compaction Finished)
    end

    UI->>Runtime: OnUserCompactionCompleted(queueDrained)
    Runtime->>Bell: Handle Completion
Loading
sequenceDiagram
    participant User
    participant Client
    participant Gateway
    participant Tool as Tool (write_stdin / exec_command)
    participant Manager

    User->>Client: RPC request (with cancel)
    Client->>Gateway: send request
    Gateway->>Tool: invoke tool
    Tool->>Manager: background write / start
    Manager-->>Tool: context.Canceled / canceled during polling

    Tool->>Tool: formatToolCallError(..., err)
    Tool-->>Gateway: ErrorResultWith(formatted message)
    Gateway->>Client: protocol.ErrCodeRequestCanceled + "request canceled by client"
    Client->>User: requestCanceledError (unwraps to context.Canceled)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • respawn-app/builder#167: modifies macOS launchd service backend and bootstrap/bootout sequences — directly related to launchd bootstrap changes.
  • respawn-app/builder#26: touches compaction/notification wiring and turn-queue hooks — related to compaction and bell-hook changes.
  • respawn-app/builder#150: modifies terminal bell/turn-queue logic — related to bell hook refactor and tests.

Suggested labels: autorelease

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'Fix shell UX edge cases' is too vague and does not clearly summarize the main changes. The PR involves multiple distinct areas (terminal focus/bell behavior, markdown rendering, input queuing, cancellation messages, file-read context, and launchd service handling) but the title only uses the generic term 'edge cases' without specifying which aspects are addressed. Consider using a more specific title that highlights the primary changes, such as 'Improve shell UX: terminal focus tracking, queued input handling, and cancellation messaging' or similar that better conveys the scope of work.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fixes-1.2

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
shared/client/remote_rpc.go (1)

417-421: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle empty request-canceled messages before applying the generic fallback.

ErrCodeRequestCanceled currently receives "protocol request failed" when resp.Message is empty, so it no longer normalizes to the cancellation message.

Proposed fix
 func protocolError(resp *protocol.ResponseError) error {
 	if resp == nil {
 		return nil
 	}
 	message := strings.TrimSpace(resp.Message)
-	if message == "" {
-		message = "protocol request failed"
-	}
+	if resp.Code == protocol.ErrCodeRequestCanceled {
+		return requestCanceledError{message: message}
+	}
+	if message == "" {
+		message = "protocol request failed"
+	}
 	switch resp.Code {
@@
-	case protocol.ErrCodeRequestCanceled:
-		return requestCanceledError{message: message}
 	default:
 		return errors.New(message)
 	}
 }

Also applies to: 450-451

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shared/client/remote_rpc.go` around lines 417 - 421, The code currently sets
a generic fallback message when resp.Message is empty which overwrites the
cancellation normalization; update the logic in remote_rpc.go so that before
applying the generic "protocol request failed" fallback you check if resp.Code
== ErrCodeRequestCanceled (and resp.Message is empty) and set message = "request
canceled" (or the normalized cancellation text) instead, and only then apply the
generic fallback for other codes; make the same change around the other
occurrence referenced (near the second block at the 450-451 area) so canceled
responses preserve the cancellation message.
cli/builder/service_backend_darwin_test.go (1)

107-203: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add tests for fallback failure branches (bootout fail and retry bootstrap fail).

The new recovery behavior is tested for success, but not for its two failure exits. That leaves part of the new business logic unguarded.

As per coding guidelines: {server,shared,cli,cmd}/**/*.go: “All business logic must be covered by tests; production code must be written to be unit-testable”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/builder/service_backend_darwin_test.go` around lines 107 - 203, Add unit
tests covering the two failure branches when recovering from a transient
bootstrap error: one where the fallback bootout command fails and one where the
retry bootstrap also fails. Duplicate the existing
TestLaunchdRestartIfInstalledReplacesStaleLoadedServiceAfterTransientBootstrapError
and TestLaunchdStartReplacesStaleLoadedServiceAfterTransientBootstrapError
patterns but modify the captured command handler in
captureLaunchdServiceCommands to return an error/result for the "launchctl
bootout gui/.../<serviceLaunchdLabel>" case (simulate failure) and another
variant where the second "launchctl bootstrap gui/... <path>" returns a non-zero
Code/Err (simulate retry bootstrap failure), then assert that
serviceSubcommand(...{"restart","--if-installed"}) and
(launchdServiceBackend{}).Start(...) return the expected non-zero exit/code
error and that *calls records the expected sequence (including failed
bootout/failed bootstrap) using countLaunchdCommand and the same helpers used by
the existing tests.
cli/app/ui_input_submission.go (1)

39-44: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Prepending here can reorder older queued work.

m.queued can already contain earlier follow-ups while pendingQueuedDrainAfterHydration is waiting on transcript sync. In that state, a fresh Enter hits this branch and inserts the new submit at index 0, so it runs before the older queued items. That breaks FIFO and the queue-order preservation this PR is trying to restore.

Please keep direct submits behind existing queued work, or split the “active pre-submit item” from m.queued so only queued-drain paths reinsert at the front.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/app/ui_input_submission.go` around lines 39 - 44, The current prepend
(m.queued = append([]string{text}, m.queued...)) can make a new direct submit
jump ahead of earlier queued items; change the behavior so direct submits do not
reorder FIFO: either append the new text to the end of m.queued (m.queued =
append(m.queued, text)) so it runs after existing queued work, or stop mutating
m.queued here and keep the submit only in m.pendingPreSubmitText (i.e., split
the “active pre-submit item” from m.queued) so only the queued-drain code
reinserts items at the front; update the branch in m.hasRuntimeClient() that
touches preSubmitCheckToken, pendingPreSubmitText, and m.queued accordingly.
🧹 Nitpick comments (1)
server/tools/shell/postprocess/runner_test.go (1)

162-168: 💤 Low value

Add clarifying comments to document intentional asymmetry in test file setup

The asymmetry between TestRunnerBuiltinFileReadAddsTotalLineCountForPartialSed (line 89, WITH trailing newline) and TestRunnerBuiltinFileReadAddsTotalLineCountForHeadTailAwkAndPowerShell (line 162, WITHOUT trailing newline) is intentional—the tests verify correct line counting in both POSIX-compliant and non-POSIX file scenarios. The implementation's countSmallRegularFileLines() correctly handles both cases via its if seenBytes && !endedWithNewline check.

Consider adding a comment to line 162 briefly explaining the intentional difference:

// File without trailing newline — verify non-POSIX file handling
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/tools/shell/postprocess/runner_test.go` around lines 162 - 168, Add a
brief clarifying comment above the test file creation at the writeTextFile call
in TestRunnerBuiltinFileReadAddsTotalLineCountForHeadTailAwkAndPowerShell
explaining that this file intentionally omits a trailing newline to exercise
non-POSIX behavior (e.g., "// File without trailing newline — verify non-POSIX
file handling"); reference the asymmetry with
TestRunnerBuiltinFileReadAddsTotalLineCountForPartialSed and note that
countSmallRegularFileLines() handles the seenBytes && !endedWithNewline case.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cli/builder/service_backend_darwin_test.go`:
- Around line 158-160: Replace the substring-based assertion using
strings.Contains on stdout with an exact-line equality or structured check:
capture/produce the expected full line (e.g., expected := "Restarted Builder
background service.") and assert stdout.String() == expected (or scan stdout
with bufio.Scanner and assert one scanned line equals expected). Update the test
assertion that currently references stdout and strings.Contains to use the exact
equality/line match so the check in the test function verifies the precise
output rather than a substring.

In `@prompts/skills/skill-creator/SKILL.md`:
- Line 6: Change the opening sentence in SKILL.md from "Skills is a specialized
technical documentation standard..." to use correct subject-verb agreement by
replacing "Skills is" with "Skills are", i.e., update the opening definition
line that currently starts with the phrase "Skills is …" so it reads "Skills are
…".
- Line 61: Update the ambiguous header rule in SKILL.md to clarify that the
prohibition is against adding a global H1 header and against inserting extra
blank lines after headers; replace "Do not add spaces after headers" with a
clearer phrase such as "Do not include a global H1 header like `# My Skill`. Do
not add extra blank lines immediately after header lines." Reference this change
in the SKILL.md header rules so skill creators follow standard Markdown spacing
(e.g., `# Title`) while avoiding unwanted blank lines.

In `@server/tools/shell/postprocess/file_read_context.go`:
- Around line 69-80: The classifier is mislabeling many full-file awk
invocations as partial reads because awkProgramMentionsNR is too broad; change
classifyFileRead to stop handling awk variants by removing or disabling the
"awk", "gawk", "mawk", "nawk" case (i.e., no longer call classifyAwkFileRead
from classifyFileRead and instead return (fileReadCandidate{}, false) for awk),
and update or remove classifyAwkFileRead/awkProgramMentionsNR usage until a
safer, bounded-read allowlist is implemented; ensure tests reflect that awk
commands are treated as unknown/unsupported rather than partial reads.

In `@server/transport/gateway_test.go`:
- Around line 125-129: Replace the substring checks that use strings.Contains on
err.Error() with exact equality assertions against the precomputed message
variable: instead of checking if err == nil || !strings.Contains(err.Error(),
"Canceled polling by user, process active") and similarly rejecting "context
canceled" substrings, assert err != nil and err.Error() == message (and remove
the second Contains check). Update the t.Fatalf messages to reflect exact
mismatch (e.g., expected %q, got %q) and reference the err variable and message
variable in the assertions.

In `@shared/client/remote_test.go`:
- Around line 9-10: Remove the substring-based assertion that uses
strings.Contains to check for cancellation; instead assert the exact
cancellation error/message. Locate the test assertions in remote_test.go that
call strings.Contains(err.Error(), "...canceled...") (also around the region
mentioned ~642-647) and replace them with an exact comparison to the canonical
cancellation value (for example compare err.Error() == context.Canceled.Error()
or assert.Equal(t, context.Canceled, errors.Unwrap(err)) as appropriate), and
then remove the now-unused "strings" import.

---

Outside diff comments:
In `@cli/app/ui_input_submission.go`:
- Around line 39-44: The current prepend (m.queued = append([]string{text},
m.queued...)) can make a new direct submit jump ahead of earlier queued items;
change the behavior so direct submits do not reorder FIFO: either append the new
text to the end of m.queued (m.queued = append(m.queued, text)) so it runs after
existing queued work, or stop mutating m.queued here and keep the submit only in
m.pendingPreSubmitText (i.e., split the “active pre-submit item” from m.queued)
so only the queued-drain code reinserts items at the front; update the branch in
m.hasRuntimeClient() that touches preSubmitCheckToken, pendingPreSubmitText, and
m.queued accordingly.

In `@cli/builder/service_backend_darwin_test.go`:
- Around line 107-203: Add unit tests covering the two failure branches when
recovering from a transient bootstrap error: one where the fallback bootout
command fails and one where the retry bootstrap also fails. Duplicate the
existing
TestLaunchdRestartIfInstalledReplacesStaleLoadedServiceAfterTransientBootstrapError
and TestLaunchdStartReplacesStaleLoadedServiceAfterTransientBootstrapError
patterns but modify the captured command handler in
captureLaunchdServiceCommands to return an error/result for the "launchctl
bootout gui/.../<serviceLaunchdLabel>" case (simulate failure) and another
variant where the second "launchctl bootstrap gui/... <path>" returns a non-zero
Code/Err (simulate retry bootstrap failure), then assert that
serviceSubcommand(...{"restart","--if-installed"}) and
(launchdServiceBackend{}).Start(...) return the expected non-zero exit/code
error and that *calls records the expected sequence (including failed
bootout/failed bootstrap) using countLaunchdCommand and the same helpers used by
the existing tests.

In `@shared/client/remote_rpc.go`:
- Around line 417-421: The code currently sets a generic fallback message when
resp.Message is empty which overwrites the cancellation normalization; update
the logic in remote_rpc.go so that before applying the generic "protocol request
failed" fallback you check if resp.Code == ErrCodeRequestCanceled (and
resp.Message is empty) and set message = "request canceled" (or the normalized
cancellation text) instead, and only then apply the generic fallback for other
codes; make the same change around the other occurrence referenced (near the
second block at the 450-451 area) so canceled responses preserve the
cancellation message.

---

Nitpick comments:
In `@server/tools/shell/postprocess/runner_test.go`:
- Around line 162-168: Add a brief clarifying comment above the test file
creation at the writeTextFile call in
TestRunnerBuiltinFileReadAddsTotalLineCountForHeadTailAwkAndPowerShell
explaining that this file intentionally omits a trailing newline to exercise
non-POSIX behavior (e.g., "// File without trailing newline — verify non-POSIX
file handling"); reference the asymmetry with
TestRunnerBuiltinFileReadAddsTotalLineCountForPartialSed and note that
countSmallRegularFileLines() handles the seenBytes && !endedWithNewline case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 69af86d7-dca2-4b01-82e8-3f417cbc2d54

📥 Commits

Reviewing files that changed from the base of the PR and between c413c30 and 5568093.

📒 Files selected for processing (38)
  • cli/app/embedded_server.go
  • cli/app/runtime_factory.go
  • cli/app/terminal_bell.go
  • cli/app/terminal_bell_test.go
  • cli/app/terminal_focus.go
  • cli/app/turn_queue_hooks.go
  • cli/app/ui.go
  • cli/app/ui_ask_controller.go
  • cli/app/ui_focus_test.go
  • cli/app/ui_input_queue.go
  • cli/app/ui_input_submission.go
  • cli/app/ui_loop.go
  • cli/app/ui_part4_test.go
  • cli/app/ui_state.go
  • cli/app/ui_terminal_cursor_test.go
  • cli/app/ui_test.go
  • cli/app/ui_turn_completion_bell_test.go
  • cli/builder/service_backend_darwin.go
  • cli/builder/service_backend_darwin_test.go
  • cli/tui/markdown_renderer.go
  • cli/tui/model_rendering_tools.go
  • cli/tui/model_test.go
  • docs/src/content/docs/command-postprocessing.md
  • prompts/skills/skill-creator/SKILL.md
  • prompts/worktree_mode_prompt.md
  • server/tools/shell/exec_command_tool.go
  • server/tools/shell/manager.go
  • server/tools/shell/manager_types.go
  • server/tools/shell/postprocess/file_read_context.go
  • server/tools/shell/postprocess/runner.go
  • server/tools/shell/postprocess/runner_test.go
  • server/tools/shell/tool.go
  • server/tools/shell/tool_test.go
  • server/tools/shell/write_stdin_tool.go
  • server/transport/gateway.go
  • server/transport/gateway_test.go
  • shared/client/remote_rpc.go
  • shared/client/remote_test.go

Comment thread cli/builder/service_backend_darwin_test.go Outdated
Comment thread prompts/skills/skill-creator/SKILL.md
Comment thread prompts/skills/skill-creator/SKILL.md Outdated
Comment thread server/tools/shell/postprocess/file_read_context.go Outdated
Comment thread server/transport/gateway_test.go Outdated
Comment thread shared/client/remote_test.go Outdated

@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: 09d48897cb

ℹ️ 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 server/tools/shell/postprocess/file_read_context.go Outdated

@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: 55d579c998

ℹ️ 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 server/tools/shell/postprocess/file_read_context.go

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (3)
prompts/skills/skill-creator/SKILL.md (1)

67-67: ⚡ Quick win

Clarify external-reference policy for workspace skills to avoid conflicting interpretation.

This line can be read as forbidding non-repo references, but Line 66 and the “Good” example in this same bullet allow public URLs. Tighten wording so the restriction clearly applies to machine-local file paths, not canonical web docs.

✏️ Proposed wording tweak
-- For workspace skills, only point to files in the skill directory and the repository (workspace). For global skills, avoid pointing to any machine-local files outside the skill dir.
+- For workspace skills, point file paths only to files in the skill directory and the repository (workspace). Public canonical URLs are allowed when they are the source of truth. For global skills, avoid pointing to any machine-local files outside the skill dir.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prompts/skills/skill-creator/SKILL.md` at line 67, The bullet that begins
"For workspace skills, only point to files in the skill directory and the
repository (workspace)..." is ambiguous; update this sentence in SKILL.md to
explicitly restrict only "machine-local file paths" (e.g., ~/Desktop/file,
C:\Users\...) while allowing canonical public URLs and repository paths;
rephrase to something like: "For workspace skills, do not reference
machine-local file paths outside the skill directory (e.g.,
~/Desktop/sample.sql); public URLs and repository-relative files are allowed."
Ensure the original examples ("Bad: 'Example query at
~/Desktop/sample.sql'"/"Good: 'FlowMVI docs index https://...'") remain
consistent with the new wording.
server/tools/shell/postprocess/file_read_context.go (1)

17-17: ⚡ Quick win

Replace the \x00-prefixed sentinel string with a typed sed-script item.

unknownSedScript is a string sentinel placed into the same []string as user-supplied sed scripts, and classifySedScripts/classifySedScript re-discriminate via string equality (line 329). The \x00 prefix makes collisions practically impossible, but the pattern conflates "literal script" and "from-file (unknown content)" into one string-typed channel that has to be re-interpreted later — exactly the kind of brittle string-based metadata the guidelines call out.

A small typed wrapper makes the intent explicit and removes the sentinel comparison entirely:

♻️ Suggested refactor sketch
type sedScriptItem struct {
    text       string
    fromFile   bool // -f / --file=...: contents unknown
}

// classifySedFileRead collects []sedScriptItem instead of []string.
// classifySedScripts iterates and treats fromFile as classified-but-not-full
// without needing a sentinel value.

As per coding guidelines, "Develop type-safe data structures and store structured data or metadata that can be reliably extracted instead of using brittle string-based logic."

Also applies to: 253-326

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/tools/shell/postprocess/file_read_context.go` at line 17, Replace the
brittle sentinel string unknownSedScript with a small typed wrapper
sedScriptItem and change the sed-script collection from []string to
[]sedScriptItem: define type sedScriptItem { text string; fromFile bool }
(fromFile true indicates "-f/--file" unknown contents), update all producers to
push sedScriptItem values instead of injecting unknownSedScript, and update
classifySedScripts and classifySedScript to use the fromFile flag and text field
(remove any string-equality checks against unknownSedScript) so callers can
distinguish literal scripts vs. file-origin scripts in a type-safe way.
cli/app/ui_input_controller_keys.go (1)

179-183: Consider moving handleEnteredSlashCommandInput call to after draft capture for consistency.

While the current code is safe—handleEnteredSlashCommandInput internally captures and restores the draft even when it calls clearInput()—the new busy path (lines 179–183) calls this function before the draft capture at line 188, whereas the non-busy path calls it after (line 204). This inconsistency in ordering makes the control flow less clear.

Moving the busy-path call to after line 188 would align both paths and make the draft-handling strategy uniform across the function, improving code readability without any functional change.

The busy-state safety concern is addressed: the function has a guard (if m.busy && !command.RunWhileBusy) that prevents non-runnable commands from executing while busy, and the commands that can run while busy do not trigger new submissions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/app/ui_input_controller_keys.go` around lines 179 - 183, The call to
handleEnteredSlashCommandInput is invoked in the busy branch before the draft is
captured, causing inconsistent ordering versus the non-busy path; move the
handleEnteredSlashCommandInput invocation in the m.busy branch so it runs after
the draft capture/restore logic (the same place it is called in the non-busy
branch) to make draft handling consistent across both paths—ensure you keep the
existing clearInput() behavior intact and preserve the m.busy guard and checks
inside handleEnteredSlashCommandInput.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/tools/shell/postprocess/file_read_context.go`:
- Around line 39-82: The classifier functions (classifyFileRead ->
classifySedFileRead/classifyHeadTailFileRead/classifyPowerShellGetContent)
assume ParsedArgs[0] is the command name and call args[1:], which can drop a
real arg if callers set CommandName and ParsedArgs independently; add a boundary
validation before calling classifyFileRead: ensure len(req.ParsedArgs) > 0 &&
req.ParsedArgs[0] == req.CommandName and return early if not, or alternatively
change classifyFileRead signature to accept argsWithoutCmd (and update callers)
and document the invariant in normalizeRequest; reference classifyFileRead,
classifySedFileRead, classifyHeadTailFileRead, classifyPowerShellGetContent,
ParsedArgs and CommandName while making the change.

---

Nitpick comments:
In `@cli/app/ui_input_controller_keys.go`:
- Around line 179-183: The call to handleEnteredSlashCommandInput is invoked in
the busy branch before the draft is captured, causing inconsistent ordering
versus the non-busy path; move the handleEnteredSlashCommandInput invocation in
the m.busy branch so it runs after the draft capture/restore logic (the same
place it is called in the non-busy branch) to make draft handling consistent
across both paths—ensure you keep the existing clearInput() behavior intact and
preserve the m.busy guard and checks inside handleEnteredSlashCommandInput.

In `@prompts/skills/skill-creator/SKILL.md`:
- Line 67: The bullet that begins "For workspace skills, only point to files in
the skill directory and the repository (workspace)..." is ambiguous; update this
sentence in SKILL.md to explicitly restrict only "machine-local file paths"
(e.g., ~/Desktop/file, C:\Users\...) while allowing canonical public URLs and
repository paths; rephrase to something like: "For workspace skills, do not
reference machine-local file paths outside the skill directory (e.g.,
~/Desktop/sample.sql); public URLs and repository-relative files are allowed."
Ensure the original examples ("Bad: 'Example query at
~/Desktop/sample.sql'"/"Good: 'FlowMVI docs index https://...'") remain
consistent with the new wording.

In `@server/tools/shell/postprocess/file_read_context.go`:
- Line 17: Replace the brittle sentinel string unknownSedScript with a small
typed wrapper sedScriptItem and change the sed-script collection from []string
to []sedScriptItem: define type sedScriptItem { text string; fromFile bool }
(fromFile true indicates "-f/--file" unknown contents), update all producers to
push sedScriptItem values instead of injecting unknownSedScript, and update
classifySedScripts and classifySedScript to use the fromFile flag and text field
(remove any string-equality checks against unknownSedScript) so callers can
distinguish literal scripts vs. file-origin scripts in a type-safe way.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d9016530-b942-42c1-9764-f79ed339a30a

📥 Commits

Reviewing files that changed from the base of the PR and between 5568093 and 55d579c.

📒 Files selected for processing (15)
  • cli/app/ui_input_controller_commands.go
  • cli/app/ui_input_controller_keys.go
  • cli/app/ui_input_queue.go
  • cli/app/ui_input_submission.go
  • cli/app/ui_part4_test.go
  • cli/builder/service_backend_darwin.go
  • cli/builder/service_backend_darwin_test.go
  • docs/src/content/docs/command-postprocessing.md
  • docs/src/content/docs/server.md
  • prompts/skills/skill-creator/SKILL.md
  • server/tools/shell/postprocess/file_read_context.go
  • server/tools/shell/postprocess/runner_test.go
  • server/transport/gateway_test.go
  • shared/client/remote_rpc.go
  • shared/client/remote_test.go
✅ Files skipped from review due to trivial changes (1)
  • docs/src/content/docs/command-postprocessing.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • cli/app/ui_input_queue.go
  • shared/client/remote_test.go
  • shared/client/remote_rpc.go
  • cli/app/ui_part4_test.go
  • server/tools/shell/postprocess/runner_test.go

Comment thread server/tools/shell/postprocess/file_read_context.go

@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: 2340a3dedf

ℹ️ 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 cli/app/ui_input_submission.go

@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: b4e0a9c2fa

ℹ️ 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 server/tools/shell/postprocess/file_read_context.go
@Nek-12 Nek-12 merged commit 00906d8 into main May 5, 2026
5 checks passed
@Nek-12 Nek-12 deleted the fixes-1.2 branch May 5, 2026 13:50
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