Go Logger Enhancement #166
go-logger.lock.yml
on: schedule
Annotations
13 errors, 2 warnings, and 2 notices
|
agent
log whether localhost URL rewriting is enabled for\n each custom MCP tool\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\n---\n pkg/parser/schedule_time_utils.go | 7 ++++++-\n pkg/parser/schema_validation.go | 7 +++++++\n pkg/parser/yaml_error.go | 2 ++\n pkg/workflow/copilot_mcp.go | 1 +\n pkg/workflow/mcp_config_playwright_renderer.go | 2 ++\n 5 files changed, 18 insertions(+), 1 deletion(-)\n\ndiff --git a/pkg/parser/schedule_time_utils.go b/pkg/parser/schedule_time_utils.go\nindex 165b3bd..c07738e 100644\n--- a/pkg/parser/schedule_time_utils.go\n+++ b/pkg/parser/schedule_time_utils.go\n@@ -75,6 +75,7 @@ func parseTimeToMinutes(hourStr, minuteStr string) int {\n // parseTime converts a time string to minute and hour, with optional UTC offset\n // Supports formats: HH:MM, midnight, noon, 3pm, 1am, HH:MM utc+N, HH:MM utc+HH:MM, HH:MM utc-N, 3pm utc+9\n func parseTime(timeStr string) (minute string, hour string) {\n+\tscheduleTimeUtilsLog.Printf(\"Parsing time string: %q\", timeStr)\n \t// Check for UTC offset\n \tparts := strings.Split(timeStr, \" \")\n \tvar utcOffset int\n@@ -241,5 +242,9 @@ func mapWeekday(day string) string {\n \t\t\"saturday\": \"6\",\n \t\t\"sat\": \"6\",\n \t}\n-\treturn weekdays[day]\n+\tresult := weekdays[day]\n+\tif result == \"\" {\n+\t\tscheduleTimeUtilsLog.Printf(\"Unrecognized weekday name: %q\", day)\n+\t}\n+\treturn result\n }\ndiff --git a/pkg/parser/schema_validation.go b/pkg/parser/schema_validation.go\nindex 3c12c4d..a445a6a 100644\n--- a/pkg/parser/schema_validation.go\n+++ b/pkg/parser/schema_validation.go\n@@ -5,8 +5,11 @@ import (\n \t\"maps\"\n \n \t\"github.com/github/gh-aw/pkg/constants\"\n+\t\"github.com/github/gh-aw/pkg/logger\"\n )\n \n+var schemaValidationLog = logger.New(\"parser:schema_validation\")\n+\n // sharedWorkflowForbiddenFields is a map for O(1) lookup of forbidden fields in shared workflows\n var sharedWorkflowForbiddenFields = buildForbiddenFieldsMap()\n \n@@ -21,6 +24,7 @@ func buildForbiddenFieldsMap() map[string]bool {\n \n // validateSharedWorkflowFields checks that a shared workflow doesn't contain forbidden fields\n func validateSharedWorkflowFields(frontmatter map[string]any) error {\n+\tschemaValidationLog.Printf(\"Checking shared workflow for forbidden fields: %d fields present\", len(frontmatter))\n \tvar forbiddenFound []string\n \n \tfor key := range frontmatter {\n@@ -30,6 +34,7 @@ func validateSharedWorkflowFields(frontmatter map[string]any) error {\n \t}\n \n \tif len(forbiddenFound) > 0 {\n+\t\tschemaValidationLog.Printf(\"Found %d forbidden field(s) in shared workflow: %v\", len(forbiddenFound), forbiddenFound)\n \t\tif len(forbiddenFound) == 1 {\n \t\t\treturn fmt.Errorf(\"field '%s' cannot be used in shared workflows (only allowed in main workflows with 'on' trigger)\", forbiddenFound[0])\n \t\t}\n@@ -52,6 +57,7 @@ func validateSharedWorkflowFields(frontmatter map[string]any) error {\n \n // ValidateMainWorkflowFrontmatterWithSchemaAndLocation validates main workflow frontmatter with file location info\n func ValidateMainWorkflowFrontmatterWithSchemaAndLocation(frontmatter map[string]any, filePath string) error {\n+\tschemaValidationLog.Printf(\"Validating main workflow frontmatter: file=%s, fields=%d\", filePath, len(frontmatter))\n \t// Filter out ignored fields before validation\n \tfiltered := filterIgnoredFields(frontmatter)\n \n@@ -73,6 +79,7 @@ func ValidateMainWorkflowFrontmatterWithSchemaAndLocation(frontmatter map[string\n \n // ValidateIncludedFileFrontmatterWithSchemaAndLocation validates included file frontmatter with file location info\n func ValidateIncludedFileFrontmatterWithSchemaAndLocation(frontmatter map[string]any, filePath string) error {\n+\tschemaValidationLog.Printf(\"Validating included file frontmatter: file=%s, fields=%d\", filePath, len(frontmatter))\n \t// Filter out ignored fields before validation\n \tfiltered := filterIgnoredFields(frontmatter)\n \ndiff --git a/pkg/parser/yaml_error.go b/pkg/parser/yaml_error.go\nindex
|
|
agent
log time-string input ...
|
|
agent
log time-string input ...
|
|
agent
log whether localhost URL rewriting is enabled for\n each custom MCP tool\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\nEOF\n)\"","description":"Commit the 5 changed files"},"caller":{"type":"direct"}}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":1,"cache_creation_input_tokens":133,"cache_read_input_tokens":136646,"cache_creation":{"ephemeral_5m_input_tokens":133,"ephemeral_1h_input_tokens":0},"output_tokens":25,"service_tier":"standard","inference_geo":"global"},"context_management":null},"parent_tool_use_id":null,"session_id":"43b6bb6d-b657-4743-8f1c-47f7d8e22fea","uuid":"f959b7df-5d34-48d2-a56e-6e5c27bef7ca"}
|
|
agent
log whether localhost URL rewriting is enabled for\n each custom MCP tool\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\nEOF\n)\"","description":"Commit the 5 changed files with descriptive message"},"caller":{"type":"direct"}}],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":1,"cache_creation_input_tokens":263,"cache_read_input_tokens":135861,"cache_creation":{"ephemeral_5m_input_tokens":263,"ephemeral_1h_input_tokens":0},"output_tokens":25,"service_tier":"standard","inference_geo":"global"},"context_management":null},"parent_tool_use_id":null,"session_id":"43b6bb6d-b657-4743-8f1c-47f7d8e22fea","uuid":"f9ab7f17-acc5-4e39-9146-e430174b5e95"}
|
|
agent
github.com/charmbracelet/lipgloss@v1.1.1-0.20250319133953-166f707985bc: Get \"https://proxy.golang.org/github.com/charmbracelet/lipgloss/@v/v1.1.1-0.20250319133953-166f707985bc.zip\": Forbidden","stderr":"","interrupted":false,"isImage":false,"noOutputExpected":false}}
|
|
agent
module lookup disabled by GOPROXY=off\nFAIL\tgithub.com/github/gh-aw/pkg/parser [setup failed]\nFAIL","stderr":"","interrupted":false,"isImage":false,"noOutputExpected":false}}
|
|
agent
github.com/santhosh-tekuri/jsonschema/v6@v6.0.2: Get \"https://proxy.golang.org/github.com/santhosh-tekuri/jsonschema/v6/@v/v6.0.2.zip\": Forbidden\nFAIL\tgithub.com/github/gh-aw/pkg/parser [setup failed]\nFAIL","stderr":"","interrupted":false,"isImage":false,"noOutputExpected":false}}
|
|
agent
github.com/santhosh-tekuri/jsonschema/v6@v6.0.2: Get \"https://proxy.golang.org/github.com/santhosh-tekuri/jsonschema/v6/@v/v6.0.2.zip\": Forbidden\nFAIL\tgithub.com/github/gh-aw/pkg/parser [setup failed]\nFAIL","stderr":"","interrupted":false,"isImage":false,"noOutputExpected":false}}
|
|
agent
Includes Playwright in setup sequence\n//\n// Example configuration:\n//\n//\ttools:\n//\t playwright:\n//\t version: v1.41.0\n//\t args:\n//\t - --debug\n//\t - --timeout=30000\n//\tnetwork:\n//\t allowed:\n//\t - github.com\n//\t - api.github.com\npackage workflow\n\nimport (\n\t\"strings\"\n\n\t\"github.com/github/gh-aw/pkg/logger\"\n)\n\nvar mcpPlaywrightLog = logger.New(\"workflow:mcp_config_playwright_renderer\")\n\n// renderPlaywrightMCPConfig generates the Playwright MCP server configuration\n// Uses Docker container to launch Playwright MCP for consistent browser environment\n// This is a shared function used by both Claude and Custom engines\nfunc renderPlaywrightMCPConfig(yaml *strings.Builder, playwrightConfig *PlaywrightToolConfig, isLast bool) {\n\tmcpPlaywrightLog.Print(\"Rendering Playwright MCP configuration\")\n\trenderPlaywrightMCPConfigWithOptions(yaml, playwrightConfig, isLast, false, false)\n}\n\n// renderPlaywrightMCPConfigWithOptions generates the Playwright MCP server configuration with engine-specific options\n// Per MCP Gateway Specification v1.0.0 section 3.2.1, stdio-based MCP servers MUST be containerized.\n// Uses MCP Gateway spec format: container, entrypointArgs, mounts, and args fields.\nfunc renderPlaywrightMCPConfigWithOptions(yaml *strings.Builder, playwrightConfig *PlaywrightToolConfig, isLast bool, includeCopilotFields bool, inlineArgs bool) {\n\tcustomArgs := getPlaywrightCustomArgs(playwrightConfig)\n\n\t// Extract all expressions from playwright arguments and replace them with env var references\n\texpressions := extractExpressionsFromPlaywrightArgs(customArgs)\n\n\t// Replace expressions in custom args\n\tif len(customArgs) > 0 {\n\t\tcustomArgs = replaceExpressionsInPlaywrightArgs(customArgs, expressions)\n\t}\n\n\t// Use official Playwright MCP Docker image (no version tag - only one image)\n\tplaywrightImage := \"mcr.microsoft.com/playwright/mcp\"\n\n\tyaml.WriteString(\" \\\"playwright\\\": {\\n\")\n\n\t// Add type field for Copilot (per MCP Gateway Specification v1.0.0, use \"stdio\" for containerized servers)\n\tif includeCopilotFields {\n\t\tyaml.WriteString(\" \\\"type\\\": \\\"stdio\\\",\\n\")\n\t}\n\n\t// MCP Gateway spec fields for containerized stdio servers\n\tyaml.WriteString(\" \\\"container\\\": \\\"\" + playwrightImage + \"\\\",\\n\")\n\n\t// Docker runtime args (goes before container image in docker run command)\n\t// These are additional flags for docker run like --init and --network\n\t// Add security-opt and ipc flags for Chromium browser compatibility in GitHub Actions\n\t// --security-opt seccomp=unconfined: Required for Chromium sandbox to function properly\n\t// --ipc=host: Provides shared memory access required by Chromium\n\tdockerArgs := []string{\"--init\", \"--network\", \"host\", \"--security-opt\", \"seccomp=unconfined\", \"--ipc=host\"}\n\tif inlineArgs {\n\t\tyaml.WriteString(\" \\\"args\\\": [\")\n\t\tfor i, arg := range dockerArgs {\n\t\t\tif i > 0 {\n\t\t\t\tyaml.WriteString(\", \")\n\t\t\t}\n\t\t\tyaml.WriteString(\"\\\"\" + arg + \"\\\"\")\n\t\t}\n\t\tyaml.WriteString(\"],\\n\")\n\t} else {\n\t\tyaml.WriteString(\" \\\"args\\\": [\\n\")\n\t\tfor i, arg := range dockerArgs {\n\t\t\tyaml.WriteString(\" \\\"\" + arg + \"\\\"\")\n\t\t\tif i < len(dockerArgs)-1 {\n\t\t\t\tyaml.WriteString(\",\")\n\t\t\t}\n\t\t\tyaml.WriteString(\"\\n\")\n\t\t}\n\t\tyaml.WriteString(\" ],\\n\")\n\t}\n\n\t// Build entrypoint args for Playwright MCP server (goes after container image)\n\t// --no-sandbox: Disables Chromium's process sandbox, which otherwise\n\t// creates a network namespace for renderer processes that cannot reach localhost.\n\t// This is required for screenshot workflows that serve docs on localhost.\n\t// Note: as of @playwright/mcp v0.0.26+, --no-sandbox is a direct top-level flag.\n\tentrypointArgs := []string{\"--output-dir\", \"/tmp/gh-aw/mcp-logs/playwright\", \"--no-sandbox\"}\n\t// Append custom args if present\n\
|
|
agent
Includes Playwright in setup sequence\n//\n// Example configuration:\n//\n//\ttools:\n//\t playwright:\n//\t version: v1.41.0\n//\t args:\n//\t - --debug\n//\t - --timeout=30000\n//\tnetwork:\n//\t allowed:\n//\t - github.com\n//\t - api.github.com\npackage workflow\n\nimport (","numLines":60,"startLine":1,"totalLines":175}}}
|
|
agent
Safe inputs HTTP server configuration\n//\n// Example:\n//\n//\t// Before: http://localhost:3001\n//\t// After: http://host.docker.internal:3001\n//\turl := rewriteLocalhostToDockerHost(\"http://localhost:3001\")\npackage workflow\n\nimport (\n\t\"strings\"\n\n\t\"github.com/github/gh-aw/pkg/logger\"\n)\n\nvar mcpUtilsLog = logger.New(\"workflow:mcp-config-utils\")\n\n// rewriteLocalhostToDockerHost rewrites localhost URLs to use host.docker.internal\n// This is necessary when MCP servers run on the host machine but are accessed from within\n// a Docker container (e.g., when firewall/sandbox is enabled)\nfunc rewriteLocalhostToDockerHost(url string) string {\n\t// Define the localhost patterns to replace and their docker equivalents\n\t// Each pattern is a (prefix, replacement) pair\n\treplacements := []struct {\n\t\tprefix string\n\t\treplacement string\n\t}{\n\t\t{\"http://localhost\", \"http://host.docker.internal\"},\n\t\t{\"https://localhost\", \"https://host.docker.internal\"},\n\t\t{\"http://127.0.0.1\", \"http://host.docker.internal\"},\n\t\t{\"https://127.0.0.1\", \"https://host.docker.internal\"},\n\t}\n\n\tfor _, r := range replacements {\n\t\tif strings.HasPrefix(url, r.prefix) {\n\t\t\tnewURL := r.replacement + url[len(r.prefix):]\n\t\t\tmcpUtilsLog.Printf(\"Rewriting localhost URL for Docker access: %s -> %s\", url, newURL)\n\t\t\treturn newURL\n\t\t}\n\t}\n\n\treturn url\n}\n\n// shouldRewriteLocalhostToDocker returns true when MCP server localhost URLs should be\n// rewritten to host.docker.internal so that containerised AI agents can reach servers\n// running on the host. Rewriting is enabled whenever the agent sandbox is active\n// (i.e. sandbox.agent is not explicitly disabled).\nfunc shouldRewriteLocalhostToDocker(workflowData *WorkflowData) bool {\n\treturn workflowData != nil && (workflowData.SandboxConfig == nil ||\n\t\tworkflowData.SandboxConfig.Agent == nil ||\n\t\t!workflowData.SandboxConfig.Agent.Disabled)\n}\n\n// noOpCacheMemoryRenderer is a no-op MCPToolRenderers.RenderCacheMemory function for engines\n// that do not need an MCP server entry for cache-memory. Cache-memory is a simple file share\n// accessible at /tmp/gh-aw/cache-memory/ and requires no MCP configuration.\nfunc noOpCacheMemoryRenderer(_ *strings.Builder, _ bool, _ *WorkflowData) {}\n","numLines":94,"startLine":1,"totalLines":94}}}
|
|
agent
JavaScript runtime mode compatibility\n//\n// # Pass-Through Field Validation\n//\n// Several workflow frontmatter fields are \"pass-through\" fields - they are extracted\n// from frontmatter and passed directly to GitHub Actions without modification:\n// - concurrency: Workflow concurrency control\n// - container: Container configuration for jobs\n// - environment: GitHub environment configuration\n// - env: Environment variables\n// - runs-on: Runner selection\n// - services: Service containers\n//\n// These fields ARE validated during frontmatter parsing using JSON Schema validation\n// (see pkg/parser/schemas/main_workflow_schema.json). The schema catches:\n// - Invalid data types (e.g., array when object expected)\n// - Missing required properties (e.g., container missing 'image')\n// - Invalid additional properties (e.g., unknown fields in concurrency)\n// - Structure violations (e.g., runs-on as number instead of string/array/object)\n//\n// Schema validation happens in pkg/parser/schema_validation.go during frontmatter\n// parsing, so errors are caught at compile time rather than GitHub Actions runtime.\n// See pkg/parser/schema_passthrough_validation_test.go for comprehensive test coverage.\n//\n// # When to Add New Validation\n//\n// Add validation to existing domain files when:\n// - It fits the domain (e.g., package validation → pip_validation.go)\n// - It extends existing functionality\n//\n// Create a new validation file when:\n// - It represents a distinct validation domain\n// - It has multiple related validation functions\n// - It requires its own caching or state management\n//\n// # Validation Patterns\n//\n// The validation system uses several patterns:\n// - Schema validation: JSON schema validation with caching\n// - External resource validation: Docker images, npm/pip packages\n// - Size limit validation: Expression sizes, file sizes\n// - Feature detection: Repository capabilities\n// - Security validation: Permission restrictions, expression safety\n\npackage workflow\n","numLines":71,"startLine":1,"totalLines":71}}}
|
|
agent
Failed to process file /tmp/gh-aw/mcp-logs/rpc-messages.jsonl: EACCES: permission denied, open '/tmp/gh-aw/mcp-logs/rpc-messages.jsonl'
|
|
agent
Failed to process file /tmp/gh-aw/mcp-logs/mcp-gateway.log: EACCES: permission denied, open '/tmp/gh-aw/mcp-logs/mcp-gateway.log'
|
|
agent
Safe Inputs MCP Server Startup Log
|
|
agent
Safe Outputs MCP Server Startup Log
|
Artifacts
Produced during runtime
| Name | Size | Digest | |
|---|---|---|---|
|
activation
Expired
|
5.9 KB |
sha256:d5af758198f47a9f26579c3f28fa80b542c07d8598be6bc54ee711c53cc36f38
|
|
|
agent-artifacts
|
339 KB |
sha256:aa083ecdd2f11ce913f50926c345921e84efb6244a2214f73c3d43543db58776
|
|
|
agent-output
|
1.18 KB |
sha256:27dfe53128525896a4ba1a6545b538381f9191b3f4ce3095749f893780022b24
|
|
|
cache-memory
|
645 Bytes |
sha256:4e063720b11669bddb711e29f27a2a69d9d9fcc44cdb6eb3c30f5fd6b5ca2848
|
|
|
safe-output
|
1.16 KB |
sha256:fc989f45929e6859a9b8bfe6c9f6f5422029c693a39b0d37c1021b5944ff0b86
|
|
|
safe-output-items
|
162 Bytes |
sha256:e71b15a764290d6cae1e00741f32ca70a6248b6712260225eaaa54f0aabf7cd5
|
|
|
threat-detection.log
|
22.8 KB |
sha256:a99b7588b5cea1859c4519eadca686c217eab213b1336318ae498bcdeafdb019
|
|