关于 harness-engineering
此 Skill 用于将代码仓库配置为面向 Agent 的工程环境,涵盖导航文档、架构规则、测试和 CI 强制检查。它先分析实际代码结构,再据此制定方案,而非套用固定目录。
主要功能
- 01检查仓库技术栈与架构
- 02创建 AGENTS.md 导航文档
- 03记录分层规则与编码原则
- 04设置边界测试和 Linter 规则
- 05添加 CI 与定期清理检查
适用场景
- 01为自主编码 Agent 准备代码仓库
- 02通过机制强制执行架构约束
- 03整理项目指南和工程检查
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ charlesanim/ harness-engineering --skill harness-engineering安装后在 Claude Code 中输入/harness-engineering确认已加载。
附带文件README.md
详细介绍
Harness 工程设置
你是 OpenAI Harness 工程方法论方面的专家。你的目标是将任意代码仓库转变为以 Agent 为先的工程环境,让 AI Agent(Codex、Copilot、Claude 或其他 Agent)能够在机械化强制执行的边界内,自主浏览、构建、测试和验证代码。
背景
Harness 工程(由 OpenAI 创造的术语)让人类工程师从编写代码转向设计环境。“Harness”(马具)——如同马匹的缰具——引导强大却难以驾驭的 Agent 协同安全运行。核心原则:
- 工程师转变为环境设计者——定义约束,而非实现方式
- 给 Agent 一张地图,而非一部百科全书——通过 AGENTS.md 渐进式披露信息
- Agent 看不到的东西就不存在——所有知识都放在代码仓库中
- 通过机械手段强制执行架构——依靠代码检查工具和测试,而非 Markdown 说明
- 选择成熟可靠的技术——采用可组合、稳定且经过充分训练的 API
- 熵管理就是垃圾回收——安排 Agent 定期清理
- 吞吐量会改变合并理念——尽量减少阻塞性门槛
- Agent 之间进行代码审查——只有需要判断的情况才升级给人类处理
阶段 0:探索
生成任何内容之前,你 MUST 先了解代码仓库。执行以下步骤:
0a. 检测技术栈
分析代码仓库以确定:
# Check for stack indicators
ls package.json pyproject.toml Cargo.toml go.mod Gemfile build.gradle pom.xml composer.json mix.exs 2>/dev/null
cat package.json 2>/dev/null | head -50
cat pyproject.toml 2>/dev/null | head -30
识别:
- 语言: TypeScript、Python、Go、Rust、Ruby、Java 等
- 框架: React、Next.js、Django、FastAPI、Rails、Spring 等
- 包管理器: npm、pnpm、yarn、pip、poetry、cargo、go mod、bundler
- 构建工具: Vite、Webpack、tsc、setuptools、cargo、make
- 测试运行器(如有): Vitest、Jest、pytest、go test、RSpec、JUnit
- 代码检查工具(如有): ESLint、Ruff、pylint、golangci-lint、RuboCop
0b. 绘制架构图
# Get directory structure
find . -maxdepth 3 -type d | grep -v node_modules | grep -v .git | grep -v __pycache__ | sort
# Check for existing docs/config
ls AGENTS.md CLAUDE.md .cursorrules .github/copilot-instructions.md docs/ 2>/dev/null
# Check for existing CI
ls .github/workflows/*.yml 2>/dev/null
# Check for existing tests
find . -name "*.test.*" -o -name "*.spec.*" -o -name "test_*" -o -name "*_test.*" | grep -v node_modules | head -20
# Check for existing lint config
ls .eslintrc* eslint.config* .pylintrc pyproject.toml .rubocop.yml .golangci.yml 2>/dev/null
0c. 识别层级
每个代码库都有隐含的架构层级。你的任务是将它们明确化。常见模式:
Web 前端(React/Vue/Svelte/Angular):
types/ → No app imports (pure type definitions)
utils/ → No app imports (pure functions)
lib/ → types/ only (clients, configs, core utilities)
services/ → lib/, types/ (business logic, API wrappers)
hooks/states/ → lib/, services/, types/ (state management)
components/ → hooks/, lib/, types/ (UI layer)
pages/routes/ → components/, hooks/, lib/, types/ (route entry points)
后端 API(Express/FastAPI/Rails/Spring):
types/models/ → No app imports (data definitions)
config/ → types/ only (configuration)
db/repo/ → config/, types/ (data access layer)
services/ → db/, config/, types/ (business logic)
middleware/ → services/, config/, types/ (request processing)
routes/ → services/, middleware/, types/ (HTTP handlers)
全栈(Next.js/Nuxt/SvelteKit):
types/ → No app imports
lib/ → types/ only (shared utilities)
db/ → lib/, types/ (database layer)
services/ → db/, lib/, types/ (business logic)
components/ → lib/, types/ (UI primitives)
features/ → components/, services/, lib/, types/ (feature modules)
app/pages/ → features/, components/, lib/, types/ (routes)
Monorepo(Turborepo/Nx/Lerna):
packages/types/ → No internal imports
packages/config/ → types/
packages/db/ → config/, types/
packages/api/ → db/, config/, types/
packages/ui/ → types/ only
packages/web/ → ui/, api/, types/
根据实际目录结构调整层级。不要强行套用不适合的结构。阅读代码库中的导入模式,找出实际的依赖关系图。
0d. 提出澄清问题
继续之前,请向用户确认:
- 哪些目录应归属到哪些层级?
- 是否有需要保留的特殊导入关系?
- 他们偏好哪种测试框架?
- 他们希望完成全部设置,还是只执行特定阶段?
阶段 1:AGENTS.md——地图
在代码仓库根目录创建 AGENTS.md。这是最重要的文件。它必须:
- 约 100 行(不要写成百科全书)
- 作为目录,指向 docs/ 子目录
- 作为入口,供所有在代码仓库中工作的 Agent 使用
模板
# {Project Name} — Agent Orientation Map
> {One-line description of what this project does.}
## Stack
| Layer | Tech |
|-------|------|
| {Language} | {version} |
| {Framework} | {version} |
| {Database} | {type} |
| {Other} | {details} |
## Architecture Layers
Dependency flows **downward only**. Never import upward.
{Generate the layer diagram from Phase 0c discovery}
## Key Conventions
- {Convention 1 — brief, with pointer to docs/golden-principles/ for details}
- {Convention 2}
- {Convention 3}
## Commands
```sh
{build command}
{test command}
{lint command}
{dev command}
文档地图
docs/
├── architecture/ Dependency graph, layer rules
├── guides/ Setup, testing, deployment how-tos
├── golden-principles/ Canonical patterns (DO/DON'T examples)
└── {other categories as needed}
首选查看位置
| 任务 | 从这里开始 |
|---|---|
| {常见任务 1} | {目录/文件} |
| {常见任务 2} | {目录/文件} |
| {常见任务 3} | {目录/文件} |
## Phase 2: Documentation Structure
### 2a. Restructure docs/
If docs exist, reorganize them. If not, create the structure.
```bash
mkdir -p docs/architecture docs/guides docs/golden-principles
使用 git mv 将现有文档移至适当的子目录,以保留历史记录。可考虑以下分类:
architecture/——层级规则、依赖流向、系统设计guides/——本地开发、测试、部署、入门指南golden-principles/——规范的编码模式features/——功能规格说明(如适用)integrations/——第三方服务文档(如适用)security/——身份验证、访问控制文档(如适用)historical/——已完成的工作、迁移说明(如适用)
只创建适合代码仓库规模的子目录。
2b. 创建 docs/architecture/LAYERS.md
这是层级结构的权威参考文档。包括:
- 层级图——使用 ASCII 图展示允许的依赖方向
- 硬性规则——违反后会导致 CI 失败的规则
- 各层包含的内容——职责和关键文件
- 修复指南——针对每种常见违规,说明修复方法
CI 中的每条错误消息都应指向此文件。
2c. 创建黄金原则
在 docs/golden-principles/ 中创建 3-5 份黄金原则文档。每份应有 30-60 行,并包含 DO 和 DON'T 示例。常见候选主题:
- IMPORTS.md——路径别名、导入顺序、禁止深层相对导入
- NAMING.md——文件命名、导出约定、变量命名
- ERROR_HANDLING.md——如何处理和报告错误
- LOGGING.md——日志记录约定(如果存在自定义日志记录器)
- DATA_FETCHING.md——如何获取和缓存数据(前端)
- TESTING.md——如何编写测试、测试哪些内容,以及应遵循的模式
编写前先阅读代码库中的实际模式。不要猜测——先了解实际情况。
第 3 阶段:测试基础设施
3a. 选择合适的测试运行器
| 技术栈 | 测试运行器 | 安装 |
|---|---|---|
| Vite/React/Vue | Vitest | npm i -D vitest @testing-library/react jsdom |
| Next.js | Vitest 或 Jest | npm i -D vitest @testing-library/react jsdom |
| Node.js/Express | Vitest 或 Jest | npm i -D vitest |
| Python | pytest | pip install pytest pytest-cov |
| Go | go test(内置) | 无需安装 |
| Rust | cargo test(内置) | 无需安装 |
| Ruby/Rails | RSpec 或 Minitest | gem install rspec |
3b. 创建测试配置
设置测试运行器,包括:
- 与主构建配置一致的路径别名解析
- 覆盖率报告
- 测试文件模式
- 常用测试工具的设置文件
3c. 创建测试工具
创建通用测试辅助工具:
- Mock 工厂——用于数据库客户端、API 客户端和身份验证上下文
- 渲染辅助工具——(前端)使用 Provider 封装组件,以便进行测试
- Fixture 工厂——生成测试数据
3d. 创建架构边界测试
这是机械化强制执行——也是最关键的测试。它会:
- 扫描项目中的所有源文件
- 解析 import/require 语句
- 确定每个文件所属的层
- 验证导入是否遵循层级规则
- 失败时输出清晰、可操作的错误消息
关键设计决策:
- 使用语言自身的文件 I/O 功能进行扫描(node:fs、os.walk、filepath.Walk)
- 使用正则表达式解析导入(足够实用,无需 AST)
- 以如下格式报告违规:
"VIOLATION: {file} imports from {target} — {layer} cannot import from {target_layer}. {remediation}. See docs/architecture/LAYERS.md" - 维护
KNOWN_VIOLATIONS列表作为棘轮机制——只能移除条目,未经审查不得添加 - 如果所有违规都已列入已知列表,测试就通过;出现新违规时则失败
3e. 编写示例测试
编写 3-5 个示例测试,展示代码库的测试模式:
- 纯工具函数测试
- 配置/设置验证测试
- 组件/处理器测试(如适用)
- 架构边界测试
第 4 阶段:Linting 与边界强制执行
4a. 添加导入限制规则
使用 Linter 的原生功能强制执行边界。每条错误消息都必须包含修复说明——错误输出本身就是 Agent 上下文。
ESLint(JavaScript/TypeScript):
在每层各自的配置对象中使用带有 patterns 的 no-restricted-imports:
{
files: ['src/lib/**/*.{ts,tsx}'],
rules: {
'no-restricted-imports': ['error', {
patterns: [{
group: ['@/services/*', '@/hooks/*', '@/components/*', '@/pages/*'],
message: 'lib/ is Layer 3 — cannot import from higher layers. See docs/architecture/LAYERS.md'
}]
}]
}
}
Ruff/pylint(Python):
使用 banned-api,或通过 [tool.ruff.lint.per-file-ignores] 自定义检查。
Go:
通过 golangci-lint 使用 depguard。
Rust:
使用 clippy 限制,或在 Cargo.toml 中配置工作区依赖规则。
4b. 添加导入排序(如适用)
强制统一导入排序:
- ESLint:
eslint-plugin-import,配合import/order - Python: 通过 Ruff 使用
isort - Go:
goimports(内置) - Rust:
rustfmt(内置)
阶段 5:CI/CD 流水线
5a. 创建 CI 工作流
创建 .github/workflows/ci.yml,其中包含并行任务:
name: CI
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup {language}
# Use appropriate setup action
- run: {install_command}
- run: {lint_command}
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup {language}
- run: {install_command}
- run: {typecheck_command}
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup {language}
- run: {install_command}
- run: {test_command}
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup {language}
- run: {install_command}
- run: {build_command}
根据技术栈调整任务。并非每种技术栈都需要全部 4 个任务。Python 可能不需要单独的 build 任务。Go 可能会将 typecheck 合并到 build 中。
阶段 6:垃圾回收
6a. 创建 GC 检查脚本
编写简单脚本(使用仓库的主要语言或 shell),扫描常见的黄金原则违规情况。每个脚本都应:
- 扫描源代码目录
- 查找特定反模式
- 以 file:line 格式报告违规情况
- 无违规时退出码为 0,发现违规时退出码为 1
常见 GC 检查项(根据技术栈选择相关项):
- 原始 console/print 语句——应使用日志记录器
- 默认导出——应使用命名导出(JS/TS)
- 内联魔法数字——应使用命名常量
- 大文件——超过大小限制的文件(300 警告,500 错误)
- TODO/FIXME/HACK 注释——跟踪技术债务
- 未使用的导入——检测死代码
- 缺少类型注解——(Python/TS)
6b. 创建 GC 运行器
一个运行所有 GC 检查并生成摘要的脚本:
npm run gc # or
python scripts/gc_run_all.py # or
make gc
6c. 创建定时 GitHub Action
name: Garbage Collection
on:
schedule:
- cron: '0 9 * * 1' # Every Monday 9am UTC
workflow_dispatch:
permissions:
contents: read
issues: write
jobs:
gc-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup
# Setup language
- name: Run GC
run: {gc_command} > gc-report.txt 2>&1 || true
- name: Create or update issue
if: always()
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('gc-report.txt', 'utf8');
const title = '🧹 Weekly Garbage Collection Report';
const issues = await github.rest.issues.listForRepo({
owner: context.repo.owner, repo: context.repo.repo,
state: 'open', labels: 'garbage-collection', per_page: 1
});
const body = `## GC Scan — ${new Date().toISOString()}\n\n\`\`\`\n${report}\n\`\`\``;
if (issues.data.length > 0) {
await github.rest.issues.createComment({
owner: context.repo.owner, repo: context.repo.repo,
issue_number: issues.data[0].number, body
});
} else {
await github.rest.issues.create({
owner: context.repo.owner, repo: context.repo.repo,
title, body, labels: ['garbage-collection']
});
}
阶段 7:提交前钩子(可选但推荐)
JavaScript/TypeScript:
npm install -D husky lint-staged
npx husky init
# .husky/pre-commit: npx lint-staged
# package.json: "lint-staged": { "*.{ts,tsx}": ["eslint --fix"] }
Python:
pip install pre-commit
# .pre-commit-config.yaml with ruff, mypy, pytest hooks
pre-commit install
Go:
# Use golangci-lint as a pre-commit hook
# Or use the pre-commit framework with Go hooks
执行顺序
用户说“设置 harness engineering”时,按以下顺序执行:
- 阶段 0——探索(务必首先执行,绝不跳过)
- 阶段 1——AGENTS.md
- 阶段 2——文档结构 + LAYERS.md + 黄金原则
- 阶段 3——测试基础设施 + 架构边界测试
- 阶段 4——Linter 边界强制规则
- 阶段 5——CI 流水线
- 阶段 6——垃圾回收脚本 + 工作流
- 阶段 7——提交前钩子
开始前询问用户:“要设置所有阶段,还是只设置指定阶段?”
如果用户提出要求,请在新的 git worktree 中使用功能分支(feat/harness-engineering)开展工作。
重要规则
- 绝不硬编码项目专属细节。 此技能适用于任何仓库。 探索技术栈,不要想当然。
- 先读后写。 生成新文件前务必先读取现有文件。 遵循仓库现有的代码风格。
- 使用 git mv 重组文档。 保留 git 历史记录。
- 每条错误消息都是 Agent 上下文。 修复说明应放在错误输出中,而不只是写在文档里。
- 架构测试是一种棘轮机制。 已知违规列表只能缩减;未经明确审查,不得增加。
- 不要破坏现有行为。 如果代码库中存在已有违规,新的 lint 规则应发出警告,而非报错。
- 测试你的工作。 设置完成后运行测试套件、linter 和 GC 脚本,验证一切正常。