Repository navigation
v1.4.0 — jankurai guard: realtime per-file audit gate for every AI agent
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
```