Changelog
All notable changes are documented here. Format: Keep a Changelog. Versioning: Semantic Versioning.
[0.1.0b2] — 2026-05-13
Breaking release on the road to 1.0. The rule set is cut down to four,
the TOML schema to nine keys, and the DSL now mirrors the TOML keys 1:1.
Added
- Full DSL parity —
tree_structure,dependencies, andno_circular_importsare available as fluent methods onServiceRuleSet. - TOML-free entry points —
PyArchRules.from_services({...})andPyArchRules.from_spec(spec)build an instance without a[tool.pyarchrules]table. service_isolation— project-levelisolate_services = trueplus per-serviceshared = trueenforces cross-service import boundaries (TOML-only).tree_ignore— glob patterns of directory basenames to skip instrict/exactmode. Available in TOML and DSL.- JSON output —
pyarchrules check --format jsonwrites a stable{summary, violations}document to stdout. - New
checkflags —--config,--service,--rule(repeatable),--warnings-as-errors/-W. - New command —
pyarchrules show-configdumps the resolved config as JSON. fileandlineonRuleViolation;internal_dependenciesviolations now include line numbers.__version__exposed on thepyarchrulespackage.- Exception hierarchy —
PyArchError→ConfigError,ValidationError,ServiceNotFoundError. - Faster scans — AST results cached per file; internal walks use
os.scandirand prune common noise dirs (.venv,.tox,node_modules,build,dist,.mypy_cache, …).
Changed (breaking)
- Only 4 rules ship:
tree_structure,dependencies,no_circular_imports,service_isolation. - TOML schema is 9 keys:
isolate_services,path,shared,tree,tree_mode,tree_allow_files,tree_ignore,dependencies,no_circular_imports. - Exit codes are contractual:
0ok,1violations,2config error. The--strict/--no-stricttoggle is gone; use-Wto upgrade warnings. - Invalid
dependenciesstrings raiseConfigErrorat load time. Overlapping rule pairs are now reported as warnings instead. - Duplicate entries in
treeraiseConfigError. - Removed project keys:
root,validate_paths. - Removed per-service keys:
allowed_service_dependencies,no_wildcard_imports,no_private_imports,allowed_external_libs,forbidden_external_libs. - Service shorthand removed:
services.x = "src/x"is no longer accepted — use the table form.
Removed
- DSL rules:
must_contain_folders,must_contain_files,files_must_match_pattern,no_files_in_folder,max_depth,no_wildcard_imports,no_private_imports,no_relative_imports_in,allowed_external_libs,forbidden_external_libs,layer_must_not_import,files_must_be_snake_case,classes_must_match_pattern,no_test_files_in. Most overlap with Ruff or pytest discovery — replace accordingly. - Linter rule:
allowed_service_dependencies— deferred to v1.x. - Heavy dependencies:
pydanticandloguru.
Fixed
DependenciesRulenow correctly resolves relative imports (from .domain import x).- Rules no longer print to a side channel via
loguruwhileConsoleViolationReporteralso prints — single output path now.
[0.1.0b1] — 2026-03-04
Beta — public API is stabilising, minor breaking changes may still occur.
Added
tree_mode— replacestree_strict/tree_recursivewith a single enum:"exists"(default),"strict","exact"tree_mode = "strict"— validates structure one-to-one at every level covered bytree, from root down to the deepest declared path; leaf directories are not inspected internallytree_mode = "exact"— same asstrictplus recursively checks inside every leaf directory; full one-to-one match of the entire treetree_allow_files— still supported alongsidetree_mode; loose files are always tolerated in strict/exact modes by default- Invalid
tree_modevalue raises a clearPyArchErrorwith the list of valid options - Documentation updated:
configuration.md,use-cases.md,getting-started.mdnow usetree_modethroughout
Changed
tree_strictandtree_recursiveboolean flags replaced bytree_mode(breaking change)init-projectno longer generates deprecatedproject_nameanddescriptionfieldsproject_nameanddescriptionremoved from known project keys — configs that still contain them will now raise an "unknown key" errorno_args_is_help = trueon the CLI app — invokingpyarchruleswith no arguments now shows the same output as--help
Fixed
tree_strictpreviously did not check the service root level, so undeclared siblings at the top level were silently ignored — now fixed in"strict"and"exact"modes
[0.1.0b0] — 2026-02-25
Beta — first public beta release.
Added
- New DSL rules:
allowed_external_libs,forbidden_external_libs,no_test_files_in,no_files_in_folder,max_depth,files_must_match_pattern,files_must_be_snake_case,classes_must_match_pattern,no_relative_imports_in,no_circular_imports,layer_must_not_import,no_private_imports,no_wildcard_imports ServiceIsolationRule— enforcesisolate_servicesat the project level; services markedshared = trueare exemptAllowedServiceDependenciesRule— validatesallowed_service_dependenciesper serviceLinterRegistryandBaseRegistryfor rule registration- MkDocs documentation site deployed to mspitb.github.io/pyarchrules
- GitHub Actions workflow for automatic docs deployment on push to
main - Unknown keys in
[tool.pyarchrules]and per-service config now raise a descriptivePyArchError
Changed
pyproject.tomldependencies relaxed from exact pins (==) to minimum bounds (>=) for better compatibility with user environments- Removed
zensicalfrom dev dependencies
Fixed
ConsoleViolationReporterlog format now includes a trailing newline to prevent messages from appearing on the same line
[0.0.1a2] — 2026-02-19
Added
pyarchrules check— validates architecture from the CLIpyarchrules init-project— initialisespyproject.tomlconfigpyarchrules add-service/remove-service/list-servicescommandsTreeRule— validates directory tree structureDependenciesRule— validates internal module import directionAllowedServiceDependenciesRule— validates cross-service importsMustContainFoldersRuleDSL rule withallow_extraparameterPyArchRulesPython API withfor_service()/validate()interfacePyArchConfigfor reading/writingpyproject.tomlviatomlkit- Pydantic-backed
ProjectSpecandServiceSpecmodels ConsoleViolationReporterfor human-readable outputRuleEvalResultwithis_valid,error_count,warning_count
Alpha — API may change before 1.0.
[0.0.1a1] — 2026-01-01
Initial private release.