feat(rules): config + ESLint-style rules engine with check command#42
Merged
Conversation
Implements specs/backlog/2026-06-02-config-rules-engine.md. - config: discovery (codebase-intelligence.json + variants + package.json key, walk-up) + zod validation + CLI overrides + ConfigError (exit 2) - engine: pluggable Rule contract, severity resolution (off/warn/error|0/1/2), ci-ignore-file / ci-ignore-next-line suppressions, stable fingerprints - rules: no-comments (configurable: keeps JSDoc/directives/header by default, style line|block|all), no-circular-deps, no-dead-exports - formatters: text, json, sarif - CLI 'check' command: exit 0/1/2, --format/--json/--config/--fail-on/--gate/--base - MCP 'check' tool + setRoot/getRoot (read-only, advisory actions only) - silence git stderr leak in getGitChurn/getHeadHash (non-git dirs) - tests: config loader, rules engine (real pipeline), CLI e2e (spawned binary), MCP tool — 38 tests, no internal mocks - docs: mcp-tools (16th tool), architecture + CLAUDE module maps
Blocker: - F1: implement file-level --gate new-only --base (git diff filtering) instead of shipping inert flags Correctness/reliability: - surface rule-throws to stderr (no silent CI false-negative) - confine sourceOf reads to project root via realpath (blocks ../ and symlink-out) - failOn:'never' now disables the maxWarnings gate too - block-comment ci-ignore (/* ci-ignore-file */) suppressions now honored - no-comments allow[] = comment-body prefix match (no 'a' over-matching 'bad') Config: - ConfigError messages use basename (no full-path leak via MCP) - stop config walk-up at repo root (no ambient-config hijack) - distinct read vs parse errors (EACCES != invalid JSON) SARIF/output: - emit shortDescription, partialFingerprints, endLine/endColumn - MCP check uses canonical formatJson; extract shared formatSummaryLine - quiet-first output ordering Types/MCP: - FindingAction.kind union; RuleSetting tuple rejects [off, opts] - register check in codebase://setup; generic tool description; getRoot TSDoc - example config gate: all (safe default) Tests: new-only gate (real git repo), block suppression, allow precision, failOn:never+maxWarnings
- git diff --relative + forward-slash normalization so changed-file paths compare correctly against rootDir-relative findings (was: subdir target filtered out every finding -> silent pass; also fixes Windows path.sep) - regression test: gate on a repo-subdirectory target keeps its findings - pin --quiet-wins-over---summary contract with e2e tests (pass: silent, fail: summary line) - hermetic git identity env in gate tests (CI without global git config)
bntvllnt
added a commit
that referenced
this pull request
Jun 10, 2026
#44) ## What Docs only — brings `roadmap.md` back in line with shipped reality and records the 2026-06-10 architecture sweep findings as a roadmap item. - **Header**: `Last updated: 2026-06-10 · shipped through v2.4.1 + rules engine (#42)` - **§2 baseline sync**: `check` added to the command list; new *Shipped since* block covering #36–#42 (config + ESLint-style rules engine foundation, `init` opt-in agent selection) - **New §5.13 — Operation registry, one engine N surfaces (P1)**: the 15 analysis operations are exposed twice (CLI + MCP) with their lifecycle (validation, error routing, hints, serialization, graph-load) smeared across `cli.ts` / `mcp/index.ts` / `src/core`. Proposal: one `Operation<TInput, TResult>` descriptor per op (zod schema feeding both surfaces, result/error union, hints, formatter) with CLI/MCP as thin adapters — the same registry shape `src/rules/` paved in #42. - **§6 sequencing**: §5.13 slotted in P1 before §5.7, since output formats (SARIF/CodeClimate/…) become formatters over the registry, and the §5.12 LSP becomes a third thin adapter. ## Evidence (self-analysis, graph-backed) | Signal | Value | |---|---| | `cli.ts` | 1205 LOC, fan-in 0 / fan-out 13, coupling 0.93 (top hotspot) | | `mcp/index.ts` | 446 LOC, cohesion 0.17 (JUNK_DRAWER) | | Validation | duplicated: `parseInt`+`isNaN` guards (CLI) vs zod (MCP) | | Graph-load pipeline | duplicated verbatim: `loadGraph` vs `runMcpMode` in `cli.ts` | | Precedent | `src/rules/` registry: cohesion 0.71, COHESIVE | ## Why The roadmap predates #41/#42, so it didn't answer "where are we" — and the sweep's keystone finding belongs on the direction file, not in a chat log.
bntvllnt
added a commit
that referenced
this pull request
Jun 10, 2026
#46) ## Summary Working-tree housekeeping batch: **.gitignore** — three groups added: - analysis + coverage artifacts (`.code-visualizer/`, `coverage/`) - local agent state (`.claude/`) - self-dogfood `init` outputs stay local, consistent with #35 being closed unmerged (`.cursor/`, `.pi/`, `GEMINI.md`, `CONVENTIONS.md`, `.github/copilot-instructions.md`) **specs/** — archive shipped, commit backlog: - `mcp-only` → shipped (2026-03-03, #3) - `cli-mode` → shipped (2026-03-12, #16) — was untracked despite all 10 scope items done - `config-rules-engine` → shipped (2026-06-10, #42) - status frontmatter updated + 3 `history.log` entries (marked *archived retroactively*; actuals unknown, left as `-`) - 3 untracked 2026-04-29 backlog specs committed (module-depth, find-seams, forces signals) Docs/config only — no source changes. ## Not touched (follow-up decision) 7 remaining `specs/active/` entries from the pre-MCP-only UI era (analytics-v2, nextjs-migration, e2e-playwright, group-metrics-legend, agent-intelligence-roadmap, symbol-level-ui, group-spatial-clustering) look obsolete (dropped, not shipped) — archiving them to `specs/dropped/` needs a judgment call per spec.
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.
Implements
specs/backlog/2026-06-02-config-rules-engine.mdend-to-end.What
src/config) — discovery (codebase-intelligence.json+ dotfile variants +package.json#codebaseIntelligence, walk-up), zod validation against the committedschema.json, CLI overrides,ConfigError→ exit 2.src/rules/engine.ts) — pluggableRulecontract, ESLint-style severities (off|warn|erroror0|1|2,[severity, options]),// ci-ignore-file/// ci-ignore-next-line <rules>suppressions, stable fingerprints, deterministic ordering.no-comments(the requested one; configurable — keeps JSDoc, tool/compiler directives, and a file-leading license header by default;style: line|block|all),no-circular-deps,no-dead-exports.text,json,sarif.check— exit codes0clean /1findings ≥ failOn /2config or usage error; flags--format/--json/--config/--fail-on/--gate/--base/--quiet/--summary.checktool — returns{verdict, summary, findings}. Read-only —actions[]are advisory hints, never applied (per roadmap §3).getGitChurn/getHeadHashno longer leak git's stderr on non-git dirs.Tests (38 new, no internal mocks)
config-loader— discovery, package.json key, walk-up, invalid JSON / unknown-key →ConfigError, overrides.rules-engine— real parser→graph→analyzer→engine pipeline: no-comments option matrix, suppressions, circular/dead-export rules, formatters, verdict gating.cli-check.e2e— spawns the real built binary, asserts exit codes + stdout (json, sarif, suppression, config error,--config).mcp-check— real in-memory MCP server + client.Validation
pnpm lintclean ·pnpm typecheckclean ·pnpm buildclean.pnpm vitest run(parallel): 380 passed, 0 errors.src/rules97.5%.Not in scope (follow-ups)
Boundary rules engine, audit
new-onlydiffing, more formatters (codeclimate/pr-comment),init/hooks/watch— speced, not built here.