mcpField
H
harness-engineering

harness-engineering

github.com/charlesanimAgent 工作流2043 次安装33 周前更新
代码仓库

关于 harness-engineering

此 Skill 用于将代码仓库配置为面向 Agent 的工程环境,涵盖导航文档、架构规则、测试和 CI 强制检查。它先分析实际代码结构,再据此制定方案,而非套用固定目录。

主要功能

  1. 01检查仓库技术栈与架构
  2. 02创建 AGENTS.md 导航文档
  3. 03记录分层规则与编码原则
  4. 04设置边界测试和 Linter 规则
  5. 05添加 CI 与定期清理检查

适用场景

  1. 01为自主编码 Agent 准备代码仓库
  2. 02通过机制强制执行架构约束
  3. 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 协同安全运行。核心原则:

  1. 工程师转变为环境设计者——定义约束,而非实现方式
  2. 给 Agent 一张地图,而非一部百科全书——通过 AGENTS.md 渐进式披露信息
  3. Agent 看不到的东西就不存在——所有知识都放在代码仓库中
  4. 通过机械手段强制执行架构——依靠代码检查工具和测试,而非 Markdown 说明
  5. 选择成熟可靠的技术——采用可组合、稳定且经过充分训练的 API
  6. 熵管理就是垃圾回收——安排 Agent 定期清理
  7. 吞吐量会改变合并理念——尽量减少阻塞性门槛
  8. 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

这是层级结构的权威参考文档。包括:

  1. 层级图——使用 ASCII 图展示允许的依赖方向
  2. 硬性规则——违反后会导致 CI 失败的规则
  3. 各层包含的内容——职责和关键文件
  4. 修复指南——针对每种常见违规,说明修复方法

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/VueVitestnpm i -D vitest @testing-library/react jsdom
Next.jsVitest 或 Jestnpm i -D vitest @testing-library/react jsdom
Node.js/ExpressVitest 或 Jestnpm i -D vitest
Pythonpytestpip install pytest pytest-cov
Gogo test(内置)无需安装
Rustcargo test(内置)无需安装
Ruby/RailsRSpec 或 Minitestgem install rspec
3b. 创建测试配置

设置测试运行器,包括:

  • 与主构建配置一致的路径别名解析
  • 覆盖率报告
  • 测试文件模式
  • 常用测试工具的设置文件
3c. 创建测试工具

创建通用测试辅助工具:

  • Mock 工厂——用于数据库客户端、API 客户端和身份验证上下文
  • 渲染辅助工具——(前端)使用 Provider 封装组件,以便进行测试
  • Fixture 工厂——生成测试数据
3d. 创建架构边界测试

这是机械化强制执行——也是最关键的测试。它会:

  1. 扫描项目中的所有源文件
  2. 解析 import/require 语句
  3. 确定每个文件所属的层
  4. 验证导入是否遵循层级规则
  5. 失败时输出清晰、可操作的错误消息

关键设计决策:

  • 使用语言自身的文件 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),扫描常见的黄金原则违规情况。每个脚本都应:

  1. 扫描源代码目录
  2. 查找特定反模式
  3. 以 file:line 格式报告违规情况
  4. 无违规时退出码为 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”时,按以下顺序执行:

  1. 阶段 0——探索(务必首先执行,绝不跳过)
  2. 阶段 1——AGENTS.md
  3. 阶段 2——文档结构 + LAYERS.md + 黄金原则
  4. 阶段 3——测试基础设施 + 架构边界测试
  5. 阶段 4——Linter 边界强制规则
  6. 阶段 5——CI 流水线
  7. 阶段 6——垃圾回收脚本 + 工作流
  8. 阶段 7——提交前钩子

开始前询问用户:“要设置所有阶段,还是只设置指定阶段?”

如果用户提出要求,请在新的 git worktree 中使用功能分支(feat/harness-engineering)开展工作。

重要规则

  1. 绝不硬编码项目专属细节。 此技能适用于任何仓库。 探索技术栈,不要想当然。
  2. 先读后写。 生成新文件前务必先读取现有文件。 遵循仓库现有的代码风格。
  3. 使用 git mv 重组文档。 保留 git 历史记录。
  4. 每条错误消息都是 Agent 上下文。 修复说明应放在错误输出中,而不只是写在文档里。
  5. 架构测试是一种棘轮机制。 已知违规列表只能缩减;未经明确审查,不得增加。
  6. 不要破坏现有行为。 如果代码库中存在已有违规,新的 lint 规则应发出警告,而非报错。
  7. 测试你的工作。 设置完成后运行测试套件、linter 和 GC 脚本,验证一切正常。

评论

支持 Markdown