diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..236594a --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,49 @@ + + + + +# issueURL + + + +# この PR で対応する範囲 / この PR で対応しない範囲 + + + +# 変更点概要 + + + +# レビュアーに重点的にチェックして欲しい点 + + + +# 補足情報 + + diff --git a/.github/mcp-servers.json b/.github/mcp-servers.json new file mode 100644 index 0000000..d39c47e --- /dev/null +++ b/.github/mcp-servers.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "lgtmeow": { + "type": "sse", + "url": "https://api.lgtmeow.com/sse" + } + } +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..442017b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: ci + +on: + workflow_dispatch: + push: + branches: + - "**" + +jobs: + build: + name: Build And Test + runs-on: ubuntu-latest + timeout-minutes: 5 + strategy: + matrix: + node-version: [24.x] + steps: + - uses: actions/checkout@v6 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v6 + with: + node-version: ${{ matrix.node-version }} + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Lint and Test + run: | + npm run lint + npm run build + npm run test:ci diff --git a/.gitignore b/.gitignore index 9a5aced..82376a7 100644 --- a/.gitignore +++ b/.gitignore @@ -78,9 +78,11 @@ web_modules/ .next out +# Build output +dist + # Nuxt.js build / generate output .nuxt -dist # Gatsby files .cache/ @@ -137,3 +139,6 @@ dist # Vite logs files vite.config.js.timestamp-* vite.config.ts.timestamp-* + +# MCP +.mcp.json diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..3787a26 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +legacy-peer-deps=true +save-exact=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..6e5aea8 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +.serena/ diff --git a/.serena/.gitignore b/.serena/.gitignore new file mode 100644 index 0000000..2e510af --- /dev/null +++ b/.serena/.gitignore @@ -0,0 +1,2 @@ +/cache +/project.local.yml diff --git a/.serena/project.yml b/.serena/project.yml new file mode 100644 index 0000000..2ac500f --- /dev/null +++ b/.serena/project.yml @@ -0,0 +1,151 @@ +# the name by which the project can be referenced within Serena +project_name: "planloop" + + +# list of languages for which language servers are started; choose from: +# al bash clojure cpp csharp +# csharp_omnisharp dart elixir elm erlang +# fortran fsharp go groovy haskell +# java julia kotlin lua markdown +# matlab nix pascal perl php +# php_phpactor powershell python python_jedi r +# rego ruby ruby_solargraph rust scala +# swift terraform toml typescript typescript_vts +# vue yaml zig +# (This list may be outdated. For the current list, see values of Language enum here: +# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py +# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.) +# Note: +# - For C, use cpp +# - For JavaScript, use typescript +# - For Free Pascal/Lazarus, use pascal +# Special requirements: +# Some languages require additional setup/installations. +# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers +# When using multiple languages, the first language server that supports a given file will be used for that file. +# The first language is the default language and the respective language server will be used as a fallback. +# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored. +languages: [] + +# the encoding used by text files in the project +# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings +encoding: "utf-8" + +# line ending convention to use when writing source files. +# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default) +# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings. +line_ending: + +# The language backend to use for this project. +# If not set, the global setting from serena_config.yml is used. +# Valid values: LSP, JetBrains +# Note: the backend is fixed at startup. If a project with a different backend +# is activated post-init, an error will be returned. +language_backend: + +# whether to use project's .gitignore files to ignore files +ignore_all_files_in_gitignore: true + +# advanced configuration option allowing to configure language server-specific options. +# Maps the language key to the options. +# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available. +# No documentation on options means no options are available. +ls_specific_settings: {} + +# list of additional paths to ignore in this project. +# Same syntax as gitignore, so you can use * and **. +# Note: global ignored_paths from serena_config.yml are also applied additively. +ignored_paths: [] + +# whether the project is in read-only mode +# If set to true, all editing tools will be disabled and attempts to use them will result in an error +# Added on 2025-04-18 +read_only: false + +# list of tool names to exclude. +# This extends the existing exclusions (e.g. from the global configuration) +# +# Below is the complete list of tools for convenience. +# To make sure you have the latest list of tools, and to view their descriptions, +# execute `uv run scripts/print_tool_overview.py`. +# +# * `activate_project`: Activates a project by name. +# * `check_onboarding_performed`: Checks whether project onboarding was already performed. +# * `create_text_file`: Creates/overwrites a file in the project directory. +# * `delete_lines`: Deletes a range of lines within a file. +# * `delete_memory`: Deletes a memory from Serena's project-specific memory store. +# * `execute_shell_command`: Executes a shell command. +# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced. +# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type). +# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). +# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. +# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file. +# * `initial_instructions`: Gets the initial instructions for the current project. +# Should only be used in settings where the system prompt cannot be set, +# e.g. in clients you have no control over, like Claude Desktop. +# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol. +# * `insert_at_line`: Inserts content at a given line in a file. +# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol. +# * `list_dir`: Lists files and directories in the given directory (optionally with recursion). +# * `list_memories`: Lists memories in Serena's project-specific memory store. +# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building). +# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context). +# * `read_file`: Reads a file within the project directory. +# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store. +# * `remove_project`: Removes a project from the Serena configuration. +# * `replace_lines`: Replaces a range of lines within a file with new content. +# * `replace_symbol_body`: Replaces the full definition of a symbol. +# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen. +# * `search_for_pattern`: Performs a search for a pattern in the project. +# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase. +# * `switch_modes`: Activates modes by providing a list of their names +# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information. +# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task. +# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed. +# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store. +excluded_tools: [] + +# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default). +# This extends the existing inclusions (e.g. from the global configuration). +included_optional_tools: [] + +# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools. +# This cannot be combined with non-empty excluded_tools or included_optional_tools. +fixed_tools: [] + +# list of mode names to that are always to be included in the set of active modes +# The full set of modes to be activated is base_modes + default_modes. +# If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply. +# Otherwise, this setting overrides the global configuration. +# Set this to [] to disable base modes for this project. +# Set this to a list of mode names to always include the respective modes for this project. +base_modes: + +# list of mode names that are to be activated by default. +# The full set of modes to be activated is base_modes + default_modes. +# If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply. +# Otherwise, this overrides the setting from the global configuration (serena_config.yml). +# This setting can, in turn, be overridden by CLI parameters (--mode). +default_modes: + +# initial prompt for the project. It will always be given to the LLM upon activating the project +# (contrary to the memories, which are loaded on demand). +initial_prompt: "" + +# time budget (seconds) per tool call for the retrieval of additional symbol information +# such as docstrings or parameter information. +# This overrides the corresponding setting in the global configuration; see the documentation there. +# If null or missing, use the setting from the global configuration. +symbol_info_budget: + +# list of regex patterns which, when matched, mark a memory entry as read‑only. +# Extends the list from the global configuration, merging the two lists. +read_only_memory_patterns: [] + +# list of regex patterns for memories to completely ignore. +# Matching memories will not appear in list_memories or activate_project output +# and cannot be accessed via read_memory or write_memory. +# To access ignored memory files, use the read_file tool on the raw file path. +# Extends the list from the global configuration, merging the two lists. +# Example: ["_archive/.*", "_episodes/.*"] +ignored_memory_patterns: [] diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d18f471 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,93 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +@nekochans/planloop is a Node.js CLI tool (installed via `npm install -g`) that reviews implementation plans created by AI coding agents using other AI agents to drive quality improvement loops. Written in TypeScript with ESM (`"type": "module"`). + +## Commands + +```bash +npm run build # TypeScript build (tsc) +npm test # Run all tests (vitest run) +npx vitest run src/path/to/file.test.ts # Run a single test file +npm run lint # Biome (ultracite) + Prettier check +npm run format # Biome (ultracite) + Prettier auto-fix +``` + +## Architecture + +- **Entry point**: `src/bin/planloop.ts` — CLI entry with shebang, mapped to `planloop` command via `bin` in package.json +- **Build output**: `dist/` (compiled from `src/` by tsc, git-ignored) +- **Module system**: ESM (Node16 module resolution) + +## Lint / Format Strategy + +- `.ts` files → ultracite (Biome) handles both linting and formatting +- `.yaml`, `.yml`, `.md`, `.mdx` → Prettier handles formatting +- Biome config extends `ultracite/biome/core` (see `biome.jsonc`) + +## Dependency Management + +- `.npmrc` enforces `save-exact=true` — all dependency versions must be pinned without `^` or `~` prefixes +- Use `npm install` (not yarn/pnpm) + +## 関連ドキュメント + +### **重要: 基本的なコーディングガイドライン** + +必ず以下のドキュメントを参照してから開発を開始してください: + +@docs/basic-coding-guidelines.md + +## 品質管理 + +全ての開発タスク完了時に、以下の手順を順番に実施してください。1つでも異常終了した場合は、問題点を修正してエラーが出なくなるまで修正を繰り返してください。 + +1. `npm run format` — Formatterの適用 +2. `npm run lint` — Linterエラーがないことを確認 +3. `npm run test` — テストコードの実行 +4. `npm run build` — ビルドが正常終了することを確認 + +## GitとGitHubワークフロールール + +### GitHubの利用ルール + +`gh` コマンドを利用してGitHubへのPRを作成する事が可能です。 + +許可されている操作は以下の通りです。 + +- GitHubへのPRの作成 +- GitHubへのPRへのコメントの追加 +- GitHub Issueの新規作成 +- GitHub Issueへのコメントの追加 + +**以下の操作はユーザーの許可があれば可能です。** + +- Gitへのコミット +- GitHubへのプッシュ + +### コミットメッセージの作成ルール + +- 対応issueがある場合は、コミットメッセージに `#` を記載します + +### PR作成ルール + +- ブランチはユーザーが作成しますので現在のブランチをそのまま利用します +- PRのタイトルは日本語で入力します +- PRの作成先は特別な指示がない場合は `main` ブランチになります +- PRの説明欄は @.github/PULL_REQUEST_TEMPLATE.md を参考に入力します +- 対応issueがある場合は、PRの説明欄に `#` を記載します +- Issue番号は現在のブランチ名から取得出来ます、例えば `feature/issue7/add-docs` の場合は `7` がIssue番号になります +- PRの説明欄には主に以下の情報を含めてください + +#### PRの説明欄に含めるべき情報 + +- 変更内容の詳細説明よりも、なぜその変更が必要なのかを重視 +- 他に影響を受ける機能やAPIエンドポイントがあれば明記 + +#### 以下の情報はPRの説明欄に記載する事を禁止する + +- 1つのissueで1つのPRとは限らないので `fix #issue番号` や `close #issue番号` のようなコメントは禁止します +- 全てのテストをパス、Linter、型チェックを通過などのコメント(テストやCIが通過しているのは当たり前でわざわざ書くべき事ではない) diff --git a/README.md b/README.md new file mode 100644 index 0000000..4673f04 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +# @nekochans/planloop + +AI コーディングエージェントが作成した実装計画を他の AI エージェントでレビューを行い、品質改善のループを回す為のツールです。 + +## 必須環境 + +- Node.js >= 22 + +## セットアップ + +```bash +npm install +``` + +## 開発コマンド + +```bash +# ビルド +npm run build + +# テスト +npm test + +# Lint (Biome + Prettier) +npm run lint + +# Format (Biome + Prettier) +npm run format +``` + +## Lint / Format の方針 + +- `.ts` ファイル → [ultracite](https://www.ultracite.ai/) (Biome) で lint & format +- `.yaml` `.yml` `.md` `.mdx` → [Prettier](https://prettier.io/) で format + +## ディレクトリ構成 + +``` +src/ + bin/ + planloop.ts # CLI エントリポイント +dist/ # ビルド出力 (git 管理外) +``` + +## ライセンス + +MIT diff --git a/biome.jsonc b/biome.jsonc new file mode 100644 index 0000000..a39804b --- /dev/null +++ b/biome.jsonc @@ -0,0 +1,4 @@ +{ + "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", + "extends": ["ultracite/biome/core"] +} diff --git a/docs/basic-coding-guidelines.md b/docs/basic-coding-guidelines.md new file mode 100644 index 0000000..589f1f2 --- /dev/null +++ b/docs/basic-coding-guidelines.md @@ -0,0 +1,126 @@ +# Basic Coding Guidelines(Provided by Ultracite) + +This project uses **Ultracite**, a zero-config preset that enforces strict code quality standards through automated formatting and linting. + +## Quick Reference + +- **Format code**: `npm exec -- ultracite fix` +- **Check for issues**: `npm exec -- ultracite check` +- **Diagnose setup**: `npm exec -- ultracite doctor` + +Biome (the underlying engine) provides robust linting and formatting. Most issues are automatically fixable. + +--- + +## Core Principles + +Write code that is **accessible, performant, type-safe, and maintainable**. Focus on clarity and explicit intent over brevity. + +### Type Safety & Explicitness + +- Use explicit types for function parameters and return values when they enhance clarity +- Prefer `unknown` over `any` when the type is genuinely unknown +- Use const assertions (`as const`) for immutable values and literal types +- Leverage TypeScript's type narrowing instead of type assertions +- Use meaningful variable names instead of magic numbers - extract constants with descriptive names + +### Modern JavaScript/TypeScript + +- Use arrow functions for callbacks and short functions +- Prefer `for...of` loops over `.forEach()` and indexed `for` loops +- Use optional chaining (`?.`) and nullish coalescing (`??`) for safer property access +- Prefer template literals over string concatenation +- Use destructuring for object and array assignments +- Use `const` by default, `let` only when reassignment is needed, never `var` + +### Async & Promises + +- Always `await` promises in async functions - don't forget to use the return value +- Use `async/await` syntax instead of promise chains for better readability +- Handle errors appropriately in async code with try-catch blocks +- Don't use async functions as Promise executors + +### React & JSX + +- Use function components over class components +- Call hooks at the top level only, never conditionally +- Specify all dependencies in hook dependency arrays correctly +- Use the `key` prop for elements in iterables (prefer unique IDs over array indices) +- Nest children between opening and closing tags instead of passing as props +- Don't define components inside other components +- Use semantic HTML and ARIA attributes for accessibility: + - Provide meaningful alt text for images + - Use proper heading hierarchy + - Add labels for form inputs + - Include keyboard event handlers alongside mouse events + - Use semantic elements (`