Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions pkg/cli/logs_usage_activity.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import (
"os"
"path/filepath"

"github.com/github/gh-aw/pkg/logger"
"github.com/github/gh-aw/pkg/sliceutil"
)

var logsUsageActivityLog = logger.New("cli:logs_usage_activity")

const usageActivitySummarySchema = "usage-activity-summary/v1"

type usageActivitySummary struct {
Expand Down Expand Up @@ -69,13 +72,16 @@ func loadUsageActivitySummary(runDir string) (*usageActivitySummary, error) {
}
var summary usageActivitySummary
if err := json.Unmarshal(raw, &summary); err != nil {
logsUsageActivityLog.Printf("loadUsageActivitySummary: failed to parse %s, trying next candidate", cleanPath)
lastErr = fmt.Errorf("parse usage activity summary %s: %w", cleanPath, err)
continue
}
if summary.Schema != usageActivitySummarySchema {
logsUsageActivityLog.Printf("loadUsageActivitySummary: unsupported schema %q in %s (expected %q)", summary.Schema, cleanPath, usageActivitySummarySchema)
lastErr = fmt.Errorf("unsupported usage activity summary schema %q in %s (expected %q)", summary.Schema, cleanPath, usageActivitySummarySchema)
continue
}
logsUsageActivityLog.Printf("loadUsageActivitySummary: loaded summary from %s", cleanPath)
return &summary, nil
}
return nil, lastErr
Expand All @@ -93,6 +99,7 @@ func applyUsageActivitySummaryToResult(summary *usageActivitySummary, result *Do
}

if summary.Firewall != nil && result.FirewallAnalysis == nil {
logsUsageActivityLog.Printf("applyUsageActivitySummaryToResult: backfilling firewall analysis (total=%d allowed=%d blocked=%d)", summary.Firewall.TotalRequests, summary.Firewall.AllowedRequests, summary.Firewall.BlockedRequests)
requestsByDomain := maps.Clone(summary.Firewall.RequestsByDomain)
if requestsByDomain == nil {
requestsByDomain = map[string]DomainRequestStats{}
Expand Down Expand Up @@ -129,6 +136,7 @@ func applyUsageActivitySummaryToResult(summary *usageActivitySummary, result *Do
}

if summary.Gateway != nil && result.MCPToolUsage == nil {
logsUsageActivityLog.Printf("applyUsageActivitySummaryToResult: backfilling MCP tool usage from %d gateway server(s)", len(summary.Gateway.Servers))
servers := make([]MCPServerStats, 0, len(summary.Gateway.Servers))
for _, server := range summary.Gateway.Servers {
servers = append(servers, MCPServerStats{
Expand Down
9 changes: 9 additions & 0 deletions pkg/importinpututil/import_input.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,33 @@ import (
"reflect"
"sort"
"strings"

"github.com/github/gh-aw/pkg/logger"
)

var importInputLog = logger.New("importinpututil:import_input")

// ResolvePathValue resolves either a top-level input key ("count") or a one-level
// dotted object sub-key ("config.apiKey") from import inputs.
func ResolvePathValue(inputs map[string]any, inputPath string) (any, bool) {
top, sub, hasDot := strings.Cut(inputPath, ".")
if !hasDot {
value, ok := inputs[top]
importInputLog.Printf("ResolvePathValue: top-level key %q found=%t", top, ok)
return value, ok
}
topVal, topOK := inputs[top]
if !topOK {
importInputLog.Printf("ResolvePathValue: parent key %q not found for path %q", top, inputPath)
return nil, false
}
obj, isMap := topVal.(map[string]any)
if !isMap {
importInputLog.Printf("ResolvePathValue: parent key %q is not an object for path %q", top, inputPath)
return nil, false
}
value, ok := obj[sub]
importInputLog.Printf("ResolvePathValue: sub-key %q under %q found=%t", sub, top, ok)
return value, ok
}

Expand All @@ -38,6 +46,7 @@ func FormatResolvedValue(value any) (string, bool) {
case map[string]any:
return marshalValue(v)
case nil:
importInputLog.Print("FormatResolvedValue: nil value, no substitution")
return "", false
default:
return formatReflectiveValue(v)
Expand Down
13 changes: 13 additions & 0 deletions pkg/intent/resolver.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package intent

import "github.com/github/gh-aw/pkg/logger"

var resolverLog = logger.New("intent:resolver")

type AttributionStatus string

const (
Expand Down Expand Up @@ -60,29 +64,38 @@ type Resolver struct {
}

func (r Resolver) ResolvePullRequest(pr PullRequestData) IntentRecord {
resolverLog.Printf("ResolvePullRequest: nodeID=%s explicitIntent=%t closingIssues=%d labels=%d", pr.NodeID, pr.ExplicitIntent != nil, len(pr.ClosingIssues), len(pr.Labels))

if pr.ExplicitIntent != nil {
intent := *pr.ExplicitIntent
if intent.ResolverVersion == "" {
intent.ResolverVersion = r.ResolverVersion
}
resolverLog.Printf("ResolvePullRequest: using explicit metadata for %s", pr.NodeID)
return intent
}

switch len(pr.ClosingIssues) {
case 1:
resolverLog.Printf("ResolvePullRequest: attributing %s to single closing issue", pr.NodeID)
return r.fromRoot(pr.ClosingIssues[0], SourceClosingIssue, "single_closing_issue")
case 0:
if len(pr.Labels) > 0 {
resolverLog.Printf("ResolvePullRequest: no closing issue, falling back to %d PR label(s) for %s", len(pr.Labels), pr.NodeID)
return r.fromLabels(pr.NodeID, pr.URL, pr.Labels, SourceArtifactLabels, "pull_request_label_fallback")
}
resolverLog.Printf("ResolvePullRequest: no intent source for %s, marking unlinked", pr.NodeID)
return r.unlinked("no_supported_intent_source")
default:
resolverLog.Printf("ResolvePullRequest: %d closing issues for %s, marking ambiguous", len(pr.ClosingIssues), pr.NodeID)
return r.ambiguous(SourceClosingIssue, "multiple_closing_issues")
}
}

func (r Resolver) ResolveIssue(nodeID, url string, labels []string) IntentRecord {
resolverLog.Printf("ResolveIssue: nodeID=%s labels=%d", nodeID, len(labels))
if len(labels) == 0 {
resolverLog.Printf("ResolveIssue: no labels for %s, marking unlinked", nodeID)
return r.unlinked("no_supported_intent_source")
}
return IntentRecord{
Expand Down
12 changes: 11 additions & 1 deletion pkg/workflow/lsp_validation.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package workflow

import "fmt"
import (
"fmt"

"github.com/github/gh-aw/pkg/logger"
)

var lspValidationLog = logger.New("workflow:lsp_validation")

func (c *Compiler) validateLSPSupport(workflowData *WorkflowData) error {
if workflowData == nil || len(workflowData.LSP) == 0 {
return nil
}

lspValidationLog.Printf("validateLSPSupport: validating %d LSP config(s)", len(workflowData.LSP))

manager := NewLSPManager(workflowData.LSP)
if err := manager.Validate(); err != nil {
return err
Expand All @@ -18,8 +26,10 @@ func (c *Compiler) validateLSPSupport(workflowData *WorkflowData) error {
}

if engineID != "copilot" {
lspValidationLog.Printf("validateLSPSupport: rejecting unsupported engine %q for LSP", engineID)
return fmt.Errorf("lsp is currently only supported for engine: copilot (found engine: %s)", engineID)
}

lspValidationLog.Printf("validateLSPSupport: LSP validation passed for engine %q", engineID)
return nil
}
8 changes: 8 additions & 0 deletions pkg/workflow/skills_frontmatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import (
"fmt"
"regexp"
"strings"

"github.com/github/gh-aw/pkg/logger"
)

var skillsFrontmatterLog = logger.New("workflow:skills_frontmatter")

var skillSpecRegexp = regexp.MustCompile(`^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+(?:/[A-Za-z0-9_.-]+(?:/[A-Za-z0-9_.-]+)*)?@[0-9a-f]{40}$`)
var skillSpecExpressionRefRegexp = regexp.MustCompile(`^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+(?:/[A-Za-z0-9_.-]+(?:/[A-Za-z0-9_.-]+)*)?@\$\{\{.+\}\}$`)
var githubActionsExpressionRegexp = regexp.MustCompile(`^\$\{\{.+\}\}$`)
Expand Down Expand Up @@ -48,6 +52,8 @@ func validateFrontmatterSkills(frontmatter map[string]any) error {
return errors.New("skills must be an array of skill references")
}

skillsFrontmatterLog.Printf("validateFrontmatterSkills: validating %d skill entr(ies)", len(skills))

for i, rawSkill := range skills {
switch typed := rawSkill.(type) {
case string:
Expand Down Expand Up @@ -124,6 +130,7 @@ func isRepositorySkillSpec(skillSpec string) bool {
}

func parseRawSkillReferences(rawSkills []any) []SkillReference {
skillsFrontmatterLog.Printf("parseRawSkillReferences: parsing %d raw skill entr(ies)", len(rawSkills))
refs := make([]SkillReference, 0, len(rawSkills))
for _, rawSkill := range rawSkills {
switch typed := rawSkill.(type) {
Expand Down Expand Up @@ -151,5 +158,6 @@ func parseRawSkillReferences(rawSkills []any) []SkillReference {
if len(refs) == 0 {
return nil
}
skillsFrontmatterLog.Printf("parseRawSkillReferences: parsed %d skill reference(s)", len(refs))
return refs
}
Loading