Replixa v2 ships today. This post covers what changed, why we built it this way, and what the upgrade path looks like for existing users. For the changelog entry, see the changelog.
Repository-wide context for style graph construction
In v1, the style graph was built from a configurable path scope — you pointed Replixa at a directory, and it built the graph from code in that directory. This worked well for single-service repositories and small monorepos. It broke down when a PR touched multiple services, or when a convention that mattered for a PR was established in a different part of the repository from the changed files.
v2 builds the style graph from the full repository by default. Rather than scoping graph construction to the directories you configure for review, the configuration now separately controls where graph construction happens (full repo, by default) and where suggestions are posted (controlled by your include/exclude paths, as before).
What this changes in practice: a PR modifying a shared utility module will now be reviewed against patterns established throughout the entire codebase that imports from that module, not just patterns within the module itself. A convention that's used consistently in 8 services that consume a utility function will be visible to the graph when reviewing PRs that modify that function.
For large repositories, full-repo graph construction adds 2–4 minutes to the initial setup time but doesn't add meaningfully to per-PR review latency — the graph is pre-built and maintained incrementally. The suggestion latency from PR open remains under 90 seconds for repositories up to 5 million lines.
Multi-language support: Python, Go, Rust, and TypeScript
v1 supported JavaScript and TypeScript. v2 adds Python, Go, and Rust.
Each language required separate work because the style graph relies on language-specific AST parsing and symbol extraction. The patterns that matter for Python codebases (decorator conventions, module-level configuration patterns, how exceptions are structured) are different from Go (how interfaces are implemented, whether function receivers follow naming conventions, how exported types are named relative to unexported ones) and Rust (how errors are propagated, whether Result types are handled consistently, trait implementation conventions).
For mixed-language repositories — which are common in organizations that have a Python data layer, a Go services layer, and a TypeScript frontend — v2 builds a per-language subgraph within the same repository graph. A PR that modifies Python and TypeScript files will receive suggestions calibrated to the respective language conventions, rather than a single cross-language graph that would produce noise across language boundaries.
Multi-language support requires no configuration changes beyond ensuring the language is in the include path scope. Replixa detects language automatically from file extensions and AST parsing.
Per-team suggestion threshold controls
The most-requested feature in v1 feedback: team-level threshold configuration without requiring separate repository configurations.
v2 introduces teams blocks in replixa.yml that allow different thresholds and category settings per team, scoped to file path patterns:
# replixa.yml v2 example
version: 2
teams:
- name: core-infra
paths: ["services/core/**", "lib/shared/**"]
suggestion_threshold: 0.65
security_patterns: true
- name: product-frontend
paths: ["src/client/**", "src/app/**"]
suggestion_threshold: 0.80
security_patterns: false # Separate SAST pipeline handles this
- name: data
paths: ["services/data/**", "pipelines/**"]
suggestion_threshold: 0.72
suppress_categories:
- import_order # Handled by black/isort in CI
Team configuration resolves by file path. If a PR modifies files in multiple team scopes, each file receives suggestions calibrated to its team's configuration. There's no requirement for team membership to be defined anywhere outside replixa.yml — it's purely path-based, so it doesn't require any user management setup.
For organizations that were working around v1's single-threshold limitation by maintaining separate replixa.yml files in subdirectories, the v2 teams block consolidates this into the root config. The migration script in the v2 release notes handles the conversion automatically if you're running the CLI.
What's not in v2
A few things that were on the v2 roadmap and didn't make it into this release: Bitbucket native suggestions API support (currently in development, v2.1 target), a public API for querying style graph data programmatically (spec is written, implementation is ongoing), and custom finding categories that teams can define without writing code. All three are on the roadmap with timelines we'll publish in the changelog when we have confidence in them.
We also decided not to include an auto-fix mode that applies all inline suggestions in batch without author review. The design conversation on this one is ongoing — there are use cases where batch application would be useful (large-scale convention migration, for example), but the risk of silently applying patches that look right but are wrong in context is high enough that we want to think carefully about the interaction model before shipping it. We'll share the design doc publicly before we build it.
Upgrading from v1
v2 is backward-compatible with v1 replixa.yml configurations. No configuration changes are required to get the new behavior — full-repo graph context and multi-language support are opt-in defaults that activate automatically on the next graph rebuild after you update to review-action@v2 (GitHub Actions) or review-runner:latest (GitLab CI).
The teams block is a new addition — v1 configs without it continue to use the global threshold. If you want per-team controls, add the teams block; otherwise no migration is needed.
One breaking change: if you were using graph_scope in your v1 config to limit graph construction to a subdirectory, that config key is now deprecated. The equivalent in v2 is using the include paths for suggestion posting scope while the graph builds full-repo. If you need to limit graph construction scope for performance reasons (very large monorepos with multiple independent products), the v2 config supports a graph_include key — see the style graph documentation for details.
For any questions on the upgrade path, [email protected] is monitored by the team directly. We'll respond within one business day for questions related to v2 migration.
What we learned building v2
The biggest technical challenge in v2 wasn't multi-language support — the AST parsers for Python, Go, and Rust are well-established, and the symbol extraction work was largely mechanical. The hard part was ensuring that full-repo graph construction didn't inflate false-positive rates for codebases with mixed-quality conventions across modules.
In early v2 testing, repositories that had a mature, well-structured core with a few newer modules built by junior engineers produced graphs that were "contaminated" by the lower-quality patterns in the newer modules. The high-quality modules would occasionally receive suggestions that reflected the lower-quality modules' patterns rather than their own established conventions. This is a solvable problem once you name it: the fix was weighted graph construction where pattern frequency within a module's own file tree is weighted more heavily than cross-module frequency. A convention that's consistent within Module A but inconsistent with Module B will generate suggestions calibrated to Module A's internal consistency, not to cross-module average.
Per-team threshold controls emerged from what was by far the most common support request from v1 users: "we have two teams with very different tolerance levels for automated suggestions, and we can't find a single threshold that works for both." The v2 implementation is simpler than we initially designed — we'd planned a user management layer that mapped GitHub/GitLab team memberships to threshold profiles, but the path-based resolution turned out to work better in practice. Most teams' scope of ownership maps cleanly to directory structure, and path-based resolution doesn't require any integration with identity providers.