Skip to content

refactor(wiki-compose): apply thermo-nuclear code quality review fixes - #992

Merged
otomatty merged 2 commits into
developfrom
cursor/wiki-compose-quality-e1bd
May 27, 2026
Merged

refactor(wiki-compose): apply thermo-nuclear code quality review fixes#992
otomatty merged 2 commits into
developfrom
cursor/wiki-compose-quality-e1bd

Conversation

@otomatty

@otomatty otomatty commented May 27, 2026

Copy link
Copy Markdown
Owner

概要

Thermo-nuclear コード品質レビューで挙がった推奨アクションをすべて反映しました。Wiki Compose の backend 契約の整合、フックの分解、auto-start の一本化、API の locale 準備の共通化、コピペ残骸の削除です。

変更点

  • Frontend backend 契約: coerceWikiComposeBackend / isWikiComposeAllowedBackend を追加し、非 Google BYOK 設定時は user_google または zedi_managed にフォールバック(サーバ #990 と整合)
  • wikiComposeSessionReducer.ts: SSE / resume / projection の純関数 reducer を切り出し(useWikiComposeSession は約 300 行に)
  • Auto-start 統合: startPolicyon-mount / when-backend-ready / never)と canRetryStart をフックに集約し、WikiComposePage の ref/effect を削除
  • API locale: composeSessionRunLocale.tsPOST /run の locale 解決・metadata 更新・graph input 整形を共通化
  • バグ修正: submitConflictAck / onSubmitConflictAck の重複、無意味な outlineForPreview 三項演算子を削除

変更の種類

  • 🐛 バグ修正 (Bug fix)
  • ✨ 新機能 (New feature)
  • 💥 破壊的変更 (Breaking change)
  • 📝 ドキュメント (Documentation)
  • 🎨 スタイル/リファクタリング (Style/Refactor)
  • 🧪 テスト (Tests)
  • 🔧 ビルド/CI (Build/CI)

テスト方法

  1. bunx vitest run src/lib/wikiCompose/resolveComposeBackend.test.ts src/hooks/useWikiComposeSession.test.ts
  2. cd server/api && bun test src/__tests__/routes/composeSessionRunLocale.test.ts
  3. Anthropic/OpenAI BYOK 設定で新規 Compose を開始し、セッション作成が 400 にならず zedi_managed または user_google で開始されること

チェックリスト

  • テストがすべてパスする(上記ユニットテスト)
  • Lint エラーがない
  • 必要に応じてドキュメントを更新した(英語正本 + 該当する場合は .ja.md ペア)
  • コミットメッセージが Conventional Commits に従っている
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • コンポーズの開始ポリシーを追加(on-mount / when-backend-ready 等)
    • 自動開始失敗時のリトライ可能状態を返すように改善
  • Refactor

    • セッションのコンテンツロケール解決と入力整形を共通化してルーティング側を簡素化
    • セッション状態管理を純粋なリデューサ層に移譲し、SSE/再開出力の取り扱いを統一
  • Tests

    • ロケール解決、バックエンド選定、起動リトライ挙動をカバーするテストを追加

Review Change Stack

- Align frontend backend resolution with Google-fixed Wiki Compose model
- Extract session reducer module; slim useWikiComposeSession hook
- Consolidate auto-start via startPolicy and canRetryStart
- Deduplicate compose session locale prep on API routes
- Remove duplicate props and dead outline preview ternary

Co-authored-by: Akimasa Sugai <otomatty@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 98813787-539a-4984-8dc8-da6d0dd3afc5

📥 Commits

Reviewing files that changed from the base of the PR and between 02fb48e and f7ee6ed.

📒 Files selected for processing (4)
  • server/api/src/routes/composeSessionRunLocale.ts
  • src/hooks/useWikiComposeSession.test.ts
  • src/hooks/useWikiComposeSession.ts
  • src/lib/wikiCompose/wikiComposeSessionReducer.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • server/api/src/routes/composeSessionRunLocale.ts
  • src/lib/wikiCompose/wikiComposeSessionReducer.ts
  • src/hooks/useWikiComposeSession.ts

📝 Walkthrough

Walkthrough

このPRはサーバーでのcontent-locale準備を集中化し、クライアント側でセッションUIの純粋なリデューサ群を導入、バックエンド選定に許容リスト/強制ルールを追加し、フックとページをポリシー駆動の起動制御へ書き換えます。

Changes

Compose Session Locale and State Management Refactoring

Layer / File(s) Summary
Server-side locale preparation and routing
server/api/src/routes/composeSessionRunLocale.ts, server/api/src/__tests__/routes/composeSessionRunLocale.test.ts, server/api/src/routes/composeSessions.ts
新規 prepareComposeRunFromRequest / resolveComposeSessionContentLocale を追加し、graph input から locale を除去・解決して必要時に session metadata パッチを生成。composeSessions の GET/POST/PATCH に統合。
Frontend backend allowlisting & coercion
src/lib/wikiCompose/resolveComposeBackend.ts, src/lib/wikiCompose/resolveComposeBackend.test.ts
isWikiComposeAllowedBackendcoerceWikiComposeBackend を追加し、Wiki Compose 用に許容バックエンドを zedi_manageduser_google に制限、優先候補の強制ロジックを導入。テストを拡張。
Pure session-state reducer module
src/lib/wikiCompose/wikiComposeSessionReducer.ts
セッションUI型と初期値を定義し、SSE/投影/ resume 出力を部分状態へ変換する純粋関数群(reduceComposeSseEventhydrateComposeFromProjectionreduceComposeResumeOutput 等)を追加。
Hook refactor with start policy and retry
src/hooks/useWikiComposeSession.ts, src/hooks/useWikiComposeSession.test.ts
フックをリデューサ群へ委譲、ComposeStartPolicy を導入して自動開始ポリシーを制御、canRetryStart を返却。resume/submit 系は reducer を用いて出力を適用。テストを調整して初期 backend をモック。
Page wiring and outline/ retry UI
src/pages/WikiComposePage.tsx
useInitialComposeBackend を削除し、useWikiComposeSessionstartPolicy を渡すよう変更。エディタプレビューは session.outlineProposal を直接使用。エラーのリトライは session.canRetryStartsession.start() を用いる。

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • otomatty/zedi#986: Overlaps UI/session-start orchestration and compose-start/retry behavior changes.
  • otomatty/zedi#985: Related centralized locale resolution changes for compose run/resume paths.

Poem

🐰 サーバでLocaleをちょいと外して、
クライアントは純粋リデューサで踊る、
バックエンドは許容だけ守って、
ポリシーが起動の鐘を鳴らす、
さあ再試行、うまくいきますように。

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.90% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed プルリクエストのタイトルはwiki-composeコンポーネントの大規模なリファクタリングと品質向上を適切に要約しており、変更内容の主要なテーマを明確に反映している。
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 docstrings
  • Create stacked PR
  • Commit on current branch

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

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request refactors the Wiki Compose session logic by extracting pure state reduction into a separate reducer (wikiComposeSessionReducer.ts), introducing a startPolicy configuration to manage session auto-start behavior, and restricting allowed execution backends to zedi_managed and user_google. It also extracts shared locale preparation helpers on the server side. Feedback from the review highlights two issues: first, the canRetryStart condition is overly restrictive and prevents retry actions under the default on-mount policy; second, a potential runtime error exists in the reducer when mapping c.sections without validating that each element is a valid object.

Comment on lines +249 to +255
const canRetryStart =
startPolicy === "when-backend-ready" &&
!initialSessionId &&
Boolean(state.error) &&
!state.session &&
!state.isStreaming &&
(state.status === "idle" || state.status === "failed");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

canRetryStartstartPolicy === "when-backend-ready" に制限されているため、デフォルトの startPolicy である "on-mount" の場合に初期起動(セッション作成や初回ストリーム開始)が失敗した際、画面に再試行(Retry)ボタンが表示されなくなってしまいます。

startPolicy に関わらず、新規セッション作成(!initialSessionId)の自動起動が失敗した場合は手動で再試行できるように、この条件を削除することをお勧めします。

Suggested change
const canRetryStart =
startPolicy === "when-backend-ready" &&
!initialSessionId &&
Boolean(state.error) &&
!state.session &&
!state.isStreaming &&
(state.status === "idle" || state.status === "failed");
const canRetryStart =
!initialSessionId &&
Boolean(state.error) &&
!state.session &&
!state.isStreaming &&
(state.status === "idle" || state.status === "failed");

Comment on lines +408 to +415
} else if (c.sections.length > 0) {
partial.outlineProposal = c.sections.map((s) => ({
id: s.sectionId,
heading: s.heading,
depth: 1,
intent: "",
}));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

c.sections の各要素に対するループ処理(398行目付近)では !section || typeof section !== "object" による安全なオブジェクトチェックが行われていますが、こちらの map 処理(409行目付近)ではチェックなしで直接プロパティ(s.sectionIds.heading)にアクセスしています。

万が一 c.sectionsnull や非オブジェクトの要素が含まれていた場合、ランタイムエラー(TypeError: Cannot read properties of null)が発生する可能性があります。
直前のループと同様に、事前にフィルタリングを行うか、安全なアクセスを行うように修正することをお勧めします。

      } else if (c.sections.length > 0) {
        partial.outlineProposal = c.sections
          .filter((s): s is DraftedSection => Boolean(s && typeof s === "object" && s.sectionId))
          .map((s) => ({
            id: s.sectionId,
            heading: s.heading ?? "",
            depth: 1,
            intent: "",
          }));
      }

@otomatty
otomatty marked this pull request as ready for review May 27, 2026 06:04
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@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: 02fb48eff9

ℹ️ 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 src/hooks/useWikiComposeSession.ts Outdated
Comment on lines 272 to 273
cancelled = true;
abortRef.current?.abort();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Do not abort the auto-start stream on state updates

For fresh compose (startPolicy === "when-backend-ready", as used by WikiComposePage) start() creates the session, updates state.session, then opens streamRun; that state update flips awaitingFreshStart from true to false, which is in this effect's dependency list, so React runs this cleanup and aborts the just-opened SSE request. The server treats that client disconnect as a failed run, so newly created compose sessions can be cancelled/failed immediately after they start rather than reaching the first interrupt.

Useful? React with 👍 / 👎.

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

🧹 Nitpick comments (2)
server/api/src/routes/composeSessionRunLocale.ts (1)

12-17: ⚡ Quick win

Add Japanese alongside English in exported type docs.

ComposeRunLocalePrep documentation is currently English-only; please make this exported API doc bilingual to match repository convention.

Suggested update
-/** Result of preparing a `POST /run` request for LangGraph execution. */
+/**
+ * Result of preparing a `POST /run` request for LangGraph execution.
+ * LangGraph 実行向け `POST /run` リクエスト前処理の結果。
+ */
 export type ComposeRunLocalePrep = {
   contentLocale: ComposeContentLocale;
   graphInput: unknown;
-  /** Metadata blob to persist on claim when locale is not yet stored. */
+  /**
+   * Metadata blob to persist on claim when locale is not yet stored.
+   * ロケール未保存時に claim 更新で永続化するメタデータ。
+   */
   metadataUpdate: Record<string, unknown> | undefined;
 };

As per coding guidelines **/*.{ts,tsx,js,jsx,md}: Include both Japanese and English comments/documentation in code and documentation files to maintain project tone consistency.

🤖 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/api/src/routes/composeSessionRunLocale.ts` around lines 12 - 17,
Update the JSDoc for the exported type ComposeRunLocalePrep to include both
English and Japanese descriptions: keep the existing English sentence for the
type and add a concise Japanese equivalent, and do the same for the field
comments (contentLocale, graphInput, metadataUpdate) so each comment has an
English line followed by a Japanese translation; locate the type declaration for
ComposeRunLocalePrep and insert the Japanese translations directly under or
inline with the existing English docs to follow the bilingual comment
convention.
server/api/src/__tests__/routes/composeSessionRunLocale.test.ts (1)

1-3: ⚡ Quick win

Make spec-facing test text bilingual (EN/JA).

Since these tests encode behavior specs, keep their documentation/title strings bilingual for consistency with project tone.

As per coding guidelines **/*.{test,spec}.{ts,tsx,js,jsx}: Tests serve as a source of truth for specifications alongside implementation code TSDoc/JSDoc, and **/*.{ts,tsx,js,jsx,md}: Include both Japanese and English comments/documentation in code and documentation files to maintain project tone consistency.

Also applies to: 10-44

🤖 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/api/src/__tests__/routes/composeSessionRunLocale.test.ts` around lines
1 - 3, Update the spec-facing test titles and any top-level describe/it strings
in the composeSessionRunLocale.test.ts unit tests to include both English and
Japanese text (bilingual), e.g., prepend or append Japanese translations to
existing English descriptions; locate and edit the describe/it/test blocks and
any comment header in this file to ensure each spec string contains an English
sentence and its Japanese counterpart so the tests’ documentation/readme tone is
bilingual and consistent with project 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.

Nitpick comments:
In `@server/api/src/__tests__/routes/composeSessionRunLocale.test.ts`:
- Around line 1-3: Update the spec-facing test titles and any top-level
describe/it strings in the composeSessionRunLocale.test.ts unit tests to include
both English and Japanese text (bilingual), e.g., prepend or append Japanese
translations to existing English descriptions; locate and edit the
describe/it/test blocks and any comment header in this file to ensure each spec
string contains an English sentence and its Japanese counterpart so the tests’
documentation/readme tone is bilingual and consistent with project guidelines.

In `@server/api/src/routes/composeSessionRunLocale.ts`:
- Around line 12-17: Update the JSDoc for the exported type ComposeRunLocalePrep
to include both English and Japanese descriptions: keep the existing English
sentence for the type and add a concise Japanese equivalent, and do the same for
the field comments (contentLocale, graphInput, metadataUpdate) so each comment
has an English line followed by a Japanese translation; locate the type
declaration for ComposeRunLocalePrep and insert the Japanese translations
directly under or inline with the existing English docs to follow the bilingual
comment convention.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ba29ee6a-8166-4ca8-adc4-168e9d780eac

📥 Commits

Reviewing files that changed from the base of the PR and between 5d28c99 and 02fb48e.

📒 Files selected for processing (9)
  • server/api/src/__tests__/routes/composeSessionRunLocale.test.ts
  • server/api/src/routes/composeSessionRunLocale.ts
  • server/api/src/routes/composeSessions.ts
  • src/hooks/useWikiComposeSession.test.ts
  • src/hooks/useWikiComposeSession.ts
  • src/lib/wikiCompose/resolveComposeBackend.test.ts
  • src/lib/wikiCompose/resolveComposeBackend.ts
  • src/lib/wikiCompose/wikiComposeSessionReducer.ts
  • src/pages/WikiComposePage.tsx

- Stop aborting SSE when session state updates after auto-start (Codex P1)
- Allow canRetryStart for any fresh-compose auto-start failure
- Guard outline mapping in resume reducer against invalid sections
- Add bilingual JSDoc on ComposeRunLocalePrep

Co-authored-by: Akimasa Sugai <otomatty@users.noreply.github.com>
@otomatty
otomatty merged commit dabd580 into develop May 27, 2026
18 checks passed
@otomatty
otomatty deleted the cursor/wiki-compose-quality-e1bd branch May 27, 2026 06:51
otomatty added a commit that referenced this pull request Jun 10, 2026
server/api's vitest suite (129 files / ~1,400 tests) was never run in CI —
only api-typecheck (`bunx tsc --noEmit`) ran, so a broken suite could slip
through unnoticed (e.g. the bun:test import in #992). server/hocuspocus had
the same gap: its tests were only wired into the root `test:run` script,
which CI does not execute (CI runs `test:coverage`).

Add `api-test` and `hocuspocus-test` jobs mirroring the `mcp-test` setup
(install deps inside the service dir, then `vitest run`), and align the
misleading comment in the `test` job. Update AGENTS.md so the CI
description matches reality, enumerating which job covers each service.

Closes #1010

Co-authored-by: Claude <noreply@anthropic.com>
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.

2 participants