From ced279e2df1302d7348c7aad3d438be8b1474052 Mon Sep 17 00:00:00 2001 From: Ken Yasue Date: Wed, 24 Jun 2026 22:32:45 +0200 Subject: [PATCH] feat: initial commit - opencode spec-driven development boilerplate Converted from Claude Code boilerplate to opencode: - CLAUDE.md -> AGENTS.md (opencode instructions) - .claude/settings.json -> opencode.json (permissions schema) - .claude/agents/ -> .opencode/agent/ (subagents with mode: subagent) - .claude/commands/ -> .opencode/command/ (slash commands with ) - .claude/skills/ -> .opencode/skills/ (7 skills, removed allowed-tools) - DevContainer updated to install opencode - All .claude/ paths and Claude Code references updated --- .devcontainer/devcontainer.json | 11 + .gitignore | 46 ++ .husky/pre-commit | 2 + .opencode/agent/doc-reviewer.md | 240 +++++++ .opencode/agent/implementation-validator.md | 352 ++++++++++ .opencode/command/add-feature.md | 129 ++++ .opencode/command/review-docs.md | 64 ++ .opencode/command/setup-project.md | 112 ++++ .opencode/skills/architecture-design/SKILL.md | 50 ++ .opencode/skills/architecture-design/guide.md | 186 ++++++ .../skills/architecture-design/template.md | 153 +++++ .../skills/development-guidelines/SKILL.md | 107 +++ .../guides/implementation.md | 627 ++++++++++++++++++ .../development-guidelines/guides/process.md | 421 ++++++++++++ .../skills/development-guidelines/template.md | 410 ++++++++++++ .opencode/skills/functional-design/SKILL.md | 52 ++ .opencode/skills/functional-design/guide.md | 470 +++++++++++++ .../skills/functional-design/template.md | 262 ++++++++ .opencode/skills/glossary-creation/SKILL.md | 55 ++ .opencode/skills/glossary-creation/guide.md | 509 ++++++++++++++ .../skills/glossary-creation/template.md | 179 +++++ .opencode/skills/prd-writing/SKILL.md | 332 ++++++++++ .opencode/skills/prd-writing/template.md | 116 ++++ .../skills/repository-structure/SKILL.md | 51 ++ .../skills/repository-structure/guide.md | 400 +++++++++++ .../skills/repository-structure/template.md | 306 +++++++++ .opencode/skills/steering/SKILL.md | 383 +++++++++++ .opencode/skills/steering/templates/design.md | 96 +++ .../skills/steering/templates/requirements.md | 48 ++ .../skills/steering/templates/tasklist.md | 107 +++ .prettierignore | 14 + .prettierrc | 9 + .steering/.gitkeep | 0 AGENTS.md | 134 ++++ LICENSE | 21 + README.md | 399 +++++++++++ docs/ideas/initial-requirements.md | 336 ++++++++++ eslint.config.js | 23 + opencode.json | 20 + package.json | 44 ++ prompt.md | 1 + src/example.test.ts | 93 +++ src/example.ts | 18 + tsconfig.json | 22 + vitest.config.ts | 29 + 45 files changed, 7439 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .gitignore create mode 100644 .husky/pre-commit create mode 100644 .opencode/agent/doc-reviewer.md create mode 100644 .opencode/agent/implementation-validator.md create mode 100644 .opencode/command/add-feature.md create mode 100644 .opencode/command/review-docs.md create mode 100644 .opencode/command/setup-project.md create mode 100644 .opencode/skills/architecture-design/SKILL.md create mode 100644 .opencode/skills/architecture-design/guide.md create mode 100644 .opencode/skills/architecture-design/template.md create mode 100644 .opencode/skills/development-guidelines/SKILL.md create mode 100644 .opencode/skills/development-guidelines/guides/implementation.md create mode 100644 .opencode/skills/development-guidelines/guides/process.md create mode 100644 .opencode/skills/development-guidelines/template.md create mode 100644 .opencode/skills/functional-design/SKILL.md create mode 100644 .opencode/skills/functional-design/guide.md create mode 100644 .opencode/skills/functional-design/template.md create mode 100644 .opencode/skills/glossary-creation/SKILL.md create mode 100644 .opencode/skills/glossary-creation/guide.md create mode 100644 .opencode/skills/glossary-creation/template.md create mode 100644 .opencode/skills/prd-writing/SKILL.md create mode 100644 .opencode/skills/prd-writing/template.md create mode 100644 .opencode/skills/repository-structure/SKILL.md create mode 100644 .opencode/skills/repository-structure/guide.md create mode 100644 .opencode/skills/repository-structure/template.md create mode 100644 .opencode/skills/steering/SKILL.md create mode 100644 .opencode/skills/steering/templates/design.md create mode 100644 .opencode/skills/steering/templates/requirements.md create mode 100644 .opencode/skills/steering/templates/tasklist.md create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .steering/.gitkeep create mode 100644 AGENTS.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 docs/ideas/initial-requirements.md create mode 100644 eslint.config.js create mode 100644 opencode.json create mode 100644 package.json create mode 100644 prompt.md create mode 100644 src/example.test.ts create mode 100644 src/example.ts create mode 100644 tsconfig.json create mode 100644 vitest.config.ts diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..d8545dd --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -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" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fc158a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# Temporary files +tmp/ + +# Node.js +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +dist/ +build/ +*.tsbuildinfo + +# 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 diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..f3f510d --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +npx lint-staged +npm run typecheck diff --git a/.opencode/agent/doc-reviewer.md b/.opencode/agent/doc-reviewer.md new file mode 100644 index 0000000..6a890db --- /dev/null +++ b/.opencode/agent/doc-reviewer.md @@ -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 diff --git a/.opencode/agent/implementation-validator.md b/.opencode/agent/implementation-validator.md new file mode 100644 index 0000000..e354515 --- /dev/null +++ b/.opencode/agent/implementation-validator.md @@ -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 diff --git a/.opencode/command/add-feature.md b/.opencode/command/add-feature.md new file mode 100644 index 0000000..6a087ab --- /dev/null +++ b/.opencode/command/add-feature.md @@ -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. diff --git a/.opencode/command/review-docs.md b/.opencode/command/review-docs.md new file mode 100644 index 0000000..c51f984 --- /dev/null +++ b/.opencode/command/review-docs.md @@ -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. diff --git a/.opencode/command/setup-project.md b/.opencode/command/setup-project.md new file mode 100644 index 0000000..23e074d --- /dev/null +++ b/.opencode/command/setup-project.md @@ -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 +" +``` diff --git a/.opencode/skills/architecture-design/SKILL.md b/.opencode/skills/architecture-design/SKILL.md new file mode 100644 index 0000000..b88ba66 --- /dev/null +++ b/.opencode/skills/architecture-design/SKILL.md @@ -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 diff --git a/.opencode/skills/architecture-design/guide.md b/.opencode/skills/architecture-design/guide.md new file mode 100644 index 0000000..f48c276 --- /dev/null +++ b/.opencode/skills/architecture-design/guide.md @@ -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 { + 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 { + 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 { + 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 diff --git a/.opencode/skills/architecture-design/template.md b/.opencode/skills/architecture-design/template.md new file mode 100644 index 0000000..d7bb2de --- /dev/null +++ b/.opencode/skills/architecture-design/template.md @@ -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] | diff --git a/.opencode/skills/development-guidelines/SKILL.md b/.opencode/skills/development-guidelines/SKILL.md new file mode 100644 index 0000000..54b9ee6 --- /dev/null +++ b/.opencode/skills/development-guidelines/SKILL.md @@ -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 diff --git a/.opencode/skills/development-guidelines/guides/implementation.md b/.opencode/skills/development-guidelines/guides/implementation.md new file mode 100644 index 0000000..52c7fc9 --- /dev/null +++ b/.opencode/skills/development-guidelines/guides/implementation.md @@ -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 { + return items.reduce((acc, item) => { + acc[item] = (acc[item] || 0) + 1; + return acc; + }, {} as Record); +} + +// ❌ 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 | 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 { + 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 { + 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 { + 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 { + 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 { + const promises = ids.map(id => userRepository.findById(id)); + return Promise.all(promises); +} + +// ❌ Bad: Sequential execution +async function fetchMultipleUsers(ids: string[]): Promise { + 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 { + // 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(); + +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 diff --git a/.opencode/skills/development-guidelines/guides/process.md b/.opencode/skills/development-guidelines/guides/process.md new file mode 100644 index 0000000..d0bee6d --- /dev/null +++ b/.opencode/skills/development-guidelines/guides/process.md @@ -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**: + +``` +(): + + + +