# Project export: AI Radar

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: OpenAI Build Week
- Tagline: An AI-powered VS Code extension that helps developers understand code changes, active pull requests, and engineering risks before writing code.
- Devpost: https://devpost.com/software/webtest-ai
- GitHub: https://github.com/AbyvargheseMandapathel/AI-Radar
- Video: https://www.youtube.com/embed/C-HnLTJzCec?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — AbyvargheseMandapathel (8 commits)

## Devpost submission (written by the team)

### Inspiration

Modern software teams work on large codebases with multiple developers contributing simultaneously. While implementing a feature, developers often don't realize that someone else has already modified the same file or that an active pull request is changing the same area. These issues are usually discovered only during code review or merge, resulting in merge conflicts, duplicated work, and unnecessary debugging. We wanted to solve this problem by giving developers engineering awareness before they start writing code. What It Does AI Radar is a VS Code extension that analyzes the currently opened file and provides engineering context in a single view. It helps developers understand: Recent file changes Why the file changed Related Pull Requests Active contributors Affected engineering areas Risk level Recommended tests Suggested next actions Instead of searching through Git history, GitHub, and documentation, developers get all the relevant information directly inside VS Code before making changes. How We Built It The extension is built using the VS Code Extension API and TypeScript. It combines multiple sources of engineering information: Local Git history Git Blame Git Status Repository analysis GitHub REST API (optional) AI-powered engineering recommendations The extension analyzes the active file, collects engineering signals, calculates a risk level, and presents everything through a custom VS Code WebView. Challenges We Faced The biggest challenge was bringing together information from multiple sources into a single, meaningful engineering view. Some of the challenges included: - Parsing Git history efficiently Github Ratelimits Balancing useful information without overwhelming the developer was another major challenge. What We Learned Throughout this project we gained experience with: VS Code Extension Development Git internals and repository analysis GitHub REST APIs Engineering workflow automation Building developer productivity tools Designing AI-assisted developer experiences Most importantly, we learned that preventing problems early is often more valuable than fixing them later. Future Plans We plan to extend AI Engineering Radar with: AI-generated engineering summaries Cross-file dependency analysis Database and API impact detection Branch conflict prediction Team collaboration insights Continuous background monitoring Marketplace release for VS Code Our vision is to make AI Engineering Radar an intelligent engineering companion that helps developers understand their codebase before they write code, reducing merge conflicts and improving collaboration across large development teams.

## README (from the GitHub repository)

# AI Engineering Radar

AI Engineering Radar is a VS Code extension that gives developers engineering context before they start implementing. Instead of waiting for conflicts, regressions, or review comments, it analyzes the active file and surfaces recent changes, relevant pull requests, active contributors, affected areas, recommended tests, risk signals, and next actions.

The original project began as **AI Merge Engineer**, a merge-conflict assistant. That foundation is still valuable and remains available, but the product has pivoted toward a broader and more differentiated workflow:

> Help developers understand what they need to know before writing code.

## Hackathon Pitch

AI Engineering Radar is a lightweight AI staff-engineer companion inside VS Code. A developer selects a tracked source file and runs **AI Radar: Analyze Current File**. Radar combines local Git history, contributors, working-tree status, and optional GitHub pull-request context into a focused engineering brief: what changed, why it changed, where the risk is, and what to review or test next.

The goal is simple: make the relevant context visible before the code changes.

## Built with Codex & GPT-5.6

This hackathon prototype was developed with **Codex, powered by GPT-5.6**, as an engineering collaborator. Codex was used to iterate on the extension's TypeScript implementation, shape the engineering-context workflow, refine prompts and UI copy, and help validate the project through its compile, lint, and test commands.

The product also integrates with the **Codex CLI** at runtime. When configured, the Radar Agent sends a bounded, read-only prompt containing the current file's Git, pull-request, contributor, risk, and test context. Codex then returns practical follow-up guidance—such as what to review, which tests to run, or how a pull-request file change relates to the active file. The same configurable CLI integration supports the legacy merge-conflict proposal flow.

This separation is intentional: local Git and GitHub signals provide the evidence; Codex/GPT-5.6 turns that evidence into concise, developer-specific guidance. The extension never requires Codex for its deterministic radar analysis, and the CLI command, arguments, and timeout remain configurable in VS Code settings.

## Judge Quick Start

The intended hackathon experience uses Codex. GitHub authentication is **not** required: the demo works with the local Git history of any public repository.

1. Install the packaged extension. In VS Code, run **Extensions: Install from VSIX...** and select `ai-engineering-radar-1.0.5.vsix` from this project. Reload VS Code when prompted.
2. Install and connect the Codex CLI in a terminal:

   ```powershell
   npm.cmd install -g @openai/codex
   codex login
   codex --version
   ```

   The extension uses `codex` by default (or `codex.cmd` on Windows). No API key needs to be entered in the extension.
3. Open any local Git repository you want Radar to analyze—no GitHub sign-in is needed. This can be a project you already have on your machine; cloning a public repository is simply an easy way to get realistic Git history for the demo. For example:

   ```powershell
   git clone https://github.com/microsoft/vscode-extension-samples.git
   code .\vscode-extension-samples
   ```

4. Open a tracked source file, then run **AI Radar: Analyze Current File** from the Command Palette.
5. In the Radar panel, use **Chat With Radar Agent** and ask, for example: *What should I check before changing this file?* The extension passes the local engineering context to Codex and displays its review guidance.

For the core demo, do not use **AI Radar: Connect GitHub**. That optional sign-in enriches GitHub API capacity but is not needed for local Git analysis or Codex-powered Radar Agent guidance.

## Product Vision

AI Engineering Radar acts like a lightweight AI staff engineer inside VS Code. When a developer opens a file, the extension should help answer:

- What changed recently?
- Which pull requests are relevant?
- Who has been working in this area?
- Which APIs, services, or database areas may be affected?
- Which tests should be run?
- Which files or areas look high risk?
- What should the developer read before making changes?

## Current Experience

Run:

```txt
AI Radar: Analyze Current File
```

The extension opens an **AI Engineering Radar** panel with:

- Recent Changes
- Why This Changed
- Open Pull Requests
- Active Contributors
- Affected Areas
- Recommended Tests
- Risk Signals
- Recommended Actions
- Chat With Radar Agent
- Diagnostics

The panel also includes a **Connect GitHub** button. It uses GitHub's OAuth device flow, stores the resulting token only in VS Code Secret Storage, enables GitHub context for the workspace, and provides a **Refresh Radar** action after connection.

The status bar also exposes:

```txt
AI Radar
```

## Example Output

For a file such as `payment.service.ts`, the radar may show:

```txt
Engineering Context

Recent Changes
- Payment API updated
- Billing service refactored
- Tax calculation changed

Open Pull Requests
- #241 Stripe Subscription Support
- #245 Payment Validation Improvements

Active Contributors
- Alice
- John

Risk Level
HIGH

Recommended Actions
- Review recent commits touching this file.
- Review open pull requests on the current branch.
- Check impact across Payments and billing, API and service boundaries.
- Run billing/payment test suite.
```

## Implemented Features

- Analyzes the active file in a Git repository.
- Reads recent file history with Git.
- Maps recent file commits to GitHub pull requests when available.
- Shows PR title/body context and file-level additions, deletions, status, and patch excerpts.
- Reads active contributors from `git blame`.
- Reads working tree changes from `git status`.
- Detects affected engineering areas from file paths and changed files.
- Recommends test areas from project context and file path signals.
- Calculates a simple risk level: `LOW`, `MEDIUM`, or `HIGH`.
- Shows results in a dedicated VS Code webview.
- Shows automatic alerts when the opened or edited file appears risky.
- Provides an in-panel Radar Agent chat for follow-up questions and suggested next steps.
- Provides on-demand AI analysis of an individual changed file in a relevant pull request.
- Supports optional GitHub OAuth device flow.
- Uses GitHub REST API context for repository and pull request awareness.
- Preserves the original merge-conflict assistant:
  - conflict marker detection
  - CodeLens actions
  - conflict explanation
  - Codex CLI merge proposal
  - proposal review UI
  - safe apply after approval

## Not Yet Implemented

- AI-generated radar summaries.
- Cross-file dependency graph analysis.
- API schema and database migration diffing.
- Pull request relevance beyond branch matching.
- Continuous background radar updates.
- Merge history and analytics.
- Marketplace publishing and distribution setup.

## Requirements

- VS Code `1.92.0` or newer
- Node.js
- npm
- Git
- Codex CLI, signed in with `codex login`, for the intended Radar Agent experience
- Optional: GitHub OAuth app for GitHub context

Install dependencies:

```powershell
npm.cmd install
```

Compile:

```powershell
npm.cmd run compile
```

Run checks:

```powershell
npm.cmd run check
npm.cmd test
```

## Running The Extension

Open this extension project:

```powershell
cd C:\Users\ABY\Desktop\project\hackathon
code .
```

Build:

```powershell
npm.cmd run compile
```

Launch the Extension Development Host:

```txt
F5
```

In the Extension Development Host:

1. Open a Git repository.
2. Open any tracked source file.
3. Run:

```txt
AI Radar: Analyze Current File
```

The radar panel should open beside the editor.

Automatic alerts are enabled by default. When you open or edit a file that crosses the configured risk threshold, VS Code shows a warning with an **Open Radar** action.

Example alert:

```txt
You are editing src/payment/payment.ser

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 39 recognized source files, 182 KB.
- TypeScript (language) — detected in the code
- CSS (language) — claimed on Devpost, not found in the code
- HTML (language) — claimed on Devpost, not found in the code
- JavaScript (language) — claimed on Devpost, not found in the code
- Node.js (technology) — claimed on Devpost, not found in the code
- OpenAI (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (54 of 54)

```
.gitignore
.vscodeignore
ai-engineering-radar-1.0.5.vsix
debug.log
eslint.config.mjs
Extension/ai-engineering-radar-1.0.5.vsix
LICENSE
package.json
README.md
src/ai/AIService.ts
src/ai/MergeResultValidator.ts
src/ai/PromptBuilder.ts
src/ai/RadarChatService.ts
src/commands/AnalyzeCurrentFileCommand.ts
src/commands/ExplainConflictCommand.ts
src/commands/GitHubSignInCommand.ts
src/commands/GitHubSignOutCommand.ts
src/commands/ResolveConflictCommand.ts
src/extension.ts
src/git/GitCommandRunner.ts
src/git/GitContextService.ts
src/git/GitHubAuthService.ts
src/git/GitHubClient.ts
src/git/GitHubContextService.ts
src/git/GitHubRepositoryResolver.ts
src/git/GitRepositoryService.ts
src/models/Conflict.ts
src/models/ConflictCommandArgs.ts
src/models/EngineeringRadar.ts
src/models/GitContext.ts
src/models/MergeResult.ts
src/models/PromptPayload.ts
src/models/RepositoryContext.ts
src/models/VerificationResult.ts
src/parser/ConflictDetector.ts
src/parser/ConflictParser.ts
src/radar/EngineeringRadarService.ts
src/radar/RadarAlertService.ts
src/services/ApplyMergeService.ts
src/services/Logger.ts
src/services/RepositoryContextService.ts
src/services/WorkspaceService.ts
src/ui/ConflictCodeLensProvider.ts
src/ui/DiffWebviewService.ts
src/ui/RadarWebviewService.ts
src/ui/StatusBarService.ts
src/verification/VerificationService.ts
test/aiService.test.cjs
test/conflictParser.test.cjs
test/engineeringRadarService.test.cjs
test/gitHubRepositoryResolver.test.cjs
test/promptBuilder.test.cjs
test/verificationService.test.cjs
tsconfig.json
```

### Dependencies

- package.json: @types/node@^22.13.1, @types/vscode@^1.92.0, @typescript-eslint/eslint-plugin@^8.20.0, @typescript-eslint/parser@^8.20.0, eslint@^9.18.0, rimraf@^6.0.1, typescript@^5.7.3

### Recent commits (newest first)

- updates
- Readme added
- Readme added
- Readme added
- feat(radar): add file-level AI analysis for relevant pull request changes
- updates
- First commit - fixes
- First commit

## Key source files (fetched from GitHub, selected and truncated for size)

### package.json

```
{
  "name": "ai-engineering-radar",
  "displayName": "AI Engineering Radar",
  "description": "Surfaces engineering context, risk, contributors, pull requests, and recommended actions before implementation begins.",
  "version": "1.0.5",
  "publisher": "abyvargheese",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/AbyvargheeseMandapathil/OpenAI-Hackathon.git"
  },
  "bugs": {
    "url": "https://github.com/AbyvargheeseMandapathil/OpenAI-Hackathon/issues"
  },
  "homepage": "https://github.com/AbyvargheeseMandapathil/OpenAI-Hackathon#readme",
  "private": true,
  "engines": {
    "vscode": "^1.92.0"
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [
    "onStartupFinished",
    "onCommand:aiRadar.analyzeCurrentFile",
    "onCommand:aiRadar.githubSignIn",
    "onCommand:aiMerge.resolveConflict",
    "onCommand:aiMerge.explainConflict",
    "onCommand:aiMerge.githubSignIn",
    "onCommand:aiMerge.githubSignOut"
  ],
  "main": "./dist/extension.js",
  "contributes": {
    "commands": [
      {
        "command": "aiRadar.analyzeCurrentFile",
        "title": "AI Radar: Analyze Current File",
        "category": "AI Radar"
      },
      {
        "command": "aiRadar.githubSignIn",
        "title": "AI Radar: Connect GitHub",
        "category": "AI Radar"
      },
      {
        "command": "aiMerge.resolveConflict",
        "title": "AI Merge: Resolve Conflict",
        "category": "AI Merge"
      },
      {
        "command": "aiMerge.explainConflict",
        "title": "AI Merge: Explain Conflict",
        "category": "AI Merge"
      },
      {
        "command": "aiMerge.githubSignIn",
        "title": "AI Merge: GitHub Sign In",
        "category": "AI Merge"
      },
      {
        "command": "aiMerge.githubSignOut",
        "title": "AI Merge: GitHub Sign Out",
        "category": "AI Merge"
      }
    ],
    "configuration": {
      "title": "AI Engineering Radar",
      "properties": {
        "aiMerge.aiCommand": {
          "type": "string",
          "default": "codex",
          "description": "Local AI command used for Radar Agent guidance and legacy merge proposals."
        },
        "aiMerge.aiArgs": {
          "type": "array",
          "default": [
            "exec",
            "--sandbox",
            "read-only",
            "--skip-git-repo-check",
            "-"
          ],
          "items": {
            "type": "string"
          },
          "description": "Arguments passed to the local AI command. Use '-' when the command should read the prompt from stdin."
        },
        "aiMerge.aiTimeoutMs": {
          "type": "number",
          "default": 120000,
          "minimum": 1000,
          "description": "Maximum time to wait for the AI command."
        },
        "aiMerge.github.enabled": {
          "type": "boolean",
          "default": false,
          "description": "Enable GitHub REST API context collection."
        },
        "aiMerge.github.webBaseUrl": {
          "type": "string",
          "default": "https://github.com",
          "description": "GitHub web base URL. Use your GitHub Enterprise web URL when needed."
        },
        "aiMerge.github.apiBaseUrl": {
          "type": "string",
          "default": "https://api.github.com",
          "description": "GitHub REST API base URL. For GitHub Enterprise this is usually https://HOST/api/v3."
        },
        "aiMerge.github.token": {
          "type": "string",
          "default": "",
          "description": "GitHub personal access token fallback. OAuth sign-in is preferred when configured."
        },
        "aiMerge.github.oauthClientId": {
          "type": "string",
          "default": "Ov23limt6GDCRy42umgV",
          "description": "GitHub OAuth app Client ID used by the device flow. Override only for GitHub Enterprise or your own OAuth app."
        },
        "aiMerge.github.oauthScopes": {
          "type": "array",
          "default": [
            "repo",
            "read:user"
          ],
          "items": {
            "type": "string"
          },
          "description": "GitHub OAuth scopes requested during sign-in. Use repo for private repositories."
        },
        "aiMerge.github.repository": {
          "type": "string",
          "default": "",
          "description": "Optional GitHub repository override in owner/name form. By default, AI Engineering Radar infers it from the origin remote."
        },
        "aiMerge.github.pullRequestNumber": {
          "type": "number",
          "default": 0,
          "minimum": 0,
          "description": "Optional GitHub pull request number to fetch. Set 0 to infer from current branch when possible."
        },
        "aiRadar.alerts.enabled": {
          "type": "boolean",
          "default": true,
          "description": "Show automatic alerts when the active file appears risky or overlaps active engineering work."
        },
        "aiRadar.pullRequests.useGitHubApi": {
          "type": "boolean",
          "default": false,
          "description": "Use the GitHub API for live open-PR metadata. Disabled by default: Radar reads every PR reference available in local Git history without API calls."
        },
        "aiRadar.alerts.riskThreshold": {
          "type": "string",
          "default": "MEDIUM",
          "enum": [
            "LOW",
            "MEDIUM",
            "HIGH"
          ],
          "description": "Minimum radar risk level required before showing an automatic alert."
        },
        "aiRadar.alerts.debounceMs": {
          "type": "number",
          "default": 3000,
          "minimum": 500,
          "description": "Delay before analyzing the active file after edits."
        }
      }
    }
  },
  "scripts": {
    "clean": "rimraf dist",
    "compile": "tsc -p ./",
    "watch": "tsc -watch -p ./",
    "lint": "eslint src",
    "check": "npm run compile && npm run lint",
    "test": "npm run compile && node --test t
[truncated — 486 more characters]
```

### src/extension.ts

```typescript
import * as vscode from "vscode";

import { AnalyzeCurrentFileCommand } from "./commands/AnalyzeCurrentFileCommand";
import { ExplainConflictCommand } from "./commands/ExplainConflictCommand";
import { GitHubSignInCommand } from "./commands/GitHubSignInCommand";
import { GitHubSignOutCommand } from "./commands/GitHubSignOutCommand";
import { ResolveConflictCommand } from "./commands/ResolveConflictCommand";
import { AIService } from "./ai/AIService";
import { PromptBuilder } from "./ai/PromptBuilder";
import { RadarChatService } from "./ai/RadarChatService";
import { GitContextService } from "./git/GitContextService";
import { GitHubAuthService } from "./git/GitHubAuthService";
import { GitHubContextService } from "./git/GitHubContextService";
import { ConflictCodeLensProvider } from "./ui/ConflictCodeLensProvider";
import { DiffWebviewService } from "./ui/DiffWebviewService";
import { ConflictDetector } from "./parser/ConflictDetector";
import { GitRepositoryService } from "./git/GitRepositoryService";
import { Logger } from "./services/Logger";
import { ApplyMergeService } from "./services/ApplyMergeService";
import { RepositoryContextService } from "./services/RepositoryContextService";
import { EngineeringRadarService } from "./radar/EngineeringRadarService";
import { RadarAlertService } from "./radar/RadarAlertService";
import { RadarWebviewService } from "./ui/RadarWebviewService";
import { StatusBarService } from "./ui/StatusBarService";
import { WorkspaceService } from "./services/WorkspaceService";

let logger: Logger | undefined;

export async function activate(context: vscode.ExtensionContext): Promise<void> {
  logger = new Logger(vscode.window.createOutputChannel("AI Engineering Radar"));
  context.subscriptions.push(logger);

  logger.info("Activating AI Engineering Radar.");

  const workspaceService = new WorkspaceService(logger);
  const gitRepositoryService = new GitRepositoryService(logger);
  const gitHubAuthService = new GitHubAuthService(context, logger);
  const gitHubContextService = new GitHubContextService(logger, gitHubAuthService);
  const gitContextService = new GitContextService(logger, gitRepositoryService, gitHubContextService);
  const repositoryContextService = new RepositoryContextService(logger);
  const engineeringRadarService = new EngineeringRadarService(
    logger,
    gitRepositoryService,
    repositoryContextService,
    gitHubContextService,
    vscode.workspace.getConfiguration("aiRadar").get<boolean>("pullRequests.useGitHubApi", false)
  );
  const radarChatService = new RadarChatService(logger);
  const radarWebviewService = new RadarWebviewService(logger, radarChatService, gitHubAuthService);
  const radarAlertService = new RadarAlertService(
    logger,
    workspaceService,
    engineeringRadarService,
    radarWebviewService
  );
  const promptBuilder = new PromptBuilder();
  const aiService = new AIService(logger);
  const applyMergeService = new ApplyMergeService(logger);
  const diffWebviewService = new DiffWebviewService(logger, applyMergeService);
  const conflictDetector = new ConflictDetector(logger);
  const statusBarService = new StatusBarService();
  context.subscriptions.push(statusBarService, radarAlertService);

  const resolveConflictCommand = new ResolveConflictCommand(
    logger,
    workspaceService,
    gitRepositoryService,
    conflictDetector,
    gitContextService,
    repositoryContextService,
    promptBuilder,
    aiService,
    diffWebviewService
  );
  const explainConflictCommand = new ExplainConflictCommand(logger, conflictDetector);
  const analyzeCurrentFileCommand = new AnalyzeCurrentFileCommand(
    logger,
    workspaceService,
    engineeringRadarService,
    radarWebviewService
  );
  const gitHubSignInCommand = new GitHubSignInCommand(logger, gitHubAuthService);
  const gitHubSignOutCommand = new GitHubSignOutCommand(logger, gitHubAuthService);
  const conflictCodeLensProvider = new ConflictCodeLensProvider(conflictDetector);

  context.subscriptions.push(
    vscode.commands.registerCommand(
      AnalyzeCurrentFileCommand.commandId,
      async () => analyzeCurrentFileCommand.execute()
    ),
    vscode.commands.registerCommand(
      ResolveConflictCommand.commandId,
      async (args?: unknown) => resolveConflictCommand.execute(args)
    ),
    vscode.commands.registerCommand(
      ExplainConflictCommand.commandId,
      async (args?: unknown) => explainConflictCommand.execute(args)
    ),
    vscode.commands.registerCommand(
      GitHubSignInCommand.commandId,
      async () => gitHubSignInCommand.execute()
    ),
    vscode.commands.registerCommand(
      "aiRadar.githubSignIn",
      async () => gitHubSignInCommand.execute()
    ),
    vscode.commands.registerCommand(
      GitHubSignOutCommand.commandId,
      async () => gitHubSignOutCommand.execute()
    ),
    vscode.languages.registerCodeLensProvider(
      { scheme: "file" },
      conflictCodeLensProvider
    )
  );

  statusBarService.show();
  radarAlertService.start();

  await logWorkspaceState(workspaceService, gitRepositoryService);

  logger.info("AI Engineering Radar initialized.");
}

export function deactivate(): void {
  logger?.info("AI Engineering Radar deactivated.");
}

async function logWorkspaceState(
  workspaceService: WorkspaceService,
  gitRepositoryService: GitRepositoryService
): Promise<void> {
  const workspaceFolder = workspaceService.getPrimaryWorkspaceFolder();

  if (!workspaceFolder) {
    logger?.warn("No workspace folder is open.");
    return;
  }

  logger?.info(`Workspace detected: ${workspaceFolder.uri.fsPath}`);

  const repository = await gitRepositoryService.detectRepository(workspaceFolder.uri.fsPath);
  if (repository.ok) {
    logger?.info(`Git repository detected: ${repository.rootPath}`);
    return;
  }

  logger?.warn(`Git repository not detected: ${repository.error}`);
}

```

### src/models/ConflictCommandArgs.ts

```typescript
export interface ConflictCommandArgs {
  documentUri: string;
  conflictId: string;
}

```

### src/models/MergeResult.ts

```typescript
export interface MergeResult {
  mergedCode: string;
  explanation: string;
  confidence: number;
  warnings: string[];
}

```

### src/models/Conflict.ts

```typescript
export interface Conflict {
  id: string;
  startLine: number;
  endLine: number;
  currentCode: string;
  incomingCode: string;
  branch: string;
  currentLabel: string;
}

```

### src/models/RepositoryContext.ts

```typescript
export interface RepositoryContextFile {
  path: string;
  content: string;
}

export interface RepositoryContext {
  repositoryRoot: string;
  files: RepositoryContextFile[];
  languages: string[];
  frameworks: string[];
  formatters: string[];
  linters: string[];
  testFrameworks: string[];
  diagnostics: string[];
}

```

### src/models/VerificationResult.ts

```typescript
export type VerificationStatus = "passed" | "failed" | "skipped";

export interface VerificationStepResult {
  name: "formatting" | "lint" | "build" | "tests";
  status: VerificationStatus;
  command?: string;
  output: string;
  durationMs: number;
}

export interface VerificationResult {
  formatting: VerificationStepResult;
  lint: VerificationStepResult;
  build: VerificationStepResult;
  tests: VerificationStepResult;
  errors: string[];
  durationMs: number;
}

```

### src/commands/GitHubSignOutCommand.ts

```typescript
import * as vscode from "vscode";

import type { GitHubAuthService } from "../git/GitHubAuthService";
import type { Logger } from "../services/Logger";

export class GitHubSignOutCommand {
  public static readonly commandId = "aiMerge.githubSignOut";

  public constructor(
    private readonly logger: Logger,
    private readonly authService: GitHubAuthService
  ) {}

  public async execute(): Promise<void> {
    await this.authService.signOut();
    this.logger.info("GitHub sign-out completed.");
    await vscode.window.showInformationMessage("GitHub signed out.");
  }
}

```

### src/services/WorkspaceService.ts

```typescript
import * as vscode from "vscode";

import type { Logger } from "./Logger";

export class WorkspaceService {
  public constructor(private readonly logger: Logger) {}

  public getPrimaryWorkspaceFolder(): vscode.WorkspaceFolder | undefined {
    const workspaceFolders = vscode.workspace.workspaceFolders;

    if (!workspaceFolders || workspaceFolders.length === 0) {
      return undefined;
    }

    if (workspaceFolders.length > 1) {
      this.logger.info(
        `Multiple workspace folders detected. Using ${workspaceFolders[0]?.uri.fsPath ?? "the first folder"}.`
      );
    }

    return workspaceFolders[0];
  }
}

```

### src/ui/StatusBarService.ts

```typescript
import * as vscode from "vscode";

import { AnalyzeCurrentFileCommand } from "../commands/AnalyzeCurrentFileCommand";

export class StatusBarService implements vscode.Disposable {
  private readonly item: vscode.StatusBarItem;

  public constructor() {
    this.item = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100);
    this.item.command = AnalyzeCurrentFileCommand.commandId;
    this.item.text = "$(radar) AI Radar";
    this.item.tooltip = "Analyze engineering context for the active file";
  }

  public show(): void {
    this.item.show();
  }

  public dispose(): void {
    this.item.dispose();
  }
}

```

[29 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]