Log first trigger reason for agentics-maintenance generation#38616
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR improves observability for agentics-maintenance.yml generation by capturing and surfacing the first workflow condition that triggered maintenance generation, making the causality explicit in logs for faster triage.
Changes:
- Extended
scanWorkflowsForExpiresto return a third value,triggerReason, representing the first trigger encountered. - Added a generation-time log line in
GenerateMaintenanceWorkflowto print the trigger reason when maintenance generation occurs. - Added unit tests covering the no-trigger case and “first trigger wins” semantics.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/maintenance_workflow.go | Returns and logs a “first trigger reason” for maintenance workflow generation. |
| pkg/workflow/maintenance_workflow_test.go | Adds unit coverage for triggerReason behavior (empty vs. first-trigger-wins). |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 1
| setTriggerReason := func(reason string) { | ||
| if triggerReason == "" { | ||
| triggerReason = reason | ||
| maintenanceLog.Printf("Maintenance workflow became required: %s", reason) | ||
| } |
|
✅ PR Code Quality Reviewer completed the code quality review. |
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed: PR #38616 does not have the implementation label (has_implementation_label=false) and has 58 new lines of code in business logic directories, which is below the 100-line threshold (requires_adr_by_default_volume=false). |
|
🧪 Test Quality Sentinel completed test quality analysis. |
|
🧠 Matt Pocock Skills Reviewer was skipped during the skills-based review. |
🧪 Test Quality Sentinel Report✅ Test Quality Score: 90/100 — Excellent
📊 Metrics & Test Classification (2 test scenarios analyzed)
Test Classification Details
Language SupportTests analyzed:
|
There was a problem hiding this comment.
✅ Test Quality Sentinel: 90/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). Both sub-tests are high-value behavioral contracts covering the 'first trigger wins' invariant and nil-input edge case. Minor: 8 assertions are missing descriptive messages (soft guideline warning, not a failure condition).
There was a problem hiding this comment.
Non-blocking observation
The refactoring correctly separates hasExpires tracking from triggerReason tracking, and the new test assertion (require.NotContains) properly validates the first-trigger-wins behavior.
One maintainability concern (see inline comment)
Moving hasExpires = true out of the closure and into 4 call sites creates a hidden contract: every future check block must remember to set hasExpires = true before calling setTriggerReason. If a new expiration type is added and the assignment is missed, scanWorkflowsForExpires silently returns hasExpires=false despite a qualifying workflow existing. Consolidating hasExpires = true back into the closure eliminates this risk with no behavioral change.
🔎 Code quality review by PR Code Quality Reviewer · ⌖ 13.2 AIC
| triggerReason := "" | ||
|
|
||
| setTriggerReason := func(reason string) { | ||
| if triggerReason == "" { |
There was a problem hiding this comment.
Decoupled invariant: setTriggerReason no longer owns hasExpires, creating an implicit call-site contract — any future check block that calls setTriggerReason without first setting hasExpires = true will silently return an inconsistent state (hasExpires=false with a non-empty triggerReason, or vice versa).
💡 Suggested fix: consolidate `hasExpires` back into the closure
The original closure atomically managed both variables. Keeping that invariant while still separating the two guards is straightforward:
setTriggerReason := func(reason string) {
hasExpires = true
if triggerReason == "" {
triggerReason = reason
maintenanceLog.Printf("Maintenance workflow became required: %s", reason)
}
}This restores a single source of truth for hasExpires and eliminates the 4 duplicated hasExpires = true assignments at the call sites. Every future check block automatically sets the flag by calling setTriggerReason, with no extra step to remember.
The compiler generated
agentics-maintenance.ymlwithout clearly stating which workflow condition required it. This change makes maintenance generation causality explicit in logs by recording and surfacing the first triggering condition.Trigger-cause visibility
triggerReason.create_issues.expires,create_discussions.expires,create_pull_requests.expires, or no-op issue reporting).Generation-time logging
Maintenance workflow generation triggered: <reason>expiresdiagnostics while adding a single high-signal cause line for quick triage.Behavior contract coverage
triggerReason == "")