diff --git a/cmd/run.go b/cmd/run.go index df217c6..f52b623 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -300,6 +300,7 @@ func fetchGraphWithCircularDeps( logFn("[warn] circular dependency check failed: %v", cr.err) } else if cr.circDeps != nil { gr.graph.Stats.CircularDependencyCycles = len(cr.circDeps.Cycles) + gr.graph.Cycles = cr.circDeps.Cycles logFn("[debug] circular dependency cycles found: %d", gr.graph.Stats.CircularDependencyCycles) } diff --git a/internal/api/client.go b/internal/api/client.go index f1bf131..62d7b9f 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -191,15 +191,16 @@ type CriticalFile struct { // ProjectGraph is the internal model used by the cache and template. type ProjectGraph struct { - Name string `json:"name"` - Language string `json:"language"` - Framework string `json:"framework,omitempty"` - Description string `json:"description,omitempty"` - Domains []Domain `json:"domains"` - ExternalDeps []string `json:"external_deps,omitempty"` - CriticalFiles []CriticalFile `json:"critical_files,omitempty"` - Stats Stats `json:"stats"` - UpdatedAt time.Time `json:"updated_at"` + Name string `json:"name"` + Language string `json:"language"` + Framework string `json:"framework,omitempty"` + Description string `json:"description,omitempty"` + Domains []Domain `json:"domains"` + ExternalDeps []string `json:"external_deps,omitempty"` + CriticalFiles []CriticalFile `json:"critical_files,omitempty"` + Stats Stats `json:"stats"` + Cycles []CircularDependencyCycle `json:"cycles,omitempty"` + UpdatedAt time.Time `json:"updated_at"` } // Subdomain represents a named sub-area within a domain. diff --git a/internal/template/render.go b/internal/template/render.go index 3fb7e46..3ed87a4 100644 --- a/internal/template/render.go +++ b/internal/template/render.go @@ -16,7 +16,8 @@ const contextBombTmpl = `# Uncompact Context — {{.ProjectName}} > Injected by Uncompact at {{.Timestamp}}{{if .Stale}} | ⚠️ STALE: last updated {{.StaleDuration}}{{end}} {{- if .Graph.Stats.CircularDependencyCycles}} -> ⚠️ {{.Graph.Stats.CircularDependencyCycles}} circular dependency {{if eq .Graph.Stats.CircularDependencyCycles 1}}cycle{{else}}cycles{{end}} detected +> ⚠️ {{.Graph.Stats.CircularDependencyCycles}} circular dependency {{if eq .Graph.Stats.CircularDependencyCycles 1}}cycle{{else}}cycles{{end}} detected{{range .Graph.Cycles}} +> - {{join .Cycle " → "}}{{end}} {{- end}} ## Project Overview @@ -182,7 +183,11 @@ func truncateToTokenBudget( if circularCycles == 1 { label = "cycle" } - hdr.WriteString(fmt.Sprintf("> ⚠️ %d circular dependency %s detected\n\n", circularCycles, label)) + hdr.WriteString(fmt.Sprintf("> ⚠️ %d circular dependency %s detected\n", circularCycles, label)) + for _, c := range graph.Cycles { + hdr.WriteString(fmt.Sprintf("> - %s\n", strings.Join(c.Cycle, " → "))) + } + hdr.WriteString("\n") } hdr.WriteString(fmt.Sprintf( "**Language:** %s · **Files:** %d · **Functions:** %d",