chore: initialize repository with project docs and tooling
- Add persistent docs: PRD, functional design, architecture, repository structure, development guidelines, milestones - Add brainstorming notes (docs/ideas/) - Configure tooling: package.json, tsconfig, eslint, prettier, vitest - Add opencode configuration (commands, skills, agents) - Add .gitignore for node_modules, .env, data/, backups/, build outputs
This commit is contained in:
50
.opencode/skills/architecture-design/SKILL.md
Normal file
50
.opencode/skills/architecture-design/SKILL.md
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
name: architecture-design
|
||||
description: A detailed guide and template for creating architecture design documents. Use only when designing architecture.
|
||||
---
|
||||
|
||||
# Architecture Design Skill
|
||||
|
||||
This skill is a detailed guide for creating high-quality architecture design documents.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting architecture design, check the following:
|
||||
|
||||
### Required Documents
|
||||
|
||||
1. `docs/product-requirements.md` (PRD)
|
||||
2. `docs/functional-design.md` (functional design document)
|
||||
|
||||
Architecture design defines the system structure and technology stack
|
||||
needed to technically realize the PRD's requirements and functional design.
|
||||
|
||||
## Priority of Existing Documents
|
||||
|
||||
**Important**: If an existing architecture design document is present at `docs/architecture.md`,
|
||||
follow this priority order:
|
||||
|
||||
1. **The existing architecture design document (`docs/architecture.md`)** - highest priority
|
||||
- It documents project-specific technology choices and design
|
||||
- It takes precedence over this skill's guide
|
||||
|
||||
2. **This skill's guide** - reference material
|
||||
- General-purpose templates and examples
|
||||
- Use when there is no existing design document, or as a supplement
|
||||
|
||||
**When creating new**: Refer to this skill's template and guide
|
||||
**When updating**: Update while preserving the structure and content of the existing design document
|
||||
|
||||
## Output Destination
|
||||
|
||||
Save the architecture design document you create to:
|
||||
|
||||
```
|
||||
docs/architecture.md
|
||||
```
|
||||
|
||||
## Referencing the Template
|
||||
|
||||
When creating an architecture design document, use the template while referring to the following guide:
|
||||
- Guide: ./guide.md
|
||||
- Template: ./template.md
|
||||
186
.opencode/skills/architecture-design/guide.md
Normal file
186
.opencode/skills/architecture-design/guide.md
Normal file
@ -0,0 +1,186 @@
|
||||
# Architecture Design Guide
|
||||
|
||||
## Basic Principles
|
||||
|
||||
### 1. State the Rationale for Technology Choices
|
||||
|
||||
**Bad example**:
|
||||
```
|
||||
- Node.js
|
||||
- TypeScript
|
||||
```
|
||||
|
||||
**Good example**:
|
||||
```
|
||||
- Node.js v24.11.0 (LTS)
|
||||
- Long-term support guaranteed until April 2026, ensuring stable operation in production
|
||||
- Excellent at asynchronous I/O, delivering high performance as an API server
|
||||
- Rich npm ecosystem makes the required libraries easy to obtain
|
||||
|
||||
- TypeScript 5.x
|
||||
- Static typing catches bugs at compile time, improving maintainability
|
||||
- Powerful IDE autocompletion boosts development efficiency
|
||||
- Shared type definitions in team development ensure code readability and quality
|
||||
|
||||
- npm 11.x
|
||||
- Bundled with Node.js v24.11.0, so no separate installation is required
|
||||
- Supports monorepo configurations via the workspaces feature
|
||||
- Enables strict dependency management through package-lock.json
|
||||
```
|
||||
|
||||
### 2. The Principle of Layer Separation
|
||||
|
||||
Clarify the responsibilities of each layer and keep dependencies unidirectional:
|
||||
|
||||
```
|
||||
UI → Service → Data (OK)
|
||||
UI ← Service (NG)
|
||||
UI → Data (NG)
|
||||
```
|
||||
|
||||
### 3. Measurable Requirements
|
||||
|
||||
Describe all performance requirements in a measurable form.
|
||||
|
||||
## Designing a Layered Architecture
|
||||
|
||||
### Responsibilities of Each Layer
|
||||
|
||||
**UI layer**:
|
||||
```typescript
|
||||
// Responsibility: Accepting and validating user input
|
||||
class CLI {
|
||||
// OK: Call the service layer
|
||||
async addTask(title: string) {
|
||||
const task = await this.taskService.create({ title });
|
||||
console.log(`Created: ${task.id}`);
|
||||
}
|
||||
|
||||
// NG: Call the data layer directly
|
||||
async addTask(title: string) {
|
||||
const task = await this.repository.save({ title }); // ❌
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Service layer**:
|
||||
```typescript
|
||||
// Responsibility: Implementing business logic
|
||||
class TaskService {
|
||||
// Business logic: Automatic priority estimation
|
||||
async create(data: CreateTaskData): Promise<Task> {
|
||||
const task = {
|
||||
...data,
|
||||
estimatedPriority: this.estimatePriority(data),
|
||||
};
|
||||
return this.repository.save(task);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Data layer**:
|
||||
```typescript
|
||||
// Responsibility: Data persistence
|
||||
class TaskRepository {
|
||||
async save(task: Task): Promise<void> {
|
||||
await this.storage.write(task);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Setting Performance Requirements
|
||||
|
||||
### Concrete Numeric Targets
|
||||
|
||||
```
|
||||
Command execution time: within 100ms (on an average PC environment)
|
||||
└─ Measurement method: measure from CLI startup to result display with console.time
|
||||
└─ Measurement environment: CPU equivalent to Core i5, 8GB RAM, SSD
|
||||
|
||||
Task list display: within 1 second for up to 1000 items
|
||||
└─ Measurement method: measure with 1000 dummy data items
|
||||
└─ Acceptable range: 100ms for 100 items, 1 second for 1000 items, 10 seconds for 10000 items
|
||||
```
|
||||
|
||||
## Security Design
|
||||
|
||||
### The Three Principles of Data Protection
|
||||
|
||||
1. **Principle of least privilege**
|
||||
```bash
|
||||
# File permissions
|
||||
chmod 600 ~/.devtask/tasks.json # Read/write for owner only
|
||||
```
|
||||
|
||||
2. **Input validation**
|
||||
```typescript
|
||||
function validateTitle(title: string): void {
|
||||
if (!title || title.length === 0) {
|
||||
throw new ValidationError('Title is required');
|
||||
}
|
||||
if (title.length > 200) {
|
||||
throw new ValidationError('Title must be 200 characters or fewer');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **Managing sensitive information**
|
||||
```bash
|
||||
# Manage via environment variables
|
||||
export DEVTASK_API_KEY="xxxxx" # Do not hardcode in the code
|
||||
```
|
||||
|
||||
## Scalability Design
|
||||
|
||||
### Handling Data Growth
|
||||
|
||||
**Expected data volume**: [e.g., 10,000 tasks]
|
||||
|
||||
**Countermeasures**:
|
||||
- Data pagination
|
||||
- Archiving old data
|
||||
- Index optimization
|
||||
|
||||
```typescript
|
||||
// Example archive feature: move old tasks to a separate file
|
||||
class ArchiveService {
|
||||
async archiveCompletedTasks(olderThan: Date): Promise<void> {
|
||||
const oldTasks = await this.repository.findCompleted(olderThan);
|
||||
await this.archiveStorage.save(oldTasks);
|
||||
await this.repository.deleteMany(oldTasks.map(t => t.id));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Dependency Management
|
||||
|
||||
### Version Management Policy
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"commander": "^11.0.0", // Minor version upgrades are automatic
|
||||
"chalk": "5.3.0" // Pin when there is a risk of breaking changes
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "~5.3.0", // Patch versions only are automatic
|
||||
"eslint": "^9.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Policy**:
|
||||
- Pin stable versions (allow up to minor versions with ^)
|
||||
- Pin completely when there is a risk of breaking changes
|
||||
- For devDependencies, automate patch versions only (~)
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Every technology choice has a stated rationale
|
||||
- [ ] The layered architecture is clearly defined
|
||||
- [ ] Performance requirements are measurable
|
||||
- [ ] Security considerations are documented
|
||||
- [ ] Scalability is taken into account
|
||||
- [ ] A backup strategy is defined
|
||||
- [ ] The dependency management policy is clear
|
||||
- [ ] A test strategy is defined
|
||||
153
.opencode/skills/architecture-design/template.md
Normal file
153
.opencode/skills/architecture-design/template.md
Normal file
@ -0,0 +1,153 @@
|
||||
# Architecture Design Document
|
||||
|
||||
## Technology Stack
|
||||
|
||||
### Languages and Runtimes
|
||||
|
||||
| Technology | Version |
|
||||
|------|-----------|
|
||||
| Node.js | v24.11.0 |
|
||||
| TypeScript | 5.x |
|
||||
| npm | 11.x |
|
||||
|
||||
### Frameworks and Libraries
|
||||
|
||||
| Technology | Version | Purpose | Rationale |
|
||||
|------|-----------|------|----------|
|
||||
| [name] | [version] | [purpose] | [rationale] |
|
||||
| [name] | [version] | [purpose] | [rationale] |
|
||||
|
||||
### Development Tools
|
||||
|
||||
| Technology | Version | Purpose | Rationale |
|
||||
|------|-----------|------|----------|
|
||||
| [name] | [version] | [purpose] | [rationale] |
|
||||
| [name] | [version] | [purpose] | [rationale] |
|
||||
|
||||
## Architecture Pattern
|
||||
|
||||
### Layered Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────┐
|
||||
│ UI layer │ ← Accepts and displays user input
|
||||
├─────────────────────────┤
|
||||
│ Service layer │ ← Business logic
|
||||
├─────────────────────────┤
|
||||
│ Data layer │ ← Data persistence
|
||||
└─────────────────────────┘
|
||||
```
|
||||
|
||||
#### UI Layer
|
||||
- **Responsibility**: Accepting user input, validation, displaying results
|
||||
- **Permitted operations**: Calling the service layer
|
||||
- **Prohibited operations**: Direct access to the data layer
|
||||
|
||||
#### Service Layer
|
||||
- **Responsibility**: Implementing business logic, data transformation
|
||||
- **Permitted operations**: Calling the data layer
|
||||
- **Prohibited operations**: Depending on the UI layer
|
||||
|
||||
#### Data Layer
|
||||
- **Responsibility**: Data persistence and retrieval
|
||||
- **Permitted operations**: Access to the file system and databases
|
||||
- **Prohibited operations**: Implementing business logic
|
||||
|
||||
## Data Persistence Strategy
|
||||
|
||||
### Storage Method
|
||||
|
||||
| Data type | Storage | Format | Rationale |
|
||||
|-----------|----------|-------------|------|
|
||||
| [data 1] | [method] | [format] | [rationale] |
|
||||
| [data 2] | [method] | [format] | [rationale] |
|
||||
|
||||
### Backup Strategy
|
||||
|
||||
- **Frequency**: [e.g., every hour]
|
||||
- **Destination**: [e.g., `.backup/` directory]
|
||||
- **Generation management**: [e.g., retain the latest 5 generations]
|
||||
- **Restoration method**: [procedure]
|
||||
|
||||
## Performance Requirements
|
||||
|
||||
### Response Time
|
||||
|
||||
| Operation | Target time | Measurement environment |
|
||||
|------|---------|---------|
|
||||
| [operation 1] | [time] | [environment] |
|
||||
| [operation 2] | [time] | [environment] |
|
||||
|
||||
### Resource Usage
|
||||
|
||||
| Resource | Limit | Rationale |
|
||||
|---------|------|------|
|
||||
| Memory | [MB] | [rationale] |
|
||||
| CPU | [%] | [rationale] |
|
||||
| Disk | [MB] | [rationale] |
|
||||
|
||||
## Security Architecture
|
||||
|
||||
### Data Protection
|
||||
|
||||
- **Encryption**: [target data and method]
|
||||
- **Access control**: [file permissions, etc.]
|
||||
- **Sensitive information management**: [environment variables, config files, etc.]
|
||||
|
||||
### Input Validation
|
||||
|
||||
- **Validation**: [validation items]
|
||||
- **Sanitization**: [target and method]
|
||||
- **Error handling**: [secure error display]
|
||||
|
||||
## Scalability Design
|
||||
|
||||
### Handling Data Growth
|
||||
|
||||
- **Expected data volume**: [e.g., 10,000 tasks]
|
||||
- **Performance degradation countermeasures**: [method]
|
||||
- **Archive strategy**: [handling of old data]
|
||||
|
||||
### Extensibility
|
||||
|
||||
- **Plugin system**: [presence/absence and design]
|
||||
- **Configuration customization**: [scope of what is possible]
|
||||
- **API extensibility**: [methods for future extension]
|
||||
|
||||
## Test Strategy
|
||||
|
||||
### Unit Tests
|
||||
- **Framework**: [framework name]
|
||||
- **Target**: [description of test target]
|
||||
- **Coverage target**: [%]
|
||||
|
||||
### Integration Tests
|
||||
- **Method**: [test method]
|
||||
- **Target**: [description of test target]
|
||||
|
||||
### E2E Tests
|
||||
- **Tool**: [tool name]
|
||||
- **Scenarios**: [test scenarios]
|
||||
|
||||
## Technical Constraints
|
||||
|
||||
### Environment Requirements
|
||||
- **OS**: [supported OS]
|
||||
- **Minimum memory**: [MB]
|
||||
- **Required disk space**: [MB]
|
||||
- **Required external dependencies**: [list]
|
||||
|
||||
### Performance Constraints
|
||||
- [constraint 1]
|
||||
- [constraint 2]
|
||||
|
||||
### Security Constraints
|
||||
- [constraint 1]
|
||||
- [constraint 2]
|
||||
|
||||
## Dependency Management
|
||||
|
||||
| Library | Purpose | Version management policy |
|
||||
|-----------|------|-------------------|
|
||||
| [name] | [purpose] | [pinned/range] |
|
||||
| [name] | [purpose] | [pinned/range] |
|
||||
107
.opencode/skills/development-guidelines/SKILL.md
Normal file
107
.opencode/skills/development-guidelines/SKILL.md
Normal file
@ -0,0 +1,107 @@
|
||||
---
|
||||
name: development-guidelines
|
||||
description: A comprehensive guide and template for establishing a unified development process and coding conventions across the team. Use when creating development guidelines and when implementing code.
|
||||
---
|
||||
|
||||
# Development Guidelines Skill
|
||||
|
||||
Covers the two elements needed for team development:
|
||||
1. Coding conventions for implementation (implementation-guide.md)
|
||||
2. Standardization of the development process (process-guide.md)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting to create development guidelines, check the following:
|
||||
|
||||
### Recommended Documents
|
||||
|
||||
1. `docs/architecture.md` (architecture design document) - confirm the technology stack
|
||||
2. `docs/repository-structure.md` (repository structure) - confirm the directory structure
|
||||
|
||||
The development guidelines define concrete coding conventions and a development process
|
||||
based on the project's technology stack and directory structure.
|
||||
|
||||
## Priority of Existing Documents
|
||||
|
||||
**Important**: If existing development guidelines are present at `docs/development-guidelines.md`,
|
||||
follow this priority order:
|
||||
|
||||
1. **The existing development guidelines (`docs/development-guidelines.md`)** - highest priority
|
||||
- They document project-specific conventions and processes
|
||||
- They take precedence over this skill's guide
|
||||
|
||||
2. **This skill's guide** - reference material
|
||||
- ./guides/implementation.md: general-purpose coding conventions
|
||||
- ./guides/process.md: general-purpose development process
|
||||
- Use when there are no existing guidelines, or as a supplement
|
||||
|
||||
**When creating new**: Refer to this skill's guides and template
|
||||
**When updating**: Update while preserving the structure and content of the existing guidelines
|
||||
|
||||
## Output Destination
|
||||
|
||||
Save the development guidelines you create to:
|
||||
|
||||
```
|
||||
docs/development-guidelines.md
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### When Implementing Code
|
||||
Rules and conventions for code implementation: ./guides/implementation.md
|
||||
|
||||
Contents:
|
||||
- TypeScript/JavaScript conventions
|
||||
- Type definitions and naming conventions
|
||||
- Function design and error handling
|
||||
- Comment conventions
|
||||
- Security and performance
|
||||
- Test code implementation
|
||||
- Refactoring techniques
|
||||
|
||||
### When Referencing/Defining the Development Process
|
||||
Git workflow, test strategy, code review: ./guides/process.md
|
||||
|
||||
Contents:
|
||||
- Basic principles (the importance of concrete examples, explaining rationale)
|
||||
- Git workflow rules (Git Flow branching strategy)
|
||||
- Commit messages and the PR process
|
||||
- Test strategy (pyramid and coverage)
|
||||
- The code review process
|
||||
- Quality automation
|
||||
|
||||
### Template
|
||||
When creating development guidelines: ./template.md
|
||||
|
||||
|
||||
## Guide by Use Case
|
||||
|
||||
### When Developing New Code
|
||||
1. Confirm naming conventions and coding standards in ./guides/implementation.md
|
||||
2. Confirm the branching strategy and PR handling in ./guides/process.md
|
||||
3. Write tests first (TDD)
|
||||
|
||||
### During Code Review
|
||||
- Refer to "The Code Review Process" in ./guides/process.md
|
||||
- Check for convention violations against ./guides/implementation.md
|
||||
|
||||
### When Designing Tests
|
||||
- "Test Strategy" in ./guides/process.md (pyramid, coverage)
|
||||
- "Test Code" in ./guides/implementation.md (implementation patterns)
|
||||
|
||||
### When Preparing a Release
|
||||
- "Git Workflow Rules" in ./guides/process.md (policy for merging into main)
|
||||
- Confirm that commit messages follow Conventional Commits
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Coding conventions are defined with concrete examples
|
||||
- [ ] Naming conventions are clear (per language and project-specific)
|
||||
- [ ] An error handling policy is defined
|
||||
- [ ] A branching strategy is decided (Git Flow recommended)
|
||||
- [ ] Commit message conventions are clear
|
||||
- [ ] A PR template is prepared
|
||||
- [ ] Test types and coverage targets are set
|
||||
- [ ] A code review process is defined
|
||||
- [ ] A CI/CD pipeline is established
|
||||
627
.opencode/skills/development-guidelines/guides/implementation.md
Normal file
627
.opencode/skills/development-guidelines/guides/implementation.md
Normal file
@ -0,0 +1,627 @@
|
||||
# Implementation Guide
|
||||
|
||||
## TypeScript/JavaScript Conventions
|
||||
|
||||
### Type Definitions
|
||||
|
||||
**Using built-in types**:
|
||||
```typescript
|
||||
// ✅ Good: Use built-in types
|
||||
function processItems(items: string[]): Record<string, number> {
|
||||
return items.reduce((acc, item) => {
|
||||
acc[item] = (acc[item] || 0) + 1;
|
||||
return acc;
|
||||
}, {} as Record<string, number>);
|
||||
}
|
||||
|
||||
// ❌ Bad: Importing from the typing module
|
||||
import { List, Dict } from 'typing';
|
||||
function processItems(items: List[str]): Dict[str, int] { }
|
||||
```
|
||||
|
||||
**Type annotation principles**:
|
||||
```typescript
|
||||
// ✅ Good: Explicit type annotations
|
||||
function calculateTotal(prices: number[]): number {
|
||||
return prices.reduce((sum, price) => sum + price, 0);
|
||||
}
|
||||
|
||||
// ❌ Bad: Over-relying on type inference
|
||||
function calculateTotal(prices) { // becomes the any type
|
||||
return prices.reduce((sum, price) => sum + price, 0);
|
||||
}
|
||||
```
|
||||
|
||||
**Interface vs. type alias**:
|
||||
```typescript
|
||||
// Interface: extensible object types
|
||||
interface Task {
|
||||
id: string;
|
||||
title: string;
|
||||
completed: boolean;
|
||||
}
|
||||
|
||||
// Extension
|
||||
interface ExtendedTask extends Task {
|
||||
priority: string;
|
||||
}
|
||||
|
||||
// Type alias: union types, primitive types, etc.
|
||||
type TaskStatus = 'todo' | 'in_progress' | 'completed';
|
||||
type TaskId = string;
|
||||
type Nullable<T> = T | null;
|
||||
```
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
**Variables and functions**:
|
||||
```typescript
|
||||
// Variables: camelCase, nouns
|
||||
const userName = 'John';
|
||||
const taskList = [];
|
||||
const isCompleted = true;
|
||||
|
||||
// Functions: camelCase, start with a verb
|
||||
function fetchUserData() { }
|
||||
function validateEmail(email: string) { }
|
||||
function calculateTotalPrice(items: Item[]) { }
|
||||
|
||||
// Boolean: start with is, has, should, or can
|
||||
const isValid = true;
|
||||
const hasPermission = false;
|
||||
const shouldRetry = true;
|
||||
const canDelete = false;
|
||||
```
|
||||
|
||||
**Classes and interfaces**:
|
||||
```typescript
|
||||
// Classes: PascalCase, nouns
|
||||
class TaskManager { }
|
||||
class UserAuthenticationService { }
|
||||
|
||||
// Interfaces: PascalCase
|
||||
interface TaskRepository { }
|
||||
interface UserProfile { }
|
||||
|
||||
// Type aliases: PascalCase
|
||||
type TaskStatus = 'todo' | 'in_progress' | 'completed';
|
||||
```
|
||||
|
||||
**Constants**:
|
||||
```typescript
|
||||
// UPPER_SNAKE_CASE
|
||||
const MAX_RETRY_COUNT = 3;
|
||||
const API_BASE_URL = 'https://api.example.com';
|
||||
const DEFAULT_TIMEOUT = 5000;
|
||||
|
||||
// For configuration objects
|
||||
const CONFIG = {
|
||||
maxRetryCount: 3,
|
||||
apiBaseUrl: 'https://api.example.com',
|
||||
defaultTimeout: 5000,
|
||||
} as const;
|
||||
```
|
||||
|
||||
**File names**:
|
||||
```typescript
|
||||
// Class files: PascalCase
|
||||
// TaskService.ts
|
||||
// UserRepository.ts
|
||||
|
||||
// Functions and utilities: camelCase
|
||||
// formatDate.ts
|
||||
// validateEmail.ts
|
||||
|
||||
// Components (React, etc.): PascalCase
|
||||
// TaskList.tsx
|
||||
// UserProfile.tsx
|
||||
|
||||
// Constants: kebab-case or UPPER_SNAKE_CASE
|
||||
// api-endpoints.ts
|
||||
// ERROR_MESSAGES.ts
|
||||
```
|
||||
|
||||
### Function Design
|
||||
|
||||
**Single responsibility principle**:
|
||||
```typescript
|
||||
// ✅ Good: A single responsibility
|
||||
function calculateTotalPrice(items: CartItem[]): number {
|
||||
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
||||
}
|
||||
|
||||
function formatPrice(amount: number): string {
|
||||
return `¥${amount.toLocaleString()}`;
|
||||
}
|
||||
|
||||
// ❌ Bad: Multiple responsibilities
|
||||
function calculateAndFormatPrice(items: CartItem[]): string {
|
||||
const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
||||
return `¥${total.toLocaleString()}`;
|
||||
}
|
||||
```
|
||||
|
||||
**Function length**:
|
||||
- Target: within 20 lines
|
||||
- Recommended: within 50 lines
|
||||
- 100 lines or more: consider refactoring
|
||||
|
||||
**Number of parameters**:
|
||||
```typescript
|
||||
// ✅ Good: Group into an object
|
||||
interface CreateTaskOptions {
|
||||
title: string;
|
||||
description?: string;
|
||||
priority?: 'high' | 'medium' | 'low';
|
||||
dueDate?: Date;
|
||||
}
|
||||
|
||||
function createTask(options: CreateTaskOptions): Task {
|
||||
// implementation
|
||||
}
|
||||
|
||||
// ❌ Bad: Too many parameters
|
||||
function createTask(
|
||||
title: string,
|
||||
description: string,
|
||||
priority: string,
|
||||
dueDate: Date,
|
||||
tags: string[],
|
||||
assignee: string
|
||||
): Task {
|
||||
// implementation
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
**Custom error classes**:
|
||||
```typescript
|
||||
// Defining error classes
|
||||
class ValidationError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public field: string,
|
||||
public value: unknown
|
||||
) {
|
||||
super(message);
|
||||
this.name = 'ValidationError';
|
||||
}
|
||||
}
|
||||
|
||||
class NotFoundError extends Error {
|
||||
constructor(
|
||||
public resource: string,
|
||||
public id: string
|
||||
) {
|
||||
super(`${resource} not found: ${id}`);
|
||||
this.name = 'NotFoundError';
|
||||
}
|
||||
}
|
||||
|
||||
class DatabaseError extends Error {
|
||||
constructor(message: string, public cause?: Error) {
|
||||
super(message);
|
||||
this.name = 'DatabaseError';
|
||||
this.cause = cause;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Error handling patterns**:
|
||||
```typescript
|
||||
// ✅ Good: Proper error handling
|
||||
async function getTask(id: string): Promise<Task> {
|
||||
try {
|
||||
const task = await repository.findById(id);
|
||||
|
||||
if (!task) {
|
||||
throw new NotFoundError('Task', id);
|
||||
}
|
||||
|
||||
return task;
|
||||
} catch (error) {
|
||||
if (error instanceof NotFoundError) {
|
||||
// Expected error: handle appropriately
|
||||
logger.warn(`Task not found: ${id}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Unexpected error: wrap and propagate upward
|
||||
throw new DatabaseError('Failed to retrieve the task', error as Error);
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ Bad: Ignoring the error
|
||||
async function getTask(id: string): Promise<Task | null> {
|
||||
try {
|
||||
return await repository.findById(id);
|
||||
} catch (error) {
|
||||
return null; // error information is lost
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Error messages**:
|
||||
```typescript
|
||||
// ✅ Good: Specific and suggests a solution
|
||||
throw new ValidationError(
|
||||
'Title must be 1-200 characters. Current length: 250',
|
||||
'title',
|
||||
title
|
||||
);
|
||||
|
||||
// ❌ Bad: Vague and unhelpful
|
||||
throw new Error('Invalid input');
|
||||
```
|
||||
|
||||
### Asynchronous Processing
|
||||
|
||||
**Using async/await**:
|
||||
```typescript
|
||||
// ✅ Good: async/await
|
||||
async function fetchUserTasks(userId: string): Promise<Task[]> {
|
||||
try {
|
||||
const user = await userRepository.findById(userId);
|
||||
const tasks = await taskRepository.findByUserId(user.id);
|
||||
return tasks;
|
||||
} catch (error) {
|
||||
logger.error('Failed to retrieve tasks', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ Bad: Promise chains
|
||||
function fetchUserTasks(userId: string): Promise<Task[]> {
|
||||
return userRepository.findById(userId)
|
||||
.then(user => taskRepository.findByUserId(user.id))
|
||||
.then(tasks => tasks)
|
||||
.catch(error => {
|
||||
logger.error('Failed to retrieve tasks', error);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**Parallel processing**:
|
||||
```typescript
|
||||
// ✅ Good: Run in parallel with Promise.all
|
||||
async function fetchMultipleUsers(ids: string[]): Promise<User[]> {
|
||||
const promises = ids.map(id => userRepository.findById(id));
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
// ❌ Bad: Sequential execution
|
||||
async function fetchMultipleUsers(ids: string[]): Promise<User[]> {
|
||||
const users: User[] = [];
|
||||
for (const id of ids) {
|
||||
const user = await userRepository.findById(id); // slow
|
||||
users.push(user);
|
||||
}
|
||||
return users;
|
||||
}
|
||||
```
|
||||
|
||||
## Comment Conventions
|
||||
|
||||
### Documentation Comments
|
||||
|
||||
**TSDoc format**:
|
||||
```typescript
|
||||
/**
|
||||
* Creates a task
|
||||
*
|
||||
* @param data - Data for the task to create
|
||||
* @returns The created task
|
||||
* @throws {ValidationError} When the data is invalid
|
||||
* @throws {DatabaseError} When a database error occurs
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const task = await createTask({
|
||||
* title: 'New task',
|
||||
* priority: 'high'
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async function createTask(data: CreateTaskData): Promise<Task> {
|
||||
// implementation
|
||||
}
|
||||
```
|
||||
|
||||
### Inline Comments
|
||||
|
||||
**Good comments**:
|
||||
```typescript
|
||||
// ✅ Explain the reason
|
||||
// Invalidate the cache to fetch the latest data
|
||||
cache.clear();
|
||||
|
||||
// ✅ Explain complex logic
|
||||
// Compute the maximum subarray sum using Kadane's algorithm
|
||||
// Time complexity: O(n)
|
||||
let maxSoFar = arr[0];
|
||||
let maxEndingHere = arr[0];
|
||||
|
||||
// ✅ Make use of TODO and FIXME
|
||||
// TODO: Implement caching (Issue #123)
|
||||
// FIXME: Performance degrades with large datasets (Issue #456)
|
||||
// HACK: Temporary workaround, needs refactoring later
|
||||
```
|
||||
|
||||
**Bad comments**:
|
||||
```typescript
|
||||
// ❌ Merely restating the code
|
||||
// Increment i by 1
|
||||
i++;
|
||||
|
||||
// ❌ Stale information
|
||||
// This code was added in 2020 (unnecessary information)
|
||||
|
||||
// ❌ Commented-out code
|
||||
// const oldImplementation = () => { ... }; // should be deleted
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
### Input Validation
|
||||
|
||||
```typescript
|
||||
// ✅ Good: Strict validation
|
||||
function validateEmail(email: string): void {
|
||||
if (!email || typeof email !== 'string') {
|
||||
throw new ValidationError('Email address is required', 'email', email);
|
||||
}
|
||||
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(email)) {
|
||||
throw new ValidationError('Email address format is invalid', 'email', email);
|
||||
}
|
||||
|
||||
if (email.length > 254) {
|
||||
throw new ValidationError('Email address is too long', 'email', email);
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ Bad: No validation
|
||||
function validateEmail(email: string): void {
|
||||
// no validation
|
||||
}
|
||||
```
|
||||
|
||||
### Managing Sensitive Information
|
||||
|
||||
```typescript
|
||||
// ✅ Good: Load from environment variables
|
||||
import { config } from './config';
|
||||
|
||||
const apiKey = process.env.API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error('The API_KEY environment variable is not set');
|
||||
}
|
||||
|
||||
// ❌ Bad: Hardcoding
|
||||
const apiKey = 'sk-1234567890abcdef'; // never do this!
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
### Choosing Data Structures
|
||||
|
||||
```typescript
|
||||
// ✅ Good: O(1) access with a Map
|
||||
const userMap = new Map(users.map(u => [u.id, u]));
|
||||
const user = userMap.get(userId); // O(1)
|
||||
|
||||
// ❌ Bad: O(n) search with an array
|
||||
const user = users.find(u => u.id === userId); // O(n)
|
||||
```
|
||||
|
||||
### Loop Optimization
|
||||
|
||||
```typescript
|
||||
// ✅ Good: Move unnecessary computation outside the loop
|
||||
const length = items.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
process(items[i]);
|
||||
}
|
||||
|
||||
// ❌ Bad: Recomputing length every iteration
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
process(items[i]);
|
||||
}
|
||||
|
||||
// ✅ Better: Use for...of
|
||||
for (const item of items) {
|
||||
process(item);
|
||||
}
|
||||
```
|
||||
|
||||
### Memoization
|
||||
|
||||
```typescript
|
||||
// Caching computation results
|
||||
const cache = new Map<string, Result>();
|
||||
|
||||
function expensiveCalculation(input: string): Result {
|
||||
if (cache.has(input)) {
|
||||
return cache.get(input)!;
|
||||
}
|
||||
|
||||
const result = /* heavy computation */;
|
||||
cache.set(input, result);
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
## Test Code
|
||||
|
||||
### Test Structure (Given-When-Then)
|
||||
|
||||
```typescript
|
||||
describe('TaskService', () => {
|
||||
describe('create', () => {
|
||||
it('can create a task with valid data', async () => {
|
||||
// Given: setup
|
||||
const service = new TaskService(mockRepository);
|
||||
const taskData = {
|
||||
title: 'Test task',
|
||||
description: 'Description for testing',
|
||||
};
|
||||
|
||||
// When: execute
|
||||
const result = await service.create(taskData);
|
||||
|
||||
// Then: verify
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBeDefined();
|
||||
expect(result.title).toBe('Test task');
|
||||
expect(result.description).toBe('Description for testing');
|
||||
expect(result.createdAt).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
it('throws a ValidationError when the title is empty', async () => {
|
||||
// Given: setup
|
||||
const service = new TaskService(mockRepository);
|
||||
const invalidData = { title: '' };
|
||||
|
||||
// When/Then: execute and verify
|
||||
await expect(
|
||||
service.create(invalidData)
|
||||
).rejects.toThrow(ValidationError);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Creating Mocks
|
||||
|
||||
```typescript
|
||||
// ✅ Good: Mocks based on an interface
|
||||
const mockRepository: TaskRepository = {
|
||||
save: jest.fn(),
|
||||
findById: jest.fn(),
|
||||
findAll: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
};
|
||||
|
||||
// Configure behavior per test
|
||||
beforeEach(() => {
|
||||
mockRepository.findById = jest.fn((id) => {
|
||||
if (id === 'existing-id') {
|
||||
return Promise.resolve(mockTask);
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Refactoring
|
||||
|
||||
### Eliminating Magic Numbers
|
||||
|
||||
```typescript
|
||||
// ✅ Good: Define constants
|
||||
const MAX_RETRY_COUNT = 3;
|
||||
const RETRY_DELAY_MS = 1000;
|
||||
|
||||
for (let i = 0; i < MAX_RETRY_COUNT; i++) {
|
||||
try {
|
||||
return await fetchData();
|
||||
} catch (error) {
|
||||
if (i < MAX_RETRY_COUNT - 1) {
|
||||
await sleep(RETRY_DELAY_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ Bad: Magic numbers
|
||||
for (let i = 0; i < 3; i++) {
|
||||
try {
|
||||
return await fetchData();
|
||||
} catch (error) {
|
||||
if (i < 2) {
|
||||
await sleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Extracting Functions
|
||||
|
||||
```typescript
|
||||
// ✅ Good: Extract functions
|
||||
function processOrder(order: Order): void {
|
||||
validateOrder(order);
|
||||
calculateTotal(order);
|
||||
applyDiscounts(order);
|
||||
saveOrder(order);
|
||||
}
|
||||
|
||||
function validateOrder(order: Order): void {
|
||||
if (!order.items || order.items.length === 0) {
|
||||
throw new ValidationError('No items selected', 'items', order.items);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateTotal(order: Order): void {
|
||||
order.total = order.items.reduce(
|
||||
(sum, item) => sum + item.price * item.quantity,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
// ❌ Bad: A long function
|
||||
function processOrder(order: Order): void {
|
||||
if (!order.items || order.items.length === 0) {
|
||||
throw new ValidationError('No items selected', 'items', order.items);
|
||||
}
|
||||
|
||||
order.total = order.items.reduce(
|
||||
(sum, item) => sum + item.price * item.quantity,
|
||||
0
|
||||
);
|
||||
|
||||
if (order.coupon) {
|
||||
order.total -= order.total * order.coupon.discountRate;
|
||||
}
|
||||
|
||||
repository.save(order);
|
||||
}
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
Confirm before completing implementation:
|
||||
|
||||
### Code Quality
|
||||
- [ ] Naming is clear and consistent
|
||||
- [ ] Functions have a single responsibility
|
||||
- [ ] No magic numbers
|
||||
- [ ] Type annotations are written appropriately
|
||||
- [ ] Error handling is implemented
|
||||
|
||||
### Security
|
||||
- [ ] Input validation is implemented
|
||||
- [ ] No sensitive information is hardcoded
|
||||
- [ ] SQL injection countermeasures are in place
|
||||
|
||||
### Performance
|
||||
- [ ] Appropriate data structures are used
|
||||
- [ ] Unnecessary computation is avoided
|
||||
- [ ] Loops are optimized
|
||||
|
||||
### Testing
|
||||
- [ ] Unit tests are written
|
||||
- [ ] Tests pass
|
||||
- [ ] Edge cases are covered
|
||||
|
||||
### Documentation
|
||||
- [ ] Functions and classes have TSDoc comments
|
||||
- [ ] Complex logic has comments
|
||||
- [ ] TODOs and FIXMEs are noted (where applicable)
|
||||
|
||||
### Tooling
|
||||
- [ ] No lint errors
|
||||
- [ ] Type checking passes
|
||||
- [ ] Formatting is consistent
|
||||
421
.opencode/skills/development-guidelines/guides/process.md
Normal file
421
.opencode/skills/development-guidelines/guides/process.md
Normal file
@ -0,0 +1,421 @@
|
||||
# Process Guide
|
||||
|
||||
## Basic Principles
|
||||
|
||||
### 1. Include Plenty of Concrete Examples
|
||||
|
||||
Present concrete code examples, not just abstract rules.
|
||||
|
||||
**Bad example**:
|
||||
```
|
||||
Make variable names easy to understand
|
||||
```
|
||||
|
||||
**Good example**:
|
||||
```typescript
|
||||
// ✅ Good: The role is clear
|
||||
const userAuthentication = new UserAuthenticationService();
|
||||
const taskRepository = new TaskRepository();
|
||||
|
||||
// ❌ Bad: Ambiguous
|
||||
const auth = new Service();
|
||||
const repo = new Repository();
|
||||
```
|
||||
|
||||
### 2. Explain the Reasoning
|
||||
|
||||
Make clear "why we do it this way."
|
||||
|
||||
**Example**:
|
||||
```
|
||||
## Don't Ignore Errors
|
||||
|
||||
Reason: Ignoring errors makes it difficult to identify the cause of a problem.
|
||||
Handle expected errors appropriately, and propagate unexpected errors upward
|
||||
so they can be recorded in the logs.
|
||||
```
|
||||
|
||||
### 3. Set Measurable Criteria
|
||||
|
||||
Avoid vague expressions and provide concrete numbers.
|
||||
|
||||
**Bad example**:
|
||||
```
|
||||
Keep code coverage high
|
||||
```
|
||||
|
||||
**Good example**:
|
||||
```
|
||||
Code coverage targets:
|
||||
- Unit tests: 80% or higher
|
||||
- Integration tests: 60% or higher
|
||||
- E2E tests: 100% of the main flows
|
||||
```
|
||||
|
||||
## Git Operation Rules
|
||||
|
||||
### Branching Strategy (Adopting Git Flow)
|
||||
|
||||
**What is Git Flow**:
|
||||
A branching model proposed by Vincent Driessen that systematically manages feature development, releases, and hotfixes. With clearly divided roles, it enables parallel work and stable releases in team development.
|
||||
|
||||
**Branch structure**:
|
||||
```
|
||||
main (production environment)
|
||||
└── develop (development/integration environment)
|
||||
├── feature/* (new feature development)
|
||||
├── fix/* (bug fixes)
|
||||
└── release/* (release preparation) *as needed
|
||||
```
|
||||
|
||||
**Operation rules**:
|
||||
- **main**: Holds only stable code already released to production. Versioned with tags
|
||||
- **develop**: Integrates the latest development code for the next release. Automated tests run in CI
|
||||
- **feature/\*, fix/\***: Branch from develop, and merge into develop via a PR after the work is complete
|
||||
- **No direct commits**: Require PR review on all branches to ensure code quality
|
||||
- **Merge policy**: Recommend squash merge for feature→develop, and a merge commit for develop→main
|
||||
|
||||
**Benefits of Git Flow**:
|
||||
- Branch roles are clear, making parallel development by multiple people easier
|
||||
- The production environment (main) is always kept clean
|
||||
- During emergencies, hotfix branches enable rapid response (introduce as needed)
|
||||
|
||||
### Commit Message Conventions
|
||||
|
||||
**Conventional Commits is recommended**:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body>
|
||||
|
||||
<footer>
|
||||
```
|
||||
|
||||
**List of types**:
|
||||
```
|
||||
feat: New feature (minor version up)
|
||||
fix: Bug fix (patch version up)
|
||||
docs: Documentation
|
||||
style: Formatting (no effect on code behavior)
|
||||
refactor: Refactoring
|
||||
perf: Performance improvement
|
||||
test: Adding or fixing tests
|
||||
build: Build system
|
||||
ci: CI/CD configuration
|
||||
chore: Other (dependency updates, etc.)
|
||||
|
||||
BREAKING CHANGE: Breaking change (major version up)
|
||||
```
|
||||
|
||||
**Example of a good commit message**:
|
||||
|
||||
```
|
||||
feat(task): Add priority-setting feature
|
||||
|
||||
Users can now set a priority (high/medium/low) on tasks.
|
||||
|
||||
Implementation details:
|
||||
- Added a priority field to the Task model
|
||||
- Added a --priority option to the CLI
|
||||
- Implemented sorting by priority
|
||||
|
||||
Breaking changes:
|
||||
- The structure of the Task type has changed
|
||||
- Existing task data requires migration
|
||||
|
||||
Closes #123
|
||||
BREAKING CHANGE: Added a required priority field to the Task type
|
||||
```
|
||||
|
||||
### Pull Request Template
|
||||
|
||||
**An effective PR template**:
|
||||
|
||||
```markdown
|
||||
## Type of Change
|
||||
- [ ] New feature (feat)
|
||||
- [ ] Bug fix (fix)
|
||||
- [ ] Refactoring (refactor)
|
||||
- [ ] Documentation (docs)
|
||||
- [ ] Other (chore)
|
||||
|
||||
## Changes
|
||||
### What was changed
|
||||
[Brief description]
|
||||
|
||||
### Why it was changed
|
||||
[Background and reasoning]
|
||||
|
||||
### How it was changed
|
||||
- [Change 1]
|
||||
- [Change 2]
|
||||
|
||||
## Testing
|
||||
### Tests performed
|
||||
- [ ] Added unit tests
|
||||
- [ ] Added integration tests
|
||||
- [ ] Performed manual testing
|
||||
|
||||
### Test results
|
||||
[Description of the test results]
|
||||
|
||||
## Related Issues
|
||||
Closes #[number]
|
||||
Refs #[number]
|
||||
|
||||
## Review Points
|
||||
[Points you especially want reviewers to look at]
|
||||
```
|
||||
|
||||
## Test Strategy
|
||||
|
||||
### Test Pyramid
|
||||
|
||||
```
|
||||
/\
|
||||
/E2E\ Few (slow, high cost)
|
||||
/------\
|
||||
/ Integ. \ Medium
|
||||
/----------\
|
||||
/ Unit \ Many (fast, low cost)
|
||||
/--------------\
|
||||
```
|
||||
|
||||
**Target ratio**:
|
||||
- Unit tests: 70%
|
||||
- Integration tests: 20%
|
||||
- E2E tests: 10%
|
||||
|
||||
### How to Write Tests
|
||||
|
||||
**Given-When-Then pattern**:
|
||||
|
||||
```typescript
|
||||
describe('TaskService', () => {
|
||||
describe('task creation', () => {
|
||||
it('can create a task with valid data', async () => {
|
||||
// Given: setup
|
||||
const service = new TaskService(mockRepository);
|
||||
const validData = { title: 'Test' };
|
||||
|
||||
// When: execute
|
||||
const result = await service.create(validData);
|
||||
|
||||
// Then: verify
|
||||
expect(result.id).toBeDefined();
|
||||
expect(result.title).toBe('Test');
|
||||
});
|
||||
|
||||
it('throws a ValidationError when the title is empty', async () => {
|
||||
// Given: setup
|
||||
const service = new TaskService(mockRepository);
|
||||
const invalidData = { title: '' };
|
||||
|
||||
// When/Then: execute and verify
|
||||
await expect(
|
||||
service.create(invalidData)
|
||||
).rejects.toThrow(ValidationError);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Coverage Targets
|
||||
|
||||
**Measurable targets**:
|
||||
|
||||
```json
|
||||
// jest.config.js
|
||||
{
|
||||
"coverageThreshold": {
|
||||
"global": {
|
||||
"branches": 80,
|
||||
"functions": 80,
|
||||
"lines": 80,
|
||||
"statements": 80
|
||||
},
|
||||
"./src/services/": {
|
||||
"branches": 90,
|
||||
"functions": 90,
|
||||
"lines": 90,
|
||||
"statements": 90
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Reasoning**:
|
||||
- Critical business logic (services/) requires high coverage
|
||||
- The UI layer is acceptable at a lower level
|
||||
- Don't aim for 100% (balance cost and benefit)
|
||||
|
||||
## Code Review Process
|
||||
|
||||
### Purpose of Review
|
||||
|
||||
1. **Quality assurance**: Early detection of bugs
|
||||
2. **Knowledge sharing**: Understanding the codebase across the whole team
|
||||
3. **Learning opportunity**: Sharing best practices
|
||||
|
||||
### Points for Effective Reviews
|
||||
|
||||
**For reviewers**:
|
||||
|
||||
1. **Constructive feedback**
|
||||
```markdown
|
||||
## ❌ Bad example
|
||||
This code is no good.
|
||||
|
||||
## ✅ Good example
|
||||
This implementation results in O(n²) time complexity.
|
||||
Using a Map can improve it to O(n):
|
||||
|
||||
```typescript
|
||||
const taskMap = new Map(tasks.map(t => [t.id, t]));
|
||||
const result = ids.map(id => taskMap.get(id));
|
||||
```
|
||||
```
|
||||
|
||||
2. **State the priority explicitly**
|
||||
```markdown
|
||||
[Required] Security: A password is being output to the logs
|
||||
[Recommended] Performance: Avoid DB calls inside a loop
|
||||
[Suggestion] Readability: Could this function name be made clearer?
|
||||
[Question] Could you explain the intent of this processing?
|
||||
```
|
||||
|
||||
3. **Positive feedback too**
|
||||
```markdown
|
||||
✨ This implementation is easy to understand!
|
||||
👍 Edge cases are thoroughly considered
|
||||
💡 This pattern looks reusable elsewhere
|
||||
```
|
||||
|
||||
**For reviewees**:
|
||||
|
||||
1. **Perform a self-review**
|
||||
- Review your own code before creating the PR
|
||||
- Add comments where explanation is needed
|
||||
|
||||
2. **Aim for small PRs**
|
||||
- 1 PR = 1 feature
|
||||
- Number of changed files: 10 or fewer recommended
|
||||
- Number of changed lines: 300 or fewer recommended
|
||||
|
||||
3. **Explain carefully**
|
||||
- Why you chose this implementation
|
||||
- Alternatives you considered
|
||||
- Points you especially want reviewed
|
||||
|
||||
### Review Time Guidelines
|
||||
|
||||
- Small PR (100 lines or fewer): 15 minutes
|
||||
- Medium PR (100-300 lines): 30 minutes
|
||||
- Large PR (300 lines or more): 1 hour or more
|
||||
|
||||
**Principle**: Avoid large PRs; split them up
|
||||
|
||||
## Promoting Automation (Where Applicable)
|
||||
|
||||
### Automating Quality Checks
|
||||
|
||||
**Automation items and the tools adopted**:
|
||||
|
||||
1. **Lint checks**
|
||||
- **ESLint 9.x** + **@typescript-eslint**
|
||||
- Unifies coding conventions with a TypeScript-specific rule set
|
||||
- Automatically detects potential bugs and deprecated patterns
|
||||
- Configuration file: `eslint.config.js` (Flat Config format)
|
||||
|
||||
2. **Code formatting**
|
||||
- **Prettier 3.x**
|
||||
- Automatically formats code style, reducing debate during review
|
||||
- Used together with ESLint, avoiding conflicts via `eslint-config-prettier`
|
||||
- Configuration file: `.prettierrc`
|
||||
|
||||
3. **Type checking**
|
||||
- **TypeScript Compiler (tsc) 5.x**
|
||||
- Checks only type errors with `tsc --noEmit`
|
||||
- Verifies type safety independently of the build
|
||||
- Configuration file: `tsconfig.json`
|
||||
|
||||
4. **Running tests**
|
||||
- **Vitest 2.x**
|
||||
- Fast startup and execution based on Vite
|
||||
- Natively supports TypeScript/ESM and works with zero configuration
|
||||
- Coverage measurement (@vitest/coverage-v8) is built in as standard
|
||||
- Modern development experience with HMR support
|
||||
|
||||
5. **Build verification**
|
||||
- **TypeScript Compiler (tsc)**
|
||||
- Guarantees a type-checked build with the standard compiler
|
||||
- Simple configuration with no additional tools required
|
||||
- Centralizes output settings in `tsconfig.json`
|
||||
|
||||
**Implementation methods**:
|
||||
|
||||
**1. CI/CD (GitHub Actions)**
|
||||
```yaml
|
||||
# .github/workflows/ci.yml
|
||||
name: CI
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '24'
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
- run: npm run typecheck
|
||||
- run: npm run test
|
||||
- run: npm run build
|
||||
```
|
||||
|
||||
**2. Pre-commit hooks (Husky 9.x + lint-staged)**
|
||||
```json
|
||||
// package.json
|
||||
{
|
||||
"scripts": {
|
||||
"prepare": "husky",
|
||||
"lint": "eslint .",
|
||||
"format": "prettier --write .",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "vitest run",
|
||||
"build": "tsc"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": [
|
||||
"eslint --fix",
|
||||
"prettier --write"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
```bash
|
||||
# .husky/pre-commit
|
||||
npm run lint-staged
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
**Effects of adoption**:
|
||||
- Automated checks run before committing, preventing defective code from being introduced
|
||||
- CI runs automatically when a PR is created, ensuring quality before merging
|
||||
- Early detection reduces fix costs by up to 80% (compared to when bugs are found after production)
|
||||
|
||||
**Why this configuration was chosen**:
|
||||
- A standard and modern configuration in the TypeScript ecosystem as of 2025
|
||||
- High compatibility between tools, with few configuration conflicts
|
||||
- An excellent balance between development experience and execution speed
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] A branching strategy is decided
|
||||
- [ ] Commit message conventions are clear
|
||||
- [ ] A PR template is prepared
|
||||
- [ ] Test types and coverage targets are set
|
||||
- [ ] A code review process is defined
|
||||
- [ ] A CI/CD pipeline is built
|
||||
410
.opencode/skills/development-guidelines/template.md
Normal file
410
.opencode/skills/development-guidelines/template.md
Normal file
@ -0,0 +1,410 @@
|
||||
# Development Guidelines
|
||||
|
||||
## Coding Conventions
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
#### Variables and Functions
|
||||
|
||||
**TypeScript/JavaScript**:
|
||||
```typescript
|
||||
// ✅ Good example
|
||||
const userProfileData = fetchUserProfile();
|
||||
function calculateTotalPrice(items: CartItem[]): number { }
|
||||
|
||||
// ❌ Bad example
|
||||
const data = fetch();
|
||||
function calc(arr: any[]): number { }
|
||||
```
|
||||
|
||||
**Principles**:
|
||||
- Variables: camelCase, noun or noun phrase
|
||||
- Functions: camelCase, start with a verb
|
||||
- Constants: UPPER_SNAKE_CASE
|
||||
- Boolean: start with `is`, `has`, or `should`
|
||||
|
||||
#### Classes and Interfaces
|
||||
|
||||
```typescript
|
||||
// Class: PascalCase, noun
|
||||
class TaskManager { }
|
||||
class UserAuthenticationService { }
|
||||
|
||||
// Interface: PascalCase, with or without the I prefix
|
||||
interface ITaskRepository { }
|
||||
interface Task { }
|
||||
|
||||
// Type alias: PascalCase
|
||||
type TaskStatus = 'todo' | 'in_progress' | 'completed';
|
||||
```
|
||||
|
||||
### Code Formatting
|
||||
|
||||
**Indentation**: [2 spaces / 4 spaces / tabs]
|
||||
|
||||
**Line length**: maximum [80/100/120] characters
|
||||
|
||||
**Example**:
|
||||
```typescript
|
||||
// [language] code formatting example
|
||||
[code example]
|
||||
```
|
||||
|
||||
### Comment Conventions
|
||||
|
||||
**Function and class documentation**:
|
||||
```typescript
|
||||
/**
|
||||
* Calculate the total number of tasks
|
||||
*
|
||||
* @param tasks - Array of tasks to count
|
||||
* @param filter - Filter condition (optional)
|
||||
* @returns Total number of tasks
|
||||
* @throws {ValidationError} When the task array is invalid
|
||||
*/
|
||||
function countTasks(
|
||||
tasks: Task[],
|
||||
filter?: TaskFilter
|
||||
): number {
|
||||
// Implementation
|
||||
}
|
||||
```
|
||||
|
||||
**Inline comments**:
|
||||
```typescript
|
||||
// ✅ Good example: explain why you do it
|
||||
// Invalidate the cache to fetch the latest data
|
||||
cache.clear();
|
||||
|
||||
// ❌ Bad example: what you are doing (obvious from the code)
|
||||
// Clear the cache
|
||||
cache.clear();
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
**Principles**:
|
||||
- Expected errors: define an appropriate error class
|
||||
- Unexpected errors: propagate upward
|
||||
- Do not ignore errors
|
||||
|
||||
**Example**:
|
||||
```typescript
|
||||
// Error class definition
|
||||
class ValidationError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public field: string,
|
||||
public value: unknown
|
||||
) {
|
||||
super(message);
|
||||
this.name = 'ValidationError';
|
||||
}
|
||||
}
|
||||
|
||||
// Error handling
|
||||
try {
|
||||
const task = await taskService.create(data);
|
||||
} catch (error) {
|
||||
if (error instanceof ValidationError) {
|
||||
console.error(`Validation error [${error.field}]: ${error.message}`);
|
||||
// Provide feedback to the user
|
||||
} else {
|
||||
console.error('Unexpected error:', error);
|
||||
throw error; // Propagate upward
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Git Workflow Rules
|
||||
|
||||
### Branching Strategy
|
||||
|
||||
**Branch types**:
|
||||
- `main`: ready to deploy to production
|
||||
- `develop`: latest development state
|
||||
- `feature/[feature-name]`: new feature development
|
||||
- `fix/[fix-description]`: bug fixes
|
||||
- `refactor/[target]`: refactoring
|
||||
|
||||
**Flow**:
|
||||
```
|
||||
main
|
||||
└─ develop
|
||||
├─ feature/task-management
|
||||
├─ feature/user-auth
|
||||
└─ fix/task-validation
|
||||
```
|
||||
|
||||
### Commit Message Conventions
|
||||
|
||||
**Format**:
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body>
|
||||
|
||||
<footer>
|
||||
```
|
||||
|
||||
**Type**:
|
||||
- `feat`: new feature
|
||||
- `fix`: bug fix
|
||||
- `docs`: documentation
|
||||
- `style`: code formatting
|
||||
- `refactor`: refactoring
|
||||
- `test`: adding or fixing tests
|
||||
- `chore`: build, supporting tools, etc.
|
||||
|
||||
**Example**:
|
||||
```
|
||||
feat(task): add a task priority setting feature
|
||||
|
||||
Allowed users to set a priority (high/medium/low) on tasks.
|
||||
- Added a priority field to the Task model
|
||||
- Added a --priority option to the CLI
|
||||
- Implemented sorting by priority
|
||||
|
||||
Closes #123
|
||||
```
|
||||
|
||||
### Pull Request Process
|
||||
|
||||
**Checks before creating**:
|
||||
- [ ] All tests pass
|
||||
- [ ] No lint errors
|
||||
- [ ] Type checking passes
|
||||
- [ ] Conflicts are resolved
|
||||
|
||||
**PR template**:
|
||||
```markdown
|
||||
## Overview
|
||||
[A brief description of the changes]
|
||||
|
||||
## Reason for Change
|
||||
[Why this change is necessary]
|
||||
|
||||
## Changes
|
||||
- [change 1]
|
||||
- [change 2]
|
||||
|
||||
## Testing
|
||||
- [ ] Unit tests added
|
||||
- [ ] Manual testing performed
|
||||
|
||||
## Screenshots (if applicable)
|
||||
[image]
|
||||
|
||||
## Related Issue
|
||||
Closes #[issue number]
|
||||
```
|
||||
|
||||
**Review process**:
|
||||
1. Self-review
|
||||
2. Run automated tests
|
||||
3. Assign reviewers
|
||||
4. Address review feedback
|
||||
5. Merge after approval
|
||||
|
||||
## Test Strategy
|
||||
|
||||
### Test Types
|
||||
|
||||
#### Unit Tests
|
||||
|
||||
**Target**: individual functions and classes
|
||||
|
||||
**Coverage target**: [80/90/100]%
|
||||
|
||||
**Example**:
|
||||
```typescript
|
||||
describe('TaskService', () => {
|
||||
describe('create', () => {
|
||||
it('can create a task with valid data', async () => {
|
||||
const service = new TaskService(mockRepository);
|
||||
const task = await service.create({
|
||||
title: 'Test task',
|
||||
description: 'Description',
|
||||
});
|
||||
|
||||
expect(task.id).toBeDefined();
|
||||
expect(task.title).toBe('Test task');
|
||||
});
|
||||
|
||||
it('throws ValidationError when the title is empty', async () => {
|
||||
const service = new TaskService(mockRepository);
|
||||
|
||||
await expect(
|
||||
service.create({ title: '' })
|
||||
).rejects.toThrow(ValidationError);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Integration Tests
|
||||
|
||||
**Target**: coordination of multiple components
|
||||
|
||||
**Example**:
|
||||
```typescript
|
||||
describe('Task CRUD', () => {
|
||||
it('can create, read, update, and delete a task', async () => {
|
||||
// Create
|
||||
const created = await taskService.create({ title: 'Test' });
|
||||
|
||||
// Read
|
||||
const found = await taskService.findById(created.id);
|
||||
expect(found?.title).toBe('Test');
|
||||
|
||||
// Update
|
||||
await taskService.update(created.id, { title: 'Updated' });
|
||||
const updated = await taskService.findById(created.id);
|
||||
expect(updated?.title).toBe('Updated');
|
||||
|
||||
// Delete
|
||||
await taskService.delete(created.id);
|
||||
const deleted = await taskService.findById(created.id);
|
||||
expect(deleted).toBeNull();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### E2E Tests
|
||||
|
||||
**Target**: the entire user scenario
|
||||
|
||||
**Example**:
|
||||
```typescript
|
||||
describe('Task management flow', () => {
|
||||
it('a user can add and complete a task', async () => {
|
||||
// Add a task
|
||||
await cli.run(['add', 'New task']);
|
||||
expect(output).toContain('Task added');
|
||||
|
||||
// Display the task list
|
||||
await cli.run(['list']);
|
||||
expect(output).toContain('New task');
|
||||
|
||||
// Complete the task
|
||||
await cli.run(['complete', '1']);
|
||||
expect(output).toContain('Task completed');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Test Naming Conventions
|
||||
|
||||
**Pattern**: `[target]_[condition]_[expectedResult]`
|
||||
|
||||
**Example**:
|
||||
```typescript
|
||||
// ✅ Good example
|
||||
it('create_emptyTitle_throwsValidationError', () => { });
|
||||
it('findById_existingId_returnsTask', () => { });
|
||||
it('delete_nonExistentId_throwsNotFoundError', () => { });
|
||||
|
||||
// ❌ Bad example
|
||||
it('test1', () => { });
|
||||
it('works', () => { });
|
||||
it('should work correctly', () => { });
|
||||
```
|
||||
|
||||
### Using Mocks and Stubs
|
||||
|
||||
**Principles**:
|
||||
- Mock external dependencies (API, DB, file system)
|
||||
- Use the real implementation for business logic
|
||||
|
||||
**Example**:
|
||||
```typescript
|
||||
// Mock the repository
|
||||
const mockRepository: ITaskRepository = {
|
||||
save: jest.fn(),
|
||||
findById: jest.fn(),
|
||||
findAll: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
};
|
||||
|
||||
// The service uses the real implementation
|
||||
const service = new TaskService(mockRepository);
|
||||
```
|
||||
|
||||
## Code Review Criteria
|
||||
|
||||
### Review Points
|
||||
|
||||
**Functionality**:
|
||||
- [ ] Does it meet the requirements?
|
||||
- [ ] Are edge cases considered?
|
||||
- [ ] Is error handling appropriate?
|
||||
|
||||
**Readability**:
|
||||
- [ ] Is the naming clear?
|
||||
- [ ] Are the comments appropriate?
|
||||
- [ ] Is complex logic explained?
|
||||
|
||||
**Maintainability**:
|
||||
- [ ] Is there any duplicate code?
|
||||
- [ ] Are responsibilities clearly separated?
|
||||
- [ ] Is the impact scope of changes limited?
|
||||
|
||||
**Performance**:
|
||||
- [ ] Are there any unnecessary computations?
|
||||
- [ ] Is there any possibility of a memory leak?
|
||||
- [ ] Are database queries optimized?
|
||||
|
||||
**Security**:
|
||||
- [ ] Is input validation appropriate?
|
||||
- [ ] Is any sensitive information hardcoded?
|
||||
- [ ] Are permission checks implemented?
|
||||
|
||||
### How to Write Review Comments
|
||||
|
||||
**Constructive feedback**:
|
||||
```markdown
|
||||
## ✅ Good example
|
||||
With this implementation, performance may degrade as the number of tasks grows.
|
||||
How about considering a search that uses an index instead?
|
||||
|
||||
## ❌ Bad example
|
||||
This way of writing it is not good.
|
||||
```
|
||||
|
||||
**Indicate priority**:
|
||||
- `[required]`: must be fixed
|
||||
- `[recommended]`: fix recommended
|
||||
- `[suggestion]`: please consider
|
||||
- `[question]`: a question for understanding
|
||||
|
||||
## Development Environment Setup
|
||||
|
||||
### Required Tools
|
||||
|
||||
| Tool | Version | Installation method |
|
||||
|--------|-----------|-----------------|
|
||||
| [tool 1] | [version] | [command] |
|
||||
| [tool 2] | [version] | [command] |
|
||||
|
||||
### Setup Procedure
|
||||
|
||||
```bash
|
||||
# 1. Clone the repository
|
||||
git clone [URL]
|
||||
cd [project-name]
|
||||
|
||||
# 2. Install dependencies
|
||||
[install command]
|
||||
|
||||
# 3. Set environment variables
|
||||
cp .env.example .env
|
||||
# Edit the .env file
|
||||
|
||||
# 4. Start the development server
|
||||
[start command]
|
||||
```
|
||||
|
||||
### Recommended Development Tools (if applicable)
|
||||
|
||||
- [tool 1]: [description]
|
||||
- [tool 2]: [description]
|
||||
52
.opencode/skills/functional-design/SKILL.md
Normal file
52
.opencode/skills/functional-design/SKILL.md
Normal file
@ -0,0 +1,52 @@
|
||||
---
|
||||
name: functional-design
|
||||
description: Detailed guide and template for creating a functional design document. Use only when creating a functional design document.
|
||||
---
|
||||
|
||||
# Functional Design Document Creation Skill
|
||||
|
||||
This skill is a detailed guide for creating high-quality functional design documents.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting to create a functional design document, confirm the following:
|
||||
|
||||
### docs/product-requirements.md has been created
|
||||
|
||||
**Required**: The PRD must exist at the following location:
|
||||
|
||||
**File path**: `docs/product-requirements.md`
|
||||
|
||||
The functional design document details how to technically realize the requirements defined in the PRD.
|
||||
|
||||
## Priority of Existing Documents
|
||||
|
||||
**Important**: If an existing functional design document is present at `docs/functional-design.md`,
|
||||
follow the priority order below:
|
||||
|
||||
1. **Existing functional design document (`docs/functional-design.md`)** - Highest priority
|
||||
- Contains project-specific design
|
||||
- Takes precedence over this skill's guide
|
||||
|
||||
2. **This skill's guide** - Reference material
|
||||
- Generic templates and examples
|
||||
- Use when no existing design document exists, or as a supplement
|
||||
|
||||
**When creating new**: Refer to this skill's template and guide
|
||||
**When updating**: Update while maintaining the structure and content of the existing design document
|
||||
|
||||
## Output Destination
|
||||
|
||||
Save the created functional design document to the following location:
|
||||
|
||||
```
|
||||
docs/functional-design.md
|
||||
```
|
||||
|
||||
## Template Reference
|
||||
|
||||
When creating a functional design document, use the following template: ./template.md
|
||||
|
||||
## Detailed Guide
|
||||
|
||||
For a more detailed creation guide, refer to the following file: ./guide.md
|
||||
470
.opencode/skills/functional-design/guide.md
Normal file
470
.opencode/skills/functional-design/guide.md
Normal file
@ -0,0 +1,470 @@
|
||||
# Functional Design Document Creation Guide
|
||||
|
||||
This guide provides practical guidance for creating a functional design document based on a Product Requirements Document (PRD).
|
||||
|
||||
## Purpose of the Functional Design Document
|
||||
|
||||
The functional design document translates the "what to build" defined in the PRD into "how to realize it".
|
||||
|
||||
**Main Content**:
|
||||
- System architecture diagram
|
||||
- Data model
|
||||
- Component design
|
||||
- Algorithm design (if applicable)
|
||||
- UI design
|
||||
- Error handling
|
||||
|
||||
## Basic Creation Flow
|
||||
|
||||
### Step 1: Review the PRD
|
||||
|
||||
Before creating the functional design document, always review the PRD.
|
||||
|
||||
```
|
||||
Example prompt for having opencode create a functional design document from the PRD:
|
||||
|
||||
Create a functional design document based on the content of the PRD.
|
||||
In particular, focus on the priority P0 (MVP) features.
|
||||
```
|
||||
|
||||
### Step 2: Create the System Architecture Diagram
|
||||
|
||||
#### Using Mermaid Notation
|
||||
|
||||
Write the system architecture diagram using Mermaid notation.
|
||||
|
||||
**Example of a basic 3-tier architecture**:
|
||||
```mermaid
|
||||
graph TB
|
||||
User[User]
|
||||
CLI[CLI Layer]
|
||||
Service[Service Layer]
|
||||
Data[Data Layer]
|
||||
|
||||
User --> CLI
|
||||
CLI --> Service
|
||||
Service --> Data
|
||||
```
|
||||
|
||||
**A more detailed example**:
|
||||
```mermaid
|
||||
graph TB
|
||||
User[User]
|
||||
CLI[CLI Interface]
|
||||
Commander[Commander.js]
|
||||
TaskManager[TaskManager]
|
||||
PriorityEstimator[PriorityEstimator]
|
||||
FileStorage[FileStorage]
|
||||
JSON[(tasks.json)]
|
||||
|
||||
User --> CLI
|
||||
CLI --> Commander
|
||||
Commander --> TaskManager
|
||||
TaskManager --> PriorityEstimator
|
||||
TaskManager --> FileStorage
|
||||
FileStorage --> JSON
|
||||
```
|
||||
|
||||
### Step 3: Define the Data Model
|
||||
|
||||
#### Define Clearly with TypeScript Type Definitions
|
||||
|
||||
Define the data model using TypeScript interfaces.
|
||||
|
||||
**Example of a basic Task type**:
|
||||
```typescript
|
||||
interface Task {
|
||||
id: string; // UUID v4
|
||||
title: string; // 1-200 characters
|
||||
description?: string; // Optional, Markdown format
|
||||
status: TaskStatus; // 'todo' | 'in_progress' | 'completed'
|
||||
priority: TaskPriority; // 'high' | 'medium' | 'low'
|
||||
estimatedPriority?: TaskPriority; // Automatically estimated priority
|
||||
dueDate?: Date; // Due date
|
||||
createdAt: Date; // Creation timestamp
|
||||
updatedAt: Date; // Update timestamp
|
||||
statusHistory?: StatusChange[]; // Status change history
|
||||
}
|
||||
|
||||
type TaskStatus = 'todo' | 'in_progress' | 'completed';
|
||||
type TaskPriority = 'high' | 'medium' | 'low';
|
||||
|
||||
interface StatusChange {
|
||||
from: TaskStatus;
|
||||
to: TaskStatus;
|
||||
changedAt: Date;
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
- Add a comment explaining each field
|
||||
- Clearly note constraints (character count, format, etc.)
|
||||
- Add `?` to optional fields
|
||||
- Improve readability with type aliases
|
||||
|
||||
#### Creating an ER Diagram
|
||||
|
||||
When there are multiple entities, show the relationships with an ER diagram.
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
TASK ||--o{ SUBTASK : has
|
||||
TASK ||--o{ TAG : has
|
||||
USER ||--o{ TASK : creates
|
||||
|
||||
TASK {
|
||||
string id PK
|
||||
string title
|
||||
string status
|
||||
datetime createdAt
|
||||
}
|
||||
SUBTASK {
|
||||
string id PK
|
||||
string taskId FK
|
||||
string title
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Component Design
|
||||
|
||||
Clarify the responsibilities of each layer.
|
||||
|
||||
#### CLI Layer
|
||||
|
||||
**Responsibility**: Accept user input, validation, display results
|
||||
|
||||
```typescript
|
||||
// CommandLineInterface
|
||||
class CLI {
|
||||
// Accept user input
|
||||
parseArguments(): Command;
|
||||
|
||||
// Display results
|
||||
displayResult(result: Result): void;
|
||||
|
||||
// Display errors
|
||||
displayError(error: Error): void;
|
||||
}
|
||||
```
|
||||
|
||||
#### Service Layer
|
||||
|
||||
**Responsibility**: Implement business logic
|
||||
|
||||
```typescript
|
||||
// TaskManager
|
||||
class TaskManager {
|
||||
// Create a task
|
||||
createTask(data: CreateTaskData): Task;
|
||||
|
||||
// Get the task list
|
||||
listTasks(filter?: FilterOptions): Task[];
|
||||
|
||||
// Update a task
|
||||
updateTask(id: string, data: UpdateTaskData): Task;
|
||||
|
||||
// Delete a task
|
||||
deleteTask(id: string): void;
|
||||
}
|
||||
```
|
||||
|
||||
#### Data Layer
|
||||
|
||||
**Responsibility**: Data persistence and retrieval
|
||||
|
||||
```typescript
|
||||
// FileStorage
|
||||
class FileStorage {
|
||||
// Save data
|
||||
save(data: any): void;
|
||||
|
||||
// Load data
|
||||
load(): any;
|
||||
|
||||
// Check whether the file exists
|
||||
exists(): boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Algorithm Design (if applicable)
|
||||
|
||||
Design complex logic (e.g., automatic priority estimation) in detail.
|
||||
|
||||
#### Example of an Automatic Priority Estimation Algorithm
|
||||
|
||||
**Purpose**: Automatically estimate priority from a task's due date, creation timestamp, and status
|
||||
|
||||
**Calculation Logic**:
|
||||
|
||||
##### Step 1: Deadline Score Calculation (0-100 points)
|
||||
```
|
||||
- Overdue: 100 points (highest)
|
||||
- 0-3 days until due: 90 points
|
||||
- 4-7 days until due: 70 points
|
||||
- 8-14 days until due: 50 points
|
||||
- 14 or more days until due: 30 points
|
||||
- No due date set: 20 points
|
||||
```
|
||||
|
||||
**Formula**:
|
||||
```typescript
|
||||
function calculateDeadlineScore(dueDate?: Date): number {
|
||||
if (!dueDate) return 20;
|
||||
|
||||
const now = new Date();
|
||||
const daysRemaining = Math.floor((dueDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (daysRemaining < 0) return 100; // Overdue
|
||||
if (daysRemaining <= 3) return 90;
|
||||
if (daysRemaining <= 7) return 70;
|
||||
if (daysRemaining <= 14) return 50;
|
||||
return 30;
|
||||
}
|
||||
```
|
||||
|
||||
##### Step 2: Elapsed Time Score Calculation (0-100 points)
|
||||
```
|
||||
- 30 or more days since creation: 100 points (highest)
|
||||
- 21-30 days since creation: 80 points
|
||||
- 14-21 days since creation: 60 points
|
||||
- 7-14 days since creation: 40 points
|
||||
- Less than 7 days since creation: 20 points
|
||||
```
|
||||
|
||||
**Formula**:
|
||||
```typescript
|
||||
function calculateAgeScore(createdAt: Date): number {
|
||||
const now = new Date();
|
||||
const daysOld = Math.floor((now.getTime() - createdAt.getTime()) / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (daysOld >= 30) return 100;
|
||||
if (daysOld >= 21) return 80;
|
||||
if (daysOld >= 14) return 60;
|
||||
if (daysOld >= 7) return 40;
|
||||
return 20;
|
||||
}
|
||||
```
|
||||
|
||||
##### Step 3: Status Score Calculation (0-100 points)
|
||||
```
|
||||
- In progress (in_progress): 100 points (highest priority)
|
||||
- Not started (todo): 50 points
|
||||
- Completed (completed): 0 points
|
||||
```
|
||||
|
||||
**Formula**:
|
||||
```typescript
|
||||
function calculateStatusScore(status: TaskStatus): number {
|
||||
if (status === 'in_progress') return 100;
|
||||
if (status === 'todo') return 50;
|
||||
return 0; // completed
|
||||
}
|
||||
```
|
||||
|
||||
##### Step 4: Total Score Calculation
|
||||
|
||||
**Weighted Average**:
|
||||
```
|
||||
Total Score = (Deadline Score × 50%) + (Elapsed Time Score × 20%) + (Status Score × 30%)
|
||||
```
|
||||
|
||||
**Formula**:
|
||||
```typescript
|
||||
function calculateTotalScore(task: Task): number {
|
||||
const deadlineScore = calculateDeadlineScore(task.dueDate);
|
||||
const ageScore = calculateAgeScore(task.createdAt);
|
||||
const statusScore = calculateStatusScore(task.status);
|
||||
|
||||
return (deadlineScore * 0.5) + (ageScore * 0.2) + (statusScore * 0.3);
|
||||
}
|
||||
```
|
||||
|
||||
##### Step 5: Priority Classification
|
||||
|
||||
**Classification by Threshold**:
|
||||
```
|
||||
- 70 points or more: high (high priority)
|
||||
- 40-70 points: medium (medium priority)
|
||||
- Less than 40 points: low (low priority)
|
||||
```
|
||||
|
||||
**Formula**:
|
||||
```typescript
|
||||
function estimatePriority(task: Task): TaskPriority {
|
||||
const score = calculateTotalScore(task);
|
||||
|
||||
if (score >= 70) return 'high';
|
||||
if (score >= 40) return 'medium';
|
||||
return 'low';
|
||||
}
|
||||
```
|
||||
|
||||
**Complete Implementation Example**:
|
||||
```typescript
|
||||
class PriorityEstimator {
|
||||
estimate(task: Task): TaskPriority {
|
||||
const deadlineScore = this.calculateDeadlineScore(task.dueDate);
|
||||
const ageScore = this.calculateAgeScore(task.createdAt);
|
||||
const statusScore = this.calculateStatusScore(task.status);
|
||||
|
||||
const totalScore = (deadlineScore * 0.5) + (ageScore * 0.2) + (statusScore * 0.3);
|
||||
|
||||
if (totalScore >= 70) return 'high';
|
||||
if (totalScore >= 40) return 'medium';
|
||||
return 'low';
|
||||
}
|
||||
|
||||
private calculateDeadlineScore(dueDate?: Date): number {
|
||||
if (!dueDate) return 20;
|
||||
|
||||
const now = new Date();
|
||||
const daysRemaining = Math.floor((dueDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (daysRemaining < 0) return 100;
|
||||
if (daysRemaining <= 3) return 90;
|
||||
if (daysRemaining <= 7) return 70;
|
||||
if (daysRemaining <= 14) return 50;
|
||||
return 30;
|
||||
}
|
||||
|
||||
private calculateAgeScore(createdAt: Date): number {
|
||||
const now = new Date();
|
||||
const daysOld = Math.floor((now.getTime() - createdAt.getTime()) / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (daysOld >= 30) return 100;
|
||||
if (daysOld >= 21) return 80;
|
||||
if (daysOld >= 14) return 60;
|
||||
if (daysOld >= 7) return 40;
|
||||
return 20;
|
||||
}
|
||||
|
||||
private calculateStatusScore(status: TaskStatus): number {
|
||||
if (status === 'in_progress') return 100;
|
||||
if (status === 'todo') return 50;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 6: Use Case Diagram
|
||||
|
||||
Express the main use cases with sequence diagrams.
|
||||
|
||||
**Task Addition Flow**:
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant CLI
|
||||
participant TaskManager
|
||||
participant PriorityEstimator
|
||||
participant FileStorage
|
||||
|
||||
User->>CLI: devtask add "task"
|
||||
CLI->>CLI: Validate input
|
||||
CLI->>TaskManager: createTask(data)
|
||||
TaskManager->>TaskManager: Create task object
|
||||
TaskManager->>PriorityEstimator: estimate(task)
|
||||
PriorityEstimator-->>TaskManager: Estimated priority
|
||||
TaskManager->>FileStorage: save(task)
|
||||
FileStorage-->>TaskManager: Success
|
||||
TaskManager-->>CLI: Created task
|
||||
CLI-->>User: "Task created (ID: xxx)"
|
||||
```
|
||||
|
||||
### Step 7: UI Design (if applicable)
|
||||
|
||||
For CLI tools, define table display and color coding.
|
||||
|
||||
#### Table Display
|
||||
|
||||
```
|
||||
┌──────────┬──────────────────┬────────────┬──────────┬───────────────┐
|
||||
│ ID │ Title │ Status │ Priority │ Due Date │
|
||||
├──────────┼──────────────────┼────────────┼──────────┼───────────────┤
|
||||
│ 7a5c6ff0 │ Buy milk on the │ Not started│ High │ 2025-11-05 │
|
||||
│ │ way home. │ │ │ (1 day left) │
|
||||
└──────────┴──────────────────┴────────────┴──────────┴───────────────┘
|
||||
```
|
||||
|
||||
#### Color Coding
|
||||
|
||||
**Status Color Coding**:
|
||||
- Completed (completed): green
|
||||
- In progress (in_progress): yellow
|
||||
- Not started (todo): white
|
||||
|
||||
**Priority Color Coding**:
|
||||
- High (high): red
|
||||
- Medium (medium): yellow
|
||||
- Low (low): blue
|
||||
|
||||
### Step 8: File Structure (if applicable)
|
||||
|
||||
Define the data storage format.
|
||||
|
||||
**Example: Data storage for a CLI tool**:
|
||||
```
|
||||
.devtask/
|
||||
├── tasks.json # Task data
|
||||
└── config.json # Configuration data
|
||||
```
|
||||
|
||||
**Example of tasks.json**:
|
||||
```json
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"id": "7a5c6ff0-5f55-474e-baf7-ea13624d73a4",
|
||||
"title": "Buy milk on the way home",
|
||||
"description": "",
|
||||
"status": "todo",
|
||||
"priority": "high",
|
||||
"estimatedPriority": "medium",
|
||||
"dueDate": "2025-11-05T00:00:00.000Z",
|
||||
"createdAt": "2025-11-04T10:00:00.000Z",
|
||||
"updatedAt": "2025-11-04T10:00:00.000Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Step 9: Error Handling
|
||||
|
||||
Define the types of errors and how to handle them.
|
||||
|
||||
| Error Category | Handling | Display to User |
|
||||
|-----------|------|-----------------|
|
||||
| Input validation error | Abort processing, display error message | "Please enter a title of 1-200 characters" |
|
||||
| File read error | Continue with empty initial data | "Data file not found. Creating a new one" |
|
||||
| Task not found | Abort processing, display error message | "Task not found (ID: xxx)" |
|
||||
|
||||
## Reviewing the Functional Design Document
|
||||
|
||||
### Review Perspectives
|
||||
|
||||
Request a review from opencode:
|
||||
|
||||
```
|
||||
Please evaluate this functional design document. Check it from the following perspectives:
|
||||
|
||||
1. Does it satisfy the requirements of the PRD?
|
||||
2. Is the data model concrete?
|
||||
3. Are the responsibilities of the components clear?
|
||||
4. Is the algorithm detailed to an implementable level?
|
||||
5. Is error handling comprehensive?
|
||||
```
|
||||
|
||||
### Implementing Improvements
|
||||
|
||||
Make improvements based on opencode's feedback.
|
||||
|
||||
## Summary
|
||||
|
||||
Keys to successfully creating a functional design document:
|
||||
|
||||
1. **Consistency with the PRD**: Accurately reflect the requirements defined in the PRD
|
||||
2. **Leverage Mermaid notation**: Express things visually with diagrams
|
||||
3. **TypeScript type definitions**: Make the data model clear
|
||||
4. **Detailed algorithm design**: Be concrete about complex logic
|
||||
5. **Layer separation**: Clarify the responsibilities of each component
|
||||
6. **Implementable level**: A level of detail that lets developers implement without confusion
|
||||
262
.opencode/skills/functional-design/template.md
Normal file
262
.opencode/skills/functional-design/template.md
Normal file
@ -0,0 +1,262 @@
|
||||
# Functional Design Document
|
||||
|
||||
## System Architecture Diagram
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
User[User]
|
||||
CLI[CLI Layer]
|
||||
Service[Service Layer]
|
||||
Data[Data Layer]
|
||||
|
||||
User --> CLI
|
||||
CLI --> Service
|
||||
Service --> Data
|
||||
```
|
||||
|
||||
## Technology Stack
|
||||
|
||||
| Category | Technology | Selection Rationale |
|
||||
|------|------|----------|
|
||||
| Language | [Language name] | [Rationale] |
|
||||
| Framework | [Name] | [Rationale] |
|
||||
| Database | [Name] | [Rationale] |
|
||||
| Tools | [Name] | [Rationale] |
|
||||
|
||||
## Data Model Definition
|
||||
|
||||
### Entity: [Entity Name]
|
||||
|
||||
```typescript
|
||||
interface [EntityName] {
|
||||
id: string; // UUID
|
||||
[field1]: [type]; // [description]
|
||||
[field2]: [type]; // [description]
|
||||
createdAt: Date; // Creation timestamp
|
||||
updatedAt: Date; // Update timestamp
|
||||
}
|
||||
```
|
||||
|
||||
**Constraints**:
|
||||
- [Constraint 1]
|
||||
- [Constraint 2]
|
||||
|
||||
### ER Diagram
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
ENTITY1 ||--o{ ENTITY2 : has
|
||||
ENTITY1 {
|
||||
string id PK
|
||||
string field1
|
||||
datetime createdAt
|
||||
}
|
||||
ENTITY2 {
|
||||
string id PK
|
||||
string entity1Id FK
|
||||
string field1
|
||||
}
|
||||
```
|
||||
|
||||
## Component Design
|
||||
|
||||
### [Component 1]
|
||||
|
||||
**Responsibilities**:
|
||||
- [Responsibility 1]
|
||||
- [Responsibility 2]
|
||||
|
||||
**Interface**:
|
||||
```typescript
|
||||
class [ComponentName] {
|
||||
[method1]([params]): [return];
|
||||
[method2]([params]): [return];
|
||||
}
|
||||
```
|
||||
|
||||
**Dependencies**:
|
||||
- [Dependency 1]
|
||||
- [Dependency 2]
|
||||
|
||||
## Use Case Diagram
|
||||
|
||||
### [Use Case 1]
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant CLI
|
||||
participant Service
|
||||
participant Data
|
||||
|
||||
User->>CLI: [action1]
|
||||
CLI->>Service: [action2]
|
||||
Service->>Data: [action3]
|
||||
Data-->>Service: [response]
|
||||
Service-->>CLI: [response]
|
||||
CLI-->>User: [result]
|
||||
```
|
||||
|
||||
**Flow Description**:
|
||||
1. [Step 1]
|
||||
2. [Step 2]
|
||||
3. [Step 3]
|
||||
|
||||
## Screen Transition Diagram (if applicable)
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> State1
|
||||
State1 --> State2: [action]
|
||||
State2 --> State3: [action]
|
||||
State3 --> [*]
|
||||
```
|
||||
|
||||
## API Design (if applicable)
|
||||
|
||||
### [Endpoint 1]
|
||||
|
||||
```
|
||||
POST /api/[resource]
|
||||
```
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"[field]": "[value]"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"[field]": "[value]"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Responses**:
|
||||
- 400 Bad Request: [Condition]
|
||||
- 404 Not Found: [Condition]
|
||||
- 500 Internal Server Error: [Condition]
|
||||
|
||||
## Algorithm Design (if applicable)
|
||||
|
||||
### [Algorithm Name]
|
||||
|
||||
**Purpose**: [Description]
|
||||
|
||||
**Calculation Logic**:
|
||||
|
||||
#### Step 1: [Step Name]
|
||||
- [Detailed description]
|
||||
- Formula: `[formula]`
|
||||
- Score range: 0-100 points
|
||||
|
||||
#### Step 2: [Step Name]
|
||||
- [Detailed description]
|
||||
- Formula: `[formula]`
|
||||
- Score range: 0-100 points
|
||||
|
||||
#### Step 3: Total Score Calculation
|
||||
- Weighted average: `Total Score = (Step 1 × Weight 1) + (Step 2 × Weight 2)`
|
||||
- Weight allocation:
|
||||
- Step 1: [%]
|
||||
- Step 2: [%]
|
||||
|
||||
#### Step 4: Classification
|
||||
- [Classification 1]: Score >= [threshold]
|
||||
- [Classification 2]: [threshold] <= Score < [threshold]
|
||||
- [Classification 3]: Score < [threshold]
|
||||
|
||||
**Implementation Example**:
|
||||
```typescript
|
||||
function [algorithmName]([params]): [return] {
|
||||
// Step 1
|
||||
const score1 = [calculation];
|
||||
|
||||
// Step 2
|
||||
const score2 = [calculation];
|
||||
|
||||
// Total score
|
||||
const totalScore = (score1 * weight1) + (score2 * weight2);
|
||||
|
||||
// Classification
|
||||
if (totalScore >= threshold1) return '[classification1]';
|
||||
if (totalScore >= threshold2) return '[classification2]';
|
||||
return '[classification3]';
|
||||
}
|
||||
```
|
||||
|
||||
## UI Design (if applicable)
|
||||
|
||||
### Table Display
|
||||
|
||||
**Display Items**:
|
||||
| Item | Description | Format |
|
||||
|------|------|-------------|
|
||||
| [Item 1] | [Description] | [Format] |
|
||||
| [Item 2] | [Description] | [Format] |
|
||||
|
||||
### Color Coding
|
||||
|
||||
**Color Usage**:
|
||||
- [Color 1]: [Use] (e.g., green = completed)
|
||||
- [Color 2]: [Use] (e.g., yellow = in progress)
|
||||
- [Color 3]: [Use] (e.g., red = not started)
|
||||
|
||||
### Interactive Mode (if applicable)
|
||||
|
||||
**Operation Flow**:
|
||||
1. [Operation 1]
|
||||
2. [Operation 2]
|
||||
3. [Operation 3]
|
||||
|
||||
## File Structure (if applicable)
|
||||
|
||||
**Data Storage Format**:
|
||||
```
|
||||
[directory]/
|
||||
├── [file1].json # [description]
|
||||
└── [file2].json # [description]
|
||||
```
|
||||
|
||||
**File Content Example**:
|
||||
```json
|
||||
{
|
||||
"[field]": "[value]"
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
- [Optimization 1]: [Description]
|
||||
- [Optimization 2]: [Description]
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- [Consideration 1]: [Countermeasure]
|
||||
- [Consideration 2]: [Countermeasure]
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Error Classification
|
||||
|
||||
| Error Category | Handling | Display to User |
|
||||
|-----------|------|-----------------|
|
||||
| [Category 1] | [Handling details] | [Message] |
|
||||
| [Category 2] | [Handling details] | [Message] |
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
- [Target 1]
|
||||
- [Target 2]
|
||||
|
||||
### Integration Tests
|
||||
- [Scenario 1]
|
||||
- [Scenario 2]
|
||||
|
||||
### E2E Tests
|
||||
- [Scenario 1]
|
||||
- [Scenario 2]
|
||||
55
.opencode/skills/glossary-creation/SKILL.md
Normal file
55
.opencode/skills/glossary-creation/SKILL.md
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
name: glossary-creation
|
||||
description: Detailed guide and template for creating a glossary. Use only when creating a glossary.
|
||||
---
|
||||
|
||||
# Glossary Creation Skill
|
||||
|
||||
This skill is a detailed guide for systematically defining project-specific terms and technical terms.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting to create a glossary, confirm the following:
|
||||
|
||||
### Recommended Documents
|
||||
|
||||
1. **docs/product-requirements.md** (PRD)
|
||||
2. **docs/functional-design.md** (Functional Design Document)
|
||||
3. **docs/architecture.md** (Architecture Design Document)
|
||||
4. **docs/repository-structure.md** (Repository Structure)
|
||||
5. **docs/development-guidelines.md** (Development Guidelines)
|
||||
|
||||
The glossary defines the terms used across all documents in a unified way.
|
||||
Extract terms from each document and organize them systematically.
|
||||
|
||||
## Priority of Existing Documents
|
||||
|
||||
**Important**: If an existing glossary is present at `docs/glossary.md`,
|
||||
follow the priority order below:
|
||||
|
||||
1. **Existing glossary (`docs/glossary.md`)** - Highest priority
|
||||
- Contains project-specific term definitions
|
||||
- Takes precedence over this skill's guide
|
||||
|
||||
2. **This skill's guide** - Reference material
|
||||
- Generic templates and examples
|
||||
- Use when no existing glossary exists, or as a supplement
|
||||
|
||||
**When creating new**: Refer to this skill's template and guide
|
||||
**When updating**: Update while maintaining the structure and content of the existing glossary
|
||||
|
||||
## Output Destination
|
||||
|
||||
Save the created glossary to the following location:
|
||||
|
||||
```
|
||||
docs/glossary.md
|
||||
```
|
||||
|
||||
## Template Reference
|
||||
|
||||
When creating a glossary, use the following template: ./template.md
|
||||
|
||||
## Detailed Guide
|
||||
|
||||
For a more detailed creation guide, refer to the following file: ./guide.md
|
||||
509
.opencode/skills/glossary-creation/guide.md
Normal file
509
.opencode/skills/glossary-creation/guide.md
Normal file
@ -0,0 +1,509 @@
|
||||
# Glossary Creation Guide
|
||||
|
||||
## Basic principles
|
||||
|
||||
### 1. Clear and consistent definitions
|
||||
|
||||
Term definitions should eliminate ambiguity so that everyone who reads them arrives at the same understanding.
|
||||
|
||||
**Bad example**:
|
||||
```markdown
|
||||
## Task
|
||||
What the user should do
|
||||
```
|
||||
|
||||
**Good example**:
|
||||
```markdown
|
||||
## Task (Task)
|
||||
**Definition**: A unit of work that the user must complete. It has a title, description, due date,
|
||||
and status (not started / in progress / completed).
|
||||
|
||||
**Related terms**: Subtask, Task group
|
||||
|
||||
**Usage examples**:
|
||||
- "Add a task": Register a new task in the system
|
||||
- "Complete a task": Change the task's status to completed
|
||||
|
||||
**Data model**: `src/types/Task.ts`
|
||||
```
|
||||
|
||||
### 2. Include concrete examples
|
||||
|
||||
Show concrete usage examples, not just abstract definitions.
|
||||
|
||||
**Example**:
|
||||
```markdown
|
||||
## Priority (Priority)
|
||||
**Definition**: A three-level indicator showing a task's importance and urgency
|
||||
|
||||
**Value definitions**:
|
||||
- `high`: Urgent and important. Requires immediate response
|
||||
- `medium`: Important but not urgent. Handle in a planned manner
|
||||
- `low`: Low in both importance and urgency. Handle if there is time
|
||||
|
||||
**Decision criteria**:
|
||||
- high: Due within 24 hours, or blocking other tasks
|
||||
- medium: Due within one week
|
||||
- low: Due more than one week out, or no due date
|
||||
|
||||
**Usage example**:
|
||||
```typescript
|
||||
const task: Task = {
|
||||
title: 'Fix security vulnerability',
|
||||
priority: 'high', // Requires urgent response
|
||||
};
|
||||
```
|
||||
```
|
||||
|
||||
### 3. Link related terms
|
||||
|
||||
Make the relationships between terms clear.
|
||||
|
||||
**Example**:
|
||||
```markdown
|
||||
## Task (Task)
|
||||
**Definition**: [Definition]
|
||||
|
||||
**Related terms**:
|
||||
- [Subtask](#subtask): A task broken down into smaller parts
|
||||
- [Task group](#task-group): Multiple tasks grouped together
|
||||
- [Status](#task-status): The progress state of a task
|
||||
|
||||
**Parent-child relationship**:
|
||||
- Parent: Task group
|
||||
- Child: Subtask
|
||||
```
|
||||
|
||||
## How to classify terms
|
||||
|
||||
### Defining domain terms
|
||||
|
||||
**Target**: Project-specific business concepts
|
||||
|
||||
**Items to define**:
|
||||
```markdown
|
||||
## [Term]
|
||||
|
||||
**Definition**: [A concise definition in 1-2 sentences]
|
||||
|
||||
**Description**: [Detailed explanation, background, constraints]
|
||||
|
||||
**Related terms**: [Other related terms]
|
||||
|
||||
**Usage examples**: [Specific usage scenarios]
|
||||
|
||||
**Data model**: [The relevant file path]
|
||||
|
||||
**English notation**: [English term] (when there is global expansion)
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```markdown
|
||||
## Steering File (Steering File)
|
||||
|
||||
**Definition**: A temporary document created for short-term task management
|
||||
|
||||
**Description**:
|
||||
A steering file is placed in the `.steering/[YYYYMMDD]-[task-name]/` directory
|
||||
and is deleted 1-2 weeks after the task is completed. It contains the task specification,
|
||||
implementation notes, review records, and so on.
|
||||
|
||||
**Related terms**:
|
||||
- [Persistent document](#persistent-document): A document stored for the long term
|
||||
- [Task mode](#task-mode): The development mode that uses steering files
|
||||
|
||||
**Usage examples**:
|
||||
- "Create a steering file for adding a feature"
|
||||
- "After the task is completed, delete or archive the steering file"
|
||||
|
||||
**Directory structure**:
|
||||
```
|
||||
.steering/
|
||||
└── 20250101-add-priority-feature/
|
||||
├── requirements.md # The requirements for this task
|
||||
├── design.md # The design of the changes
|
||||
└── tasklist.md # The task list
|
||||
```
|
||||
|
||||
**English notation**: Steering File
|
||||
```
|
||||
|
||||
### Defining technical terms
|
||||
|
||||
**Target**: The technologies, frameworks, and tools in use
|
||||
|
||||
**Items to define**:
|
||||
```markdown
|
||||
## [Technology name]
|
||||
|
||||
**Definition**: [A concise description of the technology]
|
||||
|
||||
**Official site**: [URL]
|
||||
|
||||
**Use in this project**: [How it is used]
|
||||
|
||||
**Version**: [Version in use]
|
||||
|
||||
**Reason for selection**: [Why this technology was chosen]
|
||||
|
||||
**Alternative technologies**: [Other options that were considered]
|
||||
|
||||
**Related documents**: [Links to internal documents]
|
||||
|
||||
**Configuration file**: [Path to the configuration file]
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```markdown
|
||||
## TypeScript
|
||||
|
||||
**Definition**: A programming language that adds static typing to JavaScript
|
||||
|
||||
**Official site**: https://www.typescriptlang.org/
|
||||
|
||||
**Use in this project**:
|
||||
All source code is written in TypeScript to ensure type safety.
|
||||
|
||||
**Version**: 5.3.x
|
||||
|
||||
**Reason for selection**:
|
||||
- Improved maintainability in large-scale development
|
||||
- Improved development efficiency through editor completion
|
||||
- Error detection at compile time
|
||||
|
||||
**Alternative technologies**:
|
||||
- JavaScript ESM: Cannot benefit from type checking
|
||||
- Flow: Inferior to TypeScript in ecosystem maturity
|
||||
|
||||
**Related documents**:
|
||||
- [Architecture Design Document](./architecture.md#technology-stack)
|
||||
- [Development Guidelines](./development-guidelines.md#typescript-conventions)
|
||||
|
||||
**Configuration file**: `tsconfig.json`
|
||||
```
|
||||
|
||||
### Defining abbreviations and acronyms
|
||||
|
||||
**Principles**:
|
||||
- State the full name clearly
|
||||
- On first appearance, write both the abbreviation and the full name
|
||||
- Avoid project-specific abbreviations (use only common abbreviations)
|
||||
|
||||
**Example**:
|
||||
```markdown
|
||||
## CLI
|
||||
|
||||
**Full name**: Command Line Interface
|
||||
|
||||
**Meaning**: An interface operated from the command line
|
||||
|
||||
**Use in this project**:
|
||||
Used as the main interface of the Devtask tool. Users operate tasks with commands like
|
||||
`devtask add "task"`.
|
||||
|
||||
**Implementation**: `src/cli/` directory
|
||||
|
||||
**Alternative interface**: A GUI version is under consideration as a future extension
|
||||
|
||||
## TDD
|
||||
|
||||
**Full name**: Test-Driven Development
|
||||
|
||||
**Meaning**: A development method in which tests are written first and then the implementation follows
|
||||
|
||||
**Application in this project**:
|
||||
TDD is adopted for all new feature development.
|
||||
|
||||
**Procedure**:
|
||||
1. Write a test
|
||||
2. Run the test → confirm it fails
|
||||
3. Write the implementation
|
||||
4. Run the test → confirm it succeeds
|
||||
5. Refactor
|
||||
|
||||
**Reference**: [Development Guidelines](./development-guidelines.md#tdd)
|
||||
```
|
||||
|
||||
### Defining architecture terms
|
||||
|
||||
**Target**: Concepts related to system design and patterns
|
||||
|
||||
**Items to define**:
|
||||
```markdown
|
||||
## [Concept]
|
||||
|
||||
**Definition**: [Explanation of the architecture concept]
|
||||
|
||||
**Application in this project**: [The specific implementation method]
|
||||
|
||||
**Advantages**: [Reasons for adoption]
|
||||
|
||||
**Disadvantages**: [Constraints and trade-offs]
|
||||
|
||||
**Related components**: [Related components]
|
||||
|
||||
**Diagram**: [Structure diagram]
|
||||
|
||||
**References**: [References or URLs]
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```markdown
|
||||
## Layered Architecture (Layered Architecture)
|
||||
|
||||
**Definition**: A design pattern that divides a system into multiple layers by role,
|
||||
with a one-directional dependency from upper layers to lower layers
|
||||
|
||||
**Application in this project**:
|
||||
A three-layer architecture is adopted:
|
||||
|
||||
```
|
||||
UI layer (cli/)
|
||||
↓
|
||||
Service layer (services/)
|
||||
↓
|
||||
Data layer (repositories/)
|
||||
```
|
||||
|
||||
**Responsibilities of each layer**:
|
||||
- UI layer: Accepting and displaying user input
|
||||
- Service layer: Implementing business logic
|
||||
- Data layer: Persisting and retrieving data
|
||||
|
||||
**Advantages**:
|
||||
- Improved maintainability through separation of concerns
|
||||
- Easy to test (each layer can be tested independently)
|
||||
- A limited scope of impact from changes
|
||||
|
||||
**Disadvantages**:
|
||||
- May be over-engineering for small-scale projects
|
||||
- Overhead in data conversion between layers
|
||||
|
||||
**Dependency rules**:
|
||||
- ✅ UI layer → Service layer
|
||||
- ✅ Service layer → Data layer
|
||||
- ❌ Data layer → Service layer
|
||||
- ❌ Data layer → UI layer
|
||||
|
||||
**Implementation location**: Reflected in the structure of the `src/` directory
|
||||
|
||||
**References**:
|
||||
- [Architecture Design Document](./architecture.md)
|
||||
- [Repository Structure Definition Document](./repository-structure.md)
|
||||
```
|
||||
|
||||
## Defining state transitions
|
||||
|
||||
**Target**: The statuses or states of an entity
|
||||
|
||||
**Definition method**:
|
||||
|
||||
1. **Enumerate in table form**
|
||||
2. **State the transition conditions clearly**
|
||||
3. **Visualize with a Mermaid diagram**
|
||||
|
||||
**Example**:
|
||||
```markdown
|
||||
## Task Status (Task Status)
|
||||
|
||||
**Definition**: An enumerated type that indicates the progress state of a task
|
||||
|
||||
**Possible values**:
|
||||
|
||||
| Status | Meaning | Transition condition | Next state |
|
||||
|----------|------|---------|---------|
|
||||
| `todo` | Not started | Initial state when the task is created | `in_progress` |
|
||||
| `in_progress` | In progress | The user starts the task | `completed`, `todo` |
|
||||
| `completed` | Completed | The user completes the task | `todo` (can be reopened) |
|
||||
|
||||
**State transition diagram**:
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> todo: Task created
|
||||
todo --> in_progress: Work started
|
||||
in_progress --> completed: Completed
|
||||
in_progress --> todo: Interrupted
|
||||
completed --> todo: Reopened
|
||||
completed --> [*]: Archived
|
||||
```
|
||||
|
||||
**Implementation**:
|
||||
```typescript
|
||||
// src/types/Task.ts
|
||||
export type TaskStatus = 'todo' | 'in_progress' | 'completed';
|
||||
|
||||
// Validation of state transitions
|
||||
function canTransition(
|
||||
from: TaskStatus,
|
||||
to: TaskStatus
|
||||
): boolean {
|
||||
const validTransitions: Record<TaskStatus, TaskStatus[]> = {
|
||||
todo: ['in_progress'],
|
||||
in_progress: ['completed', 'todo'],
|
||||
completed: ['todo'],
|
||||
};
|
||||
return validTransitions[from].includes(to);
|
||||
}
|
||||
```
|
||||
|
||||
**Business rules**:
|
||||
- Direct transition from `todo` → `completed` is prohibited
|
||||
- A completed task can be reopened
|
||||
- An archived task cannot be changed
|
||||
```
|
||||
|
||||
## Defining errors and exceptions
|
||||
|
||||
**Target**: The error classes defined in the system
|
||||
|
||||
**Items to define**:
|
||||
```markdown
|
||||
## [Error name]
|
||||
|
||||
**Class name**: `[ErrorClassName]`
|
||||
|
||||
**Inherits from**: `Error` or `[ParentError]`
|
||||
|
||||
**Conditions for occurrence**: [When it occurs]
|
||||
|
||||
**Error message format**: [The format of the message]
|
||||
|
||||
**How to handle**:
|
||||
- User: [What the user should do]
|
||||
- Developer: [What the developer should do]
|
||||
|
||||
**Error code**: [If applicable]
|
||||
|
||||
**Log level**: [ERROR, WARN, INFO]
|
||||
|
||||
**Implementation location**: [File path]
|
||||
|
||||
**Usage example**: [Code example]
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```markdown
|
||||
## Validation Error (Validation Error)
|
||||
|
||||
**Class name**: `ValidationError`
|
||||
|
||||
**Inherits from**: `Error`
|
||||
|
||||
**Conditions for occurrence**:
|
||||
Occurs when user input violates a business rule.
|
||||
|
||||
**Error message format**:
|
||||
```
|
||||
[Field name]: [Error description]
|
||||
```
|
||||
|
||||
**How to handle**:
|
||||
- User: Correct the input according to the error message
|
||||
- Developer: Confirm whether the validation logic is correct
|
||||
|
||||
**Error code**: `VAL-XXX` (XXX is a 3-digit number)
|
||||
|
||||
**Log level**: WARN (because it is a user-caused error)
|
||||
|
||||
**Implementation location**: `src/errors/ValidationError.ts`
|
||||
|
||||
**Usage example**:
|
||||
```typescript
|
||||
// Throwing the error
|
||||
if (title.length === 0) {
|
||||
throw new ValidationError(
|
||||
'Title is required',
|
||||
'title',
|
||||
title
|
||||
);
|
||||
}
|
||||
|
||||
// Handling the error
|
||||
try {
|
||||
await taskService.create(data);
|
||||
} catch (error) {
|
||||
if (error instanceof ValidationError) {
|
||||
console.error(`Input error: ${error.message}`);
|
||||
console.error(`Field: ${error.field}`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Related validations**:
|
||||
- Title: 1-200 characters
|
||||
- Due date: Now or later
|
||||
- Priority: One of high, medium, low
|
||||
```
|
||||
|
||||
## Maintaining and updating terms
|
||||
|
||||
### When to add a term
|
||||
|
||||
**When you should add**:
|
||||
- A new concept has been introduced
|
||||
- A term that team members have asked about
|
||||
- A term that appears three or more times in the documentation
|
||||
- When an external service or API has been integrated
|
||||
|
||||
**When you do not need to add**:
|
||||
- General programming terms (variables, functions, etc.)
|
||||
- Temporary terms used only once
|
||||
|
||||
### Update workflow
|
||||
|
||||
1. **Add or change a term**
|
||||
- Add it to the appropriate category
|
||||
- Fill in all definition items
|
||||
- Link related terms
|
||||
|
||||
2. **Review**
|
||||
- Share with team members
|
||||
- Confirm the validity of the definition
|
||||
|
||||
3. **Record the change history**
|
||||
- Update the change history table of the glossary
|
||||
- Note it in the commit message
|
||||
|
||||
4. **Confirm the scope of impact**
|
||||
- Search for places where the term is used
|
||||
- Update documents as needed
|
||||
|
||||
### Managing the index
|
||||
|
||||
**Organize in Japanese syllabary order / alphabetical order**:
|
||||
|
||||
```markdown
|
||||
## Index
|
||||
|
||||
### A-row
|
||||
- [Archive](#archive) - Process term
|
||||
- [Error handling](#error-handling) - Technical term
|
||||
|
||||
### KA-row
|
||||
- [Coverage](#coverage) - Technical term
|
||||
|
||||
### SA-row
|
||||
- [Steering file](#steering-file) - Domain term
|
||||
- [Status](#task-status) - Data model term
|
||||
|
||||
### TA-row
|
||||
- [Task](#task) - Domain term
|
||||
- [TDD](#tdd) - Abbreviation
|
||||
|
||||
### A-Z
|
||||
- [CLI](#cli) - Abbreviation
|
||||
- [TypeScript](#typescript) - Technical term
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Every term is clearly defined
|
||||
- [ ] Concrete examples are included
|
||||
- [ ] Related terms are linked
|
||||
- [ ] Categories are appropriately classified
|
||||
- [ ] Technical terms include version information
|
||||
- [ ] Abbreviations include their full names
|
||||
- [ ] State transitions are illustrated with diagrams
|
||||
- [ ] Errors include how to handle them
|
||||
- [ ] The index is organized
|
||||
- [ ] The change history is recorded
|
||||
179
.opencode/skills/glossary-creation/template.md
Normal file
179
.opencode/skills/glossary-creation/template.md
Normal file
@ -0,0 +1,179 @@
|
||||
# Project Glossary
|
||||
|
||||
## Overview
|
||||
|
||||
This document manages the definitions of terms used within the project.
|
||||
|
||||
**Updated**: [YYYY-MM-DD]
|
||||
|
||||
## Domain Terms
|
||||
|
||||
Terms related to project-specific business concepts and features.
|
||||
|
||||
### [Term 1]
|
||||
|
||||
**Definition**: [Clear definition]
|
||||
|
||||
**Description**: [Detailed description]
|
||||
|
||||
**Related Terms**: [Other related terms]
|
||||
|
||||
**Usage Examples**:
|
||||
- [Example 1]
|
||||
- [Example 2]
|
||||
|
||||
**English Notation**: [English Term]
|
||||
|
||||
### [Term 2]
|
||||
|
||||
**Definition**: [Clear definition]
|
||||
|
||||
**Description**: [Detailed description]
|
||||
|
||||
**Related Terms**: [Other related terms]
|
||||
|
||||
**Usage Examples**:
|
||||
- [Example 1]
|
||||
- [Example 2]
|
||||
|
||||
## Technical Terms
|
||||
|
||||
Terms related to the technologies, frameworks, and tools used in the project.
|
||||
|
||||
### [Technology 1]
|
||||
|
||||
**Definition**: [Description of the technology]
|
||||
|
||||
**Official Site**: [URL]
|
||||
|
||||
**Usage in This Project**: [How it is used]
|
||||
|
||||
**Version**: [Version used]
|
||||
|
||||
**Related Documents**: [Links to internal documents]
|
||||
|
||||
### [Technology 2]
|
||||
|
||||
**Definition**: [Description of the technology]
|
||||
|
||||
**Official Site**: [URL]
|
||||
|
||||
**Usage in This Project**: [How it is used]
|
||||
|
||||
**Version**: [Version used]
|
||||
|
||||
## Abbreviations and Acronyms
|
||||
|
||||
### [Abbreviation 1]
|
||||
|
||||
**Full Name**: [Full Name]
|
||||
|
||||
**Meaning**: [Description]
|
||||
|
||||
**Usage in This Project**: [Where it is used]
|
||||
|
||||
### [Abbreviation 2]
|
||||
|
||||
**Full Name**: [Full Name]
|
||||
|
||||
**Meaning**: [Description]
|
||||
|
||||
**Usage in This Project**: [Where it is used]
|
||||
|
||||
## Architecture Terms
|
||||
|
||||
Terms related to system design and architecture.
|
||||
|
||||
### [Concept 1]
|
||||
|
||||
**Definition**: [Description of the architecture concept]
|
||||
|
||||
**Application in This Project**: [How it is implemented]
|
||||
|
||||
**Related Components**: [Related component names]
|
||||
|
||||
**Diagram**:
|
||||
```
|
||||
[ASCII diagram or Mermaid diagram]
|
||||
```
|
||||
|
||||
### [Concept 2]
|
||||
|
||||
**Definition**: [Description of the architecture concept]
|
||||
|
||||
**Application in This Project**: [How it is implemented]
|
||||
|
||||
## Statuses and States
|
||||
|
||||
Definitions of various statuses used within the system.
|
||||
|
||||
### [Status Category 1]
|
||||
|
||||
| Status | Meaning | Transition Condition | Next State |
|
||||
|----------|------|---------|---------|
|
||||
| [State 1] | [Description] | [Condition] | [Next State] |
|
||||
| [State 2] | [Description] | [Condition] | [Next State] |
|
||||
|
||||
**State Transition Diagram**:
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> State1
|
||||
State1 --> State2: Condition A
|
||||
State2 --> [*]
|
||||
```
|
||||
|
||||
## Data Model Terms
|
||||
|
||||
Terms related to databases and data structures.
|
||||
|
||||
### [Entity 1]
|
||||
|
||||
**Definition**: [Description of the entity]
|
||||
|
||||
**Key Fields**:
|
||||
- `field1`: [Description]
|
||||
- `field2`: [Description]
|
||||
|
||||
**Related Entities**: [Related entities]
|
||||
|
||||
**Constraints**: [Unique constraints, foreign key constraints, etc.]
|
||||
|
||||
## Errors and Exceptions
|
||||
|
||||
Errors and exceptions defined in the system.
|
||||
|
||||
### [Error Category 1]
|
||||
|
||||
**Class Name**: `[ErrorClassName]`
|
||||
|
||||
**Trigger Condition**: [When it occurs]
|
||||
|
||||
**Resolution**: [How users/developers should handle it]
|
||||
|
||||
**Error Code**: [If applicable]
|
||||
|
||||
**Example**:
|
||||
```typescript
|
||||
throw new [ErrorClassName]('[message]');
|
||||
```
|
||||
|
||||
## Calculations and Algorithms (if applicable)
|
||||
|
||||
Terms related to specific calculation methods or algorithms.
|
||||
|
||||
### [Calculation Method 1]
|
||||
|
||||
**Definition**: [Description of the calculation method]
|
||||
|
||||
**Formula**:
|
||||
```
|
||||
[Formula]
|
||||
```
|
||||
|
||||
**Implementation Location**: `src/[path]/[file].ts`
|
||||
|
||||
**Example**:
|
||||
```
|
||||
Input: [Example]
|
||||
Output: [Result]
|
||||
```
|
||||
332
.opencode/skills/prd-writing/SKILL.md
Normal file
332
.opencode/skills/prd-writing/SKILL.md
Normal file
@ -0,0 +1,332 @@
|
||||
---
|
||||
name: prd-writing
|
||||
description: A detailed guide and template for creating a Product Requirements Document (PRD). Use only when creating a PRD.
|
||||
---
|
||||
|
||||
# PRD Writing Skill
|
||||
|
||||
This skill is a detailed guide for creating a high-quality Product Requirements Document (PRD).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin creating a PRD, the following must be complete:
|
||||
|
||||
### The idea has been refined through brainstorming
|
||||
|
||||
The user must have completed refining the product idea through dialogue with opencode.
|
||||
|
||||
### docs/ideas/initial-requirements.md has been created
|
||||
|
||||
**Important**: The brainstorming content must be saved by the user in the following file:
|
||||
|
||||
**File path**: `docs/ideas/initial-requirements.md`
|
||||
|
||||
This file must include the following content:
|
||||
- The basic idea of the product
|
||||
- The problem to be solved
|
||||
- An overview of the target users
|
||||
- The main features to be implemented
|
||||
- The scope of the MVP
|
||||
|
||||
When creating the PRD, refer to the content of this file to add detail.
|
||||
|
||||
## Priority of existing documents
|
||||
|
||||
**Important**: If an existing PRD is present at `docs/product-requirements.md`,
|
||||
follow the priority order below:
|
||||
|
||||
1. **Existing PRD (`docs/product-requirements.md`)** - Highest priority
|
||||
- Contains project-specific requirements
|
||||
- Takes precedence over this skill's guide
|
||||
|
||||
2. **This skill's guide** - Reference material
|
||||
- Generic templates and examples
|
||||
- Use when there is no existing PRD, or as a supplement
|
||||
|
||||
**When creating from scratch**: Refer to this skill's template and guide
|
||||
**When updating**: Update while preserving the structure and content of the existing PRD
|
||||
|
||||
## Output destination
|
||||
|
||||
Save the PRD you create to the following location:
|
||||
|
||||
```
|
||||
docs/product-requirements.md
|
||||
```
|
||||
|
||||
## Template reference
|
||||
|
||||
When creating the PRD, use the following template: ./template.md
|
||||
|
||||
## PRD creation process
|
||||
|
||||
### 1. Review initial-requirements.md
|
||||
|
||||
First, review the initial requirements specification created by the user:
|
||||
|
||||
Read `docs/ideas/initial-requirements.md`
|
||||
|
||||
### 2. Generate the PRD draft
|
||||
|
||||
Based on the content of initial-requirements.md, generate the PRD following the template.
|
||||
|
||||
### 3. Review and improve the PRD
|
||||
|
||||
Review the generated PRD from the following perspectives:
|
||||
|
||||
#### Review perspectives
|
||||
|
||||
1. Is the product vision clear?
|
||||
2. Are the target users specific?
|
||||
3. Are the success metrics measurable?
|
||||
4. Are the functional requirements detailed to an implementable level?
|
||||
5. Are the non-functional requirements comprehensive?
|
||||
|
||||
#### Criteria for evaluating review results
|
||||
|
||||
Evaluate the generated PRD in the following format:
|
||||
|
||||
**✅ Strengths**
|
||||
- A clear vision is described in a measurable and specific way
|
||||
- The functional specifications are detailed to an implementation level
|
||||
- KPIs are defined with quantitative metrics
|
||||
|
||||
**⚠️ Points that need improvement**
|
||||
|
||||
Ambiguity in functional requirements:
|
||||
- Problem: There are areas where the concrete implementation specification is unclear
|
||||
- Recommendation: Clearly state specific command specifications and error handling
|
||||
|
||||
Measurement method for success metrics:
|
||||
- Problem: The measurement method is unclear
|
||||
- Recommendation: Clearly state the measurement method and considerations for privacy
|
||||
|
||||
### 4. Improvement after review
|
||||
|
||||
Review the issues raised in the review one by one, and improve the areas that need more detail:
|
||||
|
||||
1. Review the raised issues one by one
|
||||
2. Improve the areas that need more detail
|
||||
3. After improving, conduct the review again
|
||||
4. Repeat until there are no more issues
|
||||
|
||||
**Cautions**:
|
||||
- Do not take the AI's review at face value; the final judgment must always be made by a human
|
||||
- Clearly specify the review perspectives
|
||||
- Have a human verify the validity of the improvement proposals
|
||||
|
||||
## Key points for creating a PRD
|
||||
|
||||
### 1. Specificity and measurability
|
||||
|
||||
Every requirement must be specific and measurable.
|
||||
|
||||
**Bad examples**:
|
||||
- The system needs to be fast
|
||||
- Users feel it is easy to use
|
||||
|
||||
**Good examples**:
|
||||
- Command execution time: within 100ms (on an average PC environment)
|
||||
- A new user can learn the basic operations within 5 minutes (measured by usability testing)
|
||||
|
||||
### 2. User-centered design
|
||||
|
||||
Every feature must solve a clear user problem.
|
||||
|
||||
**User story format**:
|
||||
```
|
||||
As a [user], I want [feature] so that [goal]
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```
|
||||
As a developer, I want a CLI-based task management tool
|
||||
so that I can manage tasks without leaving the terminal
|
||||
```
|
||||
|
||||
### 3. Clarifying priorities
|
||||
|
||||
Set a priority for every feature:
|
||||
|
||||
- **P0 (Required)**: Features to include in the MVP (Minimum Viable Product). Without these, the product does not stand as a product
|
||||
- **P1 (Important)**: Features that should be added immediately after the initial release
|
||||
- **P2 (Nice to have)**: Features to consider adding in the future
|
||||
|
||||
## Details of the main PRD sections
|
||||
|
||||
### 1. Product overview
|
||||
|
||||
#### Components
|
||||
|
||||
1. **Name**: Product name and subtitle
|
||||
2. **Product concept**: Three main concepts
|
||||
3. **Product vision**: The world you aim for, in 3-5 sentences
|
||||
4. **Purpose**: A list of specific purposes
|
||||
|
||||
#### Example
|
||||
|
||||
```markdown
|
||||
### Name
|
||||
**Devtask** - A task management CLI tool for developers
|
||||
|
||||
### Product concept
|
||||
- Task management that is complete within the CLI: Complete all operations without leaving the terminal
|
||||
- Automatic priority estimation: Automatically estimate priority from a task's due date, creation time, status change history, and so on
|
||||
- A simple and fast operating feel: Complete operations with minimal keystrokes, with instant response
|
||||
|
||||
### Product vision
|
||||
Provide a CLI tool that lets developers efficiently manage tasks without leaving the terminal.
|
||||
Specialized for command-line operation, it delivers lightweight, fast task management that does not interrupt the development flow.
|
||||
With automatic priority estimation, developers can focus on essential work.
|
||||
```
|
||||
|
||||
**Include a specific value proposition**
|
||||
|
||||
Bad example:
|
||||
```
|
||||
Build a convenient task management tool
|
||||
```
|
||||
|
||||
Good example:
|
||||
```
|
||||
A CLI tool that lets developers manage tasks without leaving the terminal.
|
||||
|
||||
Value provided:
|
||||
- Reduced context switching (zero GUI ↔ terminal switching)
|
||||
- Improved work efficiency (no mouse operation, averaging a 30% time reduction)
|
||||
- Integration with automation (can be embedded in shell scripts)
|
||||
```
|
||||
|
||||
### 2. Target users (personas)
|
||||
|
||||
#### Required elements
|
||||
|
||||
1. **Basic attributes**: Age, occupation, years of experience
|
||||
2. **Technology stack**: Tools and languages in use
|
||||
3. **Current problems**: Specific pain points
|
||||
4. **Expected solution**: What they want to become
|
||||
5. **A typical daily workflow**
|
||||
|
||||
#### Example
|
||||
|
||||
```markdown
|
||||
### Primary persona: Taro Tanaka (29, full-stack engineer)
|
||||
- Freelancer running 3-5 projects in parallel
|
||||
- Vim/Emacs + terminal environment
|
||||
- Does not want to spend time on task management
|
||||
- Prefers Markdown, Git, and CLI tools
|
||||
```
|
||||
|
||||
### 3. Success metrics (KPIs)
|
||||
|
||||
#### SMART principles
|
||||
|
||||
- **S**pecific: Clear about what is being measured
|
||||
- **M**easurable: Can be measured numerically
|
||||
- **A**chievable: A realistic target
|
||||
- **R**elevant: Related to business goals
|
||||
- **T**ime-bound: Sets a deadline for achievement
|
||||
|
||||
#### Example
|
||||
|
||||
```markdown
|
||||
### Primary KPIs
|
||||
- Daily active users (DAU): 100 (in 3 months)
|
||||
- Task completion rate: 70% or higher
|
||||
- Average number of commands executed per day: 10 or more
|
||||
```
|
||||
|
||||
### 4. Functional requirements
|
||||
|
||||
#### Core features (MVP)
|
||||
|
||||
Include the following for each feature:
|
||||
- User story
|
||||
- Acceptance criteria (in checklist form)
|
||||
- Priority (P0/P1/P2)
|
||||
|
||||
**Format**:
|
||||
```markdown
|
||||
### [Feature name]
|
||||
|
||||
User story:
|
||||
As a [user], I want [feature] so that [goal]
|
||||
|
||||
Acceptance criteria:
|
||||
- [ ] Criterion 1 (measurable)
|
||||
- [ ] Criterion 2 (measurable)
|
||||
|
||||
Priority: P0 (Required) / P1 (Important) / P2 (Nice to have)
|
||||
```
|
||||
|
||||
#### CLI interface
|
||||
|
||||
For a CLI tool, include specific command examples:
|
||||
|
||||
```bash
|
||||
# Basic operations
|
||||
devtask add "Task name" --due 2025-01-15 --priority high
|
||||
devtask list
|
||||
devtask next # Show the task to do now
|
||||
devtask done <task-id>
|
||||
devtask show <task-id>
|
||||
```
|
||||
|
||||
### 5. Non-functional requirements
|
||||
|
||||
Describe them in a measurable form:
|
||||
|
||||
**Example**:
|
||||
```markdown
|
||||
### Performance
|
||||
- Command execution time: within 100ms (on an average PC environment)
|
||||
- Task list display: within 1 second for up to 1000 items
|
||||
|
||||
### Usability
|
||||
- A new user can learn the basic operations within 5 minutes
|
||||
- All features can be checked via the help command
|
||||
|
||||
### Reliability
|
||||
- Zero data loss (automatic backup)
|
||||
- Rollback on error
|
||||
```
|
||||
|
||||
## Quality standards and checkpoints
|
||||
|
||||
To ensure the quality of the PRD, confirm the following checkpoints:
|
||||
|
||||
### Vision and goals
|
||||
- [ ] Is the product vision clear and measurable?
|
||||
- [ ] Is the specific value provided defined?
|
||||
- [ ] Is the target market clear?
|
||||
|
||||
### Target users
|
||||
- [ ] Is the persona specifically defined?
|
||||
- [ ] Are the current problems and expected solution clear?
|
||||
- [ ] Are the technology stack and daily workflow described?
|
||||
|
||||
### Success metrics
|
||||
- [ ] Are KPIs defined following the SMART principles?
|
||||
- [ ] Is the measurement method clear?
|
||||
- [ ] Is an achievement deadline set?
|
||||
|
||||
### Functional requirements
|
||||
- [ ] Is every feature described in user story form?
|
||||
- [ ] Are acceptance criteria defined in a measurable form?
|
||||
- [ ] Is the priority (P0/P1/P2) clearly set?
|
||||
|
||||
### Non-functional requirements
|
||||
- [ ] Are performance standards defined with specific numbers?
|
||||
- [ ] Are usability standards measurable?
|
||||
- [ ] Are reliability and security requirements clear?
|
||||
|
||||
## Summary
|
||||
|
||||
Keys to success in creating a PRD:
|
||||
|
||||
1. **Create based on initial-requirements.md**: Refer to the brainstorming content created by the user
|
||||
2. **Specificity and measurability**: Make every requirement clear
|
||||
3. **User-centered**: Only features that solve user problems
|
||||
4. **Clarifying priorities**: Classify by P0/P1/P2
|
||||
5. **Review and improvement**: Self-review and final human judgment
|
||||
6. **Applying the SMART principles**: Especially important when defining KPIs
|
||||
116
.opencode/skills/prd-writing/template.md
Normal file
116
.opencode/skills/prd-writing/template.md
Normal file
@ -0,0 +1,116 @@
|
||||
# Product Requirements Document
|
||||
|
||||
## Product overview
|
||||
|
||||
### Name
|
||||
**[Product name]** - [Subtitle]
|
||||
|
||||
### Product concept
|
||||
- **[Concept 1]**: [Description]
|
||||
- **[Concept 2]**: [Description]
|
||||
- **[Concept 3]**: [Description]
|
||||
|
||||
### Product vision
|
||||
[Describe the world this product aims for, in 3-5 sentences]
|
||||
|
||||
### Purpose
|
||||
- [Purpose 1]
|
||||
- [Purpose 2]
|
||||
- [Purpose 3]
|
||||
|
||||
## Target users
|
||||
|
||||
### Primary persona: [Name] ([Age], [Occupation])
|
||||
- [Attribute 1: e.g., freelancer running 3-5 projects in parallel]
|
||||
- [Attribute 2: e.g., Vim/Emacs + terminal environment]
|
||||
- [Current problem: e.g., does not want to spend time on task management]
|
||||
- [Expected solution]
|
||||
- [A typical daily workflow]
|
||||
|
||||
## Success metrics (KPIs)
|
||||
|
||||
### Primary KPIs
|
||||
- [Metric 1]: [Target value] ([Deadline])
|
||||
- Example: Daily active users (DAU): 100 (in 3 months)
|
||||
- [Metric 2]: [Target value] ([Deadline])
|
||||
- Example: Task completion rate: 70% or higher
|
||||
|
||||
### Secondary KPIs
|
||||
- [Metric 1]: [Target value] ([Deadline])
|
||||
- [Metric 2]: [Target value] ([Deadline])
|
||||
|
||||
## Functional requirements
|
||||
|
||||
### Core features (MVP)
|
||||
|
||||
#### [Feature 1]
|
||||
|
||||
**User story**:
|
||||
As a [user], I want [feature] so that [goal]
|
||||
|
||||
**Acceptance criteria**:
|
||||
- [ ] [Criterion 1: described in a measurable form]
|
||||
- [ ] [Criterion 2: described in a measurable form]
|
||||
- [ ] [Criterion 3: described in a measurable form]
|
||||
|
||||
**Priority**: P0 (Required)
|
||||
|
||||
#### [Feature 2]
|
||||
|
||||
**User story**:
|
||||
[Description]
|
||||
|
||||
**Acceptance criteria**:
|
||||
- [ ] [Criterion 1]
|
||||
- [ ] [Criterion 2]
|
||||
|
||||
**Priority**: P1 (Important)
|
||||
|
||||
### CLI interface (if applicable)
|
||||
|
||||
```bash
|
||||
# Example of basic operations
|
||||
[command] [subcommand] [options]
|
||||
# Write specific command examples
|
||||
```
|
||||
|
||||
### Future features (Post-MVP)
|
||||
|
||||
#### [Feature 3]
|
||||
|
||||
[Brief description]
|
||||
|
||||
**Priority**: P2 (Nice to have)
|
||||
|
||||
## Non-functional requirements
|
||||
|
||||
### Performance
|
||||
- [Requirement 1]: [Measurable standard]
|
||||
- Example: Command execution time: within 100ms
|
||||
- [Requirement 2]: [Measurable standard]
|
||||
- Example: Task list display: within 1 second for up to 1000 items
|
||||
|
||||
### Usability
|
||||
- [Requirement 1]: [Measurable standard]
|
||||
- Example: A new user can learn the basic operations within 5 minutes
|
||||
- [Requirement 2]: [Measurable standard]
|
||||
|
||||
### Reliability
|
||||
- [Requirement 1]: [Measurable standard]
|
||||
- Example: Zero data loss (automatic backup)
|
||||
- [Requirement 2]: [Measurable standard]
|
||||
|
||||
### Security
|
||||
- [Requirement 1]: [Measurable standard]
|
||||
- [Requirement 2]: [Measurable standard]
|
||||
|
||||
### Scalability
|
||||
- [Requirement 1]: [Measurable standard]
|
||||
- [Requirement 2]: [Measurable standard]
|
||||
|
||||
## Out of scope
|
||||
|
||||
Items explicitly considered out of scope:
|
||||
- [Item 1]
|
||||
- [Item 2]
|
||||
- [Item 3]
|
||||
51
.opencode/skills/repository-structure/SKILL.md
Normal file
51
.opencode/skills/repository-structure/SKILL.md
Normal file
@ -0,0 +1,51 @@
|
||||
---
|
||||
name: repository-structure
|
||||
description: A detailed guide and template for creating a repository structure definition document. Use only when defining the repository structure.
|
||||
---
|
||||
|
||||
# Repository Structure Definition Skill
|
||||
|
||||
This skill is a detailed guide for defining a clear and maintainable repository structure.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin defining the repository structure, confirm the following:
|
||||
|
||||
### Required documents
|
||||
|
||||
1. `docs/product-requirements.md` (PRD)
|
||||
2. `docs/functional-design.md` (Functional Design Document)
|
||||
3. `docs/architecture.md` (Architecture Design Document)
|
||||
|
||||
The repository structure defines a concrete directory layout that reflects the technology stack and system composition determined during architecture design.
|
||||
|
||||
## Priority of existing documents
|
||||
|
||||
**Important**: If an existing repository structure definition document is present at `docs/repository-structure.md`, follow the priority order below:
|
||||
|
||||
1. **Existing repository structure definition document (`docs/repository-structure.md`)** - Highest priority
|
||||
- Contains the project-specific directory structure
|
||||
- Takes precedence over this skill's guide
|
||||
|
||||
2. **This skill's guide** - Reference material
|
||||
- Generic templates and examples
|
||||
- Use when there is no existing definition document, or as a supplement
|
||||
|
||||
**When creating from scratch**: Refer to this skill's template and guide
|
||||
**When updating**: Update while preserving the structure and content of the existing definition document
|
||||
|
||||
## Output destination
|
||||
|
||||
Save the repository structure definition document you create to the following location:
|
||||
|
||||
```
|
||||
docs/repository-structure.md
|
||||
```
|
||||
|
||||
## Template reference
|
||||
|
||||
When creating the repository structure definition document, use the following template: ./template.md
|
||||
|
||||
## Detailed guide
|
||||
|
||||
For a more detailed creation guide, refer to the following file: ./guide.md
|
||||
400
.opencode/skills/repository-structure/guide.md
Normal file
400
.opencode/skills/repository-structure/guide.md
Normal file
@ -0,0 +1,400 @@
|
||||
# Repository Structure Document Authoring Guide
|
||||
|
||||
## Basic Principles
|
||||
|
||||
### 1. Clarify Roles
|
||||
|
||||
Each directory should have a single, well-defined role.
|
||||
|
||||
**Bad example**:
|
||||
```
|
||||
src/
|
||||
├── stuff/ # Vague
|
||||
├── misc/ # Miscellaneous
|
||||
└── utils/ # Too generic
|
||||
```
|
||||
|
||||
**Good example**:
|
||||
```
|
||||
src/
|
||||
├── commands/ # CLI command implementations
|
||||
├── services/ # Business logic
|
||||
├── repositories/ # Data persistence
|
||||
└── validators/ # Input validation
|
||||
```
|
||||
|
||||
### 2. Enforce Layer Separation
|
||||
|
||||
Reflect the architecture's layer structure in the directory structure:
|
||||
|
||||
```
|
||||
src/
|
||||
├── ui/ # UI layer
|
||||
│ └── cli/ # CLI implementation
|
||||
├── services/ # Service layer
|
||||
│ └── task/ # Task management service
|
||||
└── repositories/ # Data layer
|
||||
└── task/ # Task repository
|
||||
```
|
||||
|
||||
### 3. Split by Technical Concern (Baseline)
|
||||
|
||||
Split directories by related technical concerns:
|
||||
|
||||
**Basic structure**:
|
||||
```
|
||||
src/
|
||||
├── commands/ # CLI commands
|
||||
├── services/ # Business logic
|
||||
├── repositories/ # Data persistence
|
||||
└── types/ # Type definitions
|
||||
```
|
||||
|
||||
**Mapping to the layer structure**:
|
||||
```
|
||||
CLI/UI layer → commands/, cli/
|
||||
Service layer → services/
|
||||
Data layer → repositories/, storage/
|
||||
```
|
||||
|
||||
## Designing the Directory Structure
|
||||
|
||||
### Expressing the Layer Structure
|
||||
|
||||
```typescript
|
||||
// Bad example: flat structure
|
||||
src/
|
||||
├── TaskCLI.ts
|
||||
├── TaskService.ts
|
||||
├── TaskRepository.ts
|
||||
├── UserCLI.ts
|
||||
├── UserService.ts
|
||||
└── UserRepository.ts
|
||||
|
||||
// Good example: clear layers
|
||||
src/
|
||||
├── cli/
|
||||
│ ├── TaskCLI.ts
|
||||
│ └── UserCLI.ts
|
||||
├── services/
|
||||
│ ├── TaskService.ts
|
||||
│ └── UserService.ts
|
||||
└── repositories/
|
||||
├── TaskRepository.ts
|
||||
└── UserRepository.ts
|
||||
```
|
||||
|
||||
### Placement of the Test Directory
|
||||
|
||||
**Recommended structure**:
|
||||
```
|
||||
project/
|
||||
├── src/
|
||||
│ └── services/
|
||||
│ └── TaskService.ts
|
||||
└── tests/
|
||||
├── unit/
|
||||
│ └── services/
|
||||
│ └── TaskService.test.ts
|
||||
├── integration/
|
||||
└── e2e/
|
||||
```
|
||||
|
||||
**Rationale**:
|
||||
- Test code is separated from production code
|
||||
- Easy to exclude tests at build time
|
||||
- Can be organized by test type
|
||||
|
||||
## Naming Convention Best Practices
|
||||
|
||||
### Principles for Directory Names
|
||||
|
||||
**1. Use the plural form (layer directories)**
|
||||
```
|
||||
✅ services/
|
||||
✅ repositories/
|
||||
✅ controllers/
|
||||
|
||||
❌ service/
|
||||
❌ repository/
|
||||
❌ controller/
|
||||
```
|
||||
|
||||
Rationale: They hold multiple files
|
||||
|
||||
**2. Use kebab-case**
|
||||
```
|
||||
✅ task-management/
|
||||
✅ user-authentication/
|
||||
|
||||
❌ TaskManagement/
|
||||
❌ userAuthentication/
|
||||
```
|
||||
|
||||
Rationale: Compatibility with URLs and the file system
|
||||
|
||||
**3. Use specific names**
|
||||
```
|
||||
✅ validators/ # Input validation
|
||||
✅ formatters/ # Data formatting
|
||||
✅ parsers/ # Data parsing
|
||||
|
||||
❌ utils/ # Too generic
|
||||
❌ helpers/ # Vague
|
||||
❌ common/ # Meaningless
|
||||
```
|
||||
|
||||
### Principles for File Names
|
||||
|
||||
**1. Class files: PascalCase + role suffix**
|
||||
```typescript
|
||||
// Service classes
|
||||
TaskService.ts
|
||||
UserAuthenticationService.ts
|
||||
|
||||
// Repository classes
|
||||
TaskRepository.ts
|
||||
UserRepository.ts
|
||||
|
||||
// Controller classes
|
||||
TaskController.ts
|
||||
```
|
||||
|
||||
**2. Function files: camelCase + start with a verb**
|
||||
```typescript
|
||||
// Utility functions
|
||||
formatDate.ts
|
||||
validateEmail.ts
|
||||
parseCommandArguments.ts
|
||||
```
|
||||
|
||||
**3. Type definition files: PascalCase or kebab-case**
|
||||
```typescript
|
||||
// Interface definitions
|
||||
Task.ts
|
||||
UserProfile.ts
|
||||
|
||||
// Type definition collections
|
||||
task-types.d.ts
|
||||
api-types.d.ts
|
||||
```
|
||||
|
||||
**4. Constant files: UPPER_SNAKE_CASE or kebab-case**
|
||||
```typescript
|
||||
// Constant definitions
|
||||
API_ENDPOINTS.ts
|
||||
ERROR_MESSAGES.ts
|
||||
|
||||
// or
|
||||
api-endpoints.ts
|
||||
error-messages.ts
|
||||
```
|
||||
|
||||
## Managing Dependencies
|
||||
|
||||
### Dependency Rules Between Layers
|
||||
|
||||
```typescript
|
||||
// ✅ Good example: dependency from an upper layer to a lower layer
|
||||
// cli/TaskCLI.ts
|
||||
import { TaskService } from '../services/TaskService';
|
||||
|
||||
class TaskCLI {
|
||||
constructor(private taskService: TaskService) {}
|
||||
}
|
||||
|
||||
// ❌ Bad example: dependency from a lower layer to an upper layer
|
||||
// services/TaskService.ts
|
||||
import { TaskCLI } from '../cli/TaskCLI'; // Forbidden!
|
||||
```
|
||||
|
||||
### Avoiding Circular Dependencies
|
||||
|
||||
**Problematic code**:
|
||||
```typescript
|
||||
// services/TaskService.ts
|
||||
import { UserService } from './UserService';
|
||||
|
||||
export class TaskService {
|
||||
constructor(private userService: UserService) {}
|
||||
}
|
||||
|
||||
// services/UserService.ts
|
||||
import { TaskService } from './TaskService'; // Circular dependency!
|
||||
|
||||
export class UserService {
|
||||
constructor(private taskService: TaskService) {}
|
||||
}
|
||||
```
|
||||
|
||||
**Solution 1: Extract shared type definitions**
|
||||
```typescript
|
||||
// types/Service.ts
|
||||
export interface ITaskService { /* ... */ }
|
||||
export interface IUserService { /* ... */ }
|
||||
|
||||
// services/TaskService.ts
|
||||
import type { IUserService } from '../types/Service';
|
||||
|
||||
export class TaskService {
|
||||
constructor(private userService: IUserService) {}
|
||||
}
|
||||
|
||||
// services/UserService.ts
|
||||
import type { ITaskService } from '../types/Service';
|
||||
|
||||
export class UserService {
|
||||
constructor(private taskService: ITaskService) {}
|
||||
}
|
||||
```
|
||||
|
||||
**Solution 2: Rethink the dependencies**
|
||||
```typescript
|
||||
// Extract shared functionality into a separate service
|
||||
// services/NotificationService.ts
|
||||
export class NotificationService {
|
||||
notifyTaskAssignment(taskId: string, userId: string): void {
|
||||
// Notification handling
|
||||
}
|
||||
}
|
||||
|
||||
// services/TaskService.ts
|
||||
import { NotificationService } from './NotificationService';
|
||||
|
||||
export class TaskService {
|
||||
constructor(private notificationService: NotificationService) {}
|
||||
}
|
||||
|
||||
// services/UserService.ts
|
||||
import { NotificationService } from './NotificationService';
|
||||
|
||||
export class UserService {
|
||||
constructor(private notificationService: NotificationService) {}
|
||||
}
|
||||
```
|
||||
|
||||
## Scaling Strategy
|
||||
|
||||
### Recommended Structure
|
||||
|
||||
**Standard pattern**:
|
||||
```
|
||||
src/
|
||||
├── commands/
|
||||
│ └── TaskCommand.ts
|
||||
├── services/
|
||||
│ ├── TaskService.ts
|
||||
│ └── UserService.ts
|
||||
├── repositories/
|
||||
│ ├── TaskRepository.ts
|
||||
│ └── UserRepository.ts
|
||||
├── types/
|
||||
│ ├── Task.ts
|
||||
│ └── User.ts
|
||||
├── validators/
|
||||
│ └── TaskValidator.ts
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
**Rationale**:
|
||||
- Responsibilities are clear per layer
|
||||
- No later refactoring required
|
||||
- Easy to standardize across a team
|
||||
|
||||
### Timing for Module Separation
|
||||
|
||||
**Signs that separation should be considered**:
|
||||
1. A directory contains 10 or more files
|
||||
2. Related functionality is grouped together
|
||||
3. It can be tested independently
|
||||
4. It has few dependencies on other features
|
||||
|
||||
**Separation procedure**:
|
||||
```typescript
|
||||
// Before: everything placed in services/
|
||||
services/
|
||||
├── TaskService.ts
|
||||
├── TaskValidationService.ts
|
||||
├── TaskNotificationService.ts
|
||||
├── UserService.ts
|
||||
└── UserAuthService.ts
|
||||
|
||||
// After: modularized by feature
|
||||
modules/
|
||||
├── task/
|
||||
│ ├── TaskService.ts
|
||||
│ ├── TaskValidationService.ts
|
||||
│ └── TaskNotificationService.ts
|
||||
└── user/
|
||||
├── UserService.ts
|
||||
└── UserAuthService.ts
|
||||
```
|
||||
|
||||
## Handling Special Cases
|
||||
|
||||
### Placement of Shared Code
|
||||
|
||||
**shared/ or common/ directory**
|
||||
```
|
||||
src/
|
||||
├── shared/
|
||||
│ ├── utils/ # General-purpose utilities
|
||||
│ ├── types/ # Shared type definitions
|
||||
│ └── constants/ # Shared constants
|
||||
├── commands/
|
||||
├── services/
|
||||
└── repositories/
|
||||
```
|
||||
|
||||
**Rules**:
|
||||
- Only things genuinely used across multiple layers
|
||||
- Do not include anything used in only a single layer
|
||||
|
||||
### Managing Configuration Files (when applicable)
|
||||
|
||||
```
|
||||
config/
|
||||
├── default.ts # Default settings
|
||||
└── constants.ts # Constant definitions
|
||||
```
|
||||
|
||||
### Managing Scripts (when applicable)
|
||||
|
||||
```
|
||||
scripts/
|
||||
├── build.sh # Build script
|
||||
└── dev-tools.ts # Development helper script
|
||||
```
|
||||
|
||||
## Document Placement
|
||||
|
||||
### Document Types and Their Locations
|
||||
|
||||
**Project root**:
|
||||
- `README.md`: Project overview
|
||||
- `CONTRIBUTING.md`: Contribution guide
|
||||
- `LICENSE`: License
|
||||
|
||||
**docs/ directory**:
|
||||
- `product-requirements.md`: PRD
|
||||
- `functional-design.md`: Functional design document
|
||||
- `architecture.md`: Architecture design document
|
||||
- `repository-structure.md`: This document
|
||||
- `development-guidelines.md`: Development guidelines
|
||||
- `glossary.md`: Glossary
|
||||
|
||||
**Within the source code**:
|
||||
- TSDoc/JSDoc comments: Descriptions of functions and classes
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Each directory's role is clearly defined
|
||||
- [ ] The layer structure is reflected in the directories
|
||||
- [ ] Naming conventions are consistent
|
||||
- [ ] The placement policy for test code is decided
|
||||
- [ ] Dependency rules are clear
|
||||
- [ ] There are no circular dependencies
|
||||
- [ ] A scaling strategy has been considered
|
||||
- [ ] Placement rules for shared code are defined
|
||||
- [ ] A management method for configuration files is decided
|
||||
- [ ] Document locations are clear
|
||||
306
.opencode/skills/repository-structure/template.md
Normal file
306
.opencode/skills/repository-structure/template.md
Normal file
@ -0,0 +1,306 @@
|
||||
# Repository Structure Document
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
project-root/
|
||||
├── src/ # Source code
|
||||
│ ├── [layer1]/ # [Description]
|
||||
│ ├── [layer2]/ # [Description]
|
||||
│ └── [layer3]/ # [Description]
|
||||
├── tests/ # Test code
|
||||
│ ├── unit/ # Unit tests
|
||||
│ ├── integration/ # Integration tests
|
||||
│ └── e2e/ # E2E tests
|
||||
├── docs/ # Project documentation
|
||||
├── config/ # Configuration files
|
||||
└── scripts/ # Build/deploy scripts
|
||||
```
|
||||
|
||||
## Directory Details
|
||||
|
||||
### src/ (Source Code Directory)
|
||||
|
||||
#### [Directory 1]
|
||||
|
||||
**Role**: [Description]
|
||||
|
||||
**Files placed here**:
|
||||
- [File pattern 1]: [Description]
|
||||
- [File pattern 2]: [Description]
|
||||
|
||||
**Naming conventions**:
|
||||
- [Rule 1]
|
||||
- [Rule 2]
|
||||
|
||||
**Dependencies**:
|
||||
- May depend on: [Directory name]
|
||||
- Must not depend on: [Directory name]
|
||||
|
||||
**Example**:
|
||||
```
|
||||
[Directory name]/
|
||||
├── [example-file1].ts
|
||||
└── [example-file2].ts
|
||||
```
|
||||
|
||||
#### [Directory 2]
|
||||
|
||||
**Role**: [Description]
|
||||
|
||||
**Files placed here**:
|
||||
- [File pattern 1]: [Description]
|
||||
|
||||
**Naming conventions**:
|
||||
- [Rule 1]
|
||||
|
||||
**Dependencies**:
|
||||
- May depend on: [Directory name]
|
||||
- Must not depend on: [Directory name]
|
||||
|
||||
### tests/ (Test Directory)
|
||||
|
||||
#### unit/
|
||||
|
||||
**Role**: Placement of unit tests
|
||||
|
||||
**Structure**:
|
||||
```
|
||||
tests/unit/
|
||||
└── src/ # Same structure as the src directory
|
||||
└── [layer]/
|
||||
└── [filename].test.ts
|
||||
```
|
||||
|
||||
**Naming conventions**:
|
||||
- Pattern: `[name of file under test].test.ts`
|
||||
- Example: `TaskService.ts` → `TaskService.test.ts`
|
||||
|
||||
#### integration/
|
||||
|
||||
**Role**: Placement of integration tests
|
||||
|
||||
**Structure**:
|
||||
```
|
||||
tests/integration/
|
||||
└── [feature]/ # Split into directories by feature
|
||||
└── [scenario].test.ts
|
||||
```
|
||||
|
||||
#### e2e/
|
||||
|
||||
**Role**: Placement of E2E tests
|
||||
|
||||
**Structure**:
|
||||
```
|
||||
tests/e2e/
|
||||
└── [user-scenario]/ # By user scenario
|
||||
└── [flow].test.ts
|
||||
```
|
||||
|
||||
### docs/ (Documentation Directory)
|
||||
|
||||
**Documents placed here**:
|
||||
- `product-requirements.md`: Product Requirements Document
|
||||
- `functional-design.md`: Functional design document
|
||||
- `architecture.md`: Architecture design document
|
||||
- `repository-structure.md`: Repository structure document (this document)
|
||||
- `development-guidelines.md`: Development guidelines
|
||||
- `glossary.md`: Glossary
|
||||
|
||||
### config/ (Configuration File Directory - when applicable)
|
||||
|
||||
**Files placed here**:
|
||||
- Configuration files
|
||||
- Constant definition files
|
||||
|
||||
**Example**:
|
||||
```
|
||||
config/
|
||||
├── default.ts
|
||||
└── constants.ts
|
||||
```
|
||||
|
||||
### scripts/ (Script Directory - when applicable)
|
||||
|
||||
**Files placed here**:
|
||||
- Build scripts
|
||||
- Development helper scripts
|
||||
|
||||
## File Placement Rules
|
||||
|
||||
### Source Files
|
||||
|
||||
| File type | Location | Naming convention | Example |
|
||||
|------------|--------|---------|-----|
|
||||
| [Type 1] | [Directory] | [Rule] | [Example] |
|
||||
| [Type 2] | [Directory] | [Rule] | [Example] |
|
||||
|
||||
### Test Files
|
||||
|
||||
| Test type | Location | Naming convention | Example |
|
||||
|-----------|--------|---------|-----|
|
||||
| Unit test | tests/unit/ | [target].test.ts | TaskService.test.ts |
|
||||
| Integration test | tests/integration/ | [feature].test.ts | task-crud.test.ts |
|
||||
| E2E test | tests/e2e/ | [scenario].test.ts | user-workflow.test.ts |
|
||||
|
||||
### Configuration Files
|
||||
|
||||
| File type | Location | Naming convention |
|
||||
|------------|--------|---------|
|
||||
| Environment config | config/environments/ | [environment-name].ts |
|
||||
| Tool config | Project root | [tool-name].config.js |
|
||||
| Type definitions | src/types/ | [target].d.ts |
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
### Directory Names
|
||||
|
||||
- **Layer directories**: plural, kebab-case
|
||||
- Example: `services/`, `repositories/`, `controllers/`
|
||||
- **Feature directories**: singular, kebab-case
|
||||
- Example: `task-management/`, `user-authentication/`
|
||||
|
||||
### File Names
|
||||
|
||||
- **Class files**: PascalCase
|
||||
- Example: `TaskService.ts`, `UserRepository.ts`
|
||||
- **Function files**: camelCase
|
||||
- Example: `formatDate.ts`, `validateEmail.ts`
|
||||
- **Constant files**: UPPER_SNAKE_CASE
|
||||
- Example: `API_ENDPOINTS.ts`, `ERROR_MESSAGES.ts`
|
||||
|
||||
### Test File Names
|
||||
|
||||
- Pattern: `[target].test.ts` or `[target].spec.ts`
|
||||
- Example: `TaskService.test.ts`, `formatDate.spec.ts`
|
||||
|
||||
## Dependency Rules
|
||||
|
||||
### Dependencies Between Layers
|
||||
|
||||
```
|
||||
UI layer
|
||||
↓ (OK)
|
||||
Service layer
|
||||
↓ (OK)
|
||||
Data layer
|
||||
```
|
||||
|
||||
**Forbidden dependencies**:
|
||||
- Data layer → Service layer (❌)
|
||||
- Data layer → UI layer (❌)
|
||||
- Service layer → UI layer (❌)
|
||||
|
||||
### Dependencies Between Modules
|
||||
|
||||
**No circular dependencies**:
|
||||
```typescript
|
||||
// ❌ Bad example: circular dependency
|
||||
// fileA.ts
|
||||
import { funcB } from './fileB';
|
||||
|
||||
// fileB.ts
|
||||
import { funcA } from './fileA'; // Circular dependency
|
||||
```
|
||||
|
||||
**Solution**:
|
||||
```typescript
|
||||
// ✅ Good example: extract a shared module
|
||||
// shared.ts
|
||||
export interface SharedType { /* ... */ }
|
||||
|
||||
// fileA.ts
|
||||
import { SharedType } from './shared';
|
||||
|
||||
// fileB.ts
|
||||
import { SharedType } from './shared';
|
||||
```
|
||||
|
||||
## Scaling Strategy
|
||||
|
||||
### Adding Features
|
||||
|
||||
Placement policy when adding new features:
|
||||
|
||||
1. **Small features**: place in an existing directory
|
||||
2. **Medium features**: create a subdirectory within a layer
|
||||
3. **Large features**: separate into an independent module
|
||||
|
||||
**Example**:
|
||||
```
|
||||
src/
|
||||
├── services/
|
||||
│ ├── TaskService.ts # Existing feature
|
||||
│ └── task-management/ # Separation of a medium feature
|
||||
│ ├── TaskService.ts
|
||||
│ ├── SubtaskService.ts
|
||||
│ └── TaskCategoryService.ts
|
||||
```
|
||||
|
||||
### Managing File Size
|
||||
|
||||
**Guidelines for splitting files**:
|
||||
- A single file: 300 lines or fewer recommended
|
||||
- 300-500 lines: consider refactoring
|
||||
- 500 lines or more: splitting strongly recommended
|
||||
|
||||
**How to split**:
|
||||
```typescript
|
||||
// Bad example: all functionality in one file
|
||||
// TaskService.ts (800 lines)
|
||||
|
||||
// Good example: split by responsibility
|
||||
// TaskService.ts (200 lines) - CRUD operations
|
||||
// TaskValidationService.ts (150 lines) - validation
|
||||
// TaskNotificationService.ts (100 lines) - notification handling
|
||||
```
|
||||
|
||||
## Special Directories
|
||||
|
||||
### .steering/ (Steering Files)
|
||||
|
||||
**Role**: Define "what to do this time" for a specific development task
|
||||
|
||||
**Structure**:
|
||||
```
|
||||
.steering/
|
||||
└── [YYYYMMDD]-[task-name]/
|
||||
├── requirements.md # Requirements for this task
|
||||
├── design.md # Design of the changes
|
||||
└── tasklist.md # Task list
|
||||
```
|
||||
|
||||
**Naming convention**: `20250115-add-user-profile` format
|
||||
|
||||
### .opencode/ (opencode Settings)
|
||||
|
||||
**Role**: opencode settings and customization
|
||||
|
||||
**Structure**:
|
||||
```
|
||||
.opencode/
|
||||
├── command/ # Slash commands
|
||||
├── skills/ # Task-specific skills
|
||||
└── agent/ # Subagent definitions
|
||||
```
|
||||
|
||||
## Exclusion Settings
|
||||
|
||||
### .gitignore
|
||||
|
||||
Files that should be excluded in the project:
|
||||
- `node_modules/`
|
||||
- `dist/`
|
||||
- `.env`
|
||||
- `.steering/` (temporary files for task management)
|
||||
- `*.log`
|
||||
- `.DS_Store`
|
||||
|
||||
### .prettierignore, .eslintignore
|
||||
|
||||
Files that should be excluded by tooling:
|
||||
- `dist/`
|
||||
- `node_modules/`
|
||||
- `.steering/`
|
||||
- `coverage/`
|
||||
383
.opencode/skills/steering/SKILL.md
Normal file
383
.opencode/skills/steering/SKILL.md
Normal file
@ -0,0 +1,383 @@
|
||||
---
|
||||
name: steering
|
||||
description: A skill for recording the work plan and task list for each work instruction in documents. Load it during work planning, implementation, and verification triggered by user instructions.
|
||||
---
|
||||
|
||||
# Steering Skill
|
||||
|
||||
A skill that supports implementation based on steering files (`.steering/`) and reliably manages progress in tasklist.md.
|
||||
|
||||
## Purpose of This Skill
|
||||
|
||||
- Support creation of steering files (requirements.md, design.md, tasklist.md)
|
||||
- Manage incremental implementation based on tasklist.md
|
||||
- **Automatically track progress and enforce tasklist.md updates**
|
||||
- Record a retrospective after implementation is complete
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this skill at the following times:
|
||||
|
||||
1. **During work planning**: when creating steering files
|
||||
2. **During implementation**: when implementing according to tasklist.md
|
||||
3. **During verification**: when recording the retrospective after implementation is complete
|
||||
|
||||
## Mode 1: Creating Steering Files
|
||||
|
||||
### Purpose
|
||||
Create steering files for a new feature or change.
|
||||
|
||||
### Procedure
|
||||
|
||||
1. **Check the steering directory**
|
||||
```
|
||||
Get the current date and create a directory in the form `.steering/[YYYYMMDD]-[feature-name]/`
|
||||
```
|
||||
|
||||
2. **Review the persistent documents**
|
||||
- `docs/product-requirements.md`
|
||||
- `docs/functional-design.md`
|
||||
- `docs/architecture.md`
|
||||
- `docs/repository-structure.md`
|
||||
- `docs/development-guidelines.md`
|
||||
|
||||
Read these to understand the project's direction
|
||||
|
||||
3. **Create files from templates**
|
||||
|
||||
Load the following templates, replace the placeholders with concrete content, and create the files:
|
||||
|
||||
- `.opencode/skills/steering/templates/requirements.md` → `.steering/[date]-[feature-name]/requirements.md`
|
||||
- `.opencode/skills/steering/templates/design.md` → `.steering/[date]-[feature-name]/design.md`
|
||||
- `.opencode/skills/steering/templates/tasklist.md` → `.steering/[date]-[feature-name]/tasklist.md`
|
||||
|
||||
4. **Detail out tasklist.md**
|
||||
|
||||
Based on requirements.md and design.md, flesh out tasklist.md:
|
||||
- Describe the tasks of each phase concretely
|
||||
- Make subtasks clear as well
|
||||
- State the order of implementation
|
||||
|
||||
## Mode 2: Implementation (Most Important)
|
||||
|
||||
### Purpose
|
||||
Proceed with implementation according to tasklist.md and **reliably record progress in the document**.
|
||||
|
||||
### 🚨 Important Principles
|
||||
|
||||
**MUST**:
|
||||
- Implement with tasklist.md always open
|
||||
- When starting a task, always update `[ ]`→`[x]` using the edit tool
|
||||
- When completing a task, always record completion using the edit tool
|
||||
- **Keep working until all tasks in tasklist.md are complete**
|
||||
- NEVER: do not move on to the next task without updating tasklist.md
|
||||
|
||||
**NEVER**:
|
||||
- Proceed with implementation without looking at tasklist.md
|
||||
- Manage progress with the todowrite tool alone (todowrite is a helper; tasklist.md is the official record)
|
||||
- Update multiple tasks in batch (update in real time)
|
||||
- **Skip a task for reasons such as "due to time constraints" or "planned as a separate task"**
|
||||
- **Finish work while leaving incomplete tasks (`[ ]`)**
|
||||
|
||||
### 🚨 Principle of Fully Completing Tasks
|
||||
|
||||
**Rules that absolutely must be followed**:
|
||||
|
||||
1. **Keep working until all tasks in tasklist.md are complete**
|
||||
- Continue implementation until every task is `[x]`
|
||||
- Do not skip for reasons such as "it takes too long" or "it's difficult"
|
||||
- Do not write a retrospective while incomplete tasks remain
|
||||
|
||||
2. **Skipping tasks is forbidden in principle**
|
||||
- "Planned as a separate task due to time constraints" is forbidden
|
||||
- "Postponed because the implementation is too complex" is forbidden
|
||||
- Reasons such as "it's difficult, do it later" or "testing is a hassle" are forbidden
|
||||
- Skipping is permitted only for technical reasons (see below)
|
||||
|
||||
3. **How to handle a task that is too large**
|
||||
- Split the task into smaller subtasks
|
||||
- Add the split subtasks to tasklist.md
|
||||
- Complete the subtasks one by one
|
||||
|
||||
4. **Skipping is permitted only when a task becomes unnecessary for technical reasons**
|
||||
|
||||
Skipping is possible only when one of the following technical reasons applies:
|
||||
- A change in the implementation approach made the feature itself unnecessary
|
||||
- An architecture change replaced it with a different implementation method
|
||||
- A change in dependencies made the task impossible to execute
|
||||
- An upper-level design change made this task meaningless
|
||||
|
||||
Skip procedure:
|
||||
- Clearly state the technical reason in tasklist.md and mark it as skipped
|
||||
- Example: `- [x] ~~task name~~ (unnecessary due to a change in approach: the architecture was changed from X to Y, so this layer is no longer needed)`
|
||||
- Record the reason for the change in detail in the retrospective section
|
||||
|
||||
5. **Bad examples when incomplete tasks remain**
|
||||
```markdown
|
||||
## Post-Implementation Retrospective
|
||||
**Tasks not implemented**:
|
||||
- Implementing tests (planned as a separate task due to time constraints) ❌ Absolutely not allowed
|
||||
```
|
||||
|
||||
6. **What correct completion looks like**
|
||||
- All tasks are `[x]`
|
||||
- There is no "tasks not implemented" entry in the retrospective section
|
||||
- If the implementation approach changed, the reason is clearly stated
|
||||
|
||||
### Implementation Flow
|
||||
|
||||
#### Step 1: Load tasklist.md
|
||||
|
||||
Read `.steering/[date]-[feature-name]/tasklist.md`
|
||||
|
||||
Grasp the overall task structure and identify the next task to work on.
|
||||
|
||||
#### Step 2: Start task management with todowrite
|
||||
|
||||
Based on the contents of tasklist.md, create a task list with the todowrite tool:
|
||||
- This is an auxiliary, internal note
|
||||
- **tasklist.md is the official document**
|
||||
|
||||
#### Step 3: Task Loop (repeat for each task)
|
||||
|
||||
**3-1. Check the next task**
|
||||
```
|
||||
Read tasklist.md and identify the next incomplete task (`[ ]`)
|
||||
```
|
||||
|
||||
**3-2. Record the task start in tasklist.md (required)**
|
||||
```
|
||||
Use the edit tool to update the relevant line in tasklist.md from `[ ]`→`[x]`
|
||||
|
||||
Example:
|
||||
old_string: "- [ ] Implement StorageService"
|
||||
new_string: "- [x] Implement StorageService"
|
||||
```
|
||||
|
||||
**Important**: Immediately after running the edit tool, confirm that the update succeeded.
|
||||
|
||||
**3-3. Update the status in todowrite as well**
|
||||
```
|
||||
Change the relevant task to "in_progress" with the todowrite tool
|
||||
```
|
||||
|
||||
**3-4. Carry out the implementation**
|
||||
```
|
||||
Implement according to the development guidelines (docs/development-guidelines.md)
|
||||
```
|
||||
|
||||
**3-5. Record task completion in tasklist.md (required)**
|
||||
```
|
||||
After implementation is complete, always update tasklist.md with the edit tool to record completion
|
||||
|
||||
If there are subtasks, update each subtask individually as well
|
||||
```
|
||||
|
||||
**3-6. Update the status in todowrite as well**
|
||||
```
|
||||
Change the relevant task to "completed" with the todowrite tool
|
||||
```
|
||||
|
||||
**3-7. On to the next task**
|
||||
```
|
||||
Return to Step 3-1
|
||||
```
|
||||
|
||||
#### Step 4: Checking at Phase Completion
|
||||
|
||||
When each phase (e.g., Phase 1, Phase 2) is complete:
|
||||
|
||||
1. **Load tasklist.md and check progress**
|
||||
```
|
||||
Read `.steering/[date]-[feature-name]/tasklist.md`
|
||||
```
|
||||
|
||||
2. **Check completed tasks**
|
||||
- Are all tasks `[x]`?
|
||||
- Are there any tasks that were overlooked?
|
||||
|
||||
3. **Report to the user**
|
||||
```
|
||||
"Phase 1 is complete. Please check the progress in tasklist.md."
|
||||
```
|
||||
|
||||
#### Step 4.5: All-Tasks-Complete Check (required)
|
||||
|
||||
**Always run this after implementing all phases, before writing the retrospective**:
|
||||
|
||||
1. **Load tasklist.md**
|
||||
```
|
||||
Read `.steering/[date]-[feature-name]/tasklist.md`
|
||||
```
|
||||
|
||||
2. **Check for incomplete tasks (`[ ]`)**
|
||||
- Are all tasks `[x]`?
|
||||
- Is there even one `[ ]` remaining?
|
||||
|
||||
3. **If an incomplete task is found**
|
||||
|
||||
**❌ What you must not do**:
|
||||
- Write "planned as a separate task due to time constraints" in the retrospective
|
||||
- Ignore the incomplete task and move on to the next step
|
||||
|
||||
**✅ The correct response**:
|
||||
|
||||
**Pattern A: Implement the task**
|
||||
```
|
||||
Return to Step 3 (the task loop) and implement the incomplete task
|
||||
```
|
||||
|
||||
**Pattern B: If the task is too large**
|
||||
```
|
||||
1. Split the task into smaller subtasks
|
||||
2. Add the split subtasks to tasklist.md
|
||||
3. Complete the subtasks one by one
|
||||
```
|
||||
|
||||
**Pattern C: Only when a task became unnecessary for technical reasons**
|
||||
|
||||
Skipping is possible only when one of the following technical reasons applies:
|
||||
- A change in the implementation approach made the feature itself unnecessary
|
||||
- An architecture change replaced it with a different implementation method
|
||||
- A change in dependencies made the task impossible to execute
|
||||
|
||||
Skip procedure:
|
||||
```
|
||||
1. Clearly state the technical reason in tasklist.md:
|
||||
"- [x] ~~task name~~ (unnecessary due to a change in approach: describe the specific technical reason in detail)"
|
||||
2. Record the reason for the change in detail in the retrospective section
|
||||
3. Clearly describe why this task became unnecessary and what it was replaced with
|
||||
```
|
||||
|
||||
4. **Proceed only after confirming all tasks are complete**
|
||||
```
|
||||
Confirm that every task is `[x]` before proceeding to Step 5
|
||||
```
|
||||
|
||||
#### Step 5: After All Tasks Are Complete
|
||||
|
||||
1. **Final check**
|
||||
```
|
||||
Read `.steering/[date]-[feature-name]/tasklist.md`
|
||||
```
|
||||
|
||||
Confirm that every task is `[x]`
|
||||
|
||||
2. **Record in the retrospective section**
|
||||
```
|
||||
Update the "Post-Implementation Retrospective" section of tasklist.md with the edit tool:
|
||||
- Implementation completion date
|
||||
- Differences between plan and actual
|
||||
- Lessons learned
|
||||
- Improvement suggestions for next time
|
||||
```
|
||||
|
||||
### Self-Check During Implementation
|
||||
|
||||
Every 5 tasks, check the following:
|
||||
|
||||
- [ ] Did you recently update tasklist.md? (within 5 tasks since the last update)
|
||||
- [ ] Is progress reflected in the document? (verify with the read tool)
|
||||
- [ ] Can the user understand the progress by looking at tasklist.md?
|
||||
|
||||
## Mode 3: Retrospective
|
||||
|
||||
### Purpose
|
||||
After implementation is complete, record a retrospective in tasklist.md.
|
||||
|
||||
### Procedure
|
||||
|
||||
1. **Load tasklist.md**
|
||||
```
|
||||
Read `.steering/[date]-[feature-name]/tasklist.md`
|
||||
```
|
||||
|
||||
2. **Write the retrospective content**
|
||||
- Implementation completion date
|
||||
- Differences between plan and actual (points that differed from the plan)
|
||||
- Lessons learned (technical insights, process improvements)
|
||||
- Improvement suggestions for next time
|
||||
|
||||
3. **Update with the edit tool**
|
||||
```
|
||||
Update the "Post-Implementation Retrospective" section of tasklist.md
|
||||
```
|
||||
|
||||
4. **Report to the user**
|
||||
```
|
||||
"I have recorded the retrospective in tasklist.md. Please check the content."
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### If you forgot to update tasklist.md
|
||||
|
||||
If you notice during implementation that you forgot to update tasklist.md:
|
||||
|
||||
1. **Update immediately**
|
||||
```
|
||||
Read `.steering/[date]-[feature-name]/tasklist.md`
|
||||
Identify the completed tasks and update them all to `[x]` with the edit tool
|
||||
```
|
||||
|
||||
2. **Report to the user**
|
||||
```
|
||||
"The tasklist.md update was delayed, so I have reflected the current progress."
|
||||
```
|
||||
|
||||
3. **Prevent recurrence**
|
||||
- Update reliably from the next task onward
|
||||
- Strictly follow the self-check every 5 tasks
|
||||
|
||||
### Divergence between tasklist.md and the implementation
|
||||
|
||||
When the plan and the implementation differ significantly:
|
||||
|
||||
1. **Add an annotation to tasklist.md**
|
||||
```
|
||||
Add an annotation to the relevant task with the edit tool:
|
||||
"- [x] task name (changed implementation method: reason)"
|
||||
```
|
||||
|
||||
2. **Add new tasks as needed**
|
||||
```
|
||||
Add new tasks with the edit tool
|
||||
```
|
||||
|
||||
3. **Update design.md too**
|
||||
```
|
||||
If the design change is significant, update design.md as well
|
||||
```
|
||||
|
||||
## Checklist (Most Important)
|
||||
|
||||
Always check before implementation:
|
||||
|
||||
- [ ] Did you load tasklist.md?
|
||||
- [ ] Did you identify the next task?
|
||||
- [ ] Did you update with the edit tool when starting the task?
|
||||
|
||||
Always check after implementation:
|
||||
|
||||
- [ ] Did you update with the edit tool when completing the task?
|
||||
- [ ] Did you check the progress in tasklist.md?
|
||||
- [ ] Is it in a state where the user can understand the progress?
|
||||
|
||||
## Effects of This Skill
|
||||
|
||||
When this skill is used correctly:
|
||||
|
||||
- ✅ tasklist.md always reflects the latest progress
|
||||
- ✅ The user can grasp progress at a glance
|
||||
- ✅ Divergence between the document and the implementation disappears
|
||||
- ✅ Retrospectives become easy, leading to improvements next time
|
||||
- ✅ A record valuable as project history remains
|
||||
|
||||
## Important Reminder
|
||||
|
||||
🚨 **The most important role of this skill is to reliably manage the progress of tasklist.md.**
|
||||
|
||||
- todowrite is a volatile note (not visible to the user)
|
||||
- **tasklist.md is the persistent document (the user sees it)**
|
||||
|
||||
During implementation, always ask yourself, "When the user looks at tasklist.md, can they understand the progress?"
|
||||
96
.opencode/skills/steering/templates/design.md
Normal file
96
.opencode/skills/steering/templates/design.md
Normal file
@ -0,0 +1,96 @@
|
||||
# Design Document
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
{Describe the architecture pattern to adopt}
|
||||
|
||||
```
|
||||
{Describe the architecture diagram in text or Mermaid}
|
||||
```
|
||||
|
||||
## Component Design
|
||||
|
||||
### 1. {Component name 1}
|
||||
|
||||
**Responsibilities**:
|
||||
- {Responsibility 1}
|
||||
- {Responsibility 2}
|
||||
|
||||
**Implementation highlights**:
|
||||
- {Points to note during implementation}
|
||||
- {Technical constraints}
|
||||
|
||||
### 2. {Component name 2}
|
||||
|
||||
**Responsibilities**:
|
||||
- {Responsibility 1}
|
||||
- {Responsibility 2}
|
||||
|
||||
**Implementation highlights**:
|
||||
- {Points to note during implementation}
|
||||
- {Technical constraints}
|
||||
|
||||
## Data Flow
|
||||
|
||||
### {Use case name}
|
||||
```
|
||||
1. {Step 1}
|
||||
2. {Step 2}
|
||||
3. {Step 3}
|
||||
```
|
||||
|
||||
## Error Handling Strategy
|
||||
|
||||
### Custom Error Classes
|
||||
|
||||
{Define the necessary error classes}
|
||||
|
||||
### Error Handling Patterns
|
||||
|
||||
{How errors are handled}
|
||||
|
||||
## Test Strategy
|
||||
|
||||
### Unit Tests
|
||||
- {Test target 1}
|
||||
- {Test target 2}
|
||||
|
||||
### Integration Tests
|
||||
- {Test scenario 1}
|
||||
- {Test scenario 2}
|
||||
|
||||
## Dependent Libraries
|
||||
|
||||
{Describe any newly added libraries}
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"{library name}": "{version}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
{File structure to be added or changed}
|
||||
```
|
||||
|
||||
## Implementation Order
|
||||
|
||||
1. {Implementation step 1}
|
||||
2. {Implementation step 2}
|
||||
3. {Implementation step 3}
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- {Security-related points to note}
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- {Performance-related points to note}
|
||||
|
||||
## Future Extensibility
|
||||
|
||||
{A design that accounts for future extensions}
|
||||
48
.opencode/skills/steering/templates/requirements.md
Normal file
48
.opencode/skills/steering/templates/requirements.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Requirements
|
||||
|
||||
## Overview
|
||||
|
||||
{Describe the feature overview in 1-2 sentences}
|
||||
|
||||
## Background
|
||||
|
||||
{Why this feature is needed and what problem it solves}
|
||||
|
||||
## Features to Implement
|
||||
|
||||
### 1. {Feature name 1}
|
||||
- {Specific feature description}
|
||||
- {What the user will be able to do}
|
||||
|
||||
### 2. {Feature name 2}
|
||||
- {Specific feature description}
|
||||
- {What the user will be able to do}
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### {Feature name 1}
|
||||
- [ ] {Verifiable condition 1}
|
||||
- [ ] {Verifiable condition 2}
|
||||
- [ ] {Verifiable condition 3}
|
||||
|
||||
### {Feature name 2}
|
||||
- [ ] {Verifiable condition 1}
|
||||
- [ ] {Verifiable condition 2}
|
||||
|
||||
## Success Metrics
|
||||
|
||||
- {Describe quantitative goals if any}
|
||||
- {Describe qualitative goals if any}
|
||||
|
||||
## Out of Scope
|
||||
|
||||
The following will not be implemented in this phase:
|
||||
|
||||
- {Feature not implemented 1}
|
||||
- {Feature not implemented 2}
|
||||
|
||||
## Reference Documents
|
||||
|
||||
- `docs/product-requirements.md` - Product Requirements Document
|
||||
- `docs/functional-design.md` - Functional design document
|
||||
- `docs/architecture.md` - Architecture design document
|
||||
107
.opencode/skills/steering/templates/tasklist.md
Normal file
107
.opencode/skills/steering/templates/tasklist.md
Normal file
@ -0,0 +1,107 @@
|
||||
# Task List
|
||||
|
||||
## 🚨 Principle of Fully Completing Tasks
|
||||
|
||||
**Keep working until all tasks in this file are complete**
|
||||
|
||||
### Mandatory Rules
|
||||
- **Make every task `[x]`**
|
||||
- "Planned as a separate task due to time constraints" is forbidden
|
||||
- "Postponed because the implementation is too complex" is forbidden
|
||||
- Do not finish work while leaving incomplete tasks (`[ ]`)
|
||||
|
||||
### Plan Only Tasks That Can Be Implemented
|
||||
- At the planning stage, list only "tasks that can be implemented"
|
||||
- Do not include "tasks that might be done in the future"
|
||||
- Do not include "tasks under consideration"
|
||||
|
||||
### The Only Case Where Skipping a Task Is Permitted
|
||||
Skipping is possible only when one of the following technical reasons applies:
|
||||
- A change in the implementation approach made the feature itself unnecessary
|
||||
- An architecture change replaced it with a different implementation method
|
||||
- A change in dependencies made the task impossible to execute
|
||||
|
||||
When skipping, always state the reason clearly:
|
||||
```markdown
|
||||
- [x] ~~task name~~ (unnecessary due to a change in approach: specific technical reason)
|
||||
```
|
||||
|
||||
### If a Task Is Too Large
|
||||
- Split the task into smaller subtasks
|
||||
- Add the split subtasks to this file
|
||||
- Complete the subtasks one by one
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: {Phase name}
|
||||
|
||||
- [ ] {Task 1}
|
||||
- [ ] {Subtask 1-1}
|
||||
- [ ] {Subtask 1-2}
|
||||
|
||||
- [ ] {Task 2}
|
||||
- [ ] {Subtask 2-1}
|
||||
- [ ] {Subtask 2-2}
|
||||
|
||||
## Phase 2: {Phase name}
|
||||
|
||||
- [ ] {Task 1}
|
||||
- [ ] {Subtask 1-1}
|
||||
- [ ] {Subtask 1-2}
|
||||
|
||||
- [ ] {Task 2}
|
||||
|
||||
## Phase 3: Quality Check and Fixes
|
||||
|
||||
- [ ] Confirm that all tests pass
|
||||
- [ ] `npm test`
|
||||
- [ ] Confirm that there are no lint errors
|
||||
- [ ] `npm run lint`
|
||||
- [ ] Confirm that there are no type errors
|
||||
- [ ] `npm run typecheck`
|
||||
- [ ] Confirm that the build succeeds
|
||||
- [ ] `npm run build`
|
||||
|
||||
## Phase 4: Documentation Updates
|
||||
|
||||
- [ ] Update README.md (as needed)
|
||||
- [ ] Post-implementation retrospective (record at the bottom of this file)
|
||||
|
||||
---
|
||||
|
||||
## Post-Implementation Retrospective
|
||||
|
||||
### Implementation Completion Date
|
||||
{YYYY-MM-DD}
|
||||
|
||||
### Differences Between Plan and Actual
|
||||
|
||||
**Points that differed from the plan**:
|
||||
- {Technical changes not anticipated at planning time}
|
||||
- {Changes in the implementation approach and the reasons}
|
||||
|
||||
**Tasks that became newly necessary**:
|
||||
- {Tasks added during implementation}
|
||||
- {Why the addition was necessary}
|
||||
|
||||
**Tasks skipped for technical reasons** (only when applicable):
|
||||
- {Task name}
|
||||
- Reason for skipping: {specific technical reason}
|
||||
- Alternative implementation: {what it was replaced with}
|
||||
|
||||
**⚠️ Note**: Do not list tasks skipped for reasons such as "time constraints" or "difficulty" here. Completing all tasks is the principle.
|
||||
|
||||
### Lessons Learned
|
||||
|
||||
**Technical insights**:
|
||||
- {Technical knowledge gained through implementation}
|
||||
- {New technologies or patterns used}
|
||||
|
||||
**Process improvements**:
|
||||
- {What went well in task management}
|
||||
- {How the steering files were leveraged}
|
||||
|
||||
### Improvement Suggestions for Next Time
|
||||
- {Things to watch out for in the next feature addition}
|
||||
- {More efficient implementation methods}
|
||||
- {Improvements to task planning}
|
||||
Reference in New Issue
Block a user