From 5a88874fd4dda9f6eb675fd7d2167cf5cc229ed9 Mon Sep 17 00:00:00 2001 From: ojowwalker77 Date: Fri, 9 Jan 2026 22:21:15 -0300 Subject: [PATCH 1/3] feat: greptile-style review, pre-commit suggestions, rule engine fix - Enhanced /matrix:review with Greptile-style output format - Confidence score (1-5), per-file analysis table - Critical issues, positive aspects sections - Pre-commit review suggestions for git/jj commits - Detects git commit and jj commit/describe/new - Non-blocking suggestion to run review first - Fixed rule engine integration in all hooks - PreToolUse:Edit, PreToolUse:Read, UserPromptSubmit - User-defined rules now properly evaluated - Deep research saves to session directory --- CHANGELOG.md | 42 +++++++++++++++++ commands/deep-research.md | 4 +- commands/review.md | 83 ++++++++++++++++++++++++--------- src/config/index.ts | 17 +++++++ src/hooks/pre-tool-bash.ts | 76 +++++++++++++++++++++++++++--- src/hooks/pre-tool-edit.ts | 32 ++++++++++++- src/hooks/pre-tool-read.ts | 41 ++++++++++++---- src/hooks/user-prompt-submit.ts | 21 +++++++++ 8 files changed, 277 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ff46da..c01fe98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,48 @@ All notable changes to Claude Matrix are documented here. +## [2.0.1] - 2025-01-09 + +### Added + +#### Greptile-Style Code Review Output +- **Enhanced `/matrix:review`** - New output format inspired by Greptile + - Summary with 2-3 sentence overview + - Key Changes bullet list + - Critical Issues Found with numbered, detailed explanations + - Additional Issues for minor items + - Positive Aspects for good patterns + - **Confidence Score (1-5)** with explanation + - **Important Files Changed** table with per-file scores (1-5) + - Detailed File Analysis section + +#### Pre-Commit Code Review +- **PreToolUse:Bash Hook** - Suggests Matrix review BEFORE commits + - Detects `git commit` and `jj commit/describe/new` commands + - Prompts Claude to consider running `/matrix:review staged [depth]` + - Non-blocking suggestion to catch issues before they're committed +- **Jujutsu (jj) Support** - Works with both Git and Jujutsu VCS +- **New Config** - `hooks.gitCommitReview` + - `enabled`: Toggle feature on/off (default: true) + - `depth`: Review depth - `'quick'` | `'standard'` | `'thorough'` (default: `'standard'`) + +### Fixed + +- **Rule Engine Integration** - User-defined rules now properly evaluated in all hooks + - `PreToolUse:Edit` - Evaluates edit rules before cursed file checks + - `PreToolUse:Read` - Evaluates read rules before sensitive file detection + - `UserPromptSubmit` - Evaluates prompt rules at start of analysis + - Previously, rules were only evaluated in `PreToolUse:Bash` + +### Changed + +- **Deep Research Save Location** - Now saves to session directory + - Primary: `$CLAUDE_SESSION_DIR/matrix-research-[slug]-[timestamp].md` + - Fallback: `./matrix-research-[slug]-[timestamp].md` (current working directory) + - Previously saved to `~/Downloads/` + +--- + ## [2.0.0] - 2025-01-09 ### Major Release - "Matrix v2" diff --git a/commands/deep-research.md b/commands/deep-research.md index c61a49a..316d95d 100644 --- a/commands/deep-research.md +++ b/commands/deep-research.md @@ -102,7 +102,9 @@ Generate a polished markdown document: ... ``` -Save to: `~/Downloads/matrix-research-[slug]-[timestamp].md` +Save to session directory: Use `$CLAUDE_SESSION_DIR/matrix-research-[slug]-[timestamp].md` + +If `$CLAUDE_SESSION_DIR` is not available, fall back to current working directory: `./matrix-research-[slug]-[timestamp].md` ## Examples diff --git a/commands/review.md b/commands/review.md index 54b00eb..5dda9bb 100644 --- a/commands/review.md +++ b/commands/review.md @@ -121,38 +121,77 @@ For each concern from Phase 3: ### Phase 5: Reflection & Consolidation -Generate final review output: +Generate final review output in Greptile-style format: -1. **Prioritize findings** - - Critical: Must fix before merge - - Important: Should fix, may defer - - Suggestion: Nice to have improvements - - Praise: Things done well +1. **Calculate Confidence Score (1-5)** + - 5/5: No issues, ready to merge + - 4/5: Minor suggestions only, approve with optional changes + - 3/5: Some issues that should be addressed but not blocking + - 2/5: Important issues that need attention before merge + - 1/5: Critical bugs or issues that will cause incorrect behavior + +2. **Format review output** -2. **Format review comments** ```markdown -## Code Review Summary +# Matrix Review + +## Summary +[2-3 sentence overview of what this PR/change does and its purpose] + +## Key Changes +- [Change 1]: Brief description +- [Change 2]: Brief description +- [Change 3]: Brief description + +## Critical Issues Found + +### 1. [Issue Title] +[Detailed explanation of the issue, why it's critical, and what behavior it will cause] + +### 2. [Issue Title] +[Detailed explanation] + +## Additional Issues +- [Minor issue 1] +- [Minor issue 2] -**Change Type:** [bugfix|feature|refactor|...] -**Blast Radius:** [low|medium|high] - [N] files directly affected -**Overall Assessment:** [Approve|Request Changes|Comment] +## Positive Aspects +- [Good practice observed] +- [Well-implemented pattern] -### Critical Issues -- [File:Line] Issue description - Suggestion: How to fix +## Confidence Score: [N]/5 -### Important Items -- [File:Line] Issue description - Suggestion: How to improve +[Explanation of why this score was given, referencing the critical issues] -### Suggestions -- [File:Line] Suggestion description +**Files requiring attention:** [file1.ts] (critical issue #1), [file2.ts] (critical issue #2) -### What's Done Well -- [Positive observation] +--- + +## Important Files Changed + +| Filename | Score | Overview | +|----------|-------|----------| +| path/to/file1.ts | 2/5 | Brief description of issues in this file | +| path/to/file2.ts | 1/5 | Brief description of critical issues | +| path/to/file3.ts | 5/5 | No issues found, clean implementation | + +### File Analysis + +#### `path/to/file1.ts` — Score: 2/5 +[Detailed analysis of this file's changes, issues found, and suggestions] + +#### `path/to/file2.ts` — Score: 1/5 +[Detailed analysis of this file's changes, issues found, and suggestions] ``` -3. **Learning loop** +3. **Scoring Guidelines per File** + - 5/5: No issues, clean implementation + - 4/5: Minor style or documentation suggestions + - 3/5: Some improvements recommended + - 2/5: Has bugs or significant issues + - 1/5: Critical bugs that will cause incorrect behavior + +4. **Learning loop** - If reviewer spots a pattern that should be remembered: Use `matrix_store` to save for future reviews - If a recalled solution helped: diff --git a/src/config/index.ts b/src/config/index.ts index a64f3cc..36222a5 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -100,6 +100,15 @@ export interface PromptAnalysisConfig { }; } +// ═══════════════════════════════════════════════════════════════ +// Pre-Commit Review Config +// ═══════════════════════════════════════════════════════════════ +export interface GitCommitReviewConfig { + enabled: boolean; + /** Review depth: 'quick' | 'standard' | 'thorough' */ + depth: 'quick' | 'standard' | 'thorough'; +} + // ═══════════════════════════════════════════════════════════════ // User-Configurable Rules (v2.0) // ═══════════════════════════════════════════════════════════════ @@ -147,6 +156,7 @@ export interface HooksConfig { packageAuditor: PackageAuditorConfig; cursedFiles: CursedFilesConfig; promptAnalysis: PromptAnalysisConfig; + gitCommitReview: GitCommitReviewConfig; // v2.0 User Rules userRules: UserRulesConfig; // v2.0 Hook Verbosity @@ -317,6 +327,13 @@ export const DEFAULT_CONFIG: MatrixConfig = { }, }, + // ─── Pre-Commit Review (PreToolUse:Bash hook) ─── + // Triggers Matrix review before git/jj commits + gitCommitReview: { + enabled: true, + depth: 'standard' as const, + }, + // ─── User Rules (v2.0) ─── userRules: { enabled: true, diff --git a/src/hooks/pre-tool-bash.ts b/src/hooks/pre-tool-bash.ts index d78924c..1bd77ee 100644 --- a/src/hooks/pre-tool-bash.ts +++ b/src/hooks/pre-tool-bash.ts @@ -1,13 +1,11 @@ #!/usr/bin/env bun /** - * PreToolUse:Bash Hook (Package Auditor) + * PreToolUse:Bash Hook (Package Auditor + Pre-Commit Review) * * Runs before Bash tool executes. - * Detects package install commands and audits packages for: - * - CVEs (via OSV.dev) - * - Bundle size (via Bundlephobia, npm only) - * - Deprecation status (via npm registry) - * - Local warnings (Matrix database) + * Features: + * - Pre-commit code review: Suggests Matrix review before git/jj commits + * - Package auditing: CVEs, bundle size, deprecation, local warnings * * Exit codes: * 0 = Success (allows tool to proceed) @@ -28,6 +26,23 @@ import { type Ecosystem, } from './index.js'; import { matrixWarn, type WarnCheckResult, type WarnResult } from '../tools/warn.js'; +import { getConfig } from '../config/index.js'; +import { evaluateBashRules, formatRuleResult } from './rule-engine.js'; + +/** + * Check if command is a git or jj commit + */ +function isCommitCommand(command: string): { isCommit: boolean; vcs: 'git' | 'jj' | null } { + // Git: git commit, git commit -m, git commit -am, git commit --amend, etc. + if (/^\s*git\s+commit\b/.test(command)) { + return { isCommit: true, vcs: 'git' }; + } + // Jujutsu: jj commit, jj describe (creates new commit), jj new (creates new change) + if (/^\s*jj\s+(commit|describe|new)\b/.test(command)) { + return { isCommit: true, vcs: 'jj' }; + } + return { isCommit: false, vcs: null }; +} /** * Type guard to check if a WarnResult is a WarnCheckResult @@ -254,7 +269,54 @@ export async function run() { process.exit(0); } - // Parse package command + // ============================================ + // STEP 1: Evaluate user-defined rules + // ============================================ + const ruleResult = evaluateBashRules(command); + + if (ruleResult.blocked) { + const output: HookOutput = { + hookSpecificOutput: { + hookEventName: 'PreToolUse', + permissionDecision: 'deny', + permissionDecisionReason: formatRuleResult(ruleResult), + }, + }; + outputJson(output); + process.exit(0); + } + + if (ruleResult.warned) { + // Warnings don't block, but we could log them + console.error(formatRuleResult(ruleResult)); + } + + // ============================================ + // STEP 2: Pre-commit review suggestion + // ============================================ + const config = getConfig(); + const gitReviewConfig = config.hooks.gitCommitReview; + const commitCheck = isCommitCommand(command); + + if (gitReviewConfig?.enabled && commitCheck.isCommit) { + const depth = gitReviewConfig.depth ?? 'standard'; + const vcsName = commitCheck.vcs === 'jj' ? 'Jujutsu' : 'Git'; + + // Suggest review before commit (non-blocking) + const output: HookOutput = { + hookSpecificOutput: { + hookEventName: 'PreToolUse', + additionalContext: `[Matrix] ${vcsName} commit detected. Consider running a code review first:\n\n/matrix:review staged ${depth}\n\nThis helps catch issues before they're committed.`, + }, + }; + + outputJson(output); + process.exit(0); + } + + // ============================================ + // STEP 3: Package auditing + // ============================================ const parsed = parsePackageCommand(command); if (!parsed || parsed.packages.length === 0) { // Not a package install command diff --git a/src/hooks/pre-tool-edit.ts b/src/hooks/pre-tool-edit.ts index 785f9dc..46c812c 100644 --- a/src/hooks/pre-tool-edit.ts +++ b/src/hooks/pre-tool-edit.ts @@ -19,6 +19,7 @@ import { type HookOutput, } from './index.js'; import { matrixWarn, type WarnCheckResult } from '../tools/warn.js'; +import { evaluateEditRules, formatRuleResult } from './rule-engine.js'; export async function run() { try { @@ -36,7 +37,36 @@ export async function run() { process.exit(0); } - // Check for file warnings + // Get content for pattern matching (Edit has old_string/new_string, Write has content) + const content = (input.tool_input.new_string as string) || + (input.tool_input.content as string) || + ''; + + // ============================================ + // STEP 1: Evaluate user-defined rules + // ============================================ + const ruleResult = evaluateEditRules(filePath, content); + + if (ruleResult.blocked) { + const output: HookOutput = { + hookSpecificOutput: { + hookEventName: 'PreToolUse', + permissionDecision: 'deny', + permissionDecisionReason: formatRuleResult(ruleResult), + }, + }; + outputJson(output); + process.exit(0); + } + + if (ruleResult.warned) { + // Warnings don't block, but log them + console.error(formatRuleResult(ruleResult)); + } + + // ============================================ + // STEP 2: Check for file warnings (cursed files) + // ============================================ const result = await matrixWarn({ action: 'check', type: 'file', diff --git a/src/hooks/pre-tool-read.ts b/src/hooks/pre-tool-read.ts index 275080a..1541ff5 100644 --- a/src/hooks/pre-tool-read.ts +++ b/src/hooks/pre-tool-read.ts @@ -30,6 +30,7 @@ import { } from './index.js'; import { getConfig, type SensitiveFilesConfig } from '../config/index.js'; import { matrixWarn, type WarnCheckResult } from '../tools/warn.js'; +import { evaluateReadRules, formatRuleResult } from './rule-engine.js'; // ═══════════════════════════════════════════════════════════════ // Sensitive File Patterns @@ -193,18 +194,42 @@ export async function run() { // Read input from stdin const input = await readStdin(); - // Get config - const config = getConfig(); - const sensitiveConfig = config.hooks.sensitiveFiles; + // Get file path from tool input + const filePath = input.tool_input.file_path as string | undefined; + if (!filePath) { + process.exit(0); + } - // Skip if disabled - if (!sensitiveConfig.enabled || sensitiveConfig.behavior === 'disabled') { + // ============================================ + // STEP 1: Evaluate user-defined rules (always runs) + // ============================================ + const ruleResult = evaluateReadRules(filePath); + + if (ruleResult.blocked) { + const output: HookOutput = { + hookSpecificOutput: { + hookEventName: 'PreToolUse', + permissionDecision: 'deny', + permissionDecisionReason: formatRuleResult(ruleResult), + }, + }; + outputJson(output); process.exit(0); } - // Get file path from tool input - const filePath = input.tool_input.file_path as string | undefined; - if (!filePath) { + if (ruleResult.warned) { + // Warnings don't block, but log them + console.error(formatRuleResult(ruleResult)); + } + + // ============================================ + // STEP 2: Check for sensitive patterns (if enabled) + // ============================================ + const config = getConfig(); + const sensitiveConfig = config.hooks.sensitiveFiles; + + // Skip sensitive file checks if disabled + if (!sensitiveConfig.enabled || sensitiveConfig.behavior === 'disabled') { process.exit(0); } diff --git a/src/hooks/user-prompt-submit.ts b/src/hooks/user-prompt-submit.ts index 3942240..88c50ce 100644 --- a/src/hooks/user-prompt-submit.ts +++ b/src/hooks/user-prompt-submit.ts @@ -40,6 +40,7 @@ import { type SolutionData, type FailureData, } from './format-helpers.js'; +import { evaluatePromptRules, formatRuleResult } from './rule-engine.js'; const MAX_CONTEXT_WORDS = 500; @@ -211,6 +212,26 @@ export async function run() { const config = getHooksConfig(); const threshold = config.complexityThreshold ?? 5; + // ============================================ + // STEP 0: Evaluate user-defined prompt rules + // ============================================ + const ruleResult = evaluatePromptRules(input.prompt); + + if (ruleResult.blocked) { + outputJson({ + hookSpecificOutput: { + permissionDecision: 'deny', + permissionDecisionReason: formatRuleResult(ruleResult), + }, + }); + process.exit(0); + } + + if (ruleResult.warned) { + // Warnings don't block, but log them + console.error(formatRuleResult(ruleResult)); + } + // ============================================ // STEP 1: Run Prompt Agent analysis FIRST // ============================================ From c3099e390242afaa57d60253750f49da9b57429e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 10 Jan 2026 01:21:42 +0000 Subject: [PATCH 2/3] chore: sync versions to 2.0.1 --- .claude-plugin/marketplace.json | 4 ++-- .claude-plugin/plugin.json | 2 +- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index ea8577e..72e5974 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -8,8 +8,8 @@ "name": "matrix", "source": "./", "description": "Claude on Rails Tooling System - Persistent memory for Claude Code", - "version": "2.0.0" + "version": "2.0.1" } ], - "version": "2.0.0" + "version": "2.0.1" } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 672bdb5..a70c265 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "matrix", "description": "Claude on Rails Tooling System", - "version": "2.0.0", + "version": "2.0.1", "author": { "name": "Matrix Contributors" }, diff --git a/package.json b/package.json index 1ea7a79..bc2fb05 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claude-matrix", - "version": "2.0.0", + "version": "2.0.1", "description": "Claude on Rails Tooling System", "type": "module", "main": "src/index.ts", From c63b3e2ef00961e48258bea3ba98e29781b7c826 Mon Sep 17 00:00:00 2001 From: ojowwalker77 Date: Fri, 9 Jan 2026 22:23:07 -0300 Subject: [PATCH 3/3] feat: include previous release in GitHub release notes Release notes now show both current and previous version's changelog for better context when reading release notes. --- .github/workflows/release-plugin.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-plugin.yml b/.github/workflows/release-plugin.yml index 0fe8b4f..cf5ecb9 100644 --- a/.github/workflows/release-plugin.yml +++ b/.github/workflows/release-plugin.yml @@ -164,11 +164,20 @@ jobs: id: changelog run: | VERSION="${{ needs.check-release.outputs.version }}" - # Extract changelog section for this version - CHANGELOG=$(awk "/^## \[$VERSION\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md) + # Extract changelog for current version AND previous version for context + # count=0: not started, count=1: current version, count=2: previous version + CHANGELOG=$(awk ' + /^## \[/ { + count++ + if (count == 1) { print "# What'\''s New in v'"$VERSION"'"; print ""; next } + if (count == 2) { print ""; print "---"; print ""; print "# Previous Release"; print ""; } + if (count > 2) { exit } + } + count >= 1 && count <= 2 { print } + ' CHANGELOG.md) # Write to file for multiline content echo "$CHANGELOG" > /tmp/changelog.md - echo "Changelog for v$VERSION:" + echo "Changelog for v$VERSION (with previous release):" cat /tmp/changelog.md - name: Create plugin archive