From 10b1a35edff90640b2287d3eb4a1a1c5dc40a9ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 13 Mar 2026 20:29:37 +0000 Subject: [PATCH] Add debug logging to engine catalog, repo memory validation, virtual fs, deps helpers, and safe outputs runtime - pkg/workflow/engine_definition.go: log engine catalog initialization and Resolve() steps (exact match, prefix fallback, not found) - pkg/workflow/repo_memory_validation.go: log branch prefix validation and duplicate memory ID checks - pkg/parser/virtual_fs.go: log builtin virtual file registration events - pkg/cli/deps_helpers.go: log go.mod discovery path and parsed dependency count - pkg/workflow/safe_outputs_runtime.go: log resolved runner image and patch/checkout usage detection Co-Authored-By: Claude Sonnet 4.6 --- pkg/cli/deps_helpers.go | 13 ++++++++++++- pkg/parser/virtual_fs.go | 5 +++++ pkg/workflow/engine_definition.go | 9 +++++++++ pkg/workflow/repo_memory_validation.go | 6 ++++++ pkg/workflow/safe_outputs_runtime.go | 14 ++++++++++++-- 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/pkg/cli/deps_helpers.go b/pkg/cli/deps_helpers.go index d0015f95fc..f413b287f4 100644 --- a/pkg/cli/deps_helpers.go +++ b/pkg/cli/deps_helpers.go @@ -5,14 +5,22 @@ import ( "os" "path/filepath" "strings" + + "github.com/github/gh-aw/pkg/logger" ) +var depsHelpersLog = logger.New("cli:deps_helpers") + // findGoMod locates the go.mod file in the repository. // It first checks the current directory, then falls back to the git root. func findGoMod() (string, error) { // Try current directory first if _, err := os.Stat("go.mod"); err == nil { - return filepath.Abs("go.mod") + absPath, err := filepath.Abs("go.mod") + if err == nil { + depsHelpersLog.Printf("Found go.mod in current directory: %s", absPath) + } + return absPath, err } // Try git root @@ -26,12 +34,14 @@ func findGoMod() (string, error) { return "", errors.New("not in a Go module (no go.mod found)") } + depsHelpersLog.Printf("Found go.mod at git root: %s", goModPath) return goModPath, nil } // parseGoModFile parses a go.mod file and returns all dependencies (direct and indirect). // Callers can filter on the Indirect field as needed. func parseGoModFile(path string) ([]DependencyInfoWithIndirect, error) { + depsHelpersLog.Printf("Parsing go.mod file: %s", path) content, err := os.ReadFile(path) if err != nil { return nil, err @@ -75,5 +85,6 @@ func parseGoModFile(path string) ([]DependencyInfoWithIndirect, error) { } } + depsHelpersLog.Printf("Parsed %d dependencies from go.mod", len(deps)) return deps, nil } diff --git a/pkg/parser/virtual_fs.go b/pkg/parser/virtual_fs.go index f66ae0044a..da5c66a9d5 100644 --- a/pkg/parser/virtual_fs.go +++ b/pkg/parser/virtual_fs.go @@ -5,8 +5,12 @@ import ( "os" "strings" "sync" + + "github.com/github/gh-aw/pkg/logger" ) +var virtualFsLog = logger.New("parser:virtual_fs") + // builtinVirtualFiles holds embedded built-in files registered at startup. // Keys use the "@builtin:" path prefix (e.g. "@builtin:engines/copilot.md"). // The map is populated once and then read-only; concurrent reads are safe. @@ -35,6 +39,7 @@ func RegisterBuiltinVirtualFile(path string, content []byte) { } return // idempotent: same content, no-op } + virtualFsLog.Printf("Registering builtin virtual file: %s (%d bytes)", path, len(content)) builtinVirtualFiles[path] = content } diff --git a/pkg/workflow/engine_definition.go b/pkg/workflow/engine_definition.go index 9c3bf6732b..51d929bd1a 100644 --- a/pkg/workflow/engine_definition.go +++ b/pkg/workflow/engine_definition.go @@ -33,9 +33,12 @@ import ( "strings" "github.com/github/gh-aw/pkg/constants" + "github.com/github/gh-aw/pkg/logger" "github.com/github/gh-aw/pkg/parser" ) +var engineCatalogLog = logger.New("workflow:engine_definition") + // AuthStrategy identifies how an engine authenticates with its provider. type AuthStrategy string @@ -190,6 +193,7 @@ func NewEngineCatalog(registry *EngineRegistry) *EngineCatalog { catalog.Register(def) } + engineCatalogLog.Printf("Engine catalog initialized with %d built-in definitions", len(catalog.definitions)) return catalog } @@ -229,8 +233,11 @@ func (c *EngineCatalog) All() []*EngineDefinition { // 2. Prefix match in the underlying EngineRegistry (backward compat, e.g. "codex-experimental") // 3. Returns a formatted validation error when no match is found func (c *EngineCatalog) Resolve(id string, config *EngineConfig) (*ResolvedEngineTarget, error) { + engineCatalogLog.Printf("Resolving engine: %s", id) + // Exact catalog lookup if def, ok := c.definitions[id]; ok { + engineCatalogLog.Printf("Exact catalog match found for engine: %s (runtimeID=%s)", id, def.RuntimeID) runtime, err := c.registry.GetEngine(def.RuntimeID) if err != nil { return nil, fmt.Errorf("engine %q definition references unknown runtime %q: %w", id, def.RuntimeID, err) @@ -241,6 +248,7 @@ func (c *EngineCatalog) Resolve(id string, config *EngineConfig) (*ResolvedEngin // Fall back to runtime-ID prefix lookup for backward compat (e.g. "codex-experimental") runtime, err := c.registry.GetEngineByPrefix(id) if err == nil { + engineCatalogLog.Printf("Engine %q resolved via runtime-ID prefix fallback to %q", id, runtime.GetID()) def := &EngineDefinition{ ID: id, DisplayName: runtime.GetDisplayName(), @@ -251,6 +259,7 @@ func (c *EngineCatalog) Resolve(id string, config *EngineConfig) (*ResolvedEngin } // Engine not found — produce a helpful validation error matching the existing format + engineCatalogLog.Printf("Engine not found: %s", id) validEngines := c.registry.GetSupportedEngines() suggestions := parser.FindClosestMatches(id, validEngines, 1) enginesStr := strings.Join(validEngines, ", ") diff --git a/pkg/workflow/repo_memory_validation.go b/pkg/workflow/repo_memory_validation.go index fccc5a4a54..337e47063c 100644 --- a/pkg/workflow/repo_memory_validation.go +++ b/pkg/workflow/repo_memory_validation.go @@ -24,12 +24,16 @@ import ( "strings" ) +var repoMemValidationLog = newValidationLogger("repo_memory") + // validateBranchPrefix validates that the branch prefix meets requirements func validateBranchPrefix(prefix string) error { if prefix == "" { return nil // Empty means use default } + repoMemValidationLog.Printf("Validating branch prefix: %q", prefix) + // Check length (4-32 characters) if len(prefix) < 4 { return fmt.Errorf("branch-prefix must be at least 4 characters long, got %d", len(prefix)) @@ -49,12 +53,14 @@ func validateBranchPrefix(prefix string) error { return errors.New("branch-prefix cannot be 'copilot' (reserved)") } + repoMemValidationLog.Printf("Branch prefix %q passed validation", prefix) return nil } // validateNoDuplicateMemoryIDs checks for duplicate memory IDs and returns an error if found. // Uses the generic validateNoDuplicateIDs helper for consistent duplicate detection. func validateNoDuplicateMemoryIDs(memories []RepoMemoryEntry) error { + repoMemValidationLog.Printf("Validating %d memory entries for duplicate IDs", len(memories)) return validateNoDuplicateIDs(memories, func(m RepoMemoryEntry) string { return m.ID }, func(id string) error { return fmt.Errorf("duplicate memory ID found: '%s'. Each memory must have a unique ID", id) }) diff --git a/pkg/workflow/safe_outputs_runtime.go b/pkg/workflow/safe_outputs_runtime.go index f7a97040ff..81da2659cf 100644 --- a/pkg/workflow/safe_outputs_runtime.go +++ b/pkg/workflow/safe_outputs_runtime.go @@ -1,6 +1,11 @@ package workflow -import "github.com/github/gh-aw/pkg/constants" +import ( + "github.com/github/gh-aw/pkg/constants" + "github.com/github/gh-aw/pkg/logger" +) + +var safeOutputsRuntimeLog = logger.New("workflow:safe_outputs_runtime") // ======================================== // Safe Output Runtime Configuration @@ -14,9 +19,11 @@ import "github.com/github/gh-aw/pkg/constants" // Falls back to the default activation job runner image when not explicitly set. func (c *Compiler) formatSafeOutputsRunsOn(safeOutputs *SafeOutputsConfig) string { if safeOutputs == nil || safeOutputs.RunsOn == "" { + safeOutputsRuntimeLog.Printf("Safe outputs runs-on not set, using default: %s", constants.DefaultActivationJobRunnerImage) return "runs-on: " + constants.DefaultActivationJobRunnerImage } + safeOutputsRuntimeLog.Printf("Safe outputs runs-on: %s", safeOutputs.RunsOn) return "runs-on: " + safeOutputs.RunsOn } @@ -26,5 +33,8 @@ func usesPatchesAndCheckouts(safeOutputs *SafeOutputsConfig) bool { if safeOutputs == nil { return false } - return safeOutputs.CreatePullRequests != nil || safeOutputs.PushToPullRequestBranch != nil + result := safeOutputs.CreatePullRequests != nil || safeOutputs.PushToPullRequestBranch != nil + safeOutputsRuntimeLog.Printf("usesPatchesAndCheckouts: createPR=%v, pushToPRBranch=%v, result=%v", + safeOutputs.CreatePullRequests != nil, safeOutputs.PushToPullRequestBranch != nil, result) + return result }