uni-harness 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -56,6 +56,22 @@ try:
56
56
  except Exception:
57
57
  pass
58
58
 
59
+ # (4) CLAUDE.md still references the pre-v0.2 checkpoint locations
60
+ # (the installer never edits the user-owned CLAUDE.md — Claude proposes
61
+ # the fix as a diff instead)
62
+ try:
63
+ with open(os.path.join(proj, "CLAUDE.md")) as f:
64
+ cm = f.read()
65
+ if ".harness/state" not in cm and ("progress.json" in cm or "plan.md" in cm):
66
+ parts.append(
67
+ "[harness] This project's CLAUDE.md references checkpoint files "
68
+ "(plan.md / progress.json / decisions.jsonl) at the project root, "
69
+ "but the harness now keeps them in .harness/state/. Propose a "
70
+ "small diff updating those path references in the Work Loop and "
71
+ "Checkpoints sections, and apply it only with the user's approval.")
72
+ except Exception:
73
+ pass
74
+
59
75
  # (2) accumulated failures in the last 7 days -> nudge toward /ratchet
60
76
  try:
61
77
  cutoff = datetime.datetime.now() - datetime.timedelta(days=7)
package/README.ja.md ADDED
@@ -0,0 +1,213 @@
1
+ # uni-harness
2
+
3
+ 🇺🇸 [English](README.md) | 🇰🇷 [한국어](README.ko.md) | 🇨🇳 [简体中文](README.zh-CN.md) | 🇯🇵 **日本語**
4
+
5
+ ![license](https://img.shields.io/badge/license-MIT-blue)
6
+ ![node](https://img.shields.io/badge/node-%E2%89%A516-brightgreen)
7
+ ![runtime](https://img.shields.io/badge/runtime-bash%20%2B%20python3%20stdlib-lightgrey)
8
+ ![for](https://img.shields.io/badge/for-Claude%20Code-d97757)
9
+
10
+ Claude Code 向けのエージェント・ハーネスキットです。コーディング
11
+ エージェントを、自動検証(センサー)、破壊的コマンドのブロック
12
+ (ガード)、チェックポイントによるセッション復旧、トリップワイヤー
13
+ 付きの全ツール呼び出しログ、そしてあらゆる失敗を恒久的な構造へと
14
+ 変えるラチェット・ワークフローで包み込みます。
15
+
16
+ > 公式: **Agent = Model + Harness.** 推論はモデルが担い、
17
+ > それ以外のすべて — ルール、センサー、ループ上限、メモリ、
18
+ > 可観測性 — をこのキットが担います。
19
+
20
+ ## インストール
21
+
22
+ ```bash
23
+ npx uni-harness init # プロジェクトルートで(または: init <パス>)
24
+ ```
25
+
26
+ その後プロジェクトで Claude Code を開くと — Claude がハーネスの
27
+ 未設定を検知し、**`/harness-init` の実行を自ら提案**します(自分で
28
+ 実行しても構いません)。リポジトリをスキャンしてビルド/テスト/リント
29
+ コマンドを検出し、**実際に実行して検証**した上で、承認を得て
30
+ `CLAUDE.md` と `.harness/commands.env` に書き込みます。このステップ
31
+ が終わるまで検証センサーは待機状態です。
32
+
33
+ その他のインストーラーコマンド:
34
+
35
+ ```bash
36
+ npx uni-harness update # キットの機構を更新(あなたのファイルには一切触れません)
37
+ npx uni-harness doctor # インストール状態を診断
38
+ npx uni-harness uninstall --yes # キットの機構を削除、あなたのファイルは保持
39
+ ```
40
+
41
+ 必要環境: bash、python3(標準ライブラリのみ — パッケージ不要)、
42
+ インストーラー自体に node ≥16。
43
+
44
+ **進行中のプロジェクトでも安全です。** `init` はあなたが所有する
45
+ ものを決して上書きしません: 既存の `CLAUDE.md` は保持され
46
+ (`/harness-init` がハーネス用セクションの追記を提案します)、既存の
47
+ `settings.json` のフックと権限は保持されたままキットのフックが
48
+ マージされ、`.gitignore` は置き換えではなく追記されます。`update` は
49
+ 未変更のキットファイルのみを更新します — カスタマイズしたものは
50
+ スキップされ(一覧表示、`--force` で上書き可)ます。
51
+
52
+ ## 内容物
53
+
54
+ | ファイル | 役割 |
55
+ |---|---|
56
+ | `CLAUDE.md` | プロジェクトのコマンド、ルール、アンチパターン、ワークループとチェックポイントのプロトコル |
57
+ | `.claude/settings.json` | フック登録 |
58
+ | `.claude/hooks/sensor-post-edit.sh` | コード編集のたびに即座にリントを実行し、失敗をフィードバック |
59
+ | `.claude/hooks/stop-gate.sh` | ターン終了時にテストを一括実行。失敗状態での終了をブロック(セッションあたり3回上限、超過でエスカレーション要求) |
60
+ | `.claude/hooks/guard-pre-bash.sh` | 破壊的コマンドと検証バイパス(`--no-verify`)を実行前にブロック |
61
+ | `.claude/hooks/session-start.sh` | セッション開始/再開/圧縮時に進行中チェックポイントを再注入。失敗が蓄積すると `/ratchet` を提案 |
62
+ | `.claude/hooks/observe-log.sh` | 全ツール呼び出しを JSONL で記録 + トリップワイヤー(同一失敗3回、呼び出し急増) |
63
+ | `harness/harness_report.py` | ログからのヘルススコアカード |
64
+ | `harness/tests/` | フックとインストーラーのセルフテスト |
65
+ | `bin/cli.js` | インストーラー(init / update / doctor / uninstall) |
66
+
67
+ スキル:
68
+
69
+ | スキル | 役割 |
70
+ |---|---|
71
+ | `/harness-init` | リポジトリをスキャン → PROJECT セクションと commands.env を記入(インストール時に1回) |
72
+ | `/checkpoint` | `.harness/state/` に状態を保存(plan.md / decisions.jsonl / progress.json) |
73
+ | `/ratchet [ミス]` | 再現 → 分類 → ルール/センサー/権限を提案 → 検証(引数なし: ログ診断) |
74
+ | `/guide-audit` | CLAUDE.md ルールの監査 — 維持 / 削除 / センサー化(月次) |
75
+
76
+ ## 推奨パーミッション(任意)
77
+
78
+ キットはパーミッションポリシーを強制しません。無人運用や高自律
79
+ モードで使うなら、プロジェクトの `.claude/settings.json` に以下の
80
+ ような設定を検討してください — 特にエージェントが自身のハーネスを
81
+ 編集できないようにする項目を:
82
+
83
+ ```json
84
+ {
85
+ "permissions": {
86
+ "ask": [
87
+ "Edit(.claude/**)", "Write(.claude/**)",
88
+ "Edit(.harness/**)", "Write(.harness/**)",
89
+ "Edit(.env*)", "Edit(*.config.*)", "Edit(.github/**)"
90
+ ],
91
+ "deny": [
92
+ "Read(.env)", "Read(.env.*)", "Read(**/secrets/**)",
93
+ "Read(**/*.pem)", "Bash(sudo*)"
94
+ ]
95
+ }
96
+ }
97
+ ```
98
+
99
+ ## 運用ルーティン
100
+
101
+ - **毎日 / タスクごと:** 普通に作業するだけです。センサーとガードは
102
+ 自動です。長いタスクは `/checkpoint` で状態を保存。
103
+ - **ミスを見つけたら:** 会話の中で直すだけにせず — `/ratchet
104
+ [何が起きたか]` で構造化してください。同じレビューコメント3回 →
105
+ ルールへ。同じルール違反3回 → ガード/権限へ昇格。
106
+ - **毎週:** `python3 harness/harness_report.py` でスコアカードを
107
+ 確認。繰り返しの失敗が見えたら `/ratchet` を実行。
108
+ - **毎月:** `/guide-audit` で CLAUDE.md を監査 — センサーが既に
109
+ 強制しているルールは削除し、矛盾はマージ。
110
+
111
+ ## カスタマイズ
112
+
113
+ - 危険コマンドのパターン: `guard-pre-bash.sh` の `DENY_PATTERNS`
114
+ - トリップワイヤーの閾値: `observe-log.sh`(デフォルト: 同一失敗3回、300呼び出し)
115
+ - センサー対象の拡張子: `sensor-post-edit.sh` の case 文
116
+ - 終了ブロック上限: `stop-gate.sh`(デフォルト: セッションあたり3回)
117
+ - フックを変更したら `harness/tests/test_hooks.sh` にケースを追加して実行
118
+
119
+ ## 使うべきでない場面
120
+
121
+ 単発の質問、探索的なブレインストーミング、検証不能なクリエイティブ
122
+ 作業にはオーバーキルです。繰り返し実行される作業、失敗に実コストが
123
+ 伴う作業、無人で走る作業、セッションを跨いで状態を保持すべき作業で
124
+ 真価を発揮します。
125
+
126
+ ## 設計背景
127
+
128
+ このキットは2つの資料の実装です。完全な分析は [`docs/`](docs/) に
129
+ あります — npm パッケージには含まれません(動作中のエージェントに
130
+ 理論は不要)が、ここでのすべての設計判断を説明しています。
131
+
132
+ ### 📄 EnvHarness: Awakening Static Worlds for Agent Learning
133
+
134
+ > **[arXiv:2608.19880](https://arxiv.org/abs/2608.19880)** · Chengsong Huang, Zifeng Wang, Rujun Han, Chen-Yu Lee ほか (2026)
135
+ > 詳細分析: [docs/analysis-01-envharness.md](docs/analysis-01-envharness.md)
136
+
137
+ **論文の主張。** *エージェント*にハーネス(ツール、メモリ、スキル)
138
+ を装着すれば重みに触れずに拡張できるのと同様に、*環境*にハーネスを
139
+ 装着すれば、そのコードに触れずに学習信号をカスタマイズできる:
140
+ `Static Env + EnvHarness = Customized Env`。環境はインターフェース層
141
+ でのみ、3つの合成可能なコンポーネントによって変換される —
142
+ **Stage**(初期状態の再構成)、**Contract**(アクションのフィルタ、
143
+ 観測の変換、遷移のラップ)、**Chain**(環境の合成)— そのため元の
144
+ 正解検証器は常に保存され、これが LLM 生成環境に対する本手法の中核的
145
+ 優位性となる。**EnvRigger** という自動化ループが設計を駆動する:
146
+ 失敗軌跡を*観察* → 根本原因を*診断* → 変換を*作成* → 元の失敗に
147
+ 対して*検証*。5つのベンチマークでラップされた環境がエージェント性能
148
+ を引き上げ(例: ALFWorld 分布外 +9.0 ポイント、SWE-bench Verified
149
+ +2.7 かつステップ数 9.8% 減)— 分布外で最大の効果を示したことは、
150
+ 暗記ではなく転移の証拠である。
151
+
152
+ **このキットが取り入れたもの:**
153
+
154
+ | 論文の概念 | ここでの実装 |
155
+ |---|---|
156
+ | EnvRigger ループ(観察 → 診断 → 作成 → 検証) | `/ratchet` スキル — 自動受理を**ユーザー承認**に置き換え |
157
+ | Contract: アクションのフィルタリング | `guard-pre-bash.sh`(破壊的コマンドを実行前にブロック) |
158
+ | Contract: 構造化されたフィードバック | `sensor-post-edit.sh` / `stop-gate.sh`(検証結果をフィードバック) |
159
+ | Stage: 準備された初期状態 | セッション開始時のチェックポイント復旧 |
160
+ | **元の検証器の保存** | 不変条件: ハーネスはテストスイートを包むが、決して変更もバイパスもしない |
161
+
162
+ ### 📘 ハーネス・エンジニアリング: 6層プロダクション・プレイブック
163
+
164
+ > 公開されている実務者資料の統合 — [Mitchell Hashimoto](https://mitchellh.com/)
165
+ > のラチェット方法論、[OpenAI Codex フィールドレポート](https://openai.com/index/harness-engineering)、
166
+ > [Martin Fowler](https://martinfowler.com/) のガイドとセンサーの分類、
167
+ > そして Anthropic / LangChain / Cursor の資料。
168
+ > 詳細分析: [docs/analysis-02-harness-engineering.md](docs/analysis-02-harness-engineering.md)
169
+
170
+ **プレイブックの主張。** プロンプトエンジニアリング(モデルが*言う*
171
+ こと)とコンテキストエンジニアリング(モデルが*見る*こと)は、
172
+ ハーネスエンジニアリングに包含される: モデルが*できる*こと、失敗を
173
+ 生き延びるもの、許可されるもの、そして完了と見なされるもの。
174
+ **Agent = Model + Harness** という主張は、自己報告ながら一貫した証拠
175
+ に裏付けられている — 同じモデルがハーネスの交換だけで GAIA 30.91% →
176
+ 74.55% に跳躍、固定されたモデルがハーネス最適化だけで Terminal Bench
177
+ 30位 → 5位に上昇。アーキテクチャは6層で、このキットと1対1で対応する:
178
+
179
+ | # | 層 | 原則 | このキットでは |
180
+ |---|---|---|---|
181
+ | 1 | **ガイド** | 各行 = 過去の失敗1件の恒久的予防 | `CLAUDE.md` |
182
+ | 2 | **センサー** | 外部の決定論的チェック。自己判断は禁止 | `sensor-post-edit.sh`、`stop-gate.sh` |
183
+ | 3 | **エージェンティックループ** | すべての予算に上限、枯渇時はエスカレーション | ワークループ・プロトコル + トリップワイヤー + 終了ブロック3回上限 |
184
+ | 4 | **メモリ** | ファイルシステムこそがメモリ。復旧テスト合格が必須 | `/checkpoint` + `session-start.sh` |
185
+ | 5 | **パーミッション** | モデルは自分自身を制限できない | `guard-pre-bash.sh` + 推奨パーミッション |
186
+ | 6 | **可観測性** | すべてを記録し、ドリフトに警報 | `observe-log.sh` + `harness_report.py` |
187
+
188
+ 運用ルールもここから来ています — Hashimoto の**ラチェット原則**
189
+ (「エージェントがミスをするたびに、そのミスの再発を不可能にする
190
+ 解決策をエンジニアリングせよ」)と Cursor の昇格ラダー:
191
+
192
+ ```mermaid
193
+ flowchart LR
194
+ F[失敗を観察] --> R["/ratchet: 再現 + 診断"]
195
+ R --> P{最も強い層}
196
+ P -->|コンテキスト不足だった| G["ガイドルール (CLAUDE.md)"]
197
+ P -->|チェックで検出できる| S[センサー / lint ルール]
198
+ P -->|そもそも不可能にすべき| H[ガード / パーミッション]
199
+ G & S & H --> V[元の失敗に対して検証]
200
+ V --> N[同じ失敗は再発不能]
201
+ ```
202
+
203
+ 同じレビューコメント **3回** → ルールになる。同じルール違反 **3回**
204
+ → ゲートになる。そして成熟のシグナルはルール増加率の*低下*だ —
205
+ 蓄積するだけのハーネスは負債であり、それこそが `/guide-audit` の
206
+ 存在理由である。
207
+
208
+ ---
209
+
210
+ キット自体を拡張するには?
211
+ [docs/AGENT_BRIEFING.md](docs/AGENT_BRIEFING.md) から始めてください —
212
+ 不変条件(検証を弱めない、承認なしの自動適用禁止、最小限の
213
+ インフラ)と、精査済みのバックログが載っています。
package/README.ko.md ADDED
@@ -0,0 +1,207 @@
1
+ # uni-harness
2
+
3
+ 🇺🇸 [English](README.md) | 🇰🇷 **한국어** | 🇨🇳 [简体中文](README.zh-CN.md) | 🇯🇵 [日本語](README.ja.md)
4
+
5
+ ![license](https://img.shields.io/badge/license-MIT-blue)
6
+ ![node](https://img.shields.io/badge/node-%E2%89%A516-brightgreen)
7
+ ![runtime](https://img.shields.io/badge/runtime-bash%20%2B%20python3%20stdlib-lightgrey)
8
+ ![for](https://img.shields.io/badge/for-Claude%20Code-d97757)
9
+
10
+ Claude Code용 에이전트 하네스 킷입니다. 코딩 에이전트를 자동 검증(센서),
11
+ 파괴적 명령 차단(가드), 체크포인트 기반 세션 복구, 트립와이어가 달린
12
+ 전체 도구 호출 로깅, 그리고 모든 실패를 영구 구조로 바꾸는 래칫
13
+ 워크플로로 감쌉니다.
14
+
15
+ > 공식: **Agent = Model + Harness.** 추론은 모델이 가져오고,
16
+ > 나머지 전부 — 규칙, 센서, 루프 상한, 메모리, 관측 — 는 이 킷이
17
+ > 가져옵니다.
18
+
19
+ ## 설치
20
+
21
+ ```bash
22
+ npx uni-harness init # 프로젝트 루트에서 (또는: init <경로>)
23
+ ```
24
+
25
+ 그다음 프로젝트에서 Claude Code를 열면 — Claude가 하네스가 미설정
26
+ 상태임을 감지하고 **`/harness-init` 실행을 먼저 제안**합니다(직접
27
+ 실행해도 됩니다). 저장소를 스캔해 빌드/테스트/린트 명령을 감지하고,
28
+ **실제로 실행해서 검증**한 뒤, 승인을 받아 `CLAUDE.md`와
29
+ `.harness/commands.env`를 채웁니다. 이 단계 전까지 검증 센서는
30
+ 비활성 상태로 대기합니다.
31
+
32
+ 기타 인스톨러 명령:
33
+
34
+ ```bash
35
+ npx uni-harness update # 킷 기계 부품 갱신 (사용자 파일은 절대 안 건드림)
36
+ npx uni-harness doctor # 설치 상태 진단
37
+ npx uni-harness uninstall --yes # 킷 기계 부품 제거, 사용자 파일은 유지
38
+ ```
39
+
40
+ 요구사항: bash, python3 (표준 라이브러리만 — 패키지 불필요), 인스톨러
41
+ 자체는 node ≥16.
42
+
43
+ **진행 중인 프로젝트에도 안전합니다.** `init`은 사용자 소유 파일을
44
+ 절대 덮어쓰지 않습니다: 기존 `CLAUDE.md`는 유지되고(`/harness-init`이
45
+ 하네스 섹션 추가를 제안), 기존 `settings.json`의 훅·권한은 보존된 채
46
+ 킷 훅만 병합되며, `.gitignore`는 교체가 아니라 추가만 됩니다.
47
+ `update`는 수정하지 않은 킷 파일만 갱신합니다 — 커스터마이즈한 파일은
48
+ 건너뛰고 목록으로 알려줍니다(`--force`로 덮어쓰기 가능).
49
+
50
+ ## 구성 요소
51
+
52
+ | 파일 | 역할 |
53
+ |---|---|
54
+ | `CLAUDE.md` | 프로젝트 명령, 규칙, 안티패턴, 작업 루프·체크포인트 프로토콜 |
55
+ | `.claude/settings.json` | 훅 등록 |
56
+ | `.claude/hooks/sensor-post-edit.sh` | 코드 수정 즉시 lint 실행, 실패를 피드백 |
57
+ | `.claude/hooks/stop-gate.sh` | 턴 종료 시 테스트 일괄 실행; 실패 상태의 종료를 차단 (세션당 3회 상한, 초과 시 에스컬레이션 강제) |
58
+ | `.claude/hooks/guard-pre-bash.sh` | 파괴적 명령과 검증 우회(`--no-verify`)를 실행 전 차단 |
59
+ | `.claude/hooks/session-start.sh` | 세션 시작/재개/압축 시 진행 중 체크포인트 재주입; 실패 누적 시 `/ratchet` 제안 |
60
+ | `.claude/hooks/observe-log.sh` | 모든 도구 호출을 JSONL로 기록 + 트립와이어 (동일 실패 3회, 호출 급증) |
61
+ | `harness/harness_report.py` | 로그 기반 상태 스코어카드 |
62
+ | `harness/tests/` | 훅·인스톨러 자체 테스트 |
63
+ | `bin/cli.js` | 인스톨러 (init / update / doctor / uninstall) |
64
+
65
+ 스킬:
66
+
67
+ | 스킬 | 역할 |
68
+ |---|---|
69
+ | `/harness-init` | 저장소 스캔 → PROJECT 섹션 & commands.env 채우기 (설치 시 1회) |
70
+ | `/checkpoint` | `.harness/state/`에 상태 저장 (plan.md / decisions.jsonl / progress.json) |
71
+ | `/ratchet [실수]` | 재현 → 분류 → 규칙/센서/권한 제안 → 검증 (인자 없이: 로그 진단) |
72
+ | `/guide-audit` | CLAUDE.md 규칙 감사 — 유지 / 삭제 / 센서 전환 (월 1회) |
73
+
74
+ ## 권장 권한 설정 (선택)
75
+
76
+ 킷은 권한 정책을 강제하지 않습니다. 무인 실행이나 고자율 모드로 쓴다면
77
+ 프로젝트의 `.claude/settings.json`에 아래와 같은 설정을 고려하세요 —
78
+ 특히 에이전트가 자기 하네스를 수정하지 못하게 막는 항목들:
79
+
80
+ ```json
81
+ {
82
+ "permissions": {
83
+ "ask": [
84
+ "Edit(.claude/**)", "Write(.claude/**)",
85
+ "Edit(.harness/**)", "Write(.harness/**)",
86
+ "Edit(.env*)", "Edit(*.config.*)", "Edit(.github/**)"
87
+ ],
88
+ "deny": [
89
+ "Read(.env)", "Read(.env.*)", "Read(**/secrets/**)",
90
+ "Read(**/*.pem)", "Bash(sudo*)"
91
+ ]
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## 운영 루틴
97
+
98
+ - **매일 / 작업마다:** 그냥 일하면 됩니다. 센서와 가드는 자동입니다.
99
+ 긴 작업은 `/checkpoint`로 상태를 저장하세요.
100
+ - **실수를 발견하면:** 대화에서만 고치지 말고 — `/ratchet [무슨 일이
101
+ 있었는지]`로 구조화하세요. 같은 리뷰 코멘트 3회 → 규칙으로; 같은
102
+ 규칙 위반 3회 → 가드/권한으로 승격.
103
+ - **매주:** `python3 harness/harness_report.py`로 스코어카드 확인;
104
+ 반복 실패가 보이면 `/ratchet` 실행.
105
+ - **매월:** `/guide-audit`으로 CLAUDE.md 감사 — 센서가 이미 강제하는
106
+ 규칙은 삭제, 모순은 병합.
107
+
108
+ ## 커스터마이징
109
+
110
+ - 위험 명령 패턴: `guard-pre-bash.sh`의 `DENY_PATTERNS`
111
+ - 트립와이어 임계값: `observe-log.sh` (기본: 동일 실패 3회, 300 호출)
112
+ - 센서 대상 확장자: `sensor-post-edit.sh`의 case 문
113
+ - 종료 차단 상한: `stop-gate.sh` (기본: 세션당 3회)
114
+ - 훅을 수정하면 `harness/tests/test_hooks.sh`에 케이스를 추가하고 실행
115
+
116
+ ## 이런 경우에는 쓰지 마세요
117
+
118
+ 일회성 질문, 탐색적 브레인스토밍, 검증 불가능한 창작 작업에는
119
+ 과합니다. 반복 실행되는 작업, 실패 시 실제 비용이 발생하는 작업,
120
+ 무인으로 돌아가는 작업, 세션을 넘어 상태를 보존해야 하는 작업에서
121
+ 값을 합니다.
122
+
123
+ ## 설계 배경
124
+
125
+ 이 킷은 두 자료의 실무 구현입니다. 전체 분석은 [`docs/`](docs/)에
126
+ 있습니다 — npm 패키지에는 포함되지 않지만(동작하는 에이전트에게 이론은
127
+ 불필요), 여기의 모든 설계 결정을 설명합니다.
128
+
129
+ ### 📄 EnvHarness: Awakening Static Worlds for Agent Learning
130
+
131
+ > **[arXiv:2608.19880](https://arxiv.org/abs/2608.19880)** · Chengsong Huang, Zifeng Wang, Rujun Han, Chen-Yu Lee 외 (2026)
132
+ > 상세 분석: [docs/analysis-01-envharness.md](docs/analysis-01-envharness.md)
133
+
134
+ **논문의 주장.** *에이전트*에 하네스(도구, 메모리, 스킬)를 달아
135
+ 가중치를 건드리지 않고 확장하듯, *환경*에도 하네스를 달아 코드를
136
+ 건드리지 않고 학습 신호를 커스터마이즈할 수 있다: `Static Env +
137
+ EnvHarness = Customized Env`. 환경은 인터페이스 계층에서만 세 가지
138
+ 조합 가능한 컴포넌트로 변환된다 — **Stage**(초기 상태 재구성),
139
+ **Contract**(행동 필터링, 관측 변환, 전이 래핑), **Chain**(환경
140
+ 합성) — 그래서 원본 정답 검증기가 항상 보존되며, 이것이 LLM 생성
141
+ 환경 대비 핵심 우위다. **EnvRigger**라는 자동화 루프가 설계를
142
+ 주도한다: 실패 궤적 *관찰* → 근본 원인 *진단* → 변환 *작성* → 원래
143
+ 실패에 대해 *검증*. 다섯 벤치마크에서 래핑된 환경이 에이전트 성능을
144
+ 끌어올렸고(예: ALFWorld 분포 외 +9.0점, SWE-bench Verified +2.7에
145
+ 스텝 9.8% 감소) — 분포 외에서 가장 큰 이득을 보인 것은 암기가 아닌
146
+ 전이의 증거다.
147
+
148
+ **이 킷이 가져온 것:**
149
+
150
+ | 논문 개념 | 여기서의 구현 |
151
+ |---|---|
152
+ | EnvRigger 루프 (관찰 → 진단 → 작성 → 검증) | `/ratchet` 스킬 — 자동 수용을 **사용자 승인**으로 대체 |
153
+ | Contract: 행동 필터링 | `guard-pre-bash.sh` (파괴적 명령 실행 전 차단) |
154
+ | Contract: 구조화된 피드백 | `sensor-post-edit.sh` / `stop-gate.sh` (검증 결과 피드백) |
155
+ | Stage: 준비된 초기 상태 | 세션 시작 시 체크포인트 복구 |
156
+ | **원본 검증기 보존** | 불변조건: 하네스는 테스트 스위트를 감싸되 절대 수정·우회하지 않음 |
157
+
158
+ ### 📘 하네스 엔지니어링: 6계층 프로덕션 플레이북
159
+
160
+ > 공개된 실무자 자료의 종합 — [Mitchell Hashimoto](https://mitchellh.com/)의
161
+ > 래칫 방법론, [OpenAI Codex 필드 리포트](https://openai.com/index/harness-engineering),
162
+ > [Martin Fowler](https://martinfowler.com/)의 가이드·센서 분류, 그리고
163
+ > Anthropic / LangChain / Cursor 자료.
164
+ > 상세 분석: [docs/analysis-02-harness-engineering.md](docs/analysis-02-harness-engineering.md)
165
+
166
+ **플레이북의 주장.** 프롬프트 엔지니어링(모델이 *말하는* 것)과 컨텍스트
167
+ 엔지니어링(모델이 *보는* 것)은 하네스 엔지니어링에 포섭된다: 모델이
168
+ *할 수 있는* 것, 실패에서 살아남는 것, 허용되는 것, 그리고 완료로
169
+ 인정되는 것. **Agent = Model + Harness**라는 주장은 자기 보고이지만
170
+ 일관된 증거로 뒷받침된다 — 같은 모델이 하네스 교체만으로 GAIA에서
171
+ 30.91% → 74.55%로 도약, 고정된 모델이 하네스 최적화만으로 Terminal
172
+ Bench 30위 → 5위. 아키텍처는 6계층이며, 이 킷과 일대일로 대응한다:
173
+
174
+ | # | 계층 | 원칙 | 이 킷에서 |
175
+ |---|---|---|---|
176
+ | 1 | **가이드** | 각 줄 = 과거 실패 하나의 영구 방지 | `CLAUDE.md` |
177
+ | 2 | **센서** | 외부의 결정론적 검사, 자기 판단 금지 | `sensor-post-edit.sh`, `stop-gate.sh` |
178
+ | 3 | **에이전틱 루프** | 모든 예산에 상한, 소진 시 에스컬레이션 | 작업 루프 프로토콜 + 트립와이어 + 3회 종료 차단 상한 |
179
+ | 4 | **메모리** | 파일시스템이 곧 메모리; 복구 테스트 통과 필수 | `/checkpoint` + `session-start.sh` |
180
+ | 5 | **권한** | 모델은 스스로를 제한할 수 없다 | `guard-pre-bash.sh` + 권장 권한 |
181
+ | 6 | **관측** | 전부 기록하고 드리프트에 경보 | `observe-log.sh` + `harness_report.py` |
182
+
183
+ 운영 규칙도 여기서 왔습니다 — Hashimoto의 **래칫 원칙**("에이전트가
184
+ 실수할 때마다, 그 실수의 재발이 불가능해지는 해법을 엔지니어링하라")과
185
+ Cursor의 승격 사다리:
186
+
187
+ ```mermaid
188
+ flowchart LR
189
+ F[실패 관찰] --> R["/ratchet: 재현 + 진단"]
190
+ R --> P{가장 강한 계층}
191
+ P -->|컨텍스트 부족이었다| G["가이드 규칙 (CLAUDE.md)"]
192
+ P -->|검사로 잡을 수 있다| S[센서 / lint 규칙]
193
+ P -->|아예 불가능해야 한다| H[가드 / 권한]
194
+ G & S & H --> V[원래 실패에 대해 검증]
195
+ V --> N[같은 실패는 재발 불가]
196
+ ```
197
+
198
+ 같은 리뷰 코멘트 **3회** → 규칙이 된다. 같은 규칙 위반 **3회** →
199
+ 게이트가 된다. 그리고 성숙의 신호는 규칙 증가율의 *감소*다 —
200
+ 쌓이기만 하는 하네스는 부채이며, `/guide-audit`이 존재하는 이유다.
201
+
202
+ ---
203
+
204
+ 킷 자체를 확장하시나요?
205
+ [docs/AGENT_BRIEFING.md](docs/AGENT_BRIEFING.md)에서 시작하세요 —
206
+ 불변조건(검증 약화 금지, 승인 없는 자동 적용 금지, 최소 인프라)과
207
+ 검증된 백로그가 담겨 있습니다.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # uni-harness
2
2
 
3
+ 🇺🇸 **English** | 🇰🇷 [한국어](README.ko.md) | 🇨🇳 [简体中文](README.zh-CN.md) | 🇯🇵 [日本語](README.ja.md)
4
+
3
5
  ![license](https://img.shields.io/badge/license-MIT-blue)
4
6
  ![node](https://img.shields.io/badge/node-%E2%89%A516-brightgreen)
5
7
  ![runtime](https://img.shields.io/badge/runtime-bash%20%2B%20python3%20stdlib-lightgrey)
@@ -0,0 +1,201 @@
1
+ # uni-harness
2
+
3
+ 🇺🇸 [English](README.md) | 🇰🇷 [한국어](README.ko.md) | 🇨🇳 **简体中文** | 🇯🇵 [日本語](README.ja.md)
4
+
5
+ ![license](https://img.shields.io/badge/license-MIT-blue)
6
+ ![node](https://img.shields.io/badge/node-%E2%89%A516-brightgreen)
7
+ ![runtime](https://img.shields.io/badge/runtime-bash%20%2B%20python3%20stdlib-lightgrey)
8
+ ![for](https://img.shields.io/badge/for-Claude%20Code-d97757)
9
+
10
+ 一个面向 Claude Code 的智能体挽具(harness)套件。它为编码智能体包上
11
+ 自动验证(传感器)、破坏性命令拦截(守卫)、基于检查点的会话恢复、
12
+ 带绊线告警的全量工具调用日志,以及把每次失败都转化为永久结构的
13
+ 棘轮(ratchet)工作流。
14
+
15
+ > 公式:**Agent = Model + Harness。** 模型带来推理能力;
16
+ > 其余的一切 — 规则、传感器、循环上限、记忆、可观测性 —
17
+ > 由这个套件提供。
18
+
19
+ ## 安装
20
+
21
+ ```bash
22
+ npx uni-harness init # 在项目根目录执行(或:init <路径>)
23
+ ```
24
+
25
+ 然后在项目中打开 Claude Code — Claude 会发现挽具尚未配置,并
26
+ **主动提议运行 `/harness-init`**(也可以自己运行)。它会扫描仓库、
27
+ 检测构建/测试/lint 命令、**通过实际运行来验证它们**,并在你批准后
28
+ 填入 `CLAUDE.md` 和 `.harness/commands.env`。在此步骤完成前,
29
+ 验证传感器保持待机。
30
+
31
+ 其他安装器命令:
32
+
33
+ ```bash
34
+ npx uni-harness update # 刷新套件机件(绝不触碰你的文件)
35
+ npx uni-harness doctor # 诊断安装状态
36
+ npx uni-harness uninstall --yes # 移除套件机件,保留你的文件
37
+ ```
38
+
39
+ 依赖要求:bash、python3(仅标准库 — 无需任何包)、安装器本身需要
40
+ node ≥16。
41
+
42
+ **对进行中的项目同样安全。** `init` 绝不覆盖你拥有的任何东西:
43
+ 已有的 `CLAUDE.md` 会被保留(运行 `/harness-init` 后它会以追加方式
44
+ 提议补充挽具章节),已有 `settings.json` 中的钩子和权限会被保留
45
+ (套件钩子以合并方式加入),你的 `.gitignore` 只会被追加而不是替换。
46
+ `update` 只刷新未被修改的套件文件 — 你自定义过的一律跳过
47
+ (会列出,可用 `--force` 覆盖)。
48
+
49
+ ## 内含组件
50
+
51
+ | 文件 | 作用 |
52
+ |---|---|
53
+ | `CLAUDE.md` | 项目命令、规则、反模式、工作循环与检查点协议 |
54
+ | `.claude/settings.json` | 钩子注册 |
55
+ | `.claude/hooks/sensor-post-edit.sh` | 每次代码编辑立即运行 lint,将失败反馈回去 |
56
+ | `.claude/hooks/stop-gate.sh` | 回合结束时批量运行测试;失败状态下阻止收工(每会话 3 次上限,超过则强制升级上报) |
57
+ | `.claude/hooks/guard-pre-bash.sh` | 在执行前拦截破坏性命令与验证绕过(`--no-verify`) |
58
+ | `.claude/hooks/session-start.sh` | 会话启动/恢复/压缩时重新注入进行中的检查点;失败堆积时提示 `/ratchet` |
59
+ | `.claude/hooks/observe-log.sh` | 以 JSONL 记录每次工具调用 + 绊线(同一失败 3 次、调用激增) |
60
+ | `harness/harness_report.py` | 基于日志的健康记分卡 |
61
+ | `harness/tests/` | 钩子与安装器的自测 |
62
+ | `bin/cli.js` | 安装器(init / update / doctor / uninstall) |
63
+
64
+ 技能:
65
+
66
+ | 技能 | 作用 |
67
+ |---|---|
68
+ | `/harness-init` | 扫描仓库 → 填写 PROJECT 章节 & commands.env(安装时一次) |
69
+ | `/checkpoint` | 将状态保存到 `.harness/state/`(plan.md / decisions.jsonl / progress.json) |
70
+ | `/ratchet [失误]` | 复现 → 归类 → 提议规则/传感器/权限 → 验证(无参数:诊断日志) |
71
+ | `/guide-audit` | 审计 CLAUDE.md 规则 — 保留 / 删除 / 转为传感器(每月) |
72
+
73
+ ## 推荐权限配置(可选)
74
+
75
+ 套件不强加权限策略。若用于无人值守或高自治场景,可考虑在项目的
76
+ `.claude/settings.json` 中加入类似配置 — 尤其是阻止智能体修改
77
+ 自身挽具的那些条目:
78
+
79
+ ```json
80
+ {
81
+ "permissions": {
82
+ "ask": [
83
+ "Edit(.claude/**)", "Write(.claude/**)",
84
+ "Edit(.harness/**)", "Write(.harness/**)",
85
+ "Edit(.env*)", "Edit(*.config.*)", "Edit(.github/**)"
86
+ ],
87
+ "deny": [
88
+ "Read(.env)", "Read(.env.*)", "Read(**/secrets/**)",
89
+ "Read(**/*.pem)", "Bash(sudo*)"
90
+ ]
91
+ }
92
+ }
93
+ ```
94
+
95
+ ## 运营例程
96
+
97
+ - **每天 / 每个任务:** 正常干活即可。传感器和守卫是自动的。
98
+ 长任务用 `/checkpoint` 保存状态。
99
+ - **发现失误时:** 不要只在对话里修掉 — 运行 `/ratchet [发生了什么]`
100
+ 把它结构化。同一审查意见出现 3 次 → 变成规则;同一规则被违反
101
+ 3 次 → 升级为守卫/权限。
102
+ - **每周:** 用 `python3 harness/harness_report.py` 查看记分卡;
103
+ 出现重复失败就运行 `/ratchet`。
104
+ - **每月:** 用 `/guide-audit` 审计 CLAUDE.md — 删除传感器已自动
105
+ 强制执行的规则,合并互相矛盾的规则。
106
+
107
+ ## 自定义
108
+
109
+ - 危险命令模式:`guard-pre-bash.sh` 中的 `DENY_PATTERNS`
110
+ - 绊线阈值:`observe-log.sh`(默认:同一失败 3 次、300 次调用)
111
+ - 传感器文件扩展名:`sensor-post-edit.sh` 中的 case 语句
112
+ - 收工拦截上限:`stop-gate.sh`(默认:每会话 3 次)
113
+ - 修改了钩子就在 `harness/tests/test_hooks.sh` 加一个用例并运行
114
+
115
+ ## 什么时候不该用
116
+
117
+ 对一次性提问、探索性头脑风暴、无法验证的创意工作来说它是杀鸡用牛刀。
118
+ 它的价值体现在:反复运行的工作、失败有真实代价的工作、无人值守运行
119
+ 的工作、以及必须跨会话保持状态的工作。
120
+
121
+ ## 设计背景
122
+
123
+ 本套件是两份材料的可运行实现。完整分析在 [`docs/`](docs/) 中 —
124
+ 它们不随 npm 包分发(运行中的智能体不需要理论),但解释了这里的
125
+ 每一个设计决策。
126
+
127
+ ### 📄 EnvHarness: Awakening Static Worlds for Agent Learning
128
+
129
+ > **[arXiv:2608.19880](https://arxiv.org/abs/2608.19880)** · Chengsong Huang, Zifeng Wang, Rujun Han, Chen-Yu Lee 等 (2026)
130
+ > 深度解读:[docs/analysis-01-envharness.md](docs/analysis-01-envharness.md)
131
+
132
+ **论文主张。** 正如给*智能体*装上挽具(工具、记忆、技能)可以在不动
133
+ 权重的情况下扩展它,你也可以给*环境*装上挽具,在不动其代码的情况下
134
+ 定制学习信号:`Static Env + EnvHarness = Customized Env`。环境只在
135
+ 接口层通过三个可组合的组件被变换 — **Stage**(重塑初始状态)、
136
+ **Contract**(过滤动作、变换观测、包装转移)、**Chain**(组合环境)—
137
+ 因此原始的真值验证器始终得到保留,这正是它相对 LLM 生成环境的核心
138
+ 优势。一个名为 **EnvRigger** 的自动化循环驱动设计:*观察*失败轨迹 →
139
+ *诊断*根因 → *编写*变换 → 对原始失败进行*验证*。在五个基准上,
140
+ 包装后的环境提升了智能体表现(如 ALFWorld 分布外 +9.0 分、SWE-bench
141
+ Verified +2.7 且步数减少 9.8%)— 分布外增益最大,是迁移而非记忆的
142
+ 证据。
143
+
144
+ **本套件从中借鉴的:**
145
+
146
+ | 论文概念 | 此处的实现 |
147
+ |---|---|
148
+ | EnvRigger 循环(观察 → 诊断 → 编写 → 验证) | `/ratchet` 技能 — 自动接受被替换为**用户批准** |
149
+ | Contract:动作过滤 | `guard-pre-bash.sh`(破坏性命令执行前拦截) |
150
+ | Contract:结构化反馈 | `sensor-post-edit.sh` / `stop-gate.sh`(验证结果反馈) |
151
+ | Stage:备妥的初始状态 | 会话启动时的检查点恢复 |
152
+ | **保留原始验证器** | 不变量:挽具包装你的测试套件,但绝不修改或绕过它 |
153
+
154
+ ### 📘 挽具工程:6 层生产实战手册
155
+
156
+ > 公开实践者材料的综合 — [Mitchell Hashimoto](https://mitchellh.com/)
157
+ > 的棘轮方法论、[OpenAI Codex 实战报告](https://openai.com/index/harness-engineering)、
158
+ > [Martin Fowler](https://martinfowler.com/) 的向导与传感器分类法,以及
159
+ > Anthropic / LangChain / Cursor 的资料。
160
+ > 深度解读:[docs/analysis-02-harness-engineering.md](docs/analysis-02-harness-engineering.md)
161
+
162
+ **手册主张。** 提示词工程(模型*说*什么)和上下文工程(模型*看到*
163
+ 什么)都被挽具工程所涵盖:模型*能做*什么、什么能在失败中幸存、什么被
164
+ 允许、什么算完成。**Agent = Model + Harness** 这一主张有自报但一致的
165
+ 证据支撑 — 同一个模型仅靠更换挽具在 GAIA 上从 30.91% 跃升至 74.55%,
166
+ 固定模型仅靠挽具优化在 Terminal Bench 上从第 30 名爬到第 5 名。
167
+ 架构分为六层,与本套件一一对应:
168
+
169
+ | # | 层 | 原则 | 在本套件中 |
170
+ |---|---|---|---|
171
+ | 1 | **向导** | 每一行 = 对一次过往失败的永久预防 | `CLAUDE.md` |
172
+ | 2 | **传感器** | 外部确定性检查,绝不自我评判 | `sensor-post-edit.sh`、`stop-gate.sh` |
173
+ | 3 | **智能体循环** | 每项预算都有上限,耗尽即升级上报 | 工作循环协议 + 绊线 + 3 次收工拦截上限 |
174
+ | 4 | **记忆** | 文件系统即记忆;必须通过恢复测试 | `/checkpoint` + `session-start.sh` |
175
+ | 5 | **权限** | 模型无法限制它自己 | `guard-pre-bash.sh` + 推荐权限 |
176
+ | 6 | **可观测性** | 记录一切,对漂移告警 | `observe-log.sh` + `harness_report.py` |
177
+
178
+ 运营规则也来自于此 — Hashimoto 的**棘轮原则**("智能体每犯一次错,
179
+ 就工程化一个让该错误不可能重演的方案")以及 Cursor 的晋升阶梯:
180
+
181
+ ```mermaid
182
+ flowchart LR
183
+ F[观察到失败] --> R["/ratchet: 复现 + 诊断"]
184
+ R --> P{最强的层}
185
+ P -->|缺的是上下文| G["向导规则 (CLAUDE.md)"]
186
+ P -->|检查可以捕获| S[传感器 / lint 规则]
187
+ P -->|应当彻底不可能| H[守卫 / 权限]
188
+ G & S & H --> V[针对原始失败验证]
189
+ V --> N[同一失败无法重演]
190
+ ```
191
+
192
+ 同一审查意见出现 **3 次** → 变成规则。同一规则被违反 **3 次** →
193
+ 变成关卡。而成熟的信号是规则增速的*下降* — 只会堆积的挽具就是债务,
194
+ 这正是 `/guide-audit` 存在的意义。
195
+
196
+ ---
197
+
198
+ 想扩展套件本身?从
199
+ [docs/AGENT_BRIEFING.md](docs/AGENT_BRIEFING.md) 开始 — 那里有
200
+ 不变量(不得削弱验证、未经批准不得自动应用、最小基础设施)和经过
201
+ 审核的待办清单。
@@ -115,6 +115,14 @@ echo '{"task_id":"t1","status":"in_progress","next_step":"do X"}' > "$TMP/progre
115
115
  OUT=$(bash "$HOOKS/session-start.sh")
116
116
  check "reads legacy root checkpoint" "progress.json" "$OUT"
117
117
  rm "$TMP/progress.json"
118
+ # CLAUDE.md still pointing checkpoints at the root -> propose-a-diff nudge
119
+ printf '# P\n- write the plan to plan.md\n' > "$TMP/CLAUDE.md"
120
+ OUT=$(bash "$HOOKS/session-start.sh")
121
+ check "nudges CLAUDE.md path migration" "user's approval" "$OUT"
122
+ printf '# P\n- write the plan to .harness/state/plan.md\n' > "$TMP/CLAUDE.md"
123
+ OUT=$(bash "$HOOKS/session-start.sh")
124
+ check "silent when CLAUDE.md paths are current" "EMPTY" "$OUT"
125
+ rm "$TMP/CLAUDE.md"
118
126
  NOW=$(python3 -c 'import datetime; print(datetime.datetime.now().isoformat(timespec="seconds"))')
119
127
  for _ in 1 2 3; do
120
128
  echo "{\"ts\":\"$NOW\",\"session_id\":\"old\",\"event\":\"PostToolUseFailure\",\"tool\":\"Bash\",\"error\":\"x\"}" >> "$TMP/.harness/logs/tool_calls.jsonl"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uni-harness",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Agent harness kit for Claude Code — installs verification sensors, destructive-command guards, checkpoint recovery, observability logs, and ratchet skills into your project",
5
5
  "bin": {
6
6
  "uni-harness": "bin/cli.js"