Skip to content

fix: parse remote-control session log entries without validation errors#216

Open
rymalia wants to merge 1 commit into
d-kimuson:mainfrom
rymalia:fix/bridge-session-schema-entries
Open

fix: parse remote-control session log entries without validation errors#216
rymalia wants to merge 1 commit into
d-kimuson:mainfrom
rymalia:fix/bridge-session-schema-entries

Conversation

@rymalia

@rymalia rymalia commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Claude Code v2.1.145+ emits new session-log entries for its remote-control / bridge feature (continue a session on phone or web). Claude Code Viewer rejected these lines with schema validation errors. This adds/extends the Zod schemas and threads the two new metadata entry types through every consumer.

Issue Entry Fix
#210 last-prompt with leafUuid lastPrompt made optional, added optional leafUuid
#211 mode ({"type":"mode","mode":"normal"}) new ModeEntrySchema
#212 bridge-session new BridgeSessionEntrySchema
#213 system / subtype: "bridge_status" new variant before the catch-all

mode and bridge-session are treated like sibling metadata entries (permission-mode, last-prompt) — filtered out of conversation rendering, sidechains, sync, and export. The satisfies never guard in conversationRows.ts and the .cwd/.isSidechain access sites made several of these edits type-forced.

Testing

  • Full suite: 980/980 pass (schema dir 106/106); 4 e2e tests use the exact raw JSON from each issue, narrowing on .type to prove the intended union member matched.
  • typecheck clean; oxlint + oxfmt clean.

Closes #210
Closes #211
Closes #212
Closes #213

Summary by CodeRabbit

  • New Features

    • Added support for new conversation entry types, including mode, bridge-session, and bridge status records.
    • Improved compatibility with newer and older last-prompt formats.
  • Bug Fixes

    • Prevented these new entry types from breaking conversation lists, search, export, and session syncing.
    • Improved parsing so valid bridge-related records are accepted and displayed consistently.

Claude Code v2.1.145+ emits new session log entries for its remote-control /
bridge feature (continue a session on phone or web). Claude Code Viewer
rejected these lines with schema validation errors:

- last-prompt entries now use leafUuid instead of lastPrompt (d-kimuson#210)
- mode entries, e.g. {"type":"mode","mode":"normal"} (d-kimuson#211)
- bridge-session entries linking to a bridge session id (d-kimuson#212)
- system entries with subtype "bridge_status" (d-kimuson#213)

Add/extend Zod schemas for each and treat the two new metadata entry types
(mode, bridge-session) like sibling metadata entries so they are filtered out
of conversation rendering, sidechains, sync, and export.
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds schema and test coverage for last-prompt, mode, bridge-session, and bridge_status entries. Updates server-side sync/export filtering and session-list/sidechain handling to recognize or skip the new entry types.

Changes

Conversation entry support and filtering

Layer / File(s) Summary
Entry schemas and union wiring
src/lib/conversation-schema/entry/LastPromptEntrySchema.ts, src/lib/conversation-schema/entry/ModeEntrySchema.ts, src/lib/conversation-schema/entry/BridgeSessionEntrySchema.ts, src/lib/conversation-schema/entry/SystemEntrySchema.ts, src/lib/conversation-schema/index.ts
Adds optional leafUuid, new mode and bridge-session entry schemas, and the bridge_status system subtype to the conversation and system unions.
Schema validation tests
src/lib/conversation-schema/ConversationSchema.test.ts, src/lib/conversation-schema/entry/LastPromptEntrySchema.test.ts, src/lib/conversation-schema/entry/ModeEntrySchema.test.ts, src/lib/conversation-schema/entry/BridgeSessionEntrySchema.test.ts, src/lib/conversation-schema/entry/SystemEntrySchema.test.ts
Adds parsing coverage for the new entry shapes and the bridge_status system subtype.
Server-side filtering
src/server/core/sync/services/SyncService.ts, src/server/core/session/services/ExportService.ts
Skips mode and bridge-session entries during CWD extraction and excludes them from sidechain/export agent detection.
Session list and sidechain handling
src/web/app/projects/[projectId]/sessions/[sessionId]/components/conversationList/ConversationList.tsx, src/web/app/projects/[projectId]/sessions/[sessionId]/components/conversationList/conversationRows.ts, src/web/app/projects/[projectId]/sessions/[sessionId]/hooks/useSidechain.ts
Adds keys for mode and bridge-session, filters them from rendering and sidechain state, and normalizes nullable lastPrompt search text.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I nibbled the logs and hopped in delight,
last-prompt grew a leafUuid, crisp and light.
Mode and bridge-session took their place,
while bridge_status parsed with grace.
thump-thump — into the code I go!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding support for new remote-control session log entries to avoid schema validation errors.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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

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.

@rymalia rymalia marked this pull request as ready for review June 24, 2026 20:50

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

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)
src/lib/conversation-schema/entry/SystemEntrySchema.test.ts (1)

1-122: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Use testPlatformLayer-based Effect test setup in this test file.

The test additions continue the direct Vitest pattern instead of the required reusable Effect test layers.

As per coding guidelines: "**/*.test.{ts,tsx}: Use reusable Effect test layers from src/testing/layers/ for testing, with testPlatformLayer as the foundation".

🤖 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 `@src/lib/conversation-schema/entry/SystemEntrySchema.test.ts` around lines 1 -
122, The SystemEntrySchema tests are still using the direct Vitest setup instead
of the required reusable Effect test layers. Update the
SystemEntrySchema.test.ts suite to use the shared testing layers from
src/testing/layers with testPlatformLayer as the base, and wire the existing
describe/test cases through that Effect-based setup while keeping the
SystemEntrySchema assertions unchanged.

Source: Coding guidelines

src/lib/conversation-schema/ConversationSchema.test.ts (1)

1-223: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Adopt reusable Effect test layers (testPlatformLayer) for this suite.

The new cases are added in direct Vitest form, which diverges from the required test-layer pattern.

As per coding guidelines: "**/*.test.{ts,tsx}: Use reusable Effect test layers from src/testing/layers/ for testing, with testPlatformLayer as the foundation".

🤖 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 `@src/lib/conversation-schema/ConversationSchema.test.ts` around lines 1 - 223,
The ConversationSchema test suite is using plain Vitest setup instead of the
required reusable Effect test-layer pattern. Update the tests in
ConversationSchema.test to use the shared layers from src/testing/layers/, with
testPlatformLayer as the base foundation, and wire the suite through the
existing Effect testing helpers rather than direct ad hoc parsing assertions.
Keep the current test cases, but adapt the suite structure so it follows the
project’s standard layer-based test setup.

Source: Coding guidelines

src/server/core/session/services/ExportService.ts (1)

375-394: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove as cast and use a type predicate in the filter.

Line 394 uses as type casting in a backend TS file; this violates the repository rule and can hide narrowing mistakes.

Proposed fix
-  const sidechainConversations = conversations.filter(
-    (conv) =>
+  const sidechainConversations = conversations.filter(
+    (
+      conv,
+    ): conv is Extract<Conversation, { type: "user" | "assistant" | "system" }> =>
       conv.type !== "summary" &&
       conv.type !== "file-history-snapshot" &&
       conv.type !== "queue-operation" &&
       conv.type !== "progress" &&
       conv.type !== "custom-title" &&
       conv.type !== "ai-title" &&
       conv.type !== "agent-name" &&
       conv.type !== "agent-setting" &&
       conv.type !== "pr-link" &&
       conv.type !== "last-prompt" &&
       conv.type !== "permission-mode" &&
       conv.type !== "mode" &&
       conv.type !== "bridge-session" &&
       conv.isSidechain === true,
-  ) as Array<Extract<Conversation, { type: "user" | "assistant" | "system" }>>;
+  );

As per coding guidelines: "**/*.{ts,tsx}: Never use as type casting in ANY context including test code (explain the problem to the user instead)".

🤖 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 `@src/server/core/session/services/ExportService.ts` around lines 375 - 394,
The buildSidechainData helper is using an unsafe as cast after filtering
conversations, which violates the TypeScript casting rule. Replace the current
filter in buildSidechainData with a type predicate that narrows Conversation to
the allowed user, assistant, and system variants while preserving the existing
sidechain conditions, so the return type SidechainData is satisfied without any
as assertion. Use the existing buildSidechainData symbol and the
conversations.filter logic to locate the change.

Source: Coding guidelines

src/lib/conversation-schema/entry/LastPromptEntrySchema.test.ts (1)

1-47: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Migrate this test to reusable Effect test layers (testPlatformLayer).

This file uses plain Vitest directly instead of the required shared test layer foundation.

As per coding guidelines: "**/*.test.{ts,tsx}: Use reusable Effect test layers from src/testing/layers/ for testing, with testPlatformLayer as the foundation".

🤖 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 `@src/lib/conversation-schema/entry/LastPromptEntrySchema.test.ts` around lines
1 - 47, This test currently uses plain Vitest imports in
LastPromptEntrySchema.test.ts instead of the shared Effect testing foundation.
Update the test setup to use the reusable layers from src/testing/layers/, with
testPlatformLayer as the base, and wire the suite through the Effect test
utilities rather than direct describe/test usage. Keep the existing
LastPromptEntrySchema assertions, but migrate the test structure so it follows
the shared layer pattern used by other tests in the repo.

Source: Coding guidelines

🤖 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 `@src/lib/conversation-schema/entry/BridgeSessionEntrySchema.ts`:
- Around line 5-10: Make BridgeSessionEntrySchema strict so unknown fields on
bridge-session entries are rejected instead of silently stripped. Update the
z.object definition in BridgeSessionEntrySchema to use z.strictObject while
keeping the existing type, sessionId, bridgeSessionId, and lastSequenceNum
fields unchanged.

In `@src/lib/conversation-schema/entry/LastPromptEntrySchema.ts`:
- Around line 7-10: The LastPromptEntrySchema currently allows a last-prompt
entry with no payload fields because both lastPrompt and leafUuid are optional.
Update the LastPromptEntrySchema definition so that at least one of those fields
is required, using the schema’s z.object shape and any appropriate
refinement/union logic, so valid entries always carry a prompt reference or leaf
reference.

---

Outside diff comments:
In `@src/lib/conversation-schema/ConversationSchema.test.ts`:
- Around line 1-223: The ConversationSchema test suite is using plain Vitest
setup instead of the required reusable Effect test-layer pattern. Update the
tests in ConversationSchema.test to use the shared layers from
src/testing/layers/, with testPlatformLayer as the base foundation, and wire the
suite through the existing Effect testing helpers rather than direct ad hoc
parsing assertions. Keep the current test cases, but adapt the suite structure
so it follows the project’s standard layer-based test setup.

In `@src/lib/conversation-schema/entry/LastPromptEntrySchema.test.ts`:
- Around line 1-47: This test currently uses plain Vitest imports in
LastPromptEntrySchema.test.ts instead of the shared Effect testing foundation.
Update the test setup to use the reusable layers from src/testing/layers/, with
testPlatformLayer as the base, and wire the suite through the Effect test
utilities rather than direct describe/test usage. Keep the existing
LastPromptEntrySchema assertions, but migrate the test structure so it follows
the shared layer pattern used by other tests in the repo.

In `@src/lib/conversation-schema/entry/SystemEntrySchema.test.ts`:
- Around line 1-122: The SystemEntrySchema tests are still using the direct
Vitest setup instead of the required reusable Effect test layers. Update the
SystemEntrySchema.test.ts suite to use the shared testing layers from
src/testing/layers with testPlatformLayer as the base, and wire the existing
describe/test cases through that Effect-based setup while keeping the
SystemEntrySchema assertions unchanged.

In `@src/server/core/session/services/ExportService.ts`:
- Around line 375-394: The buildSidechainData helper is using an unsafe as cast
after filtering conversations, which violates the TypeScript casting rule.
Replace the current filter in buildSidechainData with a type predicate that
narrows Conversation to the allowed user, assistant, and system variants while
preserving the existing sidechain conditions, so the return type SidechainData
is satisfied without any as assertion. Use the existing buildSidechainData
symbol and the conversations.filter logic to locate the change.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 486a21d8-f942-446f-9c23-47fd60772baf

📥 Commits

Reviewing files that changed from the base of the PR and between 3c8eb62 and 99ab170.

📒 Files selected for processing (15)
  • src/lib/conversation-schema/ConversationSchema.test.ts
  • src/lib/conversation-schema/entry/BridgeSessionEntrySchema.test.ts
  • src/lib/conversation-schema/entry/BridgeSessionEntrySchema.ts
  • src/lib/conversation-schema/entry/LastPromptEntrySchema.test.ts
  • src/lib/conversation-schema/entry/LastPromptEntrySchema.ts
  • src/lib/conversation-schema/entry/ModeEntrySchema.test.ts
  • src/lib/conversation-schema/entry/ModeEntrySchema.ts
  • src/lib/conversation-schema/entry/SystemEntrySchema.test.ts
  • src/lib/conversation-schema/entry/SystemEntrySchema.ts
  • src/lib/conversation-schema/index.ts
  • src/server/core/session/services/ExportService.ts
  • src/server/core/sync/services/SyncService.ts
  • src/web/app/projects/[projectId]/sessions/[sessionId]/components/conversationList/ConversationList.tsx
  • src/web/app/projects/[projectId]/sessions/[sessionId]/components/conversationList/conversationRows.ts
  • src/web/app/projects/[projectId]/sessions/[sessionId]/hooks/useSidechain.ts

Comment on lines +5 to +10
export const BridgeSessionEntrySchema = z.object({
type: z.literal("bridge-session"),
sessionId: z.string(),
bridgeSessionId: z.string(),
lastSequenceNum: z.number().optional(),
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Files ==\n'
git ls-files 'src/lib/conversation-schema/**/*Schema.ts' 'src/lib/conversation-schema/**/*.ts' | sed -n '1,200p'

printf '\n== Outline: BridgeSessionEntrySchema.ts ==\n'
ast-grep outline src/lib/conversation-schema/entry/BridgeSessionEntrySchema.ts --view expanded || true

printf '\n== BridgeSessionEntrySchema.ts ==\n'
cat -n src/lib/conversation-schema/entry/BridgeSessionEntrySchema.ts

printf '\n== Search for strict schemas in conversation-schema ==\n'
rg -n "strictObject|\.strict\(" src/lib/conversation-schema -g '*.ts' -g '*.tsx' || true

printf '\n== Search for z.object in conversation-schema ==\n'
rg -n "z\.object\(" src/lib/conversation-schema -g '*.ts' -g '*.tsx' || true

Repository: d-kimuson/claude-code-viewer

Length of output: 8302


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== BridgeSessionEntrySchema usages ==\n'
rg -n "BridgeSessionEntrySchema|BridgeSessionEntry" src -g '*.ts' -g '*.tsx'

printf '\n== BaseEntrySchema ==\n'
cat -n src/lib/conversation-schema/entry/BaseEntrySchema.ts

printf '\n== Related entry schemas with exported object shape ==\n'
for f in \
  src/lib/conversation-schema/entry/AgentNameEntrySchema.ts \
  src/lib/conversation-schema/entry/AgentSettingEntrySchema.ts \
  src/lib/conversation-schema/entry/AiTitleEntrySchema.ts \
  src/lib/conversation-schema/entry/AssistantEntrySchema.ts \
  src/lib/conversation-schema/entry/AttachmentEntrySchema.ts \
  src/lib/conversation-schema/entry/CustomTitleEntrySchema.ts \
  src/lib/conversation-schema/entry/FileHIstorySnapshotEntrySchema.ts \
  src/lib/conversation-schema/entry/LastPromptEntrySchema.ts \
  src/lib/conversation-schema/entry/ModeEntrySchema.ts \
  src/lib/conversation-schema/entry/PermissionModeEntrySchema.ts \
  src/lib/conversation-schema/entry/PrLinkEntrySchema.ts \
  src/lib/conversation-schema/entry/ProgressEntrySchema.ts \
  src/lib/conversation-schema/entry/QueueOperationEntrySchema.ts \
  src/lib/conversation-schema/entry/SummaryEntrySchema.ts \
  src/lib/conversation-schema/entry/SystemEntrySchema.ts \
  src/lib/conversation-schema/entry/UserEntrySchema.ts
do
  echo "== $f =="
  sed -n '1,40p' "$f"
done

Repository: d-kimuson/claude-code-viewer

Length of output: 11381


Make BridgeSessionEntrySchema strict.
z.object(...) strips unknown keys, so extra fields on "bridge-session" entries are accepted and discarded instead of rejected. Use z.strictObject(...) here.

🤖 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 `@src/lib/conversation-schema/entry/BridgeSessionEntrySchema.ts` around lines 5
- 10, Make BridgeSessionEntrySchema strict so unknown fields on bridge-session
entries are rejected instead of silently stripped. Update the z.object
definition in BridgeSessionEntrySchema to use z.strictObject while keeping the
existing type, sessionId, bridgeSessionId, and lastSequenceNum fields unchanged.

Source: Coding guidelines

Comment on lines 7 to +10
export const LastPromptEntrySchema = z.object({
type: z.literal("last-prompt"),
lastPrompt: z.string(),
lastPrompt: z.string().optional(),
leafUuid: z.string().optional(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Require at least one payload field for last-prompt entries.

Line 9 and Line 10 being optional allows { type: "last-prompt", sessionId } with no prompt reference, which weakens schema guarantees.

Proposed fix
 export const LastPromptEntrySchema = z.object({
   type: z.literal("last-prompt"),
   lastPrompt: z.string().optional(),
   leafUuid: z.string().optional(),
   sessionId: z.string(),
-});
+}).refine((entry) => entry.lastPrompt !== undefined || entry.leafUuid !== undefined, {
+  error: "Either lastPrompt or leafUuid is required",
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const LastPromptEntrySchema = z.object({
type: z.literal("last-prompt"),
lastPrompt: z.string(),
lastPrompt: z.string().optional(),
leafUuid: z.string().optional(),
export const LastPromptEntrySchema = z.object({
type: z.literal("last-prompt"),
lastPrompt: z.string().optional(),
leafUuid: z.string().optional(),
sessionId: z.string(),
}).refine((entry) => entry.lastPrompt !== undefined || entry.leafUuid !== undefined, {
error: "Either lastPrompt or leafUuid is required",
});
🤖 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 `@src/lib/conversation-schema/entry/LastPromptEntrySchema.ts` around lines 7 -
10, The LastPromptEntrySchema currently allows a last-prompt entry with no
payload fields because both lastPrompt and leafUuid are optional. Update the
LastPromptEntrySchema definition so that at least one of those fields is
required, using the schema’s z.object shape and any appropriate refinement/union
logic, so valid entries always carry a prompt reference or leaf reference.

@rymalia

rymalia commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @coderabbitai. Declining all four recommendations and leaving the PR as-is:

  • strict bridge-session / required last-prompt field: these session-log entry schemas are intentionally lenient (see SystemEntrySchema.ts: "surfacing the entry beats a hard schema reject"). No sibling entry schema uses strictObject, and CC adds fields frequently — strictness would reintroduce the validation-error class this PR fixes.
  • testPlatformLayer in the test files: that guideline targets Effect-TS code with side effects; these are pure Zod parsing tests. All existing schema tests in this directory use plain Vitest, which these follow.
  • as cast in ExportService.ts: pre-existing code (note the deliberate oxlint-disable on the preceding line) — this PR only adds mode/bridge-session to the existing filter, not the cast. The suggested type predicate is equally unchecked: the filter doesn't exclude attachment (which also has isSidechain), so it asserts the same user | assistant | system narrowing without improving soundness. A correct fix would change behavior and is out of scope for this PR.

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@rymalia: Understood — all three points are well-reasoned. I'll withdraw the relevant comments and record the design decisions below.

( ˘︹˘ )🐇


✏️ Learnings added
Learnt from: rymalia
URL: https://github.com/d-kimuson/claude-code-viewer/pull/216

Timestamp: 2026-06-24T21:11:20.116Z
Learning: In the `claude-code-viewer` repository (`src/lib/conversation-schema/`), session-log entry Zod schemas (e.g., `BridgeSessionEntrySchema`, `LastPromptEntrySchema`, `ModeEntrySchema`) are intentionally lenient: they do NOT use `z.strictObject`, no sibling entry schema does, and fields are kept optional where CC (Claude Code) may omit them. The guiding principle (documented in `SystemEntrySchema.ts`) is "surfacing the entry beats a hard schema reject". Adding strictness or requiring optional fields would reintroduce the validation-error class the schemas are designed to avoid.

Learnt from: rymalia
URL: https://github.com/d-kimuson/claude-code-viewer/pull/216

Timestamp: 2026-06-24T21:11:20.116Z
Learning: In the `claude-code-viewer` repository, the `testPlatformLayer` testing guideline applies only to Effect-TS code that involves side effects. Pure Zod schema-parsing tests in `src/lib/conversation-schema/` should use plain Vitest (no `testPlatformLayer`), consistent with all pre-existing schema tests in that directory.

Learnt from: rymalia
URL: https://github.com/d-kimuson/claude-code-viewer/pull/216

Timestamp: 2026-06-24T21:11:20.116Z
Learning: In `src/server/core/session/services/ExportService.ts` in `claude-code-viewer`, the `as` type cast in `buildSidechainData` / `generateSessionHtml` is pre-existing, covered by a deliberate `oxlint-disable` comment. PRs that only extend the existing filter list (e.g., adding `mode`/`bridge-session`) should not refactor the cast: a type-predicate replacement would be equally unchecked (it still excludes `attachment` which also has `isSidechain`) and would change behavior, making it out of scope.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant