Skip to content

Commit 6f8baff

Browse files
committed
Add iso-guard package
1 parent 620882b commit 6f8baff

25 files changed

Lines changed: 1824 additions & 13 deletions

.github/workflows/ci.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ jobs:
5656
- workspace: "@razroo/iso-trace"
5757
node: "20.6.0"
5858
extra: ""
59+
- workspace: "@razroo/iso-guard"
60+
node: "20.6.0"
61+
extra: ""
5962
- workspace: "@razroo/agentmd"
6063
node: "22.0.0"
6164
extra: ""
@@ -148,6 +151,18 @@ jobs:
148151
- name: iso-trace example stats
149152
run: node packages/iso-trace/dist/cli.js stats --source packages/iso-trace/examples/sample-session.jsonl
150153

154+
- name: iso-guard example audit
155+
run: |
156+
cat > /tmp/iso-guard-events.json <<'JSON'
157+
[
158+
{ "type": "tool_call", "name": "geometra_disconnect", "data": { "round": 1 } },
159+
{ "type": "tool_call", "name": "task", "data": { "round": 1, "mode": "apply" } },
160+
{ "type": "tool_call", "name": "job-forge-merge" },
161+
{ "type": "tool_call", "name": "job-forge-verify" }
162+
]
163+
JSON
164+
node packages/iso-guard/dist/cli.js audit packages/iso-guard/examples/jobforge-apply.yaml --events /tmp/iso-guard-events.json
165+
151166
- name: iso-route example build (dry-run + verify)
152167
run: node packages/iso-route/dist/cli.js build packages/iso-route/examples/models.yaml --out /tmp/iso-route-smoke --dry-run --verify-models
153168

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: iso-guard Release to npm
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
defaults:
8+
run:
9+
working-directory: packages/iso-guard
10+
11+
jobs:
12+
publish:
13+
if: startsWith(github.ref_name, 'iso-guard-v')
14+
runs-on: ubuntu-latest
15+
permissions:
16+
contents: read
17+
checks: read
18+
id-token: write
19+
steps:
20+
- uses: actions/checkout@v6
21+
22+
- uses: actions/setup-node@v6
23+
with:
24+
node-version: '22'
25+
registry-url: 'https://registry.npmjs.org'
26+
cache: 'npm'
27+
28+
- name: Set version from release tag
29+
run: |
30+
VERSION="${GITHUB_REF_NAME#iso-guard-v}"
31+
echo "VERSION=$VERSION" >> $GITHUB_ENV
32+
33+
- name: Verify required CI passed for release commit
34+
uses: ./.github/actions/verify-release-gate
35+
env:
36+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37+
38+
- name: Verify package.json version matches release tag
39+
run: npm run release:check-source -- "$VERSION"
40+
41+
- name: Install (workspace root)
42+
run: npm ci
43+
working-directory: .
44+
45+
- name: Publish to npm (with provenance)
46+
run: npm publish --provenance --access public
47+
env:
48+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

CLAUDE.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# iso — monorepo
22

3-
Workspaces monorepo (npm) housing eight Razroo tools that together make
3+
Workspaces monorepo (npm) housing nine Razroo tools that together make
44
AI-agent harnesses *isomorphic* — the same authored source producing the
55
same behavior across every coding harness (Cursor, Claude Code, Codex,
66
OpenCode) and every model tier (frontier → 7B local).
@@ -31,9 +31,8 @@ cross-package compositions and the decouplings that are deliberate.
3131
**Wrapper:**
3232

3333
- `packages/iso``@razroo/iso`. Chains `agentmd → isolint →
34-
iso-harness` behind one CLI. Plain ESM `.mjs`. Depends on the sibling
35-
packages via workspace protocol. (iso-route is *not* composed yet — see
36-
`INTEGRATIONS.md` item #2.)
34+
iso-route → iso-harness` behind one CLI when `models.yaml` exists.
35+
Plain ESM `.mjs`. Depends on the sibling packages via workspace protocol.
3736

3837
**Feedback (post-deploy):**
3938

@@ -43,6 +42,9 @@ cross-package compositions and the decouplings that are deliberate.
4342
- `packages/iso-trace``@razroo/iso-trace`. Parses Claude Code JSONL
4443
sessions into a normalized event model for local observability. Zero
4544
upload. TypeScript.
45+
- `packages/iso-guard``@razroo/iso-guard`. Deterministic runtime
46+
policy checks over normalized event streams and `iso-trace export`
47+
JSON/JSONL. TypeScript.
4648

4749
**Runtime control:**
4850

INTEGRATIONS.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Integrations
22

3-
This repo ships eight packages that **work on their own** but are **designed
3+
This repo ships nine packages that **work on their own** but are **designed
44
to compose**. The planned cross-package compositions listed here are already
55
shipped, so this file now serves as:
66

@@ -102,6 +102,18 @@ resolved role map — plus fixture export output from the trace loop.
102102

103103
---
104104

105+
## 6. `iso-guard` ← consumes `iso-trace export` JSON/JSONL — **DONE**
106+
107+
Introduced with `@razroo/iso-guard`'s initial release. The guard package
108+
accepts either small normalized event arrays or `iso-trace export
109+
<session> --format json|jsonl` output, flattens those events, and
110+
evaluates deterministic runtime policy rules (`max-per-group`,
111+
`require-before`, `require-after`, `forbid-text`, `no-overlap`). This
112+
keeps enforcement outside the prompt/MCP surface while still letting a
113+
project audit real agent behavior after a run.
114+
115+
---
116+
105117
## Design questions that are *not* open integrations
106118

107119
The following look like integrations but are deliberately decoupled —
@@ -128,3 +140,8 @@ don't "fix" them without a conversation first.
128140
`build --verify-models` exist, but the default `build` path still
129141
validates provider names, not model IDs. Asking a live catalog is an
130142
opt-in check, not part of the baseline transpile step.
143+
- **`iso-guard` is not an MCP server.** It is a CLI/library that reads
144+
event files and emits compact pass/fail output. If a domain package
145+
wants in-loop preflight, it should call the CLI and feed only the
146+
concise result back to the agent, not load the whole policy into the
147+
prompt prefix.

README.md

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Today, writing agent instructions is fragmented on two axes:
2525
unstructured rationale all drop silently at 7B. You don't find out
2626
until the agent misbehaves in production.
2727

28-
Eight packages solve that in one pipeline with a control layer and feedback loop:
28+
Nine packages solve that in one pipeline with a control layer and feedback loop:
2929

3030
- **Four build-time tools** turn your authored source into every harness's file layout:
3131
[`@razroo/agentmd`](./packages/agentmd) validates *structure*,
@@ -37,9 +37,10 @@ Eight packages solve that in one pipeline with a control layer and feedback loop
3737
- **One orchestration library** handles durable runtime control:
3838
[`@razroo/iso-orchestrator`](./packages/iso-orchestrator) provides resumable
3939
steps, keyed mutexes, and bounded fan-out for side-effectful agent workflows.
40-
- **Two feedback tools** close the loop after deploy:
40+
- **Three feedback tools** close the loop after deploy:
4141
[`@razroo/iso-eval`](./packages/iso-eval) scores *did the agent complete the task?* and
42-
[`@razroo/iso-trace`](./packages/iso-trace) parses production transcripts to show *what the agent actually did*.
42+
[`@razroo/iso-trace`](./packages/iso-trace) parses production transcripts to show *what the agent actually did*,
43+
while [`@razroo/iso-guard`](./packages/iso-guard) enforces operational policies against those event streams.
4344

4445
```
4546
authoring build output feedback
@@ -49,6 +50,7 @@ Eight packages solve that in one pipeline with a control layer and feedback loop
4950
│ │ render │ load-bearing why │ │ │ │ .cursor/rules/* │ iso-trace ──▶ production events,
5051
└────────────────────┘ └───────────────────┘ └─────────────────┘ │ .opencode/agents/* │ which rules ever fired,
5152
│ settings.json │ regression-fixture mining
53+
│ │ iso-guard ─▶ policy pass / fail
5254
┌────────────────────┐ │ .codex/config.toml │
5355
│ models.yaml │ ───────────────────── iso-route build ─────────────────────────────────────▶│ opencode.json │
5456
│ (roles + fallback) │ │ .mcp.json │
@@ -99,6 +101,8 @@ the repo now supports a tighter loop:
99101
tend to surface first on Claude Code, Codex, and OpenCode.
100102
- `iso-trace export-fixture --runner <name>` turns a real failure into an
101103
`iso-eval` suite you can replay across shipped runners.
104+
- `iso-guard audit` checks whether a real run obeyed operational policy
105+
without turning those rules into more prompt tokens.
102106

103107
## Packages
104108

@@ -158,6 +162,13 @@ the repo now supports a tighter loop:
158162
transcripts do not yet expose stable model metadata. Zero upload —
159163
everything is local reads and user-controlled output.
160164

165+
- **[`packages/iso-guard`](./packages/iso-guard)**[`@razroo/iso-guard`](https://www.npmjs.com/package/@razroo/iso-guard)
166+
Deterministic runtime policy checks for agent workflows. Reads normalized
167+
event streams or `iso-trace export` JSON/JSONL and verifies invariants
168+
such as bounded fan-out, cleanup-before-dispatch, required follow-up
169+
commands, no overlapping same-key work, and prompt secret redaction.
170+
No model calls, no MCP server, and no injected prompt overhead.
171+
161172
- **[`packages/iso-orchestrator`](./packages/iso-orchestrator)**`@razroo/iso-orchestrator`
162173
Durable orchestration primitives for the runtime layer above a single
163174
agent session. Persists workflow state to local disk, memoizes
@@ -261,6 +272,15 @@ iso-trace export <id> --format jsonl --redact > session.jsonl
261272
iso-trace export-fixture <id> --out fixtures/my-task --runner codex --edit-checks exists-only --run
262273
```
263274

275+
### `@razroo/iso-guard` — did the run obey policy?
276+
277+
```bash
278+
iso-guard audit guard.yaml --events session.json
279+
iso-guard audit guard.yaml --events session.jsonl --json
280+
iso-guard verify guard.yaml --events session.json --fail-on warn
281+
iso-guard explain guard.yaml
282+
```
283+
264284
## Layout
265285

266286
```
@@ -275,7 +295,8 @@ iso/
275295
├── iso-route/ # one model policy → per-harness config
276296
├── iso-orchestrator/ # durable runtime control above one agent session
277297
├── iso-eval/ # behavioral eval on the produced harness
278-
└── iso-trace/ # parse + query real agent transcripts (observability)
298+
├── iso-trace/ # parse + query real agent transcripts (observability)
299+
└── iso-guard/ # deterministic runtime policy checks over events
279300
```
280301

281302
## Build & test
@@ -290,6 +311,7 @@ npm run test:pack # pack local tarballs and smoke installed CLIs
290311
npm run test:pipeline # end-to-end demo (agentmd → isolint → iso-harness)
291312
npm --workspace @razroo/iso-eval run example # iso-eval against the bundled example suite
292313
npm --workspace @razroo/iso-trace run example # iso-trace stats on the bundled sample transcript
314+
npm --workspace @razroo/iso-guard run test # iso-guard policy engine tests
293315

294316
# Target a single package
295317
npm run build --workspace @razroo/isolint
@@ -325,7 +347,7 @@ build, and `npm publish --provenance`.
325347
## End-to-end example
326348

327349
[`examples/pipeline/`](./examples/pipeline) is an executable demonstration
328-
that exercises **seven of the eight packages end-to-end** in one `npm run
350+
that exercises **seven of the nine packages end-to-end** in one `npm run
329351
test:pipeline` invocation: `agentmd lint` + `render``isolint lint` →
330352
`iso-route build` (from a bundled `models.yaml` that extends the
331353
`standard` preset) → `iso-harness build` (which consumes iso-route's
@@ -344,8 +366,9 @@ downstream repo would use.
344366

345367
`npm run test:pack` goes one level further: it packs the local workspaces into
346368
tarballs, installs them into fresh temp projects, and smoke-tests the packaged
347-
`iso-harness`, `iso`, `iso-eval`, and `iso-trace` CLIs. This guards against
348-
packaging regressions that workspace-only tests can miss.
369+
`iso-harness`, `iso`, `iso-eval`, `iso-trace`, `iso-route`, and `iso-guard`
370+
CLIs. This guards against packaging regressions that workspace-only tests can
371+
miss.
349372

350373
[`packages/iso-eval/examples/suites/echo-basic/`](./packages/iso-eval/examples/suites/echo-basic)
351374
is a runnable eval suite for the downstream side: a baseline workspace, a

package-lock.json

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/iso-guard/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# @razroo/iso-guard
2+
3+
## 0.1.0
4+
5+
### Minor Changes
6+
7+
- Introduce `@razroo/iso-guard`, a deterministic CLI/library for auditing agent workflow events against machine-readable runtime policy without adding prompt or MCP token overhead.
8+
- Adds deterministic policy auditing over normalized event streams and
9+
`iso-trace export` JSON/JSONL.
10+
- Supports `max-per-group`, `require-before`, `require-after`,
11+
`forbid-text`, and `no-overlap` rules.

packages/iso-guard/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Razroo
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.

0 commit comments

Comments
 (0)