diff --git a/.claude/skills/deep-review/SKILL.md b/.claude/skills/deep-review/SKILL.md index c2525f5b..28daa110 100644 --- a/.claude/skills/deep-review/SKILL.md +++ b/.claude/skills/deep-review/SKILL.md @@ -44,7 +44,7 @@ argument-hint: "[PR number, PR URL, or empty for local changes]" 使用 TeamCreate 创建审查团队,启动 **3 个并行 agent**,每个专注一个维度。 给每个 agent 的共同上下文: -- CLAUDE.md 的内容(项目架构、模式、技术栈) +- AGENTS.md 的内容(项目架构、模式、技术栈;其他仓库若没有该文件,读取 CLAUDE.md 及其导入内容) - 完整的 diff 内容 - 变更涉及的文件列表 @@ -69,7 +69,7 @@ argument-hint: "[PR number, PR URL, or empty for local changes]" ### Agent 3: 🏗️ 架构与质量审查 (architecture-reviewer) 检查项: -- 是否符合 CLAUDE.md 中描述的项目模式(ESM `.js` 后缀、单例模式、两阶段消息等) +- 是否符合 AGENTS.md 中描述的项目模式(ESM `.js` 后缀、单例模式、两阶段消息等) - TypeScript 类型安全(不安全的 `any`、错误的泛型、async/await 陷阱) - 模块边界是否清晰,是否有循环依赖 - 命名一致性、代码组织 diff --git a/.claude/skills/doc-health/SKILL.md b/.claude/skills/doc-health/SKILL.md index a9f46fcf..188cb3df 100644 --- a/.claude/skills/doc-health/SKILL.md +++ b/.claude/skills/doc-health/SKILL.md @@ -1,6 +1,6 @@ --- name: doc-health -description: "Set up or audit documentation health for any repo. Use 'init' to bootstrap a docs/ structure (plans/, design/, research/) with YAML front matter, agent discovery scripts, and anti-rot mechanisms. Use 'audit' to detect stale design docs, undistilled completed plans, broken internal links, and CLAUDE.md drift. Use when: 'set up docs', 'doc health', 'check documentation', 'audit docs', 'bootstrap documentation', 'prevent doc rot'." +description: "Set up or audit documentation health for any repo. Use 'init' to bootstrap a docs/ structure (plans/, design/, research/) with YAML front matter, agent discovery scripts, and anti-rot mechanisms. Use 'audit' to detect stale design docs, undistilled completed plans, broken internal links, and AGENTS.md drift. Use when: 'set up docs', 'doc health', 'check documentation', 'audit docs', 'bootstrap documentation', 'prevent doc rot'." argument-hint: "" --- @@ -26,7 +26,7 @@ Bootstrap a documentation structure. Idempotent — skips anything that already - Identify the main source directory: check `src/`, `lib/`, `app/`, or project root for code directories - List top-level module directories (e.g., `src/auth/`, `src/api/`, `src/utils/`) - Check which of these already exist: `docs/`, `docs/plans/`, `docs/design/`, `docs/research/` -- Check if `CLAUDE.md` exists and whether it already has a documentation section +- Check if `AGENTS.md` exists and whether it already has a documentation section - Check if `scripts/docs-list.mjs` exists - Note the current date for `last_updated` fields @@ -57,7 +57,7 @@ last_updated: "" > TODO: Describe current architecture and key design decisions when next modifying this module. ``` -**How to infer the summary**: Read the module's `index.ts` (or main file) exports, or check README/CLAUDE.md for mentions. If nothing is available, use the directory name as-is. +**How to infer the summary**: Read the module's `index.ts` (or main file) exports, or check README/AGENTS.md for mentions. If nothing is available, use the directory name as-is. ### Step 4: Create scripts/docs-list.mjs @@ -170,9 +170,11 @@ if (jsonOutput) { } ``` -### Step 5: Update CLAUDE.md +### Step 5: Update AGENTS.md -If CLAUDE.md does not exist, create it with a minimal project header and the documentation section below. If it exists but has no documentation section, **append** the section. If a documentation section already exists, **skip**. +If AGENTS.md does not exist, create it with a minimal project header and the documentation section below. If it exists but has no documentation section, **append** the section. If a documentation section already exists, **skip**. + +If a repository still keeps its guidance in `CLAUDE.md`, read that guidance first and preserve it when establishing `AGENTS.md` as the source of truth. Keep a `CLAUDE.md` containing `@AGENTS.md` when its Claude Code / Agent SDK consumers need compatibility. Never append project documentation to an import-only stub or maintain duplicate guidance in both files. Detect an existing section by searching for headings containing "Documentation", "Docs", or the Chinese equivalent. @@ -235,7 +237,7 @@ Doc Health Init Complete: [created] docs/design/api.md (stub) [skipped] docs/design/utils.md (already exists) [created] scripts/docs-list.mjs - [updated] CLAUDE.md (appended Documentation section) + [updated] AGENTS.md (appended Documentation section) Next steps: - Fill in design doc stubs when working on each module @@ -285,11 +287,11 @@ Scan all `.md` files in `docs/` for: - Code path references in backticks like `` `src/module/file.ts` `` — verify the file exists using Glob - Skip external URLs (http/https), anchors (#), and mailto links -### Check 5: CLAUDE.md Module Drift +### Check 5: AGENTS.md Module Drift -If CLAUDE.md exists and lists module descriptions (look for file paths like `src/*/`): +If AGENTS.md exists and lists module descriptions (look for file paths like `src/*/`): - Check that every listed path still exists on disk -- Check that major source directories have at least a mention in CLAUDE.md +- Check that major source directories have at least a mention in AGENTS.md - Report unlisted modules and phantom references ### Report @@ -311,16 +313,16 @@ Aggregate all findings into a structured report: ### Broken Internal Links (N found) - docs/design/X.md:15 — references `src/old/file.ts` which does not exist -### CLAUDE.md Drift (N found) -- CLAUDE.md mentions `src/routing/` but directory does not exist -- `src/cron/` exists but is not mentioned in CLAUDE.md +### AGENTS.md Drift (N found) +- AGENTS.md mentions `src/routing/` but directory does not exist +- `src/cron/` exists but is not mentioned in AGENTS.md ### Summary - N stale design docs - N undistilled plans - N stale plans - N broken links -- N CLAUDE.md drift issues +- N AGENTS.md drift issues ``` If everything is clean, output: "Doc health: all clear." diff --git a/.claude/skills/setup-claude/SKILL.md b/.claude/skills/setup-claude/SKILL.md index 39705419..5dcf2033 100644 --- a/.claude/skills/setup-claude/SKILL.md +++ b/.claude/skills/setup-claude/SKILL.md @@ -340,7 +340,7 @@ Use `gh pr diff` for the full diff, `gh pr view` for PR intent. Use TeamCreate to create a review team with **3 parallel agents**, each focused on one dimension. Shared context for all agents: -- Content of CLAUDE.md (if it exists — read it first and include it if present) +- Content of AGENTS.md (read it first if present; otherwise read CLAUDE.md and its imports) - Full diff content - List of changed files @@ -365,7 +365,7 @@ Checks: ### Agent 3: Architecture & Quality Reviewer (architecture-reviewer) Checks: -- If CLAUDE.md exists, verify changes follow the project patterns described there +- Verify changes follow the project patterns in AGENTS.md, or CLAUDE.md and its imports in legacy repositories - Check project conventions: consistent import style, module patterns, code organization - Language-specific: type safety, idiomatic patterns, proper use of language features - Clean module boundaries, no circular dependencies @@ -500,7 +500,7 @@ jobs: ## Step 2: Setup - 1. Read CLAUDE.md if it exists to understand the project architecture and conventions. + 1. Read AGENTS.md if it exists to understand the project architecture and conventions; otherwise read CLAUDE.md and its imports. 2. Run `gh pr view ${{ github.event.pull_request.number }}` to understand the PR intent. ## Step 3: Review Process @@ -513,7 +513,7 @@ jobs: ## What to Look For - **Bugs**: Logic errors, off-by-one, null/undefined access, race conditions, unhandled promise rejections - **Security**: Injection risks (command, SQL, XSS), secret exposure, unsafe permissions, missing input validation - - **Architecture**: Does the change follow patterns in CLAUDE.md (if it exists)? Are conventions consistent? + - **Architecture**: Does the change follow the project guidance read during setup? Are conventions consistent? - **Language-specific**: Type safety, idiomatic patterns, proper use of language features - **Resource leaks**: Unclosed connections, missing event listener cleanup, timer leaks @@ -604,7 +604,7 @@ jobs: REPO: ${{ github.repository }} You are a helpful AI assistant for this project. - Read CLAUDE.md if it exists to understand the project architecture and conventions. + Read AGENTS.md if it exists to understand the project architecture and conventions; otherwise read CLAUDE.md and its imports. When responding: 1. Always read the relevant source files to understand full context before answering. diff --git a/.claude/skills/ship/SKILL.md b/.claude/skills/ship/SKILL.md index 6e64d955..e3db8544 100644 --- a/.claude/skills/ship/SKILL.md +++ b/.claude/skills/ship/SKILL.md @@ -39,9 +39,11 @@ argument-hint: "[commit message or description of changes]" - 如果变更涉及某个 plan 的 `related_paths`,检查该 plan 的 `status` 和 `last_updated` 是否需要更新 - 如果 plan 的功能已全部实现,提醒用户将 status 改为 `completed` -#### 3c. CLAUDE.md 一致性 +#### 3c. AGENTS.md 一致性 -检查 `CLAUDE.md` 中引用的路径是否仍然有效,以及本次变更是否引入了 CLAUDE.md 应记录但未记录的内容(新目录、新工具、新工作流)。 +检查 `AGENTS.md` 中引用的路径是否仍然有效,以及本次变更是否引入了 AGENTS.md 应记录但未记录的内容(新目录、新工具、新工作流)。 + +其他仓库若仍以 `CLAUDE.md` 为规范来源,检查其正文及导入内容。本仓库的 `CLAUDE.md` 仅为兼容导入,规范更新应写入 `AGENTS.md`。 #### 3d. 用户指南检查 diff --git a/.github/workflows/claude-comment.yml b/.github/workflows/claude-comment.yml index 7b4b4695..692baf3e 100644 --- a/.github/workflows/claude-comment.yml +++ b/.github/workflows/claude-comment.yml @@ -70,7 +70,7 @@ jobs: REPO: ${{ github.repository }} You are a helpful AI assistant for this TypeScript/Node.js project. - Read CLAUDE.md first to understand the project architecture and conventions. + Read AGENTS.md first to understand the project architecture and conventions. When responding: 1. Always read the relevant source files to understand full context before answering. diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml index ee7495a7..759106a7 100644 --- a/.github/workflows/pr-review.yml +++ b/.github/workflows/pr-review.yml @@ -75,7 +75,7 @@ jobs: ## Step 2: Setup - 1. Read CLAUDE.md to understand the project architecture and conventions. + 1. Read AGENTS.md to understand the project architecture and conventions. 2. Run `gh pr view ${{ github.event.pull_request.number }}` to understand the PR intent. ## Step 3: Review Process @@ -88,7 +88,7 @@ jobs: ## What to Look For - **Bugs**: Logic errors, off-by-one, null/undefined access, race conditions, unhandled promise rejections - **Security**: Injection risks (command, SQL, XSS), secret exposure, unsafe permissions, missing input validation - - **Architecture**: Does the change follow patterns in CLAUDE.md? ESM imports with .js extensions? Proper singleton usage? + - **Architecture**: Does the change follow patterns in AGENTS.md? ESM imports with .js extensions? Proper singleton usage? - **TypeScript**: Unsafe `any` types, incorrect generics, missing error types, async/await pitfalls - **Resource leaks**: Unclosed connections, missing event listener cleanup, timer leaks diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..a3f5c10e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,168 @@ +# AGENTS.md + +This file is the source of truth for coding agents working in this repository. +Update project guidance here; `CLAUDE.md` is only a compatibility import. + +## Instruction Loading Compatibility + +- Claude Code 2.1.277+ can load `AGENTS.md` directly when no project or ancestor `CLAUDE.md` / `CLAUDE.local.md` takes precedence. Support also depends on the built-in `agents-md` plugin; gateway and telemetry-disabled sessions before 2.1.281 have additional limitations. +- Keep the root `CLAUDE.md` as the single line `@AGENTS.md`. This official import syntax loads the shared instructions for older or restricted sessions without maintaining a second copy. +- The locked Agent SDK 0.3.156 declares `claudeCodeVersion: 2.1.156`, below the direct-loading minimum. Both `claude-code-action@v1` workflows use a gateway and do not pin `claude_code_version`. A locally installed CLI version does not establish their compatibility. +- Preserve the executor's `settingSources` selection and caller overrides, including `[]`. These control filesystem settings as well as project instruction loading; renaming the source of guidance is not a reason to change permissions, settings, or skill discovery. +- CI prompts and documentation maintenance should read and update `AGENTS.md`. For other repositories, honor their existing `AGENTS.md` and `CLAUDE.md` conventions. + +References: [Claude Code instruction loading and imports](https://code.claude.com/docs/en/memory#agents-md), [2.1.277 release notes](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#21277). + +## Project Overview + +Anycode — a multi-agent development system with Feishu (Lark) as collaboration UI, powered by Anthropic's Claude Code via the Agent SDK. Users send messages in Feishu chats, and the server executes Claude Code queries against a working directory on the host machine. + +## Commands + +```bash +npm run dev # Start dev server with auto-reload (tsx watch) +npm run build # Compile TypeScript to dist/ +npm start # Run compiled JS from dist/ +npm run typecheck # Type-check without emitting +npm run lint # ESLint on src/ +``` + +```bash +npx vitest run # Run all tests (vitest) +``` + +## Architecture + +### Event Flow + +``` +Feishu User → Feishu Platform → Bridge Server → Claude Agent SDK → Claude Code subprocess + ↑ + Progress cards + result cards sent back to Feishu +``` + +### Key Modules + +- **`src/index.ts`** — Entry point: validates config, starts server, sets up 30-min cleanup interval and graceful shutdown (SIGINT/SIGTERM). +- **`src/config.ts`** — Environment-based configuration loader. Exports single config object with Feishu, Claude, workspace, memory, cron settings. +- **`src/server.ts`** — Express server with dual event mode: WebSocket (default, no public IP needed) or HTTP webhook. +- **`src/agent/`** — Multi-agent role system. `registry.ts` stores agent configs at runtime; `router.ts` routes messages to agents by chat binding rules; `config-loader.ts` loads agent configs from JSON (`config/agents.json`) with hot-reload. +- **`src/claude/executor.ts`** — Wraps `@anthropic-ai/claude-agent-sdk` `query()`. Streams SDKMessage, tracks cost/duration, supports session resumption and workspace restart with conversation trace forwarding. Budget: `CLAUDE_MAX_BUDGET_USD` (default $50), `CLAUDE_MAX_TURNS` (default 500). +- **`src/feishu/client.ts`** — Feishu API wrapper for sending/updating messages and cards. +- **`src/feishu/event-handler.ts`** — EventDispatcher: parse message → check allowlist → get/create session → enqueue task → execute → send result. +- **`src/feishu/message-builder.ts`** — Constructs interactive Feishu card messages for progress and results. +- **`src/feishu/thread-context.ts`** — Unified thread/workspace context resolution before execution. Defaults to `DEFAULT_WORK_DIR`; main agent uses `setup_workspace` MCP tool to switch repos during execution. +- **`src/feishu/bot-registry.ts`** — Tracks bot members in group chats; auto-discovers via events and message senders. +- **`src/feishu/tools/`** — MCP tool suite: `doc.ts`(文档), `wiki.ts`(知识库), `bitable.ts`(多维表格), `drive.ts`(云空间), `chat.ts`, `calendar.ts`, `contact.ts`, `task.ts`. Action-based dispatch with Zod schemas. +- **`src/workspace/manager.ts`** — Git clone + workspace isolation. Supports remote URL (via bare cache) and local path modes. +- **`src/workspace/cache.ts`** — Bare clone cache layer with atomic creation and configurable fetch interval. +- **`src/workspace/registry.ts`** — Repo registry system. Scans DEFAULT_WORK_DIR + .repo-cache, maintains JSON index (`.repo-registry.json`) with canonical URL keys, generates Markdown for LLM reading. Caches source repo paths for `isInsideSourceRepo()`. +- **`src/workspace/isolation.ts`** — Per-thread workspace isolation + source repo protection. `isInsideSourceRepo()` blocks writes to DEFAULT_WORK_DIR source repos via `canUseTool`. +- **`src/pipeline/orchestrator.ts`** — State-machine-driven dev pipeline (plan → plan_review → implement → code_review → push → pr_fixup). Max 2 retries per phase. +- **`src/pipeline/reviewer.ts`** — Parallel review with 3 agents (correctness/security/architecture) + optional Codex reviewer. +- **`src/session/manager.ts`** — SQLite-backed session store keyed by `agent:{agentId}:{chatId}:{userId}`. Thread-level sessions bind threadId → workdir/conversationId. +- **`src/session/database.ts`** — SQLite persistence with 13 migrations. Stores sessions, thread sessions, summaries, and OAuth tokens. +- **`src/session/queue.ts`** — Per-chat FIFO task queue ensuring one Claude query runs at a time per chat. +- **`src/memory/`** — Long-term memory system. `store.ts`(SQLite + sqlite-vec CRUD), `search.ts`(hybrid BM25 + vector), `extractor.ts`(LLM auto-extraction), `injector.ts`(prompt injection), `commands.ts`(/memory slash commands). +- **`src/cron/`** — Scheduled task system. `scheduler.ts`(cron/interval/at scheduling with retry), `store.ts`(SQLite persistence), `tool.ts`(MCP tool for agent interaction). +- **`src/platform/types.ts`** — Platform-agnostic message interfaces (MessagePort, InboundMessage). +- **`src/utils/security.ts`** — User allowlist check and dangerous command regex detection. +- **`src/utils/logger.ts`** — Pino logger singleton. + +### Key Patterns + +- **ESM throughout** — `"type": "module"` in package.json, ES2022 target, `.js` extensions in imports. +- **Singleton instances** — `sessionManager`, `claudeExecutor`, `taskQueue`, `feishuClient`, `logger` are module-level singletons. +- **Two-phase messaging** — Send a progress card first, then update it with the final result card. +- **Session isolation** — Each Feishu chat gets its own working directory and serialized task queue. + +### Agent SDK Gotchas + +- **`canUseTool` must return `updatedInput`** — `{ behavior: 'allow' }` alone causes SDK internal Zod validation failure. MCP tool handlers silently won't execute. Must return `{ behavior: 'allow', updatedInput: inputObj }`. +- **`bypassPermissions` fails under root** — Use `permissionMode: 'acceptEdits'` + `canUseTool` callback instead. +- **`settingSources` selects filesystem settings** — `'project'` loads `.claude/settings.json` and enables project instructions; `'local'` loads `.claude/settings.local.json`. Preserve caller overrides, especially `[]` for SDK isolation. In this repository, project instructions enter through the `CLAUDE.md` import of `AGENTS.md`. +- **Skills require `allowedTools: ['Skill']`** — SDK 默认不启用 Skill 工具。仅有 `settingSources: ['project']` 不够,还需在 `allowedTools` 中显式包含 `'Skill'`,否则 `.claude/skills/` 中的 SKILL.md 不会被加载。 +- **Feishu rich text breaks URLs** — `github.com:user/repo` gets auto-linked by Feishu as `[github.com:](http://github.com/)user/repo`. The `workspace/manager.ts` `normalizeRepoUrl()` handles SSH shorthand normalization. +- **`options.env` 完全替换子进程环境(SDK 0.3.x)** — 一旦传入 `env`,子进程**不再继承**父进程环境,必须自行展开:`{ ...process.env, ANTHROPIC_BASE_URL: ... }`。否则会丢失 `ANTHROPIC_API_KEY` / `PATH` / `HOME`,导致 Claude Code 返回 `Not logged in · Please run /login`。仅在配了代理 `ANTHROPIC_BASE_URL` 时才需要传 `env`(见 `claude/executor.ts`)。注意 0.2.x 是**合并**语义(`{...process.env, ...你的}`),升级到 0.3.x 时这是隐蔽的破坏性变更。 + +## Configuration + +### Agent Config (`config/`) + +Agent definitions, knowledge files, and persona prompts live in `config/` but are **not checked into git** (deployment-specific). Only `config/agents.example.json` is tracked as a structural reference. + +First-time setup: `cp config/agents.example.json config/agents.json` then customize. Without `config/agents.json`, the system falls back to a minimal built-in dev agent. + +### Environment Variables + +Loaded via dotenv (see `.env.example`): + +- **Required**: `FEISHU_APP_ID`, `FEISHU_APP_SECRET` +- **Claude**: `ANTHROPIC_API_KEY`, `DEFAULT_WORK_DIR` (default: parent of cwd), `CLAUDE_TIMEOUT` (default: 300s), `CLAUDE_MAX_TURNS` (default: 500), `CLAUDE_MAX_BUDGET_USD` (default: 50) +- **Workspace**: `REPO_CACHE_DIR` (bare clone cache), `WORKSPACE_BASE_DIR` (writable workspaces), `WORKSPACE_BRANCH_PREFIX` +- **Event mode**: `FEISHU_EVENT_MODE` (`websocket` | `webhook`), `FEISHU_ENCRYPT_KEY`, `FEISHU_VERIFY_TOKEN` (webhook only) +- **Memory**: `MEMORY_ENABLED`, `DASHSCOPE_API_KEY`, `MEMORY_DB_PATH` (default: `./data/memories.db`), `MEMORY_EMBEDDING_MODEL`, `MEMORY_VECTOR_WEIGHT` +- **Cron**: `CRON_DB_PATH` (default: `./data/cron.db`) +- **Security**: `ALLOWED_USER_IDS` (comma-separated, empty = allow all) +- **Server**: `PORT` (default: 3000), `NODE_ENV`, `LOG_LEVEL` + +## Testing Policy + +- **新功能必须附带单元测试** — 新增的模块/函数需要在 `tests/` 下有对应的 `.test.ts` 文件。每个 feat commit 必须伴随对应的 test commit。 +- **Bug fix 需附带回归测试** — 修复的 bug 应有测试用例覆盖,防止回归。 +- **复杂改动须通过完整回归** — 涉及多模块或核心逻辑的改动,提交前需运行 `npx vitest run` 确保全部测试通过。 +- **PR 不得降低测试覆盖率** — 新增代码应有合理的测试覆盖,不允许只加功能不加测试。 + +## Deployment + +- 部署方式取决于运行环境(PM2、systemd、Docker 等),服务启动时自动检测进程管理器类型(见 `src/utils/runtime.ts`)。 +- **升级/拉取后必须跑 `npm install`** — `@anthropic-ai/claude-agent-sdk` 0.3.x 起,Claude Code CLI 二进制改为通过 `optionalDependencies` 按平台分发(`@anthropic-ai/claude-agent-sdk-`,约 240MB)。只 `git pull` + 重新 `npm run build` + 拷 `dist/` **不会**拉到该二进制,服务会起不来。`npm install` 会按 OS/CPU/libc 自动选包(glibc/musl、x64/arm64 均有)。同理,`@anthropic-ai/sdk` 与 `@modelcontextprotocol/sdk` 在 0.3.x 是 peerDependencies,已提为本仓库的直接依赖。 +- **自重启须在对话最后一步执行** — Claude 是服务的子进程,使用 `sleep 5 && &` 脱离当前进程,避免 kill 自己的父进程导致对话中断。 + +## Tech Stack + +- TypeScript 5.7, Node.js 18+, Express 4 +- `@anthropic-ai/claude-agent-sdk` for Claude Code execution +- `@larksuiteoapi/node-sdk` for Feishu API + WebSocket events +- Pino for structured logging, Zod available for validation + +## 项目文档 + +文档按生命周期分三个目录: + +| 目录 | 内容 | 生命周期 | +|------|------|----------| +| `docs/plans/` | 活跃的实施计划 | 短期,完成后蒸馏关键决策到 `design/`,再删除 | +| `docs/design/` | 模块架构与设计决策(描述**现状**) | 长期保留,随代码持续更新 | +| `docs/research/` | 调研分析 | 只读参考 | + +### Agent 工作流 + +- **开始新任务前**,扫描 `docs/plans/*.md` 的 YAML front matter,读取 `summary` 和 `read_when` 字段,判断是否与当前任务相关。如果相关,先读完该计划再动手。 +- 也可以运行 `node scripts/docs-list.mjs` 快速查看所有活跃计划的列表(支持 `--status in_progress` 过滤和 `--json` 输出)。 +- **修改代码时**,检查 `docs/design/*.md` 的 `related_paths` 字段。如果当前修改涉及某文档的关联路径,阅读该文档,若描述与代码现状不符则一并更新(将提案口吻改写为现状描述)。 +- **Plan 完成时**,将关键设计决策和架构信息蒸馏到 `docs/design/` 对应文档,然后删除 plan 文件。 +- **新建计划文件**时,必须包含以下 front matter: + +```yaml +--- +summary: "一句话描述" +status: draft # draft | in_progress | completed +owner: git-id +last_updated: "YYYY-MM-DD" +read_when: + - 触发场景 1 + - 触发场景 2 +--- +``` + +- **Design 文档**也使用 front matter,格式: + +```yaml +--- +summary: "一句话描述" +related_paths: + - src/module/** +last_updated: "YYYY-MM-DD" +--- +``` diff --git a/CLAUDE.md b/CLAUDE.md index edca70b3..43c994c2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,157 +1 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -Anycode — a multi-agent development system with Feishu (Lark) as collaboration UI, powered by Anthropic's Claude Code via the Agent SDK. Users send messages in Feishu chats, and the server executes Claude Code queries against a working directory on the host machine. - -## Commands - -```bash -npm run dev # Start dev server with auto-reload (tsx watch) -npm run build # Compile TypeScript to dist/ -npm start # Run compiled JS from dist/ -npm run typecheck # Type-check without emitting -npm run lint # ESLint on src/ -``` - -```bash -npx vitest run # Run all tests (vitest) -``` - -## Architecture - -### Event Flow - -``` -Feishu User → Feishu Platform → Bridge Server → Claude Agent SDK → Claude Code subprocess - ↑ - Progress cards + result cards sent back to Feishu -``` - -### Key Modules - -- **`src/index.ts`** — Entry point: validates config, starts server, sets up 30-min cleanup interval and graceful shutdown (SIGINT/SIGTERM). -- **`src/config.ts`** — Environment-based configuration loader. Exports single config object with Feishu, Claude, workspace, memory, cron settings. -- **`src/server.ts`** — Express server with dual event mode: WebSocket (default, no public IP needed) or HTTP webhook. -- **`src/agent/`** — Multi-agent role system. `registry.ts` stores agent configs at runtime; `router.ts` routes messages to agents by chat binding rules; `config-loader.ts` loads agent configs from JSON (`config/agents.json`) with hot-reload. -- **`src/claude/executor.ts`** — Wraps `@anthropic-ai/claude-agent-sdk` `query()`. Streams SDKMessage, tracks cost/duration, supports session resumption and workspace restart with conversation trace forwarding. Budget: `CLAUDE_MAX_BUDGET_USD` (default $50), `CLAUDE_MAX_TURNS` (default 500). -- **`src/feishu/client.ts`** — Feishu API wrapper for sending/updating messages and cards. -- **`src/feishu/event-handler.ts`** — EventDispatcher: parse message → check allowlist → get/create session → enqueue task → execute → send result. -- **`src/feishu/message-builder.ts`** — Constructs interactive Feishu card messages for progress and results. -- **`src/feishu/thread-context.ts`** — Unified thread/workspace context resolution before execution. Defaults to `DEFAULT_WORK_DIR`; main agent uses `setup_workspace` MCP tool to switch repos during execution. -- **`src/feishu/bot-registry.ts`** — Tracks bot members in group chats; auto-discovers via events and message senders. -- **`src/feishu/tools/`** — MCP tool suite: `doc.ts`(文档), `wiki.ts`(知识库), `bitable.ts`(多维表格), `drive.ts`(云空间), `chat.ts`, `calendar.ts`, `contact.ts`, `task.ts`. Action-based dispatch with Zod schemas. -- **`src/workspace/manager.ts`** — Git clone + workspace isolation. Supports remote URL (via bare cache) and local path modes. -- **`src/workspace/cache.ts`** — Bare clone cache layer with atomic creation and configurable fetch interval. -- **`src/workspace/registry.ts`** — Repo registry system. Scans DEFAULT_WORK_DIR + .repo-cache, maintains JSON index (`.repo-registry.json`) with canonical URL keys, generates Markdown for LLM reading. Caches source repo paths for `isInsideSourceRepo()`. -- **`src/workspace/isolation.ts`** — Per-thread workspace isolation + source repo protection. `isInsideSourceRepo()` blocks writes to DEFAULT_WORK_DIR source repos via `canUseTool`. -- **`src/pipeline/orchestrator.ts`** — State-machine-driven dev pipeline (plan → plan_review → implement → code_review → push → pr_fixup). Max 2 retries per phase. -- **`src/pipeline/reviewer.ts`** — Parallel review with 3 agents (correctness/security/architecture) + optional Codex reviewer. -- **`src/session/manager.ts`** — SQLite-backed session store keyed by `agent:{agentId}:{chatId}:{userId}`. Thread-level sessions bind threadId → workdir/conversationId. -- **`src/session/database.ts`** — SQLite persistence with 13 migrations. Stores sessions, thread sessions, summaries, and OAuth tokens. -- **`src/session/queue.ts`** — Per-chat FIFO task queue ensuring one Claude query runs at a time per chat. -- **`src/memory/`** — Long-term memory system. `store.ts`(SQLite + sqlite-vec CRUD), `search.ts`(hybrid BM25 + vector), `extractor.ts`(LLM auto-extraction), `injector.ts`(prompt injection), `commands.ts`(/memory slash commands). -- **`src/cron/`** — Scheduled task system. `scheduler.ts`(cron/interval/at scheduling with retry), `store.ts`(SQLite persistence), `tool.ts`(MCP tool for agent interaction). -- **`src/platform/types.ts`** — Platform-agnostic message interfaces (MessagePort, InboundMessage). -- **`src/utils/security.ts`** — User allowlist check and dangerous command regex detection. -- **`src/utils/logger.ts`** — Pino logger singleton. - -### Key Patterns - -- **ESM throughout** — `"type": "module"` in package.json, ES2022 target, `.js` extensions in imports. -- **Singleton instances** — `sessionManager`, `claudeExecutor`, `taskQueue`, `feishuClient`, `logger` are module-level singletons. -- **Two-phase messaging** — Send a progress card first, then update it with the final result card. -- **Session isolation** — Each Feishu chat gets its own working directory and serialized task queue. - -### Agent SDK Gotchas - -- **`canUseTool` must return `updatedInput`** — `{ behavior: 'allow' }` alone causes SDK internal Zod validation failure. MCP tool handlers silently won't execute. Must return `{ behavior: 'allow', updatedInput: inputObj }`. -- **`bypassPermissions` fails under root** — Use `permissionMode: 'acceptEdits'` + `canUseTool` callback instead. -- **`settingSources: ['project']`** loads `.claude/settings.local.json` from cwd, including `permissions.allow` whitelist. This whitelist is checked *before* `canUseTool`, so unlisted tools (including MCP) get blocked. Currently `canUseTool` with proper `updatedInput` overrides this. -- **Skills require `allowedTools: ['Skill']`** — SDK 默认不启用 Skill 工具。仅有 `settingSources: ['project']` 不够,还需在 `allowedTools` 中显式包含 `'Skill'`,否则 `.claude/skills/` 中的 SKILL.md 不会被加载。 -- **Feishu rich text breaks URLs** — `github.com:user/repo` gets auto-linked by Feishu as `[github.com:](http://github.com/)user/repo`. The `workspace/manager.ts` `normalizeRepoUrl()` handles SSH shorthand normalization. -- **`options.env` 完全替换子进程环境(SDK 0.3.x)** — 一旦传入 `env`,子进程**不再继承**父进程环境,必须自行展开:`{ ...process.env, ANTHROPIC_BASE_URL: ... }`。否则会丢失 `ANTHROPIC_API_KEY` / `PATH` / `HOME`,导致 Claude Code 返回 `Not logged in · Please run /login`。仅在配了代理 `ANTHROPIC_BASE_URL` 时才需要传 `env`(见 `claude/executor.ts`)。注意 0.2.x 是**合并**语义(`{...process.env, ...你的}`),升级到 0.3.x 时这是隐蔽的破坏性变更。 - -## Configuration - -### Agent Config (`config/`) - -Agent definitions, knowledge files, and persona prompts live in `config/` but are **not checked into git** (deployment-specific). Only `config/agents.example.json` is tracked as a structural reference. - -First-time setup: `cp config/agents.example.json config/agents.json` then customize. Without `config/agents.json`, the system falls back to a minimal built-in dev agent. - -### Environment Variables - -Loaded via dotenv (see `.env.example`): - -- **Required**: `FEISHU_APP_ID`, `FEISHU_APP_SECRET` -- **Claude**: `ANTHROPIC_API_KEY`, `DEFAULT_WORK_DIR` (default: parent of cwd), `CLAUDE_TIMEOUT` (default: 300s), `CLAUDE_MAX_TURNS` (default: 500), `CLAUDE_MAX_BUDGET_USD` (default: 50) -- **Workspace**: `REPO_CACHE_DIR` (bare clone cache), `WORKSPACE_BASE_DIR` (writable workspaces), `WORKSPACE_BRANCH_PREFIX` -- **Event mode**: `FEISHU_EVENT_MODE` (`websocket` | `webhook`), `FEISHU_ENCRYPT_KEY`, `FEISHU_VERIFY_TOKEN` (webhook only) -- **Memory**: `MEMORY_ENABLED`, `DASHSCOPE_API_KEY`, `MEMORY_DB_PATH` (default: `./data/memories.db`), `MEMORY_EMBEDDING_MODEL`, `MEMORY_VECTOR_WEIGHT` -- **Cron**: `CRON_DB_PATH` (default: `./data/cron.db`) -- **Security**: `ALLOWED_USER_IDS` (comma-separated, empty = allow all) -- **Server**: `PORT` (default: 3000), `NODE_ENV`, `LOG_LEVEL` - -## Testing Policy - -- **新功能必须附带单元测试** — 新增的模块/函数需要在 `tests/` 下有对应的 `.test.ts` 文件。每个 feat commit 必须伴随对应的 test commit。 -- **Bug fix 需附带回归测试** — 修复的 bug 应有测试用例覆盖,防止回归。 -- **复杂改动须通过完整回归** — 涉及多模块或核心逻辑的改动,提交前需运行 `npx vitest run` 确保全部测试通过。 -- **PR 不得降低测试覆盖率** — 新增代码应有合理的测试覆盖,不允许只加功能不加测试。 - -## Deployment - -- 部署方式取决于运行环境(PM2、systemd、Docker 等),服务启动时自动检测进程管理器类型(见 `src/utils/runtime.ts`)。 -- **升级/拉取后必须跑 `npm install`** — `@anthropic-ai/claude-agent-sdk` 0.3.x 起,Claude Code CLI 二进制改为通过 `optionalDependencies` 按平台分发(`@anthropic-ai/claude-agent-sdk-`,约 240MB)。只 `git pull` + 重新 `npm run build` + 拷 `dist/` **不会**拉到该二进制,服务会起不来。`npm install` 会按 OS/CPU/libc 自动选包(glibc/musl、x64/arm64 均有)。同理,`@anthropic-ai/sdk` 与 `@modelcontextprotocol/sdk` 在 0.3.x 是 peerDependencies,已提为本仓库的直接依赖。 -- **自重启须在对话最后一步执行** — Claude 是服务的子进程,使用 `sleep 5 && &` 脱离当前进程,避免 kill 自己的父进程导致对话中断。 - -## Tech Stack - -- TypeScript 5.7, Node.js 18+, Express 4 -- `@anthropic-ai/claude-agent-sdk` for Claude Code execution -- `@larksuiteoapi/node-sdk` for Feishu API + WebSocket events -- Pino for structured logging, Zod available for validation - -## 项目文档 - -文档按生命周期分三个目录: - -| 目录 | 内容 | 生命周期 | -|------|------|----------| -| `docs/plans/` | 活跃的实施计划 | 短期,完成后蒸馏关键决策到 `design/`,再删除 | -| `docs/design/` | 模块架构与设计决策(描述**现状**) | 长期保留,随代码持续更新 | -| `docs/research/` | 调研分析 | 只读参考 | - -### Agent 工作流 - -- **开始新任务前**,扫描 `docs/plans/*.md` 的 YAML front matter,读取 `summary` 和 `read_when` 字段,判断是否与当前任务相关。如果相关,先读完该计划再动手。 -- 也可以运行 `node scripts/docs-list.mjs` 快速查看所有活跃计划的列表(支持 `--status in_progress` 过滤和 `--json` 输出)。 -- **修改代码时**,检查 `docs/design/*.md` 的 `related_paths` 字段。如果当前修改涉及某文档的关联路径,阅读该文档,若描述与代码现状不符则一并更新(将提案口吻改写为现状描述)。 -- **Plan 完成时**,将关键设计决策和架构信息蒸馏到 `docs/design/` 对应文档,然后删除 plan 文件。 -- **新建计划文件**时,必须包含以下 front matter: - -```yaml ---- -summary: "一句话描述" -status: draft # draft | in_progress | completed -owner: git-id -last_updated: "YYYY-MM-DD" -read_when: - - 触发场景 1 - - 触发场景 2 ---- -``` - -- **Design 文档**也使用 front matter,格式: - -```yaml ---- -summary: "一句话描述" -related_paths: - - src/module/** -last_updated: "YYYY-MM-DD" ---- -``` +@AGENTS.md diff --git a/README.md b/README.md index d54f0f96..a0a6420f 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,9 @@ All options are documented in `.env.example`. Key ones: ## Development +Read [AGENTS.md](AGENTS.md) for project architecture, conventions, and the documentation workflow. +Edit that file when updating project guidance. `CLAUDE.md` contains only an `@AGENTS.md` import for Claude Code / Agent SDK compatibility. + ```bash npm run dev # Start with auto-reload npm run build # Compile TypeScript diff --git a/docs/design/routing-agent.md b/docs/design/routing-agent.md index 0726b6bc..518a8052 100644 --- a/docs/design/routing-agent.md +++ b/docs/design/routing-agent.md @@ -3,11 +3,13 @@ summary: "轻量路由 Agent:在主查询前确定工作目录,支持本地/ related_paths: - src/claude/router.ts - src/feishu/thread-context.ts -last_updated: "2026-04-02" +last_updated: "2026-09-26" --- # Routing Agent 架构 +> 历史设计:前置路由 Agent 已移除,下文的 `CLAUDE.md` 文件名和路由实现保留用于解释旧方案。当前工作区流程见 [Workspace 架构](workspace-cache-and-restart.md),本仓库规范真源见 [AGENTS.md](../../AGENTS.md)。 + 轻量 Claude Code 实例(Sonnet),在主查询前决定工作目录。仅 thread 首条消息运行,后续消息直接复用已绑定的 workdir。 ## 决策类型 diff --git a/docs/design/thread-session-mapping.md b/docs/design/thread-session-mapping.md index 5b97db69..194cf68a 100644 --- a/docs/design/thread-session-mapping.md +++ b/docs/design/thread-session-mapping.md @@ -3,7 +3,7 @@ summary: "Thread 级会话绑定:threadId → workdir/conversationId 持久化 related_paths: - src/session/** - src/feishu/thread-context.ts -last_updated: "2026-04-02" +last_updated: "2026-09-26" --- # Session 架构 @@ -26,7 +26,7 @@ interface ThreadSession { workingDir: string; // 路由阶段绑定 conversationId?: string; // Claude Code session_id(用于 resume) conversationCwd?: string; // 创建 conversationId 时的 cwd - systemPromptHash?: string; // system prompt hash(变化时自动重置 session) + systemPromptHash?: string; // system prompt hash(变化时记录诊断日志) routingCompleted?: boolean; // 路由是否完成 routingState?: RoutingState; // need_clarification 时保存 pipelineContext?: PipelineContext; // pipeline 执行后保存(用于后续 history 注入) @@ -68,7 +68,7 @@ SQLite 持久化,13 次 migration 演化: 查找 ThreadSession ├── 无记录 → 运行 Routing Agent → 绑定 workdir → 创建 ThreadSession ├── routingState = pending_clarification → 拼接上下文重新路由 - ├── 有 workdir + conversationId → 检查 cwd 和 systemPromptHash 匹配 → resume + ├── 有 workdir + conversationId → 检查 cwd,记录 prompt hash 变化 → resume └── 有 workdir 无 conversationId → 新建 Claude Code session ↓ 执行 Claude Code query @@ -76,9 +76,9 @@ SQLite 持久化,13 次 migration 演化: 保存 conversationId(用于后续 resume) ``` -### System Prompt Hash 自动重置 +### System Prompt Hash 诊断 -`systemPromptHash` 记录创建 session 时的 prompt hash。当 agent 配置或 CLAUDE.md 变化导致 hash 不同时,自动清空 `conversationId`,强制创建新 session(避免 resume 到旧 prompt 的 session)。 +`systemPromptHash` 对 executor 构造的静态 prompt(knowledge + persona/workspace prompt)计算哈希。它不包含 `AGENTS.md` / `CLAUDE.md` 的文件内容,变化时仅记录诊断日志,不再清空 `conversationId`。本仓库的项目规范由 `CLAUDE.md` 导入 `AGENTS.md`,通过 Claude Code 的项目指引加载机制读取。 ## 文件 @@ -95,5 +95,5 @@ SQLite 持久化,13 次 migration 演化: | Thread 级而非 Chat 级 session | 同一群聊可能有多个并行话题,需要独立 workdir | | SQLite 持久化 | 服务重启后不丢失 session 绑定 | | 原子 CAS 锁 | 防止同一 chat 并发执行多个 query | -| systemPromptHash 自动重置 | 配置变化后不 resume 到过期的 session | +| systemPromptHash 仅用于诊断 | prompt 变化时继续 resume 并传入更新后的 systemPrompt,避免无谓丢失会话 | | Agent 前缀在 key 中 | 多 agent 场景下同一 thread 不同 agent 需要独立 session | diff --git a/docs/design/workspace-cache-and-restart.md b/docs/design/workspace-cache-and-restart.md index b1caa344..e2430e41 100644 --- a/docs/design/workspace-cache-and-restart.md +++ b/docs/design/workspace-cache-and-restart.md @@ -3,13 +3,19 @@ summary: "Bare clone 缓存层 + workspace 隔离 + 仓库 registry + 源仓库 related_paths: - src/workspace/** - src/claude/executor.ts -last_updated: "2026-04-06" +last_updated: "2026-09-26" --- # Workspace 架构 仓库缓存、工作区创建和 Git 安全控制。 +## 项目指引加载 + +本仓库的规范真源是根目录 `AGENTS.md`,`CLAUDE.md` 仅保留 `@AGENTS.md` 导入。SDK 与 CI 的 Claude Code 版本独立于本机 CLI;在确认所有执行路径支持直接加载前保留此兼容入口。版本限制与官方依据见 [AGENTS.md](../../AGENTS.md#instruction-loading-compatibility)。 + +`executor.ts` 保留 `settingSourcesOverride ?? ['user', 'project', 'local']`,因此调用方显式传入的 `[]` 仍生效。迁移指引文件不会改变设置来源、工具权限或技能发现。工作区切换后仍以新 cwd 重启 query,由 Claude Code 加载目标仓库自己的 `AGENTS.md` / `CLAUDE.md` 指引及项目设置。 + ## Bare Clone 缓存(cache.ts) 远程仓库通过 bare clone 缓存到本地,避免重复 clone。 diff --git a/docs/plans/plan-4-multi-agent-architecture.md b/docs/plans/plan-4-multi-agent-architecture.md index 520b6f0e..462a4b06 100644 --- a/docs/plans/plan-4-multi-agent-architecture.md +++ b/docs/plans/plan-4-multi-agent-architecture.md @@ -2,7 +2,7 @@ summary: "多 Agent 角色架构:Chat Agent + Dev Agent 分工协作" status: in_progress owner: lishuceo -last_updated: "2026-04-02" +last_updated: "2026-09-26" read_when: - 修改 Agent 角色定义或 prompt - 调整 Chat Agent / Dev Agent 分工 @@ -11,6 +11,8 @@ read_when: # Plan 4: 多 Agent 角色架构 +项目规范以根目录 `AGENTS.md` 为准;SDK 通过 `CLAUDE.md` 的 `@AGENTS.md` 导入保留兼容,`settingSources` 的选择保持不变。 + > 日期: 2026-02-24 > 状态: **Phase 1 已实现** (PR #52, #56) > 最后更新: 2026-02-25 @@ -126,7 +128,7 @@ ChatBot 用户对话 → Chat Agent 判断需要开发 | 工具白名单 | `Read`, `Glob`, `Grep`, `WebSearch`, `WebFetch`, `Task`, `invoke_agent` | | 禁止工具 | `Edit`, `Write`, `Bash`, `NotebookEdit`, `Skill` | | System Prompt | 方案讨论专用:引导用户明确需求、分析代码架构、制定方案、决定是否需要开发 | -| 读取 CLAUDE.md | 是(了解项目上下文) | +| 读取 AGENTS.md | 是(了解项目上下文) | | Session 隔离 | 独立 conversationId,key: `chat:{chatId}:{threadId}` | **核心能力:** @@ -142,8 +144,8 @@ ChatBot 用户对话 → Chat Agent 判断需要开发 | 飞书身份 | 独立 Bot 应用 (DevBot) | | 默认 Model | Opus 4.6(代码开发需要强能力) | | 工具白名单 | 全部工具 + `setup_workspace` MCP tool | -| System Prompt | 当前的开发 agent prompt(含 CLAUDE.md) | -| 读取 CLAUDE.md | 是 | +| System Prompt | 当前的开发 agent prompt(含 AGENTS.md) | +| 读取 AGENTS.md | 是 | | Session 隔离 | 独立 conversationId,key: `dev:{chatId}:{threadId}` | **触发方式:** diff --git a/docs/plans/plan-5-memory-system.md b/docs/plans/plan-5-memory-system.md index 5eebb5fc..bd1ee1c1 100644 --- a/docs/plans/plan-5-memory-system.md +++ b/docs/plans/plan-5-memory-system.md @@ -2,7 +2,7 @@ summary: "Agent 记忆系统:跨会话持久化记忆 + 自动提取注入" status: in_progress owner: lishuceo -last_updated: "2026-04-02" +last_updated: "2026-09-26" read_when: - 修改记忆存储、搜索、提取逻辑 - 开发记忆相关 MCP 工具 @@ -11,6 +11,8 @@ read_when: # Plan 5: Agent 记忆系统 +本文中的项目规范指根目录 `AGENTS.md`;SDK 通过 `CLAUDE.md` 的 `@AGENTS.md` 导入加载,保留现有 `settingSources` 配置。 + > 日期: 2026-02-27 > 状态: **Phase 0 ✅ | Phase 1 ✅** | Phase 2 待实施 > 前置依赖: Plan 4 Phase 1 (多 Agent 架构, 已实现) @@ -345,7 +347,7 @@ LLM 调用 (Haiku,成本最低): 只提取明确的、有长期价值的信息。不要提取: - 临时的调试过程 - 通用知识(不特定于此用户/项目) - - 已在 CLAUDE.md 中记录的项目约定" + - 已在 AGENTS.md 中记录的项目约定" ↓ 返回结构化 JSON array ↓ @@ -420,7 +422,7 @@ System Prompt 结构: │ Agent 基础人设 │ ← 固定 │ (chat.ts / dev.ts) │ ├─────────────────────────┤ - │ CLAUDE.md 项目上下文 │ ← 固定 (settingSources) + │ AGENTS.md 项目上下文 │ ← 固定 (settingSources) ├─────────────────────────┤ │ 用户记忆片段 │ ← 动态注入 ★ │ (本方案新增) │ @@ -429,7 +431,7 @@ System Prompt 结构: └─────────────────────────┘ ``` -注入方式:通过 `systemPromptBuilder(ctx)` 中追加记忆片段。记忆片段放在 CLAUDE.md 之后、对话之前,确保 Agent 同时有项目上下文和用户上下文。 +注入方式:通过 `systemPromptBuilder(ctx)` 中追加记忆片段。记忆片段放在 AGENTS.md 之后、对话之前,确保 Agent 同时有项目上下文和用户上下文。 ### 7.3 Token 预算 @@ -479,16 +481,16 @@ async function memoryMaintenance(): Promise { } ``` -### 8.3 记忆与 CLAUDE.md 的边界 +### 8.3 记忆与 AGENTS.md 的边界 | 信息类型 | 存储位置 | 理由 | |---------|---------|------| -| 项目架构、编码规范 | CLAUDE.md | 全团队共享,版本控制 | +| 项目架构、编码规范 | AGENTS.md | 全团队共享,版本控制 | | 用户个人偏好 | memories | per-user,不适合放公共文件 | | 项目事实(运行时发现的) | memories | 动态变化,自动抽取 | | Agent 配置、工具策略 | agent registry | 代码/配置管理 | -原则:CLAUDE.md 是**人为维护的项目知识**,memories 是**对话中自动积累的用户/项目知识**。两者互补不冲突。 +原则:AGENTS.md 是**人为维护的项目知识**,memories 是**对话中自动积累的用户/项目知识**。两者互补不冲突。 --- @@ -657,7 +659,7 @@ TTL: 2 小时 TTL: 按类型 (天~永久) ## 提取规则 - 只提取明确的、有长期价值的信息 -- 不要提取: 临时调试过程、通用知识、CLAUDE.md 中已有的信息 +- 不要提取: 临时调试过程、通用知识、AGENTS.md 中已有的信息 - preference 的 confidence 基于表达强度: "我习惯用"=0.8, "试试看"=0.4, "必须用"=1.0 - state 必须估计 ttl (会话级/天级/周级/月级) - fact 的 confidence 通常为 1.0,除非用户表达不确定 ("好像是") diff --git a/docs/plans/plan-6-documentation-system.md b/docs/plans/plan-6-documentation-system.md index b8c41f92..e1f6630b 100644 --- a/docs/plans/plan-6-documentation-system.md +++ b/docs/plans/plan-6-documentation-system.md @@ -2,7 +2,7 @@ summary: "文档维护体系建设:目录重组 + front matter 规范 + 文档 CI" status: in_progress owner: lishuceo -last_updated: "2026-03-10" +last_updated: "2026-09-26" read_when: - 新建或修改 docs/ 目录下的文件 - 配置文档相关的 CI 检查 @@ -125,7 +125,9 @@ read_when: | `read_when` | **核心字段**:告诉 agent 在什么场景下应该读这个文档 | | `owner` | 负责人的 Git ID | -#### 1.3 在 CLAUDE.md 中添加指引 +#### 1.3 在 AGENTS.md 中添加指引 + +规范仅维护在 `AGENTS.md`。根目录 `CLAUDE.md` 保留一行 `@AGENTS.md` 兼容旧版 SDK / CLI,不再追加正文。 ```markdown ## 开发计划文档 @@ -243,7 +245,7 @@ check-docs: // agent 据此决定是否 read 某个计划文件 ``` -在 CLAUDE.md 中加入: +在 AGENTS.md 中加入: ```markdown 开始复杂任务前,先运行 `node scripts/docs-list.mjs` 查看相关计划文档。 diff --git a/src/claude/executor.ts b/src/claude/executor.ts index 1b6db72b..f534a6d8 100644 --- a/src/claude/executor.ts +++ b/src/claude/executor.ts @@ -352,7 +352,7 @@ export function buildWorkspaceSystemPrompt(workingDir?: string, options?: { isRe ## 工作区管理 **重要:当用户的请求涉及特定仓库时(无论是阅读代码、修改代码还是查看结构),必须先使用 setup_workspace 切换到该仓库。** -这样才能正确加载项目的 CLAUDE.md(架构说明、命令约定)、.claude/settings.json(工具权限)、.claude/skills/(项目技能),并让代码搜索工具在正确的范围内工作。 +这样才能正确加载项目的 AGENTS.md / CLAUDE.md(架构说明、命令约定)、.claude/settings.json(工具权限)、.claude/skills/(项目技能),并让代码搜索工具在正确的范围内工作。 不要直接在 \`${projectsDir}\` 下用绝对路径浏览源仓库 — 这样会丢失项目上下文。 仅当用户的问题是通用性的(不涉及特定仓库,如"JavaScript 闭包是什么")时,才不需要 setup_workspace。 @@ -361,7 +361,7 @@ export function buildWorkspaceSystemPrompt(workingDir?: string, options?: { isRe 很多时候用户不会明确说"切到 X 仓库",而是**隐式**引用。你必须主动识别以下模式并触发 setup_workspace: -1. **提到某个项目的文件** — 如 "X 项目的 CLAUDE.md"、"Y 的 package.json"、"看看 Z 的配置" +1. **提到某个项目的文件** — 如 "X 项目的 AGENTS.md / CLAUDE.md"、"Y 的 package.json"、"看看 Z 的配置" 2. **讨论某个项目的架构/代码** — 根据上下文和 registry 关键词判断属于哪个仓库 3. **引用外部报告中的具体代码片段** — 如用户贴了一段来自某仓库的代码或错误日志 4. **问题涉及某项目特有的技术栈/概念** — 结合 registry 中的 techStack 和 keywords 匹配 @@ -399,11 +399,11 @@ export function buildWorkspaceSystemPrompt(workingDir?: string, options?: { isRe **不要跳过搜索步骤直接问用户要 URL。** 先尝试自己找到仓库。 -**重要:\`${cacheDir}\` 下的是 bare clone(无文件树),仅用于定位仓库 URL。不要在 bare repo 中直接工作(\`git show\`/\`git grep\` 等)。** 找到仓库后,如果项目不在 \`${projectsDir}\` 下,必须调用 setup_workspace 创建完整工作区,这样才能正确加载 CLAUDE.md、使用搜索工具、获得完整的代码上下文。 +**重要:\`${cacheDir}\` 下的是 bare clone(无文件树),仅用于定位仓库 URL。不要在 bare repo 中直接工作(\`git show\`/\`git grep\` 等)。** 找到仓库后,如果项目不在 \`${projectsDir}\` 下,必须调用 setup_workspace 创建完整工作区,这样才能正确加载 AGENTS.md / CLAUDE.md、使用搜索工具、获得完整的代码上下文。 **setup_workspace 后不要再次调用,除非发现进错了仓库。** 当前工作区已经配置好了正确的权限,直接在当前目录工作即可。 -**重要:调用 setup_workspace 后,系统将自动重启以加载项目配置(CLAUDE.md 等)。 +**重要:调用 setup_workspace 后,系统将自动重启以加载项目配置(AGENTS.md / CLAUDE.md 等)。 请在调用后仅输出简短确认(如"工作区已就绪,正在重新加载项目配置..."),不要继续执行后续任务。**`; } @@ -1056,7 +1056,8 @@ export class ClaudeExecutor { ? promptAppend : { type: 'preset', preset: 'claude_code', append: promptAppend }, - // 加载项目设置 (CLAUDE.md 等);路由 agent 传 [] 避免加载 + // 加载项目设置及指引;本仓库通过 CLAUDE.md 导入 AGENTS.md 兼容 SDK CLI + // 调用方可传 [] 禁用文件系统设置来源 // 'local' 加载 .claude/settings.local.json(优先级最高,覆盖 project) settingSources: settingSourcesOverride ?? ['user', 'project', 'local'], diff --git a/src/claude/types.ts b/src/claude/types.ts index dceff94b..6763ea73 100644 --- a/src/claude/types.ts +++ b/src/claude/types.ts @@ -97,7 +97,7 @@ export interface ExecuteOptions { disableWorkspaceTool?: boolean; /** 覆盖模型 (路由 agent 使用 Sonnet) */ model?: string; - /** 覆盖 settingSources (路由 agent 使用 [] 避免加载项目 CLAUDE.md) */ + /** 覆盖 settingSources;传 [] 禁用文件系统设置来源及项目指引加载 */ settingSources?: Array<'user' | 'project' | 'local'>; /** 只读模式:禁止 Edit/Write/Bash 等修改工具 */ readOnly?: boolean; diff --git a/src/feishu/event-handler.ts b/src/feishu/event-handler.ts index 93082117..bf54af8c 100644 --- a/src/feishu/event-handler.ts +++ b/src/feishu/event-handler.ts @@ -2599,7 +2599,7 @@ export function canResumeSession(params: { /** * 执行 Claude Agent SDK 任务 * 支持 workspace 变更后自动 restart:第一次 query 触发 setup_workspace 后, - * 自动以新 cwd 发起第二次 query,确保 CLAUDE.md 正确加载。 + * 自动以新 cwd 发起第二次 query,确保项目指引正确加载。 * * Resume 策略:优先使用 thread_sessions 表(threadId → conversationId 映射), * 每个 thread 独立管理自己的 conversationId,互不干扰。 @@ -2922,7 +2922,7 @@ export async function executeClaudeTask( ...(customSystemPrompt ? { systemPromptOverride: customSystemPrompt } : {}), }); - // 检测是否需要 restart(workspace 变更后重新执行以加载 CLAUDE.md) + // 检测是否需要 restart(workspace 变更后重新执行以加载项目指引) // 优先级高于 resume 失败检查:即使 query 失败,只要 workspace 已变更就应重启 if (result.needsRestart && result.newWorkingDir) { logger.info( @@ -3030,7 +3030,7 @@ export async function executeClaudeTask( ); } - // 第二次 query:以新 cwd 执行,CLAUDE.md 正确加载 + // 第二次 query:以新 cwd 执行,正确加载项目指引 // - 不传 resumeSessionId(Agent SDK 不支持跨 cwd resume,会 exit code 1) // - 不传 onWorkspaceChanged(不触发二次 restart) // - disableWorkspaceTool: 完全移除 setup_workspace MCP tool,防止无限循环 diff --git a/src/memory/extractor.ts b/src/memory/extractor.ts index 0e42bb8f..837b8dc0 100644 --- a/src/memory/extractor.ts +++ b/src/memory/extractor.ts @@ -101,7 +101,7 @@ entities 字段:列出 content 中引用的关键人名/项目名/组织名。 - 部署状态:"已部署到生产环境"、"已上线" → 不提取(运维日志可查) - 临时调试:临时调试过程、错误排查步骤 → 不提取 - 通用知识:编程常识、框架文档中的内容 → 不提取 -- 项目配置文件中已有的信息(如 CLAUDE.md)→ 不提取 +- 项目配置文件中已有的信息(如 AGENTS.md / CLAUDE.md)→ 不提取 ## 类型判定规则 - decision: 仅用于"为什么选 A 而不选 B"的架构/技术决策 diff --git a/src/workspace/tool.ts b/src/workspace/tool.ts index 992193ab..eed56646 100644 --- a/src/workspace/tool.ts +++ b/src/workspace/tool.ts @@ -94,7 +94,7 @@ export function createWorkspaceMcpServer(onWorkspaceChanged?: SessionUpdater) { '- 用户提到了已知的项目名(参考 system prompt 中的可用项目列表)', '- 用户描述的代码/功能明显属于另一个仓库', '- 用户说"切换到 X"、"去 X 仓库"', - '- 用户提到某个项目的文件(如 "X 项目的 CLAUDE.md"、"Y 的配置")', + '- 用户提到某个项目的文件(如 "X 项目的 AGENTS.md / CLAUDE.md"、"Y 的配置")', '- 用户讨论特定项目的架构、代码或实现细节', '- 需要查看实际源码才能准确回答用户问题(不要凭记忆回答代码问题)', '',