MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / planFrontload

Function planFrontload

src/directory.ts:543–583  ·  view source on GitHub ↗
(cwd: string, prompt: string)

Source from the content-addressed store, hash-verified

541 * 3. **nothing indexed reachable** → do nothing (the agent's own tools apply).
542 */
543export function planFrontload(cwd: string, prompt: string): FrontloadPlan {
544 const none: FrontloadPlan = { exploreRoot: null, nudgeProjects: [], viaSubScan: false };
545
546 // 1. up-walk — nearest indexed ancestor (incl. cwd). Cheap; covers the common
547 // single-project case without a down-scan.
548 let dir = path.resolve(cwd);
549 for (let i = 0; i < 6; i++) {
550 if (isInitialized(dir)) return { exploreRoot: dir, nudgeProjects: [], viaSubScan: false };
551 const parent = path.dirname(dir);
552 if (parent === dir) break;
553 dir = parent;
554 }
555
556 // 2. down-scan — only from something that looks like a workspace root, so a
557 // non-project cwd (e.g. $HOME) is a cheap no-op, not a deep crawl.
558 const base = path.resolve(cwd);
559 if (!looksLikeProjectRoot(base)) return none;
560 const subs = findIndexedSubprojectRoots(base);
561 if (subs.length === 0) return none;
562 if (subs.length === 1) return { exploreRoot: subs[0]!, nudgeProjects: [], viaSubScan: true };
563
564 // Several indexed sub-projects — pick the one the prompt points at, if any.
565 const p = prompt.toLowerCase();
566 let best: { root: string; score: number; relLen: number } | null = null;
567 for (const s of subs) {
568 const rel = path.relative(base, s);
569 const relLc = rel.split(path.sep).join('/').toLowerCase();
570 const name = path.basename(s).toLowerCase();
571 let score = 0;
572 if (relLc && p.includes(relLc)) score = 10; // "packages/api"
573 else if (name.length >= 3 && new RegExp(`\\b${escapeRegExp(name)}\\b`).test(p)) score = 5; // "api"
574 if (score > 0 && (!best || score > best.score || (score === best.score && rel.length < best.relLen))) {
575 best = { root: s, score, relLen: rel.length };
576 }
577 }
578 if (best) {
579 return { exploreRoot: best.root, nudgeProjects: subs.filter((s) => s !== best!.root), viaSubScan: true };
580 }
581 // No clear match — nudge the full list rather than front-load a guess.
582 return { exploreRoot: null, nudgeProjects: subs, viaSubScan: true };
583}
584
585/**
586 * Contents of `.codegraph/.gitignore`. A single wildcard ignore keeps every

Callers 2

mainFunction · 0.90

Calls 6

isInitializedFunction · 0.85
looksLikeProjectRootFunction · 0.85
resolveMethod · 0.80
escapeRegExpFunction · 0.70
joinMethod · 0.45

Tested by

no test coverage detected