ai2rules-harness 0.7.0 → 0.8.1

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.
Files changed (3) hide show
  1. package/README.md +165 -71
  2. package/bin/harness.js +1 -1
  3. package/package.json +8 -9
package/README.md CHANGED
@@ -1,116 +1,210 @@
1
1
  # ai2rules-harness
2
2
 
3
- **Govern a local coding agent in one command.**
3
+ **Govern a local coding agent in one command.** A deterministic kernel decides every
4
+ tool call Claude Code proposes, before it runs. No model takes part in the decision.
4
5
 
5
6
  ```bash
6
7
  npm install -g ai2rules-harness
7
- harness init
8
- harness demo # prove the kernel decides — 8 cases, no execution, no credentials
8
+ cd your-project
9
+ harness init # govern this project
10
+ harness demo # watch the kernel decide: 5 cases, nothing executed
9
11
  ```
10
12
 
11
- `init` writes a governance manifest, a `PreToolUse` shim, and the host settings entry
12
- into the current project. It is safe to run twice, it never replaces a manifest you
13
- have tuned, and turning it off is one file. `demo` is the credential-free first proof:
14
- it runs eight cases through the real kernel (Read, Write, Shell, JIRA_CREATE_ISSUE,
15
- scoped actions, path roots, poisoned knowledge, classification), records each verdict,
16
- and replays them to prove deterministic decisions. Decision-only, no tool execution.
13
+ > **The package is `ai2rules-harness`; the command it installs is `harness`.**
14
+ > npm does not print the commands a package adds, so if you are wondering what
15
+ > you got: it is one command, `harness`. Run `harness --help` for the list.
17
16
 
18
- > **Install it globally, not into a project.** `harness init` **refuses** to run
19
- > when the binary lives inside the project it would govern — a local
20
- > `node_modules` install puts the kernel in the agent's own writable root, where
21
- > replacing one file turns governance off silently. `npx ai2rules-harness init`
22
- > is fine: its cache is outside your project.
17
+ ## Install
23
18
 
24
- ## How it installs — and why there is no install script
19
+ ```bash
20
+ npm install -g ai2rules-harness
21
+ harness --version
22
+ ```
25
23
 
26
- The binary arrives as a **platform package** (`ai2rules-harness-linux-x64` and
27
- friends), listed in `optionalDependencies`. npm resolves exactly one by `os`/`cpu`
28
- and skips the rest.
24
+ - **No Rust, no build step.** npm installs a prebuilt binary for your platform:
25
+ Linux x64, macOS (Intel and Apple Silicon), Windows x64.
26
+ - **Install it globally, not into a project.** `harness init` refuses to run when
27
+ the binary lives inside the project it would govern: a local `node_modules`
28
+ install puts the kernel in the agent's own writable folder, where replacing one
29
+ file turns governance off silently. Not `npx ai2rules-harness init` either: the
30
+ hook would point into npx's cache, and when npm prunes it governance turns off
31
+ silently. `npx` is fine for commands that install nothing, such as
32
+ `demo --story law-firm`, `replay-transcripts` and `doctor`.
33
+ - **Windows:** run it from PowerShell or Git Bash. Claude Code runs the hook through
34
+ Git Bash, which Claude Code on Windows already needs.
35
+ - **Update:** `npm install -g ai2rules-harness@latest`.
29
36
 
30
- That means installing this package runs **no install script, makes no network
31
- request, executes no shell, and chmods nothing**. Earlier versions downloaded a
32
- binary in a `postinstall` and verified a checksum fetched from the same host — which
33
- proves the file arrived intact, not that it is the right file. Now the binary is
34
- covered by the integrity hash npm writes into *your* lockfile, and the tarballs
35
- carry [npm provenance](https://docs.npmjs.com/generating-provenance-statements)
36
- signed against the workflow and commit that built them.
37
+ If your platform has no prebuilt binary, the CLI tells you how to build one, or you
38
+ point the `AI2RULES_HARNESS` environment variable at an existing binary.
37
39
 
38
- Practical upshots: installs are reproducible, work offline from a cache, and work
39
- behind a proxy or a mirrored registry — none of which was true before.
40
+ ## A five-minute tour
40
41
 
41
- If your platform has no prebuilt binary, nothing silently breaks: the CLI tells you
42
- how to build one, or you point `AI2RULES_HARNESS` at an existing binary.
42
+ **1. Govern a project.** In the project's folder:
43
43
 
44
- ## What it does
44
+ ```bash
45
+ harness init
46
+ ```
45
47
 
46
- A local coding agent inherits your whole shell: credentials, git remotes, package
47
- managers, write access to everything. It also reads untrusted text on every turn —
48
- web pages, issue bodies, tool results. Prompt injection is therefore a question
49
- about *authority*, not about prompts.
48
+ This writes into the project: a policy file (`.claude/cc-world.yaml`), a small hook
49
+ script (`.claude/hooks/world-gate.sh`), the hook entries in `.claude/settings.json`,
50
+ and a `.gitignore` line for the runtime state. From the next Claude Code session on,
51
+ every tool call goes through the kernel first, and each decision and how the call
52
+ ended go to a local log, `.claude/state/decisions.jsonl`. It is safe to run twice and never replaces a policy you
53
+ have edited. Add `--dry-run` to see the plan without writing anything.
50
54
 
51
- This installs a deterministic kernel between the agent and the world. No model
52
- takes part in the decision: a verdict is a pure function of the proposed call, the
53
- session's context, and a compiled manifest.
55
+ **2. Watch it decide.**
54
56
 
55
- ## Prove it works
57
+ ```bash
58
+ harness demo
59
+ ```
60
+
61
+ Five cases through the real kernel and your project's policy: an in-project write
62
+ is allowed, an out-of-project write in the background is denied, tainted input
63
+ (text that came from outside, such as a web page) cannot reach the network, and a
64
+ destructive command needs your approval. Every verdict is written to a log and
65
+ replayed to show the decisions are reproducible. Nothing is executed and no
66
+ credentials are needed.
56
67
 
57
- After `init`, run the built-in demonstration:
68
+ No project at hand? `harness demo --story law-firm` tells a story over its own
69
+ built-in policy, no `init` needed: an AI legal assistant reads a poisoned client
70
+ email. Add `--html story.html` for a page you can step through in a browser.
71
+
72
+ **3. Check the installation.**
58
73
 
59
74
  ```bash
60
- harness demo
75
+ harness doctor
61
76
  ```
62
77
 
63
- Eight cases through the real kernel (ALLOW for in-root read, DENY for out-of-root
64
- write, DENY for tainted network, ASK for destructive shell, DENY for background
65
- destructive shell, and three classification/scoped/knowledge cases), with immediate
66
- replay to prove deterministic decisions. No credentials, no execution.
78
+ Reports whether the binary, the hook and the policy are in place and what the
79
+ policy covers.
80
+
81
+ **4. See what it would have done to your past sessions.**
82
+
83
+ ```bash
84
+ harness replay-transcripts
85
+ ```
67
86
 
68
- The demo footer says "Next: harness doctor" — that command is planned (issue AI2-25)
69
- but not yet shipped; the reference is honest about what comes next, not a claim it
70
- exists today.
87
+ Replays the tool calls from your earlier Claude Code sessions
88
+ (`~/.claude/projects`) through the kernel and reports how often it would have
89
+ allowed, asked or denied, and why. Nothing is executed and nothing leaves the
90
+ machine. It works without `init`, so it is a good first look before you govern
91
+ anything.
71
92
 
72
- Or ask the kernel directly about one call — no agent session needed:
93
+ **5. Change the policy with switches.**
73
94
 
74
95
  ```bash
75
- echo '{"tool_name":"Write","tool_input":{"file_path":"/etc/passwd"}}' \
76
- | CLAUDE_PROJECT_DIR=$PWD bash .claude/hooks/world-gate.sh
96
+ harness console
77
97
  ```
78
98
 
79
- You get a deny with a reason. The identical write *inside* your project stays
80
- silent. That is a path-scope policy, and it is the thing a list of allowed command
81
- strings cannot express — it is about where the path points, not what the command
82
- looks like.
99
+ Serves a local page (127.0.0.1 only) and prints its address, `http://127.0.0.1:8790/`
100
+ by default; open it in a browser. The page has profiles and Allow / Ask / Off
101
+ switches for groups of actions. The switches rewrite the project's policy file, and
102
+ a running Claude Code session follows Allow and Ask on its very next tool call. The
103
+ page also shows the live feed of decisions.
104
+
105
+ **Off** removes actions from the policy (ABSENT, below). The hook `harness init`
106
+ writes leaves such calls to Claude Code's own permissions, so Off blocks them only
107
+ when the hook runs with `--enforce-absent`; the page warns when it does not.
108
+
109
+ ## Commands
110
+
111
+ **Everyday**
112
+
113
+ | Command | What it does |
114
+ |---|---|
115
+ | `harness init` | Govern the project in this folder. `--dry-run` shows the plan; `--grant` makes the policy the allowlist (see Modes) |
116
+ | `harness init --user` | Govern every Claude Code session your account opens, in any folder. `--remove` undoes it |
117
+ | `harness init --managed` | Govern every session on the machine, for every account, through Claude Code's managed settings. Needs an admin shell |
118
+ | `harness demo` | The first proof: 5 decisions over this project's policy, replayed |
119
+ | `harness demo --story law-firm` | A story for a non-technical audience, with its own policy; `--html <file>` for a browser page |
120
+ | `harness doctor` | Check the installation and coverage in this project; `--json` for a machine-readable report |
121
+ | `harness replay-transcripts` | Replay past Claude Code sessions through the kernel and report what it would have decided |
122
+ | `harness console` | Local page to switch groups of actions between Allow, Ask and Off |
123
+ | `harness serve` | Local browser editor for policy files, backed by the real compiler and kernel |
124
+
125
+ **Integration** (what hooks, gateways and scripts call; you rarely type these)
126
+
127
+ | Command | What it does |
128
+ |---|---|
129
+ | `harness cc-hook` | The Claude Code hook. `init` wires it up for you. `--log <file>` keeps a decision log |
130
+ | `harness agy-hook` | The same hook for the Antigravity CLI (`agy`) |
131
+ | `harness gate` | Decide one proposed tool call: JSON request on stdin, verdict on stdout |
132
+ | `harness project` | Filter a host's offered tool list through the policy: tools the policy does not know are hidden |
133
+ | `harness mcp-gateway` | Put the kernel in front of a real MCP server: hide tools the policy does not declare, forward only allowed calls |
134
+ | `harness mcp-author` | Browser page to pick, rename and limit an MCP server's tools into a scoped surface |
135
+ | `harness approvals` | Review and answer approvals recorded by `mcp-gateway --approvals` |
136
+ | `harness export-otlp` | Convert a decision log to OpenTelemetry traces (OTLP/JSON) for a collector |
137
+ | `harness mock-jira` | A self-contained mock JIRA MCP server, the demo upstream for `mcp-gateway` |
138
+
139
+ `harness <command> --help` shows every option.
140
+
141
+ ## Verdicts
142
+
143
+ Every call gets one of five answers:
144
+
145
+ | Verdict | Meaning |
146
+ |---|---|
147
+ | **ALLOW** | Permitted. The host goes ahead (or asks as it normally would, in the default mode) |
148
+ | **ASK** | A person must approve it first |
149
+ | **DENY** | Refused, with the rule and the reason |
150
+ | **ABSENT** | The policy does not declare this action. An MCP gateway hides such tools from the agent; the Claude Code hook leaves the call to Claude Code unless you pass `--enforce-absent` |
151
+ | **REPLAN** | Over a budget the policy sets, such as `max_commands_per_task`: the agent should take a smaller step. It is not a refusal. The Claude Code and Antigravity hooks have no way to say "smaller step", so they leave the call to the host, as with ALLOW |
152
+
153
+ The verdict is a pure function of the proposed call, what the session has already
154
+ read, and the compiled policy. The same inputs always give the same answer, which is
155
+ why a decision log can be replayed.
83
156
 
84
157
  ## Modes
85
158
 
86
159
  | Command | Behaviour |
87
160
  |---|---|
88
- | `harness init` | **Additive.** Adds deny/ask on top of the host's own permissions. Cannot lock you out. |
89
- | `harness init --grant` | **Replace.** The manifest becomes the allowlist and grants directly, so the host stops asking. |
90
- | `harness init --dry-run` | Print the plan, write nothing. |
161
+ | `harness init` | **Additive.** Adds deny and ask on top of Claude Code's own permissions. Cannot lock you out. |
162
+ | `harness init --grant` | **Replace.** The policy becomes the allowlist and grants directly, so Claude Code stops asking for what it allows. |
91
163
 
92
164
  ## Turning it off
93
165
 
94
166
  Effective on the very next tool call, no restart:
95
167
 
96
168
  ```bash
97
- touch ~/.claude/ai2rules/off/<your-project> # this project
98
- touch ~/.claude/gate-off # everywhere
169
+ mkdir -p ~/.claude/ai2rules/off && touch ~/.claude/ai2rules/off/<your-project> # this project
170
+ touch ~/.claude/gate-off # every project
99
171
  ```
100
172
 
101
- `harness init` prints the exact per-project path. Both live **outside** the
102
- governed project on purpose: a switch inside it is one the agent can throw itself.
103
- Delete the file to re-enable. The shim runs per call, so the toggle is immediate.
173
+ `harness init` prints the exact command for this project, path quoted. In
174
+ PowerShell, create the same file with `New-Item -ItemType File -Force '<path>'`.
175
+ Both switches live **outside** the governed project on purpose: a switch inside it
176
+ is one the agent could flip itself. Delete the file to turn governance back on.
177
+
178
+ To remove it from a project for good, delete the hook entries that call
179
+ `world-gate.sh` from `.claude/settings.json`.
180
+
181
+ ## How it installs, and why there is no install script
182
+
183
+ The binary arrives as a **platform package** (`ai2rules-harness-linux-x64` and the
184
+ others), listed in `optionalDependencies`. npm picks exactly one by operating system
185
+ and CPU and skips the rest.
186
+
187
+ So the package runs **no install script**: nothing of ours executes at install time,
188
+ downloads anything beyond what npm itself fetches from the registry, runs a shell or
189
+ changes file permissions. The binary is covered by the integrity hash npm writes into
190
+ your lockfile. Installs are reproducible, work offline from a cache, and work behind
191
+ a proxy or a mirrored registry.
192
+
193
+ Releases are published from CI with npm trusted publishing, not from a developer's
194
+ machine. Versions 0.2.0 to 0.7.0, built while the repository was public, also carry
195
+ [npm provenance](https://docs.npmjs.com/generating-provenance-statements), a
196
+ signature tying them to the workflow and commit that built them. npm does not
197
+ generate provenance for packages published from a private repository, so 0.8.0
198
+ and later do not have it.
104
199
 
105
200
  ## Honest boundaries
106
201
 
107
202
  - **Governed is not sandboxed.** This decides what an agent may *do*; it does not
108
- contain where it runs. Both matter and they are different properties.
109
- - **Depth is asymmetric.** Deep on hosts that expose a pre-execution hook; at the
110
- MCP seam only on hosts that do not. What each host actually permits is measured
111
- in [the Agent Governability Index](https://github.com/sv-pro/ai2rules/blob/main/docs/GOVERNABILITY-INDEX.md),
112
- including the cells where the answer is unknown.
113
- - **This installs a policy you should read.** `.claude/cc-world.yaml` is a starter,
114
- not a finished judgement about your project.
115
-
116
- MIT OR Apache-2.0 · [source](https://github.com/sv-pro/ai2rules)
203
+ contain where it runs. Both matter, and they are different properties.
204
+ - **Depth depends on the host.** Deep on hosts that offer a hook before each tool
205
+ call (Claude Code, Antigravity); at the MCP server boundary only on hosts that do
206
+ not.
207
+ - **Read the policy you install.** `.claude/cc-world.yaml` is a starter, not a
208
+ finished judgement about your project.
209
+
210
+ MIT OR Apache-2.0 · [ai2rules.dev](https://ai2rules.dev)
package/bin/harness.js CHANGED
@@ -55,7 +55,7 @@ if (!bin || !fs.existsSync(bin)) {
55
55
 
56
56
  Build one, or point at an existing binary:
57
57
 
58
- cargo install --git https://github.com/sv-pro/ai2rules cli-harness
58
+ cargo install --git https://github.com/ai2rules/kernel cli-harness
59
59
  export AI2RULES_HARNESS=/absolute/path/to/harness
60
60
  `);
61
61
  process.exit(127);
package/package.json CHANGED
@@ -1,15 +1,14 @@
1
1
  {
2
2
  "name": "ai2rules-harness",
3
- "version": "0.7.0",
4
- "description": "Deterministic governance for local CLI coding agents. `npx ai2rules-harness init` governs a project in one command.",
3
+ "version": "0.8.1",
4
+ "description": "Deterministic governance for local CLI coding agents. Install globally, then `harness init` governs a project in one command.",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "git+https://github.com/sv-pro/ai2rules.git",
8
+ "url": "git+https://github.com/ai2rules/kernel.git",
9
9
  "directory": "npm"
10
10
  },
11
- "homepage": "https://github.com/sv-pro/ai2rules#govern-a-project-in-one-command",
12
- "bugs": "https://github.com/sv-pro/ai2rules/issues",
11
+ "homepage": "https://ai2rules.dev",
13
12
  "keywords": [
14
13
  "ai",
15
14
  "agent",
@@ -32,9 +31,9 @@
32
31
  "node": ">=18"
33
32
  },
34
33
  "optionalDependencies": {
35
- "ai2rules-harness-darwin-arm64": "0.7.0",
36
- "ai2rules-harness-darwin-x64": "0.7.0",
37
- "ai2rules-harness-linux-x64": "0.7.0",
38
- "ai2rules-harness-windows-x64": "0.7.0"
34
+ "ai2rules-harness-darwin-arm64": "0.8.1",
35
+ "ai2rules-harness-darwin-x64": "0.8.1",
36
+ "ai2rules-harness-linux-x64": "0.8.1",
37
+ "ai2rules-harness-windows-x64": "0.8.1"
39
38
  }
40
39
  }