Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions _agent/docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
name: Architecture
description: Project architecture, entry points, and use case flows.
---

# Architecture & Key Paths

## Entry and main flow

1. **GitHub Action**: `src/actions/github_action.ts` reads inputs, builds `Execution`, calls `mainRun(execution)` from `common_action.ts`.
2. **CLI**: `src/actions/local_action.ts` same flow with CLI/config inputs.
3. **common_action.ts**: Sets up; calls `waitForPreviousRuns(execution)` (sequential workflow); then:
- **Single action** → `SingleActionUseCase`
- **Issue** → `IssueCommentUseCase` or `IssueUseCase`
- **Pull request** → `PullRequestReviewCommentUseCase` or `PullRequestUseCase`
- **Push** → `CommitUseCase`

## Key paths

| Area | Path | Purpose |
|------|------|--------|
| Action entry | `src/actions/github_action.ts` | Reads inputs, builds Execution |
| CLI entry | `src/cli.ts` → `local_action.ts` | Same flow, local inputs |
| 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, 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 |
| Config | `src/utils/constants.ts` | INPUT_KEYS, ACTIONS, defaults |
| Metadata | `action.yml` | Action inputs and defaults |

## Schematic overview of use case flows

Entry point: `mainRun(execution)` in `src/actions/common_action.ts`. After `execution.setup()` and optionally `waitForPreviousRuns`, the dispatch is:

```
mainRun
├── runnedByToken && singleAction → SingleActionUseCase (only if validSingleAction)
├── issueNumber === -1 → SingleActionUseCase (only if isSingleActionWithoutIssue) or skip
├── welcome → log boxen and continue
└── try:
├── isSingleAction → SingleActionUseCase
├── isIssue → issue.isIssueComment ? IssueCommentUseCase : IssueUseCase
├── isPullRequest → pullRequest.isPullRequestReviewComment ? PullRequestReviewCommentUseCase : PullRequestUseCase
├── isPush → CommitUseCase
└── else → core.setFailed
```

### 1. IssueUseCase (`on: issues`, not a comment)

**Step order:**

1. **CheckPermissionsUseCase** → if it fails (not allowed): CloseNotAllowedIssueUseCase and return.
2. **RemoveIssueBranchesUseCase** (only if `cleanIssueBranches`).
3. **AssignMemberToIssueUseCase**
4. **UpdateTitleUseCase**
5. **UpdateIssueTypeUseCase**
6. **LinkIssueProjectUseCase**
7. **CheckPriorityIssueSizeUseCase**
8. **PrepareBranchesUseCase** (if `isBranched`) **or** **RemoveIssueBranchesUseCase** (if not).
9. **RemoveNotNeededBranchesUseCase**
10. **DeployAddedUseCase** (deploy label)
11. **DeployedAddedUseCase** (deployed label)
12. If **issue.opened**:
- If not release and not question/help → **RecommendStepsUseCase**
- If question or help → **AnswerIssueHelpUseCase**

### 2. IssueCommentUseCase (`on: issue_comment`)

**Step order:**

1. **CheckIssueCommentLanguageUseCase** (translation)
2. **DetectBugbotFixIntentUseCase** → payload: `isFixRequest`, `isDoRequest`, `targetFindingIds`, `context`, `branchOverride`
3. **ProjectRepository.isActorAllowedToModifyFiles(owner, actor, token)** (permission to modify files)
4. Branch A – **if runAutofix && allowed**:
- **BugbotAutofixUseCase** → **runBugbotAutofixCommitAndPush** → if committed: **markFindingsResolved**
5. Branch B – **if !runAutofix && canRunDoUserRequest && allowed**:
- **DoUserRequestUseCase** → **runUserRequestCommitAndPush**
6. **If no file-modifying action ran** → **ThinkUseCase**

### 3. PullRequestReviewCommentUseCase (`on: pull_request_review_comment`)

Same flow as **IssueCommentUseCase**, with:

- CheckIssueCommentLanguageUseCase → **CheckPullRequestCommentLanguageUseCase**
- User comment: `param.pullRequest.commentBody`
- DetectBugbotFixIntentUseCase may use **parent comment** (commentInReplyToId) in the prompt.

### 4. PullRequestUseCase (`on: pull_request`, not a review comment)

**Branches by PR state:**

- **pullRequest.isOpened**:
1. UpdateTitleUseCase
2. AssignMemberToIssueUseCase
3. AssignReviewersToIssueUseCase
4. LinkPullRequestProjectUseCase
5. LinkPullRequestIssueUseCase
6. SyncSizeAndProgressLabelsFromIssueToPrUseCase
7. CheckPriorityPullRequestSizeUseCase
8. If AI PR description: **UpdatePullRequestDescriptionUseCase**

- **pullRequest.isSynchronize** (new pushes):
- If AI PR description: **UpdatePullRequestDescriptionUseCase**

- **pullRequest.isClosed && isMerged**:
- **CloseIssueAfterMergingUseCase**

### 5. CommitUseCase (`on: push`)

**Precondition:** `param.commit.commits.length > 0` (if 0, return with no steps).

**Order:**

1. **NotifyNewCommitOnIssueUseCase**
2. **CheckChangesIssueSizeUseCase**
3. **CheckProgressUseCase** (OpenCode: progress + size labels on issue and PRs)
4. **DetectPotentialProblemsUseCase** (Bugbot: detection, publish to issue/PR, resolved markers)

### 6. SingleActionUseCase

Invoked when:
- `runnedByToken && isSingleAction && validSingleAction`, or
- `issueNumber === -1 && isSingleAction && isSingleActionWithoutIssue`, or
- `isSingleAction` in the main try block.

**Dispatch by action (one per run):**

| Action | Use case |
|--------|----------|
| `deployed_action` | DeployedActionUseCase |
| `publish_github_action` | PublishGithubActionUseCase |
| `create_release` | CreateReleaseUseCase |
| `create_tag` | CreateTagUseCase |
| `think_action` | ThinkUseCase |
| `initial_setup` | InitialSetupUseCase |
| `check_progress_action` | CheckProgressUseCase |
| `detect_potential_problems_action` | DetectPotentialProblemsUseCase |
| `recommend_steps_action` | RecommendStepsUseCase |
64 changes: 64 additions & 0 deletions _agent/docs/bugbot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
name: Bugbot
description: Detailed technical reference for Bugbot (detection, markers, context, intent, autofix, do user request, permissions).
---

# 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.

## 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`).

## 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).
33 changes: 33 additions & 0 deletions _agent/docs/code-conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: CodeConventions
description: Coding standards, logging, and adding new inputs.
---

# Code Conventions

## Logging and constants

- Use **logger**: `logInfo`, `logError`, `logDebugInfo` from `src/utils/logger`. No ad-hoc `console.log`.
- Use **constants**: `INPUT_KEYS` and `ACTIONS` from `src/utils/constants.ts` for input names and action names. No hardcoded strings for these.

## Adding a new action input

1. **`action.yml`**: Add the input with `description` and `default` (if any).
2. **`src/utils/constants.ts`**: Add the key to `INPUT_KEYS` (e.g. `NEW_INPUT: 'new-input'`).
3. **`src/actions/github_action.ts`**: Read the input (e.g. `core.getInput(INPUT_KEYS.NEW_INPUT)`) and pass it into the object used to build `Execution`.
4. **Optional**: If the CLI must support it, add to `local_action.ts` and the corresponding CLI option.

## Where to change content/descriptions

- **PR description** (template filling, AI content): `src/manager/description/` (configuration_handler, content interfaces).
- **Hotfix/release changelog** (markdown extraction, formatting): `src/manager/description/markdown_content_hotfix_handler.ts`.

## Build and bundles

- The project uses **`@vercel/ncc`** to bundle the action and CLI. Keep imports and dependencies compatible with ncc (no dynamic requires that ncc cannot see).
- **Do not** edit or rely on `build/`; it is generated. Run tests and lint only on `src/`.

## Style and lint

- Prefer TypeScript; avoid `any` (lint rule: no-explicit-any).
- Run `npm run lint` before committing; use `npm run lint:fix` when possible.
32 changes: 32 additions & 0 deletions _agent/docs/commit-messages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: CommitMessages
description: Specific nomenclature and branch-prefix requirements for commits.
---

# Commit messages

The commit message must use the **current branch name as prefix**, with any `/` replaced by `-`.

## Format

```
<normalized-branch>: <short description>

[optional body]
```

- **Prefix**: current branch name, replacing `/` with `-`. Example: branch `feature/292-github-action-rename` → prefix `feature-292-github-action-rename`.
- **Description**: imperative, lowercase, no trailing period. You may optionally include conventional type (`feat`, `fix`, `docs`, etc.) in the description.

## Examples

Branch `feature-292-github-action-rename`:

- `feature-292-github-action-rename: add concurrency and permissions to ci_check`
- `feature-292-github-action-rename: fix docs callouts (Info instead of Note/Tip)`

Branch `fix/123-docs-anchor` (normalized to `fix-123-docs-anchor`):

- `fix-123-docs-anchor: remove invalid MDX heading anchors`

When suggesting or writing a commit message, use the current branch with `/` replaced by `-` as the prefix. If you don't know the branch, tell the user to use their branch name as the prefix.
35 changes: 35 additions & 0 deletions _agent/docs/project-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: ProjectContext
description: High-level overview, common commands, and ignore paths.
---

# Copilot – Project Context

## Quick read (for fast understanding)

- **What it is**: GitHub Action + CLI that automates Git-Flow: creates branches from issue labels, links issues/PRs to projects, tracks commits; AI via OpenCode (progress, errors, PR descriptions).
- **Entry points**: GitHub Action → `src/actions/github_action.ts`; CLI → `src/cli.ts`. Shared logic in `src/actions/common_action.ts` (single actions vs issue/PR/push).
- **Do**: Use Node 20, run from repo root; edit only `src/`; use `INPUT_KEYS`/`ACTIONS` and `logInfo`/`logError`/`logDebugInfo`. When adding inputs: update `action.yml`, `constants.ts` (INPUT_KEYS), and `github_action.ts` (and optionally `local_action.ts`).
- **Don’t**: Edit or depend on `build/` (generated by `ncc`); run tests/lint on `build/`.

## Commands (repo root)

```bash
nvm use 20
npm install
npm run build
npm test
npm run test:watch
npm run test:coverage
npm run lint
npm run lint:fix
```

- **Build**: `npm run build` → bundles `github_action.ts` and `cli.ts` into `build/`.
- **Tests**: Jest; `npm run test:watch` / `npm run test:coverage` as needed.
- **Lint**: ESLint + typescript-eslint on `src/`; `npm run lint:fix` to auto-fix.

## What to ignore

- **`build/`** – Generated output; do not edit or run tests/lint against it.
- **`.agent-sessions/`** – Session data; ignore unless debugging.
Loading