1041 lines
35 KiB
Markdown
1041 lines
35 KiB
Markdown
# Hive Manage v3 — P0 核心闭环实施计划
|
||
|
||
> **对于 agentic workers:** 使用 superpowers:executing-plans 或直接逐 task 执行。所有代码由 Claude Code CLI (`--output-format stream-json --include-partial-messages --verbose`) 编写,工头负责 QC。Steps 使用 checkbox (`- [ ]`) 语法追踪进度。
|
||
|
||
**目标:** 从零构建蜂群运维中台 v3 的 P0 核心闭环——7 个模块覆盖 58 个 Hermes Agent Profile 的批量管控、健康监控、密钥管理、Kanban 任务追踪、Cron 定时任务管理、事件档案、用户鉴权。
|
||
|
||
**架构:** FastAPI async 后端 + React 19 TypeScript 前端,PostgreSQL 持久层,Hermes CLI 作为蜂群数据源(低侵入只读),JWT 鉴权,CSS 变量双模(暗/浅)。
|
||
|
||
**技术栈:** Python 3.12, FastAPI, SQLAlchemy 2.0 (async), PostgreSQL, Alembic, Pydantic v2, React 19, TypeScript 5, Tailwind CSS 3, Vite 5, Lucide Icons, JWT (python-jose), bcrypt, pytest, Vitest.
|
||
|
||
## 全局约束
|
||
|
||
- 不复用 v1 任何代码,全部从零重写
|
||
- 所有 API 路径前缀 `/api/v1/`
|
||
- 所有 API 请求/响应用 Pydantic 模型校验
|
||
- 四态覆盖:Loading (Skeleton) / Empty (引导文案) / Error (重试按钮) / Normal
|
||
- 暗色模式为默认主题,跟随系统并可手动切换(localStorage `hive-theme`)
|
||
- 移动端响应式:768px 断点,按钮触控 ≥ 44×44px
|
||
- 鉴权:所有 `/api/v1/` 除 `/api/v1/auth/*` 外需 JWT Bearer Token
|
||
- 审计:所有写操作(POST/PUT/PATCH/DELETE)自动记录到 `audit_logs` 表
|
||
- Hermes CLI 调用只读,不修改蜂巢核心代码
|
||
- 密钥值始终脱敏显示(前 3 + 后 4 字符)+ 不写入审计日志原文
|
||
- 模型退役 warning 可忽略(底层走 DeepSeek v4 Pro 映射)
|
||
- Nginx 反代:`/api/` → FastAPI:8000,其余 → Vite dist
|
||
|
||
---
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
/home/enzo/projects/hive-manage-v3/
|
||
├── backend/
|
||
│ ├── app/
|
||
│ │ ├── main.py # FastAPI 应用工厂 + 中间件注册
|
||
│ │ ├── config.py # Settings (pydantic-settings),读 .env
|
||
│ │ ├── database.py # async engine + session + Base
|
||
│ │ ├── models/
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── user.py # User ORM
|
||
│ │ │ └── audit.py # AuditLog ORM
|
||
│ │ ├── schemas/
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── auth.py # Login/Register/Token 请求响应
|
||
│ │ │ ├── user.py # User CRUD
|
||
│ │ │ ├── gateway.py # Gateway 状态/事件
|
||
│ │ │ ├── health.py # 健康分
|
||
│ │ │ ├── cron.py # Cron Job
|
||
│ │ │ ├── kanban.py # Kanban 任务
|
||
│ │ │ ├── keys.py # 密钥
|
||
│ │ │ ├── dashboard.py # Dashboard 聚合
|
||
│ │ │ ├── event.py # 事件档案
|
||
│ │ │ └── audit.py # 审计日志
|
||
│ │ ├── api/
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── auth.py # /api/v1/auth/*
|
||
│ │ │ ├── users.py # /api/v1/users/*
|
||
│ │ │ ├── gateway.py # /api/v1/gateway/*
|
||
│ │ │ ├── health.py # /api/v1/health/*
|
||
│ │ │ ├── cron.py # /api/v1/cron/*
|
||
│ │ │ ├── kanban.py # /api/v1/kanban/*
|
||
│ │ │ ├── keys.py # /api/v1/keys/*
|
||
│ │ │ ├── dashboard.py # /api/v1/dashboard/*
|
||
│ │ │ ├── events.py # /api/v1/events/*
|
||
│ │ │ └── audit.py # /api/v1/audit/*
|
||
│ │ ├── services/
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── hermes_cli.py # hermes gateway/cron/kanban CLI 封装
|
||
│ │ │ ├── health_scorer.py # 健康分计算引擎
|
||
│ │ │ ├── key_manager.py # .env 读写 + 脱敏
|
||
│ │ │ └── event_crawler.py # hm.zhiweidata.ai/events 爬取
|
||
│ │ └── middleware/
|
||
│ │ ├── __init__.py
|
||
│ │ ├── auth.py # JWT 鉴权依赖
|
||
│ │ └── audit.py # 审计日志中间件
|
||
│ ├── alembic/
|
||
│ │ ├── env.py
|
||
│ │ └── versions/
|
||
│ ├── tests/
|
||
│ │ ├── conftest.py # async test fixtures
|
||
│ │ ├── test_auth.py
|
||
│ │ ├── test_gateway.py
|
||
│ │ ├── test_health.py
|
||
│ │ ├── test_cron.py
|
||
│ │ ├── test_kanban.py
|
||
│ │ ├── test_keys.py
|
||
│ │ ├── test_dashboard.py
|
||
│ │ └── test_events.py
|
||
│ ├── requirements.txt
|
||
│ ├── .env.example
|
||
│ └── pyproject.toml
|
||
├── frontend/
|
||
│ ├── src/
|
||
│ │ ├── main.tsx # React 入口
|
||
│ │ ├── App.tsx # 路由 + 布局
|
||
│ │ ├── types/
|
||
│ │ │ └── index.ts # 全局 TS 类型
|
||
│ │ ├── styles/
|
||
│ │ │ └── tokens.css # CSS 变量 (暗/浅双模)
|
||
│ │ ├── components/
|
||
│ │ │ ├── ui/
|
||
│ │ │ │ ├── Button.tsx
|
||
│ │ │ │ ├── Card.tsx
|
||
│ │ │ │ ├── Table.tsx
|
||
│ │ │ │ ├── Badge.tsx
|
||
│ │ │ │ ├── Modal.tsx
|
||
│ │ │ │ ├── Drawer.tsx
|
||
│ │ │ │ ├── Toast.tsx
|
||
│ │ │ │ ├── Skeleton.tsx
|
||
│ │ │ │ ├── Toggle.tsx
|
||
│ │ │ │ ├── Timeline.tsx
|
||
│ │ │ │ └── SearchBox.tsx
|
||
│ │ │ └── layout/
|
||
│ │ │ ├── Sidebar.tsx
|
||
│ │ │ ├── Header.tsx
|
||
│ │ │ ├── MobileNav.tsx
|
||
│ │ │ ├── TabBar.tsx
|
||
│ │ │ └── AppLayout.tsx
|
||
│ │ ├── pages/
|
||
│ │ │ ├── LoginPage.tsx
|
||
│ │ │ ├── DashboardPage.tsx
|
||
│ │ │ ├── GatewayPage.tsx
|
||
│ │ │ ├── HealthPage.tsx
|
||
│ │ │ ├── CronPage.tsx
|
||
│ │ │ ├── KanbanPage.tsx
|
||
│ │ │ ├── KeysPage.tsx
|
||
│ │ │ ├── EventArchivePage.tsx
|
||
│ │ │ ├── UserManagementPage.tsx
|
||
│ │ │ └── AuditLogPage.tsx
|
||
│ │ ├── hooks/
|
||
│ │ │ ├── usePolling.ts
|
||
│ │ │ ├── useAuth.ts
|
||
│ │ │ └── useTheme.ts
|
||
│ │ └── api/
|
||
│ │ ├── client.ts # axios 实例 + JWT 拦截器
|
||
│ │ ├── auth.ts
|
||
│ │ ├── gateway.ts
|
||
│ │ ├── health.ts
|
||
│ │ ├── cron.ts
|
||
│ │ ├── kanban.ts
|
||
│ │ ├── keys.ts
|
||
│ │ ├── dashboard.ts
|
||
│ │ ├── events.ts
|
||
│ │ ├── users.ts
|
||
│ │ └── audit.ts
|
||
│ ├── index.html
|
||
│ ├── package.json
|
||
│ ├── tsconfig.json
|
||
│ ├── vite.config.ts
|
||
│ ├── tailwind.config.ts
|
||
│ └── postcss.config.js
|
||
├── deploy/
|
||
│ └── nginx-hive-manage-v3.conf
|
||
├── docs/
|
||
│ └── superpowers/
|
||
│ └── plans/
|
||
├── .gitignore
|
||
└── README.md
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 0:基础设施
|
||
|
||
> 所有后续 Phase 的前置依赖。无业务逻辑,纯骨架。
|
||
|
||
### Task 0.1:项目目录 + 基础文件
|
||
|
||
**文件:**
|
||
- Create: `.gitignore`, `README.md`, `backend/.env.example`, `backend/pyproject.toml`
|
||
|
||
- [ ] **Step 1: 创建 .gitignore**
|
||
|
||
```
|
||
__pycache__/
|
||
*.pyc
|
||
.env
|
||
node_modules/
|
||
dist/
|
||
.pytest_cache/
|
||
*.egg-info/
|
||
venv/
|
||
.DS_Store
|
||
```
|
||
|
||
- [ ] **Step 2: 创建 README.md**
|
||
|
||
```markdown
|
||
# Hive Manage v3
|
||
|
||
蜂群运维中台 — 58 个 Hermes Agent Profile 的批量管控面板。
|
||
|
||
## 技术栈
|
||
|
||
- 后端: FastAPI + SQLAlchemy async + PostgreSQL
|
||
- 前端: React 19 + TypeScript + Tailwind CSS + Vite
|
||
|
||
## 快速开始
|
||
|
||
见 deploy/ 目录下的部署文档。
|
||
```
|
||
|
||
- [ ] **Step 3: 创建 backend/pyproject.toml**
|
||
|
||
```toml
|
||
[project]
|
||
name = "hive-manage-v3"
|
||
version = "0.1.0"
|
||
requires-python = ">=3.12"
|
||
dependencies = [
|
||
"fastapi[standard]>=0.115",
|
||
"sqlalchemy[asyncio]>=2.0",
|
||
"asyncpg>=0.30",
|
||
"alembic>=1.14",
|
||
"pydantic>=2.10",
|
||
"pydantic-settings>=2.7",
|
||
"python-jose[cryptography]>=3.3",
|
||
"passlib[bcrypt]>=1.7",
|
||
"httpx>=0.28",
|
||
"uvicorn[standard]>=0.34",
|
||
]
|
||
[project.optional-dependencies]
|
||
dev = [
|
||
"pytest>=8.3",
|
||
"pytest-asyncio>=0.25",
|
||
"httpx>=0.28",
|
||
]
|
||
```
|
||
|
||
- [ ] **Step 4: 创建 backend/.env.example**
|
||
|
||
```
|
||
DATABASE_URL=postgresql+asyncpg://hive_admin:changeme@localhost:5432/hive_manage_v3
|
||
JWT_SECRET=change-me-to-random-string
|
||
JWT_ALGORITHM=HS256
|
||
JWT_EXPIRE_MINUTES=1440
|
||
HERMES_CLI_PATH=/home/enzo/.local/bin/hermes
|
||
HERMES_PROFILES_ROOT=/home/enzo/.hermes/profiles
|
||
ADMIN_EMAIL=admin@zhiwei.local
|
||
ADMIN_PASSWORD=admin123
|
||
```
|
||
|
||
- [ ] **Step 5: 提交**
|
||
|
||
```bash
|
||
git add -A && git commit -m "chore: project scaffold with .gitignore, README, pyproject.toml"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 0.2:Git 初始化 + Gitea 建库 + Mirror
|
||
|
||
> 此 Task 委托 ops-engineer(工蜂)执行。以下为指令规格,由 ops 自行完成。
|
||
|
||
**要求:**
|
||
- 在 `/home/enzo/projects/hive-manage-v3/` 执行 `git init`
|
||
- 在主 Gitea (`192.168.50.97:3002`, 用户 `enzo`) 创建仓库 `hive-manage-v3`
|
||
- 设置 remote origin 指向主 Gitea
|
||
- 首次 commit + push
|
||
- 备份 Gitea (`192.168.50.92:3030`) 的 mirror 由现有 cron 自动发现(每小时),无需手动操作
|
||
- 验证:`git remote -v` 指向正确地址,Gitea Web UI 可见仓库
|
||
|
||
**ops 执行命令参考:**
|
||
|
||
```bash
|
||
cd /home/enzo/projects/hive-manage-v3
|
||
git init
|
||
git remote add origin http://enzo:zhiwei2026!@192.168.50.97:3002/enzo/hive-manage-v3.git
|
||
git add -A && git commit -m "chore: initial commit"
|
||
git push -u origin main
|
||
```
|
||
|
||
---
|
||
|
||
### Task 0.3:FastAPI 骨架
|
||
|
||
**文件:**
|
||
- Create: `backend/app/__init__.py`
|
||
- Create: `backend/app/main.py`
|
||
- Create: `backend/app/config.py`
|
||
- Create: `backend/app/database.py`
|
||
|
||
- [ ] **Step 1: 创建 config.py**
|
||
|
||
```python
|
||
"""应用配置 — 从环境变量 / .env 读取。"""
|
||
from pydantic_settings import BaseSettings
|
||
|
||
class Settings(BaseSettings):
|
||
database_url: str = "postgresql+asyncpg://hive_admin:changeme@localhost:5432/hive_manage_v3"
|
||
jwt_secret: str = "change-me"
|
||
jwt_algorithm: str = "HS256"
|
||
jwt_expire_minutes: int = 1440
|
||
hermes_cli_path: str = "/home/enzo/.local/bin/hermes"
|
||
hermes_profiles_root: str = "/home/enzo/.hermes/profiles"
|
||
admin_email: str = "admin@zhiwei.local"
|
||
admin_password: str = "admin123"
|
||
|
||
model_config = {"env_file": ".env"}
|
||
|
||
settings = Settings()
|
||
```
|
||
|
||
- [ ] **Step 2: 创建 database.py**
|
||
|
||
```python
|
||
"""异步 SQLAlchemy 引擎 + session 工厂。"""
|
||
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
|
||
from sqlalchemy.orm import DeclarativeBase
|
||
|
||
from app.config import settings
|
||
|
||
engine = create_async_engine(settings.database_url, echo=False)
|
||
async_session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
||
|
||
|
||
class Base(DeclarativeBase):
|
||
pass
|
||
|
||
|
||
async def get_db() -> AsyncSession:
|
||
async with async_session() as session:
|
||
yield session
|
||
```
|
||
|
||
- [ ] **Step 3: 创建 main.py**
|
||
|
||
```python
|
||
"""FastAPI 应用入口。"""
|
||
from contextlib import asynccontextmanager
|
||
from fastapi import FastAPI
|
||
from fastapi.middleware.cors import CORSMiddleware
|
||
|
||
from app.database import engine, Base
|
||
|
||
|
||
@asynccontextmanager
|
||
async def lifespan(app: FastAPI):
|
||
# 启动时创建表(开发阶段;生产用 Alembic)
|
||
async with engine.begin() as conn:
|
||
await conn.run_sync(Base.metadata.create_all)
|
||
yield
|
||
await engine.dispose()
|
||
|
||
|
||
app = FastAPI(
|
||
title="Hive Manage v3",
|
||
version="0.1.0",
|
||
lifespan=lifespan,
|
||
)
|
||
|
||
app.add_middleware(
|
||
CORSMiddleware,
|
||
allow_origins=["*"],
|
||
allow_credentials=True,
|
||
allow_methods=["*"],
|
||
allow_headers=["*"],
|
||
)
|
||
|
||
|
||
@app.get("/api/v1/health")
|
||
async def health_check():
|
||
return {"status": "ok"}
|
||
```
|
||
|
||
- [ ] **Step 4: 提交**
|
||
|
||
```bash
|
||
git add backend/app/ && git commit -m "feat: FastAPI skeleton with config, database, health endpoint"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 0.4:Alembic 初始化 + User 基础 Schema
|
||
|
||
**文件:**
|
||
- Create: `backend/alembic/` (通过 `alembic init`)
|
||
- Modify: `backend/alembic/env.py`
|
||
- Create: `backend/app/models/__init__.py`
|
||
- Create: `backend/app/models/user.py`
|
||
|
||
- [ ] **Step 1: 初始化 Alembic + 创建 User 模型**
|
||
|
||
```bash
|
||
cd backend && alembic init alembic
|
||
```
|
||
|
||
- [ ] **Step 2: 配置 alembic/env.py**
|
||
|
||
将 `target_metadata` 指向 `Base.metadata`,配置异步引擎。关键改动:
|
||
|
||
```python
|
||
from app.database import Base, engine
|
||
from app.models import * # noqa: F401,F403 — 确保所有模型被导入
|
||
|
||
target_metadata = Base.metadata
|
||
|
||
def run_migrations_offline():
|
||
...
|
||
context.configure(url=settings.database_url, target_metadata=target_metadata)
|
||
|
||
def do_run_migrations(connection):
|
||
context.configure(connection=connection, target_metadata=target_metadata)
|
||
|
||
async def run_async_migrations():
|
||
async with engine.begin() as conn:
|
||
await conn.run_sync(do_run_migrations)
|
||
|
||
def run_migrations_online():
|
||
import asyncio
|
||
asyncio.run(run_async_migrations())
|
||
```
|
||
|
||
- [ ] **Step 3: 创建 User 模型 backend/app/models/user.py**
|
||
|
||
```python
|
||
"""用户 ORM 模型。"""
|
||
import uuid
|
||
from datetime import datetime
|
||
from sqlalchemy import String, Boolean, DateTime, Enum as SAEnum
|
||
from sqlalchemy.orm import Mapped, mapped_column
|
||
import enum
|
||
|
||
from app.database import Base
|
||
|
||
|
||
class UserRole(str, enum.Enum):
|
||
OWNER = "owner"
|
||
OPERATOR = "operator"
|
||
VIEWER = "viewer"
|
||
|
||
|
||
class User(Base):
|
||
__tablename__ = "users"
|
||
|
||
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||
username: Mapped[str] = mapped_column(String(50), unique=True, nullable=False, index=True)
|
||
email: Mapped[str] = mapped_column(String(255), unique=True, nullable=False)
|
||
hashed_password: Mapped[str] = mapped_column(String(255), nullable=False)
|
||
role: Mapped[UserRole] = mapped_column(SAEnum(UserRole), default=UserRole.VIEWER, nullable=False)
|
||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||
is_approved: Mapped[bool] = mapped_column(Boolean, default=False)
|
||
login_attempts: Mapped[int] = mapped_column(default=0)
|
||
locked_until: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||
```
|
||
|
||
- [ ] **Step 4: 生成初始迁移**
|
||
|
||
```bash
|
||
cd backend && alembic revision --autogenerate -m "create users table"
|
||
alembic upgrade head
|
||
```
|
||
|
||
- [ ] **Step 5: 创建 backend/app/models/audit.py**
|
||
|
||
```python
|
||
"""审计日志 ORM 模型。"""
|
||
import uuid
|
||
from datetime import datetime
|
||
from sqlalchemy import String, DateTime, Text
|
||
from sqlalchemy.orm import Mapped, mapped_column
|
||
|
||
from app.database import Base
|
||
|
||
|
||
class AuditLog(Base):
|
||
__tablename__ = "audit_logs"
|
||
|
||
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||
user_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
|
||
username: Mapped[str] = mapped_column(String(50), nullable=False)
|
||
action: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
|
||
target: Mapped[str] = mapped_column(String(255), nullable=False)
|
||
detail: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
ip_address: Mapped[str | None] = mapped_column(String(45), nullable=True)
|
||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||
```
|
||
|
||
- [ ] **Step 6: 生成 AuditLog 迁移并提交**
|
||
|
||
```bash
|
||
cd backend && alembic revision --autogenerate -m "create audit_logs table"
|
||
alembic upgrade head
|
||
git add backend/alembic/ backend/app/models/ && git commit -m "feat: Alembic setup, User and AuditLog models"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 0.5:前端 Vite + React + Tailwind 脚手架
|
||
|
||
**文件:**
|
||
- Create: `frontend/package.json`, `frontend/tsconfig.json`, `frontend/vite.config.ts`, `frontend/tailwind.config.ts`, `frontend/postcss.config.js`, `frontend/index.html`, `frontend/src/main.tsx`, `frontend/src/App.tsx`
|
||
|
||
- [ ] **Step 1: 创建 package.json**
|
||
|
||
```json
|
||
{
|
||
"name": "hive-manage-v3-frontend",
|
||
"private": true,
|
||
"version": "0.1.0",
|
||
"type": "module",
|
||
"scripts": {
|
||
"dev": "vite",
|
||
"build": "tsc && vite build",
|
||
"preview": "vite preview"
|
||
},
|
||
"dependencies": {
|
||
"react": "^19.0",
|
||
"react-dom": "^19.0",
|
||
"react-router-dom": "^7.0",
|
||
"axios": "^1.7",
|
||
"lucide-react": "^0.460"
|
||
},
|
||
"devDependencies": {
|
||
"@types/react": "^19.0",
|
||
"@types/react-dom": "^19.0",
|
||
"@vitejs/plugin-react": "^4.3",
|
||
"autoprefixer": "^10.4",
|
||
"postcss": "^8.4",
|
||
"tailwindcss": "^3.4",
|
||
"typescript": "^5.6",
|
||
"vite": "^6.0"
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: 创建 vite.config.ts**
|
||
|
||
```typescript
|
||
import { defineConfig } from 'vite'
|
||
import react from '@vitejs/plugin-react'
|
||
|
||
export default defineConfig({
|
||
plugins: [react()],
|
||
server: {
|
||
port: 5173,
|
||
proxy: {
|
||
'/api': 'http://127.0.0.1:8000',
|
||
},
|
||
},
|
||
})
|
||
```
|
||
|
||
- [ ] **Step 3: 创建 tailwind.config.ts**
|
||
|
||
```typescript
|
||
import type { Config } from 'tailwindcss'
|
||
|
||
export default {
|
||
content: ['./index.html', './src/**/*.{ts,tsx}'],
|
||
darkMode: 'class',
|
||
theme: {
|
||
extend: {
|
||
colors: {
|
||
honey: { DEFAULT: '#f0b90b', dim: '#b8970e' },
|
||
},
|
||
},
|
||
},
|
||
plugins: [],
|
||
} satisfies Config
|
||
```
|
||
|
||
- [ ] **Step 4: 创建 index.html + main.tsx + App.tsx(最小骨架)**
|
||
|
||
```html
|
||
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Hive Manage v3</title></head>
|
||
<body><div id="root"></div><script type="module" src="/src/main.tsx"></script></body>
|
||
</html>
|
||
```
|
||
|
||
```tsx
|
||
// main.tsx
|
||
import React from 'react'
|
||
import ReactDOM from 'react-dom/client'
|
||
import App from './App'
|
||
import './styles/tokens.css'
|
||
|
||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||
<React.StrictMode><App /></React.StrictMode>
|
||
)
|
||
```
|
||
|
||
```tsx
|
||
// App.tsx
|
||
export default function App() {
|
||
return <div className="min-h-screen bg-[var(--bg-root)] text-[var(--text)]">Hive Manage v3</div>
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 5: 安装依赖 + 验证**
|
||
|
||
```bash
|
||
cd frontend && npm install && npm run dev
|
||
# 访问 http://localhost:5173 应显示 "Hive Manage v3"
|
||
```
|
||
|
||
- [ ] **Step 6: 提交**
|
||
|
||
```bash
|
||
git add frontend/ && git commit -m "feat: Vite + React 19 + Tailwind + TypeScript scaffold"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 0.6:CSS 变量双模体系
|
||
|
||
**文件:**
|
||
- Create: `frontend/src/styles/tokens.css`
|
||
|
||
**根据 UI 设计规范 §2.1 精确实现:**
|
||
|
||
```css
|
||
/* ===== 暗色模式(默认) ===== */
|
||
:root {
|
||
--bg-root: #0f1117; --bg-nav: #161822; --bg-card: #1a1d2e;
|
||
--bg-hover: #1e2134; --bg-elevated: #222639;
|
||
--border: #2a2d3e; --border-light: rgba(42,45,62,.5);
|
||
--honey: #f0b90b; --honey-dim: #b8970e; --honey-glow: rgba(240,185,11,.12);
|
||
--green: #00c853; --red: #ff3d3d; --yellow: #ffab00;
|
||
--blue: #448aff; --orange: #ff6d00;
|
||
--text: #e0e0e0; --text-dim: #8b8d9a; --text-muted: #5a5d6a;
|
||
--bg-success: #0d2818; --bg-error: #2d0f0f; --bg-warn: #2d2000; --bg-info: #0d1b2d;
|
||
--radius: 8px; --radius-sm: 4px; --radius-lg: 12px; --radius-full: 9999px;
|
||
--shadow: 0 2px 8px rgba(0,0,0,.35); --shadow-lg: 0 12px 32px rgba(0,0,0,.55);
|
||
--shadow-modal: 0 24px 64px rgba(0,0,0,.65);
|
||
--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||
--font-mono: "SF Mono", "Fira Code", Consolas, monospace;
|
||
--header-h: 48px; --sidebar-w: 220px;
|
||
}
|
||
|
||
/* ===== 浅色模式 ===== */
|
||
[data-theme="light"] {
|
||
--bg-root: #f5f6fa; --bg-nav: #ffffff; --bg-card: #ffffff;
|
||
--bg-hover: #edf0f5; --bg-elevated: #ffffff;
|
||
--border: #e2e5ee; --border-light: rgba(0,0,0,.06);
|
||
--honey: #e5a800; --honey-dim: #c48f00; --honey-glow: rgba(229,168,0,.08);
|
||
--green: #008c3a; --red: #d32f2f; --yellow: #e65100;
|
||
--blue: #1565c0; --orange: #d84315;
|
||
--text: #1a1d2e; --text-dim: #555a6e; --text-muted: #8b8f9e;
|
||
--bg-success: #e8f5e9; --bg-error: #fdecea; --bg-warn: #fff3e0; --bg-info: #e3f2fd;
|
||
--shadow: 0 1px 4px rgba(0,0,0,.08); --shadow-lg: 0 8px 24px rgba(0,0,0,.10);
|
||
--shadow-modal: 0 16px 48px rgba(0,0,0,.14);
|
||
}
|
||
|
||
/* ===== 全局基础 ===== */
|
||
* { box-sizing: border-box; }
|
||
body {
|
||
margin: 0; font-family: var(--font); font-size: 13px;
|
||
background: var(--bg-root); color: var(--text);
|
||
}
|
||
/* 主题切换过渡 */
|
||
* { transition: background-color .15s, border-color .15s, color .15s; }
|
||
```
|
||
|
||
- [ ] **Step: 提交**
|
||
|
||
```bash
|
||
git add frontend/src/styles/tokens.css && git commit -m "feat: CSS variable dual-theme system (dark default + light)"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 0.7:共享 UI 组件库
|
||
|
||
**文件:** 全部在 `frontend/src/components/ui/` 下创建。
|
||
|
||
> 每个组件遵循 UI 设计规范 §4 规格。以下列出关键组件及核心实现要点,完整代码由 Claude Code 根据原型 HTML 和设计规范实现。
|
||
|
||
| 组件 | 文件 | 规范参考 | 关键要点 |
|
||
|------|------|----------|----------|
|
||
| Button | `Button.tsx` | §4.4 | 4 变体 (primary/danger/outline/ghost) + 2 尺寸 + loading/disabled 态 |
|
||
| Card | `Card.tsx` | §4.1 | header(label+action) + value(彩色) + change(↑↓) |
|
||
| Table | `Table.tsx` | §4.3 | sticky 表头 + hover 高亮 + row-danger 样式 + 移动端卡片化 |
|
||
| Badge | `Badge.tsx` | §4.5 | 6 变体 (success/danger/warning/info/honey/outline) + 胶囊形 |
|
||
| Modal | `Modal.tsx` | §4.8 | 居中弹窗 + 遮罩 + Esc 关闭 + 确认短语输入 |
|
||
| Drawer | `Drawer.tsx` | §4.9 | 右侧滑入 480px + 遮罩 + Esc 关闭 |
|
||
| Toast | `Toast.tsx` | §4.10 | 4 类型 (success/error/warn/info) + 顶部居中 + 自动消失 |
|
||
| Skeleton | `Skeleton.tsx` | §4.14 | shimmer 动画 + 形状匹配 (card/table/text) |
|
||
| Toggle | `Toggle.tsx` | §4.7 | 44×24px + 滑块动画 + 标签 |
|
||
| Timeline | `Timeline.tsx` | §4.13 | 横向时间线 + 点 hover tooltip |
|
||
| SearchBox | `SearchBox.tsx` | §4.11 | 输入框 + 下拉面板 + 分组结果 + debounce 300ms |
|
||
|
||
**测试要求:** 每个组件提供基础渲染测试(Vitest + React Testing Library),验证所有变体和状态。
|
||
|
||
- [ ] **Step: 逐个组件实现(Claude Code 编写 + 工头 QC)**
|
||
|
||
```bash
|
||
git add frontend/src/components/ui/ && git commit -m "feat: shared UI component library (11 components)"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 0.8:布局组件
|
||
|
||
**文件:** `frontend/src/components/layout/`
|
||
|
||
| 组件 | 文件 | 规范参考 | 关键要点 |
|
||
|------|------|----------|----------|
|
||
| Sidebar | `Sidebar.tsx` | §3.5 | 220px 固定 + 5 Section + NavItem active/hover + Badge |
|
||
| Header | `Header.tsx` | §3.4 | 48px + 面包屑 + 搜索框 + 主题切换 + 更新指示 |
|
||
| MobileNav | `MobileNav.tsx` | §3.2 | 汉堡菜单 → 左侧抽屉 280px + 遮罩 |
|
||
| TabBar | `TabBar.tsx` | §3.6 | 底部固定 56px + 4 核心入口 (总览/Gateway/Kanban/Cron) |
|
||
| AppLayout | `AppLayout.tsx` | §3.1 | CSS Grid: Sidebar + Header + Main,响应式 768px 断点切换移动布局 |
|
||
|
||
- [ ] **Step 1: 实现 AppLayout.tsx(核心布局)**
|
||
|
||
```tsx
|
||
// 桌面: CSS Grid (sidebar 220px + header 48px + main)
|
||
// 平板 (768-1279px): sidebar 180px
|
||
// 移动 (<768px): Header + TabBar + 汉堡抽屉
|
||
// 使用 CSS 媒体查询 + data-viewport 属性切换
|
||
```
|
||
|
||
- [ ] **Step 2: 实现路由占位**
|
||
|
||
```tsx
|
||
// App.tsx 中使用 react-router-dom
|
||
// / → Dashboard
|
||
// /login → LoginPage
|
||
// /gateway → GatewayPage
|
||
// ...
|
||
// 未登录重定向 /login,已登录根据 JWT 存在与否判断
|
||
```
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add frontend/src/components/layout/ frontend/src/App.tsx && git commit -m "feat: layout components (Sidebar, Header, MobileNav, TabBar, AppLayout)"
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 1:用户中心 + 鉴权(P0-6)
|
||
|
||
### Task 1.1:JWT 鉴权服务 + 中间件
|
||
|
||
**文件:**
|
||
- Create: `backend/app/services/auth_service.py`
|
||
- Create: `backend/app/middleware/auth.py`
|
||
- Create: `backend/app/schemas/auth.py`
|
||
|
||
- [ ] **Step 1: 创建 auth schema**
|
||
|
||
```python
|
||
# backend/app/schemas/auth.py
|
||
from pydantic import BaseModel, EmailStr
|
||
|
||
class LoginRequest(BaseModel):
|
||
username: str
|
||
password: str
|
||
|
||
class RegisterRequest(BaseModel):
|
||
username: str
|
||
email: EmailStr
|
||
password: str
|
||
|
||
class TokenResponse(BaseModel):
|
||
access_token: str
|
||
token_type: str = "bearer"
|
||
expires_in: int
|
||
user: "UserResponse" # 引用 user schema
|
||
|
||
class ChangePasswordRequest(BaseModel):
|
||
old_password: str
|
||
new_password: str
|
||
```
|
||
|
||
- [ ] **Step 2: 创建 auth_service.py**
|
||
|
||
核心功能:
|
||
- `hash_password(password: str) -> str` — bcrypt
|
||
- `verify_password(plain: str, hashed: str) -> bool`
|
||
- `create_access_token(user_id: str, role: str) -> str` — JWT 编码
|
||
- `decode_access_token(token: str) -> dict` — JWT 解码 + 过期检查
|
||
- `get_current_user(token: str, db: AsyncSession) -> User` — FastAPI Depends
|
||
|
||
- [ ] **Step 3: 创建 auth 中间件**
|
||
|
||
```python
|
||
# backend/app/middleware/auth.py
|
||
from fastapi import Depends, HTTPException, status
|
||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
from app.database import get_db
|
||
from app.services.auth_service import decode_access_token, get_user_by_id
|
||
|
||
security = HTTPBearer()
|
||
|
||
async def require_auth(
|
||
credentials: HTTPAuthorizationCredentials = Depends(security),
|
||
db: AsyncSession = Depends(get_db),
|
||
):
|
||
"""解析 JWT → 查询 User → 返回 User ORM 对象。失败抛 401。"""
|
||
payload = decode_access_token(credentials.credentials)
|
||
user = await get_user_by_id(db, payload["sub"])
|
||
if not user or not user.is_active:
|
||
raise HTTPException(status_code=401, detail="Invalid or inactive user")
|
||
return user
|
||
|
||
def require_role(*roles: str):
|
||
"""角色守卫工厂。用法: Depends(require_role("owner", "operator"))"""
|
||
async def role_check(user = Depends(require_auth)):
|
||
if user.role.value not in roles:
|
||
raise HTTPException(status_code=403, detail="Insufficient permissions")
|
||
return user
|
||
return role_check
|
||
```
|
||
|
||
- [ ] **Step 4: 编写测试**
|
||
|
||
```python
|
||
# backend/tests/test_auth.py
|
||
# 测试用例:
|
||
# - 注册成功 → 201
|
||
# - 重复注册 → 409
|
||
# - 登录成功 → 200 + JWT
|
||
# - 错误密码 → 401
|
||
# - 登录锁定(5 次失败) → 423
|
||
# - Token 过期 → 401
|
||
# - 无 Token 访问受保护路由 → 401
|
||
# - Viewer 角色访问写操作 → 403
|
||
```
|
||
|
||
- [ ] **Step 5: 提交**
|
||
|
||
```bash
|
||
git add backend/app/services/auth_service.py backend/app/middleware/ backend/app/schemas/auth.py backend/tests/test_auth.py && git commit -m "feat: JWT auth service, middleware, and role guards"
|
||
```
|
||
|
||
---
|
||
|
||
### Task 1.2:Auth API 路由
|
||
|
||
**文件:**
|
||
- Create: `backend/app/api/auth.py`
|
||
|
||
- [ ] **Step 1: 实现路由**
|
||
|
||
```python
|
||
# backend/app/api/auth.py
|
||
from fastapi import APIRouter, Depends, HTTPException, status
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
from app.database import get_db
|
||
from app.schemas.auth import LoginRequest, RegisterRequest, TokenResponse
|
||
from app.services.auth_service import *
|
||
from app.models.user import User, UserRole
|
||
|
||
router = APIRouter(prefix="/api/v1/auth", tags=["auth"])
|
||
|
||
@router.post("/register", status_code=201)
|
||
async def register(body: RegisterRequest, db: AsyncSession = Depends(get_db)):
|
||
"""新用户注册。默认 Viewer 角色 + 待审批。首个用户自动设为 Owner + 已审批。"""
|
||
...
|
||
|
||
@router.post("/login", response_model=TokenResponse)
|
||
async def login(body: LoginRequest, db: AsyncSession = Depends(get_db)):
|
||
"""用户名 + 密码登录。失败 5 次锁定 15 分钟。成功返回 JWT。"""
|
||
...
|
||
|
||
@router.post("/refresh")
|
||
async def refresh_token(user = Depends(require_auth)):
|
||
"""刷新 Token(重置过期时间)。"""
|
||
...
|
||
|
||
@router.post("/change-password")
|
||
async def change_password(body: ChangePasswordRequest, user = Depends(require_auth), db = Depends(get_db)):
|
||
"""修改当前用户密码。"""
|
||
...
|
||
```
|
||
|
||
- [ ] **Step 2: 在 main.py 注册路由**
|
||
|
||
```python
|
||
from app.api import auth
|
||
app.include_router(auth.router)
|
||
```
|
||
|
||
- [ ] **Step 3: 编写集成测试并提交**
|
||
|
||
---
|
||
|
||
### Task 1.3:用户管理 API
|
||
|
||
**文件:**
|
||
- Create: `backend/app/api/users.py`
|
||
- Create: `backend/app/schemas/user.py`
|
||
|
||
路由:`GET /api/v1/users`(列表) / `GET /api/v1/users/{id}`(详情) / `PATCH /api/v1/users/{id}`(改角色) / `POST /api/v1/users/{id}/approve`(审批) / `DELETE /api/v1/users/{id}`(停用)。
|
||
|
||
- [ ] **Step 1: 实现 + 测试 + 提交**
|
||
|
||
---
|
||
|
||
### Task 1.4:审计日志中间件 + API
|
||
|
||
**文件:**
|
||
- Modify: `backend/app/middleware/audit.py`(自动记录写操作)
|
||
- Create: `backend/app/api/audit.py`
|
||
|
||
核心逻辑:中间件监听所有 POST/PUT/PATCH/DELETE 请求,提取 `user_id`、`action`、`target`、`ip_address`,写入 `audit_logs`。审计日志不可删除(API 只提供 GET 查询)。
|
||
|
||
- [ ] **Step: 实现 + 测试 + 提交**
|
||
|
||
---
|
||
|
||
### Task 1.5-1.9:前端鉴权页面
|
||
|
||
**文件:**
|
||
- `frontend/src/pages/LoginPage.tsx`
|
||
- `frontend/src/pages/UserManagementPage.tsx`
|
||
- `frontend/src/pages/AuditLogPage.tsx`
|
||
- `frontend/src/hooks/useAuth.ts`
|
||
- `frontend/src/api/auth.ts`, `users.ts`, `audit.ts`
|
||
- `frontend/src/api/client.ts`(axios 实例 + JWT 拦截器 + 401 自动跳转登录)
|
||
|
||
- [ ] **Step: 逐页面实现(Claude Code 编写 + 工头 QC)**
|
||
|
||
```bash
|
||
git add frontend/src/pages/LoginPage.tsx frontend/src/pages/UserManagementPage.tsx frontend/src/pages/AuditLogPage.tsx frontend/src/hooks/useAuth.ts frontend/src/api/ && git commit -m "feat: login, user management, audit log pages with JWT auth flow"
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 2-8:业务模块
|
||
|
||
> 每个模块遵循相同模式:**Hermes CLI 封装服务 → Pydantic Schema → API 路由 → 前端页面**。以下为模块规格摘要,完整实现由 Claude Code 按此模式执行。
|
||
|
||
### 通用实现模式(以 Gateway 为例)
|
||
|
||
```
|
||
1. backend/app/services/hermes_cli.py — 添加 gateway_status(), gateway_start(), gateway_stop()
|
||
2. backend/app/schemas/gateway.py — GatewayStatus, GatewayEvent, ToggleRequest
|
||
3. backend/app/api/gateway.py — router + require_auth + 角色守卫
|
||
4. backend/tests/test_gateway.py — pytest + httpx AsyncClient
|
||
5. frontend/src/api/gateway.ts — axios 调用封装
|
||
6. frontend/src/pages/GatewayPage.tsx — 完整页面(四态 + 轮询 + 操作)
|
||
```
|
||
|
||
### Phase 2:Dashboard 增强(P0-3)
|
||
|
||
| Task | 后端 API | 前端页面 | 估时 |
|
||
|------|----------|----------|:--:|
|
||
| 2.1 | `GET /api/v1/dashboard/summary` — 在线/离线/任务/Cron 计数 | DashboardPage 统计卡片 | 2h |
|
||
| 2.2 | `GET /api/v1/dashboard/health-distribution` — A/B/C/D 四级计数 | 健康分布柱状图 | 1.5h |
|
||
| 2.3 | `GET /api/v1/dashboard/gateway-trend` — 24h 异常事件按小时 | Gateway 异常趋势折线图 | 1.5h |
|
||
| 2.4 | `GET /api/v1/dashboard/kanban-summary` — 活跃看板概览 | Kanban 概览卡片 | 1h |
|
||
| 2.5 | `GET /api/v1/dashboard/cron-recent` — 最近 Cron 执行 | Cron 最近执行卡片 | 1h |
|
||
| 2.6 | `GET /api/v1/search?q=` — 全局搜索 | SearchBox 组件集成 | 1.5h |
|
||
|
||
### Phase 3:Gateway 健康监控(P0-1)
|
||
|
||
| Task | 后端 API | 前端页面 | 估时 |
|
||
|------|----------|----------|:--:|
|
||
| 3.1 | `GET /api/v1/gateway/status` — 全部 Profile 状态列表 | GatewayPage 状态表(10s 轮询) | 3h |
|
||
| 3.2 | `GET /api/v1/gateway/events` — 24h 异常事件时间线 | 异常时间线组件 | 2h |
|
||
| 3.3 | `POST /api/v1/gateway/{profile}/start\|stop\|restart` | 启停按钮 + 二次确认弹窗 | 2.5h |
|
||
| 3.4 | 筛选 + 蜂型分类 | 前端筛选器(即时生效) | 1.5h |
|
||
|
||
### Phase 4:Profile 健康分(P0-2)
|
||
|
||
| Task | 后端 API | 前端页面 | 估时 |
|
||
|------|----------|----------|:--:|
|
||
| 4.1 | `GET /api/v1/health/scores` — 排行列表 | HealthPage 列表 + 展开详情 | 3h |
|
||
| 4.2 | `GET /api/v1/health/scores/{profile}` — 单 Profile 详情 | 四维度扣分明细面板 | 2h |
|
||
| 4.3 | `POST /api/v1/health/compare` — 批量对比 | 批量对比视图 | 2h |
|
||
| 4.4 | `POST /api/v1/health/calculate` — 手动触发计算 | 凌晨定时 + 手动触发按钮 | 2h |
|
||
|
||
### Phase 5:Cron 管理(P0-4b)
|
||
|
||
| Task | 后端 API | 前端页面 | 估时 |
|
||
|------|----------|----------|:--:|
|
||
| 5.1 | `GET /api/v1/cron/jobs` — 跨 Profile Cron 列表(含系统 Cron) | CronPage 列表 + 筛选 | 3h |
|
||
| 5.2 | `GET /api/v1/cron/jobs/{id}/logs` — 最近 8 条日志 | 日志面板(遮罩 + 居中弹窗) | 2h |
|
||
| 5.3 | `POST /api/v1/cron/jobs/{id}/run\|pause\|resume` | 操作按钮 + Toast | 2h |
|
||
| 5.4 | 失败告警联动 | Dashboard Badge + 导航栏红色标记 | 1.5h |
|
||
|
||
### Phase 6:密钥批量管理(P0-5)
|
||
|
||
| Task | 后端 API | 前端页面 | 估时 |
|
||
|------|----------|----------|:--:|
|
||
| 6.1 | `GET /api/v1/keys` — 密钥字段列表 | KeysPage 列表 | 2h |
|
||
| 6.2 | `POST /api/v1/keys/batch-overwrite` — 批量覆盖 | 批量覆盖弹窗(确认短语) | 2h |
|
||
| 6.3 | `POST /api/v1/keys/batch-scan` — 批量检查 | 缺失扫描结果 + CSV 导出 | 1.5h |
|
||
| 6.4 | `GET /api/v1/keys/diff` — 差异视图 | 字段对比表 | 1.5h |
|
||
|
||
### Phase 7:Kanban 增强(P0-4)
|
||
|
||
| Task | 后端 API | 前端页面 | 估时 |
|
||
|------|----------|----------|:--:|
|
||
| 7.1 | `GET /api/v1/kanban/tasks` — 跨 Profile 五列聚合 | KanbanPage 五列看板 | 4h |
|
||
| 7.2 | `GET /api/v1/kanban/tasks/{id}` — 任务详情 | 详情抽屉 | 2h |
|
||
| 7.3 | `PATCH /api/v1/kanban/tasks/{id}/move` — 拖拽移动 | 拖拽 + 异常标记 | 3h |
|
||
| 7.4 | 异常检测(阻塞超时/长期无主/失败重试) | 卡片标红/警告 | 2h |
|
||
| 7.5 | Worker 筛选 + 看板筛选 + 异常筛选 | 筛选器 | 2h |
|
||
|
||
### Phase 8:事件档案管理(P0-7)
|
||
|
||
| Task | 后端 API | 前端页面 | 估时 |
|
||
|------|----------|----------|:--:|
|
||
| 8.1 | `GET /api/v1/events` — 事件卡片列表(三维筛选) | EventArchivePage 卡片网格 | 2h |
|
||
| 8.2 | 数据爬取 → PG(`hm.zhiweidata.ai/events`) | — | 2h |
|
||
| 8.3 | 超期标记 + Toast 详情 | 超期红色标记 + 点击 Toast | 1.5h |
|
||
|
||
---
|
||
|
||
## Phase 9:集成测试 + 上线
|
||
|
||
| Task | 内容 | 估时 |
|
||
|------|------|:--:|
|
||
| 9.1 | 全量 API 集成测试(httpx + pytest-asyncio) | 3h |
|
||
| 9.2 | 前端冒烟测试(Vitest + Testing Library) | 2h |
|
||
| 9.3 | Nginx 部署配置 + 静态文件服务 | 1h |
|
||
| 9.4 | 部署文档 + API 文档(FastAPI 自动生成) | 0.5h |
|
||
|
||
---
|
||
|
||
## 执行说明
|
||
|
||
- **所有代码由 Claude Code 编写**,命令格式:
|
||
|
||
```bash
|
||
cd /home/enzo/projects/hive-manage-v3 && \
|
||
ANTHROPIC_API_KEY="sk-4eem6h6DfcPIT7EbY3tLhtd7oepyw9GaqgbSUHmkv3shmNym" \
|
||
ANTHROPIC_BASE_URL="http://127.0.0.1:3000" \
|
||
ANTHROPIC_MODEL="claude-3-opus-20240229" \
|
||
claude --model claude-3-opus-20240229 \
|
||
--dangerously-skip-permissions \
|
||
--output-format stream-json --include-partial-messages --verbose \
|
||
-p "<完整任务描述 + 上下文 + 验收标准>"
|
||
```
|
||
|
||
- **每个 Task 完成后**:工头审查产出(代码质量 + 测试覆盖 + 是否符合设计规范),通过则提交,不通过则反馈 Claude Code 修改。
|
||
- **提交粒度**:一个 Task 一个 commit,commit message 格式 `feat:` / `fix:` / `test:` / `chore:` + 简短描述。
|
||
|
||
---
|
||
|
||
*计划版本: v1.0 · 2026-07-22 · 开发工程*
|