Add kensai multi-agent code review plugin - #1
Merged
Merged
Conversation
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.
There was a problem hiding this comment.
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/reviewTypeScript 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-reviewskill 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.
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
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-reviewskill entry point.github/workflows/kensai-review-mcp.yml-- CI scoped to MCP server changesTest plan
vp checkpasses (70 files, 0 errors)vp testpasses (266 tests across 9 test files).mcp.json