archspec 1.0.0.rc1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24d73489bf5bdd8a56deffac28bbcd11aab271db3281afcce4e0aa21c93de28b
4
- data.tar.gz: 9c6303777aededa6ce4f7780943a5a7257b33cbef978e50369296d1a4d0b0a8f
3
+ metadata.gz: 07a83d8f3402826cb160272cea2739a3ad9542bc7d35fd6590544c39fcf7c597
4
+ data.tar.gz: 5d087f15b56575032c262a7f7e097270b4bad4bb09acd066003bfbbc338900eb
5
5
  SHA512:
6
- metadata.gz: 1c69995b8ce63a81ed15be9233a4f6199deb5faa710a0853613150d464229b653a4d7e122b032ba417e6048b7cf1285ee6a9272ff0217071b8cd727ed02add63
7
- data.tar.gz: 8de9a4380f15a1c8f197980207ba20939bfac7a9a7a61e9e297eb57b517c491eb9017ab91c22057b3d88536c609bac385a6fddc311cb76b8915b66c64c5dc9dc
6
+ metadata.gz: c1ee035facb38cb68d9bde3b469f6fdd0e98bf434437254c3f9123cb7eb4ca9cfb2206ce0e4ad01fd25179054cc91e0c821de729026a08e69bb2cfb99092c084
7
+ data.tar.gz: de5d78b6d8e71e26d2a9cc67e6ad0854f532b876bd7e885536e867ddf27d5fb1a324b3bdb79e63f4d880c0194de036e94c2ae77d10219bedd19f6d84008e0d6b
data/README.md CHANGED
@@ -1,19 +1,24 @@
1
+ <div align="center">
2
+
1
3
  # ArchSpec
2
4
 
3
- Architecture linter for Ruby and Rails.
5
+ <strong>Executable architecture specifications for Ruby and Rails</strong>
6
+
7
+ <p>Declare your components and boundaries in one <code>Archspec.rb</code>, and every change gets checked in CI, whether a person or a coding agent wrote it. No AI involved, just Prism.</p>
8
+
9
+ Battle tested in [<picture><source media="(prefers-color-scheme: dark)" srcset="https://rubyllm.com/assets/images/logotype_dark.svg"><img src="https://rubyllm.com/assets/images/logotype.svg" alt="RubyLLM" height="30" align="absmiddle"></picture>](https://rubyllm.com) and at [<picture><source media="(prefers-color-scheme: dark)" srcset="https://chatwithwork.com/logotype-dark.svg"><img src="https://chatwithwork.com/logotype.svg" alt="Chat with Work" height="30" align="absmiddle"></picture>](https://chatwithwork.com)
4
10
 
5
- ArchSpec turns your application's architecture into executable checks. Declare
6
- your components, dependencies, and boundaries in one file, then check every
7
- change in CI, whether a person or a coding agent wrote it. It reads Ruby source
8
- with Prism and never boots the app.
11
+ [![Gem Version](https://badge.fury.io/rb/archspec.svg)](https://rubygems.org/gems/archspec)
12
+ [![Gem Downloads](https://img.shields.io/gem/dt/archspec)](https://rubygems.org/gems/archspec)
13
+ [![CI](https://github.com/crmne/archspec/actions/workflows/ci.yml/badge.svg)](https://github.com/crmne/archspec/actions/workflows/ci.yml)
9
14
 
10
- It maps conventional Rails files to constants and checks the structural rules
11
- you write down: components, layers, constant references, inheritance, mixins,
12
- named method calls, method protocols, cycles, and Rails boundaries.
15
+ <img src="https://archspecrb.dev/assets/images/archspec-check.png" alt="archspec check reporting an architecture violation with a code frame, the offending span underlined, and the evidence as a note" width="760">
13
16
 
14
- It does not try to infer the "true" design pattern of arbitrary Ruby code. You
15
- describe the architecture your team wants. ArchSpec checks whether the code still
16
- matches it.
17
+ </div>
18
+
19
+ ---
20
+
21
+ ArchSpec turns your architecture into executable checks: components, layers, constant references, inheritance, mixins, named method calls, method protocols, naming conventions, cycles, and Rails boundaries. It is plain static analysis: it reads Ruby source with Prism, never boots the app, and no AI is involved in checking your code. The full Discourse app, 1,899 files, checks in 2.5 seconds.
17
22
 
18
23
  ## Why ArchSpec?
19
24
 
@@ -31,6 +36,10 @@ to remember, and checks them on every change:
31
36
  - query objects do not call obvious write methods
32
37
  - generated code follows the same boundaries as hand-written code
33
38
 
39
+ ArchSpec does not try to infer the "true" design pattern of arbitrary Ruby code.
40
+ You describe the architecture your team wants. ArchSpec checks whether the code
41
+ still matches it.
42
+
34
43
  ## Show me the code
35
44
 
36
45
  Start with conventional Rails boundaries:
@@ -36,7 +36,8 @@ module ArchSpec
36
36
  # prefix), applied project-wide. Adds no components, so it composes with any
37
37
  # other architecture. No options.
38
38
  #
39
- # See the guides at https://archspecrb.dev/architectures/ for each in depth.
39
+ # See the {architecture guides}[https://archspecrb.dev/architectures/] for
40
+ # each preset in depth.
40
41
  module Architectures
41
42
  extend self
42
43
 
@@ -7,10 +7,15 @@ module ArchSpec
7
7
  def evaluate(definition, graph, todo: Todo.empty)
8
8
  diagnostics = parser_diagnostics(graph) + definition.rules.flat_map { |rule| rule.evaluate(graph) }
9
9
 
10
+ # Deduplicate before rejecting. One statement can raise several diagnostics
11
+ # that differ only in evidence, because `include Foo` is both an includes
12
+ # edge and a constant reference. Todo entries are matched on evidence, so
13
+ # rejecting first would drop the recorded diagnostic and report its
14
+ # surviving sibling as new.
10
15
  diagnostics
11
- .reject { |diagnostic| graph.suppressed?(diagnostic) || todo.include?(diagnostic) }
12
16
  .sort_by { |d| [d.location.path, d.location.line, d.rule, d.message, d.evidence] }
13
17
  .uniq { |d| [d.rule, d.message, d.location.path, d.location.line] }
18
+ .reject { |diagnostic| graph.suppressed?(diagnostic) || todo.include?(diagnostic) }
14
19
  end
15
20
 
16
21
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArchSpec
4
- VERSION = '1.0.0.rc1'
4
+ VERSION = '1.0.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: archspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc1
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carmine Paolino
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-08-12 00:00:00.000000000 Z
11
+ date: 2026-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prism