# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## 项目概述 LemonBoss / ArenaSK — 多智能体自主开发系统 + AI Skill 竞技平台。Node.js + Claude CLI 驱动,提供 Agent 协作(公司 / OKR / 招聘 / Pipeline / Task Timeline)与 Skill 市场 / Arena 评测两套能力。 > 品牌历史:项目早期叫 ArenaSK(Skill 竞技场),现演进为 LemonBoss(多 Agent 公司体)。两个名称在代码中并存属正常现象。 ## 快速启动 ```bash # 一次性安装 + 拷贝 .env.example npm run setup # 开发模式(前后端分离,跑完整 ArenaSK + LemonBoss) npm run dev # 后端 server/index.js:3010 + 前端 vite:5173 # 等价快捷脚本(先 kill 占用端口再起) bash start.sh # server/index.js:3010 + vite:5173 # (历史轻量入口,仅 Agent Chat / Company / OKR / Tasks 子集) PORT=3010 node server/agent-server.js ``` > 端口默认 **3010**(`server/config.js`),不是 3000。`start.sh` 会先 kill 占用 3010 / 5173 的进程。 ## 常用命令 ```bash # 启动 npm run dev # 后端 + 前端 npm run server / server:dev # 仅后端 (start / --watch) npm run web / web:build # 前端开发 / 构建到 web/dist/ # 测试 npm test # vitest watch npm run test:unit # vitest run (CI 用) npx vitest run path/to/foo.test.js # 跑单个测试文件 npx vitest run -t "test name" # 按名称过滤单个测试用例 # 跑全量前先起「不带后台驱动」的 server:心跳每 5 分钟往 system/agents/ 建运行态目录, # 扫描该目录的守卫测试会被瞬时竞态打成偶发假失败(详见 docs/done/claude-cli-session-leak.md §七) DISABLE_BACKGROUND_AGENTS=1 bash start.sh # CLI / 工具 npm run skills:sync # 同步 Skill 到 Claude CLI 配置目录 npm run graph:seed # 按 system/agents/ 目录重建图谱种子数据 npm run okr:migrate # goals → okr 存量迁移 ``` ## 架构 ### 技术栈 - **后端**:Node.js (≥18) + Express + WebSocket + SQLite(better-sqlite3, FTS5) - **前端**:Vue 3 + Vite + vue-router + vue-i18n - **AI**:Claude CLI(本地子进程,`--dangerously-skip-permissions` 自动批准) - **包管理**:pnpm workspace(monorepo),`package.json` 含 `module-alias: { "@server": "server" }` ### 两个 Server 入口(重要) | 入口 | 端口 | 启动方式 | 挂载路由 | |------|------|----------|----------| | `server/index.js` | 3010 | `npm run dev` / `npm run server` / `bash start.sh` | 全量:`/api/claude-chat` `/api/config` `/api/evolution` `/api/innovator` `/api/master` `/api/open` `/api/arena` `/api/auth` `/api/users` `/api/whatsapp` `/api/agent` `/api/okr` `/api/company` `/api/graph-runs` `/api/tasks`,WS `/ws/claude`,插件 / 心跳 / 中断任务恢复,`NODE_ENV=production` 时托管 `web/dist/` 静态文件 | | `server/agent-server.js` | 3010 | 仅手动 `node server/agent-server.js`(历史保留) | 子集:`/api/agent` `/api/company` `/api/okr` `/api/graph-runs` `/api/tasks` | 两者**不要同时启动**(端口冲突)。默认走 `index.js`(`start.sh` / `npm run dev` 都指向它);`agent-server.js` 只在你想跑无依赖最小子集时手动启动。 ### 目录速查 | 目录 | 说明 | |------|------| | `server/index.js` | 完整 ArenaSK 服务(API + WS + 插件 + 前端托管),`start.sh` / `npm run dev` 默认入口 | | `server/agent-server.js` | 历史保留的轻量子集入口(Agent / Company / Goals / Tasks),仅手动启动 | | `server/routes/` | 各 API 路由(挂载点见上表两个入口,以入口文件为准) | | `server/services/` | 业务服务(skill-db, benchmark-runner, company-service, heartbeat-service, company-heartbeat-service, pipeline-service, retrain-pipeline, graph-engine, …) | | `server/src/core/` | Agent 引擎核心(orchestrator, master-session, agent-manager, scheduler, session-pool, prompt-builder, runtime-resolver, …) | | `server/src/engine/` | 进程层(command-queue, idle-timer, process-guard, run-registry, failover-error) | | `server/src/plugins/` | 插件系统(plugin-manager, agent-bridge, config-bridge, bootstrap) | | `server/services/devloop/path-resolver.js` / `doc-store.js` | DevLoop 退役(2026-09-17,[52 号文档](docs/done/system-design/52-devloop-retirement.md))后唯二保留的两个文件:`path-resolver.js` 是 `graph-engine.js` 项目根分配的实现,`doc-store.js` 的 `hashContract` 被 `graph-engine.js`/`goal-contract.js` 复用。其余 DevLoop 代码(`src/core/devloop/`、`src/tools/devloop/`、`services/devloop/` 下其余文件、`routes/devloop.js`)已删除 | | `system/agents/` | **全部 Agent 本体的唯一目录**。`_base/` 是元 Agent 骨架,`_registry.json` 只用于按 id 补 `benchmark_score`(**目录才是数据源头**,`graph-seed-service.seedAgents()` 直接扫目录)。`_` 前缀为保留 id,扫描时跳过 | | `system/org-graph-templates/` `system/work-graph-templates/` | Org/Work graph 的骨架模板库——公司类型 / org node 职能 → 图形状的**唯一查询入口**,`orggraph-planning`/`workgraph-planning` 建图时读这里选型,人工排查"为什么现场规划出这张图"也从这里查起。每个模板的 `whenToUse` 字段是选型依据,加新模板见各自 `README.md`「加一个新模板」一节;改完 `work-graph-templates/*.json` 跑一遍 `npx vitest run server/tests/unit/template-refs.test.js`(CI 用,查 `systemAgentId` 引用不落空) | | `server/src/tools/` | Master Agent 可调用的工具(call-agent, marketplace, orchestrate, train-skill, …) | | `web/src/views/` | 页面:AgentChat, AgentList, CompanyDashboard, GraphConsole, JobsPanel, OkrDashboard, PipelineEditor, QuotaMonitor, SkillsMarket, TaskTimeline。TemplateAgents(手工模板管理页)已于 2026-08-23 随「system/templates/ 并入 system/agents/」一起下线,agent 本体现在完全走自动化招聘产生。DevLoop 四页(Dashboard / Projects / NewRequirement / Ops)已随 DevLoop 退役一起删除 | | `packages/` | `acp-core`, `agent-core`, `evolution`, `plugin-bootstrap` | | `/../data/skills/` | Skill 仓库。**在仓库外面一层**,不是 `/data/skills/`(后者不存在)。路径由 `config.skillsDataDir` 控制,见下「数据存储」的两个 data 根 | | `scripts/` | 运维脚本(含 `sync-skills.js`) | | `docs/` | 设计文档,**按状态分目录**:`done/`(已实现 / 长期参考手册,含 `system-design/` 01–26 章与 `user-guides/`)、`todo/`(当前主线,27/28 系列)、`todo/future/`(暂缓)、`_archive/`(含 DevLoop 退役归档,见下)。**索引在 [`docs/README.md`](docs/README.md),逐条带状态说明 —— 找文档从那里进,别在本表里加文件名**(这一行曾经列了 5 个具体文件,文档移进 `done/` 之后全成了死链) | ### 关键 API 路由 | 路径 | 说明 | |------|------| | `/api/open/skills` | Open API: Skill 搜索 / 下载(FTS5) | | `/api/open/arena/leaderboard` | Arena ELO 排行榜 | | `/api/innovator/skills` | Skill 管理(Admin) | | `/api/master/chat` | Master Agent 对话(SSE) | | `/api/agent/*` | LemonBoss Agent Chat | | `/api/company/*` `/api/okr/*` `/api/tasks/*` | 公司 / OKR / Task 管理(OKR 只此一个挂载点,`/api/goals` 别名已于 27-P3C §六.1 退役,有守卫测试盯着) | | `/api/auth/*` | JWT + GitHub OAuth | | `/ws/claude` | Claude 实时对话(仅 `index.js`) | | `/api/health` `/api/plugins` | 健康检查 / 插件状态 | | `/api/dream/*` | 经验汇流(29-DREAM):`dream-service.js` 能力的 REST 封装,只读查询 + 触发 `dreamOnce`/`dreamSweep`,不新增业务逻辑,见 [`docs/done/system-design/29-dream-design.md`](docs/done/system-design/29-dream-design.md) | ### DevLoop 子系统(已退役) 原多 Agent 自动开发流水线(PM → Architect → Coder → Tester → Integrator → Triager,L1/L2/L3 三层嵌套 loop)。 **2026-09-17 整体退役**:本质是 loop workflow,已被 27 号系列的 graph workflow(org graph + work graph, `graph-engine.js`)严格覆盖(loop 是 graph 的一个退化形状),不再需要维护独立实现,用户拍板不做 27 号总纲原计划的 P6 迁移,直接删除。决策记录、退役范围、保留了什么/为什么见 [`docs/done/system-design/52-devloop-retirement.md`](docs/done/system-design/52-devloop-retirement.md)。 PRD/SDD 完整规格站点(原仓库根 docs/prd 目录)归档在 `docs/_archive/devloop-prd-2026-09-17/`。 `server/services/devloop/path-resolver.js` / `doc-store.js` 两个文件因为被 `graph-engine.js` 依赖而保留, 见上方目录速查表那一行。 ### 数据存储(SQLite,无需 PostgreSQL) > [!IMPORTANT] > **有两个不同的 `data/` 根,别混**。ArenaSK 时代的三个库落在**仓库外面一层**, > LemonBoss 的数据在**仓库内**。看到以 `data/` 开头的路径先确认是哪一个 —— 备份、迁移、 > 换机器时漏掉仓库外那半边,skill / 用户 / benchmark 数据会静默丢失。 > 判据看源码里 `path.resolve(__dirname, ...)` 的层数(当前 11 个模块指仓库内、3 个指仓库外)。 **仓库外** `/../data/` — ArenaSK 侧(`benchmark-db.js` / `skill-db.js` / `user-db.js`, 均可用 `SKILLS_DB_PATH` / `USERS_DB_PATH` / `BENCHMARK_DB_PATH` 等 env 覆盖): - `skills/` — Skill 目录(数万条),路径由 `config.skillsDataDir` 控制 - `skills.sqlite` — Skill 主库 + FTS5 - `users.sqlite` — 用户数据 - `benchmark_logs.sqlite` — Benchmark 运行数据(**不是** `benchmark.sqlite`) - `trained_skills/` — 用户训练产物(按 userId 隔离) **仓库内** `/data/` — LemonBoss 侧(company / okr / graph 都在这儿): - `graph.sqlite` — 图谱库(`GRAPH_DB_PATH` 可覆盖) - `companies/` — 公司态(含 graph-engine 项目根、agent memory;`projects/{pid}/` 这套目录布局历史上由 DevLoop 首创,`path-resolver.js` 保留后两边共用同一套分配逻辑) - `okr/` `logs/` `agents/` — OKR 索引 / 运行日志 / agent 运行态 会话持久化有**两套**,不是一处: - `/conversations/` — ArenaSK / Innovator 侧(`config.conversationsDir`,`CONVERSATIONS_DIR` 可覆盖) - `/conversations/{convId}/` — LemonBoss agent-chat 侧(`agent-chat.getConvDir` → `locator.companyStateDir`) ### 配置文件 | 文件 | 说明 | |------|------| | `.env` | 端口、CORS、`OPEN_API_KEYS`、各类目录覆盖;由 `npm run setup` 从 `.env.example` 生成 | | `server/config.js` | 端口(默认 3010)、CORS、Skill / Conversations 路径 | | `server/config/taxonomy.js` | 三维标签分类 | ## 注意事项 - 生产环境只跑 `server/index.js`:它会同时托管 API + `web/dist/` 静态文件(`NODE_ENV=production`)。 - `start.sh` **只**做:kill 占用 3010/5173 的进程 → 起 `server/index.js` → 起 `vite`。**不**会自动 `skills:sync` / `web:build` / 起 bot —— 那些要单独跑。 - `server/index.js` 与 `agent-server.js` 都内置了 **body-sanitizer 中间件**:在 `express.json()` 之前清掉 `\x00-\x1F` 控制字符,避免外部 Agent 通过 `curl` 传未转义换行/制表符导致的 `Bad control character` 报错。修改请求体解析链路前先看这两段。 - **agent-chat 的 `sessions` 池存的是常驻 claude CLI 子进程**(stream-json 模式,不是一次性的 `claude -p`)。 新增一条会创建会话的调用路径时,必须同时想清楚它的回收路径 —— 判据只有一条:**convId 会不会被下一轮复用**。 不复用的(心跳 / 日程 / 告警 / 日报)在 `CALL_KINDS` 里标 `true`,跑完即回收;会复用的(pipeline 被驳回重做、 人类多轮对话)标 `false`,靠空闲 TTL 兜底(`AGENT_SESSION_IDLE_MS`,默认 30 分钟)。 漏标的症状是**静默的**:不报错、不写日志、`git status` 干净,只有内存一路涨(曾经 2h43m 漏出 82 个进程 / 17.5 GB)。 守卫:`server/tests/unit/agent-chat-session-reclaim.test.js`。 - 模块别名 `@server` → `server/`(`module-alias` 注册),跨子包 require 时可用。 - Claude CLI 进程默认带 `--dangerously-skip-permissions`,写入受限路径前自己评估风险。 - DevLoop 已退役,详见上方「DevLoop 子系统(已退役)」一节与 52 号文档。 > [!WARNING] (Agentic Self-Correction Loop Prevention) > **Master Agent 必读**: 你目前存在一个已知的底层 Tool Calling JSON 解析缺陷。当你试图在 `Bash` tool 中使用带有多重双引号的复杂命令(例如 `curl -d '{"id":"lemonv", "name":"Lemonv"}'`)时,你的 JSON 转义会崩溃并导致你陷入"修复格式"的无限死循环,最终进程会被强制终止退出 (code=143)。 > **解决方案**: > 任何需要提交复杂 Payload (如 JSON) 的操作,**绝对禁止**直接在 `Bash` 的 command 参数里写 inline JSON 字符串。 > 如果你要创建公司或执行类似 API 请求,**必须先通过写入简单的 shell 脚本将 JSON 写入一个 /tmp/ 目录下的 `.json` 文件(确保你的 JSON 是单行紧凑格式/严格转义换行符,不要包含真回车换行 `\n`,以免引起 SyntaxError: Bad control character 崩溃),然后再通过 `curl -d @/tmp/payload.json` 发送。** > > 【创建公司/招聘的正确方式示例】 > 创建 /tmp/lemonv.json,然后执行 `Bash`: `curl -X POST http://localhost:3000/api/company/create -H "Content-Type: application/json" -d @/tmp/lemonv.json`