Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f838f8b
feature-296-bugbot-autofix: Remove getSessionDiff usage from CLI outp…
efraespada Feb 11, 2026
6055de0
feature-296-bugbot-autofix: Simplify CLI output by removing session d…
efraespada Feb 11, 2026
dc45e00
feature-296-bugbot-autofix: Add support for configurable verify comma…
efraespada Feb 11, 2026
0e92800
feature-296-bugbot-autofix: Refactor bugbot autofix logic to improve …
efraespada Feb 11, 2026
695bb09
feature-296-bugbot-autofix: Enhance logging for bugbot fix intent det…
efraespada Feb 11, 2026
7b149c5
feature-296-bugbot-autofix: Refactor bugbot fix intent handling by ex…
efraespada Feb 11, 2026
83ed5f0
feature-296-bugbot-autofix: Refactor PullRequestRepository to use pag…
efraespada Feb 11, 2026
9aefa54
feature-296-bugbot-autofix: Introduce reviewCommentPayload getter in …
efraespada Feb 11, 2026
1828498
feature-296-bugbot-autofix: Implement getTokenUserDetails method to r…
efraespada Feb 11, 2026
569b57e
feature-296-bugbot-autofix: bugbot autofix - resolve reported findings
vypbot Feb 12, 2026
919bdd1
feature-296-bugbot-autofix: bugbot autofix - resolve reported findings
vypbot Feb 12, 2026
b08044f
feature-296-bugbot-autofix: Integrate shell-quote for parsing verify …
efraespada Feb 12, 2026
abee779
Merge branch 'feature/296-bugbot-autofix' of https://github.com/vypde…
efraespada Feb 12, 2026
06a8ff1
feature-296-bugbot-autofix: Add handling for empty head branch in loa…
efraespada Feb 12, 2026
ac73ab6
feature-296-bugbot-autofix: Sanitize user comments in bugbot prompts …
efraespada Feb 12, 2026
eb0e43e
feature-296-bugbot-autofix: Enhance getHeadBranchForIssue method with…
efraespada Feb 12, 2026
a469698
feature-296-bugbot-autofix: Enhance isLinked method with timeout hand…
efraespada Feb 12, 2026
d214b72
feature-296-bugbot-autofix: bugbot autofix - resolve bugbot_autofix_c…
vypbot Feb 12, 2026
0e161d9
feature-296-bugbot-autofix: Enhance Bugbot autofix functionality with…
efraespada Feb 12, 2026
faddf72
feature-296-bugbot-autofix: Integrate OPENCODE_PROJECT_CONTEXT_INSTRU…
efraespada Feb 12, 2026
62d4398
feature-296-bugbot-autofix: Implement logic to recommend steps or pro…
efraespada Feb 12, 2026
9dde42b
feature-296-bugbot-autofix: Introduce a limit on the number of verify…
efraespada Feb 12, 2026
95033db
feature-296-bugbot-autofix: Implement truncation for finding body com…
efraespada Feb 12, 2026
11d45ae
feature-296-bugbot-autofix: Export truncateFindingBody function and a…
efraespada Feb 12, 2026
f13f847
feature-296-bugbot-autofix: Improve parent comment processing to avoi…
efraespada Feb 12, 2026
c6b4308
feature-296-bugbot-autofix: Implement user request handling in IssueC…
efraespada Feb 12, 2026
e211aeb
feature-296-bugbot-autofix: Add Bugbot documentation and enhance inte…
efraespada Feb 12, 2026
4f8f249
feature-296-bugbot-autofix: Enhance Bugbot documentation by adding ne…
efraespada Feb 12, 2026
031dafa
feature-296-bugbot-autofix: Update documentation for issues, pull req…
efraespada Feb 12, 2026
5155952
feature-296-bugbot-autofix: Enhance Bugbot marker functionality by ad…
efraespada Feb 12, 2026
06d8ad6
feature-296-bugbot-autofix: Add length limits and safe character vali…
efraespada Feb 12, 2026
3c14a69
feature-296-bugbot-autofix: Implement truncation of issue comment bod…
efraespada Feb 12, 2026
743d21f
feature-296-bugbot-autofix: Introduce sanitization and length limits …
efraespada Feb 12, 2026
4f1800c
feature-296-bugbot-autofix: Refactor user request handling in IssueCo…
efraespada Feb 12, 2026
2ac0e6c
feature-296-bugbot-autofix: Enhance file ignore pattern handling by i…
efraespada Feb 12, 2026
7c9f7f2
feature-296-bugbot-autofix: Update handling of unresolved findings to…
efraespada Feb 12, 2026
e14c6fe
feature-296-bugbot-autofix: Refactor user comment sanitization to imp…
efraespada Feb 12, 2026
6fc9e3a
feature-296-bugbot-autofix: Implement title and file length limits wi…
efraespada Feb 12, 2026
2c67a55
feature-296-bugbot-autofix: Enhance regex handling in BranchRepositor…
efraespada Feb 12, 2026
8f96f78
feature-296-bugbot-autofix: Remove unused FileRepository and related …
efraespada Feb 12, 2026
70f0a4f
feature-296-bugbot-autofix: Remove deprecated constants and utility f…
efraespada Feb 12, 2026
702181e
feature-296-bugbot-autofix: Update Jest configuration to include cove…
efraespada Feb 12, 2026
9c75a5d
feature-296-bugbot-autofix: Enhance test coverage for user request ha…
efraespada Feb 12, 2026
4df08da
feature-296-bugbot-autofix: Enhance test coverage for Bugbot use case…
efraespada Feb 12, 2026
1e1d6d6
feature-296-bugbot-autofix: Refactor GitHub Action execution logic to…
efraespada Feb 12, 2026
2bd5472
feature-296-bugbot-autofix: Refactor CLI and GitHub Action execution …
efraespada Feb 12, 2026
84673fe
feature-296-bugbot-autofix: Enhance CLI test coverage by adding scena…
efraespada Feb 12, 2026
eb13c62
feature-296-bugbot-autofix: Update README with badges and modify tsco…
efraespada Feb 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
22 changes: 21 additions & 1 deletion .cursor/rules/architecture.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ alwaysApply: true
| Shared flow | `src/actions/common_action.ts` | mainRun, waitForPreviousRuns, dispatch to use cases |
| Use cases | `src/usecase/` | issue_use_case, pull_request_use_case, commit_use_case, single_action_use_case |
| Single actions | `src/usecase/actions/` | check_progress, detect_errors, recommend_steps, think, initial_setup, create_release, create_tag, publish_github_action, deployed_action |
| Steps (issue) | `src/usecase/steps/issue/` | check_permissions, close_not_allowed_issue, assign_members, update_title, update_issue_type, link_issue_project, check_priority_issue_size, prepare_branches, remove_issue_branches, remove_not_needed_branches, label_deploy_added, label_deployed_added, move_issue_to_in_progress |
| Steps (issue) | `src/usecase/steps/issue/` | check_permissions, close_not_allowed_issue, assign_members, update_title, update_issue_type, link_issue_project, check_priority_issue_size, prepare_branches, remove_issue_branches, remove_not_needed_branches, label_deploy_added, label_deployed_added, move_issue_to_in_progress, answer_issue_help_use_case (question/help on open). On issue opened: RecommendStepsUseCase (non release/question/help) or AnswerIssueHelpUseCase (question/help). |
| Steps (PR) | `src/usecase/steps/pull_request/` | update_title, assign_members (issue), assign_reviewers_to_issue, link_pr_project, link_pr_issue, sync_size_and_progress_from_issue, check_priority_pull_request_size, update_description (AI), close_issue_after_merging |
| Steps (commit) | `src/usecase/steps/commit/` | notify commit, check size |
| Steps (issue comment) | `src/usecase/steps/issue_comment/` | check_issue_comment_language (translation) |
| Steps (PR review comment) | `src/usecase/steps/pull_request_review_comment/` | check_pull_request_comment_language (translation) |
| Bugbot autofix & user request | `src/usecase/steps/commit/bugbot/` + `user_request_use_case.ts` | detect_bugbot_fix_intent_use_case (plan agent: is_fix_request, is_do_request, target_finding_ids), BugbotAutofixUseCase + runBugbotAutofixCommitAndPush (fix findings), DoUserRequestUseCase + runUserRequestCommitAndPush (generic β€œdo this”). Permission: ProjectRepository.isActorAllowedToModifyFiles (org member or repo owner). |
| Manager (content) | `src/manager/` | description handlers, configuration_handler, markdown_content_hotfix_handler (PR description, hotfix changelog content) |
| Models | `src/data/model/` | Execution, Issue, PullRequest, SingleAction, etc. |
| Repos | `src/data/repository/` | branch_repository, issue_repository, workflow_repository, ai_repository (OpenCode), file_repository, project_repository |
Expand All @@ -48,3 +49,22 @@ alwaysApply: true
## Concurrency (sequential runs)

`common_action.ts` calls `waitForPreviousRuns(execution)` (from `src/utils/queue_utils.ts`): lists workflow runs, waits until no previous run of the **same workflow name** is in progress/queued, then continues. Implemented in `WorkflowRepository.getActivePreviousRuns`.

## Flow: issue comment & PR review comment (intent + permissions + actions)

When the event is **issue_comment** or **pull_request_review_comment**, `common_action.ts` invokes `IssueCommentUseCase` or `PullRequestReviewCommentUseCase` respectively. Both follow the same flow:

1. **Check language** (e.g. translation): `CheckIssueCommentLanguageUseCase` / `CheckPullRequestCommentLanguageUseCase`.
2. **Detect intent** (OpenCode plan agent): `DetectBugbotFixIntentUseCase` runs and returns a payload with:
- `isFixRequest`: user asked to fix one or more bugbot findings.
- `isDoRequest`: user asked to perform some other change/task in the repo (generic β€œdo this”).
- `targetFindingIds`: when fix request, which finding ids to fix.
- `context`, `branchOverride`: for autofix (e.g. branch from open PR when on issue comment).
3. **Permission check**: `ProjectRepository.isActorAllowedToModifyFiles(owner, actor, token)`:
- If repo **owner is an organization**: actor must be a **member** of that org.
- If repo **owner is a user**: actor must be the **same** as the owner.
- If not allowed and the intent was fix or do-request, we skip the file-modifying use cases and log; Think still runs so the user gets a response.
4. **Run at most one file-modifying action** (only if allowed):
- If **fix request** with targets and context: `BugbotAutofixUseCase` β†’ `runBugbotAutofixCommitAndPush` β†’ optionally `markFindingsResolved`.
- Else if **do request** (and not fix): `DoUserRequestUseCase` β†’ `runUserRequestCommitAndPush`.
5. **Think**: If **no** file-modifying action ran (no intent, no permission, or no targets/context), we run `ThinkUseCase` so the user gets an AI reply (e.g. answer to a question).
128 changes: 128 additions & 0 deletions .cursor/rules/bugbot.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
description: Detailed technical reference for Bugbot (detection, markers, context, intent, autofix, do user request, permissions)
alwaysApply: false
---

# Bugbot – technical reference

Bugbot has two main modes: **detection** (on push or single action) and **fix/do** (on issue comment or PR review comment). All Bugbot code lives under `src/usecase/steps/commit/bugbot/` and `src/usecase/steps/commit/` (DetectPotentialProblemsUseCase, user_request_use_case).

---

## 1. Detection flow (push or single action)

**Entry:** `CommitUseCase` (on push) calls `DetectPotentialProblemsUseCase`; or `SingleActionUseCase` when action is `detect_potential_problems_action`.

**Steps:**

1. **Guard:** OpenCode must be configured; `issueNumber !== -1`.
2. **Load context:** `loadBugbotContext(param)` β†’ issue comments + PR review comments parsed for markers; builds `existingByFindingId`, `issueComments`, `openPrNumbers`, `previousFindingsBlock`, `prContext`, `unresolvedFindingsWithBody`. Branch is `param.commit.branch` (or `options.branchOverride` when provided). PR context includes `prHeadSha`, `prFiles`, `pathToFirstDiffLine` for the first open PR.
3. **Build prompt:** `buildBugbotPrompt(param, context)` – repo context, head/base branch, issue number, optional `ai-ignore-files`, and `previousFindingsBlock` (task 2: which previous findings are now resolved). OpenCode is asked to compute the diff itself and return `findings` + `resolved_finding_ids`.
4. **Call OpenCode:** `askAgent(OPENCODE_AGENT_PLAN, prompt, BUGBOT_RESPONSE_SCHEMA)`.
5. **Process response:** Filter findings: safe path (`isSafeFindingFilePath`), not in `ai-ignore-files` (`fileMatchesIgnorePatterns`), `meetsMinSeverity` (min from `bugbot-severity`), `deduplicateFindings`. Apply `applyCommentLimit(findings, bugbot-comment-limit)` β†’ `toPublish`, `overflowCount`, `overflowTitles`.
6. **Mark resolved:** `markFindingsResolved(execution, context, resolvedFindingIds, normalizedResolvedIds)` – for each existing finding in context whose id is in resolved set, update issue comment (and PR review comment if any) via `replaceMarkerInBody` to set `resolved:true`; if PR comment, call `resolveReviewThread` when applicable.
7. **Publish:** `publishFindings(execution, context, toPublish, overflowCount?, overflowTitles?)` – for each finding: add or update **issue comment** (always); add or update **PR review comment** only when `finding.file` is in `prContext.prFiles` (using `pathToFirstDiffLine` when finding has no line). Each comment body is built with `buildCommentBody(finding, resolved)` and includes the **marker** `<!-- copilot-bugbot finding_id:"id" resolved:false -->`. Overflow: one extra issue comment summarizing excess findings.

**Key paths (detection):**

- `detect_potential_problems_use_case.ts` – orchestration
- `load_bugbot_context_use_case.ts` – issue/PR comments, markers, previousFindingsBlock, prContext
- `build_bugbot_prompt.ts` – prompt for plan agent (task 1: new findings, task 2: resolved ids)
- `schema.ts` – BUGBOT_RESPONSE_SCHEMA (findings, resolved_finding_ids)
- `marker.ts` – BUGBOT_MARKER_PREFIX, buildMarker, parseMarker, replaceMarkerInBody, extractTitleFromBody, buildCommentBody
- `publish_findings_use_case.ts` – add/update issue comment, create/update PR review comment
- `mark_findings_resolved_use_case.ts` – update comment body with resolved marker, resolve PR thread
- `severity.ts`, `file_ignore.ts`, `path_validation.ts`, `limit_comments.ts`, `deduplicate_findings.ts`

---

## 2. Marker format and context

**Marker:** Hidden HTML comment in every finding comment (issue and PR):

`<!-- copilot-bugbot finding_id:"<id>" resolved:true|false -->`

- **Parse:** `parseMarker(body)` returns `{ findingId, resolved }[]`. Used when loading context from issue comments and PR review comments.
- **Build:** `buildMarker(findingId, resolved)`. IDs are sanitized (`sanitizeFindingIdForMarker`) so they cannot break HTML (no `-->`, `<`, `>`, newlines, etc.).
- **Update:** `replaceMarkerInBody(body, findingId, newResolved)` – used when marking a finding as resolved (same comment, body updated with `resolved:true`).

**Context (`BugbotContext`):**

- `existingByFindingId[id]`: `{ issueCommentId?, prCommentId?, prNumber?, resolved }` – from parsing all issue + PR comments for markers.
- `issueComments`: raw list from API (for body when building previousFindingsBlock / unresolvedFindingsWithBody).
- `openPrNumbers`, `previousFindingsBlock`, `prContext` (prHeadSha, prFiles, pathToFirstDiffLine), `unresolvedFindingsWithBody`: `{ id, fullBody }[]` for findings that are not resolved (body truncated to MAX_FINDING_BODY_LENGTH when loading).

---

## 3. Fix intent and file-modifying actions (issue comment / PR review comment)

**Entry:** `IssueCommentUseCase` or `PullRequestReviewCommentUseCase` (after language check).

**Steps:**

1. **Intent:** `DetectBugbotFixIntentUseCase.invoke(param)`
- Guards: OpenCode configured, issue number set, comment body non-empty, branch (or branchOverride from `getHeadBranchForIssue` when commit.branch empty).
- `loadBugbotContext(param, { branchOverride })` β†’ unresolved findings.
- Build `UnresolvedFindingSummary[]` (id, title from `extractTitleFromBody`, description = fullBody.slice(0, 4000)).
- If PR review comment and `commentInReplyToId`: fetch parent comment body (`getPullRequestReviewCommentBody`), slice(0,1500).trim for prompt.
- `buildBugbotFixIntentPrompt(commentBody, unresolvedFindings, parentCommentBody?)` β†’ prompt asks: is_fix_request?, target_finding_ids?, is_do_request?
- `askAgent(OPENCODE_AGENT_PLAN, prompt, BUGBOT_FIX_INTENT_RESPONSE_SCHEMA)` β†’ `{ is_fix_request, target_finding_ids, is_do_request }`.
- Payload: `isFixRequest`, `isDoRequest`, `targetFindingIds` (filtered to valid unresolved ids), `context`, `branchOverride`.

2. **Permission:** `ProjectRepository.isActorAllowedToModifyFiles(owner, actor, token)`.
- If owner is Organization: `orgs.checkMembershipForUser` (204 = allowed).
- If owner is User: allowed only if `actor === owner`.

3. **Branch A – Bugbot autofix** (when `canRunBugbotAutofix(payload)` and `allowedToModifyFiles`):
- `BugbotAutofixUseCase.invoke({ execution, targetFindingIds, userComment, context, branchOverride })`
- Load context if not provided; filter targets to valid unresolved ids; `buildBugbotFixPrompt(...)` with repo, findings block (truncated fullBody per finding), user comment, verify commands; `copilotMessage(ai, prompt)` (build agent).
- If success: `runBugbotAutofixCommitAndPush(execution, { branchOverride, targetFindingIds })` – optional checkout if branchOverride, run verify commands (from `getBugbotFixVerifyCommands`, max 20), git add/commit/push (message `fix(#N): bugbot autofix - resolve ...`).
- If committed and context: `markFindingsResolved({ execution, context, resolvedFindingIds, normalizedResolvedIds })`.

4. **Branch B – Do user request** (when `!runAutofix && canRunDoUserRequest(payload)` and `allowedToModifyFiles`):
- `DoUserRequestUseCase.invoke({ execution, userComment, branchOverride })`
- `buildUserRequestPrompt(execution, userComment)` – repo context + sanitized user request; `copilotMessage(ai, prompt)`.
- If success: `runUserRequestCommitAndPush(execution, { branchOverride })` – same verify/checkout/add/commit/push with message `chore(#N): apply user request` or `chore: apply user request`.

5. **Think** (when no file-modifying action ran): `ThinkUseCase.invoke(param)` – answers the user (e.g. question).

**Key paths (fix/do):**

- `detect_bugbot_fix_intent_use_case.ts` – intent detection, branch resolution for issue_comment
- `build_bugbot_fix_intent_prompt.ts` – prompt for is_fix_request / is_do_request / target_finding_ids
- `bugbot_fix_intent_payload.ts` – getBugbotFixIntentPayload, canRunBugbotAutofix, canRunDoUserRequest
- `schema.ts` – BUGBOT_FIX_INTENT_RESPONSE_SCHEMA (is_fix_request, target_finding_ids, is_do_request)
- `bugbot_autofix_use_case.ts` – build prompt, copilotMessage (build agent)
- `build_bugbot_fix_prompt.ts` – fix prompt (findings block, verify commands, truncate finding body to MAX_FINDING_BODY_LENGTH)
- `bugbot_autofix_commit.ts` – runBugbotAutofixCommitAndPush, runUserRequestCommitAndPush (checkout, verify commands max 20, git config, add, commit, push)
- `user_request_use_case.ts` – DoUserRequestUseCase, buildUserRequestPrompt
- `mark_findings_resolved_use_case.ts` – update issue/PR comment with resolved marker
- `project_repository.ts` – isActorAllowedToModifyFiles

---

## 4. Configuration (inputs / Ai model)

- **bugbot-severity:** Minimum severity to publish (info, low, medium, high). Default low. `getBugbotMinSeverity()`, `normalizeMinSeverity`, `meetsMinSeverity`.
- **bugbot-comment-limit:** Max individual finding comments per issue/PR (overflow gets one summary). Default 20. `getBugbotCommentLimit()`, `applyCommentLimit`.
- **bugbot-fix-verify-commands:** Comma-separated commands run after autofix (and do user request) before commit. `getBugbotFixVerifyCommands()`, parsed with shell-quote; max 20 executed. Stored in `Ai` model; read in `github_action.ts` / `local_action.ts`.
- **ai-ignore-files:** Exclude paths from detection (and from reporting). Used in buildBugbotPrompt and in filtering findings.

---

## 5. Constants and types

- `BUGBOT_MARKER_PREFIX`: `'copilot-bugbot'`
- `BUGBOT_MAX_COMMENTS`: 20 (default limit)
- `MAX_FINDING_BODY_LENGTH`: 12000 (truncation when loading context and in build_bugbot_fix_prompt)
- `MAX_VERIFY_COMMANDS`: 20 (in bugbot_autofix_commit)
- Types: `BugbotContext`, `BugbotFinding` (id, title, description, file?, line?, severity?, suggestion?), `UnresolvedFindingSummary`, `BugbotFixIntentPayload`.

---

## 6. Sanitization and safety

- **User comment in prompts:** `sanitizeUserCommentForPrompt(raw)` – trim, escape backslashes, replace `"""`, truncate 4000 with no lone trailing backslash.
- **Finding body in prompts:** `truncateFindingBody(body, MAX_FINDING_BODY_LENGTH)` with suffix `[... truncated for length ...]` (used in load_bugbot_context and build_bugbot_fix_prompt).
- **Verify commands:** Parsed with shell-quote; no shell operators (;, |, etc.); max 20 run.
- **Path:** `isSafeFindingFilePath` (no null byte, no `..`, no absolute); PR review comment only if file in `prFiles`.
Loading