Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
110 changes: 77 additions & 33 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,79 +1,123 @@
# AGENTS.md - Development Guidelines for VSCode Extension
# AGENTS.md - Development Guidelines for SealCode VSCode Extension

## Overview
SealCode is a VSCode extension for smart code review management. This document provides guidelines for agents working on this codebase.

## Package Management
- Package manager: **pnpm**
- Use `nr` alias (preferred) or `pnpm` for running scripts
- No Prettier - ESLint handles all formatting
- **Package manager**: pnpm
- **Preferred alias**: Use `nr` instead of `pnpm` for running scripts
- **No Prettier**: ESLint handles all formatting automatically

## Essential Commands

### Development
- `nr build` - Build the extension with tsdown
- `nr dev` - Watch mode with sourcemaps
- `nr build` - Build the extension with tsdown (outputs to `./dist`)
- `nr dev` - Watch mode with sourcemaps for development
- `nr update` - Regenerate VSCode metadata from package.json

### Quality Assurance
- `nr lint` - Run ESLint (auto-fixes on save in VSCode)
- `nr typecheck` - Run TypeScript compiler with noEmit
- `nr test` - Run all tests with vitest
- `nr test run <path>` - Run a specific test file (e.g., `nr test run test/storage.test.ts`)
- `nr test run <path>` - Run a specific test file (e.g., `nr test run test/unit/aiTools.test.ts`)
- `nr test watch` - Run tests in watch mode

**CRITICAL**: After any JS/TS changes, always run: `nr lint` && `nr typecheck`

## Code Style Guidelines
**Critical**: After any JS/TS changes, always run: `nr lint && nr typecheck`

### TypeScript Configuration
- Strict mode enabled
## TypeScript Configuration
- Strict mode enabled with `strictNullChecks: true`
- Target: ES2017
- Module: ESNext
- No lib files checked (skipLibCheck: true)
- Module resolution: node with JSON module support
- `skipLibCheck: true` for faster builds

## Code Style Guidelines

### Imports
- Use Node protocol imports: `import { x } from 'node:module'`
- Use reactive-vscode for VSCode extension APIs: `import { defineExtension } from 'reactive-vscode'`
- Import vscode types: `import { window, workspace } from 'vscode'`
- Import test utilities: `import { describe, expect, it } from 'vitest'`

### Naming Conventions
- Variables and functions: **camelCase** (`getCommentsFilePath`, `ensureCodeReviewDir`)
- Types and interfaces: **PascalCase** (`Comment`, `CommentStorage`)
- Constants: **SCREAMING_SNAKE_CASE** (`CODEREVIEW_DIR`, `COMMENTS_FILE`)
- **Variables and functions**: camelCase (`getCommentsFilePath`, `ensureCodeReviewDir`)
- **Types and interfaces**: PascalCase (`Comment`, `CommentStorage`)
- **Constants**: SCREAMING_SNAKE_CASE (`CODEREVIEW_DIR`, `COMMENTS_FILE`)
- **Enum members**: UPPER_SNAKE_CASE or PascalCase based on context

### Code Patterns
- Use **guard clauses** (early returns) instead of deep nesting
- Use **defineExtension()** from reactive-vscode for activation/deactivation
- Export types explicitly: `export type`, `export interface`
- Prefer `async/await` over promises
- Use try/catch blocks for error handling (catch without variable is acceptable)
- Use `crypto.randomUUID()` for generating unique IDs

### Error Handling
- Use guard clauses for null/undefined checks early in functions
- Catch errors at appropriate boundaries without swallowing them
- Show user-facing errors with `window.showErrorMessage()`
- Log errors appropriately for debugging

### VSCode Extension Patterns
- Use `Uri.joinPath()` for path manipulation
- Use `workspace.fs` for file operations (createDirectory, readFile, writeFile)
- Use `workspace.fs` for file operations (`createDirectory`, `readFile`, `writeFile`)
- Use `window.showInformationMessage()` and `window.showErrorMessage()` for user feedback
- Use `crypto.randomUUID()` for generating IDs
- Use `new TextEncoder().encode()` and `new TextDecoder().decode()` for file content

### Testing
- Framework: **vitest**
- Import: `import { describe, expect, it } from 'vitest'`
- Structure: `describe('feature', () => { it('should do X', () => { ... }) })`
- Coverage: Comprehensive test suite covering storage, AI integration, filtering, and data processing
- Test Files:
- `test/unit/aiTools.test.ts` - AI tool validation and default models
- `test/unit/aiConfig.test.ts` - AI configuration and validation logic
- `test/unit/aiReview.test.ts` - Comment formatting for AI export
- `test/unit/commandBuilder.test.ts` - Command building and interpolation
- `test/unit/filtering.test.ts` - Comment filtering and sorting logic
- `test/helpers/` - Test utilities and mock helpers
- `test/fixtures/` - Test data factories
- Subscribe to VSCode events in the extension activation function
- Return a dispose function from activation for cleanup

### Formatting
- No semicolons (style preference from @antfu/eslint-config)
- ESLint handles auto-fix on save
- Run `nr lint` to fix all issues
- Run `nr lint` to fix all issues automatically
- Use consistent line breaks and whitespace

## File Structure
- `src/` - Main source code
- `src/index.ts` - Extension entry point with activation/deactivation
- `src/commands.ts` - Command registration and handlers
- `src/treeView.ts` - Tree view provider implementation
- `src/decorations.ts` - Inline decoration rendering
- `src/storage.ts` - File storage operations
- `src/CommentStorage.ts` - Comment data management
- `src/types.ts` - TypeScript type definitions
- `src/config.ts` - Configuration management
- `src/aiTools.ts` - AI tool integrations
- `src/aiConfig.ts` - AI configuration handling
- `src/aiReview.ts` - AI review functionality
- `src/commandBuilder.ts` - Command building utilities
- `src/terminalProfile.ts` - Terminal profile handling
- `test/` - Test files following source structure
- `test/unit/` - Unit tests matching source file names

## Testing Guidelines
- **Framework**: vitest
- **Structure**: `describe('feature', () => { it('should do X', () => { ... }) })`
- **Test files**: Mirror source file structure in `test/unit/`
- **Helpers**: Place utilities in `test/helpers/`
- **Fixtures**: Place test data factories in `test/fixtures/`
- **Test patterns**:
- Test constants and utilities directly
- Test validation and transformation functions
- Use descriptive test names that explain expected behavior
- Group related tests with nested `describe` blocks

### Key Test Files
- `test/unit/aiTools.test.ts` - AI tool validation and default models
- `test/unit/aiConfig.test.ts` - AI configuration and validation logic
- `test/unit/aiReview.test.ts` - Comment formatting for AI export
- `test/unit/commandBuilder.test.ts` - Command building and interpolation
- `test/unit/filtering.test.ts` - Comment filtering and sorting logic
- `test/unit/storage.test.ts` - Storage path and directory operations
- `test/unit/CommentStorage.test.ts` - Comment CRUD operations
- `test/unit/terminalProfile.test.ts` - Terminal profile handling

### Additional Rules
## Additional Rules
- Keep code modular and self-documenting
- Use meaningful variable names that explain intent
- Avoid over-engineering - keep solutions simple
- No comments unless necessary for complex logic
- Maintain consistent patterns across similar files
- Follow existing code style when making changes
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,20 +128,21 @@ Choose from built-in templates or create your own:

<!-- configs -->

| Key | Description | Type | Default |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------- |
| `seal-code.showInlineDecorations` | Show inline text decorations (after-line text preview) | `boolean` | `true` |
| `seal-code.showGutterIcons` | Show gutter icons for comments | `boolean` | `true` |
| `seal-code.showLineBackground` | Show colored background on commented lines | `boolean` | `true` |
| `seal-code.categoryColors` | Custom colors for each comment category | `object` | `{"bug":"#f44336","question":"#2196f3","suggestion":"#4caf50","nitpick":"#ff9800","note":"#9e9e9e"}` |
| `seal-code.aiTool` | AI CLI tool to use for sending review comments | `string` | `"opencode"` |
| `seal-code.aiToolCommand` | Custom command path for AI tool (used when aiTool is 'custom', e.g., 'ccs glm') | `string` | `""` |
| `seal-code.aiToolClaudeModel` | Claude model to use (e.g., haiku, sonnet, opus) | `string` | `"haiku"` |
| `seal-code.aiToolOpenCodeModel` | OpenCode model to use (e.g., opencode/big-pickle, opencode/claude) | `string` | `"opencode/big-pickle"` |
| `seal-code.aiToolCopilotModel` | Copilot model to use (e.g., gpt-4.1, gpt-4o, o3) | `string` | `"gpt-4.1"` |
| `seal-code.aiToolAmpModel` | Amp mode to use (rush or smart). Execute mode requires rush or smart. | `string` | `"smart"` |
| `seal-code.promptTemplates` | Named prompt templates for AI review. Use {{comments}} for formatted comments and {{files}} for affected file list. | `object` | See package.json |
| `seal-code.showAIQuickPick` | Show quick pick menu for AI tool selection before sending to AI | `boolean` | `false` |
| Key | Description | Type | Default |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------- |
| `seal-code.showInlineDecorations` | Show inline text decorations (after-line text preview) | `boolean` | `true` |
| `seal-code.showGutterIcons` | Show gutter icons for comments | `boolean` | `true` |
| `seal-code.showLineBackground` | Show colored background on commented lines | `boolean` | `true` |
| `seal-code.categoryColors` | Custom colors for each comment category | `object` | `{"bug":"#f44336","question":"#2196f3","suggestion":"#4caf50","nitpick":"#ff9800","note":"#9e9e9e"}` |
| `seal-code.aiTool` | AI CLI tool to use for sending review comments | `string` | `"opencode"` |
| `seal-code.aiToolCommand` | Custom command path for AI tool (used when aiTool is 'custom', e.g., 'ccs glm') | `string` | `""` |
| `seal-code.aiToolClaudeModel` | Claude model to use (e.g., haiku, sonnet, opus) | `string` | `"haiku"` |
| `seal-code.aiToolOpenCodeModel` | OpenCode model to use (e.g., opencode/big-pickle, opencode/claude) | `string` | `"opencode/big-pickle"` |
| `seal-code.aiToolCopilotModel` | Copilot model to use (e.g., gpt-4.1, gpt-4o, o3) | `string` | `"gpt-4.1"` |
| `seal-code.aiToolAmpModel` | Amp mode to use (rush or smart). Execute mode requires rush or smart. | `string` | `"smart"` |
| `seal-code.promptTemplates` | Named prompt templates for AI review. Use {{comments}} for formatted comments and {{files}} for affected file list. | `object` | See package.json |
| `seal-code.showAIQuickPick` | Show quick pick menu for AI tool selection before sending to AI | `boolean` | `false` |
| `seal-code.terminalProfile` | Terminal profile to use for AI reviews. 'default' uses VSCode terminal, 'tmux' runs in a tmux session per workspace. | `string` | `"default"` |

<!-- configs -->

Expand Down
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,12 @@
"type": "boolean",
"default": false,
"description": "Show quick pick menu for AI tool selection before sending to AI"
},
"seal-code.terminalProfile": {
"type": "string",
"enum": ["default", "tmux"],
"default": "default",
"description": "Terminal profile to use for AI reviews. 'default' uses VSCode terminal, 'tmux' runs in a tmux session per workspace."
}
}
}
Expand Down
96 changes: 96 additions & 0 deletions ralph/prd.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
"project": "SealCode",
"branchName": "ralph/terminal-profile",
"description": "Terminal Profile for Session Management - Run AI reviews in tmux with one session per workspace",
"userStories": [
{
"id": "US-001",
"title": "Add terminal profile configuration setting",
"description": "As a user, I want to configure my preferred terminal profile so that all AI reviews run within my chosen session manager.",
"acceptanceCriteria": [
"Add `seal-code.terminalProfile` setting to package.json with enum: default, tmux",
"Default value is 'default' (current VSCode terminal behavior)",
"Run `nr update` to regenerate VSCode metadata",
"Typecheck passes"
],
"priority": 1,
"passes": true,
"notes": "Implemented in package.json lines 334-340"
},
{
"id": "US-002",
"title": "Create terminalProfile module with binary detection",
"description": "As a developer, I need a module to detect tmux availability and manage session names.",
"acceptanceCriteria": [
"Create src/terminalProfile.ts module",
"Add TerminalProfile type: 'default' | 'tmux'",
"Implement isTmuxAvailable() using 'which tmux' command",
"Implement getSessionName(workspaceName) returning 'sealcode-{sanitized-name}'",
"Sanitize workspace name: lowercase, replace spaces/special chars with hyphens",
"Typecheck passes"
],
"priority": 2,
"passes": true,
"notes": "Implemented in src/terminalProfile.ts"
},
{
"id": "US-003",
"title": "Implement tmux session execution",
"description": "As a user, I want AI reviews to run in a tmux session so I can manage multiple reviews in one place.",
"acceptanceCriteria": [
"Add buildTmuxCommand(sessionName, windowName, command) to terminalProfile.ts",
"Use format: tmux new-session -A -s {session} -n {window} -d && tmux send-keys -t {session}:{window} '{command}' Enter && tmux attach -t {session}",
"Window name derived from template name and AI tool",
"Typecheck passes"
],
"priority": 3,
"passes": true,
"notes": "Implemented in src/terminalProfile.ts lines 29-32"
},
{
"id": "US-004",
"title": "Handle missing tmux with fallback prompt",
"description": "As a user, I want to be prompted to use default terminal when tmux is not installed.",
"acceptanceCriteria": [
"Add promptForFallback() showing quick pick when tmux unavailable",
"Quick pick options: 'Use Default Terminal', 'Cancel'",
"Returns 'default' or undefined if cancelled",
"Typecheck passes"
],
"priority": 4,
"passes": true,
"notes": "Implemented in src/terminalProfile.ts lines 34-46"
},
{
"id": "US-005",
"title": "Integrate terminal profile into executeAIReview",
"description": "As a user, I want the AI review command to use my configured terminal profile.",
"acceptanceCriteria": [
"Read terminalProfile setting in executeAIReview function",
"If profile is 'default', use existing terminal creation logic",
"If profile is 'tmux', check availability and build wrapped command",
"If tmux unavailable, call promptForFallback",
"Execute the final command in VSCode terminal",
"Typecheck passes"
],
"priority": 5,
"passes": true,
"notes": "Implemented in src/commands.ts lines 808-826"
},
{
"id": "US-006",
"title": "Add unit tests for terminalProfile module",
"description": "As a developer, I need tests to verify terminal profile logic.",
"acceptanceCriteria": [
"Create test/unit/terminalProfile.test.ts",
"Test getSessionName sanitizes workspace names correctly",
"Test buildTmuxCommand generates correct command format",
"Typecheck passes",
"Tests pass"
],
"priority": 6,
"passes": true,
"notes": "14 tests passing in test/unit/terminalProfile.test.ts"
}
]
}
Loading