feat(autofix): Support explorer autofix steps in slack operator#108569
feat(autofix): Support explorer autofix steps in slack operator#108569
Conversation
leeandher
left a comment
There was a problem hiding this comment.
looks good! thank you again 🙏
| # | ||
| # Everything except the processing status | ||
| # is considered as some form of completed | ||
| completed = autofix_state.status != "processing" |
There was a problem hiding this comment.
Bug: The function get_autofix_explorer_status incorrectly treats "error" and "awaiting_user_input" states as "completed", misleading users and breaking the autofix flow.
Severity: HIGH
Suggested Fix
The completion check should be more specific. Change the line completed = autofix_state.status != "processing" to completed = autofix_state.status == "completed" to ensure only successfully completed runs are marked as such. This will allow other states like "error" and "awaiting_user_input" to be handled correctly.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: src/sentry/seer/entrypoints/operator.py#L556
Potential issue: The function `get_autofix_explorer_status` at line 556 uses the logic
`completed = autofix_state.status != "processing"` to determine if a step is complete.
This incorrectly classifies runs with `"error"` or `"awaiting_user_input"` statuses as
complete. As a result, when an autofix run fails or requires user interaction, the
system reports it as successful in Slack. This misleads the user about the outcome and
prevents them from retrying a failed run or providing input to a paused one, effectively
freezing the process from their perspective.
| def trigger_autofix_explorer( | ||
| self, | ||
| *, | ||
| group: Group, | ||
| user: User | RpcUser, | ||
| stopping_point: AutofixStoppingPoint, | ||
| instruction: str | None = None, | ||
| run_id: int | None = None, | ||
| ) -> None: |
There was a problem hiding this comment.
Bug: The instruction parameter in trigger_autofix_explorer is accepted but its value is never used, causing user instructions to be silently ignored in the explorer flow.
Severity: MEDIUM
Suggested Fix
To fix this, the instruction parameter should be removed from the SeerOperator.trigger_autofix_explorer method signature to avoid confusion, as the underlying functionality does not support it. Alternatively, if instruction support is intended, the underlying trigger_autofix_explorer function in autofix_agent.py must be updated to accept and utilize the instruction parameter.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: src/sentry/seer/entrypoints/operator.py#L150-L158
Potential issue: The `trigger_autofix_explorer` method in the `SeerOperator` class
accepts an `instruction` parameter, implying that users can provide custom instructions
to guide the autofix process. However, this parameter is never used within the method's
body. The value is not passed to the underlying `trigger_autofix_explorer` function,
which does not support this parameter. This leads to user-provided instructions being
silently ignored when the explorer-based autofix flow is triggered, resulting in autofix
behavior that does not match user expectations.
| run_id=None, | ||
| ) | ||
| elif stopping_point == AutofixStoppingPoint.OPEN_PR: | ||
| pass # TODO: OPENING PRs is a little more complicated so putting it off for now |
There was a problem hiding this comment.
OPEN_PR no-op falls through to false success signal
Medium Severity
When stopping_point is OPEN_PR and run_id is set, the elif branch does pass but doesn't return, so execution falls through to on_trigger_autofix_success and cache creation. This sends a misleading success message to Slack and creates a cache entry even though no autofix step was actually triggered. The legacy path properly handles OPEN_PR by building an AutofixCreatePRPayload. The pass here needs an early return or error notification to avoid false user-facing feedback.
Additional Locations (1)
| if stopping_point == AutofixStoppingPoint.OPEN_PR and completed: | ||
| return all( | ||
| pr_state.pr_creation_status != "creating" | ||
| for pr_state in autofix_state.repo_pr_states.values() | ||
| ) |
There was a problem hiding this comment.
Bug: The use of all() on an empty repo_pr_states dictionary incorrectly returns True, marking the OPEN_PR stage as complete when no PRs have been created.
Severity: MEDIUM
Suggested Fix
Modify the logic to ensure that repo_pr_states is not empty before evaluating the all() condition. The expression should only return True if the dictionary is non-empty and all its values meet the condition. For example: return bool(autofix_state.repo_pr_states) and all(...).
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: src/sentry/seer/entrypoints/operator.py#L560-L564
Potential issue: When checking the status of an `OPEN_PR` stopping point, the code
evaluates `all(pr_state.pr_creation_status != "creating" for pr_state in
autofix_state.repo_pr_states.values())`. If the `repo_pr_states` dictionary is empty,
which can happen if the PR creation step failed or has not run, Python's `all()`
function on the empty collection returns `True`. This incorrectly signals that the
`OPEN_PR` stage is complete. As a result, the system may prevent the user from
triggering or re-triggering PR creation, as it believes the step has already finished
successfully.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| stopping_point=stopping_point, | ||
| instruction=instruction, | ||
| run_id=run_id, | ||
| ) |
There was a problem hiding this comment.
has_access blocks explorer orgs making new path unreachable
High Severity
The new trigger_autofix routing dispatches to trigger_autofix_explorer when organizations:autofix-on-explorer is enabled, but the existing has_access method returns False for the exact same flag (line 84). Since has_access gates whether autofix buttons appear in Slack messages and whether update caching is set up, the new explorer path is unreachable in production — no user can ever trigger it.


Add basic support for explorer autofix in the slack operator to trigger various steps in the integration.
Missing: