Skip to content

v1.4.0 — jankurai guard: realtime per-file audit gate for every AI agent

Choose a tag to compare

@jeppsontaylor jeppsontaylor released this 15 May 00:14
3dad310

What's new

jankurai audit-file — single-file save-gate engine

A new subcommand that audits one candidate file before it reaches disk. It overlays the candidate bytes on the in-memory Vec<FileInfo> inventory, runs the full 10-dimension + 43-rule audit pipeline scoped to "file-plus-control" (the candidate + AGENTS.md/CLAUDE.md/Cargo.*/package.json/Justfile/agent configs/.github/workflows/** + sibling modules), and returns a delta-based verdict:

Exit Meaning
0 Pass — no new findings
2 Advisory — new soft findings only
3 Block — new hard finding, worsened severity, or always-block rule
4 Error — could not complete audit

Delta logic: findings are classified by (rule_id, category, normalized_problem) key ignoring line number. Pre-existing repo debt never blocks — only new or worsened findings do.

Always-block rules (regardless of delta): secrets, unresolved TODO markers, HLT-class violations, security-critical severity.

CLI:
```
jankurai audit-file --path [--candidate <file|->] [--op create|modify|delete|rename] [--mode save-gate|advisory] [--format agent|json]
```

Candidate bytes can be piped via stdin with --candidate -.

jankurai guard — enforcement runtime

A new enforcement crate that wires audit-file into a live filesystem guard. Provider-neutral: works with Claude, Codex, Gemini, OpenCode, or any agent that writes files. No per-agent hook API required.

Two backends

Watcher backend (macOS + Ubuntu, always compiled):

Works today on every platform. After a file is written, the guard debounces the event, runs audit-file on the candidate, and enforces the verdict:

  • Pass: nothing happens.
  • Block: file reverts to its last-good snapshot, a language-aware poison header is written (.rs → compile_error!(…), .ts/.js → throw new Error(…), .py → raise RuntimeError(…), etc.), a failure report lands at .jankurai/guard/LAST_FAILURE.md, and a banner is injected into the agent's PTY.

Honest limit: watcher mode is post-write — it cannot prevent the initial save. It can revert within ~150 ms and poison the file so the agent cannot proceed without fixing the problem.

FUSE backend (Linux only, feature="fuse"):

True pre-write blocking: writes are intercepted at the commit boundary (release/fsync) before they reach the backing repository. On block, the kernel returns EACCES to the agent and the backing repo is never touched.

The fuser dependency is target-gated ([target.'cfg(target_os = "linux")'.dependencies]) — cargo build --all-features on macOS pulls no kernel-extension code.

Enforcement modes

Mode Behavior
observe Report only — never modifies files
enforce Revert + quarantine + poison + PTY banner (default)
strict Enforce + lock path for writes until failure report is read

Mode resolves as: flag > agent/guard-policy.toml > enforce.

Poison mechanism

Language-aware un-ignorable error headers by file extension. Original rejected bytes are preserved between JANKURAI-POISON-BEGIN/END sentinels so a re-save with the header still present is automatically recovered. In FUSE mode the poison is a virtual read overlay (backing repo stays clean); in watcher mode it is written to disk.

PTY injection

guard run -- <agent>: portable-pty spawns the agent in its own process group, and the denial bus subscriber writes the failure banner directly into the PTY master so the agent sees the block inline.

First-run FUSE setup prompt

On the first jankurai guard invocation, if FUSE is not available, a platform-specific notice is printed to stderr:

macOS:
```
┌─────────────────────────────────────────────────────────────┐
│ jankurai guard — FUSE not installed │
│ │
│ For pre-write blocking on macOS, install macFUSE: │
│ brew install --cask macfuse │
│ │
│ After install: System Settings → Privacy & Security │
│ → approve the macFUSE kernel extension, then restart. │
│ │
│ Watcher mode is active (detects and reverts writes). │
│ This notice appears once. Re-run after FUSE install. │
└─────────────────────────────────────────────────────────────┘
```

Ubuntu/Linux (no FUSE feature build):
```
┌─────────────────────────────────────────────────────────────┐
│ jankurai guard — FUSE dev library not found │
│ │
│ For pre-write blocking, install libfuse3 and rebuild: │
│ sudo apt-get install libfuse3-dev │
│ cargo install jankurai --features guard-fuse │
│ │
│ Watcher mode is active (detects and reverts writes). │
│ This notice appears once. Re-run after rebuild. │
└─────────────────────────────────────────────────────────────┘
```

The notice is suppressed after the first display via ~/.jankurai/guard-fuse-prompted. Watcher mode is used automatically until FUSE is installed and the binary is rebuilt — no configuration required.

CLI surface

```
jankurai guard mount [--mode] [--mount-point] [--foreground]
jankurai guard run [--mode] -- <agent...>
jankurai guard watch [--mode] [--poll]
jankurai guard status [--json]
jankurai guard doctor [--json]
jankurai guard install [--yes|--dry-run]
jankurai guard unmount
jankurai guard failures [--last|--json]
jankurai guard quarantine list|restore
```

Policy file (agent/guard-policy.toml)

```toml
mode = "enforce" # observe | enforce | strict
block_on = ["error", "critical"]
warn_on = ["warning"]
debounce_ms = 80
stable_ms = 50
fail_closed = true # errors treated as blocks
quarantine_new_files = true
respect_gitignore = true
```

Tests

699 #[test] functions total (62 in jankurai-guard, covering: transaction logic, poison roundtrip, policy parsing, denial formatting, watcher, FUSE lifecycle).

Upgrade notes

New workspace member crates/jankurai-guard. After pulling:

```bash
cargo build --workspace
```

No breaking changes to existing jankurai audit or jankurai copy-code commands.

Linux with pre-write blocking:
```bash
sudo apt-get install libfuse3-dev
cargo install jankurai --features guard-fuse
jankurai guard watch
```

macOS / Ubuntu (watcher mode, no setup required):
```bash
jankurai guard watch
```