feat: initial commit - opencode spec-driven development boilerplate

Converted from Claude Code boilerplate to opencode:
- CLAUDE.md -> AGENTS.md (opencode instructions)
- .claude/settings.json -> opencode.json (permissions schema)
- .claude/agents/ -> .opencode/agent/ (subagents with mode: subagent)
- .claude/commands/ -> .opencode/command/ (slash commands with )
- .claude/skills/ -> .opencode/skills/ (7 skills, removed allowed-tools)
- DevContainer updated to install opencode
- All .claude/ paths and Claude Code references updated
This commit is contained in:
2026-06-24 22:32:45 +02:00
commit ced279e2df
45 changed files with 7439 additions and 0 deletions

View 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