AgentStack
MCP verified MIT Self-run

Lich

mcp-enchanter-ai-lich · by enchanter-ai

Ruthless, algorithm-backed code review. Tests AI-generated code in an isolated sandbox to mathematically prove it works before merging.

No reviews yet
0 installs
15 views
0.0% view→install

Install

$ agentstack add mcp-enchanter-ai-lich

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access Used
  • Shell / process execution Used
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README — it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-enchanter-ai-lich)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Lich? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Lich

> An @enchanter-ai product — algorithm-driven, agent-managed, self-learning.

Code review for AI-assisted development that catches runtime failures compile-time checks miss.

6 sub-plugins. 5 engines. 3 slash commands. Bayesian per-developer preference. One command.

> A PR adds result = user_inputs[i] / n with n coming from a JSON body. M1 Cousot Interval Propagation flags n as [?, ?] — unknown lower bound, possible zero. M2 Falleri Structural Diff confirms the assignment is new, not refactored. M5 Bounded Subprocess Dry-Run synthesizes a fuzzer input, executes the change in a resource.setrlimit sandbox, and observes ZeroDivisionError. M7 Zheng Pairwise Rubric judges: 5/10 Robustness, 2/10 Failure Resilience. M6 remembers that this developer consistently cares about divide-by-zero — next time the prior floor is 0.72, not 0.50. Verdict: HOLD with specific finding. Zero false positives from style noise. Sylph posts the finding on the PR. > > Time: under 5 seconds. Developer effort: read one finding, merge.

TL;DR

In plain English: Tests pass. Types check. The app still crashes at 3am. Lich runs the suspect lines in a sandbox and confirms the bug before warning you — so warnings mean something again.

Technically: M1 Cousot Interval Propagation propagates abstract ranges (interval + nullability + container-shape lattices) to flag division-by-zero and null-dereference suspects; M5 Bounded Subprocess Dry-Run executes flagged call sites in a stdlib-only resource.setrlimit sandbox to confirm or dismiss each suspicion before surfacing it. M6 Beta-Binomial Thompson sampling per (developer, rule) updates a per-developer preference posterior on every accept/reject, dropping rules the developer consistently ignores toward a 5% floor so the signal-to-noise ratio never collapses.


Origin

Lich takes its name from Twilight Forest — the first major boss, an undead sorcerer who tests challengers through phased spell-trials before allowing passage deeper into the dimension. Every PR is a supplicant at the gate; every engine is a test the code must survive before it ships.

The question this plugin answers: Is this code good?

Who this is for

  • Teams who've accepted that LLMs ship runtime bugs no type checker catches (x / n with n ∈ [?, ?]) and want an automated reviewer that actually runs the code.
  • Reviewers tired of style-noise from Copilot / Cursor / Qodo who want the tool to learn their preferences, not flood them.
  • Engineers who care about the signal-to-noise ratio staying above 1 after six months of reviews, not just week one.

Not for:

  • One-off scripts, experimental notebooks, or throwaway prototypes — Lich's sandbox runner costs time you won't save.
  • Teams already satisfied with their linter / type-checker combo who don't have runtime-bug incidents in their retros.

Contents

  • [How It Works](#how-it-works)
  • [What Makes Lich Different](#what-makes-lich-different)
  • [The Full Lifecycle](#the-full-lifecycle)
  • [Install](#install)
  • [Quickstart](#quickstart)
  • [6 Sub-Plugins, 3 Agents, 5 Engines](#6-sub-plugins-3-agents-5-engines)
  • [What You Get Per Review](#what-you-get-per-review)
  • [Roadmap](#roadmap)
  • [The Science Behind Lich](#the-science-behind-lich)
  • [vs Everything Else](#vs-everything-else)
  • [Agent Conduct (12 Modules)](#agent-conduct-12-modules)
  • [Architecture](#architecture)
  • [Acknowledgments](#acknowledgments)
  • [Versioning & release cadence](#versioning--release-cadence)
  • [Contributing](#contributing)
  • [Citation](#citation)
  • [License](#license)

How It Works

Lich runs a five-engine pipeline that treats code review as static suspicion → sandboxed confirmation → Bayesian preference weighting → rubric judgment. The premise: AI-assisted development ships two dominant bug classes that traditional review tools miss.

  1. Runtime failures that pass compile time. x / n type-checks in every language; n = 0 crashes at runtime. Static type systems don't catch it; neither does cargo check / tsc. Humans catch it on review, LLMs miss it.
  2. Reviewer fatigue on noisy signals. GitHub Copilot, Cursor, and Qodo ship thousands of style suggestions, all at equal weight. Developers accept/reject without the tool learning. Over time, the signal-to-noise collapses and the reviewer disables the tool.

Lich addresses both: the M1 static flagger feeds the M5 sandboxed confirmer (catches the first); M6 Bayesian preference accumulation per (developer, rule) (addresses the second). No existing reviewer ships either at zero-external-dep weight; both together is genuinely novel.

Source: [docs/assets/pipeline.mmd](docs/assets/pipeline.mmd) · Regeneration command in [docs/assets/README.md](docs/assets/README.md).

What Makes Lich Different

It catches runtime-only bugs via sandboxed confirmation

M1 Cousot Interval Propagation propagates abstract ranges (interval + nullability + container-shape lattices) across every assignment. A / n operation flags when the interval includes zero. Then M5 Bounded Subprocess Dry-Run actually executes the change in a stdlib-only sandbox (resource.setrlimit + signal.alarm + subprocess isolation) and observes whether the bug reproduces. No other reviewer ships the static-suspicion → sandboxed-confirmation pipeline at zero-external-dep weight.

Per-developer Bayesian preference accumulation

Every accept/reject on a rule updates a Beta-Binomial posterior per (developer, rule). After 20 rejections of "use pathlib instead of os.path" from a developer who works on legacy Python 2 code, the posterior for that surface rule drops from 0.50 → 0.08. The 5% minimum floor keeps the rule alive for edge cases. Thompson sampling preserves exploration. The result: the tool learns which signals this specific developer cares about — instead of rubber-stamp-then-disable collapse.

Inter-judge reliability via Cohen's Kappa

M7 Zheng Pairwise Rubric runs the judge twice with position-swapped inputs and reports Kappa — a measure of how consistent the LLM judge is with itself. If Kappa drops below 0.6, the verdict is flagged unstable and falls back to a rules-only decision. No other LLM-based reviewer reports inter-judge reliability.

Cross-plugin signal routing

Lich defers security-lane findings to Hydra (CWE classification, pattern databases) and change-classification to Crow (Bayesian trust scoring per file). The three cooperate: Lich catches code quality, Hydra catches security, Crow catches unexpected-change risk. One PR, three orthogonal verdicts, no duplicate work.

The Full Lifecycle

A review flows top-to-bottom through five stages. M1 Cousot Interval Propagation (lich-core) propagates abstract ranges over the changed hunks, flagging suspicious assignments and divisions. M2 Falleri Structural Diff (lich-core) clusters the changes by AST edit distance, so a 200-line rename collapses to one finding. M5 Bounded Subprocess Dry-Run (lich-sandbox) sandbox-executes each flagged hunk and observes runtime behavior. M6 Bayesian Preference Accumulation (lich-preference) weights findings by this developer's per-rule posterior. M7 Zheng Pairwise Rubric Judgment (lich-rubric) scores the aggregate along a 5-axis rubric and routes the verdict through lich-verdict (DEPLOY / HOLD / FAIL).

Source: [docs/assets/lifecycle.mmd](docs/assets/lifecycle.mmd) · Regeneration command in [docs/assets/README.md](docs/assets/README.md).

Every stage is autonomous; the developer surface is pull (/lich-review), not push.

Install

Lich ships as a 6-sub-plugin marketplace. One meta-plugin — full — lists all six as dependencies, so a single install pulls in the whole pipeline.

In Claude Code (recommended):

/plugin marketplace add enchanter-ai/lich
/plugin install full@lich

Claude Code resolves the dependency list and installs all 6 sub-plugins. Verify with /plugin list.

Want to cherry-pick? Individual sub-plugins are still installable — e.g. /plugin install lich-core@lich if you only want the M1+M2 static surface. Sandbox-less / preference-less modes degrade gracefully; Lich falls back to rules-only verdicts when an engine is missing.

Quickstart

git clone https://github.com/enchanter-ai/lich
cd lich
./scripts/bootstrap.sh    # canonical first command — installs vis sibling

Without ./scripts/bootstrap.sh, conduct imports will silently miss and Claude Code's @-loader will fail-soft. Always bootstrap first.

6 Sub-Plugins, 3 Agents, 5 Engines

| Sub-plugin | Owns | Trigger | Agent | |------------|------|---------|-------| | [lich-core](plugins/lich-core/) | M1 Cousot Interval + M2 Falleri Structural Diff | skill-invoked | static-surface (Sonnet) | | [lich-sandbox](plugins/lich-sandbox/) | M5 Bounded Subprocess Dry-Run | skill-invoked | sandbox-runner (Sonnet) | | [lich-preference](plugins/lich-preference/) | M6 Bayesian Preference Accumulation | hook-driven (PostToolUse) | preference-learner (Haiku) | | [lich-rubric](plugins/lich-rubric/) | M7 Zheng Pairwise Rubric Judgment | skill-invoked | rubric-judge (Sonnet) | | [lich-python](plugins/lich-python/) | Python AST adapter | skill-invoked | — | | [lich-typescript](plugins/lich-typescript/) | TypeScript AST adapter | skill-invoked | — |

Slash commands:

| Command | Function | Agent tier | |---------|----------|------------| | /lich-review | On-demand deep review aggregating M1-M7 | Sonnet | | /lich-explain | Walk through why M1/M5/M7 flagged a specific finding | Sonnet | | /lich-disable | Permanent rule suppression with quarterly auto-reprompt | Haiku |

What You Get Per Review

Write/Edit events flow through four journals — one per review-pipeline engine — and converge on the enchanted-mcp bus and the developer query surface. Color maps engines to journals: blue = lich-core (M1+M2 static suspicion) · red = lich-sandbox (M5 runtime confirmation) · purple = lich-preference (M6 Bayesian learning) · yellow = lich-rubric (M7 judgment).

Source: [docs/assets/state-flow.mmd](docs/assets/state-flow.mmd) · Regeneration command in [docs/assets/README.md](docs/assets/README.md).

plugins/lich-core/state/
├── findings.jsonl           M1+M2 flagged hunks with interval + diff cluster metadata
└── metrics.jsonl            per-scan timing + hunk counts

plugins/lich-sandbox/state/
├── executions.jsonl         M5 sandbox runs with exit code, rlimit hit, observed exceptions
└── metrics.jsonl            sandbox run counts + avg latency

plugins/lich-preference/state/
├── posteriors.json          per-(developer, rule) Beta-Binomial α/β parameters
├── learnings.json           cross-session preference accumulation (α=0.05)
└── metrics.jsonl            accept/reject events

plugins/lich-rubric/state/
├── verdicts.jsonl           M7 5-axis scores + Kappa reliability per review
└── metrics.jsonl            rubric invocation metrics

Every review produces a JSONL row in lich-rubric/state/verdicts.jsonl with the 5-axis rubric scores (Robustness, Specificity, Clarity, Failure Resilience, Determinism), the Cohen's Kappa reliability number, and the final verdict (DEPLOY / HOLD / FAIL).

Roadmap

Tracked in [docs/ROADMAP.md](docs/ROADMAP.md) and the shared [ecosystem map](docs/ecosystem.md). For upcoming work specific to Lich, see issues tagged roadmap.

The Science Behind Lich

Every Lich engine is built on a formal mathematical model. Full derivations in [docs/science/README.md](docs/science/README.md).

| ID | Name | Plugin | Algorithm | |----|------|--------|-----------| | M1 | Cousot Interval Propagation | lich-core | Abstract interpretation over interval + nullability + container-shape lattices with threshold widening | | M2 | Falleri Structural Diff | lich-core | GumTree two-phase AST matching (top-down hash + bottom-up Dice) | | M5 | Bounded Subprocess Dry-Run | lich-sandbox | Stdlib resource.setrlimit + signal.alarm + subprocess sandbox (Unix-only) | | M6 | Bayesian Preference Accumulation | lich-preference | Beta-Binomial Thompson sampling per (developer, rule) with 5% minimum floor | | M7 | Zheng Pairwise Rubric Judgment | lich-rubric | 5-axis rubric + position-swap debiasing + Cohen's Kappa reliability |

Defining engine: M5 Bounded Subprocess Dry-Run — the static-suspicion → sandboxed-confirmation pipeline is the novel moat no existing reviewer ships at zero-external-dep weight.

Phase 2 adds M3 Yamaguchi Property-Graph Traversal, M4 Type-Reflected Invariant Synthesis, Schleimer Winnowing Clone Detection, O'Hearn Separation-Logic Bi-Abduction, and Cohort Similarity Borrowing.

vs Everything Else

Honest comparison against adjacent tools. Marks only where the feature is present and production-ready.

| Feature | Lich | GitHub Copilot | Cursor | Qodo Merge | |---------|--------|----------------|--------|------------| | Catches runtime-only bugs via sandboxed confirmation | ✓ | — | — | — | | Per-developer Bayesian preference posterior | ✓ | — | — | — | | Inter-judge reliability (Cohen's Kappa) reported | ✓ | — | — | — | | Zero external runtime deps | ✓ | — | — | — | | Markdown-file rule customization | ✓ | ✓ | ✓ | ✓ | | Auto-generated PR comments | via Sylph | ✓ | ✓ | ✓ | | Cross-plugin signal routing (Hydra, Crow, Pech) | ✓ | — | — | — |

Agent Conduct (12 Modules)

Every skill inherits a reusable behavioral contract from [shared/vis/conduct/](shared/vis/conduct/) — loaded once into [CLAUDE.md](CLAUDE.md), applied across all plugins. This is how Claude acts inside Lich: deterministic, surgical, verifiable. Not a suggestion; a contract.

| Module | What it governs | |--------|-----------------| | [discipline.md](../vis/packages/core/conduct/discipline.md) | Coding conduct: think-first, simplicity, surgical edits, goal-driven loops | | [context.md](../vis/packages/core/conduct/context.md) | Attention-budget hygiene, U-curve placement, checkpoint protocol | | [verification.md](../vis/packages/core/conduct/verification.md) | Independent checks, baseline snapshots, dry-run for destructive ops | | [delegation.md](../vis/packages/core/conduct/delegation.md) | Subagent contracts, tool whitelisting, parallel vs. serial rules | | [failure-modes.md](../vis/packages/core/conduct/failure-modes.md) | 14-code taxonomy for accumulated-learning logs | | [tool-use.md](../vis/packages/core/conduct/tool-use.md) | Tool-choice hygiene, error payload contract, parallel-dispatch rules | | [formatting.md](../vis/packages/skills/conduct/formatting.md) | Per-target format (XML / Markdown sandwich / minimal / few-shot), prefill + stop sequences | | [skill-authoring.md](../vis/packages/skills/conduct/skill-authoring.md) | SKILL.md frontmatter discipline, discovery test | | [hooks.md](../vis/packages/core/conduct/hooks.md) | Advisory-only hooks, injection over denial, fail-open | | [precedent.md](../vis/packages/core/conduct/precedent.md) | Log self-observed failures to state/precedent-log.md; consult before risky steps | | [tier-sizing.md](../vis/packages/core/conduct/tier-sizing.md) | Prompt verbosity scales inversely with model tier; Haiku needs mechanical steps, Opus runs on intent | | [web-fetch.md](../vis/packages/web/conduct/web-fetch.md) | External URL handling: cache, dedup, budget; WebFetch is Haiku-tier-only |

Architecture

Interactive architecture explorer with sub-plugin diagrams, agent cards, and data flow:

[docs/architecture/](docs/architecture/) — auto-generated from the codebase. Run python docs/architecture/generate.py to regenerate.

Architecture diagrams are auto-generated from source-of-truth (plugin.json, hooks.json, SKILL.md frontmatter). Never hand-edited. The full synthesized architecture is at [docs/architecture/lich-architecture.md](docs/architecture/lich-architecture.md).

Acknowledgments

Lich builds on subs

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.