[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化 - #572

Merged
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals
Aug 2, 2026
Merged

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化#572
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals

Conversation

@yusuke0610

@yusuke0610yusuke0610 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Closes#561

概要

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations / infra_declarations を保持しているのに、キャッシュへ永続化される AnalyzedRepoSummaryfull_name / description / created_at / pushed_at の 4 フィールドだけだった。判別材料を永続化層で捨てているため、ドラフトの選定ロジックは最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを区別できない。

本 PR は永続化層へ経路を通すところまで。選定ロジック自体の変更は #562 が担当する。

変更内容

1. 選定シグナルの追加(後方互換)

フィールド算出元
topicslist[str]RepoData.topics
language_bytes_totalintlanguages の合計
direct_dependency_countintpackage_declarations のうち direct のみ
ecosystem_countintpackage_declarations のエコシステム種別数
has_infraboolinfra_declarations の有無

いずれも既定値を持つため、旧形式 JSON のパースは従来どおり通る。

GitHub API の追加呼び出しはしない — すべて連携実行時に RepoData が取得済みの値で、_to_repo_summary は既存フィールドを参照するだけ。collector には触れていない。

2. 旧形式キャッシュの判定(409 + 再連携導線)

スキーマ側は既定値で受理するが、シグナル無しでの選定は品質を担保できないため、build_draft_source生 JSON のキー有無で判別して 409 へ倒す。ADR-0018 が定めた「repos キー欠落」判定と同じ流儀(Pydantic 検証後は既定値と区別できないため生 JSON を見る)。

1 件でもシグナル無しが混ざれば旧形式扱いにしている。部分的に許容すると、選定が「移行済みリポジトリだけ」に偏って本命を取りこぼすため。

ResumeDraftNoRepositoriesError(再連携では回復しない別導線)と取り違えていないことをテストで assert している。

3. 依存種別 "direct" の SSoT 化

response_mapper に定数を足すと同じ意味の比較が 4 箇所目になり、Rule of Three(.claude/rules/common/duplication.md)を超過するため、概念の定義元である skills/types.pyDEPENDENCY_KIND_DIRECT を置いて本差分の 2 箇所を移行した。

github_collector.py:165 / skills/aggregator.py:217 に残る 2 箇所は差分範囲外のため本 PR では変更しない(特に aggregator.py は mutmut スコープで TDD 手順が要る)。#562 以降で当該ファイルを触る回に併せる。

テスト

新規 5 件:

契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイル(test_resume_draft_mapper / test_resume_draft_api / test_worker/test_resume_draft)を新形式へ更新した。旧契約を固定化したテストは残していない。

検証

  • make ci: pass
  • make codegen-types 実行済み。web/src/api/generated.ts の差分を同 PR に含む(ADR-0007)

注意点

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Repository summaries now include topics, language usage, direct dependency counts, ecosystem counts, and infrastructure indicators.
    • These signals are carried through analysis results to support more informative repository selection and draft generation.
  • Bug Fixes

    • Incomplete or outdated cached repository data is now detected and handled gracefully instead of producing unreliable draft results.
  • Documentation

    • Updated API documentation to describe the new repository metadata, legacy cache compatibility, and relevant error handling.

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations /
infra_declarations を持つのに、キャッシュへ永続化される AnalyzedRepoSummary は
4 フィールドだけで、判別材料を永続化層で捨てていた。そのためドラフトの選定は
最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを
区別できない。
- AnalyzedRepoSummary に選定シグナルを追加(既定値付きで後方互換)
topics / language_bytes_total / direct_dependency_count /
ecosystem_count / has_infra
- response_mapper が RepoData から詰め替える。GitHub API の追加呼び出しはしない
- 旧形式キャッシュ(新キー無し)は build_draft_source が生 JSON のキー有無で
判別し、ADR-0018 と同じ 409 + 再連携導線へ倒す。1 件でも欠けたら旧形式扱いに
して選定が移行済みリポジトリへ偏るのを防ぐ
- 依存種別 "direct" の判定リテラルが 4 箇所に散っていたため、SSoT を
skills/types.py の DEPENDENCY_KIND_DIRECT に置いて本差分の 2 箇所を移行
契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイルを新形式へ更新した。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added backend バックエンド web フロントエンド (web) test テスト追加・修正 agent DevForge Agent labels Aug 2, 2026
@coderabbitai

coderabbitaiBot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, you've reached your PR review limit, so we couldn't start this review.

Next review available in:51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea57bfa1-18f1-42dd-a6ba-8436040c1d1d

📥 Commits

Reviewing files that changed from the base of the PR and between 47e1120 and f5bcc29.

📒 Files selected for processing (2)
  • backend/app/services/agent/resume_draft/context.py
  • backend/tests/test_resume_draft_mapper.py
📝 Walkthrough

Walkthrough

Changes

Repository selection signals

Layer / File(s)Summary
Summary contract and mapping
backend/app/schemas/github_link.py, backend/app/services/intelligence/..., backend/app/services/intelligence/skills/types.py, web/src/api/generated.ts, backend/tests/test_github_link.py
AnalyzedRepoSummary now stores topics, language totals, dependency counts, ecosystem counts, and infrastructure presence. The response mapper derives these values from RepoData.
Cache compatibility and resume-draft validation
backend/app/services/agent/resume_draft/context.py, backend/tests/test_resume_draft_mapper.py, backend/tests/test_resume_draft_api.py, backend/tests/test_worker/test_resume_draft.py
Resume-draft loading rejects legacy and partially migrated caches without selection signals. Test fixtures and assertions cover migrated summaries and signal preservation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
participant RepoData
participant response_mapper
participant AnalyzedRepoSummary
participant resume_draft_context
participant DraftSource
RepoData->>response_mapper: repository metadata and declarations
response_mapper->>AnalyzedRepoSummary: derived selection signals
AnalyzedRepoSummary->>resume_draft_context: cached repository summary
resume_draft_context->>DraftSource: validated repository signals
Loading

Possibly related PRs

Suggested labels:feature

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passedタイトルは、リポジトリ選定シグナルをAnalyzedRepoSummaryへ永続化する主変更を明確に示しています。
Linked Issues check✅ PassedIssue #561の要件に対応し、5つのシグナル、RepoDataからの変換、旧形式キャッシュ判定、生成型、テストを追加しています。
Out of Scope Changes check✅ Passed変更はIssue #561の永続化、旧形式キャッシュ対応、共有定数、テスト、生成型更新に限定されています。
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/561-repo-selection-signals

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.

@coderabbitaicoderabbitaiBot 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: 1

🤖 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 `@backend/app/services/agent/resume_draft/context.py`:
- Around line 43-46: Replace _SELECTION_SIGNAL_KEY with an immutable set
containing all five required ADR-0026 signals: language_bytes_total, topics,
direct_dependency_count, ecosystem_count, and has_infra; update the repository
validation around _SELECTION_SIGNAL_KEY at
backend/app/services/agent/resume_draft/context.py lines 106-114 to reject
dictionaries missing any key and preserve the existing 409 path. Parameterize
the missing-key test at backend/tests/test_resume_draft_mapper.py lines 280-318
to cover each required signal.
🪄 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 Plus

Run ID: 0d873261-6e5d-4f36-bd70-9c8d999152ce

📥 Commits

Reviewing files that changed from the base of the PR and between 77a1c4b and 47e1120.

📒 Files selected for processing (9)
  • backend/app/schemas/github_link.py
  • backend/app/services/agent/resume_draft/context.py
  • backend/app/services/intelligence/response_mapper.py
  • backend/app/services/intelligence/skills/types.py
  • backend/tests/test_github_link.py
  • backend/tests/test_resume_draft_api.py
  • backend/tests/test_resume_draft_mapper.py
  • backend/tests/test_worker/test_resume_draft.py
  • web/src/api/generated.ts

Comment threadbackend/app/services/agent/resume_draft/context.py Outdated
CodeRabbit の指摘(PR #572)を反映する。
代表キー(language_bytes_total)1 つの存在確認では、一部のシグナルだけを持つ
キャッシュが guard を通過してしまう。Pydantic が既定値で欠落を埋めるため、
不完全なデータのまま選定が走る。
- _SELECTION_SIGNAL_KEY を 5 キーの frozenset へ置き換え、issubset で全件必須にする
- 欠落キーごとにテストを parametrize(5 ケース)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit e3e3f17 into mainAug 2, 2026
21 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentDevForge Agentbackendバックエンドtestテスト追加・修正webフロントエンド (web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ドラフト縮小 1/7] backend: リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化

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

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化 - #572

Merged
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals
Aug 2, 2026
Merged

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化#572
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals

Conversation

@yusuke0610

@yusuke0610yusuke0610 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Closes#561

概要

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations / infra_declarations を保持しているのに、キャッシュへ永続化される AnalyzedRepoSummaryfull_name / description / created_at / pushed_at の 4 フィールドだけだった。判別材料を永続化層で捨てているため、ドラフトの選定ロジックは最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを区別できない。

本 PR は永続化層へ経路を通すところまで。選定ロジック自体の変更は #562 が担当する。

変更内容

1. 選定シグナルの追加(後方互換)

フィールド算出元
topicslist[str]RepoData.topics
language_bytes_totalintlanguages の合計
direct_dependency_countintpackage_declarations のうち direct のみ
ecosystem_countintpackage_declarations のエコシステム種別数
has_infraboolinfra_declarations の有無

いずれも既定値を持つため、旧形式 JSON のパースは従来どおり通る。

GitHub API の追加呼び出しはしない — すべて連携実行時に RepoData が取得済みの値で、_to_repo_summary は既存フィールドを参照するだけ。collector には触れていない。

2. 旧形式キャッシュの判定(409 + 再連携導線)

スキーマ側は既定値で受理するが、シグナル無しでの選定は品質を担保できないため、build_draft_source生 JSON のキー有無で判別して 409 へ倒す。ADR-0018 が定めた「repos キー欠落」判定と同じ流儀(Pydantic 検証後は既定値と区別できないため生 JSON を見る)。

1 件でもシグナル無しが混ざれば旧形式扱いにしている。部分的に許容すると、選定が「移行済みリポジトリだけ」に偏って本命を取りこぼすため。

ResumeDraftNoRepositoriesError(再連携では回復しない別導線)と取り違えていないことをテストで assert している。

3. 依存種別 "direct" の SSoT 化

response_mapper に定数を足すと同じ意味の比較が 4 箇所目になり、Rule of Three(.claude/rules/common/duplication.md)を超過するため、概念の定義元である skills/types.pyDEPENDENCY_KIND_DIRECT を置いて本差分の 2 箇所を移行した。

github_collector.py:165 / skills/aggregator.py:217 に残る 2 箇所は差分範囲外のため本 PR では変更しない(特に aggregator.py は mutmut スコープで TDD 手順が要る)。#562 以降で当該ファイルを触る回に併せる。

テスト

新規 5 件:

契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイル(test_resume_draft_mapper / test_resume_draft_api / test_worker/test_resume_draft)を新形式へ更新した。旧契約を固定化したテストは残していない。

検証

  • make ci: pass
  • make codegen-types 実行済み。web/src/api/generated.ts の差分を同 PR に含む(ADR-0007)

注意点

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Repository summaries now include topics, language usage, direct dependency counts, ecosystem counts, and infrastructure indicators.
    • These signals are carried through analysis results to support more informative repository selection and draft generation.
  • Bug Fixes

    • Incomplete or outdated cached repository data is now detected and handled gracefully instead of producing unreliable draft results.
  • Documentation

    • Updated API documentation to describe the new repository metadata, legacy cache compatibility, and relevant error handling.

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations /
infra_declarations を持つのに、キャッシュへ永続化される AnalyzedRepoSummary は
4 フィールドだけで、判別材料を永続化層で捨てていた。そのためドラフトの選定は
最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを
区別できない。
- AnalyzedRepoSummary に選定シグナルを追加(既定値付きで後方互換)
topics / language_bytes_total / direct_dependency_count /
ecosystem_count / has_infra
- response_mapper が RepoData から詰め替える。GitHub API の追加呼び出しはしない
- 旧形式キャッシュ(新キー無し)は build_draft_source が生 JSON のキー有無で
判別し、ADR-0018 と同じ 409 + 再連携導線へ倒す。1 件でも欠けたら旧形式扱いに
して選定が移行済みリポジトリへ偏るのを防ぐ
- 依存種別 "direct" の判定リテラルが 4 箇所に散っていたため、SSoT を
skills/types.py の DEPENDENCY_KIND_DIRECT に置いて本差分の 2 箇所を移行
契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイルを新形式へ更新した。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added backend バックエンド web フロントエンド (web) test テスト追加・修正 agent DevForge Agent labels Aug 2, 2026
@coderabbitai

coderabbitaiBot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, you've reached your PR review limit, so we couldn't start this review.

Next review available in:51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea57bfa1-18f1-42dd-a6ba-8436040c1d1d

📥 Commits

Reviewing files that changed from the base of the PR and between 47e1120 and f5bcc29.

📒 Files selected for processing (2)
  • backend/app/services/agent/resume_draft/context.py
  • backend/tests/test_resume_draft_mapper.py
📝 Walkthrough

Walkthrough

Changes

Repository selection signals

Layer / File(s)Summary
Summary contract and mapping
backend/app/schemas/github_link.py, backend/app/services/intelligence/..., backend/app/services/intelligence/skills/types.py, web/src/api/generated.ts, backend/tests/test_github_link.py
AnalyzedRepoSummary now stores topics, language totals, dependency counts, ecosystem counts, and infrastructure presence. The response mapper derives these values from RepoData.
Cache compatibility and resume-draft validation
backend/app/services/agent/resume_draft/context.py, backend/tests/test_resume_draft_mapper.py, backend/tests/test_resume_draft_api.py, backend/tests/test_worker/test_resume_draft.py
Resume-draft loading rejects legacy and partially migrated caches without selection signals. Test fixtures and assertions cover migrated summaries and signal preservation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
participant RepoData
participant response_mapper
participant AnalyzedRepoSummary
participant resume_draft_context
participant DraftSource
RepoData->>response_mapper: repository metadata and declarations
response_mapper->>AnalyzedRepoSummary: derived selection signals
AnalyzedRepoSummary->>resume_draft_context: cached repository summary
resume_draft_context->>DraftSource: validated repository signals
Loading

Possibly related PRs

Suggested labels:feature

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passedタイトルは、リポジトリ選定シグナルをAnalyzedRepoSummaryへ永続化する主変更を明確に示しています。
Linked Issues check✅ PassedIssue #561の要件に対応し、5つのシグナル、RepoDataからの変換、旧形式キャッシュ判定、生成型、テストを追加しています。
Out of Scope Changes check✅ Passed変更はIssue #561の永続化、旧形式キャッシュ対応、共有定数、テスト、生成型更新に限定されています。
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/561-repo-selection-signals

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.

@coderabbitaicoderabbitaiBot 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: 1

🤖 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 `@backend/app/services/agent/resume_draft/context.py`:
- Around line 43-46: Replace _SELECTION_SIGNAL_KEY with an immutable set
containing all five required ADR-0026 signals: language_bytes_total, topics,
direct_dependency_count, ecosystem_count, and has_infra; update the repository
validation around _SELECTION_SIGNAL_KEY at
backend/app/services/agent/resume_draft/context.py lines 106-114 to reject
dictionaries missing any key and preserve the existing 409 path. Parameterize
the missing-key test at backend/tests/test_resume_draft_mapper.py lines 280-318
to cover each required signal.
🪄 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 Plus

Run ID: 0d873261-6e5d-4f36-bd70-9c8d999152ce

📥 Commits

Reviewing files that changed from the base of the PR and between 77a1c4b and 47e1120.

📒 Files selected for processing (9)
  • backend/app/schemas/github_link.py
  • backend/app/services/agent/resume_draft/context.py
  • backend/app/services/intelligence/response_mapper.py
  • backend/app/services/intelligence/skills/types.py
  • backend/tests/test_github_link.py
  • backend/tests/test_resume_draft_api.py
  • backend/tests/test_resume_draft_mapper.py
  • backend/tests/test_worker/test_resume_draft.py
  • web/src/api/generated.ts

Comment threadbackend/app/services/agent/resume_draft/context.py Outdated
CodeRabbit の指摘(PR #572)を反映する。
代表キー(language_bytes_total)1 つの存在確認では、一部のシグナルだけを持つ
キャッシュが guard を通過してしまう。Pydantic が既定値で欠落を埋めるため、
不完全なデータのまま選定が走る。
- _SELECTION_SIGNAL_KEY を 5 キーの frozenset へ置き換え、issubset で全件必須にする
- 欠落キーごとにテストを parametrize(5 ケース)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit e3e3f17 into mainAug 2, 2026
21 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentDevForge Agentbackendバックエンドtestテスト追加・修正webフロントエンド (web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ドラフト縮小 1/7] backend: リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化

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

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化 - #572

Merged
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals
Aug 2, 2026
Merged

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化#572
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals

Conversation

@yusuke0610

@yusuke0610yusuke0610 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Closes#561

概要

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations / infra_declarations を保持しているのに、キャッシュへ永続化される AnalyzedRepoSummaryfull_name / description / created_at / pushed_at の 4 フィールドだけだった。判別材料を永続化層で捨てているため、ドラフトの選定ロジックは最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを区別できない。

本 PR は永続化層へ経路を通すところまで。選定ロジック自体の変更は #562 が担当する。

変更内容

1. 選定シグナルの追加(後方互換)

フィールド算出元
topicslist[str]RepoData.topics
language_bytes_totalintlanguages の合計
direct_dependency_countintpackage_declarations のうち direct のみ
ecosystem_countintpackage_declarations のエコシステム種別数
has_infraboolinfra_declarations の有無

いずれも既定値を持つため、旧形式 JSON のパースは従来どおり通る。

GitHub API の追加呼び出しはしない — すべて連携実行時に RepoData が取得済みの値で、_to_repo_summary は既存フィールドを参照するだけ。collector には触れていない。

2. 旧形式キャッシュの判定(409 + 再連携導線)

スキーマ側は既定値で受理するが、シグナル無しでの選定は品質を担保できないため、build_draft_source生 JSON のキー有無で判別して 409 へ倒す。ADR-0018 が定めた「repos キー欠落」判定と同じ流儀(Pydantic 検証後は既定値と区別できないため生 JSON を見る)。

1 件でもシグナル無しが混ざれば旧形式扱いにしている。部分的に許容すると、選定が「移行済みリポジトリだけ」に偏って本命を取りこぼすため。

ResumeDraftNoRepositoriesError(再連携では回復しない別導線)と取り違えていないことをテストで assert している。

3. 依存種別 "direct" の SSoT 化

response_mapper に定数を足すと同じ意味の比較が 4 箇所目になり、Rule of Three(.claude/rules/common/duplication.md)を超過するため、概念の定義元である skills/types.pyDEPENDENCY_KIND_DIRECT を置いて本差分の 2 箇所を移行した。

github_collector.py:165 / skills/aggregator.py:217 に残る 2 箇所は差分範囲外のため本 PR では変更しない(特に aggregator.py は mutmut スコープで TDD 手順が要る)。#562 以降で当該ファイルを触る回に併せる。

テスト

新規 5 件:

契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイル(test_resume_draft_mapper / test_resume_draft_api / test_worker/test_resume_draft)を新形式へ更新した。旧契約を固定化したテストは残していない。

検証

  • make ci: pass
  • make codegen-types 実行済み。web/src/api/generated.ts の差分を同 PR に含む(ADR-0007)

注意点

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Repository summaries now include topics, language usage, direct dependency counts, ecosystem counts, and infrastructure indicators.
    • These signals are carried through analysis results to support more informative repository selection and draft generation.
  • Bug Fixes

    • Incomplete or outdated cached repository data is now detected and handled gracefully instead of producing unreliable draft results.
  • Documentation

    • Updated API documentation to describe the new repository metadata, legacy cache compatibility, and relevant error handling.

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations /
infra_declarations を持つのに、キャッシュへ永続化される AnalyzedRepoSummary は
4 フィールドだけで、判別材料を永続化層で捨てていた。そのためドラフトの選定は
最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを
区別できない。
- AnalyzedRepoSummary に選定シグナルを追加(既定値付きで後方互換)
topics / language_bytes_total / direct_dependency_count /
ecosystem_count / has_infra
- response_mapper が RepoData から詰め替える。GitHub API の追加呼び出しはしない
- 旧形式キャッシュ(新キー無し)は build_draft_source が生 JSON のキー有無で
判別し、ADR-0018 と同じ 409 + 再連携導線へ倒す。1 件でも欠けたら旧形式扱いに
して選定が移行済みリポジトリへ偏るのを防ぐ
- 依存種別 "direct" の判定リテラルが 4 箇所に散っていたため、SSoT を
skills/types.py の DEPENDENCY_KIND_DIRECT に置いて本差分の 2 箇所を移行
契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイルを新形式へ更新した。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added backend バックエンド web フロントエンド (web) test テスト追加・修正 agent DevForge Agent labels Aug 2, 2026
@coderabbitai

coderabbitaiBot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, you've reached your PR review limit, so we couldn't start this review.

Next review available in:51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea57bfa1-18f1-42dd-a6ba-8436040c1d1d

📥 Commits

Reviewing files that changed from the base of the PR and between 47e1120 and f5bcc29.

📒 Files selected for processing (2)
  • backend/app/services/agent/resume_draft/context.py
  • backend/tests/test_resume_draft_mapper.py
📝 Walkthrough

Walkthrough

Changes

Repository selection signals

Layer / File(s)Summary
Summary contract and mapping
backend/app/schemas/github_link.py, backend/app/services/intelligence/..., backend/app/services/intelligence/skills/types.py, web/src/api/generated.ts, backend/tests/test_github_link.py
AnalyzedRepoSummary now stores topics, language totals, dependency counts, ecosystem counts, and infrastructure presence. The response mapper derives these values from RepoData.
Cache compatibility and resume-draft validation
backend/app/services/agent/resume_draft/context.py, backend/tests/test_resume_draft_mapper.py, backend/tests/test_resume_draft_api.py, backend/tests/test_worker/test_resume_draft.py
Resume-draft loading rejects legacy and partially migrated caches without selection signals. Test fixtures and assertions cover migrated summaries and signal preservation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
participant RepoData
participant response_mapper
participant AnalyzedRepoSummary
participant resume_draft_context
participant DraftSource
RepoData->>response_mapper: repository metadata and declarations
response_mapper->>AnalyzedRepoSummary: derived selection signals
AnalyzedRepoSummary->>resume_draft_context: cached repository summary
resume_draft_context->>DraftSource: validated repository signals
Loading

Possibly related PRs

Suggested labels:feature

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passedタイトルは、リポジトリ選定シグナルをAnalyzedRepoSummaryへ永続化する主変更を明確に示しています。
Linked Issues check✅ PassedIssue #561の要件に対応し、5つのシグナル、RepoDataからの変換、旧形式キャッシュ判定、生成型、テストを追加しています。
Out of Scope Changes check✅ Passed変更はIssue #561の永続化、旧形式キャッシュ対応、共有定数、テスト、生成型更新に限定されています。
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/561-repo-selection-signals

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.

@coderabbitaicoderabbitaiBot 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: 1

🤖 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 `@backend/app/services/agent/resume_draft/context.py`:
- Around line 43-46: Replace _SELECTION_SIGNAL_KEY with an immutable set
containing all five required ADR-0026 signals: language_bytes_total, topics,
direct_dependency_count, ecosystem_count, and has_infra; update the repository
validation around _SELECTION_SIGNAL_KEY at
backend/app/services/agent/resume_draft/context.py lines 106-114 to reject
dictionaries missing any key and preserve the existing 409 path. Parameterize
the missing-key test at backend/tests/test_resume_draft_mapper.py lines 280-318
to cover each required signal.
🪄 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 Plus

Run ID: 0d873261-6e5d-4f36-bd70-9c8d999152ce

📥 Commits

Reviewing files that changed from the base of the PR and between 77a1c4b and 47e1120.

📒 Files selected for processing (9)
  • backend/app/schemas/github_link.py
  • backend/app/services/agent/resume_draft/context.py
  • backend/app/services/intelligence/response_mapper.py
  • backend/app/services/intelligence/skills/types.py
  • backend/tests/test_github_link.py
  • backend/tests/test_resume_draft_api.py
  • backend/tests/test_resume_draft_mapper.py
  • backend/tests/test_worker/test_resume_draft.py
  • web/src/api/generated.ts

Comment threadbackend/app/services/agent/resume_draft/context.py Outdated
CodeRabbit の指摘(PR #572)を反映する。
代表キー(language_bytes_total)1 つの存在確認では、一部のシグナルだけを持つ
キャッシュが guard を通過してしまう。Pydantic が既定値で欠落を埋めるため、
不完全なデータのまま選定が走る。
- _SELECTION_SIGNAL_KEY を 5 キーの frozenset へ置き換え、issubset で全件必須にする
- 欠落キーごとにテストを parametrize(5 ケース)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit e3e3f17 into mainAug 2, 2026
21 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentDevForge Agentbackendバックエンドtestテスト追加・修正webフロントエンド (web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ドラフト縮小 1/7] backend: リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化

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

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化 - #572

Merged
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals
Aug 2, 2026
Merged

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化#572
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals

Conversation

@yusuke0610

@yusuke0610yusuke0610 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Closes#561

概要

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations / infra_declarations を保持しているのに、キャッシュへ永続化される AnalyzedRepoSummaryfull_name / description / created_at / pushed_at の 4 フィールドだけだった。判別材料を永続化層で捨てているため、ドラフトの選定ロジックは最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを区別できない。

本 PR は永続化層へ経路を通すところまで。選定ロジック自体の変更は #562 が担当する。

変更内容

1. 選定シグナルの追加(後方互換)

フィールド算出元
topicslist[str]RepoData.topics
language_bytes_totalintlanguages の合計
direct_dependency_countintpackage_declarations のうち direct のみ
ecosystem_countintpackage_declarations のエコシステム種別数
has_infraboolinfra_declarations の有無

いずれも既定値を持つため、旧形式 JSON のパースは従来どおり通る。

GitHub API の追加呼び出しはしない — すべて連携実行時に RepoData が取得済みの値で、_to_repo_summary は既存フィールドを参照するだけ。collector には触れていない。

2. 旧形式キャッシュの判定(409 + 再連携導線)

スキーマ側は既定値で受理するが、シグナル無しでの選定は品質を担保できないため、build_draft_source生 JSON のキー有無で判別して 409 へ倒す。ADR-0018 が定めた「repos キー欠落」判定と同じ流儀(Pydantic 検証後は既定値と区別できないため生 JSON を見る)。

1 件でもシグナル無しが混ざれば旧形式扱いにしている。部分的に許容すると、選定が「移行済みリポジトリだけ」に偏って本命を取りこぼすため。

ResumeDraftNoRepositoriesError(再連携では回復しない別導線)と取り違えていないことをテストで assert している。

3. 依存種別 "direct" の SSoT 化

response_mapper に定数を足すと同じ意味の比較が 4 箇所目になり、Rule of Three(.claude/rules/common/duplication.md)を超過するため、概念の定義元である skills/types.pyDEPENDENCY_KIND_DIRECT を置いて本差分の 2 箇所を移行した。

github_collector.py:165 / skills/aggregator.py:217 に残る 2 箇所は差分範囲外のため本 PR では変更しない(特に aggregator.py は mutmut スコープで TDD 手順が要る)。#562 以降で当該ファイルを触る回に併せる。

テスト

新規 5 件:

契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイル(test_resume_draft_mapper / test_resume_draft_api / test_worker/test_resume_draft)を新形式へ更新した。旧契約を固定化したテストは残していない。

検証

  • make ci: pass
  • make codegen-types 実行済み。web/src/api/generated.ts の差分を同 PR に含む(ADR-0007)

注意点

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Repository summaries now include topics, language usage, direct dependency counts, ecosystem counts, and infrastructure indicators.
    • These signals are carried through analysis results to support more informative repository selection and draft generation.
  • Bug Fixes

    • Incomplete or outdated cached repository data is now detected and handled gracefully instead of producing unreliable draft results.
  • Documentation

    • Updated API documentation to describe the new repository metadata, legacy cache compatibility, and relevant error handling.

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations /
infra_declarations を持つのに、キャッシュへ永続化される AnalyzedRepoSummary は
4 フィールドだけで、判別材料を永続化層で捨てていた。そのためドラフトの選定は
最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを
区別できない。
- AnalyzedRepoSummary に選定シグナルを追加(既定値付きで後方互換)
topics / language_bytes_total / direct_dependency_count /
ecosystem_count / has_infra
- response_mapper が RepoData から詰め替える。GitHub API の追加呼び出しはしない
- 旧形式キャッシュ(新キー無し)は build_draft_source が生 JSON のキー有無で
判別し、ADR-0018 と同じ 409 + 再連携導線へ倒す。1 件でも欠けたら旧形式扱いに
して選定が移行済みリポジトリへ偏るのを防ぐ
- 依存種別 "direct" の判定リテラルが 4 箇所に散っていたため、SSoT を
skills/types.py の DEPENDENCY_KIND_DIRECT に置いて本差分の 2 箇所を移行
契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイルを新形式へ更新した。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added backend バックエンド web フロントエンド (web) test テスト追加・修正 agent DevForge Agent labels Aug 2, 2026
@coderabbitai

coderabbitaiBot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, you've reached your PR review limit, so we couldn't start this review.

Next review available in:51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea57bfa1-18f1-42dd-a6ba-8436040c1d1d

📥 Commits

Reviewing files that changed from the base of the PR and between 47e1120 and f5bcc29.

📒 Files selected for processing (2)
  • backend/app/services/agent/resume_draft/context.py
  • backend/tests/test_resume_draft_mapper.py
📝 Walkthrough

Walkthrough

Changes

Repository selection signals

Layer / File(s)Summary
Summary contract and mapping
backend/app/schemas/github_link.py, backend/app/services/intelligence/..., backend/app/services/intelligence/skills/types.py, web/src/api/generated.ts, backend/tests/test_github_link.py
AnalyzedRepoSummary now stores topics, language totals, dependency counts, ecosystem counts, and infrastructure presence. The response mapper derives these values from RepoData.
Cache compatibility and resume-draft validation
backend/app/services/agent/resume_draft/context.py, backend/tests/test_resume_draft_mapper.py, backend/tests/test_resume_draft_api.py, backend/tests/test_worker/test_resume_draft.py
Resume-draft loading rejects legacy and partially migrated caches without selection signals. Test fixtures and assertions cover migrated summaries and signal preservation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
participant RepoData
participant response_mapper
participant AnalyzedRepoSummary
participant resume_draft_context
participant DraftSource
RepoData->>response_mapper: repository metadata and declarations
response_mapper->>AnalyzedRepoSummary: derived selection signals
AnalyzedRepoSummary->>resume_draft_context: cached repository summary
resume_draft_context->>DraftSource: validated repository signals
Loading

Possibly related PRs

Suggested labels:feature

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passedタイトルは、リポジトリ選定シグナルをAnalyzedRepoSummaryへ永続化する主変更を明確に示しています。
Linked Issues check✅ PassedIssue #561の要件に対応し、5つのシグナル、RepoDataからの変換、旧形式キャッシュ判定、生成型、テストを追加しています。
Out of Scope Changes check✅ Passed変更はIssue #561の永続化、旧形式キャッシュ対応、共有定数、テスト、生成型更新に限定されています。
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/561-repo-selection-signals

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.

@coderabbitaicoderabbitaiBot 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: 1

🤖 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 `@backend/app/services/agent/resume_draft/context.py`:
- Around line 43-46: Replace _SELECTION_SIGNAL_KEY with an immutable set
containing all five required ADR-0026 signals: language_bytes_total, topics,
direct_dependency_count, ecosystem_count, and has_infra; update the repository
validation around _SELECTION_SIGNAL_KEY at
backend/app/services/agent/resume_draft/context.py lines 106-114 to reject
dictionaries missing any key and preserve the existing 409 path. Parameterize
the missing-key test at backend/tests/test_resume_draft_mapper.py lines 280-318
to cover each required signal.
🪄 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 Plus

Run ID: 0d873261-6e5d-4f36-bd70-9c8d999152ce

📥 Commits

Reviewing files that changed from the base of the PR and between 77a1c4b and 47e1120.

📒 Files selected for processing (9)
  • backend/app/schemas/github_link.py
  • backend/app/services/agent/resume_draft/context.py
  • backend/app/services/intelligence/response_mapper.py
  • backend/app/services/intelligence/skills/types.py
  • backend/tests/test_github_link.py
  • backend/tests/test_resume_draft_api.py
  • backend/tests/test_resume_draft_mapper.py
  • backend/tests/test_worker/test_resume_draft.py
  • web/src/api/generated.ts

Comment threadbackend/app/services/agent/resume_draft/context.py Outdated
CodeRabbit の指摘(PR #572)を反映する。
代表キー(language_bytes_total)1 つの存在確認では、一部のシグナルだけを持つ
キャッシュが guard を通過してしまう。Pydantic が既定値で欠落を埋めるため、
不完全なデータのまま選定が走る。
- _SELECTION_SIGNAL_KEY を 5 キーの frozenset へ置き換え、issubset で全件必須にする
- 欠落キーごとにテストを parametrize(5 ケース)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit e3e3f17 into mainAug 2, 2026
21 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentDevForge Agentbackendバックエンドtestテスト追加・修正webフロントエンド (web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ドラフト縮小 1/7] backend: リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化

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

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化 - #572

Merged
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals
Aug 2, 2026
Merged

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化#572
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals

Conversation

@yusuke0610

@yusuke0610yusuke0610 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Closes#561

概要

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations / infra_declarations を保持しているのに、キャッシュへ永続化される AnalyzedRepoSummaryfull_name / description / created_at / pushed_at の 4 フィールドだけだった。判別材料を永続化層で捨てているため、ドラフトの選定ロジックは最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを区別できない。

本 PR は永続化層へ経路を通すところまで。選定ロジック自体の変更は #562 が担当する。

変更内容

1. 選定シグナルの追加(後方互換)

フィールド算出元
topicslist[str]RepoData.topics
language_bytes_totalintlanguages の合計
direct_dependency_countintpackage_declarations のうち direct のみ
ecosystem_countintpackage_declarations のエコシステム種別数
has_infraboolinfra_declarations の有無

いずれも既定値を持つため、旧形式 JSON のパースは従来どおり通る。

GitHub API の追加呼び出しはしない — すべて連携実行時に RepoData が取得済みの値で、_to_repo_summary は既存フィールドを参照するだけ。collector には触れていない。

2. 旧形式キャッシュの判定(409 + 再連携導線)

スキーマ側は既定値で受理するが、シグナル無しでの選定は品質を担保できないため、build_draft_source生 JSON のキー有無で判別して 409 へ倒す。ADR-0018 が定めた「repos キー欠落」判定と同じ流儀(Pydantic 検証後は既定値と区別できないため生 JSON を見る)。

1 件でもシグナル無しが混ざれば旧形式扱いにしている。部分的に許容すると、選定が「移行済みリポジトリだけ」に偏って本命を取りこぼすため。

ResumeDraftNoRepositoriesError(再連携では回復しない別導線)と取り違えていないことをテストで assert している。

3. 依存種別 "direct" の SSoT 化

response_mapper に定数を足すと同じ意味の比較が 4 箇所目になり、Rule of Three(.claude/rules/common/duplication.md)を超過するため、概念の定義元である skills/types.pyDEPENDENCY_KIND_DIRECT を置いて本差分の 2 箇所を移行した。

github_collector.py:165 / skills/aggregator.py:217 に残る 2 箇所は差分範囲外のため本 PR では変更しない(特に aggregator.py は mutmut スコープで TDD 手順が要る)。#562 以降で当該ファイルを触る回に併せる。

テスト

新規 5 件:

契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイル(test_resume_draft_mapper / test_resume_draft_api / test_worker/test_resume_draft)を新形式へ更新した。旧契約を固定化したテストは残していない。

検証

  • make ci: pass
  • make codegen-types 実行済み。web/src/api/generated.ts の差分を同 PR に含む(ADR-0007)

注意点

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Repository summaries now include topics, language usage, direct dependency counts, ecosystem counts, and infrastructure indicators.
    • These signals are carried through analysis results to support more informative repository selection and draft generation.
  • Bug Fixes

    • Incomplete or outdated cached repository data is now detected and handled gracefully instead of producing unreliable draft results.
  • Documentation

    • Updated API documentation to describe the new repository metadata, legacy cache compatibility, and relevant error handling.

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations /
infra_declarations を持つのに、キャッシュへ永続化される AnalyzedRepoSummary は
4 フィールドだけで、判別材料を永続化層で捨てていた。そのためドラフトの選定は
最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを
区別できない。
- AnalyzedRepoSummary に選定シグナルを追加(既定値付きで後方互換)
topics / language_bytes_total / direct_dependency_count /
ecosystem_count / has_infra
- response_mapper が RepoData から詰め替える。GitHub API の追加呼び出しはしない
- 旧形式キャッシュ(新キー無し)は build_draft_source が生 JSON のキー有無で
判別し、ADR-0018 と同じ 409 + 再連携導線へ倒す。1 件でも欠けたら旧形式扱いに
して選定が移行済みリポジトリへ偏るのを防ぐ
- 依存種別 "direct" の判定リテラルが 4 箇所に散っていたため、SSoT を
skills/types.py の DEPENDENCY_KIND_DIRECT に置いて本差分の 2 箇所を移行
契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイルを新形式へ更新した。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added backend バックエンド web フロントエンド (web) test テスト追加・修正 agent DevForge Agent labels Aug 2, 2026
@coderabbitai

coderabbitaiBot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, you've reached your PR review limit, so we couldn't start this review.

Next review available in:51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea57bfa1-18f1-42dd-a6ba-8436040c1d1d

📥 Commits

Reviewing files that changed from the base of the PR and between 47e1120 and f5bcc29.

📒 Files selected for processing (2)
  • backend/app/services/agent/resume_draft/context.py
  • backend/tests/test_resume_draft_mapper.py
📝 Walkthrough

Walkthrough

Changes

Repository selection signals

Layer / File(s)Summary
Summary contract and mapping
backend/app/schemas/github_link.py, backend/app/services/intelligence/..., backend/app/services/intelligence/skills/types.py, web/src/api/generated.ts, backend/tests/test_github_link.py
AnalyzedRepoSummary now stores topics, language totals, dependency counts, ecosystem counts, and infrastructure presence. The response mapper derives these values from RepoData.
Cache compatibility and resume-draft validation
backend/app/services/agent/resume_draft/context.py, backend/tests/test_resume_draft_mapper.py, backend/tests/test_resume_draft_api.py, backend/tests/test_worker/test_resume_draft.py
Resume-draft loading rejects legacy and partially migrated caches without selection signals. Test fixtures and assertions cover migrated summaries and signal preservation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
participant RepoData
participant response_mapper
participant AnalyzedRepoSummary
participant resume_draft_context
participant DraftSource
RepoData->>response_mapper: repository metadata and declarations
response_mapper->>AnalyzedRepoSummary: derived selection signals
AnalyzedRepoSummary->>resume_draft_context: cached repository summary
resume_draft_context->>DraftSource: validated repository signals
Loading

Possibly related PRs

Suggested labels:feature

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passedタイトルは、リポジトリ選定シグナルをAnalyzedRepoSummaryへ永続化する主変更を明確に示しています。
Linked Issues check✅ PassedIssue #561の要件に対応し、5つのシグナル、RepoDataからの変換、旧形式キャッシュ判定、生成型、テストを追加しています。
Out of Scope Changes check✅ Passed変更はIssue #561の永続化、旧形式キャッシュ対応、共有定数、テスト、生成型更新に限定されています。
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/561-repo-selection-signals

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.

@coderabbitaicoderabbitaiBot 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: 1

🤖 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 `@backend/app/services/agent/resume_draft/context.py`:
- Around line 43-46: Replace _SELECTION_SIGNAL_KEY with an immutable set
containing all five required ADR-0026 signals: language_bytes_total, topics,
direct_dependency_count, ecosystem_count, and has_infra; update the repository
validation around _SELECTION_SIGNAL_KEY at
backend/app/services/agent/resume_draft/context.py lines 106-114 to reject
dictionaries missing any key and preserve the existing 409 path. Parameterize
the missing-key test at backend/tests/test_resume_draft_mapper.py lines 280-318
to cover each required signal.
🪄 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 Plus

Run ID: 0d873261-6e5d-4f36-bd70-9c8d999152ce

📥 Commits

Reviewing files that changed from the base of the PR and between 77a1c4b and 47e1120.

📒 Files selected for processing (9)
  • backend/app/schemas/github_link.py
  • backend/app/services/agent/resume_draft/context.py
  • backend/app/services/intelligence/response_mapper.py
  • backend/app/services/intelligence/skills/types.py
  • backend/tests/test_github_link.py
  • backend/tests/test_resume_draft_api.py
  • backend/tests/test_resume_draft_mapper.py
  • backend/tests/test_worker/test_resume_draft.py
  • web/src/api/generated.ts

Comment threadbackend/app/services/agent/resume_draft/context.py Outdated
CodeRabbit の指摘(PR #572)を反映する。
代表キー(language_bytes_total)1 つの存在確認では、一部のシグナルだけを持つ
キャッシュが guard を通過してしまう。Pydantic が既定値で欠落を埋めるため、
不完全なデータのまま選定が走る。
- _SELECTION_SIGNAL_KEY を 5 キーの frozenset へ置き換え、issubset で全件必須にする
- 欠落キーごとにテストを parametrize(5 ケース)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit e3e3f17 into mainAug 2, 2026
21 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentDevForge Agentbackendバックエンドtestテスト追加・修正webフロントエンド (web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ドラフト縮小 1/7] backend: リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化

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

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化 - #572

Merged
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals
Aug 2, 2026
Merged

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化#572
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals

Conversation

@yusuke0610

@yusuke0610yusuke0610 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Closes#561

概要

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations / infra_declarations を保持しているのに、キャッシュへ永続化される AnalyzedRepoSummaryfull_name / description / created_at / pushed_at の 4 フィールドだけだった。判別材料を永続化層で捨てているため、ドラフトの選定ロジックは最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを区別できない。

本 PR は永続化層へ経路を通すところまで。選定ロジック自体の変更は #562 が担当する。

変更内容

1. 選定シグナルの追加(後方互換)

フィールド算出元
topicslist[str]RepoData.topics
language_bytes_totalintlanguages の合計
direct_dependency_countintpackage_declarations のうち direct のみ
ecosystem_countintpackage_declarations のエコシステム種別数
has_infraboolinfra_declarations の有無

いずれも既定値を持つため、旧形式 JSON のパースは従来どおり通る。

GitHub API の追加呼び出しはしない — すべて連携実行時に RepoData が取得済みの値で、_to_repo_summary は既存フィールドを参照するだけ。collector には触れていない。

2. 旧形式キャッシュの判定(409 + 再連携導線)

スキーマ側は既定値で受理するが、シグナル無しでの選定は品質を担保できないため、build_draft_source生 JSON のキー有無で判別して 409 へ倒す。ADR-0018 が定めた「repos キー欠落」判定と同じ流儀(Pydantic 検証後は既定値と区別できないため生 JSON を見る)。

1 件でもシグナル無しが混ざれば旧形式扱いにしている。部分的に許容すると、選定が「移行済みリポジトリだけ」に偏って本命を取りこぼすため。

ResumeDraftNoRepositoriesError(再連携では回復しない別導線)と取り違えていないことをテストで assert している。

3. 依存種別 "direct" の SSoT 化

response_mapper に定数を足すと同じ意味の比較が 4 箇所目になり、Rule of Three(.claude/rules/common/duplication.md)を超過するため、概念の定義元である skills/types.pyDEPENDENCY_KIND_DIRECT を置いて本差分の 2 箇所を移行した。

github_collector.py:165 / skills/aggregator.py:217 に残る 2 箇所は差分範囲外のため本 PR では変更しない(特に aggregator.py は mutmut スコープで TDD 手順が要る)。#562 以降で当該ファイルを触る回に併せる。

テスト

新規 5 件:

契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイル(test_resume_draft_mapper / test_resume_draft_api / test_worker/test_resume_draft)を新形式へ更新した。旧契約を固定化したテストは残していない。

検証

  • make ci: pass
  • make codegen-types 実行済み。web/src/api/generated.ts の差分を同 PR に含む(ADR-0007)

注意点

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Repository summaries now include topics, language usage, direct dependency counts, ecosystem counts, and infrastructure indicators.
    • These signals are carried through analysis results to support more informative repository selection and draft generation.
  • Bug Fixes

    • Incomplete or outdated cached repository data is now detected and handled gracefully instead of producing unreliable draft results.
  • Documentation

    • Updated API documentation to describe the new repository metadata, legacy cache compatibility, and relevant error handling.

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations /
infra_declarations を持つのに、キャッシュへ永続化される AnalyzedRepoSummary は
4 フィールドだけで、判別材料を永続化層で捨てていた。そのためドラフトの選定は
最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを
区別できない。
- AnalyzedRepoSummary に選定シグナルを追加(既定値付きで後方互換)
topics / language_bytes_total / direct_dependency_count /
ecosystem_count / has_infra
- response_mapper が RepoData から詰め替える。GitHub API の追加呼び出しはしない
- 旧形式キャッシュ(新キー無し)は build_draft_source が生 JSON のキー有無で
判別し、ADR-0018 と同じ 409 + 再連携導線へ倒す。1 件でも欠けたら旧形式扱いに
して選定が移行済みリポジトリへ偏るのを防ぐ
- 依存種別 "direct" の判定リテラルが 4 箇所に散っていたため、SSoT を
skills/types.py の DEPENDENCY_KIND_DIRECT に置いて本差分の 2 箇所を移行
契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイルを新形式へ更新した。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added backend バックエンド web フロントエンド (web) test テスト追加・修正 agent DevForge Agent labels Aug 2, 2026
@coderabbitai

coderabbitaiBot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, you've reached your PR review limit, so we couldn't start this review.

Next review available in:51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea57bfa1-18f1-42dd-a6ba-8436040c1d1d

📥 Commits

Reviewing files that changed from the base of the PR and between 47e1120 and f5bcc29.

📒 Files selected for processing (2)
  • backend/app/services/agent/resume_draft/context.py
  • backend/tests/test_resume_draft_mapper.py
📝 Walkthrough

Walkthrough

Changes

Repository selection signals

Layer / File(s)Summary
Summary contract and mapping
backend/app/schemas/github_link.py, backend/app/services/intelligence/..., backend/app/services/intelligence/skills/types.py, web/src/api/generated.ts, backend/tests/test_github_link.py
AnalyzedRepoSummary now stores topics, language totals, dependency counts, ecosystem counts, and infrastructure presence. The response mapper derives these values from RepoData.
Cache compatibility and resume-draft validation
backend/app/services/agent/resume_draft/context.py, backend/tests/test_resume_draft_mapper.py, backend/tests/test_resume_draft_api.py, backend/tests/test_worker/test_resume_draft.py
Resume-draft loading rejects legacy and partially migrated caches without selection signals. Test fixtures and assertions cover migrated summaries and signal preservation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
participant RepoData
participant response_mapper
participant AnalyzedRepoSummary
participant resume_draft_context
participant DraftSource
RepoData->>response_mapper: repository metadata and declarations
response_mapper->>AnalyzedRepoSummary: derived selection signals
AnalyzedRepoSummary->>resume_draft_context: cached repository summary
resume_draft_context->>DraftSource: validated repository signals
Loading

Possibly related PRs

Suggested labels:feature

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passedタイトルは、リポジトリ選定シグナルをAnalyzedRepoSummaryへ永続化する主変更を明確に示しています。
Linked Issues check✅ PassedIssue #561の要件に対応し、5つのシグナル、RepoDataからの変換、旧形式キャッシュ判定、生成型、テストを追加しています。
Out of Scope Changes check✅ Passed変更はIssue #561の永続化、旧形式キャッシュ対応、共有定数、テスト、生成型更新に限定されています。
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/561-repo-selection-signals

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.

@coderabbitaicoderabbitaiBot 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: 1

🤖 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 `@backend/app/services/agent/resume_draft/context.py`:
- Around line 43-46: Replace _SELECTION_SIGNAL_KEY with an immutable set
containing all five required ADR-0026 signals: language_bytes_total, topics,
direct_dependency_count, ecosystem_count, and has_infra; update the repository
validation around _SELECTION_SIGNAL_KEY at
backend/app/services/agent/resume_draft/context.py lines 106-114 to reject
dictionaries missing any key and preserve the existing 409 path. Parameterize
the missing-key test at backend/tests/test_resume_draft_mapper.py lines 280-318
to cover each required signal.
🪄 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 Plus

Run ID: 0d873261-6e5d-4f36-bd70-9c8d999152ce

📥 Commits

Reviewing files that changed from the base of the PR and between 77a1c4b and 47e1120.

📒 Files selected for processing (9)
  • backend/app/schemas/github_link.py
  • backend/app/services/agent/resume_draft/context.py
  • backend/app/services/intelligence/response_mapper.py
  • backend/app/services/intelligence/skills/types.py
  • backend/tests/test_github_link.py
  • backend/tests/test_resume_draft_api.py
  • backend/tests/test_resume_draft_mapper.py
  • backend/tests/test_worker/test_resume_draft.py
  • web/src/api/generated.ts

Comment threadbackend/app/services/agent/resume_draft/context.py Outdated
CodeRabbit の指摘(PR #572)を反映する。
代表キー(language_bytes_total)1 つの存在確認では、一部のシグナルだけを持つ
キャッシュが guard を通過してしまう。Pydantic が既定値で欠落を埋めるため、
不完全なデータのまま選定が走る。
- _SELECTION_SIGNAL_KEY を 5 キーの frozenset へ置き換え、issubset で全件必須にする
- 欠落キーごとにテストを parametrize(5 ケース)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit e3e3f17 into mainAug 2, 2026
21 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentDevForge Agentbackendバックエンドtestテスト追加・修正webフロントエンド (web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ドラフト縮小 1/7] backend: リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化

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

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化 - #572

Merged
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals
Aug 2, 2026
Merged

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化#572
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals

Conversation

@yusuke0610

@yusuke0610yusuke0610 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Closes#561

概要

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations / infra_declarations を保持しているのに、キャッシュへ永続化される AnalyzedRepoSummaryfull_name / description / created_at / pushed_at の 4 フィールドだけだった。判別材料を永続化層で捨てているため、ドラフトの選定ロジックは最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを区別できない。

本 PR は永続化層へ経路を通すところまで。選定ロジック自体の変更は #562 が担当する。

変更内容

1. 選定シグナルの追加(後方互換)

フィールド算出元
topicslist[str]RepoData.topics
language_bytes_totalintlanguages の合計
direct_dependency_countintpackage_declarations のうち direct のみ
ecosystem_countintpackage_declarations のエコシステム種別数
has_infraboolinfra_declarations の有無

いずれも既定値を持つため、旧形式 JSON のパースは従来どおり通る。

GitHub API の追加呼び出しはしない — すべて連携実行時に RepoData が取得済みの値で、_to_repo_summary は既存フィールドを参照するだけ。collector には触れていない。

2. 旧形式キャッシュの判定(409 + 再連携導線)

スキーマ側は既定値で受理するが、シグナル無しでの選定は品質を担保できないため、build_draft_source生 JSON のキー有無で判別して 409 へ倒す。ADR-0018 が定めた「repos キー欠落」判定と同じ流儀(Pydantic 検証後は既定値と区別できないため生 JSON を見る)。

1 件でもシグナル無しが混ざれば旧形式扱いにしている。部分的に許容すると、選定が「移行済みリポジトリだけ」に偏って本命を取りこぼすため。

ResumeDraftNoRepositoriesError(再連携では回復しない別導線)と取り違えていないことをテストで assert している。

3. 依存種別 "direct" の SSoT 化

response_mapper に定数を足すと同じ意味の比較が 4 箇所目になり、Rule of Three(.claude/rules/common/duplication.md)を超過するため、概念の定義元である skills/types.pyDEPENDENCY_KIND_DIRECT を置いて本差分の 2 箇所を移行した。

github_collector.py:165 / skills/aggregator.py:217 に残る 2 箇所は差分範囲外のため本 PR では変更しない(特に aggregator.py は mutmut スコープで TDD 手順が要る)。#562 以降で当該ファイルを触る回に併せる。

テスト

新規 5 件:

契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイル(test_resume_draft_mapper / test_resume_draft_api / test_worker/test_resume_draft)を新形式へ更新した。旧契約を固定化したテストは残していない。

検証

  • make ci: pass
  • make codegen-types 実行済み。web/src/api/generated.ts の差分を同 PR に含む(ADR-0007)

注意点

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Repository summaries now include topics, language usage, direct dependency counts, ecosystem counts, and infrastructure indicators.
    • These signals are carried through analysis results to support more informative repository selection and draft generation.
  • Bug Fixes

    • Incomplete or outdated cached repository data is now detected and handled gracefully instead of producing unreliable draft results.
  • Documentation

    • Updated API documentation to describe the new repository metadata, legacy cache compatibility, and relevant error handling.

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations /
infra_declarations を持つのに、キャッシュへ永続化される AnalyzedRepoSummary は
4 フィールドだけで、判別材料を永続化層で捨てていた。そのためドラフトの選定は
最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを
区別できない。
- AnalyzedRepoSummary に選定シグナルを追加(既定値付きで後方互換)
topics / language_bytes_total / direct_dependency_count /
ecosystem_count / has_infra
- response_mapper が RepoData から詰め替える。GitHub API の追加呼び出しはしない
- 旧形式キャッシュ(新キー無し)は build_draft_source が生 JSON のキー有無で
判別し、ADR-0018 と同じ 409 + 再連携導線へ倒す。1 件でも欠けたら旧形式扱いに
して選定が移行済みリポジトリへ偏るのを防ぐ
- 依存種別 "direct" の判定リテラルが 4 箇所に散っていたため、SSoT を
skills/types.py の DEPENDENCY_KIND_DIRECT に置いて本差分の 2 箇所を移行
契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイルを新形式へ更新した。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added backend バックエンド web フロントエンド (web) test テスト追加・修正 agent DevForge Agent labels Aug 2, 2026
@coderabbitai

coderabbitaiBot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, you've reached your PR review limit, so we couldn't start this review.

Next review available in:51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea57bfa1-18f1-42dd-a6ba-8436040c1d1d

📥 Commits

Reviewing files that changed from the base of the PR and between 47e1120 and f5bcc29.

📒 Files selected for processing (2)
  • backend/app/services/agent/resume_draft/context.py
  • backend/tests/test_resume_draft_mapper.py
📝 Walkthrough

Walkthrough

Changes

Repository selection signals

Layer / File(s)Summary
Summary contract and mapping
backend/app/schemas/github_link.py, backend/app/services/intelligence/..., backend/app/services/intelligence/skills/types.py, web/src/api/generated.ts, backend/tests/test_github_link.py
AnalyzedRepoSummary now stores topics, language totals, dependency counts, ecosystem counts, and infrastructure presence. The response mapper derives these values from RepoData.
Cache compatibility and resume-draft validation
backend/app/services/agent/resume_draft/context.py, backend/tests/test_resume_draft_mapper.py, backend/tests/test_resume_draft_api.py, backend/tests/test_worker/test_resume_draft.py
Resume-draft loading rejects legacy and partially migrated caches without selection signals. Test fixtures and assertions cover migrated summaries and signal preservation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
participant RepoData
participant response_mapper
participant AnalyzedRepoSummary
participant resume_draft_context
participant DraftSource
RepoData->>response_mapper: repository metadata and declarations
response_mapper->>AnalyzedRepoSummary: derived selection signals
AnalyzedRepoSummary->>resume_draft_context: cached repository summary
resume_draft_context->>DraftSource: validated repository signals
Loading

Possibly related PRs

Suggested labels:feature

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passedタイトルは、リポジトリ選定シグナルをAnalyzedRepoSummaryへ永続化する主変更を明確に示しています。
Linked Issues check✅ PassedIssue #561の要件に対応し、5つのシグナル、RepoDataからの変換、旧形式キャッシュ判定、生成型、テストを追加しています。
Out of Scope Changes check✅ Passed変更はIssue #561の永続化、旧形式キャッシュ対応、共有定数、テスト、生成型更新に限定されています。
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/561-repo-selection-signals

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.

@coderabbitaicoderabbitaiBot 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: 1

🤖 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 `@backend/app/services/agent/resume_draft/context.py`:
- Around line 43-46: Replace _SELECTION_SIGNAL_KEY with an immutable set
containing all five required ADR-0026 signals: language_bytes_total, topics,
direct_dependency_count, ecosystem_count, and has_infra; update the repository
validation around _SELECTION_SIGNAL_KEY at
backend/app/services/agent/resume_draft/context.py lines 106-114 to reject
dictionaries missing any key and preserve the existing 409 path. Parameterize
the missing-key test at backend/tests/test_resume_draft_mapper.py lines 280-318
to cover each required signal.
🪄 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 Plus

Run ID: 0d873261-6e5d-4f36-bd70-9c8d999152ce

📥 Commits

Reviewing files that changed from the base of the PR and between 77a1c4b and 47e1120.

📒 Files selected for processing (9)
  • backend/app/schemas/github_link.py
  • backend/app/services/agent/resume_draft/context.py
  • backend/app/services/intelligence/response_mapper.py
  • backend/app/services/intelligence/skills/types.py
  • backend/tests/test_github_link.py
  • backend/tests/test_resume_draft_api.py
  • backend/tests/test_resume_draft_mapper.py
  • backend/tests/test_worker/test_resume_draft.py
  • web/src/api/generated.ts

Comment threadbackend/app/services/agent/resume_draft/context.py Outdated
CodeRabbit の指摘(PR #572)を反映する。
代表キー(language_bytes_total)1 つの存在確認では、一部のシグナルだけを持つ
キャッシュが guard を通過してしまう。Pydantic が既定値で欠落を埋めるため、
不完全なデータのまま選定が走る。
- _SELECTION_SIGNAL_KEY を 5 キーの frozenset へ置き換え、issubset で全件必須にする
- 欠落キーごとにテストを parametrize(5 ケース)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit e3e3f17 into mainAug 2, 2026
21 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentDevForge Agentbackendバックエンドtestテスト追加・修正webフロントエンド (web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ドラフト縮小 1/7] backend: リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化

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

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化 - #572

Merged
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals
Aug 2, 2026
Merged

[ドラフト縮小 1/7] リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化#572
yusuke0610 merged 2 commits into
mainfrom
feat/561-repo-selection-signals

Conversation

@yusuke0610

@yusuke0610yusuke0610 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Closes#561

概要

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations / infra_declarations を保持しているのに、キャッシュへ永続化される AnalyzedRepoSummaryfull_name / description / created_at / pushed_at の 4 フィールドだけだった。判別材料を永続化層で捨てているため、ドラフトの選定ロジックは最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを区別できない。

本 PR は永続化層へ経路を通すところまで。選定ロジック自体の変更は #562 が担当する。

変更内容

1. 選定シグナルの追加(後方互換)

フィールド算出元
topicslist[str]RepoData.topics
language_bytes_totalintlanguages の合計
direct_dependency_countintpackage_declarations のうち direct のみ
ecosystem_countintpackage_declarations のエコシステム種別数
has_infraboolinfra_declarations の有無

いずれも既定値を持つため、旧形式 JSON のパースは従来どおり通る。

GitHub API の追加呼び出しはしない — すべて連携実行時に RepoData が取得済みの値で、_to_repo_summary は既存フィールドを参照するだけ。collector には触れていない。

2. 旧形式キャッシュの判定(409 + 再連携導線)

スキーマ側は既定値で受理するが、シグナル無しでの選定は品質を担保できないため、build_draft_source生 JSON のキー有無で判別して 409 へ倒す。ADR-0018 が定めた「repos キー欠落」判定と同じ流儀(Pydantic 検証後は既定値と区別できないため生 JSON を見る)。

1 件でもシグナル無しが混ざれば旧形式扱いにしている。部分的に許容すると、選定が「移行済みリポジトリだけ」に偏って本命を取りこぼすため。

ResumeDraftNoRepositoriesError(再連携では回復しない別導線)と取り違えていないことをテストで assert している。

3. 依存種別 "direct" の SSoT 化

response_mapper に定数を足すと同じ意味の比較が 4 箇所目になり、Rule of Three(.claude/rules/common/duplication.md)を超過するため、概念の定義元である skills/types.pyDEPENDENCY_KIND_DIRECT を置いて本差分の 2 箇所を移行した。

github_collector.py:165 / skills/aggregator.py:217 に残る 2 箇所は差分範囲外のため本 PR では変更しない(特に aggregator.py は mutmut スコープで TDD 手順が要る)。#562 以降で当該ファイルを触る回に併せる。

テスト

新規 5 件:

契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイル(test_resume_draft_mapper / test_resume_draft_api / test_worker/test_resume_draft)を新形式へ更新した。旧契約を固定化したテストは残していない。

検証

  • make ci: pass
  • make codegen-types 実行済み。web/src/api/generated.ts の差分を同 PR に含む(ADR-0007)

注意点

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Repository summaries now include topics, language usage, direct dependency counts, ecosystem counts, and infrastructure indicators.
    • These signals are carried through analysis results to support more informative repository selection and draft generation.
  • Bug Fixes

    • Incomplete or outdated cached repository data is now detected and handled gracefully instead of producing unreliable draft results.
  • Documentation

    • Updated API documentation to describe the new repository metadata, legacy cache compatibility, and relevant error handling.

ADR-0026 決定 4。収集層の RepoData は topics / package_declarations /
infra_declarations を持つのに、キャッシュへ永続化される AnalyzedRepoSummary は
4 フィールドだけで、判別材料を永続化層で捨てていた。そのためドラフトの選定は
最終 push 日時と言語バイト数しか使えず、チュートリアルと実プロジェクトを
区別できない。
- AnalyzedRepoSummary に選定シグナルを追加(既定値付きで後方互換)
topics / language_bytes_total / direct_dependency_count /
ecosystem_count / has_infra
- response_mapper が RepoData から詰め替える。GitHub API の追加呼び出しはしない
- 旧形式キャッシュ(新キー無し)は build_draft_source が生 JSON のキー有無で
判別し、ADR-0018 と同じ 409 + 再連携導線へ倒す。1 件でも欠けたら旧形式扱いに
して選定が移行済みリポジトリへ偏るのを防ぐ
- 依存種別 "direct" の判定リテラルが 4 箇所に散っていたため、SSoT を
skills/types.py の DEPENDENCY_KIND_DIRECT に置いて本差分の 2 箇所を移行
契約変更に伴い、旧形式 fixture を持つ既存テスト 3 ファイルを新形式へ更新した。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added backend バックエンド web フロントエンド (web) test テスト追加・修正 agent DevForge Agent labels Aug 2, 2026
@coderabbitai

coderabbitaiBot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, you've reached your PR review limit, so we couldn't start this review.

Next review available in:51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea57bfa1-18f1-42dd-a6ba-8436040c1d1d

📥 Commits

Reviewing files that changed from the base of the PR and between 47e1120 and f5bcc29.

📒 Files selected for processing (2)
  • backend/app/services/agent/resume_draft/context.py
  • backend/tests/test_resume_draft_mapper.py
📝 Walkthrough

Walkthrough

Changes

Repository selection signals

Layer / File(s)Summary
Summary contract and mapping
backend/app/schemas/github_link.py, backend/app/services/intelligence/..., backend/app/services/intelligence/skills/types.py, web/src/api/generated.ts, backend/tests/test_github_link.py
AnalyzedRepoSummary now stores topics, language totals, dependency counts, ecosystem counts, and infrastructure presence. The response mapper derives these values from RepoData.
Cache compatibility and resume-draft validation
backend/app/services/agent/resume_draft/context.py, backend/tests/test_resume_draft_mapper.py, backend/tests/test_resume_draft_api.py, backend/tests/test_worker/test_resume_draft.py
Resume-draft loading rejects legacy and partially migrated caches without selection signals. Test fixtures and assertions cover migrated summaries and signal preservation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
participant RepoData
participant response_mapper
participant AnalyzedRepoSummary
participant resume_draft_context
participant DraftSource
RepoData->>response_mapper: repository metadata and declarations
response_mapper->>AnalyzedRepoSummary: derived selection signals
AnalyzedRepoSummary->>resume_draft_context: cached repository summary
resume_draft_context->>DraftSource: validated repository signals
Loading

Possibly related PRs

Suggested labels:feature

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passedタイトルは、リポジトリ選定シグナルをAnalyzedRepoSummaryへ永続化する主変更を明確に示しています。
Linked Issues check✅ PassedIssue #561の要件に対応し、5つのシグナル、RepoDataからの変換、旧形式キャッシュ判定、生成型、テストを追加しています。
Out of Scope Changes check✅ Passed変更はIssue #561の永続化、旧形式キャッシュ対応、共有定数、テスト、生成型更新に限定されています。
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/561-repo-selection-signals

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.

@coderabbitaicoderabbitaiBot 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: 1

🤖 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 `@backend/app/services/agent/resume_draft/context.py`:
- Around line 43-46: Replace _SELECTION_SIGNAL_KEY with an immutable set
containing all five required ADR-0026 signals: language_bytes_total, topics,
direct_dependency_count, ecosystem_count, and has_infra; update the repository
validation around _SELECTION_SIGNAL_KEY at
backend/app/services/agent/resume_draft/context.py lines 106-114 to reject
dictionaries missing any key and preserve the existing 409 path. Parameterize
the missing-key test at backend/tests/test_resume_draft_mapper.py lines 280-318
to cover each required signal.
🪄 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 Plus

Run ID: 0d873261-6e5d-4f36-bd70-9c8d999152ce

📥 Commits

Reviewing files that changed from the base of the PR and between 77a1c4b and 47e1120.

📒 Files selected for processing (9)
  • backend/app/schemas/github_link.py
  • backend/app/services/agent/resume_draft/context.py
  • backend/app/services/intelligence/response_mapper.py
  • backend/app/services/intelligence/skills/types.py
  • backend/tests/test_github_link.py
  • backend/tests/test_resume_draft_api.py
  • backend/tests/test_resume_draft_mapper.py
  • backend/tests/test_worker/test_resume_draft.py
  • web/src/api/generated.ts

Comment threadbackend/app/services/agent/resume_draft/context.py Outdated
CodeRabbit の指摘(PR #572)を反映する。
代表キー(language_bytes_total)1 つの存在確認では、一部のシグナルだけを持つ
キャッシュが guard を通過してしまう。Pydantic が既定値で欠落を埋めるため、
不完全なデータのまま選定が走る。
- _SELECTION_SIGNAL_KEY を 5 キーの frozenset へ置き換え、issubset で全件必須にする
- 欠落キーごとにテストを parametrize(5 ケース)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit e3e3f17 into mainAug 2, 2026
21 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentDevForge Agentbackendバックエンドtestテスト追加・修正webフロントエンド (web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ドラフト縮小 1/7] backend: リポジトリ選定シグナルを AnalyzedRepoSummary へ永続化

1 participant

@yusuke0610