Conversation
…ection - Replace reflection-based hasAnySafeOutputEnabled with direct nil-checks for all 41 SafeOutputsConfig pointer fields — eliminates ~37 reflect.FieldByName calls per compilation, saving ~50µs/iteration - Replace reflection-based hasNonBuiltinSafeOutputsEnabled similarly - Cache os.Getwd() with sync.Once in ToRelativePath to eliminate repeated syscalls during compilation output formatting - Remove now-unused safeOutputReflectionLog, builtinSafeOutputFields, and nonBuiltinSafeOutputFieldNames variables - Update file header comment and safeOutputFieldMapping doc to guide future contributors when adding new safe output types Benchmark result: BenchmarkYAMLGeneration improved ~14% Before: ~1,020,330 ns/op After: ~862,000 ns/op Agent-Logs-Url: https://github.com/github/gh-aw/sessions/eaeef1d3-12cd-442d-902b-fcfb53133977 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
…tions against drift Add a reflection-based test that validates every field in safeOutputFieldMapping is also covered by hasAnySafeOutputEnabled and hasNonBuiltinSafeOutputsEnabled. If a new safe output type is added to safeOutputFieldMapping without updating the direct-check functions, this test will fail immediately. Also add field count comments to both functions (42 total, 39 non-builtin). Agent-Logs-Url: https://github.com/github/gh-aw/sessions/eaeef1d3-12cd-442d-902b-fcfb53133977 Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Optimizes two compile-time hot paths by replacing reflective safe-output state checks with direct field checks and by caching the working directory used for path rendering.
Changes:
- Replaced reflection in
hasAnySafeOutputEnabledandhasNonBuiltinSafeOutputsEnabledwith explicit nil checks. - Added a regression test to keep the manual safe-output field lists aligned with the mapped handler fields.
- Cached
os.Getwd()inToRelativePathusingsync.Onceto avoid repeated syscalls.
Show a summary per file
| File | Description |
|---|---|
pkg/workflow/safe_outputs_state.go |
Reworks safe-output enabled-state detection to use direct field checks instead of reflection. |
pkg/workflow/safe_outputs_state_test.go |
Adds a reflection-driven regression test for the manual safe-output check lists. |
pkg/console/render.go |
Caches the working directory for relative-path rendering. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
pkg/workflow/safe_outputs_state.go:153
- CommentMemory is also missing from the non-builtin list. Because applyDefaultCreateIssue() runs after comment-memory is attached to SafeOutputs (compiler_orchestrator_workflow.go:322-329, 409-411), a workflow whose only meaningful output is comment-memory is still seen as having no non-builtin outputs and gets an auto-injected create-issue it did not ask for.
// Direct nil checks for non-builtin pointer fields (39 fields = 42 total minus 3 builtins:
// NoOp, MissingData, MissingTool).
return safeOutputs.CreateIssues != nil ||
safeOutputs.CreateAgentSessions != nil ||
safeOutputs.CreateDiscussions != nil ||
- Files reviewed: 3/3 changed files
- Comments generated: 3
| workingDirOnce.Do(func() { | ||
| workingDir, workingDirErr = os.Getwd() | ||
| }) |
| // Direct nil checks — no reflection, no heap allocation (42 fields matching safeOutputFieldMapping). | ||
| return safeOutputs.CreateIssues != nil || | ||
| safeOutputs.CreateAgentSessions != nil || | ||
| safeOutputs.CreateDiscussions != nil || | ||
| safeOutputs.UpdateDiscussions != nil || |
| // TestSafeOutputStateFieldCoverage verifies that hasAnySafeOutputEnabled and | ||
| // hasNonBuiltinSafeOutputsEnabled cover every pointer field listed in | ||
| // safeOutputFieldMapping. This acts as a regression guard to ensure that when | ||
| // a new safe output type is added to safeOutputFieldMapping, the developer is | ||
| // reminded (via a failing test) to also update the two direct-check functions. |
|
@copilot review all changes |
…hdir bug - Add CommentMemory to hasAnySafeOutputEnabled and hasNonBuiltinSafeOutputsEnabled: a workflow that only enables tools.comment-memory was incorrectly treated as having no safe outputs, preventing safe-output prompt/config generation. - Revert sync.Once caching in ToRelativePath: the codebase calls os.Chdir() in production paths (trial_helpers.go, trial_repository.go, pr_command.go) so caching the working directory on first access would yield stale paths after any directory change. - Update stale "reflection-based" comment in safe_jobs_needs_validation.go. - Add TestSafeOutputStateCommentMemoryCoverage to explicitly guard CommentMemory, which lives outside safeOutputFieldMapping and is not caught by the map-driven TestSafeOutputStateFieldCoverage test. - Bump field counts to 43 total / 40 non-builtin. Agent-Logs-Url: https://github.com/github/gh-aw/sessions/3d0069d6-f3d5-47eb-b2b3-c39f758faeda Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Three issues were found and fixed in commit
|
BenchmarkYAMLGenerationregressed ~28% (1.62ms → 2.08ms) due to a hot path executing on every compilation.Root cause
hasAnySafeOutputEnabled/hasNonBuiltinSafeOutputsEnabled— both usedreflect.Value.FieldByNamein a loop across 41+SafeOutputsConfigpointer fields (~54µs/iter). BecauseapplyDefaultCreateIssuealways produces a non-nilSafeOutputsConfigeven for workflows withoutsafe-outputs:, the reflection loop ran unconditionally on every compile.Changes
safe_outputs_state.go: Replace reflection loops in bothhasAnySafeOutputEnabled(43 fields) andhasNonBuiltinSafeOutputsEnabled(40 non-builtin fields) with direct!= nilpointer comparisons — zero allocation, zero reflection overhead. Also addsCommentMemorywhich was previously missing from both checks: workflows using onlytools: comment-memory:were incorrectly treated as having no safe outputs, preventing safe-output prompt/config generation and causing an unwanted auto-injectedcreate-issue. Remove now-dead variables (safeOutputReflectionLog,builtinSafeOutputFields,nonBuiltinSafeOutputFieldNames).safe_outputs_state_test.go(new):TestSafeOutputStateFieldCoverageiteratessafeOutputFieldMappingvia reflection and asserts each field triggers both check functions — fails immediately if a new safe output type is added to the mapping without updating the direct-check lists.TestSafeOutputStateCommentMemoryCoverageexplicitly guardsCommentMemory, which lives outsidesafeOutputFieldMapping.safe_jobs_needs_validation.go: Update stale comment that referred to the removed reflection-based implementation.