FE refacter - #272

Merged
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode
May 26, 2026
Merged

FE refacter#272
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode

Conversation

@yusuke0610

Copy link
Copy Markdown
Owner

Summary

  • dirty 判定の isDeepEqualutils/deepEqual.ts に集約し、useCareerDirty / useProjectFormDirty の byte 一致コピペを解消(等価判定の乖離リスクを除去)。
  • useAsyncTaskPage の未参照デッドコード getNextInterval を削除(バックオフは useTaskPolling が実装済み)。
  • useCareerExperienceMutators に単体テストを新規追加し、フォーム state を書き換える仕様分岐(is_current↔end_date / has_client↔name / 最後の1件削除ガード / onProjectSave 追加・置換)を固定。
  • useTaskPolling.test のフレーキーな実時間待ち(setTimeout)を fake timers ベースへ置換し、unmount でポーリングが止まる仕様を決定論的に検証。

Applied Changes

High

  • なし(レポート通り構造的破綻なし)

Medium

  • [frontend/src/utils/deepEqual.ts:8] 新規。isDeepEqual を移設(Findings Medium / Duplication High「isDeepEqual の byte 一致コピペ」)。
  • [frontend/src/hooks/career/useCareerDirty.ts:10,117] ローカル定義を削除し ../../utils/deepEqual から import。挙動不変。
  • [frontend/src/hooks/career/useProjectFormDirty.ts:5,55-57] 同上。diffProject / team・technology_stacks・phases 比較はそのまま共通関数を利用。

Low

  • [frontend/src/hooks/useAsyncTaskPage.ts:21-25] getNextInterval の定義・export・「将来の拡張用」コメントを削除(Findings Low「デッドコード export」)。rg getNextInterval src/ で参照ゼロを確認済み。
  • [.claude/rules/frontend/architecture.md] hooks ディレクトリ記載 drift(Findings Low)を修正。実態調査で analyze 機能削除(commit ee481a0 "all anarize remove" 系)による drift が hooks 以外にも波及していたため、同種の乖離をまとめて是正:
    • hooks ブロックを実構成(top-level 8 件 + blog/ + career/)へ更新。存在しない useBlogSummaryPolling / useCareerAnalysisPage / useAsyncAnalysisPage / analysis/ 記載を削除し、未記載だった useAsyncTaskPage / useAuthSession を追記。
    • pages/ から削除済み CareerAnalysisPage.tsxcomponents/career-analysis/ ディレクトリ記載を削除。
    • api/ モジュール一覧から削除済み career-analysis / intelligence を除き、実在の githubLink を追記。
    • utils/ に新規 deepEqual.ts と既存未記載の pdfjs.ts / taskStatus.ts を追記。
    • 本文の非同期タスク進捗の記述を useAsyncAnalysisPageuseAsyncTaskPage に修正。

Test Changes

Removed

  • なし(レポートの削除推奨は無し)。

Added

  • [frontend/src/hooks/career/useCareerExperienceMutators.test.ts] 新規。守るユーザー挙動:
    • is_current=true で end_date がクリアされる / is_current=false では保持される
    • 通常フィールド更新は end_date を巻き込まない
    • has_client=false で取引先名がクリアされる / true では保持される
    • removeExperience / removeClient / removeProject の「最後の1件は削除せず blank で置換」ガード(各 1 件時)と複数時の index 削除
    • onProjectSave の projIndex=null(末尾追加)/ 非 null(置換)分岐
    • 実 React state(useState)越しに act で駆動し、操作後の form state を assert。

Changed

  • [frontend/src/hooks/useTaskPolling.test.ts:110-135] 「アンマウント時にポーリングが停止する」を置換。await new Promise((r)=>setTimeout(r, FAST_INTERVAL*3)) の実時間待ちを vi.useFakeTimers() + vi.advanceTimersByTimeAsync に変更。マウント中は反復(呼び出し ≥2)→ unmount → 仮想時間を進めても呼び出しが増えないことを決定論的に検証。守る仕様(unmount でポーリング停止)は維持。

Duplication Resolved

  • [frontend/src/utils/deepEqual.ts] Duplication Findings High「useCareerDirty.ts:72-96useProjectFormDirty.ts:30-54isDeepEqual(27L clone)」を統合。抽出先は duplication.md「Frontend → 純粋関数は src/utils/」に準拠。両 hook は import 1 行に置換し、再帰等価判定の正本を 1 か所に集約。
  • Allowed Duplication(useCareerExperienceMutators の nested setForm パターン、テストの arrange-act-assert 群)は偶発的重複として抽出せず維持(Skipped 参照)。

Structure Changes

  • utils/deepEqual.ts を新設したのみ。ディレクトリ移動・hook 切り出しなし(レポートの Oversized 3 件は全て「現状維持推奨」)。
frontend/src/
utils/
appError.ts
errorId.ts
pdfjs.ts
taskStatus.ts
deepEqual.ts # ← 新規: isDeepEqual を useCareerDirty / useProjectFormDirty から集約

Skipped

  • Allowed Duplication 群(useCareerExperienceMutators の experience/client/project 別 nested updater、jscpd 検出のテスト arrange-act-assert 13 件)は duplication.md「許容される類似」に該当するため抽出しない。
  • Oversized Components(ProjectModal 321L / CareerExperienceEditor 296L / CareerResumeForm 272L)はレポート通り責務分離済み・分割は過剰抽象化になるため未対応。

Validation

  • make lint-frontend: pass(eslint src/ エラーなし)
  • make lint-frontend-messages: pass(grep ベース検知ゼロ)
  • make test-frontend: pass(node:test 4 / vitest 22 ファイル 160 tests 全 green。新規 useCareerExperienceMutators.test.ts 含む)
  • make build-frontend: pass(tsc -b + vite build、220 modules、型エラーなし)
  • E2E (npm run test:e2e): 未実行。理由: 新規ページ/ルート追加・認証/ナビゲーション/レイアウト/サイドバー変更・UI フローに影響する API 変更のいずれにも該当しない(util 抽出は挙動不変、デッドコード削除、テストのみの変更)。

Follow-ups

  • なし(architecture.md の drift 是正を本 PR に取り込み済み)。仕様判断が必要で保留にした項目もなし。

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f7730381-698b-4916-848a-b683c218cd60

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/backend/deadcode

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

@yusuke0610
yusuke0610 merged commit ec66f91 into devMay 26, 2026
16 of 17 checks passed
Sign up for freeto 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

@yusuke0610
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

FE refacter - #272

Merged
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode
May 26, 2026
Merged

FE refacter#272
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode

Conversation

@yusuke0610

Copy link
Copy Markdown
Owner

Summary

  • dirty 判定の isDeepEqualutils/deepEqual.ts に集約し、useCareerDirty / useProjectFormDirty の byte 一致コピペを解消(等価判定の乖離リスクを除去)。
  • useAsyncTaskPage の未参照デッドコード getNextInterval を削除(バックオフは useTaskPolling が実装済み)。
  • useCareerExperienceMutators に単体テストを新規追加し、フォーム state を書き換える仕様分岐(is_current↔end_date / has_client↔name / 最後の1件削除ガード / onProjectSave 追加・置換)を固定。
  • useTaskPolling.test のフレーキーな実時間待ち(setTimeout)を fake timers ベースへ置換し、unmount でポーリングが止まる仕様を決定論的に検証。

Applied Changes

High

  • なし(レポート通り構造的破綻なし)

Medium

  • [frontend/src/utils/deepEqual.ts:8] 新規。isDeepEqual を移設(Findings Medium / Duplication High「isDeepEqual の byte 一致コピペ」)。
  • [frontend/src/hooks/career/useCareerDirty.ts:10,117] ローカル定義を削除し ../../utils/deepEqual から import。挙動不変。
  • [frontend/src/hooks/career/useProjectFormDirty.ts:5,55-57] 同上。diffProject / team・technology_stacks・phases 比較はそのまま共通関数を利用。

Low

  • [frontend/src/hooks/useAsyncTaskPage.ts:21-25] getNextInterval の定義・export・「将来の拡張用」コメントを削除(Findings Low「デッドコード export」)。rg getNextInterval src/ で参照ゼロを確認済み。
  • [.claude/rules/frontend/architecture.md] hooks ディレクトリ記載 drift(Findings Low)を修正。実態調査で analyze 機能削除(commit ee481a0 "all anarize remove" 系)による drift が hooks 以外にも波及していたため、同種の乖離をまとめて是正:
    • hooks ブロックを実構成(top-level 8 件 + blog/ + career/)へ更新。存在しない useBlogSummaryPolling / useCareerAnalysisPage / useAsyncAnalysisPage / analysis/ 記載を削除し、未記載だった useAsyncTaskPage / useAuthSession を追記。
    • pages/ から削除済み CareerAnalysisPage.tsxcomponents/career-analysis/ ディレクトリ記載を削除。
    • api/ モジュール一覧から削除済み career-analysis / intelligence を除き、実在の githubLink を追記。
    • utils/ に新規 deepEqual.ts と既存未記載の pdfjs.ts / taskStatus.ts を追記。
    • 本文の非同期タスク進捗の記述を useAsyncAnalysisPageuseAsyncTaskPage に修正。

Test Changes

Removed

  • なし(レポートの削除推奨は無し)。

Added

  • [frontend/src/hooks/career/useCareerExperienceMutators.test.ts] 新規。守るユーザー挙動:
    • is_current=true で end_date がクリアされる / is_current=false では保持される
    • 通常フィールド更新は end_date を巻き込まない
    • has_client=false で取引先名がクリアされる / true では保持される
    • removeExperience / removeClient / removeProject の「最後の1件は削除せず blank で置換」ガード(各 1 件時)と複数時の index 削除
    • onProjectSave の projIndex=null(末尾追加)/ 非 null(置換)分岐
    • 実 React state(useState)越しに act で駆動し、操作後の form state を assert。

Changed

  • [frontend/src/hooks/useTaskPolling.test.ts:110-135] 「アンマウント時にポーリングが停止する」を置換。await new Promise((r)=>setTimeout(r, FAST_INTERVAL*3)) の実時間待ちを vi.useFakeTimers() + vi.advanceTimersByTimeAsync に変更。マウント中は反復(呼び出し ≥2)→ unmount → 仮想時間を進めても呼び出しが増えないことを決定論的に検証。守る仕様(unmount でポーリング停止)は維持。

Duplication Resolved

  • [frontend/src/utils/deepEqual.ts] Duplication Findings High「useCareerDirty.ts:72-96useProjectFormDirty.ts:30-54isDeepEqual(27L clone)」を統合。抽出先は duplication.md「Frontend → 純粋関数は src/utils/」に準拠。両 hook は import 1 行に置換し、再帰等価判定の正本を 1 か所に集約。
  • Allowed Duplication(useCareerExperienceMutators の nested setForm パターン、テストの arrange-act-assert 群)は偶発的重複として抽出せず維持(Skipped 参照)。

Structure Changes

  • utils/deepEqual.ts を新設したのみ。ディレクトリ移動・hook 切り出しなし(レポートの Oversized 3 件は全て「現状維持推奨」)。
frontend/src/
utils/
appError.ts
errorId.ts
pdfjs.ts
taskStatus.ts
deepEqual.ts # ← 新規: isDeepEqual を useCareerDirty / useProjectFormDirty から集約

Skipped

  • Allowed Duplication 群(useCareerExperienceMutators の experience/client/project 別 nested updater、jscpd 検出のテスト arrange-act-assert 13 件)は duplication.md「許容される類似」に該当するため抽出しない。
  • Oversized Components(ProjectModal 321L / CareerExperienceEditor 296L / CareerResumeForm 272L)はレポート通り責務分離済み・分割は過剰抽象化になるため未対応。

Validation

  • make lint-frontend: pass(eslint src/ エラーなし)
  • make lint-frontend-messages: pass(grep ベース検知ゼロ)
  • make test-frontend: pass(node:test 4 / vitest 22 ファイル 160 tests 全 green。新規 useCareerExperienceMutators.test.ts 含む)
  • make build-frontend: pass(tsc -b + vite build、220 modules、型エラーなし)
  • E2E (npm run test:e2e): 未実行。理由: 新規ページ/ルート追加・認証/ナビゲーション/レイアウト/サイドバー変更・UI フローに影響する API 変更のいずれにも該当しない(util 抽出は挙動不変、デッドコード削除、テストのみの変更)。

Follow-ups

  • なし(architecture.md の drift 是正を本 PR に取り込み済み)。仕様判断が必要で保留にした項目もなし。

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f7730381-698b-4916-848a-b683c218cd60

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/backend/deadcode

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

@yusuke0610
yusuke0610 merged commit ec66f91 into devMay 26, 2026
16 of 17 checks passed
Sign up for freeto 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

@yusuke0610
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

FE refacter - #272

Merged
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode
May 26, 2026
Merged

FE refacter#272
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode

Conversation

@yusuke0610

Copy link
Copy Markdown
Owner

Summary

  • dirty 判定の isDeepEqualutils/deepEqual.ts に集約し、useCareerDirty / useProjectFormDirty の byte 一致コピペを解消(等価判定の乖離リスクを除去)。
  • useAsyncTaskPage の未参照デッドコード getNextInterval を削除(バックオフは useTaskPolling が実装済み)。
  • useCareerExperienceMutators に単体テストを新規追加し、フォーム state を書き換える仕様分岐(is_current↔end_date / has_client↔name / 最後の1件削除ガード / onProjectSave 追加・置換)を固定。
  • useTaskPolling.test のフレーキーな実時間待ち(setTimeout)を fake timers ベースへ置換し、unmount でポーリングが止まる仕様を決定論的に検証。

Applied Changes

High

  • なし(レポート通り構造的破綻なし)

Medium

  • [frontend/src/utils/deepEqual.ts:8] 新規。isDeepEqual を移設(Findings Medium / Duplication High「isDeepEqual の byte 一致コピペ」)。
  • [frontend/src/hooks/career/useCareerDirty.ts:10,117] ローカル定義を削除し ../../utils/deepEqual から import。挙動不変。
  • [frontend/src/hooks/career/useProjectFormDirty.ts:5,55-57] 同上。diffProject / team・technology_stacks・phases 比較はそのまま共通関数を利用。

Low

  • [frontend/src/hooks/useAsyncTaskPage.ts:21-25] getNextInterval の定義・export・「将来の拡張用」コメントを削除(Findings Low「デッドコード export」)。rg getNextInterval src/ で参照ゼロを確認済み。
  • [.claude/rules/frontend/architecture.md] hooks ディレクトリ記載 drift(Findings Low)を修正。実態調査で analyze 機能削除(commit ee481a0 "all anarize remove" 系)による drift が hooks 以外にも波及していたため、同種の乖離をまとめて是正:
    • hooks ブロックを実構成(top-level 8 件 + blog/ + career/)へ更新。存在しない useBlogSummaryPolling / useCareerAnalysisPage / useAsyncAnalysisPage / analysis/ 記載を削除し、未記載だった useAsyncTaskPage / useAuthSession を追記。
    • pages/ から削除済み CareerAnalysisPage.tsxcomponents/career-analysis/ ディレクトリ記載を削除。
    • api/ モジュール一覧から削除済み career-analysis / intelligence を除き、実在の githubLink を追記。
    • utils/ に新規 deepEqual.ts と既存未記載の pdfjs.ts / taskStatus.ts を追記。
    • 本文の非同期タスク進捗の記述を useAsyncAnalysisPageuseAsyncTaskPage に修正。

Test Changes

Removed

  • なし(レポートの削除推奨は無し)。

Added

  • [frontend/src/hooks/career/useCareerExperienceMutators.test.ts] 新規。守るユーザー挙動:
    • is_current=true で end_date がクリアされる / is_current=false では保持される
    • 通常フィールド更新は end_date を巻き込まない
    • has_client=false で取引先名がクリアされる / true では保持される
    • removeExperience / removeClient / removeProject の「最後の1件は削除せず blank で置換」ガード(各 1 件時)と複数時の index 削除
    • onProjectSave の projIndex=null(末尾追加)/ 非 null(置換)分岐
    • 実 React state(useState)越しに act で駆動し、操作後の form state を assert。

Changed

  • [frontend/src/hooks/useTaskPolling.test.ts:110-135] 「アンマウント時にポーリングが停止する」を置換。await new Promise((r)=>setTimeout(r, FAST_INTERVAL*3)) の実時間待ちを vi.useFakeTimers() + vi.advanceTimersByTimeAsync に変更。マウント中は反復(呼び出し ≥2)→ unmount → 仮想時間を進めても呼び出しが増えないことを決定論的に検証。守る仕様(unmount でポーリング停止)は維持。

Duplication Resolved

  • [frontend/src/utils/deepEqual.ts] Duplication Findings High「useCareerDirty.ts:72-96useProjectFormDirty.ts:30-54isDeepEqual(27L clone)」を統合。抽出先は duplication.md「Frontend → 純粋関数は src/utils/」に準拠。両 hook は import 1 行に置換し、再帰等価判定の正本を 1 か所に集約。
  • Allowed Duplication(useCareerExperienceMutators の nested setForm パターン、テストの arrange-act-assert 群)は偶発的重複として抽出せず維持(Skipped 参照)。

Structure Changes

  • utils/deepEqual.ts を新設したのみ。ディレクトリ移動・hook 切り出しなし(レポートの Oversized 3 件は全て「現状維持推奨」)。
frontend/src/
utils/
appError.ts
errorId.ts
pdfjs.ts
taskStatus.ts
deepEqual.ts # ← 新規: isDeepEqual を useCareerDirty / useProjectFormDirty から集約

Skipped

  • Allowed Duplication 群(useCareerExperienceMutators の experience/client/project 別 nested updater、jscpd 検出のテスト arrange-act-assert 13 件)は duplication.md「許容される類似」に該当するため抽出しない。
  • Oversized Components(ProjectModal 321L / CareerExperienceEditor 296L / CareerResumeForm 272L)はレポート通り責務分離済み・分割は過剰抽象化になるため未対応。

Validation

  • make lint-frontend: pass(eslint src/ エラーなし)
  • make lint-frontend-messages: pass(grep ベース検知ゼロ)
  • make test-frontend: pass(node:test 4 / vitest 22 ファイル 160 tests 全 green。新規 useCareerExperienceMutators.test.ts 含む)
  • make build-frontend: pass(tsc -b + vite build、220 modules、型エラーなし)
  • E2E (npm run test:e2e): 未実行。理由: 新規ページ/ルート追加・認証/ナビゲーション/レイアウト/サイドバー変更・UI フローに影響する API 変更のいずれにも該当しない(util 抽出は挙動不変、デッドコード削除、テストのみの変更)。

Follow-ups

  • なし(architecture.md の drift 是正を本 PR に取り込み済み)。仕様判断が必要で保留にした項目もなし。

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f7730381-698b-4916-848a-b683c218cd60

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/backend/deadcode

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

@yusuke0610
yusuke0610 merged commit ec66f91 into devMay 26, 2026
16 of 17 checks passed
Sign up for freeto 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

@yusuke0610
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

FE refacter - #272

Merged
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode
May 26, 2026
Merged

FE refacter#272
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode

Conversation

@yusuke0610

Copy link
Copy Markdown
Owner

Summary

  • dirty 判定の isDeepEqualutils/deepEqual.ts に集約し、useCareerDirty / useProjectFormDirty の byte 一致コピペを解消(等価判定の乖離リスクを除去)。
  • useAsyncTaskPage の未参照デッドコード getNextInterval を削除(バックオフは useTaskPolling が実装済み)。
  • useCareerExperienceMutators に単体テストを新規追加し、フォーム state を書き換える仕様分岐(is_current↔end_date / has_client↔name / 最後の1件削除ガード / onProjectSave 追加・置換)を固定。
  • useTaskPolling.test のフレーキーな実時間待ち(setTimeout)を fake timers ベースへ置換し、unmount でポーリングが止まる仕様を決定論的に検証。

Applied Changes

High

  • なし(レポート通り構造的破綻なし)

Medium

  • [frontend/src/utils/deepEqual.ts:8] 新規。isDeepEqual を移設(Findings Medium / Duplication High「isDeepEqual の byte 一致コピペ」)。
  • [frontend/src/hooks/career/useCareerDirty.ts:10,117] ローカル定義を削除し ../../utils/deepEqual から import。挙動不変。
  • [frontend/src/hooks/career/useProjectFormDirty.ts:5,55-57] 同上。diffProject / team・technology_stacks・phases 比較はそのまま共通関数を利用。

Low

  • [frontend/src/hooks/useAsyncTaskPage.ts:21-25] getNextInterval の定義・export・「将来の拡張用」コメントを削除(Findings Low「デッドコード export」)。rg getNextInterval src/ で参照ゼロを確認済み。
  • [.claude/rules/frontend/architecture.md] hooks ディレクトリ記載 drift(Findings Low)を修正。実態調査で analyze 機能削除(commit ee481a0 "all anarize remove" 系)による drift が hooks 以外にも波及していたため、同種の乖離をまとめて是正:
    • hooks ブロックを実構成(top-level 8 件 + blog/ + career/)へ更新。存在しない useBlogSummaryPolling / useCareerAnalysisPage / useAsyncAnalysisPage / analysis/ 記載を削除し、未記載だった useAsyncTaskPage / useAuthSession を追記。
    • pages/ から削除済み CareerAnalysisPage.tsxcomponents/career-analysis/ ディレクトリ記載を削除。
    • api/ モジュール一覧から削除済み career-analysis / intelligence を除き、実在の githubLink を追記。
    • utils/ に新規 deepEqual.ts と既存未記載の pdfjs.ts / taskStatus.ts を追記。
    • 本文の非同期タスク進捗の記述を useAsyncAnalysisPageuseAsyncTaskPage に修正。

Test Changes

Removed

  • なし(レポートの削除推奨は無し)。

Added

  • [frontend/src/hooks/career/useCareerExperienceMutators.test.ts] 新規。守るユーザー挙動:
    • is_current=true で end_date がクリアされる / is_current=false では保持される
    • 通常フィールド更新は end_date を巻き込まない
    • has_client=false で取引先名がクリアされる / true では保持される
    • removeExperience / removeClient / removeProject の「最後の1件は削除せず blank で置換」ガード(各 1 件時)と複数時の index 削除
    • onProjectSave の projIndex=null(末尾追加)/ 非 null(置換)分岐
    • 実 React state(useState)越しに act で駆動し、操作後の form state を assert。

Changed

  • [frontend/src/hooks/useTaskPolling.test.ts:110-135] 「アンマウント時にポーリングが停止する」を置換。await new Promise((r)=>setTimeout(r, FAST_INTERVAL*3)) の実時間待ちを vi.useFakeTimers() + vi.advanceTimersByTimeAsync に変更。マウント中は反復(呼び出し ≥2)→ unmount → 仮想時間を進めても呼び出しが増えないことを決定論的に検証。守る仕様(unmount でポーリング停止)は維持。

Duplication Resolved

  • [frontend/src/utils/deepEqual.ts] Duplication Findings High「useCareerDirty.ts:72-96useProjectFormDirty.ts:30-54isDeepEqual(27L clone)」を統合。抽出先は duplication.md「Frontend → 純粋関数は src/utils/」に準拠。両 hook は import 1 行に置換し、再帰等価判定の正本を 1 か所に集約。
  • Allowed Duplication(useCareerExperienceMutators の nested setForm パターン、テストの arrange-act-assert 群)は偶発的重複として抽出せず維持(Skipped 参照)。

Structure Changes

  • utils/deepEqual.ts を新設したのみ。ディレクトリ移動・hook 切り出しなし(レポートの Oversized 3 件は全て「現状維持推奨」)。
frontend/src/
utils/
appError.ts
errorId.ts
pdfjs.ts
taskStatus.ts
deepEqual.ts # ← 新規: isDeepEqual を useCareerDirty / useProjectFormDirty から集約

Skipped

  • Allowed Duplication 群(useCareerExperienceMutators の experience/client/project 別 nested updater、jscpd 検出のテスト arrange-act-assert 13 件)は duplication.md「許容される類似」に該当するため抽出しない。
  • Oversized Components(ProjectModal 321L / CareerExperienceEditor 296L / CareerResumeForm 272L)はレポート通り責務分離済み・分割は過剰抽象化になるため未対応。

Validation

  • make lint-frontend: pass(eslint src/ エラーなし)
  • make lint-frontend-messages: pass(grep ベース検知ゼロ)
  • make test-frontend: pass(node:test 4 / vitest 22 ファイル 160 tests 全 green。新規 useCareerExperienceMutators.test.ts 含む)
  • make build-frontend: pass(tsc -b + vite build、220 modules、型エラーなし)
  • E2E (npm run test:e2e): 未実行。理由: 新規ページ/ルート追加・認証/ナビゲーション/レイアウト/サイドバー変更・UI フローに影響する API 変更のいずれにも該当しない(util 抽出は挙動不変、デッドコード削除、テストのみの変更)。

Follow-ups

  • なし(architecture.md の drift 是正を本 PR に取り込み済み)。仕様判断が必要で保留にした項目もなし。

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f7730381-698b-4916-848a-b683c218cd60

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/backend/deadcode

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

@yusuke0610
yusuke0610 merged commit ec66f91 into devMay 26, 2026
16 of 17 checks passed
Sign up for freeto 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

@yusuke0610
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

FE refacter - #272

Merged
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode
May 26, 2026
Merged

FE refacter#272
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode

Conversation

@yusuke0610

Copy link
Copy Markdown
Owner

Summary

  • dirty 判定の isDeepEqualutils/deepEqual.ts に集約し、useCareerDirty / useProjectFormDirty の byte 一致コピペを解消(等価判定の乖離リスクを除去)。
  • useAsyncTaskPage の未参照デッドコード getNextInterval を削除(バックオフは useTaskPolling が実装済み)。
  • useCareerExperienceMutators に単体テストを新規追加し、フォーム state を書き換える仕様分岐(is_current↔end_date / has_client↔name / 最後の1件削除ガード / onProjectSave 追加・置換)を固定。
  • useTaskPolling.test のフレーキーな実時間待ち(setTimeout)を fake timers ベースへ置換し、unmount でポーリングが止まる仕様を決定論的に検証。

Applied Changes

High

  • なし(レポート通り構造的破綻なし)

Medium

  • [frontend/src/utils/deepEqual.ts:8] 新規。isDeepEqual を移設(Findings Medium / Duplication High「isDeepEqual の byte 一致コピペ」)。
  • [frontend/src/hooks/career/useCareerDirty.ts:10,117] ローカル定義を削除し ../../utils/deepEqual から import。挙動不変。
  • [frontend/src/hooks/career/useProjectFormDirty.ts:5,55-57] 同上。diffProject / team・technology_stacks・phases 比較はそのまま共通関数を利用。

Low

  • [frontend/src/hooks/useAsyncTaskPage.ts:21-25] getNextInterval の定義・export・「将来の拡張用」コメントを削除(Findings Low「デッドコード export」)。rg getNextInterval src/ で参照ゼロを確認済み。
  • [.claude/rules/frontend/architecture.md] hooks ディレクトリ記載 drift(Findings Low)を修正。実態調査で analyze 機能削除(commit ee481a0 "all anarize remove" 系)による drift が hooks 以外にも波及していたため、同種の乖離をまとめて是正:
    • hooks ブロックを実構成(top-level 8 件 + blog/ + career/)へ更新。存在しない useBlogSummaryPolling / useCareerAnalysisPage / useAsyncAnalysisPage / analysis/ 記載を削除し、未記載だった useAsyncTaskPage / useAuthSession を追記。
    • pages/ から削除済み CareerAnalysisPage.tsxcomponents/career-analysis/ ディレクトリ記載を削除。
    • api/ モジュール一覧から削除済み career-analysis / intelligence を除き、実在の githubLink を追記。
    • utils/ に新規 deepEqual.ts と既存未記載の pdfjs.ts / taskStatus.ts を追記。
    • 本文の非同期タスク進捗の記述を useAsyncAnalysisPageuseAsyncTaskPage に修正。

Test Changes

Removed

  • なし(レポートの削除推奨は無し)。

Added

  • [frontend/src/hooks/career/useCareerExperienceMutators.test.ts] 新規。守るユーザー挙動:
    • is_current=true で end_date がクリアされる / is_current=false では保持される
    • 通常フィールド更新は end_date を巻き込まない
    • has_client=false で取引先名がクリアされる / true では保持される
    • removeExperience / removeClient / removeProject の「最後の1件は削除せず blank で置換」ガード(各 1 件時)と複数時の index 削除
    • onProjectSave の projIndex=null(末尾追加)/ 非 null(置換)分岐
    • 実 React state(useState)越しに act で駆動し、操作後の form state を assert。

Changed

  • [frontend/src/hooks/useTaskPolling.test.ts:110-135] 「アンマウント時にポーリングが停止する」を置換。await new Promise((r)=>setTimeout(r, FAST_INTERVAL*3)) の実時間待ちを vi.useFakeTimers() + vi.advanceTimersByTimeAsync に変更。マウント中は反復(呼び出し ≥2)→ unmount → 仮想時間を進めても呼び出しが増えないことを決定論的に検証。守る仕様(unmount でポーリング停止)は維持。

Duplication Resolved

  • [frontend/src/utils/deepEqual.ts] Duplication Findings High「useCareerDirty.ts:72-96useProjectFormDirty.ts:30-54isDeepEqual(27L clone)」を統合。抽出先は duplication.md「Frontend → 純粋関数は src/utils/」に準拠。両 hook は import 1 行に置換し、再帰等価判定の正本を 1 か所に集約。
  • Allowed Duplication(useCareerExperienceMutators の nested setForm パターン、テストの arrange-act-assert 群)は偶発的重複として抽出せず維持(Skipped 参照)。

Structure Changes

  • utils/deepEqual.ts を新設したのみ。ディレクトリ移動・hook 切り出しなし(レポートの Oversized 3 件は全て「現状維持推奨」)。
frontend/src/
utils/
appError.ts
errorId.ts
pdfjs.ts
taskStatus.ts
deepEqual.ts # ← 新規: isDeepEqual を useCareerDirty / useProjectFormDirty から集約

Skipped

  • Allowed Duplication 群(useCareerExperienceMutators の experience/client/project 別 nested updater、jscpd 検出のテスト arrange-act-assert 13 件)は duplication.md「許容される類似」に該当するため抽出しない。
  • Oversized Components(ProjectModal 321L / CareerExperienceEditor 296L / CareerResumeForm 272L)はレポート通り責務分離済み・分割は過剰抽象化になるため未対応。

Validation

  • make lint-frontend: pass(eslint src/ エラーなし)
  • make lint-frontend-messages: pass(grep ベース検知ゼロ)
  • make test-frontend: pass(node:test 4 / vitest 22 ファイル 160 tests 全 green。新規 useCareerExperienceMutators.test.ts 含む)
  • make build-frontend: pass(tsc -b + vite build、220 modules、型エラーなし)
  • E2E (npm run test:e2e): 未実行。理由: 新規ページ/ルート追加・認証/ナビゲーション/レイアウト/サイドバー変更・UI フローに影響する API 変更のいずれにも該当しない(util 抽出は挙動不変、デッドコード削除、テストのみの変更)。

Follow-ups

  • なし(architecture.md の drift 是正を本 PR に取り込み済み)。仕様判断が必要で保留にした項目もなし。

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f7730381-698b-4916-848a-b683c218cd60

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/backend/deadcode

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

@yusuke0610
yusuke0610 merged commit ec66f91 into devMay 26, 2026
16 of 17 checks passed
Sign up for freeto 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

@yusuke0610
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

FE refacter - #272

Merged
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode
May 26, 2026
Merged

FE refacter#272
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode

Conversation

@yusuke0610

Copy link
Copy Markdown
Owner

Summary

  • dirty 判定の isDeepEqualutils/deepEqual.ts に集約し、useCareerDirty / useProjectFormDirty の byte 一致コピペを解消(等価判定の乖離リスクを除去)。
  • useAsyncTaskPage の未参照デッドコード getNextInterval を削除(バックオフは useTaskPolling が実装済み)。
  • useCareerExperienceMutators に単体テストを新規追加し、フォーム state を書き換える仕様分岐(is_current↔end_date / has_client↔name / 最後の1件削除ガード / onProjectSave 追加・置換)を固定。
  • useTaskPolling.test のフレーキーな実時間待ち(setTimeout)を fake timers ベースへ置換し、unmount でポーリングが止まる仕様を決定論的に検証。

Applied Changes

High

  • なし(レポート通り構造的破綻なし)

Medium

  • [frontend/src/utils/deepEqual.ts:8] 新規。isDeepEqual を移設(Findings Medium / Duplication High「isDeepEqual の byte 一致コピペ」)。
  • [frontend/src/hooks/career/useCareerDirty.ts:10,117] ローカル定義を削除し ../../utils/deepEqual から import。挙動不変。
  • [frontend/src/hooks/career/useProjectFormDirty.ts:5,55-57] 同上。diffProject / team・technology_stacks・phases 比較はそのまま共通関数を利用。

Low

  • [frontend/src/hooks/useAsyncTaskPage.ts:21-25] getNextInterval の定義・export・「将来の拡張用」コメントを削除(Findings Low「デッドコード export」)。rg getNextInterval src/ で参照ゼロを確認済み。
  • [.claude/rules/frontend/architecture.md] hooks ディレクトリ記載 drift(Findings Low)を修正。実態調査で analyze 機能削除(commit ee481a0 "all anarize remove" 系)による drift が hooks 以外にも波及していたため、同種の乖離をまとめて是正:
    • hooks ブロックを実構成(top-level 8 件 + blog/ + career/)へ更新。存在しない useBlogSummaryPolling / useCareerAnalysisPage / useAsyncAnalysisPage / analysis/ 記載を削除し、未記載だった useAsyncTaskPage / useAuthSession を追記。
    • pages/ から削除済み CareerAnalysisPage.tsxcomponents/career-analysis/ ディレクトリ記載を削除。
    • api/ モジュール一覧から削除済み career-analysis / intelligence を除き、実在の githubLink を追記。
    • utils/ に新規 deepEqual.ts と既存未記載の pdfjs.ts / taskStatus.ts を追記。
    • 本文の非同期タスク進捗の記述を useAsyncAnalysisPageuseAsyncTaskPage に修正。

Test Changes

Removed

  • なし(レポートの削除推奨は無し)。

Added

  • [frontend/src/hooks/career/useCareerExperienceMutators.test.ts] 新規。守るユーザー挙動:
    • is_current=true で end_date がクリアされる / is_current=false では保持される
    • 通常フィールド更新は end_date を巻き込まない
    • has_client=false で取引先名がクリアされる / true では保持される
    • removeExperience / removeClient / removeProject の「最後の1件は削除せず blank で置換」ガード(各 1 件時)と複数時の index 削除
    • onProjectSave の projIndex=null(末尾追加)/ 非 null(置換)分岐
    • 実 React state(useState)越しに act で駆動し、操作後の form state を assert。

Changed

  • [frontend/src/hooks/useTaskPolling.test.ts:110-135] 「アンマウント時にポーリングが停止する」を置換。await new Promise((r)=>setTimeout(r, FAST_INTERVAL*3)) の実時間待ちを vi.useFakeTimers() + vi.advanceTimersByTimeAsync に変更。マウント中は反復(呼び出し ≥2)→ unmount → 仮想時間を進めても呼び出しが増えないことを決定論的に検証。守る仕様(unmount でポーリング停止)は維持。

Duplication Resolved

  • [frontend/src/utils/deepEqual.ts] Duplication Findings High「useCareerDirty.ts:72-96useProjectFormDirty.ts:30-54isDeepEqual(27L clone)」を統合。抽出先は duplication.md「Frontend → 純粋関数は src/utils/」に準拠。両 hook は import 1 行に置換し、再帰等価判定の正本を 1 か所に集約。
  • Allowed Duplication(useCareerExperienceMutators の nested setForm パターン、テストの arrange-act-assert 群)は偶発的重複として抽出せず維持(Skipped 参照)。

Structure Changes

  • utils/deepEqual.ts を新設したのみ。ディレクトリ移動・hook 切り出しなし(レポートの Oversized 3 件は全て「現状維持推奨」)。
frontend/src/
utils/
appError.ts
errorId.ts
pdfjs.ts
taskStatus.ts
deepEqual.ts # ← 新規: isDeepEqual を useCareerDirty / useProjectFormDirty から集約

Skipped

  • Allowed Duplication 群(useCareerExperienceMutators の experience/client/project 別 nested updater、jscpd 検出のテスト arrange-act-assert 13 件)は duplication.md「許容される類似」に該当するため抽出しない。
  • Oversized Components(ProjectModal 321L / CareerExperienceEditor 296L / CareerResumeForm 272L)はレポート通り責務分離済み・分割は過剰抽象化になるため未対応。

Validation

  • make lint-frontend: pass(eslint src/ エラーなし)
  • make lint-frontend-messages: pass(grep ベース検知ゼロ)
  • make test-frontend: pass(node:test 4 / vitest 22 ファイル 160 tests 全 green。新規 useCareerExperienceMutators.test.ts 含む)
  • make build-frontend: pass(tsc -b + vite build、220 modules、型エラーなし)
  • E2E (npm run test:e2e): 未実行。理由: 新規ページ/ルート追加・認証/ナビゲーション/レイアウト/サイドバー変更・UI フローに影響する API 変更のいずれにも該当しない(util 抽出は挙動不変、デッドコード削除、テストのみの変更)。

Follow-ups

  • なし(architecture.md の drift 是正を本 PR に取り込み済み)。仕様判断が必要で保留にした項目もなし。

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f7730381-698b-4916-848a-b683c218cd60

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/backend/deadcode

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

@yusuke0610
yusuke0610 merged commit ec66f91 into devMay 26, 2026
16 of 17 checks passed
Sign up for freeto 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

@yusuke0610
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

FE refacter - #272

Merged
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode
May 26, 2026
Merged

FE refacter#272
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode

Conversation

@yusuke0610

Copy link
Copy Markdown
Owner

Summary

  • dirty 判定の isDeepEqualutils/deepEqual.ts に集約し、useCareerDirty / useProjectFormDirty の byte 一致コピペを解消(等価判定の乖離リスクを除去)。
  • useAsyncTaskPage の未参照デッドコード getNextInterval を削除(バックオフは useTaskPolling が実装済み)。
  • useCareerExperienceMutators に単体テストを新規追加し、フォーム state を書き換える仕様分岐(is_current↔end_date / has_client↔name / 最後の1件削除ガード / onProjectSave 追加・置換)を固定。
  • useTaskPolling.test のフレーキーな実時間待ち(setTimeout)を fake timers ベースへ置換し、unmount でポーリングが止まる仕様を決定論的に検証。

Applied Changes

High

  • なし(レポート通り構造的破綻なし)

Medium

  • [frontend/src/utils/deepEqual.ts:8] 新規。isDeepEqual を移設(Findings Medium / Duplication High「isDeepEqual の byte 一致コピペ」)。
  • [frontend/src/hooks/career/useCareerDirty.ts:10,117] ローカル定義を削除し ../../utils/deepEqual から import。挙動不変。
  • [frontend/src/hooks/career/useProjectFormDirty.ts:5,55-57] 同上。diffProject / team・technology_stacks・phases 比較はそのまま共通関数を利用。

Low

  • [frontend/src/hooks/useAsyncTaskPage.ts:21-25] getNextInterval の定義・export・「将来の拡張用」コメントを削除(Findings Low「デッドコード export」)。rg getNextInterval src/ で参照ゼロを確認済み。
  • [.claude/rules/frontend/architecture.md] hooks ディレクトリ記載 drift(Findings Low)を修正。実態調査で analyze 機能削除(commit ee481a0 "all anarize remove" 系)による drift が hooks 以外にも波及していたため、同種の乖離をまとめて是正:
    • hooks ブロックを実構成(top-level 8 件 + blog/ + career/)へ更新。存在しない useBlogSummaryPolling / useCareerAnalysisPage / useAsyncAnalysisPage / analysis/ 記載を削除し、未記載だった useAsyncTaskPage / useAuthSession を追記。
    • pages/ から削除済み CareerAnalysisPage.tsxcomponents/career-analysis/ ディレクトリ記載を削除。
    • api/ モジュール一覧から削除済み career-analysis / intelligence を除き、実在の githubLink を追記。
    • utils/ に新規 deepEqual.ts と既存未記載の pdfjs.ts / taskStatus.ts を追記。
    • 本文の非同期タスク進捗の記述を useAsyncAnalysisPageuseAsyncTaskPage に修正。

Test Changes

Removed

  • なし(レポートの削除推奨は無し)。

Added

  • [frontend/src/hooks/career/useCareerExperienceMutators.test.ts] 新規。守るユーザー挙動:
    • is_current=true で end_date がクリアされる / is_current=false では保持される
    • 通常フィールド更新は end_date を巻き込まない
    • has_client=false で取引先名がクリアされる / true では保持される
    • removeExperience / removeClient / removeProject の「最後の1件は削除せず blank で置換」ガード(各 1 件時)と複数時の index 削除
    • onProjectSave の projIndex=null(末尾追加)/ 非 null(置換)分岐
    • 実 React state(useState)越しに act で駆動し、操作後の form state を assert。

Changed

  • [frontend/src/hooks/useTaskPolling.test.ts:110-135] 「アンマウント時にポーリングが停止する」を置換。await new Promise((r)=>setTimeout(r, FAST_INTERVAL*3)) の実時間待ちを vi.useFakeTimers() + vi.advanceTimersByTimeAsync に変更。マウント中は反復(呼び出し ≥2)→ unmount → 仮想時間を進めても呼び出しが増えないことを決定論的に検証。守る仕様(unmount でポーリング停止)は維持。

Duplication Resolved

  • [frontend/src/utils/deepEqual.ts] Duplication Findings High「useCareerDirty.ts:72-96useProjectFormDirty.ts:30-54isDeepEqual(27L clone)」を統合。抽出先は duplication.md「Frontend → 純粋関数は src/utils/」に準拠。両 hook は import 1 行に置換し、再帰等価判定の正本を 1 か所に集約。
  • Allowed Duplication(useCareerExperienceMutators の nested setForm パターン、テストの arrange-act-assert 群)は偶発的重複として抽出せず維持(Skipped 参照)。

Structure Changes

  • utils/deepEqual.ts を新設したのみ。ディレクトリ移動・hook 切り出しなし(レポートの Oversized 3 件は全て「現状維持推奨」)。
frontend/src/
utils/
appError.ts
errorId.ts
pdfjs.ts
taskStatus.ts
deepEqual.ts # ← 新規: isDeepEqual を useCareerDirty / useProjectFormDirty から集約

Skipped

  • Allowed Duplication 群(useCareerExperienceMutators の experience/client/project 別 nested updater、jscpd 検出のテスト arrange-act-assert 13 件)は duplication.md「許容される類似」に該当するため抽出しない。
  • Oversized Components(ProjectModal 321L / CareerExperienceEditor 296L / CareerResumeForm 272L)はレポート通り責務分離済み・分割は過剰抽象化になるため未対応。

Validation

  • make lint-frontend: pass(eslint src/ エラーなし)
  • make lint-frontend-messages: pass(grep ベース検知ゼロ)
  • make test-frontend: pass(node:test 4 / vitest 22 ファイル 160 tests 全 green。新規 useCareerExperienceMutators.test.ts 含む)
  • make build-frontend: pass(tsc -b + vite build、220 modules、型エラーなし)
  • E2E (npm run test:e2e): 未実行。理由: 新規ページ/ルート追加・認証/ナビゲーション/レイアウト/サイドバー変更・UI フローに影響する API 変更のいずれにも該当しない(util 抽出は挙動不変、デッドコード削除、テストのみの変更)。

Follow-ups

  • なし(architecture.md の drift 是正を本 PR に取り込み済み)。仕様判断が必要で保留にした項目もなし。

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f7730381-698b-4916-848a-b683c218cd60

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/backend/deadcode

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

@yusuke0610
yusuke0610 merged commit ec66f91 into devMay 26, 2026
16 of 17 checks passed
Sign up for freeto 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

@yusuke0610
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

FE refacter - #272

Merged
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode
May 26, 2026
Merged

FE refacter#272
yusuke0610 merged 1 commit into
devfrom
refactor/backend/deadcode

Conversation

@yusuke0610

Copy link
Copy Markdown
Owner

Summary

  • dirty 判定の isDeepEqualutils/deepEqual.ts に集約し、useCareerDirty / useProjectFormDirty の byte 一致コピペを解消(等価判定の乖離リスクを除去)。
  • useAsyncTaskPage の未参照デッドコード getNextInterval を削除(バックオフは useTaskPolling が実装済み)。
  • useCareerExperienceMutators に単体テストを新規追加し、フォーム state を書き換える仕様分岐(is_current↔end_date / has_client↔name / 最後の1件削除ガード / onProjectSave 追加・置換)を固定。
  • useTaskPolling.test のフレーキーな実時間待ち(setTimeout)を fake timers ベースへ置換し、unmount でポーリングが止まる仕様を決定論的に検証。

Applied Changes

High

  • なし(レポート通り構造的破綻なし)

Medium

  • [frontend/src/utils/deepEqual.ts:8] 新規。isDeepEqual を移設(Findings Medium / Duplication High「isDeepEqual の byte 一致コピペ」)。
  • [frontend/src/hooks/career/useCareerDirty.ts:10,117] ローカル定義を削除し ../../utils/deepEqual から import。挙動不変。
  • [frontend/src/hooks/career/useProjectFormDirty.ts:5,55-57] 同上。diffProject / team・technology_stacks・phases 比較はそのまま共通関数を利用。

Low

  • [frontend/src/hooks/useAsyncTaskPage.ts:21-25] getNextInterval の定義・export・「将来の拡張用」コメントを削除(Findings Low「デッドコード export」)。rg getNextInterval src/ で参照ゼロを確認済み。
  • [.claude/rules/frontend/architecture.md] hooks ディレクトリ記載 drift(Findings Low)を修正。実態調査で analyze 機能削除(commit ee481a0 "all anarize remove" 系)による drift が hooks 以外にも波及していたため、同種の乖離をまとめて是正:
    • hooks ブロックを実構成(top-level 8 件 + blog/ + career/)へ更新。存在しない useBlogSummaryPolling / useCareerAnalysisPage / useAsyncAnalysisPage / analysis/ 記載を削除し、未記載だった useAsyncTaskPage / useAuthSession を追記。
    • pages/ から削除済み CareerAnalysisPage.tsxcomponents/career-analysis/ ディレクトリ記載を削除。
    • api/ モジュール一覧から削除済み career-analysis / intelligence を除き、実在の githubLink を追記。
    • utils/ に新規 deepEqual.ts と既存未記載の pdfjs.ts / taskStatus.ts を追記。
    • 本文の非同期タスク進捗の記述を useAsyncAnalysisPageuseAsyncTaskPage に修正。

Test Changes

Removed

  • なし(レポートの削除推奨は無し)。

Added

  • [frontend/src/hooks/career/useCareerExperienceMutators.test.ts] 新規。守るユーザー挙動:
    • is_current=true で end_date がクリアされる / is_current=false では保持される
    • 通常フィールド更新は end_date を巻き込まない
    • has_client=false で取引先名がクリアされる / true では保持される
    • removeExperience / removeClient / removeProject の「最後の1件は削除せず blank で置換」ガード(各 1 件時)と複数時の index 削除
    • onProjectSave の projIndex=null(末尾追加)/ 非 null(置換)分岐
    • 実 React state(useState)越しに act で駆動し、操作後の form state を assert。

Changed

  • [frontend/src/hooks/useTaskPolling.test.ts:110-135] 「アンマウント時にポーリングが停止する」を置換。await new Promise((r)=>setTimeout(r, FAST_INTERVAL*3)) の実時間待ちを vi.useFakeTimers() + vi.advanceTimersByTimeAsync に変更。マウント中は反復(呼び出し ≥2)→ unmount → 仮想時間を進めても呼び出しが増えないことを決定論的に検証。守る仕様(unmount でポーリング停止)は維持。

Duplication Resolved

  • [frontend/src/utils/deepEqual.ts] Duplication Findings High「useCareerDirty.ts:72-96useProjectFormDirty.ts:30-54isDeepEqual(27L clone)」を統合。抽出先は duplication.md「Frontend → 純粋関数は src/utils/」に準拠。両 hook は import 1 行に置換し、再帰等価判定の正本を 1 か所に集約。
  • Allowed Duplication(useCareerExperienceMutators の nested setForm パターン、テストの arrange-act-assert 群)は偶発的重複として抽出せず維持(Skipped 参照)。

Structure Changes

  • utils/deepEqual.ts を新設したのみ。ディレクトリ移動・hook 切り出しなし(レポートの Oversized 3 件は全て「現状維持推奨」)。
frontend/src/
utils/
appError.ts
errorId.ts
pdfjs.ts
taskStatus.ts
deepEqual.ts # ← 新規: isDeepEqual を useCareerDirty / useProjectFormDirty から集約

Skipped

  • Allowed Duplication 群(useCareerExperienceMutators の experience/client/project 別 nested updater、jscpd 検出のテスト arrange-act-assert 13 件)は duplication.md「許容される類似」に該当するため抽出しない。
  • Oversized Components(ProjectModal 321L / CareerExperienceEditor 296L / CareerResumeForm 272L)はレポート通り責務分離済み・分割は過剰抽象化になるため未対応。

Validation

  • make lint-frontend: pass(eslint src/ エラーなし)
  • make lint-frontend-messages: pass(grep ベース検知ゼロ)
  • make test-frontend: pass(node:test 4 / vitest 22 ファイル 160 tests 全 green。新規 useCareerExperienceMutators.test.ts 含む)
  • make build-frontend: pass(tsc -b + vite build、220 modules、型エラーなし)
  • E2E (npm run test:e2e): 未実行。理由: 新規ページ/ルート追加・認証/ナビゲーション/レイアウト/サイドバー変更・UI フローに影響する API 変更のいずれにも該当しない(util 抽出は挙動不変、デッドコード削除、テストのみの変更)。

Follow-ups

  • なし(architecture.md の drift 是正を本 PR に取り込み済み)。仕様判断が必要で保留にした項目もなし。

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f7730381-698b-4916-848a-b683c218cd60

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/backend/deadcode

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

@yusuke0610
yusuke0610 merged commit ec66f91 into devMay 26, 2026
16 of 17 checks passed
Sign up for freeto 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

@yusuke0610