Skip to content

feat(intelligence): GitHub スキル推論に verify ステージ(import 解析)を追加#445

Merged
yusuke0610 merged 2 commits into
mainfrom
feat/skill-verify-import-analysis
Jun 30, 2026
Merged

feat(intelligence): GitHub スキル推論に verify ステージ(import 解析)を追加#445
yusuke0610 merged 2 commits into
mainfrom
feat/skill-verify-import-analysis

Conversation

@yusuke0610

@yusuke0610 yusuke0610 commented Jun 30, 2026

Copy link
Copy Markdown
Owner

概要

ADR-0016「GitHub 連携によるスキル推論基盤」の残タスク タスク1(verify ステージ / D6) を実装。direct 依存が実際に import されているかをソース解析で確認し、manifest_declared(宣言)を actual_import(実使用)証跡へ昇格させる(昇格のみ・降格なし。declare 証跡は保持 / D8「保持は細かく」)。

declare までで経歴書は出力可能、verify は精度を後追いで上げる位置づけ(D5)。

変更内容

  • github/api_client.py: fetch_manifest_pathsfetch_repo_tree(recursive Trees を 1 コールで全 blob パス取得)に分離。manifest 探索(declare)と import 解析(verify)が同一ツリーを共有し、verify のために tree を再取得しない(D9(a) 維持)
  • 新規 skills/imports/: ImportScanner plugin(go / python / js_ts / rust)+ registry。辞書を持たず(D3)、エコシステム別の保守的照合で実 import を判定:
    • go: import パス完全一致 or module/... 接頭辞一致
    • npm: specifier == package(@scope/name / subpath 対応)
    • pypi / cargo: -_ 変換後の一致
    • import 名乖離(PyYAMLyaml 等)は昇格漏れ(false negative)として受容(テストで明示固定)
  • github_collector.py: _collect_manifests_collect_repo_signals に拡張。1 ツリーから manifest 宣言と、direct 宣言のあるエコシステムの source を除外セグメント/浅い順/件数キャップ(30件)でサンプリング → import 解析。生コードは scan 後に破棄(永続化しない / D6)
  • skills/aggregator.py: RepoSkillInput.imported_symbols を追加。direct かつ import 検出時に actual_import 証跡(confidence 0.85)を追加
  • テスト追加: import スキャナ(test_skill_import_scanners.py)/ aggregator verify / collector verify / api_client tree

判断事項

  • 設計分岐: import 照合は辞書レス・保守的マッチ。Python の import 名乖離は false negative として受容(昇格漏れのみで害なし)
  • 挙動変更: GET /api/github-link/skills の evidence に direct 依存で actual_import が増える(既存 manifest_declared は残存)
  • スキーマ不変: signal_source は既存値域内(actual_import は model/schema に既記載)→ migration 不要・codegen drift なし
  • コスト: verify でリポあたり最大 30 ソースファイルの追加 fetch(同一ツリー再利用で tree API 呼び出しは増やさない)

テスト

  • make ci green(backend lint+test / web / build)
  • codegen drift なし
  • E2E 不要(UI フロー不変。evidence 配列が増えるのみ)

補足(別 PR 予定)

skills/imports/ および skills/manifests/ の Protocol 属性に対する pyright 型注釈(extensions: tuple[str, ...] 等の invariance 対応)は、本 PR と分離して別 PR で対応します。

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added import-scanning support for multiple ecosystems, including Python, JavaScript/TypeScript, Go, and Rust.
    • Enhanced repository analysis to capture both declared dependencies and actual imports from source files.
    • Added support for additional evidence when a declared dependency is confirmed in code.
  • Bug Fixes

    • Improved handling of repository tree traversal, including partial/truncated results and invalid repository inputs.
    • Refined dependency matching rules for common naming differences and package subpaths.

ADR-0016 D6 を実装。direct 依存が実際に import されているかをソース解析で確認し、
manifest_declared を actual_import 証跡へ昇格させる(昇格のみ・降格なし)。

- api_client: fetch_repo_tree を新設し recursive Trees を 1 コール化。
  manifest 探索と import 解析が同一ツリーを共有(tree 再取得しない / D9(a))
- skills/imports/: ImportScanner plugin(go/python/js_ts/rust)。辞書レスの
  保守的照合(-→_ 変換 / go 接頭辞一致 / npm 完全一致)。取りこぼしは false negative 受容
- github_collector: _collect_repo_signals で manifest 宣言 + direct エコシステムの
  source を除外/浅い順/件数キャップ(30)でサンプリング→import 解析。生コードは scan 後破棄
- aggregator: direct かつ import 検出時に actual_import 証跡(confidence 0.85)を追加
- テスト追加(import スキャナ / aggregator verify / collector / api_client tree)

API スキーマ・型は不変(signal_source 値域内)。migration / codegen drift なし。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the feature 新機能 label Jun 30, 2026
@coderabbitai

coderabbitai Bot commented Jun 30, 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: 42 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: 155fd2ee-a086-4e0e-9c84-059f3d7fed15

📥 Commits

Reviewing files that changed from the base of the PR and between 1a68f7f and 7fc60d4.

📒 Files selected for processing (4)
  • backend/app/services/intelligence/github_collector.py
  • backend/app/services/intelligence/skills/imports/js_ts.py
  • backend/app/services/intelligence/skills/imports/rust.py
  • backend/tests/test_skill_import_scanners.py
📝 Walkthrough

Walkthrough

Implements the D6 verify stage for GitHub skill inference: introduces an imports/ plugin package with ImportScanner protocol and ecosystem-specific implementations (Go, Python, JS/TS, Rust), replaces fetch_manifest_paths with a general fetch_repo_tree, unifies manifest and source scanning in _collect_repo_signals, and promotes confirmed direct-dependency imports to actual_import evidence in the skill aggregator.

Changes

D6 Verify Stage: Import Scanner Plugins and actual_import Evidence

Layer / File(s) Summary
ImportScanner protocol and registry
backend/app/services/intelligence/skills/imports/base.py, backend/app/services/intelligence/skills/imports/registry.py, backend/app/services/intelligence/skills/imports/__init__.py
Defines the runtime_checkable ImportScanner Protocol with extensions, ecosystem, scan, and matches contracts. Registry instantiates Tier1 scanners and exposes scanner_for_ecosystem, scanner_for_extension, and SOURCE_EXTENSIONS.
Ecosystem scanner implementations
backend/app/services/intelligence/skills/imports/go.py, backend/app/services/intelligence/skills/imports/python.py, backend/app/services/intelligence/skills/imports/js_ts.py, backend/app/services/intelligence/skills/imports/rust.py
Adds Go (exact + subpackage prefix match), Python (PEP 503 dash-to-underscore normalization), JS/TS (scoped package canonicalization, require/import extraction), and Rust (use/extern crate with reserved-segment exclusion) ImportScanner implementations.
Replace fetch_manifest_paths with fetch_repo_tree
backend/app/services/intelligence/github/api_client.py, backend/tests/test_github_api_client.py
Removes the manifest-name-filtered tree traversal and replaces it with fetch_repo_tree returning all blob paths, with ([], False) for invalid repos, (paths, True) for truncated, and ([], True) for HTTP/network errors. Tests updated accordingly.
Unified _collect_repo_signals
backend/app/services/intelligence/github_collector.py, backend/tests/test_github_collector_extended.py
Replaces _collect_manifests with _collect_repo_signals, which reuses the single fetch_repo_tree result to extract both package_declarations and imported_symbols (source files scanned only for direct-dependency ecosystems). Adds RepoData.imported_symbols, _SOURCE_MAX_COUNT/_SOURCE_MAX_DEPTH limits, and unified partial-scan flag.
actual_import evidence promotion in aggregator
backend/app/services/intelligence/skills/aggregator.py, backend/app/services/intelligence/github_link_service.py
Extends RepoSkillInput with imported_symbols, adds _is_imported helper and _SIGNAL_ACTUAL_IMPORT/_ACTUAL_IMPORT_CONFIDENCE constants. For direct declarations confirmed by the ecosystem scanner, appends an actual_import evidence record without downgrading existing manifest_declared evidence. github_link_service wires repo.imported_symbols into RepoSkillInput.
Scanner tests, aggregator verify tests, and ADR update
backend/tests/test_skill_import_scanners.py, backend/tests/test_skill_aggregator.py, docs/adr/0016-github-skill-inference.md, .claude/rules/backend/architecture.md
Adds full scanner unit tests (registry dispatch, per-ecosystem scan/matches including false-negative cases), aggregator verify tests (direct promoted, dev not promoted, Go subpackage prefix), and updates ADR-0016 with the implemented D6 design and revision history entry.

Sequence Diagram(s)

sequenceDiagram
  participant collect_repos
  participant _collect_repo_signals
  participant fetch_repo_tree as GitHub Trees API
  participant parse_manifest
  participant ImportScanner

  collect_repos->>_collect_repo_signals: repo metadata (owner/repo/branch)
  _collect_repo_signals->>fetch_repo_tree: recursive tree request
  fetch_repo_tree-->>_collect_repo_signals: (all_blob_paths, truncated)
  _collect_repo_signals->>parse_manifest: manifest file contents
  parse_manifest-->>_collect_repo_signals: package_declarations (with dependency_kind)
  _collect_repo_signals->>ImportScanner: source files for direct-dep ecosystems only
  ImportScanner-->>_collect_repo_signals: imported_symbols per ecosystem
  _collect_repo_signals-->>collect_repos: (decls, imported_symbols, scan_partial)

  Note over collect_repos: RepoData.imported_symbols populated

  collect_repos->>aggregator: RepoSkillInput(imported_symbols=...)
  aggregator->>ImportScanner: scanner_for_ecosystem + matches(canonical_name, imported)
  ImportScanner-->>aggregator: bool
  aggregator-->>collect_repos: EvidenceRecord(actual_import) appended if matched
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • yusuke0610/devforge#408: Introduced the ADR-0016 3-layer schema, persistence, and manifest-declare parsing that this PR extends with the D6 verify stage and actual_import promotion.
  • yusuke0610/devforge#417: Introduced the earlier fetch_manifest_paths Trees API approach in github/api_client.py that this PR replaces with the generalized fetch_repo_tree.

Poem

🐇 A rabbit hops through code so wide,
Scanning imports far and near with pride,
go, pypi, npm, cargo too—
Each blob path checked, direct or new.
actual_import earned, not merely declared,
Evidence stacked, the truth is bared! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a verify stage with import analysis to GitHub skill inference.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/skill-verify-import-analysis

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.

@github-actions github-actions Bot added documentation Improvements or additions to documentation backend バックエンド test テスト追加・修正 labels Jun 30, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
backend/app/services/intelligence/github_collector.py (1)

149-168: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Optional: avoid the duplicate scanner_for_extension lookup.

scanner_for_extension(path) is computed once to build source_candidates and recomputed inside the selection loop. You can carry the scanner alongside the path to avoid the second lookup.

♻️ Possible refactor
-        source_candidates = []
+        source_candidates: list[tuple[str, object]] = []
         for path in tree_paths:
             scanner = scanner_for_extension(path)
             if scanner is not None and scanner.ecosystem in direct_ecosystems:
-                source_candidates.append(path)
-        selected_sources, source_dropped = _select_shallow(
-            source_candidates, _SOURCE_MAX_DEPTH, _SOURCE_MAX_COUNT
-        )
-        for path in selected_sources:
-            scanner = scanner_for_extension(path)
-            if scanner is None:
-                continue
+                source_candidates.append((path, scanner))
+        selected_paths, source_dropped = _select_shallow(
+            [p for p, _ in source_candidates], _SOURCE_MAX_DEPTH, _SOURCE_MAX_COUNT
+        )
+        scanner_by_path = dict(source_candidates)
+        for path in selected_paths:
+            scanner = scanner_by_path[path]
             content = await fetch_repo_file(client, owner, repo, path)
             if not content:
                 continue
             imported_symbols.setdefault(scanner.ecosystem, set()).update(
                 scanner.scan(content)
             )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/intelligence/github_collector.py` around lines 149 -
168, Avoid recomputing scanner_for_extension(path) in the direct_ecosystems path
selection flow: in the logic that builds source_candidates and then iterates
selected_sources, carry the scanner together with each path so the same scanner
object can be reused after _select_shallow. Update the selected_sources loop in
github_collector.py to use the precomputed scanner instead of looking it up
again, while keeping the existing fetch_repo_file and imported_symbols update
behavior unchanged.
🤖 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/intelligence/skills/imports/js_ts.py`:
- Around line 12-14: The import scanner in js_ts.py is matching require/import
text inside comments, docs, and string literals, which can create false
positives in imported_symbols and incorrectly mark packages as actual imports.
Update the extraction logic around _SPEC_RE and the JS/TS import parsing path to
ignore comments and string contents before matching, preferably by using a
token/AST-based approach or a preprocessing step that strips non-code regions
before applying the regex.

In `@backend/app/services/intelligence/skills/imports/rust.py`:
- Around line 11-24: Update the Rust import scanner so `RustImportScanner.scan`
also detects re-exported imports like `pub use` and `pub(crate) use`, not just
plain `use` statements. Adjust `_USE_RE` in the Rust import module to allow an
optional visibility prefix before `use`, while keeping the existing
`RustImportScanner`, `_USE_RE`, and `_NON_CRATE` behavior unchanged for
filtering and external-crate detection.

---

Nitpick comments:
In `@backend/app/services/intelligence/github_collector.py`:
- Around line 149-168: Avoid recomputing scanner_for_extension(path) in the
direct_ecosystems path selection flow: in the logic that builds
source_candidates and then iterates selected_sources, carry the scanner together
with each path so the same scanner object can be reused after _select_shallow.
Update the selected_sources loop in github_collector.py to use the precomputed
scanner instead of looking it up again, while keeping the existing
fetch_repo_file and imported_symbols update behavior unchanged.
🪄 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: 5fe0422c-62e3-4ccd-9bcc-be3c58ff04ba

📥 Commits

Reviewing files that changed from the base of the PR and between b152643 and 1a68f7f.

📒 Files selected for processing (17)
  • .claude/rules/backend/architecture.md
  • backend/app/services/intelligence/github/api_client.py
  • backend/app/services/intelligence/github_collector.py
  • backend/app/services/intelligence/github_link_service.py
  • backend/app/services/intelligence/skills/aggregator.py
  • backend/app/services/intelligence/skills/imports/__init__.py
  • backend/app/services/intelligence/skills/imports/base.py
  • backend/app/services/intelligence/skills/imports/go.py
  • backend/app/services/intelligence/skills/imports/js_ts.py
  • backend/app/services/intelligence/skills/imports/python.py
  • backend/app/services/intelligence/skills/imports/registry.py
  • backend/app/services/intelligence/skills/imports/rust.py
  • backend/tests/test_github_api_client.py
  • backend/tests/test_github_collector_extended.py
  • backend/tests/test_skill_aggregator.py
  • backend/tests/test_skill_import_scanners.py
  • docs/adr/0016-github-skill-inference.md

Comment on lines +12 to +14
_SPEC_RE = re.compile(
r"""(?:\bfrom|\bimport|\brequire)\s*\(?\s*["']([^"']+)["']""",
)

@coderabbitai coderabbitai Bot Jun 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== file outline ==\n'
ast-grep outline backend/app/services/intelligence/skills/imports/js_ts.py --view expanded || true

printf '\n== target file excerpt ==\n'
nl -ba backend/app/services/intelligence/skills/imports/js_ts.py | sed -n '1,220p'

printf '\n== search downstream usages ==\n'
rg -n "imported_symbols|manifest_declared|actual_import|_SPEC_RE" backend/app/services -S

printf '\n== related tests ==\n'
rg -n "exclude.*relative|imported_symbols|manifest_declared|actual_import|require\\(" backend -g '*test*' -g '*spec*' -S

Repository: yusuke0610/devforge

Length of output: 632


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== target file ==\n'
sed -n '1,220p' backend/app/services/intelligence/skills/imports/js_ts.py | cat -n

printf '\n== related code ==\n'
rg -n "imported_symbols|manifest_declared|actual_import|JsTsImportScanner|_SPEC_RE" backend/app/services -S

printf '\n== tests ==\n'
rg -n "JsTsImportScanner|imported_symbols|manifest_declared|actual_import|require\\(" backend -g '*test*' -g '*spec*' -S

Repository: yusuke0610/devforge

Length of output: 6555


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== scanner tests ==\n'
sed -n '1,220p' backend/tests/test_skill_import_scanners.py | cat -n

printf '\n== aggregator tests around actual_import ==\n'
sed -n '160,260p' backend/tests/test_skill_aggregator.py | cat -n

printf '\n== regex probe ==\n'
python3 - <<'PY'
import re
spec_re = re.compile(r'''(?:\bfrom|\bimport|\brequire)\s*\(?\s*["']([^"']+)["']''')
cases = {
    "line_comment": "// require(\"react\")",
    "block_comment": "/* import 'left-pad' */",
    "string_literal": "const s = 'import(\"lodash\")'",
    "real_require": "const x = require('lodash');",
    "real_import": "import {x} from '`@scope/pkg/subpath`';",
    "dynamic_import": "const m = import('vite');",
    "example_text": "docs: import('react') in README",
}
for name, text in cases.items():
    print(name, spec_re.findall(text))
PY

Repository: yusuke0610/devforge

Length of output: 8860


Strip comments and string literals before scanning JS/TS imports
backend/app/services/intelligence/skills/imports/js_ts.py:12-40
This regex also matches text inside comments, docs, and string literals (// require("react"), 'import("lodash")'), so imported_symbols can include packages that never appear in real import syntax and wrongly promote manifest_declared to actual_import. Switch to token/AST-based extraction, or preprocess the file to exclude comments and strings before matching.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/intelligence/skills/imports/js_ts.py` around lines 12 -
14, The import scanner in js_ts.py is matching require/import text inside
comments, docs, and string literals, which can create false positives in
imported_symbols and incorrectly mark packages as actual imports. Update the
extraction logic around _SPEC_RE and the JS/TS import parsing path to ignore
comments and string contents before matching, preferably by using a
token/AST-based approach or a preprocessing step that strips non-code regions
before applying the regex.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@coderabbitai RVして

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== git head ==\n'
git rev-parse --short HEAD

printf '\n== file outline ==\n'
ast-grep outline backend/app/services/intelligence/skills/imports/js_ts.py --view expanded || true

printf '\n== current js_ts.py ==\n'
nl -ba backend/app/services/intelligence/skills/imports/js_ts.py | sed -n '1,220p'

printf '\n== related scanner tests ==\n'
nl -ba backend/tests/test_skill_import_scanners.py | sed -n '1,260p'

printf '\n== search for new comment/string stripping logic ==\n'
rg -n -C2 "comment|string|strip|token|lexer|scan\(" backend/app/services/intelligence/skills/imports backend/tests/test_skill_import_scanners.py -S

Length of output: 1624


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== current js_ts.py ==\n'
cat -n backend/app/services/intelligence/skills/imports/js_ts.py | sed -n '1,220p'

printf '\n== JS/TS scanner tests excerpt ==\n'
cat -n backend/tests/test_skill_import_scanners.py | sed -n '40,180p'

printf '\n== focused grep around false-positive coverage ==\n'
rg -n -C3 "comment|string literal|string_literal|relative_imports_excluded|require\\(|import\\(" backend/tests/test_skill_import_scanners.py backend/app/services/intelligence/skills/imports/js_ts.py -S

Length of output: 14549


@yusuke0610, 再RVしました。

  • コメント内の誤検出は解消されています。backend/app/services/intelligence/skills/imports/js_ts.pyLine 16-Line 28 でコメント除去が入り、Line 50 でそれを通してから走査しています。
  • そのうえで、backend/tests/test_skill_import_scanners.pyLine 90-Line 97 に回帰テストも追加されていました。

一方で、string literal 内の import("x") / require("x") 風テキストについては、backend/app/services/intelligence/skills/imports/js_ts.pyLine 25-Line 26 にある通り、現状は意図的に未対応です。

なので結論としては:

  • 元コメントのうち 「comments/docs で誤検出する」部分は解消済み
  • 「string literals でも誤検出しうる」部分はまだ残っている

という状態です。
必要なら、元の指摘は少し広すぎたので、コメント起因の部分は取り下げて、string literal 限定の懸念に絞るのが正確です。


🧠 Learnings used
Learnt from: yusuke0610
Repo: yusuke0610/devforge PR: 265
File: backend/app/routers/resume_imports.py:165-168
Timestamp: 2026-05-22T11:50:08.476Z
Learning: Follow the devforge project rule in `.claude/CLAUDE.md`: during code review, do NOT ask for extra error handling/fallbacks/defensive validation for states that are guaranteed not to occur by system invariants. Treat data written by the system’s own handlers within the same DB transaction (and tied to the same commit/invariant—e.g., fields associated with `status="completed"`) as trusted. Apply validation only at system boundaries (user input and external APIs) or when data can change across transaction boundaries / originate outside the trusted handler path. Example: keep `json.loads(record.result_json)` unguarded in `backend/app/routers/resume_imports.py` when `result_json` is guaranteed valid by the same handler that sets the corresponding completion status.

Comment thread backend/app/services/intelligence/skills/imports/rust.py Outdated
- js_ts: コメント(// と /* */)を除去してから import を走査。コメント内の
  import/require 誤検出による actual_import 誤昇格を防止(URL の // は保護)
- rust: pub use / pub(crate) use の re-export も外部クレート使用として拾うよう
  visibility 接頭辞を許容
- github_collector: verify の source 選定で scanner_for_extension の二重計算を解消
  (path→scanner を一度引いて持ち回る)
- スキャナ改善に対応するテストを追加

挙動は精度向上のみ。API 契約・スキーマは不変。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend バックエンド documentation Improvements or additions to documentation feature 新機能 test テスト追加・修正

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant