Skip to content
CAI
Software that uses CAICheck a score

Shopify/packwerk

64.5

Adequate · 19 September 2026

3.4k

lines of production code

Ruby

primary language

1

measurement over time

CAI band scale
CAI lens gauges

What this system is

This system is Packwerk, a static analysis tool for Ruby on Rails applications that enforces package boundaries and dependency rules. It validates that code references between packages comply with a declared dependency graph, detecting violations and managing a 'todo' file for unlisted dependencies. The system provides CLI commands to check for offenses, update dependency manifests, and format results, while supporting caching and lazy loading for performance.

How it got here

2020 — Packwerk 3.0 release and architecture modernization

22 changes.

This period focused on the major release of Packwerk 3.0, which removed privacy checking, simplified configuration, and upgraded the Ruby parser to Prism. The work involved a comprehensive architectural refactor to implement lazy autoloading and file-based caching for improved performance, alongside a strict migration to Sorbet type checking across the codebase and test infrastructure.

2021–2022 — Packwerk architecture and testing overhaul

12 changes.

This period focused on restructuring Packwerk's core validation logic by introducing dedicated classes for reference checking, dependency validation, and orchestration. Significant effort was also directed toward enhancing type safety through Sorbet RBI shims and expanding the test suite with comprehensive unit and integration tests for the new components.

2023–2024 — CLI refactoring and test coverage

5 changes.

This period focused on restructuring the Packwerk CLI commands to improve startup performance through lazy loading and enforcing strict mode behavior. Comprehensive unit tests were added to verify the new command logic, reference checking, and autoload behavior. Additionally, a standardized development environment was established using a Ruby-based devcontainer with Watchman support.

Features

Add RBI shims for Minitest, Packwerk, Parser, and Psych

New RBI shim files have been added to improve type checking for several dependencies. A shim for Minitest::Test now includes the StubConst module. Type signatures for Packwerk::Reference and Packwerk::UnresolvedReference have been added, defining their keyword-based initializers and attribute readers. The Parser::Base class now has a strict signature for its parse method, allowing it to return nil on non-fatal errors. Additionally, a shim for Psych adds a to\_yaml method to Object.

sorbet/rbi/shims · high confidence

Added binstubs for development tools

New binstubs have been added to the \bin\ directory for \m\, \rake\, \rubocop\, \srb\ (Sorbet), and \tapioca\. These scripts allow developers to run these tools directly from the project root without needing to invoke them through \bundle exec\, ensuring consistent execution against the project's specific gem versions.

bin · high confidence

Initial devcontainer setup with Ruby 4.0.3 and Watchman

Developers can now launch the project in a standardized VS Code devcontainer environment. The container is based on the Ruby 4.0.3 image and includes the Sorbet VS Code extension. It also installs Watchman (version v2026.05.04.00) with support for both x86\_64 and ARM64 architectures, ensuring file-watching capabilities are available out of the box.

.devcontainer · high confidence

New DependencyValidator for package manifest and graph validation

A new DependencyValidator class has been introduced to centralize validation logic for package dependencies. This validator checks for malformed syntax in package manifests (specifically the 'enforce\_dependencies' and 'dependencies' settings), ensures the dependency graph is acyclic by detecting and reporting circular dependencies, and verifies that all declared dependencies point to valid package paths. This change consolidates these checks into a single component, improving the clarity and maintainability of dependency validation within the Packwerk library.

lib/packwerk/validators · high confidence

New dependency checker enforces package dependency rules

A new DependencyChecker has been introduced to validate that references between packages comply with the configured dependency graph. This checker ensures that a package cannot reference constants from another package unless that dependency is explicitly declared, providing clear error messages and support for strict mode enforcement to fail checks for unlisted violations.

_lib/packwerk/reference\checking/checkers · high confidence

Behavioural changes

Enable strict typing and add parallel gem requirement

The Tapioca configuration file now enforces strict type checking (changing from \typed: false\ to \typed: strict\) and explicitly requires the \parallel\ gem, ensuring that the tool operates with higher type safety and includes support for parallel processing dependencies.

sorbet/tapioca · high confidence

Packwerk 3.0 release: removal of privacy checking and configuration simplifications

This release extracts Packwerk from the Shopify codebase and introduces breaking changes for users upgrading from 2.x. The most significant behavioral change is the removal of privacy checking (the \enforce\_privacy\ configuration and associated violations); users requiring this functionality must now use the \packwerk-extensions\ gem. Configuration has been simplified: the \load\_paths\ key is no longer read from \packwerk.yml\ (Packwerk now uses Rails' load paths), and custom inflections no longer require a separate \inflections.yml\ file (revert to the standard \inflections.rb\ initializer). The \deprecated\_references.yml\ file has been renamed to \package\_todo.yml\, and the \update-deprecations\ command is now \update-todo\. Additionally, the \vendor\ directory is excluded by default, and the minimum supported Ruby version is now 2.7.

(repo-wide) · high confidence

Packwerk CLI commands restructured with lazy loading and strict mode enforcement

The CLI command architecture has been refactored to use lazy loading via \LazyLoadedEntry\ and \const\_get\ instead of a static registry, improving startup performance. The \check\ and \update-todo\ commands now strictly enforce that unlisted strict mode violations are not silently added to \package\_todo.yml\ files, ensuring that existing strict mode violations prevent automatic updates to the todo file. Additionally, the commands now support \--offenses-formatter\ and \--parallel\ options, and output has been standardized through dedicated formatters.

lib/packwerk/commands · high confidence

Packwerk introduces caching and refactors core architecture

Packwerk now supports a configurable file-based cache to significantly improve performance by skipping unchanged files, with automatic invalidation when configuration or inflection files change. The tool's internal architecture has been refactored to use a lazy-loading command registry, replacing the previous eager-loading approach to reduce startup time. Additionally, the deprecated \deprecated\_references.yml\ files have been fully replaced by \package\_todo.yml\, and the \update\ command has been renamed to \update-todo\ to reflect this change.

lib/packwerk · high confidence

Packwerk template simplification and configuration updates

The Packwerk generator templates have been updated to streamline initial configuration and improve usability. The custom inflections file (inflections.yml) and the custom binstub/test templates (packwerk, packwerk\_validator\_test.rb) have been removed, eliminating the need for users to maintain custom inflections or a separate test/binstub file. The root package.yml template now defaults dependency enforcement to false, requiring users to explicitly opt-in. The main packwerk.yml.erb configuration template has been updated to exclude the vendor directory by default, corrected to reference the 'configuring-packwerk' documentation section, and now includes commented-out options for enabling and configuring the cache directory, replacing the removed inflections file reference.

lib/packwerk/generators/templates · high confidence

Refactored formatters with Sorbet strict typing and new default offense output

The formatter subsystem has been updated to Sorbet strict typing, introducing a new DefaultOffensesFormatter that provides a structured summary of detected offenses and stale violations. The ProgressFormatter has been refactored to use block-based execution for validation and inspection phases, improving how progress and timing are reported to the user. Additionally, the output styling system has been moved to an interface-backed design, allowing for more flexible presentation of errors and progress indicators.

lib/packwerk/formatters · high confidence

Refactored reference checking into a dedicated ReferenceChecker class

The reference checking logic has been restructured to use a new \ReferenceChecker\ class that orchestrates multiple \Checker\ instances. This change separates the orchestration layer from individual checker implementations, allowing the system to iterate through registered checkers and aggregate \Offense\ objects for any invalid references found. This improves the modularity and strict typing of the reference validation process.

_lib/packwerk/reference\checking · high confidence

Ruby parser switches to Prism and ERB parser becomes configurable

The Ruby parser now uses the Prism engine (via Prism::Translation::Parser) instead of the previous parser/current implementation, improving parsing reliability. The ERB parser has been refactored to include a new ParserInterface, allowing its underlying parser class to be configured via the Factory (e.g., for testing or alternative implementations). Additionally, all parser components have been upgraded to Sorbet strict typing.

lib/packwerk/parsers · high confidence

Simplification and type-strengthening of Packwerk generators

The generator classes have been refactored to use Sorbet's RBS comment signatures instead of the \T::Sig\ DSL, and \ConfigurationFile\ and \RootPackage\ are now typed as \strict\. The \ApplicationValidation\ generator has been removed entirely, and \ConfigurationFile\ no longer accepts or manages \load\_paths\, simplifying the configuration generation process.

lib/packwerk/generators · high confidence

Sorbet configuration updates for Prism parser and experimental features

The Sorbet configuration has been updated to enable the Prism parser and two experimental features: 'requires ancestor' and 'RBS comments'. Additionally, the vendor/bundle directory is now ignored during type checking.

sorbet · high confidence

Switch to lazy autoloading and refine public API surface

The library now uses \ActiveSupport::Autoload\ to load classes lazily instead of requiring all files upfront, which improves startup performance and avoids early constant resolution. The public API has been reorganized: \Checker\, \Cli\, \Configuration\, \OffenseCollection\, and \OffensesFormatter\ are now explicitly autoloaded as public interfaces, while internal components like \Generators\ and \ReferenceChecking\ are marked as private constants. Additionally, the \ViolationType\ constant has been removed from the main require list, and specific Active Support extensions (\string\ pluralization, \object/json\) are now explicitly required.

lib · high confidence

Updated Sorbet RBI stubs for ActionPack, ActionView, and ActiveSupport to version 7.2.3.1

The Sorbet RBI stubs in \sorbet/rbi/gems\ have been regenerated to reflect the API of \actionpack\, \actionview\, and \activesupport\ version 7.2.3.1. This update ensures that static type checking aligns with the latest changes in these Rails components, including new methods and type signatures for controller actions, view rendering, and core utility modules.

sorbet/rbi/gems · high confidence

Updated executable to support Spring and test environment

The packwerk executable now sets the RAILS\_ENV to 'test' to ensure test helper paths are available in autoload paths, and explicitly duplicates command-line arguments before passing them to the CLI to prevent modification issues when running under Spring.

exe · high confidence

Test coverage

Add test fixtures for Sales component models; Added and updated unit tests for Packwerk formatters and generators; Added empty test fixture files for skeleton config; Added integration tests for Packwerk CLI and offense collection; Added minimal test fixture for Packwerk validation; Added test fixture for valid ERB JavaScript template; Added test fixtures for extended Packwerk configuration and extensions; Added test fixtures for skeleton vendor cache; Added test for Packwerk autoload behavior; Added test support helpers for Packwerk fixtures and formatters; Added test support helpers for Rails fixtures, constant stubbing, and YAML management; Added unit tests for Packwerk check and update-todo commands; Added unit tests for Packwerk core components; Added unit tests for the ReferenceChecker component; Removed integration test for custom executable; Removed legacy unit test suite for core validators and CLI; Removed test fixture for PrivateThing model; Removed tests for custom inflection loading; Test suite infrastructure and configuration updates; Updated and expanded unit tests for Packwerk parsers.

Dependencies

Packwerk 3.3.1: Major dependency and runtime upgrades

Packwerk has been upgraded to version 3.3.1, requiring Ruby 3.3+ and Rails 6.0+ (via activesupport). The gem now depends on the Prism parser (\>= 1.4.0) for Ruby parsing, replaces sorbet-runtime with sorbet-static for development, and adds bundler, benchmark, parallel, and zeitwerk (\>= 2.6.1) as runtime dependencies. Development dependencies have been reorganized, adding minitest-focus and minitest-mock while removing sorbet-runtime from the runtime bundle.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Baseline

  • First survey — no prior run to compare against. CAI 65.

Lenses

  • Code Health 99
  • Architecture 99
  • Maturity 51
  • Readiness 69
  • Security 71

Changes since last survey

  • 300 commits — 278 feature/other, 22 fixes

By area

  • lib/packwerk — 95 commits
  • (repo) — 88 commits
  • (root) — 80 commits
  • .github/workflows — 10 commits
  • test/unit — 7 commits
  • sorbet/rbi — 6 commits
  • lib/packwerk.rb — 3 commits
  • .devcontainer/Dockerfile — 2 commits
  • .github/dependabot.yml — 2 commits
  • .devcontainer/install-watchman.sh — 1 commit
  • exe/packwerk — 1 commit
  • sorbet/config — 1 commit
  • test/fixtures — 1 commit
  • test/integration — 1 commit
  • test/loading_test_helper.rb — 1 commit
  • test/support — 1 commit

Notable commits

  • fix: Bump sorbet, fix failing tests
  • fix: Custom offenses formatter docs fix
  • fix: Fix Sorbet
  • fix: Fix builder subclass
  • fix: Fix bundler version for Ruby 2.7
  • fix: Fix dependabot indent
  • fix: Fix documentation link in packwerk.yml template
  • fix: Fix error when parsing ERB files with yield on the top level
  • fix: Fix exception when running sig blocks
  • fix: Fix test failures from gem bumps and RBS assertion changes
  • fix: Fix type check to work with new version of sorbet
  • fix: Fix watchman installation in devcontainer
  • fix: Merge pull request #334 from Shopify/fix-exception-sig-blocks
  • fix: Merge pull request #379 from Shopify/revert-371-cw/update-stale-violations-error-message
  • fix: Merge pull request #398 from exterm/fix-package-mismatch-on-overlapping-prefix
  • fix: Merge pull request #404 from Shopify/rm-fix-prism
  • fix: Merge pull request #451 from Shopify/at/fix-prism-warnings
  • fix: Merge pull request #452 from Shopify/at-fix-dependabot
  • fix: Merge pull request #463 from Shopify/uk-fix-gemspec-files
  • fix: Merge pull request #471 from Hashim1999164/fix/skip-dynamic-namespace-in-class-defs
  • …and 280 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

Shopify/packwerk was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 19 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 31e534283f93a225b520cddab3c2d735557c76de — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-13a154b7f5d1.