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:
2026-06-24 23:31:06 +02:00
commit 80e195b3dc
51 changed files with 12716 additions and 0 deletions

View File

@ -0,0 +1,11 @@
{
"name": "opencode-spec-driven-boilerplate",
"image": "mcr.microsoft.com/devcontainers/base:bookworm",
"workspaceFolder": "/workspaces/opencode-spec-driven-boilerplate",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "lts"
}
},
"postCreateCommand": "npm install && curl -fsSL https://opencode.ai/install | bash && ln -sf $HOME/.opencode/bin/opencode /usr/local/bin/opencode"
}

57
.gitignore vendored Normal file
View File

@ -0,0 +1,57 @@
# Temporary files
tmp/
# Node.js
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Build outputs
dist/
build/
.next/
*.tsbuildinfo
# App data (SQLite DB + uploads)
data/
# Backups
backups/
# Playwright
test-results/
playwright-report/
# Environment variables
.env
.env.local
.env.*.local
# Logs
logs/
*.log
# OS files
.DS_Store
Thumbs.db
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# Testing
coverage/
.nyc_output/
# Steering files (task management - temporary)
.steering/*
!.steering/.gitkeep
# Lock files (keep package-lock.json for consistency)
# yarn.lock
.opencode/opencode.local.json

2
.husky/pre-commit Normal file
View File

@ -0,0 +1,2 @@
npx lint-staged
npm run typecheck

View File

@ -0,0 +1,240 @@
---
description: A subagent that reviews document quality and provides improvement suggestions. Use when reviewing project documents (PRD, functional design, architecture, etc.) for completeness, clarity, consistency, implementability, and measurability.
mode: subagent
---
# Document Review Agent
You are a specialized review agent that evaluates document quality and provides improvement suggestions.
## Purpose
Evaluate the quality of project documents (PRD, functional design document, architecture design document, etc.) and provide concrete improvement suggestions.
## Review Perspectives
### 1. Completeness
**Checklist**:
- [ ] Are all required sections included?
- [ ] Does each section contain sufficient information?
- [ ] Are there any ambiguous expressions?
- [ ] Are the prerequisites stated clearly?
**Evaluation Criteria**:
- ✅ Complete: All required information is provided
- ⚠️ Improvement recommended: Some information is missing
- ❌ Insufficient: Important information is missing
### 2. Clarity
**Checklist**:
- [ ] Are terms used consistently?
- [ ] Are the definitions clear?
- [ ] Are figures and tables used appropriately?
- [ ] Are concrete examples included?
**Evaluation Criteria**:
- ✅ Clear: Understandable by any reader
- ⚠️ Improvement recommended: Some parts are hard to understand
- ❌ Unclear: Much room for interpretation
### 3. Consistency
**Checklist**:
- [ ] Are there any contradictions with other documents?
- [ ] Is the usage of terms unified?
- [ ] Is the formatting unified?
- [ ] Are figures and dates consistent?
**Evaluation Criteria**:
- ✅ Consistent: No contradictions
- ⚠️ Improvement recommended: Minor inconsistencies exist
- ❌ Inconsistent: Significant contradictions exist
### 4. Implementability
**Checklist**:
- [ ] Is the information developers need to implement available?
- [ ] Is it technically feasible?
- [ ] Are the resource estimates reasonable?
- [ ] Are the dependencies clear?
**Evaluation Criteria**:
- ✅ Implementable: Can start implementation right away
- ⚠️ Improvement recommended: Additional information would help
- ❌ Insufficient: Information needed for implementation is missing
### 5. Measurability
**Checklist**:
- [ ] Are the success criteria measurable?
- [ ] Do the performance requirements have concrete numbers?
- [ ] Are the testing methods clear?
- [ ] Are the acceptance criteria defined?
**Evaluation Criteria**:
- ✅ Measurable: Clear metrics exist
- ⚠️ Improvement recommended: Some criteria are ambiguous
- ❌ Unclear: The measurement method is unknown
## Review Process
### Step 1: Read the Document
Read the specified document and identify its type:
- Product Requirements Document (PRD)
- Functional Design Document
- Architecture Design Document
- Repository Structure Document
- Development Guidelines
- Glossary
### Step 2: Check the Structure
Check whether the document's structure follows the appropriate template.
### Step 3: Evaluate the Content
Evaluate the document from the five perspectives above (completeness, clarity, consistency, implementability, measurability).
### Step 4: Create Improvement Suggestions
Provide concrete improvement suggestions in the following format:
```markdown
## Review Results: [document name]
### Overall Evaluation
| Perspective | Rating | Score |
|-----|------|--------|
| Completeness | [✅/⚠️/❌] | [1-5] |
| Clarity | [✅/⚠️/❌] | [1-5] |
| Consistency | [✅/⚠️/❌] | [1-5] |
| Implementability | [✅/⚠️/❌] | [1-5] |
| Measurability | [✅/⚠️/❌] | [1-5] |
**Overall Score**: [average score]/5
### Strengths
- [Specific strength 1]
- [Specific strength 2]
- [Specific strength 3]
### Areas That Need Improvement
#### [Required] Critical Issues
**Issue 1**: [description of the issue]
- **Location**: [section name or line number]
- **Reason**: [why it is a problem]
- **Suggested fix**: [specific way to improve]
- **Example**:
```
[before]
[after]
```
#### [Recommended] Improvements Recommended
**Issue 2**: [description of the issue]
- **Location**: [section name]
- **Reason**: [why it should be improved]
- **Suggested fix**: [specific way to improve]
#### [Suggestion] Further Improvements
**Suggestion 1**: [content of the suggestion]
- **Benefit**: [benefit of this improvement]
- **How to implement**: [how to improve]
### References
- [Related documents]
- [Best practices]
### Next Steps
1. [What to address with top priority]
2. [What to address next]
3. [What to address if there is time]
```
## Special Perspectives by Document Type
### Product Requirements Document (PRD)
Additional checklist:
- [ ] Is the target user clear?
- [ ] Is the problem being solved concrete?
- [ ] Are success metrics (KPIs) defined?
- [ ] Are priorities (P0/P1/P2) set?
- [ ] Is what is out of scope stated explicitly?
### Functional Design Document
Additional checklist:
- [ ] Is there a system configuration diagram?
- [ ] Is the data model defined?
- [ ] Are use cases shown with sequence diagrams?
- [ ] Is error handling considered?
- [ ] Is the API design concrete (where applicable)?
### Architecture Design Document
Additional checklist:
- [ ] Is there a rationale for the technology choices?
- [ ] Is the layered architecture clear?
- [ ] Are the performance requirements measurable?
- [ ] Are there security considerations?
- [ ] Is scalability considered?
### Repository Structure Document
Additional checklist:
- [ ] Is the directory structure visualized?
- [ ] Is the role of each directory explained?
- [ ] Are the naming conventions clear?
- [ ] Are the dependency rules defined?
- [ ] Is there a scaling strategy?
### Development Guidelines
Additional checklist:
- [ ] Do the coding standards include concrete examples?
- [ ] Are the Git workflow rules clear?
- [ ] Is the testing strategy defined?
- [ ] Is there a code review process?
- [ ] Are the environment setup steps documented?
### Glossary
Additional checklist:
- [ ] Are the terms classified appropriately?
- [ ] Does each term have a clear definition?
- [ ] Are concrete examples included?
- [ ] Are related terms linked?
- [ ] Is the index organized?
## Output Format
Always output the review results in the following structure:
1. **Overall Evaluation**: Scores and the evaluation matrix
2. **Strengths**: Positive feedback (at least 3)
3. **Areas That Need Improvement**: Organized by priority
- [Required] Critical issues
- [Recommended] Improvements recommended
- [Suggestion] Further improvements
4. **References**: Helpful resources
5. **Next Steps**: Concrete action items
## Review Attitude
- **Constructive**: Offer suggestions for improvement rather than criticism
- **Specific**: Instead of "hard to understand," state "where," "why," and "how to improve"
- **Balanced**: Point out not only the weaknesses but also the strengths
- **Practical**: Present improvement suggestions that can actually be carried out
- **Grounded**: Always provide a reason for each improvement suggestion

View File

@ -0,0 +1,352 @@
---
description: A subagent that validates implementation code quality and confirms consistency with the spec. Use when verifying that implemented code meets spec requirements, coding standards, test coverage, security, and performance targets.
mode: subagent
---
# Implementation Validation Agent
You are a specialized validation agent that verifies the quality of implementation code and confirms its consistency with the spec.
## Purpose
Verify that the implemented code meets the following criteria:
1. Consistency with the spec (PRD, functional design document, architecture design document)
2. Code quality (coding standards, best practices)
3. Test coverage
4. Security
5. Performance
## Validation Perspectives
### 1. Spec Compliance
**Checklist**:
- [ ] Are the features defined in the PRD implemented?
- [ ] Does it match the data model in the functional design document?
- [ ] Does it follow the layer structure of the architecture design?
- [ ] Does it match the required API specification?
**Evaluation Criteria**:
- ✅ Compliant: Implemented as specified
- ⚠️ Some differences: Minor differences exist
- ❌ Inconsistent: Significant differences exist
### 2. Code Quality
**Checklist**:
- [ ] Does it follow the coding standards?
- [ ] Is the naming appropriate?
- [ ] Does each function have a single responsibility?
- [ ] Is there any duplicated code?
- [ ] Are there appropriate comments?
**Evaluation Criteria**:
- ✅ High quality: Fully compliant with the coding standards
- ⚠️ Improvement recommended: Some room for improvement
- ❌ Low quality: Significant problems exist
### 3. Test Coverage
**Checklist**:
- [ ] Are unit tests written?
- [ ] Is the coverage target met?
- [ ] Are edge cases tested?
- [ ] Are the tests named appropriately?
**Evaluation Criteria**:
- ✅ Sufficient: Coverage of 80% or more, covering the main cases
- ⚠️ Improvement recommended: Coverage of 60-80%
- ❌ Insufficient: Coverage below 60%
### 4. Security
**Checklist**:
- [ ] Is input validation implemented?
- [ ] Is any sensitive information hardcoded?
- [ ] Do error messages contain sensitive information?
- [ ] Are file permissions appropriate (where applicable)?
- [ ] Are authentication and authorization implemented appropriately (where applicable)?
**Evaluation Criteria**:
- ✅ Safe: Security measures are appropriate
- ⚠️ Caution needed: Some improvement is required
- ❌ Dangerous: A significant vulnerability exists
### 5. Performance
**Checklist**:
- [ ] Are the performance requirements met?
- [ ] Are appropriate data structures used?
- [ ] Are there any unnecessary computations?
- [ ] Are loops optimized?
- [ ] Is there any possibility of a memory leak?
**Evaluation Criteria**:
- ✅ Optimal: Meets the performance requirements
- ⚠️ Improvement recommended: Room for optimization
- ❌ Problematic: Performance requirements not met
## Validation Process
### Step 1: Understand the Spec
Read the relevant spec documents:
- `docs/product-requirements.md`
- `docs/functional-design.md`
- `docs/architecture.md`
- `docs/development-guidelines.md`
### Step 2: Analyze the Implementation Code
Read the implemented code and understand its structure:
- Review the directory structure
- Identify the main classes and functions
- Understand the data flow
### Step 3: Validate from Each Perspective
Validate from the five perspectives above (spec compliance, code quality, test coverage, security, performance).
### Step 4: Report the Validation Results
Report concrete validation results in the following format:
```markdown
## Implementation Validation Results
### Target
- **Implementation content**: [feature name or change description]
- **Target files**: [file list]
- **Related spec**: [spec document]
### Overall Evaluation
| Perspective | Rating | Score |
|-----|------|--------|
| Spec compliance | [✅/⚠️/❌] | [1-5] |
| Code quality | [✅/⚠️/❌] | [1-5] |
| Test coverage | [✅/⚠️/❌] | [1-5] |
| Security | [✅/⚠️/❌] | [1-5] |
| Performance | [✅/⚠️/❌] | [1-5] |
**Overall Score**: [average score]/5
### Good Implementation
- [Specific strength 1]
- [Specific strength 2]
- [Specific strength 3]
### Issues Detected
#### [Required] Critical Issues
**Issue 1**: [description of the issue]
- **File**: `[file path]:[line number]`
- **Problematic code**:
```typescript
[problematic code]
```
- **Reason**: [why it is a problem]
- **Suggested fix**:
```typescript
[corrected code]
```
#### [Recommended] Improvements Recommended
**Issue 2**: [description of the issue]
- **File**: `[file path]`
- **Reason**: [why it should be improved]
- **Suggested fix**: [specific way to improve]
#### [Suggestion] Further Improvements
**Suggestion 1**: [content of the suggestion]
- **Benefit**: [benefit of this improvement]
- **How to implement**: [how to improve]
### Test Results
**Tests run**:
- Unit tests: [pass/fail count]
- Integration tests: [pass/fail count]
- Coverage: [%]
**Areas with insufficient testing**:
- [Area 1]
- [Area 2]
### Differences from the Spec
**Difference 1**: [description of the difference]
- **Spec**: [what the spec states]
- **Implementation**: [the actual implementation]
- **Impact**: [the impact of this difference]
- **Recommendation**: [what should be done]
### Next Steps
1. [What to address with top priority]
2. [What to address next]
3. [What to address if there is time]
```
## Running Validation Tools
During validation, run the following tools:
### Lint Check
```bash
npm run lint
```
### Type Check
```bash
npm run typecheck
```
### Run Tests
```bash
npm test
npm run test:coverage
```
### Build Check
```bash
npm run build
```
## Detailed Code Quality Checks
### Naming Conventions
**Variables and functions**:
```typescript
// ✅ Good example
const userProfileData = fetchUserProfile();
function calculateTotalPrice(items: CartItem[]): number { }
// ❌ Bad example
const data = fetch();
function calc(arr: any[]): number { }
```
**Classes and interfaces**:
```typescript
// ✅ Good example
class TaskService { }
interface TaskRepository { }
// ❌ Bad example
class Manager { } // ambiguous
interface IData { } // meaningless
```
### Function Design
**Single responsibility principle**:
```typescript
// ✅ Good example: a single responsibility
function calculateTotal(items: CartItem[]): number { }
function formatPrice(amount: number): string { }
// ❌ Bad example: multiple responsibilities
function calculateAndFormatPrice(items: CartItem[]): string { }
```
**Function length**:
- Recommended: within 20 lines
- Acceptable: within 50 lines
- 100 lines or more: refactoring is recommended
### Error Handling
**Appropriate error handling**:
```typescript
// ✅ Good example
try {
const task = await taskService.create(data);
return task;
} catch (error) {
if (error instanceof ValidationError) {
logger.warn(`Validation error: ${error.message}`);
throw error;
}
throw new DatabaseError('Failed to create the task', error);
}
// ❌ Bad example: ignoring the error
try {
return await taskService.create(data);
} catch (error) {
return null; // error information is lost
}
```
## Security Checklist
### Input Validation
```typescript
// ✅ Good example
function validateEmail(email: string): void {
if (!email || typeof email !== 'string') {
throw new ValidationError('Email address is required', 'email', email);
}
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
throw new ValidationError('Email address format is invalid', 'email', email);
}
}
// ❌ Bad example: no validation
function validateEmail(email: string): void { }
```
### Sensitive Information Management
```typescript
// ✅ Good example
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('The API_KEY environment variable is not set');
}
// ❌ Bad example
const apiKey = 'sk-1234567890abcdef'; // hardcoding is forbidden
```
## Performance Checklist
### Choosing Data Structures
```typescript
// ✅ Good example: O(1) access
const taskMap = new Map(tasks.map(t => [t.id, t]));
const task = taskMap.get(taskId);
// ❌ Bad example: O(n) search
const task = tasks.find(t => t.id === taskId);
```
### Loop Optimization
```typescript
// ✅ Good example
for (const item of items) {
process(item);
}
// ❌ Bad example: computing length every iteration
for (let i = 0; i < items.length; i++) {
process(items[i]);
}
```
## Validation Attitude
- **Objective**: Evaluate based on facts
- **Specific**: Clearly indicate the problem locations
- **Constructive**: Always present improvement suggestions
- **Balanced**: Point out the strengths as well
- **Practical**: Provide fixes that can actually be carried out

View File

@ -0,0 +1,129 @@
---
description: Implement a new feature following existing patterns, fully autonomously without stopping
agent: build
---
# Adding a New Feature (Fully Autonomous Execution Mode)
**Important:** This workflow is designed to run fully automatically from start to finish without user intervention. After completing each step, immediately move on to the next step. Do not ask the user for confirmation mid-thought or interrupt the work.
**Feature name**: `$ARGUMENTS` (e.g. `/add-feature User profile editing`)
---
## Step 1: Preparation and Context Setup
1. Establish the current task context:
- Feature name: `$ARGUMENTS`
- Date: `[get the current date in YYYYMMDD format]`
- Steering directory path: `.steering/[date]-[feature name]/`
2. Create the steering directory above.
3. Create the following three empty files:
- `[steering directory path]/requirements.md`
- `[steering directory path]/design.md`
- `[steering directory path]/tasklist.md`
## Step 2: Understand the Project
1. Read `AGENTS.md` to grasp the overall picture of the project.
2. Review the persistent documents in the `docs/` directory to understand the relevant design philosophy and architecture.
## Step 3: Investigate Existing Patterns
1. Use the grep tool to search the source code (`src/`) for keywords related to the feature name.
2. Analyze the search results to identify existing implementation patterns, naming conventions, and how components are used.
## Step 4: Planning Phase (Automatic Generation of Steering Files)
1. Follow the **steering** skill (loaded automatically) in **planning mode** to generate the contents of the three files created in Step 1 (`requirements.md`, `design.md`, `tasklist.md`).
2. **Once this step completes successfully, never stop; immediately proceed to Step 5.**
## Step 5: Implementation Loop (Fully Working Through tasklist.md)
**This step is a loop that repeats automatically until all tasks in `tasklist.md` are `[x]`.**
**Once this step completes successfully, never stop; immediately proceed to Step 6.**
**Loop start:**
1. Read the task list:
- Read the `[steering directory path]/tasklist.md` file.
2. Check progress:
- Check whether any incomplete tasks (`[ ]`) exist in the file.
- **If no incomplete tasks exist:** consider this implementation loop complete and immediately proceed to **Step 6**.
- **If incomplete tasks exist:** proceed to the next step (3. Execute the task).
3. Execute the task:
- Identify one **incomplete task at the top** of `tasklist.md`.
- Carry out the implementation work needed to complete that task.
- Follow the **steering** skill in **implementation mode**.
- Always follow the coding standards in the **development-guidelines** skill.
4. Update the task list:
- Once the executed task is complete, use the edit tool to update `tasklist.md`, changing the task from `[ ]` to `[x]`.
5. Continue the loop:
- **Return to the top of Step 5 (1. Read the task list) and repeat the process.**
---
### * Exception-Handling Rules Within the Implementation Loop *
If any of the following situations occur while the implementation loop is running, handle them autonomously according to these rules and continue the loop.
- **Rule A: When a task is too large**
- **Handling:** Break the current task into multiple smaller subtasks. Use the edit tool to delete the original task and insert the new subtasks (with `[ ]`) in its place. Then continue the loop.
- **Rule B: When a task becomes unnecessary for technical reasons**
- **Condition:** Apply only when there is a clear technical reason, such as a change in implementation approach, architecture, or dependencies.
- **Handling:** Use the edit tool to update the task in the format `[x] ~~task name~~ (Reason: [briefly describe the specific technical reason])`. Then continue the loop.
- **❌ Strictly Forbidden Actions:**
- Intentionally skipping an incomplete task for reasons such as "do it later" or "make it a separate task."
- Leaving incomplete tasks unaddressed and ending the loop without reason.
- Asking the user to make a decision.
---
## Step 6: Implementation Validation (Launch a Subagent)
1. Do a final check that all tasks in `tasklist.md` are complete.
2. Use the Task tool to launch the `implementation-validator` subagent to validate quality:
- `subagent_type`: "implementation-validator"
- `description`: "Implementation quality validation"
- `prompt`: "Please validate the quality of all the changes related to the `[feature name]` implemented this time. The target files are `[list of paths of the implemented files]`. Focus on coding standards, error handling, testability, and consistency with existing patterns."
**Once this step completes successfully, never stop; immediately proceed to Step 7.**
## Step 7: Run Automated Tests
1. Run the following commands in order and confirm that all tests pass.
```bash
npm test
npm run lint
npm run typecheck
```
2. If any command produces an error, analyze the problem, generate and apply a fix, and then run this step again.
**Once this step completes successfully, never stop; immediately proceed to Step 8.**
## Step 8: Retrospective and Document Updates
1. Follow the **steering** skill in **retrospective mode** and record handover notes in `tasklist.md`.
- Implementation completion date
- Differences between plan and actual
- Lessons learned
- Improvement suggestions for next time
2. Determine whether this change affects the project's fundamental design or architecture.
3. If there is an impact, use the edit tool to update the relevant persistent documents in `docs/`.
## Completion Criteria
This workflow completes automatically once all of the following conditions are met.
- Step 5: All tasks in `tasklist.md` are complete (`[x]` or skipped for a valid reason).
- Step 6: The `implementation-validator` subagent's validation passes.
- Step 7: The `test`, `lint`, and `typecheck` commands all succeed without errors.
- Step 8: Handover notes are recorded in `tasklist.md`.
Until these completion criteria are met, continue to think autonomously, solve problems, and carry on the work.

View File

@ -0,0 +1,64 @@
---
description: Run a detailed document review using a subagent
agent: build
---
# Document Review
**Document path**: `$ARGUMENTS` (e.g. `/review-docs docs/product-requirements.md`)
## How to Run
```
opencode
> /review-docs docs/product-requirements.md
```
## Procedure
### Step 1: Verify the Document Exists
Check whether the specified document exists.
### Step 2: Launch the doc-reviewer Subagent
Launch the doc-reviewer subagent to run the review:
Use the Task tool to launch the doc-reviewer subagent:
- subagent_type: "doc-reviewer"
- description: "Document detailed review"
- prompt: "Please review $ARGUMENTS in detail.\n\nEvaluate it from the following perspectives:\n1. Completeness: Are all required items included?\n2. Specificity: Are there any ambiguous expressions?\n3. Consistency: Is it consistent with other documents?\n4. Measurability: Are success metrics measurable? (for a PRD)\n\nPlease produce a review report."
### Step 3: Summarize the Review Results
Extract the key points from the review report produced by the subagent and report them to the user.
## Output Format
```markdown
# Document Review Results
## Document: [file name]
### Key Improvements
1. [Improvement 1] (Priority: High/Medium/Low)
2. [Improvement 2] (Priority: High/Medium/Low)
3. [Improvement 3] (Priority: High/Medium/Low)
### Overall Rating
[1-5]/5
### Next Actions
- [Recommended action 1]
- [Recommended action 2]
For the full report, refer to the subagent's output.
```
## Notes
- The review involves detailed analysis and may take a few minutes.
- The subagent runs in an independent context, so it does not consume the main agent's context.

View File

@ -0,0 +1,112 @@
---
description: Initial setup - interactively create the six persistent documents
agent: build
---
# Initial Project Setup
This command interactively creates the project's six persistent documents.
## How to Run
```
opencode
> /setup-project
```
## Pre-Run Check
Check the files in the `docs/ideas/` directory.
```bash
# Check
ls docs/ideas/
# If files exist
✅ Found docs/ideas/initial-requirements.md
The PRD will be created based on its contents
# If no files exist
⚠️ No files found in docs/ideas/
The PRD will be created interactively
```
## Procedure
### Step 0: Read the Inputs
1. Read all markdown files in `docs/ideas/`
2. Understand their contents and use them as reference for creating the PRD
### Step 1: Create the Product Requirements Document
1. Follow the **prd-writing** skill (loaded automatically) to guide PRD creation
2. Create `docs/product-requirements.md` based on the contents of `docs/ideas/`
3. Flesh out the ideas raised during brainstorming:
- Detailed user stories
- Acceptance criteria
- Non-functional requirements
- Success metrics
4. Ask the user for confirmation and **wait until approved**
**The subsequent steps are based on the Product Requirements Document, so they are created automatically**
### Step 2: Create the Functional Design Document
1. Follow the **functional-design** skill (loaded automatically)
2. Read `docs/product-requirements.md`
3. Create `docs/functional-design.md` following the skill's template and guide
### Step 3: Create the Architecture Design Document
1. Follow the **architecture-design** skill (loaded automatically)
2. Read the existing documents
3. Create `docs/architecture.md` following the skill's template and guide
### Step 4: Create the Repository Structure Document
1. Follow the **repository-structure** skill (loaded automatically)
2. Read the existing documents
3. Create `docs/repository-structure.md` following the skill's template
### Step 5: Create the Development Guidelines
1. Follow the **development-guidelines** skill (loaded automatically)
2. Read the existing documents
3. Create `docs/development-guidelines.md` following the skill's template
### Step 6: Create the Glossary
1. Follow the **glossary-creation** skill (loaded automatically)
2. Read the existing documents
3. Create `docs/glossary.md` following the skill's template
## Completion Criteria
- All six persistent documents have been created
Completion message:
```
"Initial setup is complete!
Documents created:
✅ docs/product-requirements.md
✅ docs/functional-design.md
✅ docs/architecture.md
✅ docs/repository-structure.md
✅ docs/development-guidelines.md
✅ docs/glossary.md
You are now ready to start development.
How to use going forward:
- Editing documents: just ask in normal conversation
Examples: 'Add a new feature to the PRD', 'Review architecture.md'
- Adding features: run /add-feature [feature name]
Example: /add-feature User authentication
- Document review: run /review-docs [path]
Example: /review-docs docs/product-requirements.md
"
```

View 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

View 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

View 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] |

View 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

View 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

View 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

View 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]

View 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

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

View 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]

View 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

View 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

View 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]
```

View 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

View 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]

View 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

View 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

View 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/`

View 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?"

View 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}

View 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

View 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}

14
.prettierignore Normal file
View File

@ -0,0 +1,14 @@
# ドキュメント・設定ディレクトリ
.opencode/
.steering/
docs/
AGENTS.md
# ログファイル
*log.json
# 依存関係
node_modules/
# ビルド成果物
dist/

9
.prettierrc Normal file
View File

@ -0,0 +1,9 @@
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"arrowParens": "always"
}

0
.steering/.gitkeep Normal file
View File

134
AGENTS.md Normal file
View File

@ -0,0 +1,134 @@
# Project Memory
## Technology Stack
- Development environment: devcontainer
- Node.js v24.11.0
- TypeScript 5.x
- Package manager: npm
## Basic Principles of Spec-Driven Development
### Basic Flow
1. **Document creation**: Define "what to build" in persistent documents (`docs/`)
2. **Work planning**: Plan "what to do this time" in steering files (`.steering/`)
3. **Implementation**: Implement according to tasklist.md and update progress as you go
4. **Verification**: Testing and operation checks
5. **Update**: Update documents as needed
### Important Rules
#### When Creating Documents
**Create one file at a time, and always obtain the user's approval before moving on to the next.**
When waiting for approval, communicate clearly:
```
"The creation of [document name] is complete. Please review the content.
Once you approve, I will proceed to the next document."
```
#### Checks Before Implementation
Before starting a new implementation, always check the following:
1. Read AGENTS.md
2. Read the related persistent documents (`docs/`)
3. Search for existing similar implementations with Grep
4. Understand existing patterns before starting implementation
#### Steering File Management
Create `.steering/[YYYYMMDD]-[task-name]/` for each piece of work:
- `requirements.md`: The requirements for this work
- `design.md`: The implementation approach
- `tasklist.md`: A concrete task list
Naming convention: `20250115-add-user-profile` format
#### Steering File Management
**Use the `steering` skill when planning work, implementing, and verifying.**
- **When planning work**: Mode 1 (creating steering files) via the steering skill
- **When implementing**: Mode 2 (implementation and tasklist.md update management) via the steering skill
- **When verifying**: Mode 3 (retrospective) via the steering skill
Detailed procedures and update-management rules are defined within the steering skill.
## Directory Structure
### Persistent Documents (`docs/`)
Define "what to build" and "how to build it" for the entire application:
#### Drafts and Ideas (`docs/ideas/`)
- Outputs of brainstorming and ideation
- Technical research notes
- Free-form (minimal structure)
- Automatically loaded when `/setup-project` is run
#### Official Documents
- **product-requirements.md** - Product requirements document
- **functional-design.md** - Functional design document
- **architecture.md** - Technical specification
- **repository-structure.md** - Repository structure definition document
- **development-guidelines.md** - Development guidelines
- **glossary.md** - Ubiquitous language definitions
### Work-Unit Documents (`.steering/`)
Define "what to do this time" for a specific development task:
- `requirements.md`: The requirements for this work
- `design.md`: The design of the changes
- `tasklist.md`: The task list
### opencode Configuration (`.opencode/`)
- `.opencode/agent/` - Subagent definitions (doc-reviewer, implementation-validator)
- `.opencode/command/` - Slash commands (setup-project, add-feature, review-docs)
- `.opencode/skills/` - Task-specific skills (prd-writing, functional-design, architecture-design, repository-structure, development-guidelines, glossary-creation, steering)
## Development Process
### Initial Setup
1. Use this template
2. Create persistent documents with `/setup-project` (interactively creating six)
3. Implement features with `/add-feature [feature]`
### Day-to-Day Usage
**Basically, just make requests through normal conversation:**
```bash
# Editing documents
> Please add a new feature to the PRD
> Review the performance requirements in architecture.md
> Add a new domain term to glossary.md
# Adding features (use commands for the standard flow)
> /add-feature edit user profile
# Detailed review (when a detailed report is needed)
> /review-docs docs/product-requirements.md
```
**Key point**: You do not need to be conscious of the details of spec-driven development. opencode will determine and load the appropriate skill.
## Principles of Document Management
### Persistent Documents (`docs/`)
- Describe the fundamental design
- Not updated frequently
- The "north star" for the entire project
### Work-Unit Documents (`.steering/`)
- Specialized for a specific task
- Created anew for each piece of work
- Retained as history

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Ken Yasue
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

399
README.md Normal file
View File

@ -0,0 +1,399 @@
# opencode Spec-Driven Development Boilerplate
A spec-driven development boilerplate for [opencode](https://opencode.ai), converted from the
[Claude Code boilerplate](https://git.yasue.org/ken/claudecode-boilerplate) that accompanies the book
*"Practical Claude Code Introduction."*
It gives opencode a structured workflow for turning ideas into production code through persistent design
documents, per-task steering files, AI skills, subagents, and slash commands.
---
## Table of Contents
- [What Is Spec-Driven Development?](#what-is-spec-driven-development)
- [Conversion Summary (Claude Code → opencode)](#conversion-summary-claude-code--opencode)
- [Prerequisites](#prerequisites)
- [Quick Start](#quick-start)
- [Directory Structure](#directory-structure)
- [Configuration Overview](#configuration-overview)
- [Usage Workflow](#usage-workflow)
- [Commands Reference](#commands-reference)
- [Skills Reference](#skills-reference)
- [Agents Reference](#agents-reference)
- [Customizing the Boilerplate](#customizing-the-boilerplate)
- [Troubleshooting](#troubleshooting)
- [License](#license)
---
## What Is Spec-Driven Development?
Spec-driven development separates **"what to build"** from **"how to build it"**:
1. **Persistent documents** (`docs/`) — the north-star design (PRD, functional design, architecture, etc.)
2. **Steering files** (`.steering/`) — per-task plans created fresh for each piece of work
3. **Implementation** — the agent follows `tasklist.md`, updating progress as it goes
4. **Verification** — tests, lint, typecheck, and a retrospective
opencode loads the right skill automatically based on what you're doing, so you don't have to think about
the process — just describe what you want.
---
## Conversion Summary (Claude Code → opencode)
| Claude Code | opencode | Notes |
|---|---|---|
| `CLAUDE.md` | `AGENTS.md` | Referenced via `instructions` in `opencode.json` |
| `.claude/settings.json` | `opencode.json` | Permissions converted to opencode's `permission` schema |
| `.claude/agents/*.md` | `.opencode/agent/*.md` | Added `mode: subagent`; `model: sonnet` removed (inherits default) |
| `.claude/commands/*.md` | `.opencode/command/*.md` | Tool-call syntax (`Bash()`, `Grep()`, `Skill()`) converted to natural instructions; `$ARGUMENTS` added |
| `.claude/skills/*/SKILL.md` | `.opencode/skills/*/SKILL.md` | `allowed-tools` frontmatter removed (not an opencode field) |
| `Skill('steering')` calls | Auto-loaded by description | opencode surfaces skills via `description` matching |
| `TodoWrite` / `Edit` tool refs | `todowrite` / `edit` | Lowercased to match opencode tool names |
| Claude Code devcontainer feature | `curl … opencode.ai/install` | Replaced Anthropic feature with opencode install script |
All skill templates and guides were preserved verbatim except for `.claude/` path references and
"Claude Code" mentions, which were updated to `.opencode/` and "opencode" respectively.
---
## Prerequisites
- **Node.js** v18+ (v24.11.0 recommended)
- **npm**
- **opencode** — install with:
```bash
curl -fsSL https://opencode.ai/install | bash
```
See <https://opencode.ai/docs> for alternatives (npm, Homebrew, etc.)
- **Docker** (only if using the Dev Container)
---
## Quick Start
### Option A — Dev Container (recommended)
1. Open this folder in **VS Code**.
2. When prompted, click **"Reopen in Container"** (or run the command
*Dev Containers: Reopen in Container*).
3. The container automatically:
- Installs Node.js LTS
- Runs `npm install`
- Installs opencode
4. Open a terminal and start opencode:
```bash
opencode
```
### Option B — Manual setup
```bash
# 1. Install dependencies
npm install
# 2. Set up Git hooks
npm run prepare
# 3. Start opencode
opencode
```
---
## Directory Structure
```
.
├── opencode.json # opencode config (permissions, instructions)
├── AGENTS.md # Project instructions (loaded into every session)
├── package.json # Node.js project + scripts
├── tsconfig.json # TypeScript config
├── eslint.config.js # ESLint flat config
├── vitest.config.ts # Vitest config (80% coverage threshold)
├── .prettierrc / .prettierignore
├── .gitignore
├── .husky/pre-commit # Runs lint-staged + typecheck before commit
├── .devcontainer/devcontainer.json
├── prompt.md # Example MVP prompt
├── src/ # Source code
│ ├── example.ts
│ └── example.test.ts
├── docs/ # Persistent design documents (created by /setup-project)
│ └── ideas/
│ └── initial-requirements.md # Brainstorming notes (pre-PRD)
├── .steering/ # Per-task steering files (created by /add-feature)
│ └── .gitkeep
└── .opencode/ # opencode configuration
├── agent/ # Subagent definitions
│ ├── doc-reviewer.md
│ └── implementation-validator.md
├── command/ # Slash commands
│ ├── setup-project.md
│ ├── add-feature.md
│ └── review-docs.md
└── skills/ # Task-specific skills
├── prd-writing/ (SKILL.md + template.md)
├── functional-design/ (SKILL.md + template.md + guide.md)
├── architecture-design/ (SKILL.md + template.md + guide.md)
├── repository-structure/ (SKILL.md + template.md + guide.md)
├── development-guidelines/(SKILL.md + template.md + guides/)
├── glossary-creation/ (SKILL.md + template.md + guide.md)
└── steering/ (SKILL.md + templates/)
```
---
## Configuration Overview
### `opencode.json`
The main configuration file. Key sections:
```jsonc
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["AGENTS.md"], // Loaded into every session
"permission": {
"skill": "allow", // Skills are auto-available
"bash": { // Common dev commands pre-approved
"*": "ask",
"npm *": "allow",
"npx *": "allow",
"git *": "allow",
// ...
}
}
}
```
> **After editing `opencode.json`, quit and restart opencode** — config is loaded once at startup.
### `AGENTS.md`
The project memory file. opencode reads it on every session. It defines:
- The technology stack
- The spec-driven development principles
- The directory structure
- The development process and workflow
### Agents (`.opencode/agent/`)
Subagents run in isolated contexts via the `task` tool. They don't consume the main session's context.
### Commands (`.opencode/command/`)
Slash commands invoked in the opencode TUI with `/command-name`. Each command is a prompt template
that opencode executes.
### Skills (`.opencode/skills/`)
Skills are loaded automatically based on their `description` field. You don't invoke them by name —
opencode surfaces the right skill when the task matches.
---
## Usage Workflow
### 1. Initial project setup
Run the setup command to create all six persistent design documents interactively:
```
> /setup-project
```
This creates (one at a time, with your approval):
1. `docs/product-requirements.md` (PRD)
2. `docs/functional-design.md`
3. `docs/architecture.md`
4. `docs/repository-structure.md`
5. `docs/development-guidelines.md`
6. `docs/glossary.md`
The PRD is based on the brainstorming notes in `docs/ideas/initial-requirements.md`. Edit that file
first if you have your own idea, or replace it.
### 2. Add a feature
```
> /add-feature User authentication
```
This fully autonomous workflow:
1. Creates `.steering/[YYYYMMDD]-[feature-name]/` with `requirements.md`, `design.md`, `tasklist.md`
2. Generates the steering files (planning mode of the steering skill)
3. Implements every task in `tasklist.md`, marking each `[ ]` → `[x]` as it goes
4. Launches the `implementation-validator` subagent for quality review
5. Runs `npm test`, `npm run lint`, `npm run typecheck`
6. Records a retrospective in `tasklist.md`
### 3. Review a document
```
> /review-docs docs/product-requirements.md
```
Launches the `doc-reviewer` subagent to evaluate the document from five perspectives:
completeness, clarity, consistency, implementability, and measurability.
### 4. Day-to-day editing
You don't always need a command — just ask in normal conversation:
```
> Add a new feature to the PRD
> Review the performance requirements in architecture.md
> Add a new domain term to glossary.md
```
opencode loads the appropriate skill automatically.
---
## Commands Reference
| Command | Description | Example |
|---|---|---|
| `/setup-project` | Create the six persistent documents interactively | `/setup-project` |
| `/add-feature` | Implement a feature end-to-end (autonomous) | `/add-feature User profile editing` |
| `/review-docs` | Detailed document review via subagent | `/review-docs docs/architecture.md` |
---
## Skills Reference
| Skill | When it loads | Output |
|---|---|---|
| `prd-writing` | Creating a Product Requirements Document | `docs/product-requirements.md` |
| `functional-design` | Creating a functional design document | `docs/functional-design.md` |
| `architecture-design` | Designing the system architecture | `docs/architecture.md` |
| `repository-structure` | Defining the directory layout | `docs/repository-structure.md` |
| `development-guidelines` | Creating coding conventions / implementing code | `docs/development-guidelines.md` |
| `glossary-creation` | Creating a project glossary | `docs/glossary.md` |
| `steering` | Planning, implementing, and retrospecting on a task | `.steering/[date]-[name]/` files |
Each skill folder contains a `SKILL.md` (instructions) plus `template.md` and/or `guide.md` (reference
material the skill points to).
---
## Agents Reference
| Agent | Mode | Purpose |
|---|---|---|
| `doc-reviewer` | subagent | Reviews document quality across 5 dimensions; outputs a scored report with prioritized improvements |
| `implementation-validator` | subagent | Validates code against the spec; checks quality, test coverage, security, performance; runs lint/test/typecheck |
Agents are launched via the `task` tool (e.g., by the `/add-feature` and `/review-docs` commands).
They run in an isolated context window.
---
## Customizing the Boilerplate
### Change the model
Agents inherit the default model from `opencode.json`. To pin a specific model for a subagent, add
`model` to its frontmatter:
```yaml
---
description: ...
mode: subagent
model: anthropic/claude-sonnet-4-6
---
```
Or set a global default in `opencode.json`:
```jsonc
{
"model": "anthropic/claude-sonnet-4-6"
}
```
> Model IDs use the `provider/model-id` format. See <https://opencode.ai/config.json> for the full schema.
### Adjust permissions
Edit the `permission` block in `opencode.json`. For example, to allow all bash commands:
```jsonc
{
"permission": { "bash": "allow" }
}
```
### Add a new skill
1. Create `.opencode/skills/my-skill/SKILL.md`
2. Add frontmatter with `name` and `description` (the description controls when opencode loads it)
3. Add any companion `template.md` or `guide.md` files
4. Restart opencode
### Add a new command
1. Create `.opencode/command/my-command.md`
2. Add `description` frontmatter + a prompt body (use `$ARGUMENTS` for user input)
3. Restart opencode
### Add a new agent
1. Create `.opencode/agent/my-agent.md`
2. Add `description` and `mode: subagent` frontmatter + a prompt body
3. Restart opencode
---
## Troubleshooting
### opencode won't start after editing config
opencode validates `opencode.json` strictly and refuses to start on invalid fields. To recover:
```bash
# Skip the project config and start from globals only
OPENCODE_DISABLE_PROJECT_CONFIG=1 opencode
```
Then fix the broken file and restart normally.
### Skills not loading
- Ensure each `SKILL.md` has a `description` in its frontmatter — skills without one are filtered out.
- Ensure the folder name matches the `name` field.
- Restart opencode after adding or changing skills.
### Commands not appearing
- Command files must be directly inside `.opencode/command/` (not in subdirectories).
- Restart opencode after adding commands.
### Dev Container: `opencode` command not found
The install script adds opencode to `~/.opencode/bin/` and updates your shell profile. If the command
isn't found in a new terminal:
```bash
export PATH="$HOME/.opencode/bin:$PATH"
opencode
```
Or create a permanent symlink:
```bash
sudo ln -sf "$HOME/.opencode/bin/opencode" /usr/local/bin/opencode
```
---
## License
MIT — see [LICENSE](LICENSE).

271
docs/architecture.md Normal file
View File

@ -0,0 +1,271 @@
# アーキテクチャ設計書 (Architecture Design Document)
> 本書は `docs/product-requirements.md` と `docs/functional-design.md` を技術的に実現するためのシステム構造・技術選定・インフラ要件を定義する。
## 技術スタック
### 言語・ランタイム
| 技術 | バージョン | 選定理由 |
|------|-----------|----------|
| Node.js | v24.11.0 | 開発環境(devcontainer)と同一。better-sqlite3の同期APIを直接扱える。LTS保証下で本番運用が安定 |
| TypeScript | 5.x | 静的型付けによりコンパイル時バグ検出。Repository/Service/Entity間の型共有で保守性向上。IDE補完により開発効率向上 |
| npm | 11.x | Node.js v24.11.0にバンドル。package-lock.jsonによる厳密な依存管理。workspaces対応 |
### フレームワーク・ライブラリ
| 技術 | バージョン | 目的 | 選定理由 |
|------|-----------|------|----------|
| Next.js | 15 | Webフレームワーク | App Router・Server Components・Route Handlers・Server Actionsを統合利用。Node.js Runtime選択可能でSQLite直接操作に適合 |
| better-sqlite3 | 最新安定 | SQLiteドライバ | 同期APIで扱いやすく高速。トランザクション・プリペアドステートメント・pragma制御が直接可能 |
| react-markdown | 最新安定 | Markdownレンダリング | GFM拡張と連携可能。プラグインでサニタイズパイプラインを構築できる |
| remark-gfm | 最新安定 | GFM対応 | テーブル・チェックリスト・取り消し線等のGFM記法を有効化 |
| rehype-sanitize | 最新安定 | HTMLサニタイズ | Markdown表示時のXSS対策。危険なHTML・URLスキームを除去 |
| Tailwind CSS | 最新安定 | スタイリング | ユーティリティファーストでUI構築が高速。カスタムCSS削減 |
| bcrypt | 最新安定 | パスワードハッシュ | ソルト付きハッシュで平文保存を回避。適切なコスト係数でブルートフォース耐性 |
| FullCalendar系 または独自実装 | - | カレンダーUI | 月/週/日/リスト表示・ドラッグ操作・イベントフィルタ要件を満たす |
### 開発ツール
| 技術 | バージョン | 目的 | 選定理由 |
|------|-----------|------|----------|
| Vitest | 最新安定 | Unit Test | Viteベースで高速。TypeScriptネイティブ対応。better-sqlite3等のネイティブモジュールも扱える |
| Playwright | 最新安定 | E2E Test | 実ブラウザChromium/Firefox/WebKit操作で主要ユーザーフローを検証。SSEのリアルタイム挙動も検証可能 |
| ESLint | 最新安定 | リンタ | コード品質・一貫性維持。TypeScriptルールと連携 |
| TypeScripttsc | 5.x | 型チェック | 型エラーをCIで検出 |
## アーキテクチャパターン
### レイヤードアーキテクチャ
```
┌─────────────────────────────────────────────┐
│ UI層 (Next.js) │ ← Server Components / Client Components
│ Route Handler / Server Action / SSE │ 入力受付・表示・認証・認可
├─────────────────────────────────────────────┤
│ Service層 │ ← 業務ロジック・権限チェック・トランザクション
│ AuthService / ProjectService / ... │ 通知生成・アクティビティログ・SSE配信
├─────────────────────────────────────────────┤
│ Repository層 │ ← SQL保持・データアクセス・論理削除フィルタ
│ UserRepository / ProjectRepository / ... │
├─────────────────────────────────────────────┤
│ Data層 │ ← SQLite接続・SQL実行・Migration
│ lib/db/sqlite.ts / migrator.ts / SQLite │
└─────────────────────────────────────────────┘
```
### レイヤ責務と依存規則
依存は一方向UI → Service → Repository → Dataのみ許可する。逆方向依存・層飛ばしを禁止する。
#### UI層Route Handler / Server Action / Server Components / SSEエンドポイント
- **責務**: 入力受付・バリデーション・認証・認可・結果表示
- **許可操作**: Service層の呼び出し
- **禁止操作**: Repository層・Data層への直接アクセス、SQLの直接記述
#### Service層
- **責務**: 業務ロジック・権限チェック(`isMember`/ロール・トランザクション境界・副作用通知生成・アクティビティログ記録・SSE配信
- **許可操作**: Repository層の呼び出し・FileStorageServiceによるファイル操作・SseHubへの配信依頼
- **禁止操作**: UI層への依存、SQLの直接記述、SQLiteライブラリの直接操作
#### Repository層
- **責務**: SQLの保持・パラメータバインド実行・論理削除`deleted_at IS NULL`)の確実な付与・プロジェクト分離の担保
- **許可操作**: SQLラッパー`lib/db/sqlite.ts`経由のDBアクセス
- **禁止操作**: 業務ロジックの実装、SQLiteライブラリの直接操作、UI層への依存
#### Data層
- **責務**: SQLite接続の共通管理・SQL実行・トランザクション・Migration
- **許可操作**: better-sqlite3へのアクセス・ファイルシステムMigrationファイル・バックアップへのアクセス
- **禁止操作**: 業務ロジックの実装
```typescript
// 許容: UI → Service → Repository → Data
routeHandler projectService.createProject(...) projectRepository.create(...) db.execute(sql, params)
// 禁止: UI → Data (層飛ばし)
routeHandler db.execute("INSERT INTO projects ...") // ❌
// 禁止: Repository → SQLite直接 (ラッパー未使用)
projectRepository new Database(dbPath) // ❌
```
### ランタイム方針
SQLiteを直接扱うため、Next.jsのEdge Runtimeは使用しない。API Route・Server Actions・DBアクセス処理・SSEエンドポイントはすべてNode.js Runtimeで実行する。各Route Handlerの先頭で `export const runtime = 'nodejs'` を明示する。
### Prisma不使用の方針
DBアクセスは独自SQLラッパー`lib/db/sqlite.ts`とRepositoryクラスで実装する。Prismaは導入しない。
- 理由1: SQLを直接制御することでクエリ最適化・インデックス設計を明示できる
- 理由2: better-sqlite3の同期APIと相性が良く、コード生成のオーバーヘッドがない
- 理由3: MigrationもSQLファイルベースの独自実装でバージョン管理する
## データ永続化戦略
### 保存方式
| データ種別 | 保存先 | 形式 | 理由 |
|-----------|----------|-------------|------|
| アプリケーションデータ | SQLite`./data/app.db` | リレーショナル | トランザクション・外部キー・インデックス・論理削除を一貫管理 |
| アップロードファイル | ローカルFS`./data/uploads/<projectId>/` | バイナリ | 外部ストレージ不要・自己完結。DBにメタデータ`file_assets`)を保存 |
| Migration履歴 | SQLite`schema_migrations` | 行レコード | 適用済みファイルを一意管理・再実行回避 |
| バックアップ | ローカルFS`./backups/` | ZIP | DBファイル+uploadsディレクトリをZIP化 |
### SQLite接続設定
- `journal_mode = WAL`: 読み書きの並行性向上
- `foreign_keys = ON`: 外部キー制約・カスケード削除を有効化
- 接続はシングルトン(`getDb()`で共有。dbPathは `process.env.SQLITE_PATH ?? "./data/app.db"`
### バックアップ戦略
- **作成タイミング**: 管理者がバックアップ画面から手動実行
- **作成内容**: SQLite DBファイル + uploadsディレクトリをZIP化
- **保存先**: `./backups/backup-<timestamp>.zip`
- **世代管理**: 一覧表示・ダウンロード可能(世代数は運用で定義)
- **リストア手順**: サーバ停止 → ZIP展開 → `./data/app.db``./data/uploads/` を差替 → サーバ再起動
## パフォーマンス要件
### 応答時間
| 操作 | 目標時間 | 測定環境 |
|------|---------|---------|
| チャットSSE配信遅延 | 送信から全クライアント受信まで3秒以内95パーセンタイル | 小規模同時接続(数十) |
| 一覧画面表示 | 1000件データ時1秒以内掲示板・チャット履歴・ファイル一覧・Markdownメモ | ページネーション20件/頁 |
| バックアップ作成 | DB+uploads合計100MB相当で30秒以内 | ローカルFS |
| Migration実行 | 1ファイル1トランザクション・失敗時即座ロールバック | 初回スキーマ適用 |
### リソース使用量
| リソース | 上限 | 理由 |
|---------|------|------|
| メモリ | Next.jsサーバプロセス1GB程度 | 1プロジェクト数十人規模・小規模同時接続前提 |
| CPU | 単一サーバで十分 | SQLite同期処理・SSE数十接続を想定 |
| ディスク | DB+uploads合計数百MB〜数GBを想定 | バックアップは別途容量確保 |
### パフォーマンス最適化施策
- **ページネーション**: 全一覧APIで `?page=&pageSize=` を必須化し必要件数のみ取得
- **インデックス**: `project_notes(project_id)`, `project_notes(updated_at)` 等の高頻度検索カラムにインデックス付与
- **Server Components**: 可能な限りServer Componentsでデータ取得しクライアント送信量を削減
- **WALモード**: 読み書き並行性向上
- **SSE配信のスコープ限定**: プロジェクト単位でクライアント集合を管理し、無関係プロジェクトへの配信コストを排除
## セキュリティアーキテクチャ
### データ保護
- **パスワード保護**: bcryptでハッシュ化保存。平文保存禁止。ソルト付き・適切なコスト係数
- **暗号化**: 通信はHTTPS前提。保存時のDBファイル暗号化は本スコープ外ローカルFSのアクセス権限で保護
- **アクセス制御**: サーバプロセスのファイル権限により `./data/`, `./backups/` を保護
- **機密情報管理**: 設定は `.env` で管理(`SQLITE_PATH` 等)。コード内にハードコード禁止。`.env` はリポジトリにコミットしない
### 認証・認可
- **認証**: 独自ログイン方式・セッションベース。未認証リクエストは保護画面/APIにアクセス不可401/リダイレクト)
- **認可(プロジェクト)**: Service層で `ProjectMemberRepository.isMember(projectId, userId)` を必ず実施。非参加者は403
- **認可(管理者機能)**: バックアップ・Migration状態確認は `role='system_admin'` のみ許可
- **ファイルアクセス**: ダウンロードAPIでもプロジェクト参加権限をチェック
### 入力バリデーション
- **バリデーション**: 全入力で必須チェック・長さ制限タイトル1-200文字等・形式チェックをService層で実施
- **SQL対策**: 全SQLをパラメータバインドで実行。文字列結合によるSQL構築は禁止
- **Markdownサニタイズ**: HTML直接入力無効化 + rehype-sanitize でサニタイズ + 危険URLスキーム`javascript:`等)除外
- **ファイルアップロード**: MIMEタイプチェック・ファイル名サニタイズ・保存名の一意化`<uuid>.<ext>`
- **エラー表示**: スタックトレース・内部情報を本番では非表示。ユーザーには抽象メッセージのみ表示
### 監査
- 管理者操作・主要な変更操作をアクティビティログに記録(`activity_logs` テーブル)
## スケーラビリティ設計
### データ増大への対応
- **想定データ量**: 1プロジェクトあたり数十人・数千〜数万レコードチャット・掲示板・アクティビティログが主要
- **性能劣化対策**:
- ページネーションによる取得件数制限
- インデックス最適化(検索頻度高いカラム)
- 論理削除データの取得除外(`deleted_at IS NULL` を全取得クエリに付与)
- **アーカイブ戦略**: 完了/アーカイブ済みプロジェクトは `status='archived'` で残置。大量データの物理削除は本スコープ外(運用で判断)
### 拡張性
- **プラグインシステム**: なし(本スコープ外)
- **設定カスタマイズ**: `.env` による設定管理(`SQLITE_PATH`・ uploadsパス等
- **API拡張性**: Route Handlerベースでリソースごとにエンドポイントを分割。将来の公開REST API化はPost-MVP
- **SSEイベント拡張**: `SseEvent` 型に新種別を追加するだけで新イベント配信が可能
## テスト戦略
### Unit Test
- **フレームワーク**: Vitest
- **対象**: SQLラッパー・Migration・全Repository・全Service・権限チェック・バリデーション・スケジュール重複判定・通知作成ロジック・アクティビティログ作成ロジック・マイルストーン進捗計算
- **カバレッジ目標**: Repository/Service層 80%以上
- **実行コマンド**: `npm test`
### 統合テスト
- **方法**: Vitestで実際のSQLite一時ファイルを使用
- **対象**: 認証フロー・プロジェクト作成→メンバー追加→権限分離・チャット送信→SSE配信
### E2E Test
- **ツール**: Playwright
- **シナリオ**: 認証・プロジェクト管理・掲示板・チャットSSEリアルタイム・ToDoドラッグ&ドロップ・ファイル共有Lightbox・Markdownメモ・カレンダー・ミーティング予定重複警告・通知・アクティビティログ・バックアップ
- **実行コマンド**: `npm run test:e2e`
## 技術的制約
### 環境要件
- **OS**: devcontainer開発/ Linux想定本番。Windows・macOSでもNode.js Runtime動作可能
- **最小メモリ**: 1GB
- **必要ディスク**: DB+uploads+backups数百MB〜数GB
- **必須外部依存**: なし外部DB・外部ストレージ・外部IdPに非依存・自己完結
### パフォーマンス制約
- 1プロジェクトあたり数十人規模を想定数百人規模はスコープ外
- チャットSSEは小規模同時接続数十接続を前提
- 一覧取得は必ずページネーション(全件取得禁止)
### セキュリティ制約
- 認証必須(`/api/auth/*`除く)
- 全SQLパラメータバインド文字列結合禁止
- Markdown表示時のHTML無効化・サニタイズ必須
- パスワード平文保存禁止
### ランタイム制約
- Edge Runtime使用禁止SQLite直接操作のため全てNode.js Runtime
- Prisma使用禁止
## 依存管理
| ライブラリ | 目的 | バージョン管理方針 |
|-----------|------|-------------------|
| next | フレームワーク | 固定(破壊的変更リスク大) |
| react / react-dom | UI | ^(マイナーアップ許容) |
| better-sqlite3 | SQLiteドライバ | ^(ネイティブビルド要注意) |
| react-markdown / remark-gfm / rehype-sanitize | Markdown | ^(マイナーアップ許容) |
| bcrypt | パスワードハッシュ | ^ |
| tailwindcss | スタイリング | ^ |
| typescript | 型チェック | ~パッチのみ自動・devDependencies |
| vitest | Unit Test | ^devDependencies |
| @playwright/test | E2E Test | ^devDependencies |
| eslint | リンタ | ^devDependencies |
**方針**:
- 安定版は `^` でマイナーアップを許容
- 破壊的変更リスクのあるものnext等は固定
- devDependenciesは `~` でパッチのみ自動アップ許容
- package-lock.jsonで厳密にロックしCIで再現性を担保
## チェックリスト
- [x] 全技術選定に理由が記載されている
- [x] レイヤードアーキテクチャが明確に定義されている(依存規則含む)
- [x] パフォーマンス要件が測定可能である
- [x] セキュリティ考慮事項が文書化されている
- [x] スケーラビリティが考慮されている
- [x] バックアップ戦略が定義されている
- [x] 依存管理方針が明確である
- [x] テスト戦略が定義されている

View File

@ -0,0 +1,761 @@
# 開発ガイドライン (Development Guidelines)
> 本書はシンプルグループウェアのチーム開発におけるコーディング規約と開発プロセスを定義する。技術スタックは `docs/architecture.md`、ディレクトリ構成は `docs/repository-structure.md` に基づく。
## コーディング規約
### 命名規約
#### 変数・関数
```typescript
// ✅ 良い例: 役割が明確
const projectMembers = await projectMemberRepository.findByProject(projectId);
function formatDueDate(dueDate: string): string { }
const hasPermission = await projectMemberRepository.isMember(projectId, userId);
// ❌ 悪い例: 曖昧
const data = await repo.find(id);
function calc(arr: any[]): number { }
```
**原則**:
- 変数: camelCase・名詞または名詞句
- 関数: camelCase・動詞始まり`find`, `create`, `update`, `delete`, `format`, `validate`
- 定数: UPPER_SNAKE_CASE`MAX_PAGE_SIZE`, `DEFAULT_PAGE_SIZE`
- 真偽値: `is`, `has`, `should`, `can` 始まり(`isMember`, `hasPermission`
#### クラス・インターフェース・型
```typescript
// クラス: PascalCase + 役割接尾
class UserRepository { }
class ChatService { }
class SqliteDatabase { }
// インターフェース: PascalCase接尾辞Iは付けない
interface ProjectMember { }
interface CreateMeetingInput { }
// 型エイリアス: PascalCase
type ProjectStatus = 'active' | 'on_hold' | 'completed' | 'archived';
type NotificationType = 'mention' | 'todo_assigned' | ...;
```
#### ファイル名
- Repository/Serviceクラス: PascalCase + 接尾(`UserRepository.ts`, `ChatService.ts`
- 関数・ユーティリティ: camelCase・動詞始まり`formatDate.ts`, `validateEmail.ts`
- 型定義: PascalCase`TodoItem.ts`
- Reactコンポーネント: PascalCase`KanbanBoard.tsx`
- Route Handler/画面: Next.js固定名`route.ts`, `page.tsx`, `layout.tsx`
- Migration: `NNN_description.sql``001_initial.sql`
### コードフォーマット
- **インデント**: 2スペース
- **行長**: 最大100文字
- **セミコロン**: 必須
- **クォート**: シングルクォート
- **ツール**: Prettier`.prettierrc`+ ESLint`eslint.config.js` Flat Configで自動整形
### TypeScript規約
#### 型定義
```typescript
// ✅ 良い例: 明示的な型注釈
function findByProject(projectId: number): ProjectMember[] { }
// ❌ 悪い例: 型推論への過度な依存暗黙のany
function findByProject(projectId) { }
```
- 公開APIの引数・戻り値には明示的な型注釈を付ける
- `any` は原則禁止。やむを得ない場合は `unknown` + 型ガードを使用
- オブジェクト型は `interface`、共用型・プリミティブ型は `type` エイリアスを使用
- Entity型は `lib/types/` に集約し、レイヤ間で共有する
#### 関数設計
```typescript
// ✅ 良い例: 単一責任・パラメータをオブジェクトに集約
interface CreateTodoInput {
title: string;
description?: string;
assigneeId?: number;
dueDate?: string;
priority?: TodoPriority;
}
function createTodo(input: CreateTodoInput): TodoItem { }
// ❌ 悪い例: 多すぎるパラメータ
function createTodo(title, description, assigneeId, dueDate, priority, milestoneId): TodoItem { }
```
- 1関数の責務は単一に目安20行以内・50行推奨上限
- パラメータが4つ超の場合はオブジェクトに集約
- 1ファイル300行以下推奨・500行超は分割
### コメント規約
#### ドキュメントコメントTSDoc
```typescript
/**
* プロジェクトにメンバーを追加する
*
* @param actorId - 操作実行者のユーザーID権限チェックに使用
* @param projectId - 対象プロジェクトID
* @param userId - 追加するユーザーID
* @param role - プロジェクト内ロール
* @throws {ForbiddenError} 実行者に権限がない場合
* @throws {NotFoundError} プロジェクトまたはユーザーが存在しない場合
*/
async function addMember(
actorId: number,
projectId: number,
userId: number,
role: ProjectMemberRole
): Promise<void> { }
```
#### インラインコメント
```typescript
// ✅ 良い例: 理由を説明する
// 論理削除済みデータを除外するため deleted_at IS NULL を付与
const threads = db.query<BoardThread>(`
SELECT * FROM board_threads
WHERE project_id = @projectId AND deleted_at IS NULL
`, { projectId });
// ❌ 悪い例: コードの再述
// スレッドを取得する
const threads = db.query(...);
```
- コードから自明な内容は書かない
- 「なぜ」その処理をするかを書く
- TODO/FIXMEは課題番号と共に記載`// TODO: キャッシュを実装する (Issue #123)`
- コメントアウトされたコードは残さない(削除する)
### エラーハンドリング
#### カスタムエラークラス
```typescript
// 期待されるエラー: 適切なエラークラスを定義
class ValidationError extends Error {
constructor(message: string, public field: string, public value: unknown) {
super(message);
this.name = 'ValidationError';
}
}
class ForbiddenError extends Error {
constructor(message: string) {
super(message);
this.name = 'ForbiddenError';
}
}
class NotFoundError extends Error {
constructor(public resource: string, public id: number | string) {
super(`${resource} not found: ${id}`);
this.name = 'NotFoundError';
}
}
```
#### エラー処理パターン
```typescript
// ✅ 良い例: 期待されるエラーは適切に処理、予期せぬエラーは伝播
async function getThread(threadId: number): Promise<BoardThread> {
const thread = await boardRepository.findThreadById(threadId);
if (!thread) {
throw new NotFoundError('BoardThread', threadId);
}
return thread;
}
// Route HandlerでのHTTPステータスへの変換
try {
const thread = await boardService.getThread(threadId);
return Response.json(thread);
} catch (error) {
if (error instanceof ValidationError) return Response.json({ error: { message: error.message } }, { status: 400 });
if (error instanceof ForbiddenError) return Response.json({ error: { message: error.message } }, { status: 403 });
if (error instanceof NotFoundError) return Response.json({ error: { message: error.message } }, { status: 404 });
console.error('Unexpected error:', error);
return Response.json({ error: { message: '内部エラーが発生しました' } }, { status: 500 });
}
// ❌ 悪い例: エラーを無視して null を返す
async function getThread(threadId: number): Promise<BoardThread | null> {
try {
return await boardRepository.findThreadById(threadId);
} catch (error) {
return null; // エラー情報が失われる
}
}
```
**原則**:
- 期待されるエラー(バリデーション・権限・存在確認)は適切なエラークラスで表現
- 予期せぬエラーは上位に伝播しログに記録
- エラーを無視空catchしない
- エラーメッセージは具体的で解決策を示す(`'タイトルは1-200文字で入力してください。現在: 250文字'`
## プロジェクト固有規約
### Repository層の規約
#### SQLは必ずパラメータバインド
```typescript
// ✅ 良い例: パラメータバインド
const user = db.get<User>('SELECT * FROM users WHERE email = @email', { email });
// ❌ 悪い例: 文字列結合SQLインジェクション脆弱性
const user = db.get<User>(`SELECT * FROM users WHERE email = '${email}'`);
```
#### 論理削除テーブルの取得には必ず deleted_at IS NULL
```typescript
// ✅ 良い例
const notes = db.query<ProjectNote>(`
SELECT * FROM project_notes
WHERE project_id = @projectId AND deleted_at IS NULL
ORDER BY is_pinned DESC, updated_at DESC
LIMIT @limit OFFSET @offset
`, { projectId, limit, offset });
// ❌ 悪い例: 削除済みデータが混入
const notes = db.query<ProjectNote>(`SELECT * FROM project_notes WHERE project_id = @projectId`, { projectId });
```
#### Repositoryは直接SQLiteライブラリを触らない
```typescript
// ✅ 良い例: SQLラッパー経由
import { getDb } from '@/lib/db/sqlite';
const db = getDb();
db.execute('INSERT INTO projects ...', params);
// ❌ 悪い例: better-sqlite3を直接操作
import Database from 'better-sqlite3';
const db = new Database('./data/app.db');
```
#### ページネーション
一覧取得APIは必ずページネーション`LIMIT`/`OFFSET`)し、全件取得しない。
```typescript
function findThreads(projectId: number, page: number, pageSize: number = 20) {
const offset = (page - 1) * pageSize;
return db.query<BoardThread>(`
SELECT * FROM board_threads
WHERE project_id = @projectId AND deleted_at IS NULL
ORDER BY is_pinned DESC, created_at DESC
LIMIT @pageSize OFFSET @offset
`, { projectId, pageSize, offset });
}
```
### Service層の規約
#### 権限チェックを必ず実施
```typescript
// ✅ 良い例: 操作前に権限チェック
async function addMember(actorId: number, projectId: number, userId: number, role: ProjectMemberRole) {
const actorRole = await projectMemberRepository.getRole(projectId, actorId);
if (!actorRole || actorRole !== 'admin') {
throw new ForbiddenError('プロジェクト管理者のみメンバー追加が可能です');
}
// ...メンバー追加処理
}
```
#### トランザクション境界の明示
複数テーブルを更新する場合はトランザクション内で実行する。
```typescript
async function createMeeting(actorId: number, projectId: number, input: MeetingInput) {
return db.transaction(() => {
const meeting = meetingRepository.create({ ...input, projectId, createdById: actorId });
meetingRepository.addMembers(meeting.id, input.memberIds);
activityLogService.log({ projectId, actorId, action: 'meeting_created', targetType: 'meeting', targetId: meeting.id });
return meeting;
});
}
```
#### 副作用の分離
通知生成・アクティビティログ記録・SSE配信は専用Service`NotificationService`, `ActivityLogService`, `SseHub`)に委譲し、業務ロジックと分離する。
### Next.js規約
#### Node.js Runtimeの明示
```typescript
// app/api/.../route.ts の先頭
export const runtime = 'nodejs'; // Edge Runtime使用禁止
```
#### Server Componentsを優先
データ取得は可能な限りServer Componentsで行い、クライアント送信量を削減する。インタラクティブな要素ドラッグ&ドロップ・SSE受信・フォームのみClient Componentsとする。
#### Markdownレンダリングの安全性
```typescript
// ✅ 必ず rehype-sanitize を通す
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeSanitize from 'rehype-sanitize';
<ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeSanitize]}>
{bodyMd}
</ReactMarkdown>
```
HTML直接入力は無効化し、危険なURLスキーム`javascript:`等)は除外する。
### セキュリティ規約
- 機密情報パスワード・APIキーはコードにハードコードしない。`.env` で管理
- パスワードは bcrypt でハッシュ化保存
- ファイルアップロードはMIMEタイプチェック・ファイル名サニタイズ・保存名の一意化
- ファイルアクセスAPIでもプロジェクト参加権限をチェック
- 管理者機能バックアップ・Migration状態`role='system_admin'` のみ許可
## Gitワークフロー規則
### ブランチ戦略Git Flow
```
main (本番環境)
└── develop (開発統合)
├── feature/task-management
├── feature/user-auth
├── fix/chat-sse-reconnect
└── refactor/todo-repository
```
**運用ルール**:
- `main`: リリース済みの安定コードのみ。タグでバージョン管理
- `develop`: 次回リリースの最新開発コード。CIで自動テスト実行
- `feature/*`, `fix/*`: developから分岐しPR経由でdevelopへマージ
- `release/*`: リリース準備(必要に応じて)
- `hotfix/*`: 本番障害対応mainから分岐しmain/develop両方へマージ
- 直接コミット禁止: 全ブランチでPRレビュー必須
- マージ方針: feature→develop はsquash merge推奨、develop→main はmerge commit
### コミットメッセージ規約Conventional Commits
```
<type>(<scope>): <subject>
<body>
<footer>
```
**type**:
- `feat`: 新機能
- `fix`: バグ修正
- `docs`: ドキュメント
- `style`: フォーマット(コード挙動への影響なし)
- `refactor`: リファクタリング
- `perf`: パフォーマンス改善
- `test`: テスト追加・修正
- `build`: ビルドシステム
- `ci`: CI/CD設定
- `chore`: その他(依存更新等)
**例**:
```
feat(chat): SSEによるリアルタイムメッセージ配信を実装
プロジェクト別のSSEエンドポイントを追加し、メッセージ送信時に
参加メンバーへリアルタイム配信する。
- SseHubクラスをlib/sse/hub.tsに追加
- ChatService.sendMessageでブロードキャスト
- chat.message.created/updated/deletedイベント定義
Closes #42
```
### Pull Requestプロセス
**PR作成前チェック**:
- [ ] 全テスト成功(`npm test`, `npm run test:e2e`
- [ ] Lintエラーなし`npm run lint`
- [ ] 型チェック成功(`npm run typecheck`
- [ ] コンフリクト解消済み
**PRテンプレート**:
```markdown
## 変更種別
- [ ] 新機能 (feat)
- [ ] バグ修正 (fix)
- [ ] リファクタリング (refactor)
- [ ] ドキュメント (docs)
- [ ] その他 (chore)
## 概要
[変更内容の簡潔な説明]
## 変更理由
[なぜこの変更が必要か]
## 変更内容
- [変更1]
- [変更2]
## テスト
- [ ] Unit Test追加
- [ ] E2E Test追加
- [ ] 手動テスト実施
テスト結果: [説明]
## 関連Issue
Closes #[番号]
## レビューポイント
[特に確認してほしい点]
```
**レビュープロセス**:
1. セルフレビュー
2. 自動テスト実行CI
3. レビュアー割当
4. レビュー指摘対応
5. 承認後にマージ
**PRサイズ目安**:
- 小PR100行以下: 推奨
- 中PR100-300行: 許容
- 大PR300行超: 分割を検討
## テスト戦略
### テスト実装の必須条件
本プロジェクトでは、品質担保のため **Unit TestVitestと E2E TestPlaywrightの実装を必須とする。** テストが未実装・未成功のPRはマージ不可。
#### Unit TestVitestの実装【必須】
以下の対象について Unit Test の実装を必須とする。新規実装・修正時に対応する Unit Test を必ず作成すること。
- SQLラッパー
- Migration実行
- 全RepositoryクラスUser / Project / ProjectMember / Board / Chat / Todo / File / Calendar / Meeting / ProjectNote / Notification / ActivityLog
- 全ServiceクラスAuth / Project / Chat / Meeting / Schedule / FileStorage / Backup
- 権限チェック・バリデーション・スケジュール重複判定・通知作成ロジック・アクティビティログ作成ロジック・マイルストーン進捗計算
**合格基準**:
- [ ] `npm test` で全件成功すること
- [ ] Repository/Service層のカバレッジ 80%以上を維持すること
- [ ] 正常系・異常系(権限エラー・バリデーションエラー・存在確認)を網羅すること
#### E2E TestPlaywrightの実装【必須】
主要ユーザーフローについて Playwright による E2E Test の実装を必須とする。機能追加時は該当フローの E2E Test を必ず作成すること。
対象フロー:
- 認証(ログイン・ログアウト・未ログインの保護)
- プロジェクト管理(作成・編集・メンバー追加/削除・アーカイブ)
- 掲示板(スレッド作成・編集・コメント・検索)
- チャット送信・SSEリアルタイム受信・編集・削除
- ToDo / Kanbanカラム作成・タスク作成・編集・移動・担当者/期限設定・完了)
- ファイル共有アップロード・一覧・Lightbox閲覧・PDFプレビュー・削除
- Markdownメモ作成・編集・プレビュー・ピン留め・検索・削除
- カレンダーToDo期限・マイルストーン・ミーティング表示・イベント作成/編集)
- ミーティング(作成・参加メンバー設定・予定重複警告・アジェンダ/議事録・関連付け)
- 通知ToDo担当者・メンション・ミーティング参加者への通知・既読化
- アクティビティログ(各操作の記録)
- バックアップ(作成・一覧表示・ダウンロード)
**合格基準**:
- [ ] `npm run test:e2e` で全件成功すること
- [ ] 主要フローのカバレッジ 100%を維持すること
### テストピラミッド
```
/\
/E2E\ 少数(遅い・高コスト)
/------\
/ Integ. \ 中程度
/----------\
/ Unit \ 多数(高速・低コスト)
/--------------\
```
**対象比率**:
- Unit Test: 70%
- Integration Test: 20%
- E2E Test: 10%
### Unit TestVitest
**対象**: SQLラッパー・Migration・全Repository・全Service・権限チェック・バリデーション・スケジュール重複判定・通知作成ロジック・アクティビティログ作成ロジック・マイルストーン進捗計算
**カバレッジ目標**: Repository/Service層 80%以上
**構造Given-When-Then**:
```typescript
describe('ChatService', () => {
describe('sendMessage', () => {
it('有効なデータでメッセージを作成できる', async () => {
// Given: セットアップ
const chatService = new ChatService(mockChatRepo, mockSseHub, mockNotificationService);
const input = { body: 'テストメッセージ' };
// When: 実行
const result = await chatService.sendMessage(actorId, projectId, input.body);
// Then: 検証
expect(result.id).toBeDefined();
expect(result.body).toBe('テストメッセージ');
expect(mockSseHub.broadcast).toHaveBeenCalledWith(projectId, expect.objectContaining({ type: 'chat.message.created' }));
});
it('プロジェクト非参加者はメッセージ送信時にForbiddenErrorを投げる', async () => {
// Given
const chatService = new ChatService(...);
mockProjectMemberRepository.isMember.mockReturnValue(false);
// When/Then
await expect(chatService.sendMessage(nonMemberId, projectId, 'body')).rejects.toThrow(ForbiddenError);
});
});
});
```
**テスト命名**: `[対象]_[条件]_[期待結果]`
```typescript
it('findById_existingId_returnsThread', () => { });
it('findById_nonExistentId_returnsNull', () => { });
it('create_emptyTitle_throwsValidationError', () => { });
```
**モック原則**: 外部依存DB・ファイルシステム・SSEはモック化、業務ロジックは実体を使用。
### Integration TestVitest
**対象**: 複数コンポーネントの連携。実際のSQLite一時ファイルを使用。
```typescript
describe('プロジェクトメンバー権限', () => {
it('非参加者はプロジェクトデータにアクセスできない', async () => {
// 実DBでプロジェクト・ユーザー作成
const project = await projectService.createProject(ownerId, { name: 'P1' });
await expect(boardService.listThreads(nonMemberId, project.id)).rejects.toThrow(ForbiddenError);
});
});
```
### E2E TestPlaywright
**対象**: 主要ユーザーフローの全体検証。`tests/e2e/*.spec.ts`
```typescript
test('チャットメッセージがSSEでリアルタイム配信される', async ({ browser }) => {
const contextA = await browser.newContext();
const contextB = await browser.newContext();
const pageA = await contextA.newPage();
const pageB = await contextB.newPage();
// 両ブラウザで同プロジェクトのチャット画面を開く
await pageA.goto('/projects/1/chat');
await pageB.goto('/projects/1/chat');
// Aがメッセージ送信
await pageA.fill('input[name=message]', 'こんにちは');
await pageA.click('button[type=submit]');
// Bにリアルタイム表示される
await expect(pageB.locator('text=こんにちは')).toBeVisible();
});
```
**カバレッジ目標**: 主要フロー100%認証・プロジェクト管理・掲示板・チャット・ToDo・ファイル・メモ・カレンダー・ミーティング・通知・アクティビティ・バックアップ
### 実行コマンド
| コマンド | 説明 |
|---------|------|
| `npm test` | Unit Test実行Vitest |
| `npm run test:e2e` | E2E Test実行Playwright |
| `npm run lint` | Lint実行ESLint |
| `npm run typecheck` | 型チェック実行tsc --noEmit |
| `npm run build` | ビルド |
## コードレビュー基準
### レビューポイント
**機能性**:
- [ ] 要件を満たしているか
- [ ] エッジケースが考慮されているか
- [ ] エラーハンドリングが適切か
**可読性**:
- [ ] 命名が明確か
- [ ] コメントが適切か
- [ ] 複雑なロジックに説明があるか
**保守性**:
- [ ] 重複コードがないか
- [ ] 責務が分離されているか
- [ ] 変更の影響範囲が限定的か
**パフォーマンス**:
- [ ] 不要な計算がないか
- [ ] N+1クエリになっていないか
- [ ] 一覧取得がページネーションされているか
**セキュリティ**:
- [ ] 入力バリデーションが適切か
- [ ] SQLがパラメータバインドされているか
- [ ] 権限チェックが実装されているか
- [ ] 機密情報のハードコードがないか
- [ ] Markdownがサニタイズされているか
### レビューコメントの書き方
**建設的フィードバック**:
```markdown
// ✅ 良い例
この実装だとメンバー数増加時にN+1クエリになります。
JOINで一括取得するのはいかがでしょうか
// ❌ 悪い例
この書き方は良くないです。
```
**優先度の明示**:
- `[必須]`: 修正必須(セキュリティ・バグ等)
- `[推奨]`: 修正推奨
- `[提案]`: 検討提案
- `[質問]`: 意図の確認
## 開発環境セットアップ
### 必須ツール
| ツール | バージョン | インストール方法 |
|--------|-----------|-----------------|
| Node.js | v24.11.0 | 公式インストーラ/nvm |
| npm | 11.x | Node.jsにバンドル |
| devcontainer | - | VS Code拡張開発環境統一 |
### セットアップ手順
```bash
# 1. リポジトリクローン
git clone [URL]
cd [project-name]
# 2. 依存関係インストール
npm install
# 3. 環境変数設定
cp .env.example .env
# .env を編集SQLITE_PATH等
# 4. DB初期化Migration実行
npm run migrate
# 5. 開発サーバ起動
npm run dev
```
### 品質自動化
**Pre-commitHusky + lint-staged**: コミット前にLint・フォーマット・型チェックを自動実行
```json
// package.json
{
"scripts": {
"lint": "eslint .",
"format": "prettier --write .",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test:e2e": "playwright test",
"migrate": "tsx lib/db/run-migrations.ts",
"dev": "next dev",
"build": "next build"
},
"lint-staged": {
"*.{ts,tsx}": ["eslint --fix", "prettier --write"]
}
}
```
**CIGitHub Actions**: PR作成時にLint・型チェック・Unit Test・ビルドを自動実行
```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
```
**効果**: 欠陥コードの混入防止・早期発見による修正コスト削減・CIによる品質担保。
## チェックリスト
### 実装完了前
- [ ] 命名が明確で一貫している
- [ ] 関数が単一責務
- [ ] マジックナンバーがない
- [ ] 型注釈が適切
- [ ] エラーハンドリングが実装されている
### セキュリティ
- [ ] 入力バリデーション実装
- [ ] 機密情報のハードコードなし
- [ ] SQLパラメータバインド
- [ ] 権限チェック実装
- [ ] Markdownサニタイズ
### パフォーマンス
- [ ] 適切なデータ構造
- [ ] N+1クエリ回避
- [ ] 一覧のページネーション
### テスト【必須】
- [ ] Unit TestVitest作成
- [ ] E2E TestPlaywright作成
- [ ] `npm test` 全件成功
- [ ] `npm run test:e2e` 全件成功
- [ ] エッジケース網羅
### ツール
- [ ] Lintエラーなし
- [ ] 型チェック成功
- [ ] フォーマット統一

1077
docs/functional-design.md Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

870
docs/milestones.md Normal file
View File

@ -0,0 +1,870 @@
# マイルストーン・タスク定義書 (Milestones & Tasks)
> 本書は `docs/product-requirements.md`・`docs/functional-design.md`・`docs/architecture.md`・`docs/repository-structure.md`・`docs/development-guidelines.md` に基づき、プロジェクト全体のマイルストーンと各マイルストーンのタスクを詳細に定義する。機能漏れを防ぐため、末尾に「機能カバレッジマトリクス」を設ける。
## マイルストーン全体構成
PRDの開発フェーズPhase 1〜5を依存関係を考慮して15マイルストーンに展開する。
| MS | 名称 | 対応フェーズ | 主な成果物 | 前提 |
|----|------|------------|-----------|------|
| M1 | プロジェクト基盤セットアップ | Phase 1 | Next.js環境・設定ファイル・CI | - |
| M2 | DB基盤SQLラッパー・Migration | Phase 1 | sqlite.ts・migrator.ts・初期スキーマ | M1 |
| M3 | 認証・ユーザー管理 | Phase 1 | AuthService・UserRepository・ログイン画面 | M2 |
| M4 | プロジェクト管理・メンバー管理 | Phase 1 | ProjectService・プロジェクト画面・レイアウト | M3 |
| M5 | 通知・アクティビティログ基盤 | Phase 2 | NotificationService・ActivityLogService | M4 |
| M6 | 掲示板 | Phase 2 | BoardService・掲示板画面 | M5 |
| M7 | Markdownメモ | Phase 2 | NoteService・メモエディタ・Markdownプレビュー | M5 |
| M8 | SSE基盤・チャット | Phase 3 | SseHub・ChatService・チャット画面 | M5 |
| M9 | ToDo / Kanban | Phase 3 | TodoService・Kanbanボード | M8 |
| M10 | ファイル共有・Lightbox | Phase 4 | FileStorageService・Lightbox | M4 |
| M11 | カレンダー・マイルストーン | Phase 4 | ScheduleService・カレンダーUI・進捗計算 | M9 |
| M12 | ミーティング管理・スケジュール重複 | Phase 5 | MeetingService・重複判定アルゴリズム | M11 |
| M13 | 検索・ダッシュボード完成 | (横断) | 横断検索・個人/プロジェクトダッシュボード | M6-M12 |
| M14 | バックアップ・管理者機能 | Phase 5 | BackupService・管理者画面 | M2 |
| M15 | 全体テスト完成・品質担保 | (全体) | 全Unit/E2E/統合テスト成功 | M1-M14 |
### マイルストーン進行ルール
- 各マイルストーン完了時に `npm run lint``npm run typecheck` が成功すること
- 各マイルストーンで実装したRepository/Service/画面には **Unit Test または E2E Test を必須で実装**する(`docs/development-guidelines.md` テスト実装の必須条件に準拠)
- テスト未実装・未成功のマイルストーンは完了扱いとしない
---
## M1: プロジェクト基盤セットアップ
**目的**: Next.js 15 + TypeScript + Tailwind CSS の開発環境を構築し、全レイヤのディレクトリ構成と品質自動化ツールを整える。
**前提**: なし
### 実装タスク
**基盤・設定**:
- [ ] Next.js 15 プロジェクト初期化App Router・TypeScript
- [ ] Tailwind CSS セットアップ(`app/globals.css``tailwind.config`
- [ ] `tsconfig.json` 設定(`@/*` パスエイリアス・strict モード)
- [ ] `next.config.mjs` 設定
- [ ] `.env.example` 作成(`SQLITE_PATH`・uploadsパス等
- [ ] ディレクトリ構成作成: `app/``lib/``repositories/``services/``components/``tests/``data/``backups/`
**品質自動化ツール**:
- [ ] ESLint セットアップ(`eslint.config.js` Flat Config
- [ ] Prettier セットアップ(`.prettierrc``.prettierignore`
- [ ] Vitest セットアップ(`vitest.config.ts`
- [ ] Playwright セットアップ(`playwright.config.ts`
- [ ] Husky + lint-staged セットアップpre-commit で Lint・フォーマット・型チェック
- [ ] CI 設定(`.github/workflows/ci.yml`: Lint・型チェック・Unit Test・ビルド
**package.json スクリプト**:
- [ ] `lint``format``typecheck``test``test:e2e``migrate``dev``build` スクリプト定義
**依存関係**:
- [ ] 本体依存: next・react・react-dom・better-sqlite3・bcrypt・react-markdown・remark-gfm・rehype-sanitize・tailwindcss
- [ ] dev依存: typescript・vitest・@playwright/test・eslint・prettier・husky・lint-staged・tsx
### 完了条件
- [ ] `npm run dev` で開発サーバが起動する
- [ ] `npm run lint``npm run typecheck``npm run build` が成功する
- [ ] ディレクトリ構成が `repository-structure.md` に準拠している
---
## M2: DB基盤SQLラッパー・Migration
**目的**: SQLiteへの共通アクセス基盤とSQLファイルベースのMigration機構を実装する。
**前提**: M1
### 実装タスク
**Data層**:
- [ ] `lib/db/sqlite.ts`: `SqliteDatabase` クラス実装
- `query<T>` / `get<T>` / `execute` / `transaction<T>` / `close`
- コンストラクタで `journal_mode=WAL``foreign_keys=ON` 設定
- `getDb()` シングルトンdbPath = `process.env.SQLITE_PATH ?? "./data/app.db"`
- [ ] `lib/db/migrator.ts`: `Migrator` クラス実装
- `schema_migrations` テーブル作成
- ファイル名順実行・実行済み再実行回避・1ファイル1トランザクション・失敗時ロールバック
- [ ] `lib/db/migrations/001_initial.sql`: 全16テーブル + インデックス作成
- users・projects・project_members・board_threads・board_comments・chat_messages・todo_columns・todo_items・file_assets・project_notes・milestones・calendar_events・meetings・meeting_members・notifications・activity_logs
- `idx_project_notes_project_id``idx_project_notes_updated_at` インデックス
**型定義**:
- [ ] `lib/types/` に全Entity型定義User・Project・ProjectMember・BoardThread・BoardComment・ChatMessage・TodoColumn・TodoItem・FileAsset・ProjectNote・Milestone・CalendarEvent・Meeting・MeetingMember・Notification・ActivityLog・SchemaMigration
- 列挙型: `UserRole``UserStatus``ProjectStatus``ProjectMemberRole``BoardCategory``TodoPriority``MilestoneStatus``CalendarEventType``MeetingMemberStatus``NotificationType`
**Migration実行・状態確認**:
- [ ] `lib/db/run-migrations.ts`: Migration実行スクリプト`npm run migrate`
- [ ] API: `GET /api/admin/migrations`Migration状態確認・管理者のみ
### テスト
- [ ] **Unit Test**: `tests/unit/lib/db/sqlite.test.ts`query/get/execute/transaction・WAL/外部キー設定)
- [ ] **Unit Test**: `tests/unit/lib/db/migrator.test.ts`(ファイル名順実行・再実行回避・失敗時ロールバック)
### 完了条件
- [ ] `npm run migrate` で初期スキーマが作成される
- [ ] Migrationがファイル名順に実行され、実行済みは再実行されない
- [ ] Migration失敗時にロールバックされる
- [ ] Unit Test が成功する
---
## M3: 認証・ユーザー管理
**目的**: 独自ログイン方式による認証とユーザー管理(登録・ログイン・プロフィール・ロール・有効/無効)を実装する。
**前提**: M2
### 実装タスク
**Repository**:
- [ ] `repositories/UserRepository.ts`: `findById``findByEmail``create``update`
**Service**:
- [ ] `services/AuthService.ts`: `register``login``logout``getCurrentUser``updateProfile`
- [ ] パスワードハッシュ化bcrypt・平文保存禁止
- [ ] ロール管理system_admin・project_admin・member・guest
- [ ] アカウント有効/無効status='inactive' はログイン不可)
**認証ヘルパ**:
- [ ] `lib/auth/session.ts`: セッション読み書き
- [ ] `lib/auth/getCurrentUser.ts`: リクエストから現在ユーザー解決
**バリデータ**:
- [ ] `lib/validators/userValidator.ts`: 必須・メール形式・パスワード強度・名前長
**API**:
- [ ] `POST /api/auth/register`(ユーザー登録)
- [ ] `POST /api/auth/login`ログイン・Set-Cookie
- [ ] `POST /api/auth/logout`(ログアウト)
- [ ] `GET /api/auth/me`(現在のユーザー)
- [ ] `PATCH /api/users/me`(プロフィール編集: 表示名・メール・アイコン画像)
- [ ] 全Route Handler に `export const runtime = 'nodejs'` 明示
- [ ] 認証ミドルウェア: 未ログイン時は保護画面をログイン画面へリダイレクト401
**画面**:
- [ ] `app/login/page.tsx`(ログイン画面)
- [ ] `app/profile/page.tsx`(ユーザープロフィール・アイコン画像設定・表示名設定)
- [ ] `app/layout.tsx`(ルートレイアウト)
### テスト
- [ ] **Unit Test**: `tests/unit/repositories/UserRepository.test.ts`CRUD・email一意・論理的確認
- [ ] **Unit Test**: `tests/unit/services/AuthService.test.ts`(登録・ログイン・ログアウト・プロフィール更新・無効アカウント拒否)
- [ ] **E2E Test**: `tests/e2e/auth.spec.ts`(ログイン・ログアウト・未ログインの保護画面アクセス拒否)
### 完了条件
- [ ] ユーザー登録・ログイン・ログアウトができる
- [ ] パスワードがハッシュ化保存される
- [ ] プロフィール・アイコン画像が編集できる
- [ ] 無効アカウントはログイン不可
- [ ] 未ログインで保護画面にアクセスできない
- [ ] Unit Test・E2E Test が成功する
---
## M4: プロジェクト管理・メンバー管理
**目的**: プロジェクトの作成・編集・削除・アーカイブと、メンバー追加・削除・ロール設定を実装する。プロジェクトダッシュボードの骨組みも作る。
**前提**: M3
### 実装タスク
**Repository**:
- [ ] `repositories/ProjectRepository.ts`: `findById``findByOwner``create``update``delete`
- [ ] `repositories/ProjectMemberRepository.ts`: `findByProject``findByUser``add``remove``isMember``getRole`
**Service**:
- [ ] `services/ProjectService.ts`: `createProject``updateProject``addMember``removeMember``archiveProject``getDashboard`
- [ ] 権限チェック: `isMember``getRole`非参加者は403・プロジェクト管理者権限チェック
- [ ] プロジェクトステータス管理active・on_hold・completed・archived
- [ ] メンバー追加時に通知M5のNotificationService連携
**バリデータ**:
- [ ] `lib/validators/projectValidator.ts`: プロジェクト名1-200文字・説明文
**API**:
- [ ] `GET /api/projects`(自分の参加プロジェクト一覧)
- [ ] `POST /api/projects`(プロジェクト作成)
- [ ] `GET /api/projects/:projectId`(プロジェクト詳細/ダッシュボード)
- [ ] `PATCH /api/projects/:projectId`(プロジェクト編集: 名前・説明・ステータス)
- [ ] `DELETE /api/projects/:projectId`(プロジェクト削除)
- [ ] `GET /api/projects/:projectId/members`(メンバー一覧)
- [ ] `POST /api/projects/:projectId/members`(メンバー追加)
- [ ] `DELETE /api/projects/:projectId/members/:userId`(メンバー削除)
**画面・コンポーネント**:
- [ ] `app/dashboard/page.tsx`(個人ダッシュボード骨組み: 参加プロジェクト一覧)
- [ ] `app/projects/[projectId]/page.tsx`(プロジェクト概要/ダッシュボード骨組み)
- [ ] `app/projects/[projectId]/members/page.tsx`(メンバー管理)
- [ ] `app/projects/[projectId]/settings/page.tsx`(プロジェクト設定)
- [ ] `components/layout/`Header・Sidebar・ProjectNav
- [ ] `components/project/`ProjectCard・DashboardWidget
### テスト
- [ ] **Unit Test**: `tests/unit/repositories/ProjectRepository.test.ts`
- [ ] **Unit Test**: `tests/unit/repositories/ProjectMemberRepository.test.ts`CRUD・UNIQUE制約・isMember・getRole
- [ ] **Unit Test**: `tests/unit/services/ProjectService.test.ts`(作成・編集・アーカイブ・メンバー追加/削除・権限チェック・プロジェクト分離)
- [ ] **Integration Test**: `tests/integration/project-member-permission.test.ts`(非参加者はプロジェクトデータにアクセス不可)
- [ ] **E2E Test**: `tests/e2e/project-management.spec.ts`(作成・編集・メンバー追加/削除・アーカイブ)
### 完了条件
- [ ] プロジェクト作成・編集・削除・アーカイブができる
- [ ] メンバー追加・削除・ロール設定ができる
- [ ] 非参加者はプロジェクト情報にアクセスできない403
- [ ] Unit・Integration・E2E Test が成功する
---
## M5: 通知・アクティビティログ基盤
**目的**: 通知生成とアクティビティログ記録の基盤Serviceを実装し、後続機能掲示板・チャット・ToDo等から利用可能にする。
**前提**: M4
### 実装タスク
**Repository**:
- [ ] `repositories/NotificationRepository.ts`: 通知作成・未読一覧(ページネーション)・既読化
- [ ] `repositories/ActivityLogRepository.ts`: ログ作成・プロジェクト別一覧(ページネーション)
**Service**:
- [ ] `services/NotificationService.ts`: `notifyOnEvent``resolveTargets`
- 対象イベント: mention・todo_assigned・todo_due_soon・meeting_invited・board_commented・project_added・file_shared・note_updated
- 対象ユーザー解決ロジック(メンション先・担当者・ミーティング参加者・掲示板投稿者・プロジェクトメンバー等)
- [ ] `services/ActivityLogService.ts`: `logActivity`
- 記録対象: todo_created・todo_updated・todo_completed・file_uploaded・board_posted・comment_added・note_created・note_updated・meeting_created・member_added・milestone_updated
- [ ] 管理者操作もアクティビティログに記録
**API**:
- [ ] `GET /api/notifications`(未読通知一覧)
- [ ] `POST /api/notifications/:id/read`(既読化)
- [ ] `GET /api/projects/:projectId/activity`(アクティビティログ一覧)
**画面・コンポーネント**:
- [ ] `app/notifications/page.tsx`(通知一覧画面)※共通画面
- [ ] `components/notifications/NotificationList.tsx``NotificationBadge.tsx`(ヘッダの未読バッジ)
- [ ] `app/projects/[projectId]/activity/page.tsx`(プロジェクト別アクティビティログ画面)
### テスト
- [ ] **Unit Test**: `tests/unit/repositories/NotificationRepository.test.ts`
- [ ] **Unit Test**: `tests/unit/repositories/ActivityLogRepository.test.ts`
- [ ] **Unit Test**: `tests/unit/services/NotificationService.test.ts`正しいユーザーへ通知作成・resolveTargets
- [ ] **Unit Test**: `tests/unit/services/ActivityLogService.test.ts`(ログ記録・プロジェクト分離)
### 完了条件
- [ ] 各イベント種別で通知が正しいユーザーに作成される
- [ ] 変更操作がアクティビティログに記録される
- [ ] 通知の既読化ができる
- [ ] Unit Test が成功する
---
## M6: 掲示板
**目的**: プロジェクト単位の非リアルタイム情報共有(スレッド・コメント・カテゴリ・ピン留め・重要マーク・既読・検索)を実装する。
**前提**: M5
### 実装タスク
**Repository**:
- [ ] `repositories/BoardRepository.ts`: スレッドCRUD・コメントCRUD・検索・ページネーション`deleted_at IS NULL` 必須)
**Service**:
- [ ] `services/BoardService.ts`: スレッド作成/編集/削除・コメント作成/編集/削除
- [ ] 権限チェック(プロジェクト参加者のみ)
- [ ] カテゴリ分類notice・spec・minutes・question・decision・trouble・memo
- [ ] ピン留め・重要マーク
- [ ] 既読管理
- [ ] コメント追加時に通知(`board_commented` → 投稿者)・アクティビティログ記録(`board_posted``comment_added`
**API**:
- [ ] `GET /api/projects/:projectId/board/threads`(一覧・ページネーション・検索)
- [ ] `POST /api/projects/:projectId/board/threads`(作成)
- [ ] `GET /api/projects/:projectId/board/threads/:threadId`(詳細)
- [ ] `PATCH /api/projects/:projectId/board/threads/:threadId`(編集)
- [ ] `DELETE /api/projects/:projectId/board/threads/:threadId`(削除)
- [ ] `POST /api/projects/:projectId/board/threads/:threadId/comments`(コメント作成)
- [ ] `PATCH /api/projects/:projectId/board/comments/:commentId`(コメント編集)
- [ ] `DELETE /api/projects/:projectId/board/comments/:commentId`(コメント削除)
**画面・コンポーネント**:
- [ ] `app/projects/[projectId]/board/page.tsx`(掲示板一覧)
- [ ] スレッド詳細・作成/編集フォーム
- [ ] `components/board/`ThreadList・ThreadForm・CommentList
- [ ] Markdown本文表示react-markdown + rehype-sanitize
### テスト
- [ ] **Unit Test**: `tests/unit/repositories/BoardRepository.test.ts`CRUD・論理削除非取得・プロジェクト分離・検索
- [ ] **Unit Test**: `tests/unit/services/BoardService.test.ts`(権限チェック・カテゴリ・ピン留め・通知・アクティビティログ)
- [ ] **E2E Test**: `tests/e2e/board.spec.ts`(スレッド作成・編集・コメント・検索)
### 完了条件
- [ ] スレッド・コメントのCRUDができる
- [ ] カテゴリ・ピン留め・重要マーク・既読・検索ができる
- [ ] 論理削除済みデータが通常取得に含まれない
- [ ] Unit・E2E Test が成功する
---
## M7: Markdownメモ
**目的**: プロジェクトごとのMarkdownメモ作成・編集・プレビュー・タグ・ピン留め・検索・添付・関連付けを実装する。
**前提**: M5
### 実装タスク
**Repository**:
- [ ] `repositories/ProjectNoteRepository.ts`: メモCRUD・検索・ピン留め`deleted_at IS NULL`・インデックス活用)
**Service**:
- [ ] `services/NoteService.ts`: メモ作成/編集/削除
- [ ] 権限チェック
- [ ] タイトル・タグ・ピン留め
- [ ] 作成者・最終更新者・更新日時管理
- [ ] ファイル添付・関連ToDo・関連ミーティング設定
- [ ] 更新時に通知(`note_updated`)・アクティビティログ(`note_created``note_updated`
**Markdownレンダリングセキュリティ**:
- [ ] react-markdown + remark-gfm + rehype-sanitize でプレビュー
- [ ] HTML直接入力無効化・危険URLスキーム`javascript:`等)除外
- [ ] 対応記法: 見出し・箇条書き・番号リスト・チェックリスト・コードブロック・テーブル・リンク・画像・引用
**API**:
- [ ] `GET /api/projects/:projectId/notes`(一覧・検索・ページネーション)
- [ ] `POST /api/projects/:projectId/notes`(作成)
- [ ] `GET /api/projects/:projectId/notes/:noteId`(詳細)
- [ ] `PATCH /api/projects/:projectId/notes/:noteId`(編集)
- [ ] `DELETE /api/projects/:projectId/notes/:noteId`(削除)
**画面・コンポーネント**:
- [ ] `app/projects/[projectId]/notes/page.tsx`(メモ一覧)
- [ ] メモエディタ・プレビュー画面
- [ ] `components/notes/`NoteEditor・MarkdownPreview
### テスト
- [ ] **Unit Test**: `tests/unit/repositories/ProjectNoteRepository.test.ts`CRUD・検索・ピン留め・論理削除・プロジェクト分離
- [ ] **Unit Test**: `tests/unit/services/NoteService.test.ts`(権限・タグ・ピン留め・関連付け・通知・アクティビティログ)
- [ ] **E2E Test**: `tests/e2e/markdown-notes.spec.ts`(作成・編集・プレビュー・ピン留め・検索・削除)
### 完了条件
- [ ] MarkdownメモのCRUD・プレビューができる
- [ ] タグ・ピン留め・検索ができる
- [ ] MarkdownがサニタイズされHTML直接入力が無効化される
- [ ] Unit・E2E Test が成功する
---
## M8: SSE基盤・チャット
**目的**: SSE配信基盤SseHubとプロジェクト別リアルタイムチャット送信・編集・削除・メンション・リアクション・既読/未読・検索)を実装する。
**前提**: M5
### 実装タスク
**SSE基盤**:
- [ ] `lib/sse/hub.ts`: `SseHub` クラス(`addClient``removeClient``broadcast`
- プロジェクト単位のクライアント集合管理
- 当該プロジェクトのみ配信(他プロジェクトへ漏れさせない)
- [ ] SSEエンドポイント: `GET /api/projects/:projectId/chat/stream`
- [ ] クライアント側の自動再接続対応
- [ ] SSEイベント種別: `chat.message.created``chat.message.updated``chat.message.deleted``todo.updated``file.uploaded``meeting.created``note.updated``notification.created`
**Repository**:
- [ ] `repositories/ChatRepository.ts`: メッセージCRUD・ページネーション・検索`deleted_at IS NULL`
**Service**:
- [ ] `services/ChatService.ts`: `sendMessage``editMessage``deleteMessage``getHistory`
- [ ] 権限チェック(プロジェクト参加者のみ)
- [ ] メンション検出 → 通知(`mention`
- [ ] SSE配信`chat.message.created/updated/deleted`
- [ ] リアクション・既読/未読・添付ファイル
**API**:
- [ ] `GET /api/projects/:projectId/chat/messages`(履歴・ページネーション・検索)
- [ ] `POST /api/projects/:projectId/chat/messages`(送信)
- [ ] `PATCH /api/projects/:projectId/chat/messages/:messageId`(編集)
- [ ] `DELETE /api/projects/:projectId/chat/messages/:messageId`(削除)
**画面・コンポーネント**:
- [ ] `app/projects/[projectId]/chat/page.tsx`(チャット画面)
- [ ] `components/chat/`ChatWindow・MessageInput・MessageList
### テスト
- [ ] **Unit Test**: `tests/unit/lib/sse/hub.test.ts`(クライアント管理・プロジェクト別配信・配信スコープ)
- [ ] **Unit Test**: `tests/unit/repositories/ChatRepository.test.ts`CRUD・検索・論理削除・プロジェクト分離
- [ ] **Unit Test**: `tests/unit/services/ChatService.test.ts`送信・編集・削除・メンション通知・SSE配信呼出・権限
- [ ] **Integration Test**: `tests/integration/chat-sse-broadcast.test.ts`送信→SSE配信
- [ ] **E2E Test**: `tests/e2e/chat-sse.spec.ts`送信・別コンテキストでSSEリアルタイム受信・編集・削除
### 完了条件
- [ ] メッセージ送信・編集・削除ができる
- [ ] SSEで別クライアントにリアルタイム配信される
- [ ] 接続切断時に自動再接続される
- [ ] メンション・リアクション・既読/未読・検索ができる
- [ ] Unit・Integration・E2E Test が成功する
---
## M9: ToDo / Kanban
**目的**: プロジェクトごとのタスクをKanban形式で管理するカラム・タスク・ドラッグ&ドロップ・担当者・期限・優先度・ラベル・チェックリスト・完了・マイルストーン紐づけ・カレンダー表示)。
**前提**: M8
### 実装タスク
**Repository**:
- [ ] `repositories/TodoRepository.ts`: カラムCRUD・タスクCRUD・並び替えorderIndex再計算・ページネーション`deleted_at IS NULL`
**Service**:
- [ ] `services/TodoService.ts`: カラム作成/編集/削除/並び替え・タスク作成/編集/削除/移動
- [ ] 権限チェック
- [ ] 担当者・期限・優先度low/normal/high・ラベル設定
- [ ] チェックリスト・コメント・添付ファイル
- [ ] 完了状態管理(`completedAt`
- [ ] マイルストーン紐づけ
- [ ] 担当者割り当て時に通知(`todo_assigned`)・アクティビティログ(`todo_created``todo_updated``todo_completed`
- [ ] SSE配信`todo.updated`
- [ ] 標準カラム初期生成: Backlog・To Do・In Progress・Review・Done
**API**:
- [ ] `GET /api/projects/:projectId/todos/columns`(カラム一覧)
- [ ] `POST /api/projects/:projectId/todos/columns`(カラム作成)
- [ ] `PATCH /api/projects/:projectId/todos/columns/:columnId`(カラム編集/並び替え)
- [ ] `DELETE /api/projects/:projectId/todos/columns/:columnId`(カラム削除)
- [ ] `GET /api/projects/:projectId/todos/items`(タスク一覧)
- [ ] `POST /api/projects/:projectId/todos/items`(タスク作成)
- [ ] `PATCH /api/projects/:projectId/todos/items/:itemId`(タスク編集/移動)
- [ ] `DELETE /api/projects/:projectId/todos/items/:itemId`(タスク削除)
**画面・コンポーネント**:
- [ ] `app/projects/[projectId]/todos/page.tsx`Kanbanボード
- [ ] `components/todo/`KanbanBoard・KanbanColumn・TodoCardドラッグ&ドロップ対応
### テスト
- [ ] **Unit Test**: `tests/unit/repositories/TodoRepository.test.ts`CRUD・並び替え・論理削除・プロジェクト分離
- [ ] **Unit Test**: `tests/unit/services/TodoService.test.ts`(作成・編集・移動・完了・担当者通知・アクティビティログ・権限)
- [ ] **E2E Test**: `tests/e2e/todo-kanban.spec.ts`(カラム作成・タスク作成・編集・別カラム移動・担当者/期限設定・完了)
### 完了条件
- [ ] Kanbanボードが表示される標準カラム5つ
- [ ] カラム・タスクのCRUD・ドラッグ&ドロップ移動ができる
- [ ] 担当者・期限・優先度・ラベル・チェックリスト・コメントが設定できる
- [ ] 完了タスクがDoneカラムに表示される
- [ ] Unit・E2E Test が成功する
---
## M10: ファイル共有・Lightbox
**目的**: プロジェクト内ファイルのアップロード・一覧・フォルダ管理・Lightbox閲覧・PDFプレビュー・紐づけを実装する。
**前提**: M4
### 実装タスク
**Repository**:
- [ ] `repositories/FileRepository.ts`: ファイルメタCRUD・フォルダ管理`deleted_at IS NULL`
**Service**:
- [ ] `services/FileStorageService.ts`: `upload``getDownloadStream``delete`
- ローカルFS保存: `data/uploads/<projectId>/<uuid>.<ext>`
- MIMEタイプチェック・ファイル名サニタイズ・保存名一意化
- ファイルアクセス権限チェック(プロジェクト参加者のみ)
- アクティビティログ(`file_uploaded`)・通知(`file_shared`・SSE配信`file.uploaded`
**ファイル紐づけ**:
- [ ] ファイルとToDo・掲示板投稿・ミーティング・Markdownメモの紐づけ
- [ ] ファイルコメント
**API**:
- [ ] `GET /api/projects/:projectId/files`(一覧・ページネーション)
- [ ] `POST /api/projects/:projectId/files`アップロード・multipart
- [ ] `GET /api/files/:fileId/download`(ダウンロード・権限チェック)
- [ ] `DELETE /api/files/:fileId`(削除)
**画面・コンポーネント**:
- [ ] `app/projects/[projectId]/files/page.tsx`(ファイル一覧)
- [ ] `components/files/`FileList・Uploader・Lightbox
- 画像Lightbox表示・PDFプレビュー
### テスト
- [ ] **Unit Test**: `tests/unit/repositories/FileRepository.test.ts`
- [ ] **Unit Test**: `tests/unit/services/FileStorageService.test.ts`アップロード・MIMEチェック・保存名一意化・権限・削除・アクティビティログ
- [ ] **E2E Test**: `tests/e2e/file-sharing.spec.ts`アップロード・一覧・Lightbox閲覧・PDFプレビュー・削除
### 完了条件
- [ ] ファイルアップロード・一覧・ダウンロード・削除ができる
- [ ] 画像をLightboxで閲覧できる・PDFをプレビューできる
- [ ] MIMEチェック・権限チェックが機能する
- [ ] ファイル紐づけ・コメントができる
- [ ] Unit・E2E Test が成功する
---
## M11: カレンダー・マイルストーン
**目的**: カレンダー(月/週/日/リスト表示・各種イベント表示・フィルターとマイルストーン管理CRUD・進捗率自動計算を実装する。
**前提**: M9
### 実装タスク
**Repository**:
- [ ] `repositories/CalendarRepository.ts`: イベントCRUD・期間検索`deleted_at IS NULL`
- [ ] `repositories/MilestoneRepository.ts`: マイルストーンCRUD・関連ToDo取得`deleted_at IS NULL`
**Service**:
- [ ] `services/ScheduleService.ts`: `getCalendarEvents`(期間・フィルター)
- 表示対象: マイルストーン・デッドライン・ToDo開始日・ToDo期限・ミーティング・任意イベント
- メンバー別フィルター・種別フィルター
- [ ] マイルストーン管理Service: 作成/編集/削除・期限・説明文・関連ToDo紐づけ
- [ ] **進捗率自動計算アルゴリズム**: 関連ToDoの完了率から0-100を算出
- [ ] 完了状態管理・カレンダー表示
- [ ] アクティビティログ(`milestone_updated`
**API**:
- [ ] `GET /api/projects/:projectId/calendar/events`(イベント一覧・期間・フィルタ)
- [ ] `POST /api/projects/:projectId/calendar/events`(イベント作成)
- [ ] `PATCH /api/projects/:projectId/calendar/events/:eventId`(編集)
- [ ] `DELETE /api/projects/:projectId/calendar/events/:eventId`(削除)
- [ ] `GET /api/projects/:projectId/milestones`(マイルストーン一覧)
- [ ] `POST /api/projects/:projectId/milestones`(作成)
- [ ] `PATCH /api/projects/:projectId/milestones/:id`(編集)
- [ ] `GET /api/projects/:projectId/milestones/:id/progress`(進捗率取得)
**画面・コンポーネント**:
- [ ] `app/projects/[projectId]/calendar/page.tsx`(カレンダー: 月/週/日/リスト表示)
- [ ] `app/projects/[projectId]/milestones/page.tsx`(マイルストーン一覧・進捗バー)
- [ ] `components/calendar/`CalendarView・EventBadge
### テスト
- [ ] **Unit Test**: `tests/unit/repositories/CalendarRepository.test.ts`
- [ ] **Unit Test**: `tests/unit/repositories/MilestoneRepository.test.ts`
- [ ] **Unit Test**: `tests/unit/services/ScheduleService.test.ts`(期間検索・フィルタ・種別別取得)
- [ ] **Unit Test**: 進捗率計算アルゴリズム(`calcMilestoneProgress`・ToDo0件時0%・完了率計算)
- [ ] **E2E Test**: `tests/e2e/calendar.spec.ts`ToDo期限・マイルストーン・ミーティング表示・イベント作成/編集)
### 完了条件
- [ ] 月/週/日/リスト表示ができる
- [ ] マイルストーン・デッドライン・ToDo期限・ミーティングが表示される
- [ ] イベントCRUD・フィルターができる
- [ ] マイルストーン進捗率が自動計算される
- [ ] Unit・E2E Test が成功する
---
## M12: ミーティング管理・スケジュール重複チェック
**目的**: ミーティングCRUD・参加メンバー設定・アジェンダ/議事録・関連付け・スケジュール重複判定を実装する。
**前提**: M11
### 実装タスク
**Repository**:
- [ ] `repositories/MeetingRepository.ts`: ミーティングCRUD・meeting_members管理`deleted_at IS NULL`
**Service**:
- [ ] `services/MeetingService.ts`: `createMeeting``updateMeeting``deleteMeeting``checkScheduleConflicts``updateMinutes`
- [ ] 権限チェック
- [ ] タイトル・説明・開始/終了日時・参加メンバー・場所・ミーティングURL設定
- [ ] アジェンダ・議事録Markdown
- [ ] 関連ToDo・関連ファイル・関連掲示板投稿・関連Markdownメモ設定
- [ ] カレンダー表示連携
- [ ] 参加者招待通知(`meeting_invited`)・アクティビティログ(`meeting_created`・SSE配信`meeting.created`
**スケジュール重複判定アルゴリズム**:
- [ ] `checkScheduleConflicts`: 選択メンバーの予定重複を検出
- 判定対象1: 他のミーティングmeeting_members経由・時間重複
- 判定対象2: カレンダーイベント(時間重複)
- 判定対象3: 期限の近い重要タスクpriority='high'・dueDate ±3日以内
- 時間重複判定: `NOT (existing.end <= new.start OR existing.start >= new.end)`
- 重複があれば警告返却(作成自体はブロックしない)
**API**:
- [ ] `GET /api/projects/:projectId/meetings`(一覧)
- [ ] `POST /api/projects/:projectId/meetings`作成・conflicts返却
- [ ] `PATCH /api/projects/:projectId/meetings/:id`(編集)
- [ ] `POST /api/projects/:projectId/meetings/check`(予定重複チェックのみ)
**画面・コンポーネント**:
- [ ] `app/projects/[projectId]/meetings/page.tsx`(ミーティング一覧)
- [ ] ミーティング作成フォーム・アジェンダ/議事録編集
- [ ] `components/meetings/`MeetingForm・ConflictWarning
### テスト
- [ ] **Unit Test**: `tests/unit/repositories/MeetingRepository.test.ts`CRUD・meeting_members・UNIQUE制約・論理削除・プロジェクト分離
- [ ] **Unit Test**: `tests/unit/services/MeetingService.test.ts`(作成・編集・議事録更新・参加者通知・アクティビティログ・権限)
- [ ] **Unit Test**: スケジュール重複判定アルゴリズム他ミーティング重複・カレンダーイベント重複・重要タスク検出・時間重複ロジック・excludeMeetingId
- [ ] **E2E Test**: `tests/e2e/meetings.spec.ts`(作成・参加メンバー設定・予定重複警告・アジェンダ/議事録・関連付け)
### 完了条件
- [ ] ミーティングCRUD・参加メンバー設定ができる
- [ ] アジェンダ・議事録が入力できる
- [ ] 関連付けToDo/ファイル/掲示板/メモ)ができる
- [ ] 参加メンバーの予定重複が画面上で警告される
- [ ] Unit・E2E Test が成功する
---
## M13: 検索・ダッシュボード完成
**目的**: プロジェクト内横断検索と、個人/プロジェクトダッシュボードの全項目表示を完成させる。
**前提**: M6-M12各データソース完成後
### 実装タスク
**横断検索**:
- [ ] 検索対象: 掲示板・チャット・ToDo・ファイル名・カレンダーイベント・ミーティング・議事録・マイルストーン・Markdownメモ
- [ ] 検索条件: キーワード・投稿者・担当者・日付・種別・プロジェクト・タグ
- [ ] API: `GET /api/projects/:projectId/search`
- [ ] 画面: 検索結果一覧
**個人ダッシュボード完成**:
- [ ] 自分の参加プロジェクト
- [ ] 自分の未完了ToDo
- [ ] 今日の予定
- [ ] 近日中のミーティング
- [ ] 未読通知
- [ ] 期限切れタスク
- [ ] 最近のアクティビティ
- [ ] `app/dashboard/page.tsx` 完成版
**プロジェクトダッシュボード完成**:
- [ ] プロジェクト概要
- [ ] 進行中ToDo
- [ ] 期限が近いToDo7日以内
- [ ] 最新チャット直近5件
- [ ] 最新掲示板ピン留め優先・直近5件
- [ ] 最新Markdownメモピン留め優先・直近5件
- [ ] 最近のファイル直近5件
- [ ] 次回ミーティング直近1件
- [ ] マイルストーン進捗(進捗バー付き)
- [ ] 最近のアクティビティ直近10件
- [ ] `app/projects/[projectId]/page.tsx` 完成版
### テスト
- [ ] **Unit Test**: 検索ロジック(各リソース横断検索・フィルタ絞り込み)
- [ ] **Unit Test**: ダッシュボード集計ロジック未完了ToDo・期限近いToDo・今日の予定等
- [ ] **E2E Test**: ダッシュボード表示確認(個人・プロジェクト各項目の表示)
### 完了条件
- [ ] 横断検索で全リソースが検索できる
- [ ] 検索フィルターが機能する
- [ ] 個人ダッシュボードの全項目が表示される
- [ ] プロジェクトダッシュボードの全項目が表示される
- [ ] Unit・E2E Test が成功する
---
## M14: バックアップ・管理者機能
**目的**: 管理者によるバックアップ作成DB+uploads ZIP化・一覧・ダウンロードとMigration状態確認画面を実装する。
**前提**: M2
### 実装タスク
**Service**:
- [ ] `services/BackupService.ts`: `createBackup``listBackups``downloadBackup`
- SQLite DBファイル + uploadsディレクトリをZIP化
- 保存先: `backups/backup-<timestamp>.zip`
- 管理者権限チェック(`role='system_admin'` のみ)
- 管理者操作をアクティビティログに記録
**API**:
- [ ] `GET /api/admin/backups`(バックアップ一覧・管理者のみ)
- [ ] `POST /api/admin/backups`(バックアップ作成・管理者のみ)
- [ ] `GET /api/admin/backups/:filename`(ダウンロード・管理者のみ)
- [ ] `GET /api/admin/migrations`Migration状態確認・管理者のみ※M2でAPI実装済なら画面連携
**画面**:
- [ ] `app/admin/backups/page.tsx`(管理者バックアップ画面: 作成・一覧・ダウンロード)
- [ ] Migration状態確認画面管理者
### テスト
- [ ] **Unit Test**: `tests/unit/services/BackupService.test.ts`バックアップ作成・ZIP化・一覧・ダウンロード・権限チェック
- [ ] **E2E Test**: `tests/e2e/backup.spec.ts`(作成・一覧表示・ダウンロード)
### 完了条件
- [ ] 管理者がバックアップを作成できる
- [ ] バックアップ一覧が表示される
- [ ] バックアップファイルをダウンロードできる
- [ ] 非管理者はアクセスできない403
- [ ] Migration状態が確認できる
- [ ] Unit・E2E Test が成功する
---
## M15: 全体テスト完成・品質担保
**目的**: 全マイルストールのテストを統合し、カバレッジ目標と成功条件/受け入れ要件を全項目クリアする。
**前提**: M1-M14
### 実装タスク
**Unit Test 完成**:
- [ ] SQLラッパー・Migration・全13Repository・全12Service のUnit Test 完成
- [ ] 権限チェック・バリデーション・スケジュール重複判定・通知作成ロジック・アクティビティログ作成ロジック・マイルストーン進捗計算 のUnit Test 完成
- [ ] Repository/Service層カバレッジ 80%以上
- [ ] `npm test` 全件成功
**統合テスト完成**:
- [ ] `tests/integration/auth-flow.test.ts`(登録→ログイン→保護画面アクセス)
- [ ] `tests/integration/project-member-permission.test.ts`(プロジェクト作成→メンバー追加→権限分離)
- [ ] `tests/integration/chat-sse-broadcast.test.ts`チャット送信→SSE配信
**E2E Test 完成**:
- [ ] 全12シナリオ完成: auth・project-management・board・chat-sse・todo-kanban・file-sharing・markdown-notes・calendar・meetings・notifications・activity-log・backup
- [ ] 主要フローカバレッジ 100%
- [ ] `npm run test:e2e` 全件成功
**品質ゲート**:
- [ ] `npm run lint` エラーなし
- [ ] `npm run typecheck` 成功
- [ ] `npm run build` 成功
**受け入れ要件確認**:
- [ ] PRD「成功条件/受け入れ要件」の全項目を確認ユーザーログイン〜バックアップ作成・Unit Test・E2E Test 全成功まで)
### 完了条件
- [ ] `npm test` でUnit Testが全件成功する
- [ ] `npm run test:e2e` でPlaywright E2E Testが全件成功する
- [ ] 統合テストが全件成功する
- [ ] Lint・型チェック・ビルドが成功する
- [ ] PRDの受け入れ要件を全項目クリアする
---
## 機能カバレッジマトリクス
PRDの機能要件16機能DB基盤テストがどのマイルストーンで実装されるかを示す。機能漏れがないことを保証する。
| 機能 | PRD優先度 | 実装MS | 完了確認MS | 備考 |
|------|----------|--------|-----------|------|
| DB基盤SQLラッパー・Migration・Repository基盤 | P0 | M2 | M2 | 全16テーブル+schema_migrations |
| ユーザー管理(登録・ログイン・プロフィール・ロール・有効/無効) | P0 | M3 | M3 | bcrypt・独自ログイン |
| プロジェクト管理(作成・編集・削除・アーカイブ・ステータス) | P0 | M4 | M4 | |
| プロジェクトメンバー管理(追加・削除・ロール) | P0 | M4 | M4 | |
| 通知アプリ内・未読一覧・既読化・8イベント | P0 | M5 | M5 | 基盤Service・各機能から連携 |
| アクティビティログ11操作記録・時系列表示 | P1 | M5 | M5 | 基盤Service・各機能から連携 |
| 掲示板(スレッド・コメント・カテゴリ・ピン留め・重要・既読・検索) | P0 | M6 | M6 | |
| MarkdownメモCRUD・プレビュー・タグ・ピン留め・検索・添付・関連付け | P0 | M7 | M7 | サニタイズ必須 |
| SSE基盤SseHub・プロジェクト別配信・自動再接続・8イベント | P0 | M8 | M8 | |
| チャット(送信・編集・削除・メンション・リアクション・既読/未読・検索) | P0 | M8 | M8 | SSEリアルタイム |
| ToDo / Kanbanカラム・タスク・D&D・担当・期限・優先度・ラベル・チェックリスト・完了・マイルストーン紐づけ | P0 | M9 | M9 | |
| ファイル共有アップロード・一覧・フォルダ・Lightbox・PDF・コメント・紐づけ・MIMEチェック | P0 | M10 | M10 | ローカルFS保存 |
| カレンダー(月/週/日/リスト・イベントCRUD・フィルタ | P0 | M11 | M11 | |
| マイルストーン管理CRUD・期限・関連ToDo・進捗率自動計算・完了 | P1 | M11 | M11 | |
| ミーティング管理CRUD・メンバー・アジェンダ/議事録・関連付け・カレンダー連携) | P0 | M12 | M12 | |
| スケジュール重複チェック(他ミーティング・カレンダーイベント・重要タスク) | P0 | M12 | M12 | 警告表示(ブロックしない) |
| 検索横断検索・7フィルタ条件 | P1 | M13 | M13 | 9リソース横断 |
| 個人ダッシュボード7項目 | P0 | M4(骨組み) | M13 | 全項目完成はM13 |
| プロジェクトダッシュボード9項目 | P0 | M4(骨組み) | M13 | 全項目完成はM13 |
| バックアップDB+uploads ZIP・一覧・ダウンロード・Migration状態確認 | P1 | M14 | M14 | 管理者のみ |
### Repository カバレッジ13クラス
| Repository | 実装MS | Unit Test MS |
|-----------|--------|-------------|
| UserRepository | M3 | M3 |
| ProjectRepository | M4 | M4 |
| ProjectMemberRepository | M4 | M4 |
| NotificationRepository | M5 | M5 |
| ActivityLogRepository | M5 | M5 |
| BoardRepository | M6 | M6 |
| ProjectNoteRepository | M7 | M7 |
| ChatRepository | M8 | M8 |
| TodoRepository | M9 | M9 |
| FileRepository | M10 | M10 |
| CalendarRepository | M11 | M11 |
| MilestoneRepository | M11 | M11 |
| MeetingRepository | M12 | M12 |
### Service カバレッジ12クラス
| Service | 実装MS | Unit Test MS |
|---------|--------|-------------|
| AuthService | M3 | M3 |
| ProjectService | M4 | M4 |
| NotificationService | M5 | M5 |
| ActivityLogService | M5 | M5 |
| BoardService | M6 | M6 |
| NoteService | M7 | M7 |
| ChatService | M8 | M8 |
| TodoService | M9 | M9 |
| FileStorageService | M10 | M10 |
| ScheduleService | M11 | M11 |
| (マイルストーン進捗計算) | M11 | M11 |
| MeetingService | M12 | M12 |
| (スケジュール重複判定) | M12 | M12 |
| BackupService | M14 | M14 |
### E2E Test カバレッジ12シナリオ
| E2Eシナリオ | 実装MS |
|------------|--------|
| auth.spec.ts | M3 |
| project-management.spec.ts | M4 |
| board.spec.ts | M6 |
| markdown-notes.spec.ts | M7 |
| chat-sse.spec.ts | M8 |
| todo-kanban.spec.ts | M9 |
| file-sharing.spec.ts | M10 |
| calendar.spec.ts | M11 |
| meetings.spec.ts | M12 |
| notifications.spec.ts | M5通知一覧/ 各MSイベント発生時 |
| activity-log.spec.ts | M5一覧/ 各MS記録時 |
| backup.spec.ts | M14 |
### 統合テスト カバレッジ3シナリオ
| 統合テスト | 実装MS |
|----------|--------|
| auth-flow.test.ts | M3 |
| project-member-permission.test.ts | M4 |
| chat-sse-broadcast.test.ts | M8 |
---
## フェーズ対応表
PRDの開発順序Phase 1〜5とマイルストーンの対応。
| フェーズ | 内容 | 対象マイルストーン |
|---------|------|------------------|
| Phase 1: 基盤 | Next.js・Tailwind・SQLite・SQLラッパー・Migration・Repository基盤・認証・ユーザー管理・プロジェクト管理・メンバー管理 | M1・M2・M3・M4 |
| Phase 2: プロジェクト内基本機能 | 通知・アクティビティログ・プロジェクトダッシュボード(骨組み)・掲示板・Markdownメモ | M5・M6・M7 |
| Phase 3: リアルタイム・タスク管理 | SSE基盤・チャット・メンション・既読/未読・ToDo/Kanban | M8・M9 |
| Phase 4: ファイル・カレンダー | ファイル共有・Lightbox・カレンダー・マイルストーン・デッドライン表示 | M10・M11 |
| Phase 5: ミーティング・バックアップ | ミーティング作成・メンバー設定・スケジュール重複チェック・議事録・ToDo連携・メモ連携・バックアップ | M12・M14 |
| (横断) | 検索・ダッシュボード完成 | M13 |
| (全体) | 全体テスト完成・品質担保 | M15 |
---
## テスト要件サマリー
`docs/development-guidelines.md` の「テスト実装の必須条件」に準拠し、各マイルストーンでテスト実装を必須とする。
### Unit TestVitest【必須】
- **対象**: SQLラッパー・Migration・全13Repository・全12Service・権限チェック・バリデーション・スケジュール重複判定・通知作成ロジック・アクティビティログ作成ロジック・マイルストーン進捗計算
- **合格基準**: `npm test` 全件成功・Repository/Service層カバレッジ80%以上・正常系/異常系網羅
- **最終確認**: M15
### 統合テストVitest【必須】
- **対象**: 認証フロー・プロジェクトメンバー権限・チャットSSE配信
- **最終確認**: M15
### E2E TestPlaywright【必須】
- **対象**: 認証・プロジェクト管理・掲示板・チャット(SSE)・ToDo(Kanban)・ファイル共有(Lightbox)・Markdownメモ・カレンダー・ミーティング(予定重複警告)・通知・アクティビティログ・バックアップ全12シナリオ
- **合格基準**: `npm run test:e2e` 全件成功・主要フロー100%
- **最終確認**: M15

View File

@ -0,0 +1,524 @@
# Product Requirements Document
## プロダクト概要
### 名前
**シンプルグループウェア** - プロジェクト単位で情報共有・タスク管理を行えるチームコラボレーションツール
### プロダクトコンセプト
- **プロジェクト中心の情報管理**: すべての主要機能掲示板・チャット・ToDo・ファイル・メモ・カレンダー・ミーティングがプロジェクトに紐づき、プロジェクトごとに独立して利用できる
- **軽量で扱いやすい技術構成**: Next.js 15 + TypeScript + SQLite(better-sqlite3) で構築し、Prisma を使わず独自SQLラッパーとRepositoryクラスでDBアクセスを実装する。小規模チームプロジェクトあたり数十人で運用できるシンプルさを追求する
- **リアルタイム性と一元管理の両立**: SSEによるリアルタイムチャットを備えつつ、カレンダーでマイルストーン・デッドライン・ToDo・ミーティングを一画面に集約し、チームの進捗を可視化する
### プロダクトビジョン
プロジェクトごとに独立した情報共有空間を提供し、チームが掲示板・チャット・タスク・ファイル・メモ・カレンダー・ミーティングを一つのアプリで完結できるグループウェアを実現する。
軽量なSQLiteベースの構成により、小規模チームでも簡単に導入・運用できる。
リアルタイムチャットとカレンダーによる一元管理で、情報散逸を防ぎ、チームの生産性を高める。
### 目的
- ユーザーを管理できる
- プロジェクトを作成・管理できる
- プロジェクトごとにメンバーを管理できる
- プロジェクトごとに掲示板を使える
- プロジェクトごとにSSEチャットを使える
- プロジェクトごとにKanban形式のToDoを使える
- プロジェクトごとにファイル共有を使える
- ファイルをLightboxで閲覧できる
- プロジェクトごとにMarkdownメモを作成・編集・閲覧できる
- プロジェクトごとにカレンダーを使える
- カレンダーでマイルストーン、デッドライン、ToDo、ミーティングを表示できる
- プロジェクトごとにミーティングを管理できる
- ミーティング作成時に参加メンバーの予定重複を確認できる
- アプリ内通知を使える
- アクティビティログを記録できる
- SQLiteのDBスキーマをSQL Migrationで更新できる
- 管理者がバックアップを作成できる
## ターゲットユーザー
### 主要ペルソナ: 佐藤 健太32歳、プロジェクトマネージャー
- 中小規模の開発チーム5〜30名で複数プロジェクトを並行管理している
- プロジェクトごとにメンバー構成が変わり、情報共有手段を都度切り替えるのに負担を感じている
- チャット・タスク管理・ファイル共有・ミーティング調整が別々のツールに分散しており、情報を行き来させるのに時間がかかっている
- 各メンバーの予定やタスク期限を一画面で把握し、ミーティングの重複を自動検知したい
- 軽量なツールを自社サーバー(またはローカル)で手軽に運用したい
### サブペルソナ: 山田 花子27歳、フロントエンドエンジニア / プロジェクトメンバー)
- 複数プロジェクトに所属し、それぞれのToDo期限やミーティング予定を見逃さずに把握したい
- Markdownでメモや議事録を書くことに慣れており、プレビュー付きの編集環境を求めている
- チャットでリアルタイムに相談しつつ、掲示板で非同期的に仕様や決定事項を残したい
## 成功指標KPI
### 主要KPI
- **主要ユーザーフローの動作確認**: 認証・プロジェクト作成・掲示板・SSEチャット・Kanban ToDo・ファイル共有・Markdownメモ・カレンダー・ミーティング・通知・アクティビティログ・バックアップのすべてが正常に動作するリリース時
- **Unit Test カバレッジ**: SQLラッパー・Migration・全Repository・全ServiceクラスのUnit Testが実装され、`npm test` で全件成功する(リリース時)
- **E2E Test 合格率**: Playwrightによる主要ユーザーフローのE2E Testが実装され、`npm run test:e2e` で全件成功する(リリース時)
### 副次KPI
- **リアルタイム性**: チャットメッセージ送信から他クライアントのSSE受信まで1秒以内小規模同時接続前提
- **一覧表示の応答性**: チャット履歴・掲示板・ファイル一覧・Markdownメモ一覧はページネーションされ、1ページあたりの取得が1秒以内
- **バックアップの可用性**: 管理者が1操作でSQLite DBファイルとuploadsディレクトリをZIP化したバックアップを作成・ダウンロードできる
## 機能要件
### コア機能MVP
#### 1. ユーザー管理
**ユーザーストーリー**:
システム管理者として、ユーザーの登録・ロール割り当て・有効/無効管理を行いたい。それはシステムへのアクセスを適切に制御するためである。
またユーザーとして、パスワードでログインし、自分のプロフィール・アイコン・表示名を編集したい。それは自分のアイデンティティをチーム内で正しく表現するためである。
**受け入れ基準**:
- [ ] ユーザー登録ができる(名前・メールアドレス・パスワード)
- [ ] パスワードログインができる
- [ ] ログアウトができる
- [ ] プロフィール編集(表示名・メールアドレス)ができる
- [ ] アイコン画像を設定できる
- [ ] アカウントを有効/無効にできる(無効アカウントはログイン不可)
- [ ] ロールSystem Admin / Project Admin / Member / Guestを管理できる
- [ ] 認証必須の画面で未ログイン時はログイン画面へリダイレクトされる
- [ ] ログインしていないユーザーは保護された画面にアクセスできない
**優先度**: P0必須
---
#### 2. プロジェクト管理
**ユーザーストーリー**:
プロジェクト管理者として、プロジェクトを作成し、メンバーを追加・削除し、プロジェクト内ロールを設定したい。それはプロジェクトごとに適切な権限でチームを運用するためである。
またプロジェクト管理者として、プロジェクトのステータスActive/On Hold/Completed/Archivedを管理し、不要になったプロジェクトをアーカイブ・削除したい。それはプロジェクトのライフサイクルを整理するためである。
**受け入れ基準**:
- [ ] プロジェクトを作成できる(名前・説明文)
- [ ] プロジェクト名・説明文を編集できる
- [ ] プロジェクトのステータスActive/On Hold/Completed/Archivedを変更できる
- [ ] プロジェクトにメンバーを追加できる
- [ ] プロジェクトからメンバーを削除できる
- [ ] プロジェクト内ロールを設定できる
- [ ] プロジェクトをアーカイブできる
- [ ] プロジェクトを削除できる
- [ ] プロジェクト参加者以外はプロジェクト情報にアクセスできない
- [ ] プロジェクトダッシュボードに以下が表示される:
- 最新チャット
- 最新掲示板投稿
- 最新Markdownメモ
- 未完了ToDo
- 期限が近いToDo
- 次回ミーティング
- 直近のマイルストーン
- 最近アップロードされたファイル
- 最近のアクティビティ
**優先度**: P0必須
---
#### 3. 掲示板
**ユーザーストーリー**:
プロジェクトメンバーとして、プロジェクト単位で非リアルタイムの情報共有(お知らせ・仕様・議事録・質問・決定事項・トラブル・メモ)をスレッド形式で行いたい。それは重要な情報を後から振り返れる形で残すためである。
**受け入れ基準**:
- [ ] スレッドを作成・編集・削除できるMarkdown本文
- [ ] スレッドにコメントを作成・編集・削除できる
- [ ] スレッドに添付ファイルを付けられる
- [ ] スレッドをピン留めできる
- [ ] スレッドに重要マークを付けられる
- [ ] カテゴリ(お知らせ/仕様/議事録/質問/決定事項/トラブル/メモ)で分類できる
- [ ] 既読管理ができる
- [ ] スレッドを検索できる
- [ ] 論理削除されたスレッド・コメントは通常取得に含まれない
**優先度**: P0必須
---
#### 4. チャットSSE
**ユーザーストーリー**:
プロジェクトメンバーとして、プロジェクト内でリアルタイムに短い会話をしたい。それは素早い相談ややり取りを円滑に行うためである。
**受け入れ基準**:
- [ ] プロジェクト別のチャットが使える
- [ ] メッセージを送信できる
- [ ] SSEにより新規メッセージがリアルタイムに他クライアントへ配信される別ブラウザ/別コンテキストで確認)
- [ ] 接続切断時に自動再接続される
- [ ] SSEイベントはプロジェクト単位で配信される
- [ ] メッセージを編集・削除できる
- [ ] メッセージに添付ファイルを付けられる
- [ ] メンションができる
- [ ] リアクションができる
- [ ] 既読/未読が管理できる
- [ ] チャット履歴を検索できる(ページネーション付き)
- [ ] SSEイベント種別: `chat.message.created` / `chat.message.updated` / `chat.message.deleted` / `todo.updated` / `file.uploaded` / `meeting.created` / `note.updated` / `notification.created` が配信される
**優先度**: P0必須
---
#### 5. ToDo / Kanban
**ユーザーストーリー**:
プロジェクトメンバーとして、プロジェクトごとのタスクをKanbanボード形式で管理したい。それはタスクの状態と担当を視覚的に把握するためである。
**受け入れ基準**:
- [ ] Kanbanボードが表示される標準カラム: Backlog/To Do/In Progress/Review/Done
- [ ] カラムを作成・編集・削除・並び替えできる
- [ ] タスクを作成・編集・削除できる
- [ ] タスクをドラッグ&ドロップで別カラムへ移動できる
- [ ] タスクに担当者・期限・優先度・ラベルを設定できる
- [ ] タスクにチェックリスト・コメント・添付ファイルを付けられる
- [ ] タスクの完了状態を管理できる
- [ ] 完了したToDoがDoneカラムに表示される
- [ ] タスクをカレンダーに表示できる
- [ ] タスクをマイルストーンと紐づけられる
**優先度**: P0必須
---
#### 6. ファイル共有
**ユーザーストーリー**:
プロジェクトメンバーとして、プロジェクト内でファイルをアップロード・閲覧・共有したい。それは資料や画像をチーム内で簡単に扱うためである。
**受け入れ基準**:
- [ ] ファイルをアップロードできる(ローカルファイルシステムに保存)
- [ ] ファイル一覧が表示される(ページネーション付き)
- [ ] フォルダ管理ができる
- [ ] ファイル名変更・削除・ダウンロードができる
- [ ] 画像ファイルをLightboxで閲覧できる
- [ ] PDFファイルをプレビューできる
- [ ] ファイルにコメントを付けられる
- [ ] ファイルをToDo・掲示板投稿・ミーティング・Markdownメモと紐づけられる
- [ ] ファイルアクセスにも権限チェックが行われる
- [ ] アップロードファイルのMIMEチェックが行われる
**優先度**: P0必須
---
#### 7. Markdownメモ
**ユーザーストーリー**:
プロジェクトメンバーとして、プロジェクトごとにMarkdown形式のメモを作成・編集・閲覧したい。それは仕様メモやウハウを構造化して蓄積するためである。
**受け入れ基準**:
- [ ] Markdownメモを作成・編集・削除できる
- [ ] Markdownプレビューが表示される
- [ ] タイトル・タグを設定できる
- [ ] メモをピン留めできる
- [ ] メモを検索できる
- [ ] 作成者・最終更新者・更新日時が表示される
- [ ] ファイル添付ができる
- [ ] 関連ToDo・関連ミーティングを設定できる
- [ ] 対応記法: 見出し・箇条書き・番号リスト・チェックリスト・コードブロック・テーブル・リンク・画像・引用
- [ ] HTML直接入力は無効化され、表示時にサニタイズされる
- [ ] 危険なURLスキームは除外される
**優先度**: P0必須
---
#### 8. カレンダー
**ユーザーストーリー**:
プロジェクトメンバーとして、プロジェクト内の予定・マイルストーン・ToDo期限・ミーティングをカレンダー上で確認したい。それはチームのスケジュールを一画面で把握するためである。
**受け入れ基準**:
- [ ] 月表示・週表示・日表示・リスト表示ができる
- [ ] マイルストーン・デッドライン・ToDo開始日・ToDo期限・ミーティング・任意イベントが表示される
- [ ] カレンダーイベントを作成・編集・削除できる
- [ ] イベント種別Meeting/Deadline/Milestone/Todo/Reminder/Customを設定できる
- [ ] メンバー別フィルターができる
- [ ] 種別フィルターができる
**優先度**: P0必須
---
#### 9. マイルストーン管理
**ユーザーストーリー**:
プロジェクト管理者として、プロジェクトの重要な節目(マイルストーン)を管理したい。それは進捗の目標を明確にし、完了率を可視化するためである。
**受け入れ基準**:
- [ ] マイルストーンを作成・編集・削除できる
- [ ] 期限・説明文を設定できる
- [ ] 関連ToDoを紐づけられる
- [ ] 関連ToDoの完了率から進捗率が自動計算される
- [ ] 完了状態を管理できる
- [ ] カレンダーに表示される
**優先度**: P1重要
---
#### 10. ミーティング管理
**ユーザーストーリー**:
プロジェクト管理者として、プロジェクトメンバーとのミーティングを設定し、参加者の予定重複を確認したい。それはスケジュールの競合を事前に防ぐためである。
**受け入れ基準**:
- [ ] ミーティングを作成・編集・削除できる
- [ ] タイトル・説明・開始日時・終了日時・参加メンバー・場所・ミーティングURLを設定できる
- [ ] アジェンダ・議事録をMarkdownで作成できる
- [ ] 関連ToDo・関連ファイル・関連掲示板投稿・関連Markdownメモを設定できる
- [ ] カレンダーに表示される
- [ ] ミーティング作成時に参加メンバーの予定重複をチェックし、同じ時間帯に他のミーティング・カレンダーイベント・期限の近い重要タスクがある場合は警告する
- [ ] 参加メンバーの予定重複が画面上で警告される
**優先度**: P0必須
---
#### 11. 通知
**ユーザーストーリー**:
ユーザーとして、自分に関係する重要な更新メンション・ToDo割り当て・期限前・ミーティング招待・コメント・プロジェクト追加・ファイル共有・メモ更新を見逃さないようにしたい。それは必要な対応を迅速に行うためである。
**受け入れ基準**:
- [ ] アプリ内通知が表示される
- [ ] 未読通知一覧が表示される
- [ ] 通知を既読化できる
- [ ] 以下のイベントで通知が作成される:
- 自分がメンションされた
- 自分にToDoが割り当てられた
- ToDoの期限が近い
- ミーティングに招待された
- 掲示板にコメントが付いた
- プロジェクトに追加された
- ファイルが共有された
- Markdownメモが更新された
- [ ] 通知が正しいユーザーに作成される
**優先度**: P0必須
---
#### 12. アクティビティログ
**ユーザーストーリー**:
プロジェクトメンバーとして、プロジェクト内の変更履歴を時系列で確認したい。それは誰がいつ何を変更したかを追跡するためである。
**受け入れ基準**:
- [ ] 以下の操作がアクティビティログに記録される:
- ToDo作成・更新・完了
- ファイルアップロード
- 掲示板投稿
- コメント追加
- Markdownメモ作成・更新
- ミーティング作成
- メンバー追加
- マイルストーン更新
- [ ] アクティビティログがプロジェクト単位で時系列表示される
- [ ] 管理者操作もアクティビティログに記録される
**優先度**: P1重要
---
#### 13. 検索
**ユーザーストーリー**:
プロジェクトメンバーとして、プロジェクト内の情報掲示板・チャット・ToDo・ファイル・カレンダーイベント・ミーティング・議事録・マイルストーン・Markdownメモを横断検索したい。それは目的の情報にすばやくたどり着くためである。
**受け入れ基準**:
- [ ] 掲示板・チャット・ToDo・ファイル名・カレンダーイベント・ミーティング・議事録・マイルストーン・Markdownメモを検索できる
- [ ] 検索条件(キーワード・投稿者・担当者・日付・種別・プロジェクト・タグ)で絞り込みできる
**優先度**: P1重要
---
#### 14. ダッシュボード
**ユーザーストーリー**:
ユーザーとして、ログイン後に自分に関係する情報を一画面で確認したい。それは今日やるべきことと近日の予定を把握するためである。
**受け入れ基準**:
- [ ] 個人ダッシュボードに以下が表示される:
- 自分の参加プロジェクト
- 自分の未完了ToDo
- 今日の予定
- 近日中のミーティング
- 未読通知
- 期限切れタスク
- 最近のアクティビティ
- [ ] プロジェクトダッシュボードに以下が表示される:
- プロジェクト概要
- 進行中ToDo
- 期限が近いToDo
- 最新チャット
- 最新掲示板
- 最新Markdownメモ
- 最近のファイル
- 次回ミーティング
- マイルストーン進捗
**優先度**: P0必須
---
#### 15. バックアップ
**ユーザーストーリー**:
システム管理者として、SQLite DBファイルとアップロードファイルをバックアップしたい。それはデータ喪失に備えるためである。
**受け入れ基準**:
- [ ] 管理者用バックアップ画面が使える
- [ ] SQLite DBファイルのバックアップを作成できる
- [ ] uploadsディレクトリのバックアップを作成できる
- [ ] DBとuploadsをZIP化できる
- [ ] バックアップファイル一覧が表示される
- [ ] バックアップファイルをダウンロードできる
**優先度**: P1重要
---
#### 16. DB基盤SQLラッパー・Migration・Repository
**ユーザーストーリー**:
開発者として、SQLiteへのアクセスを共通SQLラッパーで行い、SQLファイルベースのMigrationでスキーマを管理したい。それはDBアクセスを一貫させ、スキーマ変更を追跡可能にするためである。
**受け入れ基準**:
- [ ] 共通SQLラッパーSELECT複数行/SELECT単一行/INSERT・UPDATE・DELETE/トランザクション/初期設定/接続管理/エラー処理)が実装される
- [ ] 各Repositoryは直接SQLiteライブラリを触らず、共通SQLラッパーを通してSQLを実行する
- [ ] Migrationファイルがファイル名順に実行される
- [ ] 実行済みMigrationは再実行されない
- [ ] 実行済み履歴は `schema_migrations` テーブルに保存される
- [ ] 1ファイルごとにトランザクションが張られ、失敗時はロールバックされる
- [ ] 管理者がMigration状態を確認できる
- [ ] SQLはパラメータバインドで実行されるSQLインジェクション対策
**優先度**: P0必須
---
### 画面構成
#### 共通画面
- ログイン画面
- ダッシュボード
- 通知一覧
- ユーザープロフィール
- 管理者設定
- バックアップ管理
#### プロジェクト内画面
- プロジェクト概要
- 掲示板
- チャット
- ToDo / Kanban
- ファイル
- Markdownメモ
- カレンダー
- マイルストーン
- ミーティング
- メンバー
- アクティビティログ
- 設定
### 今後の機能Post-MVP
#### 外部連携・拡張
- 外部カレンダーGoogle Calendar等との同期
- メール通知・Webhook通知
- モバイル専用UIの最適化
**優先度**: P2今後検討
## 非機能要件
### パフォーマンス
- 1プロジェクトあたり数十人規模を想定する
- チャットSSEは小規模同時接続を前提とする
- ファイル一覧・チャット履歴・掲示板・Markdownメモはページネーションを行う
- 一覧取得では必要な件数だけ取得する
### ユーザビリティ
- ログイン後、ユーザーはダッシュボードで自分に関係する情報を一画面で確認できる
- プロジェクト内の主要機能はサイドメニューから1クリックで遷移できる
- Kanbanタスクはドラッグ&ドロップで直感的に操作できる
### 信頼性
- DB更新は1ファイルごとにトランザクションを張り、失敗時はロールバックする
- 管理者がSQLite DBファイルとuploadsディレクトリのバックアップを作成できる
- SQLite DBファイル・uploadsディレクトリは永続化される
### セキュリティ
- 認証必須(未ログインは保護された画面にアクセス不可)
- プロジェクト参加者以外はプロジェクト情報にアクセス不可
- ファイルアクセスにも権限チェックを行う
- SQLはパラメータバインドで実行する
- Markdown表示時はHTMLを無効化しサニタイズする
- 危険なURLスキームを除外する
- アップロードファイルのMIMEチェックを行う
- 管理者操作をアクティビティログに記録する
### スケーラビリティ
- Next.jsのEdge Runtimeは使用せず、API Route・Server Actions・DBアクセスはすべてNode.js Runtimeで実行するSQLite直接扱いのため
- SQLiteはWALモード・外部キー制約ONで運用する
### 運用・保守
- `.env` で設定管理できる
- SQLite DBファイルを永続化する
- uploadsディレクトリを永続化する
- 管理者がDB Migration状態を確認できる
- 管理者がバックアップを作成できる
## テスト要件
### Unit TestVitest
以下を対象とする:
- SQLラッパー
- Migration実行
- 全RepositoryUser/Project/ProjectMember/Board/Chat/Todo/File/Calendar/Meeting/ProjectNote/Notification/ActivityLog
- 全ServiceAuth/Project/Chat/Meeting/Schedule/FileStorage/Backup
- 権限チェック・バリデーション・スケジュール重複判定・通知作成ロジック・アクティビティログ作成ロジック
確認内容:
- 正常にデータを作成・取得・更新・削除できる
- 論理削除されたデータが通常取得に含まれない
- プロジェクト単位でデータが分離される
- 権限がないユーザーは操作できない
- 必須項目不足時にエラーになる
- Migrationがファイル名順に実行され、実行済みは再実行されない
- 予定重複を検出できる
- 通知が正しいユーザーに作成される
- アクティビティログが正しく記録される
`npm test` でUnit Testが実行できること。
### E2E TestPlaywright
主要ユーザーフローを実際のブラウザ操作で検証する:
- 認証(ログイン・ログアウト・未ログインの保護)
- プロジェクト管理(作成・編集・メンバー追加/削除・アーカイブ)
- 掲示板(スレッド作成・編集・コメント・検索)
- チャット送信・SSEリアルタイム受信・編集・削除
- ToDo/Kanbanカラム作成・タスク作成・編集・移動・担当者/期限設定・完了)
- ファイル共有アップロード・一覧・Lightbox閲覧・PDFプレビュー・削除
- Markdownメモ作成・編集・プレビュー・ピン留め・検索・削除
- カレンダーToDo期限・マイルストーン・ミーティング表示・イベント作成/編集)
- ミーティング(作成・参加メンバー設定・予定重複警告・アジェンダ/議事録・関連付け)
- 通知ToDo担当者・メンション・ミーティング参加者への通知・既読化
- アクティビティログToDo作成・ファイルアップロード・メモ更新・ミーティング作成の記録
- バックアップ(作成・一覧表示・ダウンロード)
`npm run test:e2e` でPlaywright E2E Testが実行できること。
Unit TestとE2E Testがすべて成功すること。
## スコープ外
明示的にスコープ外とする項目:
- Prisma等のORMは使用しない独自SQLラッパー + Repositoryクラスで実装
- Next.js Edge Runtimeは使用しないNode.js Runtimeのみ
- 外部カレンダーGoogle Calendar等との同期Post-MVP
- メール通知・Webhook通知Post-MVP
- モバイル専用UIの最適化Post-MVP
- 外部認証プロバイダOAuth/SSOは使用しない独自ログイン方式
- クラウドストレージへのファイル保存は行わない(ローカルファイルシステムのみ)

View File

@ -0,0 +1,506 @@
# リポジトリ構成定義書 (Repository Structure Document)
> 本書は `docs/architecture.md` で定義したレイヤードアーキテクチャを具体的なディレクトリ構成に落とし込んだものである。Next.js 15 App Router の規約に従い、`app/`・`lib/`・`repositories/`・`services/`・`components/` をルート直下に配置する。
## プロジェクト構成
```
repo/
├── app/ # UI層: Next.js App Router
│ ├── api/ # Route Handlers (REST/SSEエンドポイント)
│ ├── login/ # ログイン画面
│ ├── dashboard/ # 個人ダッシュボード
│ ├── projects/[projectId]/ # プロジェクト内画面群
│ ├── profile/ # ユーザープロフィール
│ ├── admin/ # 管理者画面(バックアップ等)
│ ├── layout.tsx # ルートレイアウト
│ └── globals.css # Tailwind エントリ
├── lib/ # Data層 + 共通基盤
│ ├── db/ # SQLite接続・Migration
│ ├── sse/ # SSE配信基盤
│ ├── auth/ # 認証・セッションヘルパ
│ ├── types/ # Entity型定義
│ └── validators/ # 入力バリデーション
├── repositories/ # Repository層
├── services/ # Service層
├── components/ # Reactコンポーネント
│ ├── layout/
│ ├── project/
│ ├── board/
│ ├── chat/
│ ├── todo/
│ ├── files/
│ ├── calendar/
│ ├── meetings/
│ ├── notes/
│ └── notifications/
├── tests/ # テストコード
│ ├── unit/
│ ├── integration/
│ └── e2e/
├── data/ # 永続化データgit管理外
│ ├── app.db
│ └── uploads/
├── backups/ # バックアップZIPgit管理外
├── docs/ # プロジェクトドキュメント
├── .steering/ # ワーク単位のステアリングファイル
├── .opencode/ # opencode設定
├── public/ # 静的アセット
└── 設定ファイル群package.json, tsconfig.json, next.config 等)
```
## ディレクトリ詳細
### app/ UI層
**役割**: Next.js App Router。画面表示・入力受付・認証・認可・Route Handler/SSEエンドポイント。
**配置ファイル**:
- `page.tsx`: 画面コンポーネントServer Components 中心)
- `route.ts`: Route HandlerREST API
- `layout.tsx`: レイアウト
- `loading.tsx` / `error.tsx`: ローディング・エラー状態
**命名規則**:
- ディレクトリはNext.js規約`[projectId]`等の動的セグメント含む)
- 画面ディレクトリは kebab-case`projects/[projectId]/board/`
**依存**:
- 依存可能: `services/`, `components/`, `lib/`
- 依存禁止: `repositories/`, `lib/db/` への直接アクセスService経由のみ
**構成例**:
```
app/
├── api/
│ ├── auth/
│ │ ├── login/route.ts
│ │ ├── logout/route.ts
│ │ └── me/route.ts
│ ├── projects/
│ │ ├── route.ts # 一覧・作成
│ │ └── [projectId]/
│ │ ├── route.ts # 詳細・編集・削除
│ │ ├── members/route.ts
│ │ ├── board/
│ │ ├── chat/
│ │ │ ├── messages/route.ts
│ │ │ └── stream/route.ts # SSEエンドポイント
│ │ ├── todos/
│ │ ├── files/
│ │ ├── notes/
│ │ ├── calendar/
│ │ ├── milestones/
│ │ └── meetings/
│ ├── files/[fileId]/download/route.ts
│ ├── notifications/route.ts
│ └── admin/
│ ├── backups/route.ts
│ └── migrations/route.ts
├── login/page.tsx
├── dashboard/page.tsx
├── projects/[projectId]/
│ ├── page.tsx # プロジェクト概要/ダッシュボード
│ ├── board/page.tsx
│ ├── chat/page.tsx
│ ├── todos/page.tsx
│ ├── files/page.tsx
│ ├── notes/page.tsx
│ ├── calendar/page.tsx
│ ├── milestones/page.tsx
│ ├── meetings/page.tsx
│ ├── members/page.tsx
│ ├── activity/page.tsx
│ └── settings/page.tsx
├── profile/page.tsx
└── admin/backups/page.tsx
```
**各 Route Handler の先頭に `export const runtime = 'nodejs'` を明示する**Edge Runtime使用禁止
### lib/ Data層 + 共通基盤)
#### lib/db/
**役割**: SQLite接続の共通管理・SQL実行・Migration。
**配置ファイル**:
- `sqlite.ts`: `SqliteDatabase` クラス・`getDb()` シングルトン
- `migrator.ts`: `Migrator` クラス
- `migrations/*.sql`: Migrationファイルファイル名順実行
**命名規則**: Migrationファイルは `001_initial.sql` 形式3桁連番 + 説明)
**依存**: better-sqlite3。Repository層からのみ利用される。
#### lib/sse/
**役割**: プロジェクト単位のSSEクライアント管理・イベント配信。
**配置ファイル**:
- `hub.ts`: `SseHub` クラスaddClient/removeClient/broadcast
**依存**: なしService層から呼び出される
#### lib/auth/
**役割**: セッション管理・認証ヘルパ・現在ユーザー取得。
**配置ファイル**:
- `session.ts`: セッション読み書き
- `getCurrentUser.ts`: リクエストから現在ユーザー解決
#### lib/types/
**役割**: Entity型定義・共有型。`functional-design.md` のデータモデルに対応。
**配置ファイル**: `User.ts`, `Project.ts`, `BoardThread.ts`, `ChatMessage.ts`, `TodoItem.ts`, `FileAsset.ts`, `ProjectNote.ts`, `Milestone.ts`, `CalendarEvent.ts`, `Meeting.ts`, `Notification.ts`, `ActivityLog.ts`
**命名規則**: PascalCaseEntity名
#### lib/validators/
**役割**: 入力バリデーション必須・長さ・形式。Service層から呼び出される。
**配置ファイル**: `projectValidator.ts`, `todoValidator.ts`, `meetingValidator.ts`
**命名規則**: camelCase + `Validator` 接尾
### repositories/ Repository層
**役割**: SQLの保持・パラメータバインド実行・論理削除フィルタ`deleted_at IS NULL`・プロジェクト分離の担保。直接SQLiteライブラリを触らず `lib/db/sqlite.ts` 経由。
**配置ファイル**: テーブルごとに1クラス。
```
repositories/
├── UserRepository.ts
├── ProjectRepository.ts
├── ProjectMemberRepository.ts
├── BoardRepository.ts
├── ChatRepository.ts
├── TodoRepository.ts
├── FileRepository.ts
├── CalendarRepository.ts
├── MeetingRepository.ts
├── ProjectNoteRepository.ts
├── NotificationRepository.ts
├── ActivityLogRepository.ts
└── MilestoneRepository.ts
```
**命名規則**: PascalCase + `Repository` 接尾
**依存**:
- 依存可能: `lib/db/sqlite.ts`, `lib/types/`
- 依存禁止: `services/`, `app/`, `lib/sse/`(業務ロジック・配信を持たない)
### services/ Service層
**役割**: 業務ロジック・権限チェック・トランザクション境界・副作用通知生成・アクティビティログ記録・SSE配信
**配置ファイル**:
```
services/
├── AuthService.ts
├── ProjectService.ts
├── ChatService.ts
├── MeetingService.ts
├── ScheduleService.ts
├── FileStorageService.ts
├── BackupService.ts
├── TodoService.ts
├── BoardService.ts
├── NoteService.ts
├── NotificationService.ts
└── ActivityLogService.ts
```
**命名規則**: PascalCase + `Service` 接尾
**依存**:
- 依存可能: `repositories/`, `lib/sse/`, `lib/validators/`, `lib/types/`, `lib/db/`(トランザクションのため)
- 依存禁止: `app/`UI層への依存
### components/ Reactコンポーネント
**役割**: 再利用可能なUIコンポーネント。機能領域ごとに分割。
**配置ファイル**: 機能ディレクトリ配下にコンポーネント。
```
components/
├── layout/ # Header, Sidebar, ProjectNav
├── project/ # ProjectCard, DashboardWidget
├── board/ # ThreadList, ThreadForm, CommentList
├── chat/ # ChatWindow, MessageInput, MessageList
├── todo/ # KanbanBoard, KanbanColumn, TodoCard
├── files/ # FileList, Uploader, Lightbox
├── calendar/ # CalendarView, EventBadge
├── meetings/ # MeetingForm, ConflictWarning
├── notes/ # NoteEditor, MarkdownPreview
└── notifications/ # NotificationList, NotificationBadge
```
**命名規則**: コンポーネントファイルは PascalCase`KanbanBoard.tsx`
**依存**: `app/` から利用される。`services/` 型・`lib/types/` を参照可能。直接 `repositories/` は触らない。
### tests/ (テストディレクトリ)
#### tests/unit/
**役割**: Unit TestVitest。本番コードと同じ構造をミラーする。
**構成**:
```
tests/unit/
├── lib/db/sqlite.test.ts
├── lib/db/migrator.test.ts
├── lib/sse/hub.test.ts
├── repositories/UserRepository.test.ts
├── repositories/ProjectRepository.test.ts
├── ...
└── services/ChatService.test.ts
```
**命名規則**: `[対象ファイル].test.ts`(対象と同名 + `.test`
#### tests/integration/
**役割**: 統合テスト。実際のSQLite一時ファイルを使用。
**構成**:
```
tests/integration/
├── auth-flow.test.ts
├── project-member-permission.test.ts
└── chat-sse-broadcast.test.ts
```
**命名規則**: `[シナリオ].test.ts`kebab-case
#### tests/e2e/
**役割**: E2E TestPlaywright。ユーザーシナリオごとに分割。
**構成**:
```
tests/e2e/
├── auth.spec.ts
├── project-management.spec.ts
├── board.spec.ts
├── chat-sse.spec.ts
├── todo-kanban.spec.ts
├── file-sharing.spec.ts
├── markdown-notes.spec.ts
├── calendar.spec.ts
├── meetings.spec.ts
├── notifications.spec.ts
├── activity-log.spec.ts
└── backup.spec.ts
```
**命名規則**: `[領域].spec.ts`
### data/ ・ backups/ (永続化データ)
**役割**: SQLite DBファイル・アップロードファイル・バックアップZIPの永続化先。git管理外。
```
data/
├── app.db # SQLite DBファイル
└── uploads/<projectId>/<uuid>.<ext>
backups/
└── backup-<timestamp>.zip
```
### docs/ (ドキュメント)
**配置ファイル**:
- `product-requirements.md`: PRD
- `functional-design.md`: 機能設計書
- `architecture.md`: アーキテクチャ設計書
- `repository-structure.md`: 本書
- `development-guidelines.md`: 開発ガイドライン
- `glossary.md`: 用語集
- `ideas/`: ブレインストーミング成果物
### .steering/ (ステアリングファイル)
**役割**: ワーク単位の要件・設計・タスクリスト。
**構成**:
```
.steering/[YYYYMMDD]-[task-name]/
├── requirements.md
├── design.md
└── tasklist.md
```
**命名規則**: `20250115-add-user-profile` 形式
### .opencode/ opencode設定
**役割**: opencode設定・カスタマイズ。
**構成**: `command/`, `skills/`, `agent/`
## ファイル配置ルール
### ソースファイル
| ファイル種別 | 配置先 | 命名規則 | 例 |
|------------|--------|---------|-----|
| Route Handler | `app/api/.../route.ts` | `route.ts`(固定) | `app/api/projects/route.ts` |
| 画面 | `app/.../page.tsx` | `page.tsx`(固定) | `app/dashboard/page.tsx` |
| Repository | `repositories/` | PascalCase + `Repository` | `UserRepository.ts` |
| Service | `services/` | PascalCase + `Service` | `ChatService.ts` |
| SQLラッパ | `lib/db/` | camelCase | `sqlite.ts` |
| Migration | `lib/db/migrations/` | `NNN_description.sql` | `001_initial.sql` |
| Entity型 | `lib/types/` | PascalCase | `TodoItem.ts` |
| バリデータ | `lib/validators/` | camelCase + `Validator` | `todoValidator.ts` |
| Reactコンポーネント | `components/<area>/` | PascalCase | `KanbanBoard.tsx` |
| ユーティリティ関数 | `lib/` 配下の適切な領域 | camelCase + 動詞始まり | `formatDate.ts` |
### テストファイル
| テスト種別 | 配置先 | 命名規則 | 例 |
|-----------|--------|---------|-----|
| Unit test | `tests/unit/` | `[対象].test.ts` | `ChatService.test.ts` |
| Integration test | `tests/integration/` | `[シナリオ].test.ts` | `chat-sse-broadcast.test.ts` |
| E2E test | `tests/e2e/` | `[領域].spec.ts` | `todo-kanban.spec.ts` |
### 設定ファイル
| ファイル種別 | 配置先 | 命名規則 |
|------------|--------|---------|
| ツール設定 | プロジェクトルート | `[tool].config.{js,ts,mjs}``next.config.mjs`, `vitest.config.ts`, `playwright.config.ts` |
| 環境変数 | プロジェクトルート | `.env`, `.env.example` |
| TypeScript設定 | プロジェクトルート | `tsconfig.json` |
## 命名規則
### ディレクトリ名
- **レイヤディレクトリ**: 複数形・kebab-case`repositories/`, `services/`, `components/`
- **機能ディレクトリ**: 単数形・kebab-case`board/`, `chat/`, `meetings/`※画面はNext.js規約に従う
- **汎用ディレクトリ名禁止**: `utils/`, `misc/`, `common/` は役割が曖昧になるため避ける
### ファイル名
- **クラスファイル**: PascalCase + 役割接尾(`UserRepository.ts`, `ChatService.ts`
- **関数ファイル**: camelCase + 動詞始まり(`formatDate.ts`, `validateEmail.ts`
- **型定義**: PascalCase`TodoItem.ts`
- **Route Handler/画面**: Next.js固定名`route.ts`, `page.tsx`, `layout.tsx`
## 依存規則
### レイヤ間の依存
```
app/ (UI層)
↓ (OK)
services/ (Service層)
↓ (OK)
repositories/ (Repository層)
↓ (OK)
lib/db/ (Data層)
```
**禁止依存**:
- `lib/db/``repositories/`/`services/`/`app/`(下位から上位へ ❌)
- `repositories/``services/`/`app/`(❌)
- `services/``app/`(❌)
- `app/``repositories/`/`lib/db/` の直接アクセス(層飛ばし ❌、Service経由のみ
- `repositories/` → better-sqlite3 直接(❌、`lib/db/sqlite.ts` 経由のみ)
```typescript
// ✅ 許容: UI → Service → Repository → Data
import { projectService } from '@/services/ProjectService';
// ProjectService内:
import { projectRepository } from '@/repositories/ProjectRepository';
// ProjectRepository内:
import { getDb } from '@/lib/db/sqlite';
// ❌ 禁止: Route HandlerがRepositoryを直接呼ぶ
import { projectRepository } from '@/repositories/ProjectRepository'; // app/api/... から ❌
```
### モジュール間の依存
**循環依存禁止**: Service間で循環依存が生じる場合は、共有型を `lib/types/` に抽出するか、共通機能を別Service例: `NotificationService`, `ActivityLogService`)に切り出す。
```typescript
// ❌ 循環依存
// services/TaskService.ts
import { UserService } from './UserService';
// services/UserService.ts
import { TaskService } from './TaskService';
// ✅ 解決: 共通副作用を別Serviceに切り出し
// services/NotificationService.ts ← 両方から利用
// services/ActivityLogService.ts ← 両方から利用
```
### パスエイリアス
`tsconfig.json``@/*` をプロジェクトルートにマッピングし、相対パスの深い `../../` を避ける。
```json
{ "compilerOptions": { "paths": { "@/*": ["./*"] } } }
```
## スケーリング戦略
### 機能追加時の配置方針
1. **小機能**: 既存ディレクトリに追加(例: 新しいRepository → `repositories/` に1ファイル
2. **中機能**: レイヤ内にサブディレクトリ作成(例: `services/meeting/` 配下に複数Service
3. **大機能**: 独立モジュール化を検討
### ファイルサイズ管理
- 1ファイル **300行以下** 推奨
- 300-500行: リファクタリング検討
- 500行超: 分割推奨(責務ごとに分割。例: `TaskService.ts``TaskService.ts` + `TaskValidationService.ts` + `TaskNotificationService.ts`
### モジュール分離のタイミング
以下の兆候があれば機能単位のモジュール化を検討:
- 1ディレクトリに10ファイル超
- 関連機能がグループ化されている
- 独立してテスト可能
- 他機能への依存が少ない
## 除外設定
### .gitignore
除外対象:
- `node_modules/`
- `.next/`
- `dist/`
- `coverage/`
- `data/`DB・uploads・一時データ
- `backups/`
- `.env`
- `.steering/`(タスク管理の一時ファイル)
- `*.log`
- `test-results/`, `playwright-report/`
- `.DS_Store`
### ツール除外
`.prettierignore`, `.eslintignore`:
- `dist/`, `node_modules/`, `.next/`, `coverage/`, `data/`, `backups/`
## チェックリスト
- [x] 各ディレクトリの役割が明確に定義されている
- [x] レイヤ構造がディレクトリに反映されている
- [x] 命名規則が一貫している
- [x] テストコードの配置方針が決まっている
- [x] 依存規則が明確である
- [x] 循環依存を避ける方針がある
- [x] スケーリング戦略が考慮されている
- [x] 共有コードの配置ルールが定義されている(`lib/types/`, `lib/validators/`
- [x] 設定ファイルの管理方法が決まっている
- [x] ドキュメントの配置が明確である

23
eslint.config.js Normal file
View File

@ -0,0 +1,23 @@
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import prettierConfig from 'eslint-config-prettier';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
prettierConfig,
{
rules: {
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_' },
],
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
},
},
{
ignores: ['node_modules/**', 'dist/**', '.steering/**'],
}
);

7
opencode.json Normal file
View File

@ -0,0 +1,7 @@
{
"$schema": "https://opencode.ai/config.json",
"instructions": [
"AGENTS.md"
],
"permission": "allow"
}

44
package.json Normal file
View File

@ -0,0 +1,44 @@
{
"name": "opencode-spec-driven-boilerplate",
"version": "0.1.0",
"description": "Spec-driven development boilerplate for opencode",
"type": "module",
"scripts": {
"prepare": "husky",
"build": "tsc",
"dev": "tsc --watch",
"lint": "eslint .",
"format": "npx prettier --write .",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"test:ui": "vitest --ui"
},
"keywords": [
"spec-driven-development",
"opencode",
"template"
],
"author": "",
"license": "MIT",
"devDependencies": {
"@types/node": "^20.11.0",
"@vitest/coverage-v8": "^2.0.0",
"@vitest/ui": "^2.0.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
"husky": "^9.0.0",
"lint-staged": "^15.2.0",
"prettier": "^3.2.0",
"typescript": "~5.3.0",
"typescript-eslint": "^8.0.0",
"vitest": "^2.0.0"
},
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix",
"prettier --write"
]
}
}

1
prompt.md Normal file
View File

@ -0,0 +1 @@
/add-feature Please develop the core feature (MVP) defined in the product requirements document.

93
src/example.test.ts Normal file
View File

@ -0,0 +1,93 @@
import { describe, it, expect } from 'vitest';
import { add, subtract, multiply, divide } from './example';
describe('Math operations', () => {
describe('add', () => {
it('正の数を足すと正しい結果が返る', () => {
// Given: 準備
const a = 2;
const b = 3;
// When: 実行
const result = add(a, b);
// Then: 検証
expect(result).toBe(5);
});
it('負の数を足すと正しい結果が返る', () => {
// Given: 準備
const a = -2;
const b = 3;
// When: 実行
const result = add(a, b);
// Then: 検証
expect(result).toBe(1);
});
});
describe('subtract', () => {
it('正の数を引くと正しい結果が返る', () => {
// Given: 準備
const a = 5;
const b = 3;
// When: 実行
const result = subtract(a, b);
// Then: 検証
expect(result).toBe(2);
});
});
describe('multiply', () => {
it('正の数をかけると正しい結果が返る', () => {
// Given: 準備
const a = 2;
const b = 3;
// When: 実行
const result = multiply(a, b);
// Then: 検証
expect(result).toBe(6);
});
it('0をかけると0が返る', () => {
// Given: 準備
const a = 5;
const b = 0;
// When: 実行
const result = multiply(a, b);
// Then: 検証
expect(result).toBe(0);
});
});
describe('divide', () => {
it('正の数で割ると正しい結果が返る', () => {
// Given: 準備
const a = 6;
const b = 3;
// When: 実行
const result = divide(a, b);
// Then: 検証
expect(result).toBe(2);
});
it('0で割るとエラーをスローする', () => {
// Given: 準備
const a = 5;
const b = 0;
// When/Then: 実行と検証
expect(() => divide(a, b)).toThrow('Division by zero is not allowed');
});
});
});

18
src/example.ts Normal file
View File

@ -0,0 +1,18 @@
export function add(a: number, b: number): number {
return a + b;
}
export function subtract(a: number, b: number): number {
return a - b;
}
export function multiply(a: number, b: number): number {
return a * b;
}
export function divide(a: number, b: number): number {
if (b === 0) {
throw new Error('Division by zero is not allowed');
}
return a / b;
}

22
tsconfig.json Normal file
View File

@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"lib": ["ES2022"],
"moduleResolution": "bundler",
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"types": ["vitest/globals"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

29
vitest.config.ts Normal file
View File

@ -0,0 +1,29 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'node',
include: [
'src/**/*.{test,spec}.{ts,tsx}',
'tests/**/*.{test,spec}.{ts,tsx}',
],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
exclude: [
'node_modules/**',
'dist/**',
'.steering/**',
'**/*.config.{ts,js}',
'**/types/**',
],
thresholds: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
},
});