From 49a783225143b895c7aaa585a519fcb8dfc88cde Mon Sep 17 00:00:00 2001 From: gh-aw agent Date: Wed, 25 Feb 2026 20:30:44 +0000 Subject: [PATCH] Add debug logging to 5 pkg files for improved troubleshooting Adds meaningful debug log calls to key functions in: - pkg/workflow/checkout_manager.go: log CheckoutManager creation, default/additional checkout step generation, and config parsing - pkg/workflow/frontmatter_extraction_yaml.go: log workflow_run annotation, permissions extraction, and command config parsing - pkg/parser/schedule_parser.go: log entry to interval and base schedule parsing methods - pkg/cli/logs_orchestrator.go: log safe-output type checks and final run processing summary - pkg/workflow/claude_logs.go: log result payload extraction and parsed JSON log metrics Co-Authored-By: Claude Sonnet 4.6 --- pkg/cli/logs_orchestrator.go | 2 ++ pkg/parser/schedule_parser.go | 2 ++ pkg/workflow/checkout_manager.go | 5 +++++ pkg/workflow/claude_logs.go | 5 +++++ pkg/workflow/frontmatter_extraction_yaml.go | 5 +++++ 5 files changed, 19 insertions(+) diff --git a/pkg/cli/logs_orchestrator.go b/pkg/cli/logs_orchestrator.go index da65e335975..5628f084ffa 100644 --- a/pkg/cli/logs_orchestrator.go +++ b/pkg/cli/logs_orchestrator.go @@ -473,6 +473,7 @@ func DownloadWorkflowLogs(ctx context.Context, workflowName string, count int, s } // Build structured logs data + logsOrchestratorLog.Printf("Building logs data from %d processed runs (continuation=%t)", len(processedRuns), continuation != nil) logsData := buildLogsData(processedRuns, outputDir, continuation) // Write summary file if requested (default behavior unless disabled with empty string) @@ -804,6 +805,7 @@ func normalizeSafeOutputType(safeOutputType string) string { // runContainsSafeOutputType checks if a run's agent_output.json contains a specific safe output type func runContainsSafeOutputType(runDir string, safeOutputType string, verbose bool) (bool, error) { + logsOrchestratorLog.Printf("Checking run for safe output type: dir=%s, type=%s", runDir, safeOutputType) // Normalize the type for comparison (convert dashes to underscores) normalizedType := normalizeSafeOutputType(safeOutputType) diff --git a/pkg/parser/schedule_parser.go b/pkg/parser/schedule_parser.go index 97f0ed7a90e..aa273638b88 100644 --- a/pkg/parser/schedule_parser.go +++ b/pkg/parser/schedule_parser.go @@ -91,6 +91,7 @@ func (p *ScheduleParser) parseInterval() (string, error) { if len(p.tokens) < 2 { return "", errors.New("invalid interval format, expected 'every N unit' or 'every Nunit'") } + scheduleLog.Printf("Parsing interval schedule: tokens=%v", p.tokens) // Check if "on weekdays" suffix is present at the end hasWeekdaysSuffix := p.hasWeekdaysSuffix() @@ -275,6 +276,7 @@ func (p *ScheduleParser) parseBase() (string, error) { } baseType := p.tokens[0] + scheduleLog.Printf("Parsing base schedule: type=%s, tokens=%v", baseType, p.tokens) var minute, hour, day, month, weekday string // Default time is 00:00 diff --git a/pkg/workflow/checkout_manager.go b/pkg/workflow/checkout_manager.go index fd35f3f1434..58e459bdb73 100644 --- a/pkg/workflow/checkout_manager.go +++ b/pkg/workflow/checkout_manager.go @@ -94,6 +94,7 @@ type CheckoutManager struct { // NewCheckoutManager creates a new CheckoutManager pre-loaded with user-supplied // CheckoutConfig entries from the frontmatter. func NewCheckoutManager(userCheckouts []*CheckoutConfig) *CheckoutManager { + checkoutManagerLog.Printf("Creating checkout manager with %d user checkout config(s)", len(userCheckouts)) cm := &CheckoutManager{ index: make(map[checkoutKey]int), } @@ -172,6 +173,7 @@ func (cm *CheckoutManager) GetDefaultCheckoutOverride() *resolvedCheckout { // (additional) checkouts — those that target a specific path other than the root. // The caller is responsible for emitting the default workspace checkout separately. func (cm *CheckoutManager) GenerateAdditionalCheckoutSteps(getActionPin func(string) string) []string { + checkoutManagerLog.Printf("Generating additional checkout steps from %d configured entries", len(cm.ordered)) var lines []string for _, entry := range cm.ordered { // Skip the default checkout (handled separately) @@ -180,6 +182,7 @@ func (cm *CheckoutManager) GenerateAdditionalCheckoutSteps(getActionPin func(str } lines = append(lines, generateCheckoutStepLines(entry, getActionPin)...) } + checkoutManagerLog.Printf("Generated %d additional checkout step(s)", len(lines)) return lines } @@ -199,6 +202,7 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( getActionPin func(string) string, ) []string { override := cm.GetDefaultCheckoutOverride() + checkoutManagerLog.Printf("Generating default checkout step: trialMode=%t, hasOverride=%t", trialMode, override != nil) var sb strings.Builder sb.WriteString(" - name: Checkout repository\n") @@ -363,6 +367,7 @@ func ParseCheckoutConfigs(raw any) ([]*CheckoutConfig, error) { if raw == nil { return nil, nil } + checkoutManagerLog.Printf("Parsing checkout configuration: type=%T", raw) // Try single object first if singleMap, ok := raw.(map[string]any); ok { diff --git a/pkg/workflow/claude_logs.go b/pkg/workflow/claude_logs.go index ac675c920c5..6d705a24b3b 100644 --- a/pkg/workflow/claude_logs.go +++ b/pkg/workflow/claude_logs.go @@ -96,6 +96,7 @@ func (e *ClaudeEngine) isClaudeResultPayload(line string) bool { // extractClaudeResultMetrics extracts metrics from Claude result payload func (e *ClaudeEngine) extractClaudeResultMetrics(line string) LogMetrics { + claudeLogsLog.Print("Extracting metrics from Claude result payload") var metrics LogMetrics trimmed := strings.TrimSpace(line) @@ -136,6 +137,7 @@ func (e *ClaudeEngine) extractClaudeResultMetrics(line string) LogMetrics { // Note: Duration extraction is handled in the main parsing logic where we have access to tool calls // This is because we need to distribute duration among tool calls + claudeLogsLog.Printf("Extracted Claude result metrics: tokens=%d, cost=$%.4f, turns=%d", metrics.TokenUsage, metrics.EstimatedCost, metrics.Turns) return metrics } @@ -317,6 +319,9 @@ func (e *ClaudeEngine) parseClaudeJSONLog(logContent string, verbose bool) LogMe // Finalize tool calls and sequences using shared helper FinalizeToolCallsAndSequence(&metrics, toolCallMap, currentSequence) + claudeLogsLog.Printf("Parsed %d log entries: tokens=%d, cost=$%.4f, turns=%d, tool_types=%d", + len(logEntries), metrics.TokenUsage, metrics.EstimatedCost, metrics.Turns, len(metrics.ToolCalls)) + if verbose && len(metrics.ToolSequences) > 0 { totalTools := 0 for _, seq := range metrics.ToolSequences { diff --git a/pkg/workflow/frontmatter_extraction_yaml.go b/pkg/workflow/frontmatter_extraction_yaml.go index 823874c0658..96ecf00b6dc 100644 --- a/pkg/workflow/frontmatter_extraction_yaml.go +++ b/pkg/workflow/frontmatter_extraction_yaml.go @@ -501,6 +501,7 @@ func (c *Compiler) addZizmorIgnoreForWorkflowRun(yamlStr string) string { if !strings.Contains(yamlStr, "workflow_run:") { return yamlStr } + frontmatterLog.Print("Adding zizmor ignore annotation for workflow_run trigger") lines := strings.Split(yamlStr, "\n") var result []string @@ -551,6 +552,7 @@ func (c *Compiler) addZizmorIgnoreForWorkflowRun(yamlStr string) string { func (c *Compiler) extractPermissions(frontmatter map[string]any) string { permissionsValue, exists := frontmatter["permissions"] if !exists { + frontmatterLog.Print("No permissions field found in frontmatter") return "" } @@ -612,6 +614,7 @@ func (c *Compiler) extractExpressionFromIfString(ifString string) string { // extractCommandConfig extracts command configuration from frontmatter including name and events func (c *Compiler) extractCommandConfig(frontmatter map[string]any) (commandNames []string, commandEvents []string) { + frontmatterLog.Print("Extracting command configuration from frontmatter") // Check new format: on.slash_command or on.slash_command.name (preferred) // Also check legacy format: on.command or on.command.name (deprecated) if onValue, exists := frontmatter["on"]; exists { @@ -641,6 +644,7 @@ func (c *Compiler) extractCommandConfig(frontmatter map[string]any) (commandName // Check if command is a string (shorthand format) if commandStr, ok := commandValue.(string); ok { + frontmatterLog.Printf("Extracted command name (shorthand): %s", commandStr) return []string{commandStr}, nil // nil means default (all events) } // Check if command is a map with a name key (object format) @@ -666,6 +670,7 @@ func (c *Compiler) extractCommandConfig(frontmatter map[string]any) (commandName events = ParseCommandEvents(eventsValue) } + frontmatterLog.Printf("Extracted command config: names=%v, events=%v", names, events) return names, events } }