Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 43 additions & 24 deletions .github/PRE_RELEASE_CHECKLIST.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
# Stable-release readiness

All four currently open feature issues (#47, #48, #54, #55) have implementations in the pending
PR stack. They are not considered shipped until those changes reach `main` and a gem is published.

## Before 1.0.0

- Merge the reviewed integration work and the rationale/exclusion PRs in dependency order. Retarget
stacked PRs to `main` after their base merges. Do not bypass the existing branch protections.
- Merge the pre-v1 audit fixes and rerun the entire matrix on `main`: supported Ruby versions,
Windows/Linux, coverage, lint, dogfooding, documentation links, installed-gem checks, and the RAG fixture.
- Keep the import-only default and the explicit `imports_and_constants` opt-in documented. Unknown
runtime behavior, ambiguous constants, and dynamic import paths are not a complete Ruby interpreter.
- Review representative passing and failing rules manually. Include a constant-only forbidden edge,
a safely inferred import, a `.because(...)` failure, and `.archignore` exclusions.
- Set the version to `1.0.0`, refresh the local gem lock entry, date the changelog, update installation
instructions, and replace prototype/pre-release wording with an accurate stable API contract.
- Run `bundle exec ruby scripts/check_release_metadata.rb --release`; development checks alone
intentionally do not prove publication readiness.
- Run `bundle exec rake security` with a freshly updated advisory database and review the JSON
evidence. Resolve actionable findings; do not add unexplained advisory ignores to pass CI.
- Publish only after maintainer approval via the trusted-publisher workflow. Install the published
version in a clean project and rerun a passing/failing architecture example before announcing it.
The original feature backlog (#47, #48, #54, #55) and the correctness/QA audit fixes (#63-65) are
merged. PRs #68-70 were reviewed and merged on 2026-10-26; the resulting `main` passed CI, security
scanning, and documentation deployment. This checklist tracks the 1.0.0 preparation, not proof that
RubyGems publication has happened. The preceding published gem is 0.0.1.

## 1.0.0 preparation

- [x] Merge the reviewed extraction, source-boundary, cycle, parser-diagnostic, conditional-constant,
and coverage fixes without bypassing protections.
- [x] Document the import-only default, explicit expanded mode, stable public surface, and migration
from 0.0.1. Unknown runtime behavior and ambiguous or unsupported names remain analysis limits.
- [x] Synchronize version 1.0.0, local lock entry, dated changelog, and installation instructions.
- [x] Run `bundle exec ruby scripts/check_release_metadata.rb --release` on the candidate.
- [x] Run the full coverage/lint/dogfood suite, build/link-check docs, and check both public-API
smoke scripts. Native symlink skips on Windows must also be exercised in Linux CI.
- [x] Refresh advisory data and pass `bundle exec rake security`, including scanner-health checks.
- [x] Check passing/failing rules and both dependency modes on the pinned Rack/Rake/RSpec corpus.
- [x] Build with `gem build --strict`, install that exact artifact in an isolated gem home, confirm
its version/path, and exercise the installed API from a clean project without the source checkout.

Preparation evidence (2026-10-26): 614 examples, zero failures, eight native-symlink skips on Windows;
98.48% library line and 91.51% branch coverage; 267 Ruby files lint-clean; 179 validated documentation
pages; 1,269 fresh advisories with no findings and the vulnerable-fixture health check passing.
All six pinned corpus/mode baselines matched. The isolated installed 1.0.0 artifact passed a clean
rule, an intentionally failing one-line import change, conditional-constant policies, exclusion
refresh, and strict malformed-source diagnostics, plus both dependency-analysis smoke scripts.

## Publication remains a separate approval

- [ ] Review and merge the preparation PR, then verify the full matrix on that exact `main` revision:
supported Ruby versions, Windows/Linux, library-only coverage, lint, dogfooding, docs, packaging,
installed-gem checks, security, and the downstream RAG fixture.
- [ ] Confirm the changelog date at publication and explicitly authorize the trusted-publisher
`Release` workflow for version `1.0.0` on `main`. Verify the RubyGems account and configured release
environment still belong to the intended maintainers. Never publish merely to run checks.
- [ ] Verify the published 1.0.0 gem and generated tag, install from RubyGems in a clean project,
and rerun passing/failing architecture examples before announcing availability.

CLI, richer semantic method/protocol rules, presets, and gradual-adoption baselines remain in #66.
They are not prerequisites for the initial stable API baseline.

## Audit coverage added

Expand All @@ -38,8 +57,8 @@ an actively changing or hostile filesystem. Dense graphs can have exponentially

## Next useful improvements

- Establish repeated real-world performance baselines on pinned Ruby repositories before setting
tighter thresholds. Report cold analysis, warm cache reuse, graph contents, and memory separately.
- Add an opt-in, non-blocking real-world canary once the repository set and update policy are agreed.
- The pinned real-world canary is implemented with manually triggered/relevant-PR checks, reviewed
graph fingerprints, and cold/warm/memory evidence. Review its stability and cost before scheduling
it or tightening thresholds; the small lib-only corpus is not a full Rails benchmark.
- Dependency vulnerability scanning is available as a separate task/workflow. Consider mutation
testing as another measured addition; high line coverage is not proof of semantic correctness.
4 changes: 4 additions & 0 deletions .github/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ and makes that RubyGems account an owner.

## Publishing a version

Preparation and publication are separate actions. A version commit, successful CI run, or strict
metadata check does not publish a gem. Do not dispatch `Release` for a dry run: its last step uploads
to RubyGems and creates the version tag. Keep publication behind explicit maintainer authorization.

1. Update `ArchUnit::VERSION` in `lib/archunit/version.rb` and add the release to `CHANGELOG.md`.
2. Refresh the local gem's `Gemfile.lock` entry, date the changelog heading as
`## <version> - YYYY-MM-DD`, and update the README installation example to `~> <version>`.
Expand Down
14 changes: 14 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ which entry point to choose and how the stages fit together.
All rule builders are immutable and lazy. Constructing a rule does not read the project; `check`,
`measure`, `snapshot`, and export methods are the terminals that perform work.

## 1.x compatibility contract

This guide defines the supported 1.0 public surface: documented entry points, fluent methods,
options, public data/error types, and report formats. Additive capabilities can arrive in minor
versions; incompatible public API changes require a major version and migration notes. Private
helpers and classes marked as implementation details are not part of that compatibility promise.
Correctness fixes can change detected violations; compatibility is not a promise to preserve missed
dependencies or misleading clean results.

Static extraction remains bounded and does not execute the target application's source or gemspecs.
Import-only is the default; expanded constant analysis is explicit opt-in. The documented unresolved
lookup cases, project source/exclusion policy, strict parser failures, and explicit cache-clearing
behavior remain important when upgrading. See the README's migration notes for changes from 0.0.1.

## Common rule shape

~~~ruby
Expand Down
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Changelog

## 0.0.2 (unreleased)
## 1.0.0 - 2026-10-26

First stable API baseline. The previously unreleased 0.0.2 development work is included here;
0.0.1 remains the preceding published version. See the README's migration notes before upgrading.

- Fail closed on malformed included Ruby in dependency graphs and AST metrics, with structured
source diagnostics and profile counters instead of silently treating incomplete analysis as clean.
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
archunit (0.0.2)
archunit (1.0.0)
csv (>= 3.3, < 4.0)
json (>= 2.7, < 3.0)
prism (>= 1.0, < 2.0)
Expand Down Expand Up @@ -112,7 +112,7 @@ DEPENDENCIES
yard (~> 0.9.45)

CHECKSUMS
archunit (0.0.2)
archunit (1.0.0)
ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
bundler-audit (0.9.3) sha256=81c8766c71e47d0d28a0f98c7eed028539f21a6ea3cd8f685eb6f42333c9b4e9
csv (3.3.6) sha256=aba61e7e507a66f03d45cb1f3c4b6359861c3504038b422962875dce099e4456
Expand Down
42 changes: 34 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ ArchUnit.project_files
.in_folder('app/database/**')
~~~

It is a working executable prototype with file, layer, slice, graph-reporting, and metric APIs. It
is tested on Ruby 3.3, 3.4, and 4.0 on Linux and Ruby 4.0 on Windows. Install the latest release as
[`archunit`](https://rubygems.org/gems/archunit) on RubyGems.
ArchUnitRuby provides file, layer, slice, graph-reporting, and metric APIs with a documented 1.0
compatibility baseline. It is tested on Ruby 3.3, 3.4, and 4.0 on Linux and Ruby 4.0 on Windows.
The gem is named [`archunit`](https://rubygems.org/gems/archunit); check RubyGems for published-version
availability, since a development checkout can be ahead of the published gem.

ArchUnitRuby follows the shared ArchUnitEverything architecture and fluent-API standard used by
its siblings [ArchUnitTS](https://github.com/LukasNiessen/ArchUnitTS) and
Expand All @@ -47,12 +48,13 @@ from `main`, so the published reference follows the repository.

### Installation

ArchUnitRuby requires Ruby 3.3 or newer. Add it to your test dependencies:
ArchUnitRuby requires Ruby 3.3 or newer. These instructions target the 1.0 series. Add it to your
test dependencies once the target version is published:

~~~ ruby
# Gemfile
group :test do
gem 'archunit', '~> 0.0.1'
gem 'archunit', '~> 1.0.0'
end
~~~

Expand All @@ -62,7 +64,7 @@ Then install it:
bundle install
~~~

Or install it directly with `gem install archunit`.
Or install it directly with `gem install archunit --version '~> 1.0.0'`.

[ClickGems download analytics](https://clickgems.clickhouse.com/dashboard/archunit) show trends by
date, gem version, Ruby version, system, and country. Download totals count package fetches rather
Expand Down Expand Up @@ -530,7 +532,7 @@ than silently returning a partial graph or zero counts. Its immutable `diagnosti
`malformed_files`. Fix or explicitly exclude invalid files using the project source policy.
Fluent rule selectors do not limit graph discovery. Failed graph builds are not cached; after
editing previously cached valid source, the normal explicit `clear_cache: true` policy still applies.
This intentionally changes the prototype's permissive behavior before the stable release.
This intentionally changes the 0.0.1 prototype's permissive behavior in the 1.0 API.

Expanded analysis uses a bounded Prism index and adds no runtime dependency. The design spike
considered [RubyDEX](https://github.com/Shopify/rubydex), whose semantic index is broader but adds a
Expand Down Expand Up @@ -608,6 +610,29 @@ those projects or installs their dependencies, and is not scheduled automaticall

The implementation conventions and intended dependency directions live in [`AGENTS.md`](AGENTS.md).

## 1.0 compatibility and migration

The documented entry points, fluent rule methods, options, public data/error types, and report
formats in the [API guide](https://lukasniessen.github.io/ArchUnitRuby/file.API.html) form the 1.x
compatibility baseline. Additive capabilities may be introduced in minor versions; incompatible
public API changes require a new major version and migration notes. Private implementation helpers
are not part of that contract. Correctness fixes can reveal violations that earlier versions missed;
review the changelog when updating.

When upgrading from 0.0.1:

- The default remains import-only. Explicitly opt into `dependency_analysis: :imports_and_constants`
when you want the documented static constant-reference model; it may reveal additional violations.
- Included malformed Ruby now raises `SourceParseError < TechnicalError`, rather than silently
passing or returning zero AST counts. Fix or explicitly exclude invalid source files.
- Project `.archignore` exclusions and skipped symlinked source entries can change the discovered
file set. Empty selections are still violations by default; check selectors rather than blindly
allowing empty tests.
- Cached graph results still require explicit clearing after source edits in a long-lived process.

Stable API compatibility does not mean complete Ruby interpretation or exhaustive runtime detection.
The supported static-analysis boundaries below remain part of the contract.

## 📅 Plans and Current Limitations

- Files are the primary vocabulary; opt-in constant analysis has the lookup limits described above.
Expand All @@ -616,7 +641,8 @@ The implementation conventions and intended dependency directions live in [`AGEN
- `.archignore` supports exclusion globs, not negated gitignore patterns or nested ignore files.
- Cycle traversal is iterative and tested on 10,000-node chains and rings. Enumerating every cycle
can still be expensive in densely connected graphs; narrow the selected scope when necessary.
- The API is still pre-release and may change before the first stable gem version.
- Method-call/protocol rules, a standalone CLI, presets, and adoption baselines are roadmap work,
not claims made by the current 1.0 API.

## 💟 Community

Expand Down
2 changes: 1 addition & 1 deletion lib/archunit/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module ArchUnit
VERSION = '0.0.2'
VERSION = '1.0.0'
end
Loading