perf(compose): optimize chat UI recompositions and allocations#381
perf(compose): optimize chat UI recompositions and allocations#381yacosta738 wants to merge 3 commits into
Conversation
Co-authored-by: yacosta738 <33158051+yacosta738@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
📝 WalkthroughSummary by CodeRabbit
WalkthroughJetpack Compose runtime optimizations for the chat UI: extracted Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Deploying corvus with
|
| Latest commit: |
10105e4
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://3df13c74.corvus-42x.pages.dev |
| Branch Preview URL: | https://perf-compose-ui-optimization.corvus-42x.pages.dev |
✅ Contributor ReportUser: @yacosta738
Contributor Report evaluates based on public GitHub activity. Analysis period: 2025-04-02 to 2026-04-02 |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt (2)
283-295: 🧹 Nitpick | 🔵 TrivialMemoization keys may cause unnecessary re-creations.
The
sendButtonModifierremember block usesgradient(itself a rememberedBrush) as a key. SinceBrushdoesn't implement stable equality by default, this could defeat the caching. Consider usingcorvusColors.gradientPrimarydirectly as the key instead.♻️ Suggested fix
val sendButtonModifier = - remember(isEnabled, gradient, corvusColors.glowPurple) { + remember(isEnabled, corvusColors.gradientPrimary, corvusColors.glowPurple) { Modifier.size(48.dp) .shadow( elevation = 6.dp, shape = CircleShape, spotColor = if (isEnabled) corvusColors.glowPurple else Color.Gray, ) .clip(CircleShape) .background( if (isEnabled) gradient else Brush.linearGradient(listOf(Color.Gray, Color.Gray)) ) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt` around lines 283 - 295, The remember block for sendButtonModifier is using gradient (a Brush) as a key which can prevent proper memoization; change the remember keys to use stable values such as isEnabled and corvusColors.gradientPrimary (or corvusColors.glowPurple) instead of the gradient Brush, and then use the existing gradient value inside the block; update the remember call that creates sendButtonModifier to reference corvusColors.gradientPrimary (or another stable color/identifier) as the key while keeping the body unchanged so the modifier isn't recreated unnecessarily.
236-308:⚠️ Potential issue | 🟡 MinorAddress Detekt pipeline failures.
The pipeline reports:
LongParameterList: 7 parameters exceed the threshold of 6.LongMethod: 62 lines exceed the threshold of 60.Consider extracting the send button into a separate composable (e.g.,
SendButton) to reduce method length and improve modularity. Alternatively, suppress with justification if the team accepts this structure.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt` around lines 236 - 308, The ChatInputField composable currently violates Detekt rules (LongParameterList and LongMethod); fix by extracting the send-button UI into a new composable SendButton (take isEnabled, gradient/brush, glow color, onSend and value/trim as needed) and by collapsing multiple parameters into a single data holder (e.g., ChatInputFieldProps or ChatInputState) so ChatInputField signature no longer has 7 parameters; update callers to pass the new props object and move the send-button creation (remember block, Box, IconButton) into SendButton to reduce ChatInputField length below threshold and eliminate the LongParameterList violation.clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt (2)
284-326:⚠️ Potential issue | 🟡 MinorAcknowledge Detekt
LongParameterListonChatPanel.The pipeline flags 7 parameters exceeding the threshold of 6. Consider grouping related params into a data class (e.g., combine
state,bridgeState,pendingApprovalinto aChatPanelState) or suppress with justification.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt` around lines 284 - 326, The ChatPanel function currently has 7 parameters triggering Detekt LongParameterList; refactor by creating a small data holder (e.g., ChatPanelState) that groups related params such as state: ChatWorkspaceState, bridgeState: MobileBridgeUiState, and pendingApproval: RuntimeApprovalRequest? into one object and update the ChatPanel signature to accept that ChatPanelState plus the remaining args (messages, query, actions, modifier), then update all callers to construct and pass the new ChatPanelState (ensure MessageList still reads modelName from the grouped state, ApprovalCard receives the grouped pendingApproval, and ChatInputField checks grouped bridgeState.isChatReady). Alternatively, if grouping is not desired, add a targeted `@Suppress`("LongParameterList") annotation on the ChatPanel declaration with a short justification comment.
169-194:⚠️ Potential issue | 🟠 MajorAdd
bridgeStatetoactionsremember dependencies for correct state tracking.The
sendMessagefunction readsbridgeState.isChatReady(line 154), butbridgeStateis absent from therememberdependency list (lines 170–177). While Kotlin closures read current values at invocation time, Compose's dependency model requires explicit declaration when a memoized callback's behavior depends on state changes. Without this, the dependency graph is incomplete and the code violates Compose best practices—ifbridgeSnapshotchanges,actionsshould recalculate to ensure the closure captures the updated state.Fix: add bridgeState to remember keys
val actions = remember( + bridgeState, onRetryBridge, onLinkSurface, onStartSession, onResumeSession, onDisconnectReset, onApprove, onDeny, ) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt` around lines 169 - 194, The remember block that builds actions is missing bridgeState in its dependency keys, causing closures (notably sendMessage which reads bridgeState.isChatReady) to potentially capture stale state; update the remember(...) call that constructs ChatWorkspaceActions (the variable actions) to include bridgeState (or bridgeSnapshot) among its keys so the actions including sendMessage and the BridgeActions instance are recomputed when bridgeState changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt`:
- Around line 222-231: The current remember block in ChatWorkspace that computes
screenModifier using remember(modifier, colors.background) will frequently miss
cache when callers pass a new Modifier each recomposition; change it to only key
on stable inputs (e.g., colors.background) and compose the incoming modifier
after the remembered base modifier: remember(colors.background) { baseModifier =
fillMaxSize()... } then combine with the parameter (e.g.,
modifier.then(baseModifier)) so the heavy construction is memoized while still
respecting the caller's Modifier. Update references to screenModifier
accordingly in the Column.
- Around line 327-357: The vertical gradient Brush in MessageList is recreated
on every recomposition; memoize it with remember to avoid unnecessary
allocations by creating a remembered val (e.g., val backgroundBrush = remember {
Brush.verticalGradient(listOf(Color.White.copy(alpha = 0.05f),
Color.Transparent)) } ) and use that backgroundBrush in the Box modifier instead
of calling Brush.verticalGradient inline; reference: MessageList and the inline
Brush.verticalGradient call inside the Box.
---
Outside diff comments:
In
`@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt`:
- Around line 283-295: The remember block for sendButtonModifier is using
gradient (a Brush) as a key which can prevent proper memoization; change the
remember keys to use stable values such as isEnabled and
corvusColors.gradientPrimary (or corvusColors.glowPurple) instead of the
gradient Brush, and then use the existing gradient value inside the block;
update the remember call that creates sendButtonModifier to reference
corvusColors.gradientPrimary (or another stable color/identifier) as the key
while keeping the body unchanged so the modifier isn't recreated unnecessarily.
- Around line 236-308: The ChatInputField composable currently violates Detekt
rules (LongParameterList and LongMethod); fix by extracting the send-button UI
into a new composable SendButton (take isEnabled, gradient/brush, glow color,
onSend and value/trim as needed) and by collapsing multiple parameters into a
single data holder (e.g., ChatInputFieldProps or ChatInputState) so
ChatInputField signature no longer has 7 parameters; update callers to pass the
new props object and move the send-button creation (remember block, Box,
IconButton) into SendButton to reduce ChatInputField length below threshold and
eliminate the LongParameterList violation.
In
`@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt`:
- Around line 284-326: The ChatPanel function currently has 7 parameters
triggering Detekt LongParameterList; refactor by creating a small data holder
(e.g., ChatPanelState) that groups related params such as state:
ChatWorkspaceState, bridgeState: MobileBridgeUiState, and pendingApproval:
RuntimeApprovalRequest? into one object and update the ChatPanel signature to
accept that ChatPanelState plus the remaining args (messages, query, actions,
modifier), then update all callers to construct and pass the new ChatPanelState
(ensure MessageList still reads modelName from the grouped state, ApprovalCard
receives the grouped pendingApproval, and ChatInputField checks grouped
bridgeState.isChatReady). Alternatively, if grouping is not desired, add a
targeted `@Suppress`("LongParameterList") annotation on the ChatPanel declaration
with a short justification comment.
- Around line 169-194: The remember block that builds actions is missing
bridgeState in its dependency keys, causing closures (notably sendMessage which
reads bridgeState.isChatReady) to potentially capture stale state; update the
remember(...) call that constructs ChatWorkspaceActions (the variable actions)
to include bridgeState (or bridgeSnapshot) among its keys so the actions
including sendMessage and the BridgeActions instance are recomputed when
bridgeState changes.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 9a5d11cd-f3f8-40c6-989b-6521a1c81b07
📒 Files selected for processing (3)
.agents/journal/bolt-journal.mdclients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.ktclients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: sonar
- GitHub Check: pr-checks
- GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (2)
**/*.kt
⚙️ CodeRabbit configuration file
**/*.kt: Enforce null safety (no !!), structured concurrency, and non-blocking suspend code.
Prefer idiomatic Kotlin (expression bodies, sealed types, value classes when justified).
Verify tests follow TDD intent and use backtick test names where applicable.
Files:
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.ktclients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt
**/*
⚙️ CodeRabbit configuration file
**/*: Security first, performance second.
Validate input boundaries, auth/authz implications, and secret management.
Look for behavioral regressions, missing tests, and contract breaks across modules.
Files:
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.ktclients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt
🧠 Learnings (1)
📚 Learning: 2026-02-21T09:07:52.298Z
Learnt from: yacosta738
Repo: dallay/corvus PR: 62
File: .agents/journal/sentinnel-journal.md:1-1
Timestamp: 2026-02-21T09:07:52.298Z
Learning: Branding guideline: The intentional brand name for the security-first agent in the dallay/corvus repository is 'Sentinnel' (with double n). Do not treat it as a typo of 'Sentinel'. Ensure all agent-related docs and journals under .agents/journal consistently use 'Sentinnel' with double n.
Applied to files:
.agents/journal/bolt-journal.md
🪛 GitHub Actions: Scan with Detekt
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt
[error] 236-236: detekt LongParameterList: The function ChatInputField(...) has too many parameters. The current threshold is set to 6. [LongParameterList]
[error] 236-236: detekt LongMethod: The function ChatInputField is too long (62). The maximum length is 60. [LongMethod]
[error] 589-589: detekt CyclomaticComplexMethod: Function bridgeStateRecovery appears to be too complex based on Cyclomatic Complexity (complexity: 15). Defined complexity threshold for methods is set to '15' [CyclomaticComplexMethod]
[error] 1-1: detekt TooManyFunctions: File 'ChatComponents.kt' with '17' functions detected. Defined threshold inside files is set to '11' [TooManyFunctions]
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt
[error] 126-126: detekt LongParameterList: The function ChatWorkspace(...) has too many parameters. The current threshold is set to 6. [LongParameterList]
[error] 284-284: detekt LongParameterList: The function ChatPanel(...) has too many parameters. The current threshold is set to 6. [LongParameterList]
🔇 Additional comments (4)
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt (2)
154-156: LGTM — memoized gradient reduces allocations.Good use of
remember(corvusColors.gradientPrimary)to avoid recreating theBrushon every recomposition.Also applies to: 165-165
239-239: Breaking API change:onSendnow takes aStringparameter.The signature changed from
onSend: () -> UnittoonSend: (String) -> Unit. The caller inChatWorkspace.kt(line 321) has been correctly updated to passactions.onSend, which is properly typed as(String) -> Unitand bound to thesendMessagefunction.clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt (1)
161-167: LGTM — memoizeddisplayMessagesavoids list recreation on keystrokes.Correctly keyed on
messagesandstate.welcomeMessage..agents/journal/bolt-journal.md (1)
16-35: Documentation accurately reflects the code changes.The entry correctly describes:
MessageListextraction to isolate fromquerystaterememberusage for modifiers/brushesonSendsignature updateMinor: Entry dated 2025-05-24 (line 16) appears before the 2025-05-23 entry (line 36). If intentionally reverse-chronological, consider adding a note; otherwise, reorder for consistency.
…ions - Optimized `screenModifier` by isolating base modifiers and combining with `then()`. - Grouped `ChatPanel` and `ChatInputField` parameters into `Immutable` data classes to resolve `LongParameterList`. - Extracted `SendButton` and `MessageList` to reduce method length and isolate recompositions. - Added `bridgeState` to `actions` cache keys to ensure closure stability. - Memoized high-frequency brushes and modifiers with stable keys. Co-authored-by: yacosta738 <33158051+yacosta738@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt (1)
169-195:⚠️ Potential issue | 🟠 MajorAdd
onSendMessagetoactionsremember keys.
sendMessagecloses overonSendMessage. Without it in the dependency list, swapping the callback while other keys remain unchanged leavesactions.onSendinvoking the stale sender—a behavioral regression.Fix
val actions = remember( bridgeState, + onSendMessage, onRetryBridge, onLinkSurface, onStartSession,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt` around lines 169 - 195, The remember block creating actions in ChatWorkspace closes over sendMessage (used as ChatWorkspaceActions.onSend) but does not list onSendMessage in the remember keys, causing a stale callback; update the remember(...) dependency list for the actions variable to include onSendMessage so that when onSendMessage changes the remembered ChatWorkspaceActions (and its .onSend) are recomputed.clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt (1)
252-290:⚠️ Potential issue | 🟠 MajorMemoize the send callback to prevent unnecessary
SendButtonrecompositions.Line 289 creates a fresh lambda wrapper around
props.onSendon everyChatInputFieldrecomposition. When the user types, the callback reference changes, causingSendButtonto recompose despite no functional change. Line 252 also callstrim()on the hot path unnecessarily—useisNotBlank()for the enabled check.The suggested refactor with
rememberUpdatedStateandrememberis the standard Jetpack Compose pattern: it keeps the callback stable while still reading the latest value when invoked.Additionally, the behavior change (now trimming input before send) should have test coverage to prevent regressions.
Refactor to apply
+import androidx.compose.runtime.rememberUpdatedState ... - val isEnabled = props.enabled && props.value.trim().isNotBlank() + val isEnabled = props.enabled && props.value.isNotBlank() + val latestValue = rememberUpdatedState(props.value) + val latestOnSend = rememberUpdatedState(props.onSend) + val onSendClick = remember { + { latestOnSend.value(latestValue.value.trim()) } + } ... - onSend = { props.onSend(props.value.trim()) }, + onSend = onSendClick,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt` around lines 252 - 290, The ChatInputField creates a fresh lambda for SendButton on every recomposition and trims on the hot path; change the enabled check to use props.value.isNotBlank() (avoid trim on hot path) and stabilize the send callback by using rememberUpdatedState for props.onSend and then remember to create a single lambda that calls the current onSend with props.value.trim() when invoked (refer to SendButton and the onSend prop, and to the isEnabled computation); also add/adjust tests to cover that input is trimmed only at send time to prevent regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt`:
- Around line 235-240: Add unit tests that cover the new trimmed-send contract
for ChatInputFieldProps: verify that entering only whitespace does not call
onSend and that entering a value with surrounding spaces (e.g., " foo ") results
in a single onSend call with the trimmed string ("foo"). Target the component or
function that consumes ChatInputFieldProps (the chat input composable/renderer)
and simulate user typing and send action; assert onSend is not invoked for
whitespace-only input and invoked exactly once with the trimmed payload for
padded input. Name the tests using backtick-style descriptions (e.g.,
`whitespace-only input is not sent` and `padded input sends trimmed value once`)
and attach them to the appropriate test suite for the chat input UI code that
uses ChatInputFieldProps.
In `@pnpm-workspace.yaml`:
- Line 21: The change downgrades the happy-dom dependency to 20.8.8 which
reintroduces CVE-2026-34226; update the version entry "happy-dom: 20.8.8" back
to "happy-dom: 20.8.9" in the pnpm-workspace.yaml to restore the security patch,
and if you intentionally need a different version add a brief justification in
the PR explaining why the downgrade is necessary and how you mitigate the
vulnerability.
---
Outside diff comments:
In
`@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt`:
- Around line 252-290: The ChatInputField creates a fresh lambda for SendButton
on every recomposition and trims on the hot path; change the enabled check to
use props.value.isNotBlank() (avoid trim on hot path) and stabilize the send
callback by using rememberUpdatedState for props.onSend and then remember to
create a single lambda that calls the current onSend with props.value.trim()
when invoked (refer to SendButton and the onSend prop, and to the isEnabled
computation); also add/adjust tests to cover that input is trimmed only at send
time to prevent regressions.
In
`@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt`:
- Around line 169-195: The remember block creating actions in ChatWorkspace
closes over sendMessage (used as ChatWorkspaceActions.onSend) but does not list
onSendMessage in the remember keys, causing a stale callback; update the
remember(...) dependency list for the actions variable to include onSendMessage
so that when onSendMessage changes the remembered ChatWorkspaceActions (and its
.onSend) are recomputed.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 46341d98-1edb-4325-845f-eed95eb78468
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (4)
.github/workflows/fix-renovate.ymlclients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.ktclients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.ktpnpm-workspace.yaml
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: sonar
- GitHub Check: pr-checks
- GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (2)
**/*
⚙️ CodeRabbit configuration file
**/*: Security first, performance second.
Validate input boundaries, auth/authz implications, and secret management.
Look for behavioral regressions, missing tests, and contract breaks across modules.
Files:
pnpm-workspace.yamlclients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.ktclients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt
**/*.kt
⚙️ CodeRabbit configuration file
**/*.kt: Enforce null safety (no !!), structured concurrency, and non-blocking suspend code.
Prefer idiomatic Kotlin (expression bodies, sealed types, value classes when justified).
Verify tests follow TDD intent and use backtick test names where applicable.
Files:
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.ktclients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt
🪛 GitHub Actions: Scan with Detekt
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt
[error] 126-126: detekt [LongParameterList]: Function ChatWorkspace has too many parameters; current threshold is set to 6.
[error] 214-214: detekt [LongMethod]: Function ChatWorkspaceScreen is too long (64); maximum length is 60.
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt
[error] 601-601: detekt [CyclomaticComplexMethod]: Function bridgeStateRecovery too complex (complexity: 15); threshold set to 15.
[error] 1-1: detekt [TooManyFunctions]: File has '18' functions; threshold inside files is set to '11'.
[error] 66-66: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 87-87: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 129-129: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 153-153: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 178-178: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 188-188: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 245-245: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 295-295: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 323-323: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 356-356: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 405-405: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 424-424: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 457-457: detekt [FunctionNaming]: Function names should match pattern [a-z][a-zA-Z0-9]*.
[error] 101-101: detekt [MagicNumber]: This expression contains a magic number.
[error] 328-328: detekt [MagicNumber]: This expression contains a magic number.
[error] 334-334: detekt [MagicNumber]: This expression contains a magic number.
[error] 1-1: detekt [File too many functions]: File '/home/runner/work/corvus/corvus/clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt' with '18' functions detected; threshold set to '11'.
🔇 Additional comments (2)
.github/workflows/fix-renovate.yml (1)
157-157: Good hardening of the pre-write head validation.Including local HEAD mismatch in the same guard correctly blocks write actions when checkout drift occurs, reducing TOCTOU risk.
clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatWorkspace.kt (1)
341-365: Verify recomposition behavior for skippability.The performance benefit of this
MessageListextraction depends on whether strong skipping or immutable collections are used for themessagesparameter. Without confirmation, the recomposition win may be smaller than expected. As a secondary optimization concern (per guidelines, after security and behavioral regressions), verify thatChatMessageandList<ChatMessage>support stable/skippable composition before relying on this extraction for performance gains.
| @Immutable | ||
| data class ChatInputFieldProps( | ||
| val value: String, | ||
| val onValueChange: (String) -> Unit, | ||
| val onSend: (String) -> Unit, | ||
| val placeholder: String, |
There was a problem hiding this comment.
Add regression coverage for the new trimmed-send contract.
This API now changes send semantics, but there is no focused test here for whitespace-only input staying unsendable or for " foo " dispatching "foo" exactly once.
As per coding guidelines, "Verify tests follow TDD intent and use backtick test names where applicable."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@clients/composeApp/src/commonMain/kotlin/com/profiletailors/corvus/ui/chat/ChatComponents.kt`
around lines 235 - 240, Add unit tests that cover the new trimmed-send contract
for ChatInputFieldProps: verify that entering only whitespace does not call
onSend and that entering a value with surrounding spaces (e.g., " foo ") results
in a single onSend call with the trimmed string ("foo"). Target the component or
function that consumes ChatInputFieldProps (the chat input composable/renderer)
and simulate user typing and send action; assert onSend is not invoked for
whitespace-only input and invoked exactly once with the trimmed payload for
padded input. Name the tests using backtick-style descriptions (e.g.,
`whitespace-only input is not sent` and `padded input sends trimmed value once`)
and attach them to the appropriate test suite for the chat input UI code that
uses ChatInputFieldProps.
| astro: 6.0.8 | ||
| astro-vtbot: 2.1.12 | ||
| happy-dom: 20.8.9 | ||
| happy-dom: 20.8.8 |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Are there any known bugs or issues with happy-dom version 20.8.9 that would require downgrading to 20.8.8? What are the changes between happy-dom 20.8.8 and 20.8.9?
💡 Result:
No, there are no known bugs or issues with happy-dom version 20.8.9 that would require downgrading to 20.8.8. Version 20.8.9 is a patch release that fixes a security vulnerability present in prior versions (including 20.8.8), specifically an issue where cookies from the current origin were incorrectly forwarded to the target origin in fetch requests with credentials: "include". This vulnerability is documented as GHSA-w4gp-fjgq-3q4g and CVE-2026-34226. The change between 20.8.8 and 20.8.9 is solely this security fix, implemented in pull request #2117. No regressions or new bugs specific to 20.8.9 were found in GitHub issues opened after its release on 2026-03-26. Existing open issues predate 20.8.9 and are not attributed to it. Projects are observed upgrading from 20.8.8 to 20.8.9 without reported problems.
Citations:
- 1: https://github.com/capricorn86/happy-dom/releases/tag/v20.8.9
- 2: https://newreleases.io/project/npm/happy-dom/release/20.8.9
- 3: https://www.tenable.com/cve/CVE-2026-34226
- 4: https://newreleases.io/project/npm/happy-dom/release/20.8.8
- 5: fix: [#0] Fixes issue where cookies from the current origin was being forwarded to the target origin in fetch requests capricorn86/happy-dom#2117
🌐 Web query:
Are there any security vulnerabilities in happy-dom version 20.8.8 or 20.8.9?
💡 Result:
Yes, there is a known security vulnerability in happy-dom version 20.8.8. Version 20.8.8 fixes CVE-2026-33943 (GHSA-6q6h-j7hj-3r64), a high-severity code injection vulnerability in ECMAScriptModuleCompiler affecting versions up to 20.8.7. However, it is vulnerable to CVE-2026-34226 (GHSA-w4gp-fjgq-3q4g), a high-severity information disclosure vulnerability where fetch requests with credentials: "include" incorrectly attach cookies from the page origin instead of the target origin, allowing cross-origin cookie leakage. This was fixed in version 20.8.9. Version 20.8.9 has no known security vulnerabilities; it is listed as the latest non-vulnerable version by Snyk and patches the fetch cookie issue.
Citations:
- 1: https://security.snyk.io/package/npm/happy-dom/20.8.8
- 2: https://nvd.nist.gov/vuln/detail/CVE-2026-33943
- 3: GHSA-6q6h-j7hj-3r64
- 4: https://nvd.nist.gov/vuln/detail/CVE-2026-34226
- 5: https://www.resolvedsecurity.com/vulnerability-catalog/CVE-2026-34226
- 6: https://newreleases.io/project/npm/happy-dom/release/20.8.8
- 7: https://newreleases.io/project/npm/happy-dom/release/20.8.9
Do not downgrade happy-dom: version 20.8.8 contains an unpatched security vulnerability.
This downgrade from 20.8.9 to 20.8.8 reintroduces CVE-2026-34226, a high-severity information disclosure vulnerability where fetch requests with credentials: "include" incorrectly forward cookies from the current origin to target origins. Version 20.8.9 patched this issue; downgrading undoes the fix.
Additionally, this JavaScript dependency change is unrelated to the PR's Compose UI scope and lacks justification. Revert to 20.8.9.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pnpm-workspace.yaml` at line 21, The change downgrades the happy-dom
dependency to 20.8.8 which reintroduces CVE-2026-34226; update the version entry
"happy-dom: 20.8.8" back to "happy-dom: 20.8.9" in the pnpm-workspace.yaml to
restore the security patch, and if you intentionally need a different version
add a brief justification in the PR explaining why the downgrade is necessary
and how you mitigate the vulnerability.
|



Optimized the Compose Multiplatform Chat UI by isolating the message list recompositions and caching modifiers/brushes. This reduces main-thread work and GC pressure during user typing.
Key changes:
MessageListinChatWorkspace.ktto isolate it from high-frequencyquerystate changes.Modifierchains andBrushobjects inrememberblocks.ChatInputFieldto accept a stableonSendcallback, avoiding redundant lambda allocations..agents/journal/bolt-journal.md.PR created automatically by Jules for task 14414712215313423242 started by @yacosta738