Skip to content

Add kensai multi-agent code review plugin - #1

Merged
xobotyi merged 26 commits into
mainfrom
dev-master
May 26, 2026
Merged

Add kensai multi-agent code review plugin#1
xobotyi merged 26 commits into
mainfrom
dev-master

Conversation

@xobotyi

@xobotyi xobotyi commented May 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Multi-agent code review pipeline with adversarial falsification, orchestrated by a stateful MCP server
  • Four-phase pipeline: grounding (map the change) -> surfacing (parallel reviewers find issues) -> proving (adversarial falsification filters false positives) -> filing (terminal report)
  • MCP server with 24 tools across 4 toolsets (session, filesystem, git, findings), phase state machine, paginated context delivery
  • Infrastructure libraries: llmxml markup builder, pathindex (tree-structured file index with fuzzy/glob), lineiter (streaming binary-safe line reader), git/rg CLI abstractions
  • 266 tests, strict TypeScript, CI workflow (lint + test matrix on Node LTS and 26)

Components

  • claude/kensai/mcp/review/ -- stateful MCP server (TypeScript, Node 26+)
  • claude/kensai/agents/ -- three agent definitions (grounder, surfacer, prover)
  • claude/kensai/skills/review/ -- /kensai-review skill entry point
  • .github/workflows/kensai-review-mcp.yml -- CI scoped to MCP server changes

Test plan

  • vp check passes (70 files, 0 errors)
  • vp test passes (266 tests across 9 test files)
  • MCP server starts and connects via .mcp.json
  • Full review pipeline ran end-to-end on its own codebase

xobotyi added 23 commits May 23, 2026 02:41
Stdio MCP server with Node 26 native TS stripping, Vite+ toolchain.
llmxml library renders pseudo-XML for LLM-facing responses.
Tree-structured file index with async parallel walker, per-file
stat, symlink detection, fuzzy search (fuzzysort), and glob
filtering (picomatch).

Builder dispatches readdir + stat concurrently via Promise.all
per directory. Supports globSearch, fuzzySearch (multi-word
waterfall), and O(1) entry/directory lookup.
Pseudo-XML renderer for LLM-facing tool responses. Fluent
element builder with self-closing/open-close rendering, scalar
attribute formatting, and one-shot content (inline or wrapped).

Escapes backslash, quotes, newline, carriage return, and tab
in attribute values. Private constructor -- Element.create()
and element() factory as public API.
Streaming pull-style line iterator ported from Go fstoolset/lineiter.
Consumes AsyncIterable<Buffer> (e.g. createReadStream) with pluggable
binary detection, per-line byte cap, and AbortSignal support.
Foundation for the fs-file-read tool.
Thin git CLI abstraction ported from Go git/repo.go and
gittoolset/annotate.go. Wraps execFile with argument arrays,
sets GIT_LITERAL_PATHSPECS=1, validates git >= 2.0 on first
use via cached singleton promise.

Repo class: open, diffFile, changedFiles, log. Log format
uses %x1e/%x1f record/field separators for multi-line commit
message bodies -- body placed last in field order for
robustness against separator collisions in message content.

Annotation utilities: annotateDiff, parseHunkStart,
countDiffLines -- used by diff tool and review pipeline for
precise line references.
Ripgrep CLI abstraction for content search, ported from Go
tools/v2/searchtoolset/grep.go. Foundation for the search-grep
MCP tool.

grep(root, pattern, options?, signal?) runs rg via execFile
with argument arrays and 50 MiB maxBuffer. Exit code 1 (no
matches) returns an empty result instead of throwing.

Multi-target: target accepts string[] so agents can pass
multiple paths in a single call. Configurable excludeDirs
defaults to .git, vendor, node_modules, dist, build,
__pycache__ -- pass [] to disable.

processOutput strips ./ prefixes, applies maxResults line-count
truncation, and removes trailing group separators.
Composes PathIndex, Repo, and rg behind a containment layer that
normalizes any path (absolute or relative) to POSIX relative from root
and rejects escapes. Sub-modules (git, rg, pathindex, lineiter)
co-located under src/repofs/.

API: resolve, fileExists, dirExists, readFile (raw Buffer), findFiles,
globFiles, grep, flushReadPaths. Index-based validation -- no stat
calls for readFile. Symlinks rejected by entry type since PathIndex
does not traverse them.
Extend IndexEntryFile with lineCount, maxLineLen, and isBinary
fields populated during the walk via LineIter in body-less mode.

Binary files detected by null byte probe on the first chunk --
large binary files (e.g. 4GB git packfiles) bail immediately
without reading the full content.

Concurrent file descriptor usage bounded by a Pool(256) to
prevent fd table overflow on large repos (172K+ files).
In-memory findings registry for a review session. Supports
surface/cancel/verdict lifecycle with status tracking, filtering
by dimension and status, and sequential ID assignment (F1, F2...).

Verdict extracted to dedicated subtype on Finding -- carries
result, reason, severity override, and blocking flag.
Two-layer grounding state: incremental observations (O1, O2...)
recorded during exploration, plus a one-shot GroundingResult
synthesized at the end. Observations support cancel for disproved
findings. Result store rejects duplicates.

Each observation carries a terse summary + explanatory detail.
GroundingResult has structured hotspots and blindspots arrays.
Fat start: validates git, builds PathIndex, collects changed
files, per-file diffs (3-line context), and manifest (bytes,
lines, maxLineLen, binary from PathIndex).

Repo.changedFiles and Repo.diffFile accept null head for
working tree diffs (uncommitted/all modes).

Diff filtering ported from Go harness -- vendor prefixes,
lock files, generated suffixes excluded from diffs but kept
in changedFiles and manifest. Deleted files excluded from
both diffs and manifest.
Toolsets as providers -- each defines its own tools internally.
SessionToolset acts as the binder: registers all tools (own +
dependants) on the server via a single bind() call. Dependant
tools start disabled and are enabled/disabled via declarative
state sync on session lifecycle.

Four toolsets, 22 tool stubs total:
- session (9): start, state, end, grounding_store/get/complete,
  surfacing_complete, proving_complete, filing_complete
- fs (4): read_file, find_files, list_dir, grep
- git (3): diff_file, changed_files, log
- findings (6): finding_surface, surface_clean, finding_cancel,
  finding_verdict, findings_list, finding_get

SessionDependant interface provides update(rfs)/clear() hooks
for RepoFs lifecycle injection. ToolRegistrar separates tool
definition from server registration.
Session gains SessionPhase (GROUNDING -> SURFACING -> PROVING ->
FILING -> COMPLETE) with advance() for validated transitions.

All 24 tool handlers wired to domain:
- Session lifecycle: start/state/end call Session.start()
- Findings: surface/cancel/verdict/list/get via FindingsStorage
- Grounding: store/get/observations via GroundingStorage
- Phase transitions: validate preconditions, call advance()
- FS: read_file/find_files/list_dir/grep call RepoFs
- Git: changed_files returns pre-collected data, diff_file/log
  call Repo with base/head from resolveRefs()

Tool file pattern standardized: module-level z.object() schema,
standalone handle(), thin ToolRegistrar factory. Responses via
ok()/err()/errFrom() helpers in new result.ts module.

Error handling converted from throw to isError returns per MCP
SDK convention. ToolContext gains session() accessor.

Stale types.ts files removed (session/, findings/).
Port Go v2 toolset response patterns into MCP tool handlers:
- fs tools: cat-n lines, path (N bytes), rg output, one-per-line
- git tools: header + status table, annotated diff, sha subject
- findings/grounding/state: LLMXML via element()/attr()

Add session_priming tool -- multi-block priming (metadata, changed
files, file stats, diffs) with 500K maxResultSizeChars.

Add shared suggestPaths()/formatSuggestions() to result.ts for
directory-scoped fuzzy path suggestions on not-found.

Separate soft errors (ok with bracketed marker) from hard errors
(err with isError:true). Tool visibility: only session_start
exposed before session active.
Port Go v2 tool prompt patterns -- each tool now documents its behaviour,
alternatives to reach for, output format, and constraints within the MCP
description field (under 2KB cap per tool).

Helps calling agents understand when to use each tool and what to expect
from the response without needing separate documentation.
Agents use mcp__kensai__* wildcard -- no Read/Grep/Glob/Bash. All
codebase access through MCP tools (read_file, grep, find_files,
diff_file, etc). Each agent starts with session_priming for full
context.

Skill pipeline simplified -- no data threading from lead to agents.
Removed Change Context section (git commands). Spawn prompts carry
only dimension + quality criteria; agents self-serve via MCP.
Add plugin infrastructure (plugin.json, marketplace.json, .mcp.json).
Actualize all CLAUDE.md files to reflect MCP-first tooling, complete
Phase 2 implementation, session_priming, tool visibility, and soft
error conventions. Set version 0.1.0 across all manifests.
Discover CLAUDE.md/AGENTS.md from directory chains of changed files
using PathIndex for existence checks. Resolved at Session.start() in
parallel with diff fetching.

Delivered in session_priming as <agent-instruction path="..."> blocks
between file stats and diffs. Agents receive project conventions
alongside review context -- no separate delivery mechanism needed.

Excludes changed instruction files (already primed as diffs).
Agents updated with guidance on applying <agent-instruction> blocks.
Priming paginated at 350K per page -- agents call session_priming(page=N)
until footer shows complete. Diff context bumped from 3 to 25 lines
(matching Go). Skill gains model selection guidance for large changes.

Review findings fixed: /review -> /kensai-review in CLAUDE.md + README,
stale tool visibility docs updated across 3 files, session tool count
corrected to 12, toolset.ts JSDoc + bind() comment aligned.

Agent tools: explicit per-phase tool lists replace mcp__kensai__* glob
to avoid polluting agents with phase-inappropriate tools (session_start,
session_end, filing_complete). All tools still always registered on the
MCP server -- scoping is agent-side only.
Fix 10 doc findings: /review -> /kensai-review in components table,
tool count 13 -> 12, priming descriptions updated with pagination +
agent-instructions, tool visibility plan item corrected, session tool
table expanded from 9 to 12 entries.

Rework surfacing dimension derivation: remove stock vocabulary that
was copied verbatim every review. Dimensions must name change-specific
risks derived from grounding hotspots, not generic review categories.

Truncate oversized priming blocks at 480K with a marker directing
agents to diff_file. Separate from page budget (350K) so blocks
between 350K-480K land intact on their own page.

Improve #require() error message to match soft-error convention --
agents hitting a session-dependent tool pre-session see a descriptive
bracketed message instead of a raw throw.
Remove within-file duplication (session_priming pagination
restated in both Tool Usage and methodology steps), drop
rationale sentences adjacent to self-evident rules, compress
verbose sections (Grounding is lossy, Implied Accompaniments),
and cut filler phrases across all three agent definitions and
the review skill.

All behavioral content preserved -- no structural rubrics,
falsification gates, or investigation steps touched.
GitHub Actions workflow scoped to claude/kensai/mcp/review/**.
Two jobs: lint (vp check on Node 26) and test (vp test on
Node LTS + 26 matrix). Triggers on push to main and PRs.
Replaces PATH-dependent rg invocation with the bundled
binary from @vscode/ripgrep. Eliminates the need to install
ripgrep on CI runners or fresh dev machines.

rg.ts imports rgPath and uses it at both call sites
(version check and grep execution). Error message updated
to reference the bundled path instead of PATH.
@xobotyi
xobotyi requested a review from Copilot May 26, 2026 08:24
@xobotyi xobotyi self-assigned this May 26, 2026
@xobotyi xobotyi added the enhancement New feature or request label May 26, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds the new Kensai Claude Code plugin, including a stateful stdio MCP server and agent/skill definitions to run a four-phase multi-agent code review pipeline (grounding → surfacing → proving → filing).

Changes:

  • Introduces the claude/kensai/mcp/review TypeScript MCP server with session state, toolsets, and supporting libraries (RepoFs, PathIndex, rg wrapper, llmxml, etc.).
  • Adds agent definitions (review-grounder, review-surfacer, review-prover) and the /kensai-review skill orchestration docs.
  • Adds CI workflow for MCP server lint/test and plugin marketplace metadata.

Reviewed changes

Copilot reviewed 85 out of 87 changed files in this pull request and generated 18 comments.

Show a summary per file
File Description
.claude/settings.json Claude Code settings updates for plugin development environment.
.claude-plugin/marketplace.json Registers the kensai plugin in the marketplace index.
.github/workflows/kensai-review-mcp.yml CI workflow for claude/kensai/mcp/review (lint + tests).
.gitignore Root ignore rules update.
CLAUDE.md Repo-level conventions and plugin ecosystem documentation.
claude/CLAUDE.md Claude plugin ecosystem documentation and conventions.
claude/kensai/.claude-plugin/plugin.json Kensai plugin metadata (name/version/author/repo/license/keywords).
claude/kensai/.mcp.json MCP server wiring for Kensai (stdio command and args).
claude/kensai/აგენტs/review-grounder.md Grounding agent definition and instructions.
claude/kensai/agents/review-prover.md Proving agent definition and instructions.
claude/kensai/agents/review-surfacer.md Surfacing agent definition and instructions.
claude/kensai/CLAUDE.md Agent-facing Kensai plugin documentation and tool list.
claude/kensai/README.md Human-facing Kensai README (problem/solution/usage/install).
claude/kensai/skills/review/SKILL.md /kensai-review skill entrypoint and pipeline orchestration instructions.
claude/kensai/mcp/review/.gitignore MCP server package ignore rules.
claude/kensai/mcp/review/.node-version Pins Node runtime version for MCP server.
claude/kensai/mcp/review/CLAUDE.md MCP server architecture and implementation notes.
claude/kensai/mcp/review/package.json MCP server package manifest (deps/scripts/engines).
claude/kensai/mcp/review/pnpm-workspace.yaml pnpm workspace/catalog configuration for MCP server.
claude/kensai/mcp/review/tsconfig.json TypeScript configuration for MCP server.
claude/kensai/mcp/review/vite.config.ts Vite+ formatting/lint/type-aware settings.
claude/kensai/mcp/review/src/index.ts MCP server bootstrap: toolset wiring + stdio transport.
claude/kensai/mcp/review/src/llmxml/CLAUDE.md llmxml module documentation.
claude/kensai/mcp/review/src/llmxml/llmxml.ts LLMXML builder implementation.
claude/kensai/mcp/review/src/llmxml/llmxml.test.ts LLMXML unit tests.
claude/kensai/mcp/review/src/repofs/CLAUDE.md RepoFs module documentation.
claude/kensai/mcp/review/src/repofs/repofs.ts Repo-scoped filesystem facade with containment + search.
claude/kensai/mcp/review/src/repofs/repofs.test.ts RepoFs unit tests.
claude/kensai/mcp/review/src/repofs/git/CLAUDE.md git wrapper documentation.
claude/kensai/mcp/review/src/repofs/git/git.ts git CLI wrapper + diff annotation utilities.
claude/kensai/mcp/review/src/repofs/lineiter/CLAUDE.md lineiter module documentation.
claude/kensai/mcp/review/src/repofs/lineiter/lineiter.ts Streaming line iterator with binary probing.
claude/kensai/mcp/review/src/repofs/lineiter/lineiter.test.ts lineiter unit tests.
claude/kensai/mcp/review/src/repofs/lineiter/lineiter.bench.ts lineiter benchmarks.
claude/kensai/mcp/review/src/repofs/pathindex/CLAUDE.md pathindex module documentation.
claude/kensai/mcp/review/src/repofs/pathindex/pathindex.ts Tree index + fuzzy/glob search implementation.
claude/kensai/mcp/review/src/repofs/pathindex/pathindex.bench.ts pathindex benchmarks.
claude/kensai/mcp/review/src/repofs/rg/CLAUDE.md rg wrapper documentation.
claude/kensai/mcp/review/src/repofs/rg/rg.ts ripgrep CLI wrapper implementation.
claude/kensai/mcp/review/src/repofs/rg/rg.test.ts rg wrapper tests.
claude/kensai/mcp/review/src/session/CLAUDE.md session domain documentation.
claude/kensai/mcp/review/src/session/findings-storage.ts Findings storage and lifecycle state.
claude/kensai/mcp/review/src/session/findings-storage.test.ts Findings storage tests.
claude/kensai/mcp/review/src/session/grounding-storage.ts Grounding storage (observations + result).
claude/kensai/mcp/review/src/session/grounding-storage.test.ts Grounding storage tests.
claude/kensai/mcp/review/src/session/instructions.ts Instruction-file discovery/resolution for priming.
claude/kensai/mcp/review/src/session/session.ts Core Session state machine + diff/manifest/instructions assembly.
claude/kensai/mcp/review/src/toolsets/CLAUDE.md Toolset architecture documentation.
claude/kensai/mcp/review/src/toolsets/result.ts Tool result helpers (ok/err/errFrom + suggestions).
claude/kensai/mcp/review/src/toolsets/types.ts Toolset and context type definitions.
claude/kensai/mcp/review/src/toolsets/findings/CLAUDE.md Findings toolset documentation.
claude/kensai/mcp/review/src/toolsets/findings/cancel.ts finding_cancel tool.
claude/kensai/mcp/review/src/toolsets/findings/get.ts finding_get tool.
claude/kensai/mcp/review/src/toolsets/findings/list.ts findings_list tool.
claude/kensai/mcp/review/src/toolsets/findings/surface.ts finding_surface tool.
claude/kensai/mcp/review/src/toolsets/findings/surface_clean.ts surface_clean tool.
claude/kensai/mcp/review/src/toolsets/findings/toolset.ts FindingsToolset registration.
claude/kensai/mcp/review/src/toolsets/findings/verdict.ts finding_verdict tool.
claude/kensai/mcp/review/src/toolsets/fs/CLAUDE.md FS toolset documentation.
claude/kensai/mcp/review/src/toolsets/fs/find_files.ts find_files tool.
claude/kensai/mcp/review/src/toolsets/fs/grep.ts grep tool.
claude/kensai/mcp/review/src/toolsets/fs/list_dir.ts list_dir tool.
claude/kensai/mcp/review/src/toolsets/fs/read_file.ts read_file tool.
claude/kensai/mcp/review/src/toolsets/fs/toolset.ts FsToolset registration.
claude/kensai/mcp/review/src/toolsets/git/CLAUDE.md Git toolset documentation.
claude/kensai/mcp/review/src/toolsets/git/changed_files.ts changed_files tool.
claude/kensai/mcp/review/src/toolsets/git/diff_file.ts diff_file tool.
claude/kensai/mcp/review/src/toolsets/git/log.ts log tool.
claude/kensai/mcp/review/src/toolsets/git/toolset.ts GitToolset registration.
claude/kensai/mcp/review/src/toolsets/session/CLAUDE.md Session toolset documentation.
claude/kensai/mcp/review/src/toolsets/session/end.ts session_end tool.
claude/kensai/mcp/review/src/toolsets/session/filing_complete.ts filing_complete transition tool.
claude/kensai/mcp/review/src/toolsets/session/grounding_complete.ts grounding_complete transition tool.
claude/kensai/mcp/review/src/toolsets/session/grounding_get.ts grounding_get tool.
claude/kensai/mcp/review/src/toolsets/session/grounding_store.ts grounding_store tool.
claude/kensai/mcp/review/src/toolsets/session/observation_cancel.ts observation_cancel tool.
claude/kensai/mcp/review/src/toolsets/session/observation_create.ts observation_create tool.
claude/kensai/mcp/review/src/toolsets/session/priming.ts session_priming tool (paginated context).
claude/kensai/mcp/review/src/toolsets/session/proving_complete.ts proving_complete transition tool.
claude/kensai/mcp/review/src/toolsets/session/start.ts session_start tool.
claude/kensai/mcp/review/src/toolsets/session/state.ts session_state tool.
claude/kensai/mcp/review/src/toolsets/session/surfacing_complete.ts surfacing_complete transition tool.
claude/kensai/mcp/review/src/toolsets/session/toolset.ts SessionToolset binder + enable/disable logic.
Files not reviewed (1)
  • claude/kensai/mcp/review/pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread claude/kensai/mcp/review/src/toolsets/fs/read_file.ts
Comment thread claude/kensai/mcp/review/src/toolsets/fs/grep.ts
Comment thread claude/kensai/mcp/review/src/toolsets/fs/list_dir.ts
Comment thread claude/kensai/mcp/review/src/toolsets/git/diff_file.ts
Comment thread claude/kensai/mcp/review/src/toolsets/findings/verdict.ts
Comment thread claude/kensai/mcp/review/src/toolsets/session/start.ts Outdated
Comment thread claude/kensai/mcp/review/src/toolsets/fs/find_files.ts
Comment thread claude/kensai/mcp/review/src/toolsets/fs/list_dir.ts
Comment thread claude/kensai/mcp/review/src/toolsets/git/log.ts
Comment thread CLAUDE.md
xobotyi added 2 commits May 26, 2026 11:03
Root CLAUDE.md: installation instructions, version
management (plugin.json <-> marketplace.json sync),
npm package field requirements, .npmignore convention,
and supply chain protection (ignore-scripts,
minimum-release-age, 2FA on @Gaijin scope).

Kensai MCP package.json: remove private flag, add
license/author/repository/engines/bin/publishConfig.
.npmrc: ignore-scripts=true, minimum-release-age=7d.
.npmignore: whitelist src/, exclude tests and docs.
Agent instructions used wrong field names for MCP tool
calls, causing silent failures:
- prover: result/pass/reject -> verdict/confirmed/rejected
- grounder: blind_spots -> blindspots
- surfacer: summary -> notes (surface_clean)

session_start default mode changed from committed to
uncommitted, matching the SKILL.md pipeline default.

Toolset CLAUDE.md tables aligned with actual Zod schemas
(fs, git, findings). Missing plugin LICENSE added.
Wrap rfs.fileExists/dirExists precondition checks in
try/catch across read_file, grep, list_dir, and diff_file
handlers. Path-escape attempts (../../) return errFrom()
instead of uncaught RepoFsError.

Fix misleading tool descriptions:
- find_files: remove glob/directory-suffix/exclusion claims
  not implemented by the handler
- list_dir: max_depth=1 is direct children, not directory
  itself
- log: schema rejects non-positive count; description
  updated to match
@xobotyi
xobotyi merged commit e30fbaf into main May 26, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants