第 4 章:目录结构、全局配置与跨平台兼容
2026/9/11 22:04:30 网站建设 项目流程

前两章讲了骨架与零件:四阶段流水线、七角色博弈、十个核心概念。这一章,把镜头对准地基——Harness 工程在磁盘上的布局。每个文件该放哪、该被谁读、该解决什么问题,在目录层面就已定型。不懂目录,你就无法判断"哪个文件是权威、哪个文件会被机器校验、哪个文件改了会触发什么"。


4.1.harness/.claude/:两套目录,各司其事

打开 Harness 工程的根目录,你会看到两大配置目录并排:.harness/.claude/。这两个名字容易让人以为"它们是一回事",但它们的职责有严格分工:

  • .harness/——Harness 的"数据与机器":放状态、契约、知识、脚本。这是 Harness 框架自己管理的东西——系统能力真相(specs/)、经验库(memory/)、任务看板(tasks/)、角色契约(workflow/)、自动化脚本(scripts/)、脚手架模板(templates/)。.它回答"系统现在知道什么、机器接下来要做什么"。
  • .claude/——Claude Code 的"身份与行为":放角色定义、命令、规则、技能、钩子。这是 Claude Code 原生消费的配置——Agent 该如何行事(agents/)、用户如何触发(commands/)、不可碰的红线(rules/)、标准操作手册(skills/)、实时拦截(hooks/)。它回答"AI 是谁、它该怎么行动"。

一句话概括两者的分工:.harness/是"记忆与机器",.claude/是"身份与规则"。前者存"系统知道什么",后者存"AI 怎么做"。

下面这张目录树来自一个真实的 Harness 工程,我用它来实地讲解每个目录的职责:

请对照这张树,记住三个关键观察:

观察点一:目录结构本身就是四层元模型(第 3 章)的物理映射。你看——workflow/config.json是契约层,agents/commands/skills/是行为层,specs/memory/codebase-guide/是知识层,scripts/hooks/rules/tasks/是执行层。四层元模型不是抽象概念,你打开目录就能看到。理解了四层,你就知道任何一个文件该去哪、该怎么归类。

观察点二:.harness/agents/是指向.claude/agents/的符号链接。同一个角色定义只有一个权威源(在.claude/),.harness/agents/只是提供一条更符合"框架心智"的访问路径。这体现了单一真相源在文件系统层面的一种常见手法:用链接而不是副本——复制会制造双份真相,链接不会。

观察点三:deliverables/的"活目录 + 归档"设计。在途任务用deliverables/<task>/,归档后用_archive/<task>/,活目录定期清空、归档目录增量追加。这套设计我在第 10 章(Archive)会完整展开,这里你先种个印象:Harness 把"进行中"与"已沉淀"在磁盘上就分开了。

settings.json:Hook 是怎么被"注册"的

有一个文件值得单独看一眼——.claude/settings.json。它就是第 3 章讲的三个 Hook 的"注册表":Claude Code 通过它知道"哪个事件触发哪个脚本"。

{"hooks":{"PreToolUse":[{"matcher":"Edit|Write","hooks":[{"type":"command","command":"python3 .claude/hooks/pre_edit.py"}]}],"UserPromptSubmit":[{"matcher":"","hooks":[{"type":"command","command":"python3 .claude/hooks/pre_command.py"}]}],"PostToolUse":[{"matcher":"Agent","hooks":[{"type":"command","command":"python3 .claude/hooks/dev_gate.py"}]}]}}

注意三个 Hook 的触发设计,每个都精心选择了时机和匹配范围:

这就是"纵深防御"在配置层面的形态:同一个规则(如分支合规)不靠一个检查点守住,而是靠多个 Hook、多个时机独立 enforce。细节在第 9 章展开。


4.2config.json——全局兜底配置与"单一真相源"的入口

在 4.1 的目录树里,我特意给config.json标了 ★。它只有几行,却是整个 Harness 最容易被误用的地方——也是最容易被"硬编码"毁掉的地方。先看它的真实内容:

{"apply-mode":"review","mainline-branch":"dev","description":"Apply 流程模式: auto=CR 通过后自动进入 TE(默认); review=CR 通过后暂停,等待人工审查通过后再进入 TE。任务级可用 proposal.md 的 flow-mode 字段覆盖。mainline-branch: 子工程主线分支(集成/同步/归档合并目标),子工程 .harness/build.json 的 mainline-branch 字段可覆盖,默认 dev。"}

只有两个真正的配置项,我来逐一讲它们的设计意图:

mainline-branch:把"主线分支名"从代码里拔出来

想象一下没有这个配置的 Harness 会怎样:sync.py要同步到哪个分支?create_feat_branch.py从哪个分支建特性分支?archive.py要把 feat 分支合并到哪?verify.py检查"是否在集成分支"要看哪几个分支名?

所有这些脚本的答案,原本只能靠硬编码。而在一个演进中的工程里,"主线分支叫 dev 还是 develop 还是 release-2.x"是会变的。如果你把dev写死在 18 个脚本里,改一次主线分支名 = 改 18 处 + 祈祷没漏。

Harness 的做法是把这条信息收敛到一处config.json),并设计了一套三级覆盖优先级

  • 大多数子工程不配置 → 用根 config.json 的dev
  • 某个子工程特殊(比如单独维护的 legacy 仓库用release-x)→ 在自己 build.json 里覆盖;
  • 都没有 → 兜底默认dev

而所有脚本(sync / create_feat_branch / check_branch / verify / archive)都通过lib.py里唯一的get_mainline_branch(service_path)函数读取这个值——全世界只有一个地方知道"主线分支叫什么"。这就是单一真相源:不是"不要硬编码",而是"把硬编码收敛到一个地方,再让所有人读它"。

apply-mode:把"流程行为"收敛到配置文件

第二个配置项apply-mode控制的是 Apply 阶段的流程行为(这个我在第 2 章 2.4 已经接触过):

apply-mode: auto → CR 审查通过后,自动进入 TE apply-mode: review → CR 审查通过后,暂停,等待人工审查 code-review.md,人确认后再进 TE

注意它的优先级设计(与 mainline-branch 同思路):

proposal.md 的 flow-mode(任务级) > .harness/config.json 的 apply-mode(全局) > 默认 auto

这样设计的好处:"流程行为"这个本该人人皆知、处处一致的东西,有了一个权威来源。单任务特例(proposal 里写flow-mode: review)不会破坏全局;全局改档(config.json 改auto)不用逐个任务改。配置项的每一层决策,都发生在离决策最近的地方——这是配置设计的黄金法则。

一句话理解 config.json

config.json每个被放进这里的配置项,都回答同一个问题:“这个值,全系统都应该一致地知道,但它不藏在任何一个具体脚本里。” 当你发现某个值被 3 个以上脚本硬编码时,它就该被提升到 config.json。


4.3 跨平台兼容层:macOS 与 Windows 的"双系统纪律"

最后一块地基是跨平台兼容。你可能觉得这没什么好讲的——“脚本写好不就行了?”——但 Harness 面对的是一个极其刺眼的现实:团队里一半人用 macOS,一半人用 Windows。

  • macOS 开发者习惯了bash -lcwhichexport PATH=eval "$(...)"
  • Windows 开发者面对的是cmdwhereset、PowerShell 的$env:
  • 路径分隔符一个/一个\;行尾一个 LF 一个 CRLF;删文件一个rm -rf一个rmdir /s /q

如果 Harness 的脚本是单平台写的,团队里必然有一半人每天的开工仪式是"先折腾环境"。Harness 用一整套设计把这件事制度化,核心是os-compatibility.md规则文件 +check_harness.py的跨平台扫描

os-compatibility.md:写成"法律"的兼容纪律

Harness 把跨平台要求写成了强制规则(.claude/rules/os-compatibility.md)。注意它的措辞——不是"尽量兼容",而是"违反 → check_harness.py 跨平台扫描 FAIL"。我摘几条最硬的规定:

条款禁止强制
Python 子进程调用硬编码"python3"/"python"作为 programsys.executable
命令执行os.systemshell=Truesubprocess/lib.run(list 形式)
文件删除rm -rf/rm -r/rmdirPython 内shutil.rmtree/Path.unlink
脚本形态.harness/下新增.sh(除 git-hooks/)跨平台脚本一律 Python
行尾CRLF框架脚本与 git hook 必须 LF;hook shebang#!/bin/sh+ python3/python 兜底

为什么这些条目能上"法律"?因为每一条都对应着一个真实事故:硬编码python3在 Windows 上不存在(是python.exe);os.system无法跨平台;rm -rf在 Windows 上会直接报错;CRLF 行尾会让 shebang 失效。这些事故足够痛,才值得写成 FAIL 级规则。

check_harness.py的跨平台扫描:机器来执法

光有规则文件不够——AI 可能看不见规则,人可能忘执行它。所以check_harness.py全量校验里内置了一个「🖥️ 跨平台兼容」检查段,用正则扫描的方式自动执法。让我把真实工程的执行结果展示给你看:

🛡️ Harness 系统完整性检查 ============================ ... 🔍 三边一致性校验... ✅ contract.json role [PM] ↔ project-manager.md ✅ contract.json role [BA] ↔ business-analyst.md ✅ contract.json role [SA] ↔ solution-architect.md ✅ contract.json role [RR] ↔ readiness-reviewer.md ✅ contract.json role [Dev] ↔ developer.md ✅ contract.json role [CR] ↔ code-reviewer.md ✅ contract.json role [TE] ↔ test-engineer.md 🖥️ 跨平台兼容检查(macOS + Windows) ✅ 跨平台扫描:0 ERROR / 0 WARNING(通过) ============================================ PASS: 66 FAIL: 0 ✅ 框架完整性检查全部通过

这条规则是双重的:它强制框架本身跨平台(scripts/hooks 的代码风格),也强制"写文档的人别忘了给 Windows 留口子"——例如os-compatibility.md明确要求:命令文档里若含rm -rf等 POSIX 专属命令,必须注明 Windows 等价写法(rmdir /s /q/Remove-Item -Recurse -Force)。文档也是兼容层的一部分。

env_auto.py:跨平台兼容的"实战代表"

跨平台纪律不是为兼容而兼容——它服务于一个真实的强需求:零配置环境自动识别(第 7 章会完整展开)。这里我先看它跨平台的一面。env_auto.py站在每个子工程面前,自动回答三个问题:这是什么工程?需要什么版本?这台机器上哪个运行时满足?真实输出长这样(macOS):

$ python3 .harness/scripts/env_auto.py services/backend ✅ Java 1.8 → /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home ✅ Node >=14 → /opt/homebrew/bin backend: Java 1.8、Node >=14 — ✅ 环境就绪 [format=posix] export JAVA_HOME='/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home' export PATH='/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/bin:$PATH' export PATH='/opt/homebrew/bin:$PATH'

services/frontend就更薄——一个纯前端工程只需要 Node:

$ python3 .harness/scripts/env_auto.py services/frontend ✅ Node >=14 → /opt/homebrew/bin frontend: Node >=14 — ✅ 环境就绪 [format=posix] export PATH='/opt/homebrew/bin:$PATH'

注意输出的最后一行:export语句本身,就是跨平台兼容的产物。export是 POSIX 语法(macOS/Linux),而 Windows 上是另一套。env_auto.py支持三种输出格式,按平台自动切换:

同样一份探测逻辑,三种 shell 各出一套加载语法——跨平台的本质不是写一套"哪里都能跑"的代码,而是把平台差异隔离在输出层,让上层逻辑完全一致。这就是为什么os-compatibility.md要求"新增 shell 输出型脚本时,参考 env_auto.py 的detect_format/fmt_exports实现"——它成了跨平台输出层的标杆实现。

跨平台兼容的三层防线总结

这三层分别解决了"意识的约束"、“执行的约束”、“设计的约束”——规则管想法、扫描管动作、模式管结构。


小结

这一章,我带你看了 Harness 的地基:

  • 两套目录——.harness/存"系统知道什么"(数据+机器),.claude/存"AI 怎么做"(身份+规则);目录结构本身就是四层元模型的物理映射;
  • config.json——把"主线分支名""流程模式"这类全局共识收敛到一处,用三级覆盖优先级让"单一真相源"落地;
  • 跨平台兼容层——os-compatibility.md规则 +check_harness.py机器扫描 +env_auto.py输出层模式,三层防线让 macOS/Windows 双平台团队共享同一套流程;
  • settings.json / templates/ git-hooks/——Hook 注册表、脚手架弹药库、提交门禁入口,各司其职。

下一章,走进这层地基里最重要的一根承重柱——Spec 系统:为什么系统能力需要一个"单一真相源"?GWT 格式为什么是"防 AI 作弊的物理锁"?跨域机制 FLOW 与 CSTR 如何不复制行为地编排全局?翻到第 5 章。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询