1212from rich .table import Table
1313from rich .text import Text
1414
15- from whygraph .scan import Crawler , GitCrawler , GitHubCrawler
15+ from whygraph .scan import CodeGraphCrawler , Crawler , GitCrawler , GitHubCrawler
1616
1717from ..console import console
1818
4444 "refresh_codegraph" ,
4545 default = True ,
4646 help = (
47- "Refresh the CodeGraph index before crawling — `codegraph sync` when "
48- "an index exists, `codegraph init -i` on first run. Uses the local "
49- "`codegraph` binary if present, else runs it inside the WhyGraph "
50- "Docker image. The crawl itself doesn't need CodeGraph (only the MCP "
51- "rationale/evidence tools do), so a failure here warns rather than "
52- "aborting. Default: on."
47+ "Refresh the CodeGraph index concurrently with the crawl — "
48+ "`codegraph sync` when an index exists, `codegraph init -i` on first "
49+ "run. Uses the local `codegraph` binary if present, else runs it "
50+ "inside the WhyGraph Docker image. The crawl itself doesn't need "
51+ "CodeGraph (only the MCP rationale/evidence tools do), so a failure "
52+ "here warns rather than aborting. Default: on."
5353 ),
5454)
5555@click .option (
@@ -122,13 +122,19 @@ def scan_cmd(
122122 remote_enabled = remote ,
123123 )
124124
125- # CodeGraph refresh runs before the crawl and outside the Progress
126- # live-display (it streams its own output on first index). It's
127- # best-effort: the crawl doesn't depend on it.
128- if refresh_codegraph :
129- _refresh_codegraph (repository .root , image = codegraph_image )
130-
131125 with Progress () as progress :
126+ # CodeGraph refresh — runs concurrently as its own crawler. It
127+ # writes .codegraph/ and has no data dependency on the WhyGraph DB,
128+ # so it overlaps the entire crawl (started with phase 1, joined
129+ # last). Best-effort: failures land on .warning, not .error.
130+ codegraph_crawler = (
131+ CodeGraphCrawler (
132+ progress , project_root = repository .root , image = codegraph_image
133+ )
134+ if refresh_codegraph
135+ else None
136+ )
137+
132138 # Phase 1 — source crawlers, run concurrently.
133139 phase1 : list [Crawler ] = [GitCrawler (progress , repository = repository )]
134140 if github_client is not None :
@@ -148,6 +154,8 @@ def scan_cmd(
148154 )
149155 )
150156
157+ if codegraph_crawler is not None :
158+ codegraph_crawler .start ()
151159 for c in phase1 :
152160 c .start ()
153161 for c in phase1 :
@@ -156,8 +164,15 @@ def scan_cmd(
156164 c .start ()
157165 for c in phase2 :
158166 c .join ()
167+ if codegraph_crawler is not None :
168+ codegraph_crawler .join ()
169+
170+ if codegraph_crawler is not None and codegraph_crawler .warning is not None :
171+ console .print (Text (codegraph_crawler .warning , style = "yellow" ))
159172
160173 crawlers = phase1 + phase2
174+ if codegraph_crawler is not None :
175+ crawlers .append (codegraph_crawler )
161176 failed = [c for c in crawlers if c .error is not None ]
162177 for c in failed :
163178 click .echo (f"crawler { c .name !r} failed: { c .error } " , err = True )
@@ -196,34 +211,6 @@ def _apply_github_token(config: "Config") -> None:
196211 os .environ ["GH_TOKEN" ] = token
197212
198213
199- def _refresh_codegraph (project_root : Path , * , image : str | None ) -> None :
200- """Bring the CodeGraph index up to date before the crawl.
201-
202- Best-effort: the git / GitHub / analyze crawl does not depend on the
203- CodeGraph index (only the MCP ``whygraph_rationale_brief`` and
204- ``whygraph_evidence_for`` tools read it), so a CodeGraph failure is
205- reported as a warning and the scan continues.
206-
207- Parameters
208- ----------
209- project_root : Path
210- Repository root whose ``.codegraph/`` index is refreshed.
211- image : str or None
212- Docker image override for the fallback path; ``None`` uses the
213- pinned default. Ignored when a local ``codegraph`` binary is found.
214- """
215- from whygraph .services .codegraph import (
216- CodeGraphBootstrapError ,
217- refresh_codegraph_index ,
218- )
219-
220- console .print ("Refreshing CodeGraph index…" )
221- try :
222- refresh_codegraph_index (project_root , image = image )
223- except CodeGraphBootstrapError as exc :
224- console .print (Text (f"CodeGraph refresh skipped — { exc } " , style = "yellow" ))
225-
226-
227214def _select_github_client (
228215 provider : str , repository : "Repository"
229216) -> "GitHubClient | None" :
0 commit comments