| name | Bugbot |
|---|---|
| description | Detailed technical reference for Bugbot (detection, markers, context, intent, autofix, do user request, permissions) |
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).
Entry: CommitUseCase (on push) calls DetectPotentialProblemsUseCase; or SingleActionUseCase when action is detect_potential_problems_action.
Steps:
- Guard: OpenCode must be configured;
issueNumber !== -1. - Load context:
loadBugbotContext(param)→ issue comments + PR review comments parsed for markers; buildsexistingByFindingId,issueComments,openPrNumbers,previousFindingsBlock,prContext,unresolvedFindingsWithBody. Branch isparam.commit.branch(oroptions.branchOverridewhen provided). PR context includesprHeadSha,prFiles,pathToFirstDiffLinefor the first open PR. - Build prompt:
buildBugbotPrompt(param, context)– repo context, head/base branch, issue number, optionalai-ignore-files, andpreviousFindingsBlock(task 2: which previous findings are now resolved). OpenCode is asked to compute the diff itself and returnfindings+resolved_finding_ids. - Call OpenCode:
askAgent(OPENCODE_AGENT_PLAN, prompt, BUGBOT_RESPONSE_SCHEMA). - Process response: Filter findings: safe path (
isSafeFindingFilePath), not inai-ignore-files(fileMatchesIgnorePatterns),meetsMinSeverity(min frombugbot-severity),deduplicateFindings. ApplyapplyCommentLimit(findings, bugbot-comment-limit)→toPublish,overflowCount,overflowTitles. - 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) viareplaceMarkerInBodyto setresolved:true; if PR comment, callresolveReviewThreadwhen applicable. - Publish:
publishFindings(execution, context, toPublish, overflowCount?, overflowTitles?)– for each finding: add or update issue comment (always); add or update PR review comment only whenfinding.fileis inprContext.prFiles(usingpathToFirstDiffLinewhen finding has no line). Each comment body is built withbuildCommentBody(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– orchestrationload_bugbot_context_use_case.ts– issue/PR comments, markers, previousFindingsBlock, prContextbuild_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, buildCommentBodypublish_findings_use_case.ts– add/update issue comment, create/update PR review commentmark_findings_resolved_use_case.ts– update comment body with resolved marker, resolve PR threadseverity.ts,file_ignore.ts,path_validation.ts,limit_comments.ts,deduplicate_findings.ts
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 withresolved: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).
Entry: IssueCommentUseCase or PullRequestReviewCommentUseCase (after language check).
Steps:
-
Intent:
DetectBugbotFixIntentUseCase.invoke(param)- Guards: OpenCode configured, issue number set, comment body non-empty, branch (or branchOverride from
getHeadBranchForIssuewhen commit.branch empty). loadBugbotContext(param, { branchOverride })→ unresolved findings.- Build
UnresolvedFindingSummary[](id, title fromextractTitleFromBody, 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.
- Guards: OpenCode configured, issue number set, comment body non-empty, branch (or branchOverride from
-
Permission:
ProjectRepository.isActorAllowedToModifyFiles(owner, actor, token).- If owner is Organization:
orgs.checkMembershipForUser(204 = allowed). - If owner is User: allowed only if
actor === owner.
- If owner is Organization:
-
Branch A – Bugbot autofix (when
canRunBugbotAutofix(payload)andallowedToModifyFiles):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 (fromgetBugbotFixVerifyCommands, max 20), git add/commit/push (messagefix(#N): bugbot autofix - resolve ...). - If committed and context:
markFindingsResolved({ execution, context, resolvedFindingIds, normalizedResolvedIds }).
-
Branch B – Do user request (when
!runAutofix && canRunDoUserRequest(payload)andallowedToModifyFiles):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 messagechore(#N): apply user requestorchore: apply user request.
-
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_commentbuild_bugbot_fix_intent_prompt.ts– prompt for is_fix_request / is_do_request / target_finding_idsbugbot_fix_intent_payload.ts– getBugbotFixIntentPayload, canRunBugbotAutofix, canRunDoUserRequestschema.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, buildUserRequestPromptmark_findings_resolved_use_case.ts– update issue/PR comment with resolved markerproject_repository.ts– isActorAllowedToModifyFiles
- 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 inAimodel; read ingithub_action.ts/local_action.ts. - ai-ignore-files: Exclude paths from detection (and from reporting). Used in buildBugbotPrompt and in filtering findings.
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.
- 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 inprFiles.