动态多仓库和单体仓库意识,用于Claude Code。分析工作区拓扑结构,跟踪API契约,并维护跨仓库上下文。
工作区分析技能
动态多仓库和单体仓库意识,用于Claude Code。分析工作区拓扑结构,跟踪API契约,并维护跨仓库上下文。
问题
当您拥有独立的前端/后端仓库(或单体仓库中的多个应用程序)时,Claude Code在隔离状态下运行。它不知道:
- 模块/仓库之间的API契约
- 共享类型和接口
- 完整的系统架构
- 跨仓库依赖关系
- 系统中其他部分的变化
这导致:
- 重复的类型定义
- API契约不匹配
- 直到运行时才捕获到的破坏性更改
- Claude重新实现其他地方已经存在的东西
解决方案:动态工作区分析
与静态清单不同,Claude动态分析工作区并生成上下文工件,这些工件通过钩子保持新鲜。
┌─────────────────────────────────────────────────────────────────┐
│ 工作区分析系统 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ /analyze-workspace (完整分析 - ~2分钟) │
│ ├── 拓扑发现(单体仓库与多仓库) │
│ ├── 依赖图(谁调用谁) │
│ ├── 契约提取(OpenAPI、GraphQL、类型) │
│ └── 关键文件识别(何时加载) │
│ │
│ /sync-contracts (增量 - ~15秒) │
│ ├── 检查契约源文件是否更改 │
│ ├── 更新CONTRACTS.md与差异 │
│ └── 验证一致性 │
│ │
│ 钩子(自动) │
│ ├── 会话开始:陈旧性咨询(~5秒) │
│ ├── 提交后:如果契约更改则自动同步(~15秒) │
│ └── 推送前:验证门(~10秒) │
│ │
└─────────────────────────────────────────────────────────────────┘
工作区分类
检测模式
| 类型 | 指标 | 文件访问 |
|---|---|---|
| 单体仓库 | pnpm-workspace.yaml, nx.json, turbo.json, lerna.json | 直接(同一树) |
| 多仓库 | 具有单独.git的同级目录 | 通过符号链接或路径 |
| 混合 | 单体仓库+外部仓库依赖 | 混合 |
| 单一 | 一个应用程序,没有工作区配置 | N/A(使用现有仓库) |
单体仓库检测
# 检查单体仓库指标
ls package.json pnpm-workspace.yaml lerna.json nx.json turbo.json 2>/dev/null
ls apps/ packages/ services/ libs/ modules/ 2>/dev/null
多仓库检测
# 检查相关仓库的兄弟目录
ls -la ../*.git 2>/dev/null
cat ../*/.git/config 2>/dev/null | grep "url"
# 查看命名模式
ls .. | grep -E "(frontend|backend|api|web|shared|common)"
多语言检测
# 查找所有包清单
find . -maxdepth 4 -name "package.json" -o -name "pyproject.toml" \
-o -name "go.mod" -o -name "Cargo.toml" -o -name "pom.xml" \
-o -name "build.gradle" -o -name "Gemfile"
分析协议
第1阶段:拓扑发现(~30秒)
确定工作区结构:
## 发现清单
1. [ ] 确定工作区根
2. [ ] 分类工作区类型(单体仓库/多仓库/混合/单一)
3. [ ] 列出所有模块/应用程序/包
4. [ ] 检测每个模块的技术栈
5. [ ] 确定每个模块的入口点
模块检测模式:
workspace-root/
├── apps/ → 应用程序模块
│ ├── web/ → 前端应用程序
│ └── api/ → 后端应用程序
├── packages/ → 共享包
│ ├── ui/ → 组件库
│ ├── types/ → 共享类型
│ └── db/ → 数据库层
├── services/ → 微服务
└── libs/ → 内部库
第2阶段:依赖图(~60秒)
对于每个模块,映射:
1. 内部依赖
# TypeScript/JavaScript
grep -r "from ['\"]@" --include="*.ts" --include="*.tsx" | head -50
grep -r "workspace:" package.json
# Python
grep -r "from \".\" --include="*.py" | head -50
2. API关系
# 查找API调用
grep -rE "fetch|axios|httpx|requests\." --include="*.ts" --include="*.py" | \
grep -E "/api|localhost|127\.0\.0\.1" | head -30
3. 数据库连接
# 查找数据库访问模式
grep -rE "prisma|drizzle|sqlalchemy|sequelize|typeorm" --include="*.ts" --include="*.py"
第3阶段:契约提取(~45秒)
识别并解析API契约:
| 契约类型 | 检测 | 提取 |
|---|---|---|
| OpenAPI | openapi.json, swagger.yaml, /docs端点 | 解析路径,模式 |
| GraphQL | schema.graphql, *.gql, /graphql端点 | 解析类型,查询,突变 |
| tRPC | trpc路由器文件,@trpc/*导入 | 解析路由器定义 |
| Protobuf | *.proto文件 | 解析服务,消息 |
| TypeScript | 共享.d.ts,导出的接口 | 解析导出的类型 |
| Pydantic | schemas/, models/与BaseModel | 解析模型定义 |
| Zod | schemas/与z.object | 解析模式定义 |
契约源优先级:
- 生成的规范(openapi.json)- 最准确
- 模式定义(Pydantic,Zod)- 源真相
- 类型导出(TypeScript .d.ts)- 消费者契约
- 从代码推断 - 最后手段
第4阶段:关键文件识别(~30秒)
确定Claude必须了解的每个上下文的文件:
| 类别 | 检测模式 | 令牌优先级 |
|---|---|---|
| 路由定义 | **/routes/**, **/api/**, @app.get, @router |
高 |
| 类型定义 | **/types/**, *.d.ts, schemas/, models/ |
高 |
| 配置 | .env.example, config/, settings.py |
中 |
| 入口点 | main.ts, index.ts, app.py, server.py |
中 |
| API客户端 | **/api/client*, **/lib/api* |
高 |
| 数据库架构 | schema/, migrations/, prisma/schema.prisma |
中 |
| 测试 | __tests__/, *_test.py, *.spec.ts |
低(按需) |
生成的工件
所有工件都在_project_specs/workspace/中:
_project_specs/workspace/
├── TOPOLOGY.md # 哪些模块存在,它们的角色
├── CONTRACTS.md # API规范,共享类型(总结)
├── DEPENDENCY_GRAPH.md # 谁调用谁(视觉+列表)
├── KEY_FILES.md # 每个上下文需要加载什么
├── CROSS_REPO_INDEX.md # 所有模块的能力
└── .contract-sources # 监控更改的文件
TOPOLOGY.md格式
# 工作区拓扑
生成:2026-01-20T14:32:00Z
分析器:claude-bootstrap/work区分析
工作区类型:单体仓库(Turborepo)
## 概述
┌─────────────────────────────────────────────────┐ │ apps/web (Next.js) ←→ apps/api (FastAPI) │ │ ↓ ↓ │ │ packages/shared-types ← packages/db │ └─────────────────────────────────────────────────┘
## 模块
### apps/web
- **路径**:/apps/web
- **技术**:Next.js 14, TypeScript, TailwindCSS
- **角色**:面向客户的仪表板
- **消耗**:apps/api(REST), packages/shared-types
- **入口**:src/app/layout.tsx
- **关键文件**:
- `src/lib/api/client.ts` - API客户端(187行)
- `src/types/` - 前端特定类型(12个文件)
- **令牌估计**:~15K(全部), ~4K(总结)
### apps/api
- **路径**:/apps/api
- **技术**:FastAPI, Python 3.12, SQLAlchemy
- **角色**:REST API, 业务逻辑
- **暴露**:OpenAPI在/docs(47个端点)
- **消耗**:packages/db
- **入口**:app/main.py
- **关键文件**:
- `app/routes/` - 所有端点(8个路由器)
- `app/schemas/` - Pydantic模型(23个文件)
- `openapi.json` - 生成的规范
- **令牌估计**:~22K(全部), ~6K(总结)
### packages/shared-types
- **路径**:/packages/shared-types
- **技术**:TypeScript
- **角色**:共享类型定义
- **被消耗**:apps/web, apps/api(代码生成)
- **关键文件**:
- `src/index.ts` - 所有导出(340行)
- **令牌估计**:~3K
### packages/db
- **路径**:/packages/db
- **技术**:Drizzle ORM, TypeScript
- **角色**:数据库架构,迁移
- **被消耗**:apps/api
- **关键文件**:
- `schema/` - 表定义(8个文件)
- `migrations/` - 迁移历史(23个文件)
- **令牌估计**:~8K(全部), ~2K(仅架构)
CONTRACTS.md格式
# API契约
生成:2026-01-20T14:32:00Z
上次同步:2026-01-20T16:45:00Z
监控源:3个文件
## REST API:apps/api → apps/web
### 端点摘要(总共47个)
| 域 | 计数 | 关键端点 |
|--------|-------|---------------|
| /api/auth | 5 | POST /login, POST /register, POST /refresh |
| /api/users | 6 | GET /me, PATCH /me, GET /:id |
| /api/campaigns | 8 | CRUD + POST /bulk, GET /analytics |
| /api/analytics | 12 | GET /dashboard, GET /timeseries, GET /funnel |
| /api/settings | 4 | GET /, PATCH /, GET /integrations |
### 关键类型
```typescript
// 活动领域(来自apps/api/app/schemas/campaign.py)
interface Campaign {
id: string;
name: string;
status: 'draft' | 'active' | 'paused' | 'completed';
budget: number;
target_audience: TargetAudence;
created_at: string;
updated_at: string;
}
interface CampaignCreate {
name: string;
budget: number;
target_audience?: TargetAudience;
}
// 认证领域(来自apps/api/app/schemas/auth.py)
interface User {
id: string;
email: string;
name: string;
role: 'user' | 'admin';
}
interface TokenPair {
access_token: string;
refresh_token: string;
expires_in: number;
}
契约验证状态
| 检查 | 状态 | 详细信息 |
|---|---|---|
| OpenAPI与路由匹配 | ✅ | 47/47端点已记录 |
| 类型与模式匹配 | ✅ | 所有Pydantic模型已导出 |
| 前端类型当前 | ⚠️ | 2个类型需要再生 |
共享类型:packages/shared-types
导出类型(总共34个)
| 类别 | 类型 | 使用者 |
|---|---|---|
| 领域模型 | Campaign, User, Analytics | web, api |
| API响应 | ApiResponse<T>, PaginatedResponse<T> | web |
| 公用事业 | DateRange, FilterParams | web, api |
数据库架构:packages/db
表(总共12个)
| 表 | 关键列 | 关系 |
|---|---|---|
| users | id, email, name, role | campaigns, sessions |
| campaigns | id, user_id, name, status | analytics, targets |
| analytics | id, campaign_id, date, metrics | campaigns |
### DEPENDENCY_GRAPH.md格式
```markdown
# 依赖图
生成:2026-01-20T14:32:00Z
## 视觉概览
┌─────────────────┐
│ packages/db │
│ (Drizzle ORM) │
└────────┬────────┘
│
▼
┌─────────────────┐ ┌─────────────────┐ │ apps/web │◄──│ apps/api │ │ (Next.js) │ │ (FastAPI) │ └────────┬────────┘ └────────┬────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────┐ │ packages/shared-types │ │ (TypeScript) │ └─────────────────────────────────────────┘
## 依赖矩阵
| 模块 | 依赖于 | 被依赖 |
|--------|------------|-------------|
| apps/web | shared-types, apps/api(运行时) | - |
| apps/api | shared-types(代码生成), db | apps/web |
| packages/shared-types | - | apps/web, apps/api |
| packages/db | - | apps/api |
## 导入分析
### apps/web导入:
@repo/shared-types: 23个文件 apps/api(通过fetch):15个文件
### apps/api导入:
packages/db: 12个文件 packages/shared-types(代码生成):8个文件
## API调用图
apps/web apps/api ───────── ──────── src/lib/api/client.ts ──────────► app/routes/auth.py └── login() POST /api/auth/login └── register() POST /api/auth/register
src/app/campaigns/page.tsx ─────► app/routes/campaigns.py └── getCampaigns() GET /api/campaigns └── createCampaign() POST /api/campaigns
KEY_FILES.md格式
# 按上下文分类的关键文件
## 上下文:前端API集成
**何时**:在前端修改API调用、响应处理或API类型时
加载这些文件(~8K令牌):
apps/web/src/lib/api/client.ts # API客户端实现 apps/web/src/types/api.d.ts # 前端API类型 apps/api/openapi.json # 完整的API规范(或总结) packages/shared-types/src/index.ts # 共享类型定义
## 上下文:后端端点开发
**何时**:添加/修改API端点
加载这些文件(~12K令牌):
apps/api/app/routes/ # 现有路由模式 apps/api/app/schemas/ # Pydantic模型(相关领域) apps/api/app/dependencies/ # 认证,数据库依赖 packages/db/schema/ # 相关表定义
## 上下文:数据库更改
**何时**:架构修改,迁移,查询
加载这些文件(~6K令牌):
packages/db/schema/ # 所有表定义 packages/db/migrations/ # 最后5个迁移 apps/api/app/models/ # ORM模型使用
## 上下文:共享类型
**何时**:修改跨模块使用的接口
加载这些文件(~4K令牌):
packages/shared-types/src/ # 类型源文件 apps/web/src/types/api.d.ts # 消费者(前端) apps/api/app/schemas/ # 源(后端)
## 上下文:认证
**何时**:认证流程,会话,令牌
加载这些文件(~5K令牌):
apps/api/app/routes/auth.py # 认证端点 apps/api/app/dependencies/auth.py # 认证中间件 apps/web/src/lib/auth/ # 前端认证处理 packages/shared-types/src/auth.ts # 认证类型
## 按需加载触发器
| Claude检测到... | 加载额外的 |
|-------------------|-------------------|
| "检查API契约" | 完整的OpenAPI规范 |
| 从另一个模块导入 | 该模块的导出 |
| 数据库查询模式 | 完整的架构定义 |
| 其他模块的测试失败 | 该模块的测试文件 |
| "破坏性更改" | 契约的双方 |
CROSS_REPO_INDEX.md格式
# 跨仓库能力索引
生成:2026-01-20T14:32:00Z
## 按领域分类的能力
### 认证
| 能力 | 位置 | 模块 | 类型 |
|------------|----------|--------|------|
| 登录用户 | POST /api/auth/login | apps/api | 端点 |
| 注册用户 | POST /api/auth/register | apps/api | 端点 |
| 刷新令牌 | POST /api/auth/refresh | apps/api | 端点 |
| 认证上下文 | src/contexts/AuthContext.tsx | apps/web | 组件 |
| 认证钩子 | src/hooks/useAuth.ts | apps/web | 钩子 |
| 用户类型 | src/auth.ts | shared-types | 类型 |
| 会话类型 | src/auth.ts | shared-types | 类型 |
### 活动
| 能力 | 位置 | 模块 | 类型 |
|------------|----------|--------|------|
| 列出活动 | GET /api/campaigns | apps/api | 端点 |
| 创建活动 | POST /api/campaigns | apps/api | 端点 |
| 活动CRUD | app/routes/campaigns.py | apps/api | 路由器 |
| 活动表单 | src/components/CampaignForm.tsx | apps/web | 组件 |
| 活动类型 | src/campaign.ts | shared-types | 类型 |
| 活动表 | schema/campaigns.ts | packages/db | 表 |
### 分析
| 能力 | 位置 | 模块 | 类型 |
|------------|----------|--------|------|
| 仪表板数据 | GET /api/analytics/dashboard | apps/api | 端点 |
| 时间序列 | GET /api/analytics/timeseries | apps/api | 端点 |
| 分析钩子 | src/hooks/useAnalytics.ts | apps/web | 钩子 |
| 图表组件 | src/components/charts/ | apps/web | 组件 |
## 搜索索引
在实现新功能之前,请在此索引中搜索:
Q: “如何获取当前用户?” A: 使用apps/web/src/hooks/useAuth.ts中的useAuth()钩子 或GET /api/users/me端点从apps/api
Q: “活动类型在哪里定义?” A: 源真相:packages/shared-types/src/campaign.ts 后端架构:apps/api/app/schemas/campaign.py 前端类型:apps/web/src/types/api.d.ts(生成)
Q: “如何添加新的API端点?” A: 模式在apps/api/app/routes/campaigns.py中 在apps/api/app/routes/init.py中注册 添加类型到packages/shared-types 再生前端类型
令牌预算管理
上下文限制
┌─────────────────────────────────────────────────────────────────┐
│ 令牌预算分配 │
├─────────────────────────────────────────────────────────────────┤
│ 总上下文:~200K令牌 │
│ 保留用于输出:~50K令牌 │
│ 工作预算:~150K令牌 │
├─────────────────────────────────────────────────────────────────┤
│ P0(必须有): 50K │ 当前模块(全部) │
│ P1(应该有): 40K │ 直接相关模块(总结) │
│ P2(最好有): 30K │ 契约+共享类型 │
│ P3(如果有空间): 20K │ 决策,待办事项,历史 │
│ 缓冲区: 10K │ 会话期间动态加载 │
└─────────────────────────────────────────────────────────────────┘
自动总结
当加载跨模块上下文时,进行总结:
| 内容类型 | 全部加载阈值 | 总结策略 |
|---|---|---|
| OpenAPI规范 | < 50个端点 | 端点+关键类型仅 |
| 类型文件 | < 30个类型 | 仅导出类型 |
| 路由文件 | < 200行 | 签名+文档字符串 |
| 配置文件 | < 50行 | 仅键(无值/机密) |
| 测试文件 | 从不全部 | 仅在明确请求时 |
上下文加载策略
┌─────────────────────────────────────────────────────────────────┐
│ 上下文加载层次结构 │
├─────────────────────────────────────────────────────────────────┤
│ 第1级:始终加载(~5K令牌) │
│ ├── TOPOLOGY.md(工作区结构) │
│ ├── CONTRACTS.md(API摘要) │
│ └── CROSS_REPO_INDEX.md(能力搜索) │
│ │
│ 第2级:根据当前文件加载(~15K令牌) │
│ ├── KEY_FILES.md当前上下文的建议 │
│ ├── 相关模块摘要 │
│ └── 相关类型定义 │
│ │
│ 第3级:按需扩展(可变) │
│ ├── 全部OpenAPI规范(当"检查API契约") │
│ ├── 全部类型文件(当修改接口) │
│ └── 其他模块的全部文件(当跨仓库更改) │
└─────────────────────────────────────────────────────────────────┘
多仓库文件访问
对于多仓库工作区(单独.git目录):
选项1:兄弟目录约定(推荐)
~/code/
├── myapp-frontend/ # git仓库
├── myapp-backend/ # git仓库
├── myapp-shared/ # git仓库
└── .workspace/ # 工作区配置(可选)
└── myapp.yaml
Claude通过相对路径访问:../myapp-backend/
选项2:工作区符号链接
# 在前端仓库中
mkdir -p .workspace/repos
ln -s ../../myapp-backend .workspace/repos/backend
ln -s ../../myapp-shared .workspace/repos/shared
选项3:Git子模块
# 将相关仓库添加为子模块(只读)
git submodule add --depth 1 ../myapp-shared .workspace/shared
文件访问规则
## 多仓库访问协议
访问另一个仓库的文件时:
1. 使用工作区根目录的相对路径
2. 只读访问(不要修改其他仓库)
3. 在_project_specs/workspace/cache/中本地缓存契约文件
4. 在decisions.md中记录跨仓库读取
在进行跨仓库更改之前:
1. 在两个仓库的decisions.md中记录更改
2. 在两个仓库中创建链接的待办事项
3. 按依赖顺序实现(共享→后端→前端)
跨仓库更改检测
当Claude检测到影响其他模块的更改时:
┌─────────────────────────────────────────────────────────────────┐
│ ⚠️ 跨仓库更改检测到 │
├─────────────────────────────────────────────────────────────────┤
│ 此更改影响:apps/api │
│ 特别是:端点POST /api/campaigns期望新字段 │
│ │
│ 影响分析: │
│ ├── apps/web/src/lib/api/client.ts - 需要更新 │
│ ├── packages/shared-types/src/campaign.ts - 需要新字段 │
│ └── apps/api/app/schemas/campaign.py - 变更源 │
│ │
│ 推荐顺序: │
│ 1. 首先更新packages/shared-types(源真相) │
│ 2. 更新apps/api架构 │
│ 3. 再生前端类型 │
│ 4. 更新apps/web API客户端 │
│ 5. 运行/sync-contracts │
│ │
│ [按指导进行] [加载全部上下文] [取消] │
└─────────────────────────────────────────────────────────────────┘
更改影响模式
| 更改类型 | 影响 | 行动 |
|---|---|---|
| 新API端点 | 前端客户端,类型 | 添加到两者,同步契约 |
| 修改响应 | 前端类型,测试 | 再生类型,更新测试 |
| 新必填字段 | 所有消费者 | 破坏性更改协议 |
| 重命名字段 | 所有消费者 | 迁移+弃用 |
| 新共享类型 | 下次使用的消费者 | 从shared-types导出 |
| 架构迁移 | API模型,查询 | 运行迁移,验证查询 |
契约新鲜度系统
陈旧性检测
# .contract-sources文件(自动生成)
# 定义契约的文件 - 监控更改
# OpenAPI规范
apps/api/openapi.json
apps/api/docs/openapi.yaml
# 类型定义
packages/shared-types/src/index.ts
packages/shared-types/src/api.ts
# Pydantic架构
apps/api/app/schemas/*.py
# 数据库架构
packages/db/schema/*.ts
新鲜度等级
| 等级 | 触发器 | 行动 | 时间 | 阻塞 |
|---|---|---|---|---|
| 1 | 会话开始 | 陈旧性检查 | ~5s | 否 |
| 2 | 提交后 | 如果契约更改则自动同步 | ~15s | 否 |
| 3 | 推送前 | 验证门 | ~10s | 是(可绕过) |
| 4 | PR打开 | CI验证 | ~30s | 是 |
| 5 | 每周cron | 完整重新分析 | ~2分钟 | 否 |
新鲜度指标
## 契约状态(显示在CONTRACTS.md标题中)
上次完整分析:2026-01-18T10:00:00Z
上次同步:2026-01-20T14:32:00Z
陈旧性:🟢 新鲜(2小时前同步)
## 置信度级别
🟢 新鲜 - 24小时内同步,源未更改
🟡 陈旧 - 自上次同步以来源已更改
🔴 过时 - 上次分析超过7天
⚠️ 漂移 - 验证发现不一致
与现有技能集成
与existing-repo.md
workspace.md调用每个模块的existing-repo.md分析:
## 模块分析委托
对于工作区中的每个模块:
1. 在该模块上运行现有仓库分析
2. 提取:技术栈,约定,护栏状态
3. 聚合到TOPOLOGY.md
4. 不要重复 - 引用existing-repo输出
与session-management.md
## 会话状态集成
工作区上下文文件是会话状态的一部分:
- TOPOLOGY.md → 结构上下文(很少更改)
- CONTRACTS.md → API上下文(每次会话检查新鲜度)
- KEY_FILES.md → 加载指导(静态引用)
会话开始时:
1. 将_project_specs/workspace/*.md加载到上下文
2. 检查契约新鲜度
3. 如果需要同步,则提供建议
与code-review.md
## 跨仓库审查检查
审查触及契约的代码时:
1. 检查更改是否影响其他模块
2. 验证契约一致性
3. 如果CONTRACTS.md需要更新,则标记
4. 如果有破坏性更改,则警告
添加到审查输出:
### 🔗 跨仓库影响
- [ ] 此更改影响:apps/web(API客户端)
- [ ] 契约更新需要:是
- [ ] 破坏性更改:否
命令
/analyze-workspace
完整工作区分析 - 在首次设置或重大更改时运行。
有关完整规范,请参阅commands/analyze-workspace.md。
/sync-contracts
轻量级增量契约更新 - 频繁运行。
有关完整规范,请参阅commands/sync-contracts.md。
/workspace-status
快速状态检查:
📊 工作区状态:myapp
类型:单体仓库(Turborepo)
模块:4(2个应用程序,2个包)
契约:🟢 新鲜(2小时前同步)
令牌估计:45K / 150K预算
快速操作:
/sync-contracts - 更新契约
/analyze-workspace - 完全刷新
CI/CD集成
GitHub Actions:契约验证
# .github/workflows/contracts.yml
name: 契约验证
on:
pull_request:
paths:
- 'apps/api/**'
- 'packages/shared-types/**'
- 'packages/db/schema/**'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 检查契约新鲜度
run: |
CHANGED=$(git diff --name-only origin/main HEAD | \
grep -E "openapi|schema|types" || true)
if [ -n "$CHANGED" ]; then
echo "契约源已更改:"
echo "$CHANGED"
if ! git diff --name-only origin/main HEAD | grep -q "CONTRACTS.md"; then
echo "::error::契约源已更改但CONTRACTS.md未更新"
echo "合并前运行/sync-contracts"
exit 1
fi
fi
- name: 验证一致性
run: |
if [ -f "apps/api/openapi.json" ]; then
ENDPOINTS=$(jq -r '.paths | keys | length' apps/api/openapi.json)
DOCUMENTED=$(grep -c "^| /" _project_specs/workspace/CONTRACTS.md || echo 0)
if [ "$ENDPOINTS" != "$DOCUMENTED" ]; then
echo "::warning::端点计数不匹配"
fi
fi
提交前钩子
#!/bin/bash
# hooks/pre-commit-contracts
WORKSPACE_DIR="_project_specs/workspace"
[ ! -f "$WORKSPACE_DIR/.contract-sources" ] && exit 0
# 检查暂存文件是否包括契约源
STAGED=$(git diff --cached --name-only)
CONTRACT_SOURCES=$(cat "$WORKSPACE_DIR/.contract-sources")
for source in $CONTRACT_SOURCES; do
if echo "$STAGED" | grep -q "$source"; then
echo "📝 契约源暂存:$source"
echo "记得在推送前运行/sync-contracts"
fi
done
故障排除
“未检测到工作区”
# 检查工作区指标
ls -la package.json pnpm-workspace.yaml turbo.json nx.json 2>/dev/null
# 如果是多仓库,检查兄弟目录
ls -la ../
# 手动分类
/analyze-workspace --type monorepo
/analyze-workspace --type multi-repo --repos "../backend,../shared"
“契约同步失败”
# 检查契约源是否存在
cat _project_specs/workspace/.contract-sources
# 验证文件访问
for f in $(cat .contract-sources); do
ls -la "$f" 2>/dev/null || echo "缺失:$f"
done
# 强制完全刷新
/analyze-workspace --force
“令牌预算超出”
# 检查当前估计
/workspace-status
# 减少上下文加载
# 编辑KEY_FILES.md以优先
# 或一次只处理一个模块
“跨仓库访问被拒绝”
# 检查路径是否正确
ls ../backend/ # 或相关仓库的位置
# 如果需要,设置符号链接
mkdir -p .workspace/repos
ln -s ../../backend .workspace/repos/backend
# 或在工作区中配置
/analyze-workspace --repo-path backend=../myapp-backend