uni-harness 0.1.0

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.
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: ratchet
3
+ description: Convert failures into permanent structure (rules, sensors, guards, permissions) instead of one-off corrections. With an argument, handles that one mistake end-to-end (/ratchet [what happened]); without arguments, diagnoses recurring failure patterns from the harness logs. Proposes only — applying always requires user approval.
4
+ ---
5
+
6
+ # Ratchet — Turning Failures into Structure
7
+
8
+ Goal: the same failure never happens twice. Always put the fix in the
9
+ **strongest layer** (weak → strong: in-conversation correction < CLAUDE.md
10
+ rule < automated sensor < guard/permissions block). **Never apply any
11
+ change without user approval.**
12
+
13
+ ## Mode A — Single Incident (`/ratchet [what happened]`)
14
+
15
+ Handle one mistake end-to-end:
16
+
17
+ 1. **Reproduce** — reproduce the failure with the same input/conditions.
18
+ If it doesn't reproduce, report that; never create a rule from a guess.
19
+ 2. **Classify** — use the failure-class table below.
20
+ 3. **Pick the layer** — choose the single strongest fix layer for that class.
21
+ 4. **Draft the fix** — produce a concrete diff/pattern per "Proposal format".
22
+ 5. **Verify** — (after user approval and applying) re-run the original
23
+ failing input from step 1 and confirm it is now blocked or caught.
24
+ 6. **Regression check** — run the full TEST command to confirm nothing
25
+ else broke.
26
+
27
+ ## Mode B — Log Diagnosis (`/ratchet` with no arguments)
28
+
29
+ 1. **Observe** — collect this (or the most recent) session's records from
30
+ `.harness/logs/tool_calls.jsonl`. Focus on `PostToolUseFailure` entries,
31
+ repeated edits to the same file, and repeated runs of the same command.
32
+ If there are no logs, tell the user and stop.
33
+ 2. **Diagnose** — classify failures by **failure class**, not symptom.
34
+ Each diagnosis gets "one-sentence root cause + the log entries behind it".
35
+ 3. **Write** — draft one fix per class, in its strongest layer.
36
+
37
+ ## Failure Class → Fix Layer
38
+
39
+ | Failure class | Signal | Strongest fix layer |
40
+ |---|---|---|
41
+ | Known bad pattern recurring | same type of code error again | linter rule (sensor) > guide rule |
42
+ | Missing context | worked without knowing project conventions | CLAUDE.md guide entry |
43
+ | Wrong tool use | dangerous/inappropriate command attempted | guard-pre-bash.sh pattern or permissions |
44
+ | Quality drift | declared done without verification | strengthen sensor (TEST_CMD scope) |
45
+ | Lost state | repeated already-completed steps | strengthen checkpoint protocol |
46
+ | Runaway/cost blowup | tool-call surge, same-error loop | adjust tripwire thresholds |
47
+
48
+ ## Proposal Format
49
+
50
+ - CLAUDE.md rule → a diff in the form `- [today's date] rule (failure summary)`
51
+ - Guard pattern → the regex to add to DENY_PATTERNS in guard-pre-bash.sh
52
+ - Permission → the allow/ask/deny change for settings.json permissions
53
+ - Sensor → commands.env change or file-extension additions in sensor-post-edit.sh
54
+
55
+ With each proposal, include: (1) the failure class it prevents,
56
+ (2) possible side effects (over-blocking etc.), (3) overlap/conflict with
57
+ existing rules.
58
+
59
+ ## Approval and Cleanup
60
+
61
+ - Apply only what the user approves.
62
+ - After applying, if an existing guide rule is now enforced automatically
63
+ by a sensor, propose deleting it (guide hygiene — see `/guide-audit`).
64
+
65
+ ## Forbidden
66
+
67
+ - No auto-applying without approval.
68
+ - No proposals that weaken verification: disabling tests, ignoring
69
+ failures, or loosening blocks is regression, not ratcheting. If the logs
70
+ show such a request, report that itself as a failure class.
71
+ - No more than 5 proposals at once (start with the most frequent class).
72
+ - No rules for failures that didn't reproduce (don't grow rules from guesses).
@@ -0,0 +1,13 @@
1
+ # ════════════════════════════════════════════════════════════════
2
+ # Verification sensor commands — fill in for your project
3
+ # (/harness-init fills these for you). Empty = that sensor is off.
4
+ # Keep in sync with the PROJECT section of CLAUDE.md.
5
+ # ════════════════════════════════════════════════════════════════
6
+
7
+ # e.g. LINT_CMD="ruff check ." (Python)
8
+ # LINT_CMD="npm run lint" (Node)
9
+ LINT_CMD=""
10
+
11
+ # e.g. TEST_CMD="pytest -q" (Python)
12
+ # TEST_CMD="npm test" (Node)
13
+ TEST_CMD=""
package/CLAUDE.md ADDED
@@ -0,0 +1,68 @@
1
+ # PROJECT
2
+
3
+ - PROJECT: [project name]
4
+ - LANGUAGE: [primary language, e.g. Python 3.12 / TypeScript 5]
5
+ - BUILD: [exact build command, e.g. `npm run build`]
6
+ - TEST: [exact test command, e.g. `npm test` / `pytest -q`]
7
+ - LINT: [exact lint command, e.g. `npm run lint` / `ruff check .`]
8
+
9
+ > Setting up for the first time? Run `/harness-init` — it scans the repository
10
+ > and fills in this section plus `.harness/commands.env`. The verification
11
+ > sensors only work once commands.env is filled. Keep both places in sync.
12
+
13
+ ## RULES
14
+
15
+ - After modifying code, always run the TEST command, read the full failure
16
+ output, and fix it. Never declare work "done" without passing tests.
17
+ - Never modify config / environment / CI / harness files (.env, *.config.*,
18
+ .github/**, .claude/**, .harness/**) without asking the user. In particular,
19
+ any change that weakens tests, lint, or guards requires confirming the
20
+ reason with the user — even if the user asked for it.
21
+ - Announce dependency additions (package installs) to the user with the
22
+ reason before running them.
23
+ - If the same error occurs 3 times, stop repeating the same approach and
24
+ write an escalation packet (see Work Loop below).
25
+ - [YYYY-MM-DD] [add new rules here with a date — /ratchet proposes them]
26
+
27
+ ## ANTI-PATTERNS
28
+
29
+ - [YYYY-MM-DD] [observed failure pattern, e.g. "ran only a -k subset because
30
+ tests were slow, then reported the full suite as passing"]
31
+
32
+ ## Work Loop
33
+
34
+ - For any task with 3+ steps, write the plan to `plan.md` before starting.
35
+ - Retry ceiling: at most 3 fix attempts per goal. Beyond that, stop and
36
+ write an escalation packet.
37
+ - Escalation packet format (report to the user):
38
+ 1. What decision is needed
39
+ 2. Alternatives already tried and why each failed
40
+ 3. The cost of waiting
41
+ 4. The safest default action if there is no response
42
+ - When the budget is exhausted (retries/time), report the best output so
43
+ far + completed work + unresolved issues + the reason for stopping.
44
+ Never hide partial failure behind a fluent summary.
45
+
46
+ ## Checkpoints
47
+
48
+ - At session start, if `progress.json` (checkpoint) exists, read it first
49
+ and do not repeat completed steps. (The SessionStart hook will remind you.)
50
+ - After completing each meaningful step, run `/checkpoint` to update
51
+ plan.md / decisions.jsonl / progress.json.
52
+ - Keep transient facts and exploratory reasoning out of checkpoints. Record
53
+ only settled decisions in decisions.jsonl.
54
+
55
+ ## When a Mistake Is Found
56
+
57
+ - Don't just fix it in conversation — make it structural: handle the mistake
58
+ with `/ratchet [what happened]` — reproduce → classify root cause →
59
+ propose a rule/sensor/permission → verify. Apply only after user approval.
60
+
61
+ ## Guide Maintenance (for humans)
62
+
63
+ - Once a month, audit this file with `/guide-audit`: delete rules the
64
+ sensors now enforce automatically, and merge contradictory rules.
65
+ - Every rule must be traceable to a date and an originating failure.
66
+ 200 undated rules is not a harness — it's tech debt.
67
+ - The same review comment 3 times → promote to a rule; the same rule
68
+ violated 3 times → promote to a gate (hook block).
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GAFFWC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,212 @@
1
+ # uni-harness
2
+
3
+ ![license](https://img.shields.io/badge/license-MIT-blue)
4
+ ![node](https://img.shields.io/badge/node-%E2%89%A516-brightgreen)
5
+ ![runtime](https://img.shields.io/badge/runtime-bash%20%2B%20python3%20stdlib-lightgrey)
6
+ ![for](https://img.shields.io/badge/for-Claude%20Code-d97757)
7
+
8
+ An agent harness kit for Claude Code. It wraps the coding agent with
9
+ automatic verification (sensors), destructive-command blocking (guards),
10
+ checkpoint-based session recovery, full tool-call logging with tripwires,
11
+ and a ratchet workflow that turns every failure into permanent structure.
12
+
13
+ > Formula: **Agent = Model + Harness.** The model brings the reasoning;
14
+ > this kit brings everything else — rules, sensors, loop limits, memory,
15
+ > and observability.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ npx uni-harness init # in your project root (or: init <path>)
21
+ ```
22
+
23
+ Then open Claude Code in the project — Claude will notice the harness is
24
+ unconfigured and **offer to run `/harness-init`** (or run it yourself). It
25
+ scans the repository, detects your build/test/lint commands, **verifies
26
+ them by actually running them**, and fills in `CLAUDE.md` and
27
+ `.harness/commands.env` with your approval. The verification sensors stay
28
+ inactive until this step is done.
29
+
30
+ Other installer commands:
31
+
32
+ ```bash
33
+ npx uni-harness update # refresh kit machinery (never touches your files)
34
+ npx uni-harness doctor # diagnose the installation
35
+ npx uni-harness uninstall --yes # remove kit machinery, keep your files
36
+ ```
37
+
38
+ Requirements: bash, python3 (stdlib only — no packages), node ≥16 for the
39
+ installer itself.
40
+
41
+ **Existing projects are safe.** `init` never overwrites anything you own:
42
+ an existing `CLAUDE.md` is kept (run `/harness-init` to have the harness
43
+ sections proposed as an append), existing `settings.json` hooks and
44
+ permissions are preserved (kit hooks are merged in), and your `.gitignore`
45
+ is appended, not replaced. `update` refreshes only unmodified kit files —
46
+ anything you've customized is skipped (listed, with `--force` to override).
47
+
48
+ ## What's Inside
49
+
50
+ | File | Role |
51
+ |---|---|
52
+ | `CLAUDE.md` | Project commands, rules, anti-patterns, work-loop and checkpoint protocols |
53
+ | `.claude/settings.json` | Hook registration |
54
+ | `.claude/hooks/sensor-post-edit.sh` | Runs lint immediately on code edits, feeds failures back |
55
+ | `.claude/hooks/stop-gate.sh` | Runs tests in batch at turn end; blocks stopping on failure (3-per-session cap, then demands escalation) |
56
+ | `.claude/hooks/guard-pre-bash.sh` | Blocks destructive commands and verification bypasses (`--no-verify`) before execution |
57
+ | `.claude/hooks/session-start.sh` | Re-injects in-progress checkpoints at session start/resume/compaction; nudges `/ratchet` when failures pile up |
58
+ | `.claude/hooks/observe-log.sh` | Logs every tool call as JSONL + tripwires (same failure 3x, call surge) |
59
+ | `.claude/agents/TEMPLATE.md` | Custom agent template (inactive until you uncomment `name`; example: fresh-context code reviewer) |
60
+ | `harness/harness_report.py` | Health scorecard from the logs |
61
+ | `harness/tests/` | Self-tests for the hooks and the installer |
62
+ | `bin/cli.js` | The installer (init / update / doctor / uninstall) |
63
+
64
+ Skills:
65
+
66
+ | Skill | Role |
67
+ |---|---|
68
+ | `/harness-init` | Scan the repo → fill PROJECT section & commands.env (once, at install) |
69
+ | `/checkpoint` | Save state to plan.md / decisions.jsonl / progress.json |
70
+ | `/ratchet [mistake]` | Reproduce → classify → propose rule/sensor/permission → verify (no args: diagnose the logs) |
71
+ | `/guide-audit` | Audit CLAUDE.md rules — keep / delete / convert-to-sensor (monthly) |
72
+
73
+ ## Recommended Permissions (optional)
74
+
75
+ The kit does not impose a permission policy. For unattended or
76
+ high-autonomy use, consider adding something like this to your project's
77
+ `.claude/settings.json` — in particular the entries that stop the agent
78
+ from editing its own harness:
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
+ ## Operating Routine
97
+
98
+ - **Daily / per task:** just work. Sensors and guards are automatic. For
99
+ long tasks, save state with `/checkpoint`.
100
+ - **When you spot a mistake:** don't just fix it in conversation — run
101
+ `/ratchet [what happened]` to make it structural. Same review comment
102
+ 3x → rule; same rule violated 3x → promote to a guard/permission.
103
+ - **Weekly:** check the scorecard with `python3 harness/harness_report.py`;
104
+ if repeated failures show up, run `/ratchet`.
105
+ - **Monthly:** audit CLAUDE.md with `/guide-audit` — delete rules the
106
+ sensors now enforce, merge contradictions.
107
+
108
+ ## Customizing
109
+
110
+ - Dangerous command patterns: `DENY_PATTERNS` in `guard-pre-bash.sh`
111
+ - Tripwire thresholds: `observe-log.sh` (defaults: same failure 3x, 300 calls)
112
+ - Sensor file extensions: the case statement in `sensor-post-edit.sh`
113
+ - Stop-gate block cap: `stop-gate.sh` (default: 3 per session)
114
+ - If you modify a hook, add a case to `harness/tests/test_hooks.sh` and run it
115
+
116
+ ## When Not to Use This
117
+
118
+ It's overkill for one-off questions, exploratory brainstorming, or
119
+ unverifiable creative work. It earns its keep on work that runs
120
+ repeatedly, has real consequences on failure, runs unsupervised, or must
121
+ preserve state across sessions.
122
+
123
+ ## Design Background
124
+
125
+ This kit is a working implementation of two sources. Full analyses live in
126
+ [`docs/`](docs/) — they are not shipped with the npm package (the running
127
+ agent doesn't need theory), but they explain every design decision here.
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 et al. (2026)
132
+ > Deep-dive: [docs/analysis-01-envharness.md](docs/analysis-01-envharness.md)
133
+
134
+ **What the paper says.** Just as attaching a harness (tools, memory,
135
+ skills) to an *agent* extends it without touching its weights, you can
136
+ attach a harness to an *environment* and customize its learning signal
137
+ without touching its code: `Static Env + EnvHarness = Customized Env`.
138
+ Environments are transformed only at the interface layer through three
139
+ composable components — **Stage** (reshape the initial state), **Contract**
140
+ (filter actions, transform observations, wrap transitions), **Chain**
141
+ (compose environments) — so the original ground-truth verifier is always
142
+ preserved, which is the method's core advantage over LLM-generated
143
+ environments. An automated loop called **EnvRigger** drives the design:
144
+ *Observe* failure trajectories → *Diagnose* root causes → *Write* a
145
+ transformation → *Validate* it against the original failure. Across five
146
+ benchmarks the wrapped environments lift agent performance (e.g. ALFWorld
147
+ out-of-distribution +9.0 points, SWE-bench Verified +2.7 with 9.8% fewer
148
+ steps) — with the biggest gains out-of-distribution, evidence of transfer
149
+ rather than memorization.
150
+
151
+ **What this kit takes from it:**
152
+
153
+ | Paper concept | Implementation here |
154
+ |---|---|
155
+ | EnvRigger loop (Observe → Diagnose → Write → Validate) | the `/ratchet` skill — with automated acceptance replaced by **user approval** |
156
+ | Contract: action filtering | `guard-pre-bash.sh` (destructive commands blocked pre-execution) |
157
+ | Contract: structured feedback | `sensor-post-edit.sh` / `stop-gate.sh` (verification results fed back) |
158
+ | Stage: prepared initial state | checkpoint recovery at session start |
159
+ | **Preserve the original verifier** | invariant: the harness wraps your test suite and may never modify or bypass it |
160
+
161
+ ### 📘 Harness Engineering: The 6-Layer Production Playbook
162
+
163
+ > A synthesis of public practitioner material — [Mitchell Hashimoto](https://mitchellh.com/)'s
164
+ > ratchet methodology, the [OpenAI Codex field report](https://openai.com/index/harness-engineering),
165
+ > [Martin Fowler](https://martinfowler.com/)'s guides-and-sensors taxonomy, and
166
+ > Anthropic / LangChain / Cursor sources.
167
+ > Deep-dive: [docs/analysis-02-harness-engineering.md](docs/analysis-02-harness-engineering.md)
168
+
169
+ **What the playbook says.** Prompt engineering (what the model *says*) and
170
+ context engineering (what the model *sees*) are subsumed by harness
171
+ engineering: what the model *can do*, what survives failure, what is
172
+ permitted, and what counts as done. The claim **Agent = Model + Harness**
173
+ is backed by self-reported but consistent evidence — the same model
174
+ jumping 30.91% → 74.55% on GAIA from a harness swap alone, a fixed model
175
+ climbing rank 30 → 5 on Terminal Bench through harness optimization. The
176
+ architecture is six layers, and they map one-to-one onto this kit:
177
+
178
+ | # | Layer | Principle | In this kit |
179
+ |---|---|---|---|
180
+ | 1 | **Guides** | each line = permanent prevention of one past failure | `CLAUDE.md` |
181
+ | 2 | **Sensors** | external deterministic checks, never self-judgment | `sensor-post-edit.sh`, `stop-gate.sh` |
182
+ | 3 | **Agentic Loop** | ceilings on every budget, escalate on exhaustion | Work Loop protocol + tripwires + 3-block stop cap |
183
+ | 4 | **Memory** | the filesystem is the memory; must pass the recovery test | `/checkpoint` + `session-start.sh` |
184
+ | 5 | **Permissions** | the model cannot limit itself | `guard-pre-bash.sh` + recommended permissions |
185
+ | 6 | **Observability** | record everything, alert on drift | `observe-log.sh` + `harness_report.py` |
186
+
187
+ The operating rules come from it too — Hashimoto's **ratchet principle**
188
+ ("every time the agent makes a mistake, engineer a solution that makes
189
+ that mistake impossible to repeat") and Cursor's promotion ladder:
190
+
191
+ ```mermaid
192
+ flowchart LR
193
+ F[failure observed] --> R["/ratchet: reproduce + diagnose"]
194
+ R --> P{strongest layer}
195
+ P -->|context was missing| G["guide rule (CLAUDE.md)"]
196
+ P -->|detectable by check| S[sensor / lint rule]
197
+ P -->|should be impossible| H[guard / permission]
198
+ G & S & H --> V[verified against the original failure]
199
+ V --> N[the same failure cannot recur]
200
+ ```
201
+
202
+ Same review comment **3×** → becomes a rule. Same rule violated **3×** →
203
+ becomes a gate. And the maturity signal is a *declining* growth rate of
204
+ rules — a harness that only accumulates is debt, which is what
205
+ `/guide-audit` exists to prevent.
206
+
207
+ ---
208
+
209
+ Extending the kit itself? Start with
210
+ [docs/AGENT_BRIEFING.md](docs/AGENT_BRIEFING.md) — it carries the
211
+ invariants (never weaken verification, no auto-apply without approval,
212
+ minimal infrastructure) and the vetted backlog.