feat(ipuaro): add circular dependencies to initial context

- Add formatCircularDeps() to display cycle chains in context
- Add includeCircularDeps config option (default: true)
- Add circularDeps parameter to BuildContextOptions
- Format: ## ⚠️ Circular Dependencies with → arrows
- 23 new tests (1798 total), 97.48% coverage
This commit is contained in:
imfozilbek
2025-12-05 15:12:26 +05:00
parent d63d85d850
commit d6d15dd271
7 changed files with 364 additions and 21 deletions

View File

@@ -17,6 +17,8 @@ export interface ProjectStructure {
export interface BuildContextOptions {
includeSignatures?: boolean
includeDepsGraph?: boolean
includeCircularDeps?: boolean
circularDeps?: string[][]
}
/**
@@ -129,6 +131,7 @@ export function buildInitialContext(
const sections: string[] = []
const includeSignatures = options?.includeSignatures ?? true
const includeDepsGraph = options?.includeDepsGraph ?? true
const includeCircularDeps = options?.includeCircularDeps ?? true
sections.push(formatProjectHeader(structure))
sections.push(formatDirectoryTree(structure))
@@ -141,6 +144,13 @@ export function buildInitialContext(
}
}
if (includeCircularDeps && options?.circularDeps && options.circularDeps.length > 0) {
const circularDepsSection = formatCircularDeps(options.circularDeps)
if (circularDepsSection) {
sections.push(circularDepsSection)
}
}
return sections.join("\n\n")
}
@@ -526,6 +536,38 @@ export function formatDependencyGraph(metas: Map<string, FileMeta>): string | nu
return lines.join("\n")
}
/**
* Format circular dependencies for display in context.
* Shows warning section with cycle chains.
*
* Format:
* ## ⚠️ Circular Dependencies
* - services/user → services/auth → services/user
* - utils/a → utils/b → utils/c → utils/a
*/
export function formatCircularDeps(cycles: string[][]): string | null {
if (!cycles || cycles.length === 0) {
return null
}
const lines: string[] = ["## ⚠️ Circular Dependencies", ""]
for (const cycle of cycles) {
if (cycle.length === 0) {
continue
}
const formattedCycle = cycle.map(shortenPath).join(" → ")
lines.push(`- ${formattedCycle}`)
}
// Return null if only header (no actual cycles)
if (lines.length <= 2) {
return null
}
return lines.join("\n")
}
/**
* Format line range for display.
*/