Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

a-check

English · Deutsch

CI

Cross-language hexagonal-architecture checker — deterministic, side-effect-free, text-heuristic, shipped as a container image.

What is a-check?

a-check enforces a repository's hexagonal layered architecture across languages, driven by a single config file. Seven universal rules, each one requirement in the requirements spec:

  • core-impurity — the core (domain, innermost layer) imports neither a port, an adapter, nor a framework/tech (AC-FA-RULE-001)
  • lateral-adapter — an adapter imports no other adapter (except the shared sink) (AC-FA-RULE-002)
  • tech-leak — a framework/tech appears only in its adapter (AC-FA-RULE-003)
  • port-impurity — a port imports no adapter and no framework/tech (it may reference the core's domain types) (AC-FA-RULE-004)
  • wrong-direction — layer edges are one-way (AC-FA-RULE-005)
  • app-impurity — the application layer imports no adapter and no framework/tech (it may use the domain and ports) (AC-FA-RULE-007)
  • port-direction-mismatch — an adapter talks only to ports of its direction (optional driving/driven dimension, orthogonal to the role) (AC-FA-RULE-008)

Imports are extracted text-heuristically per language (C++/Go/Rust/Kotlin/Java/Python/C#/TypeScript) (AC-FA-EXTRACT-001). Every finding names the file, line, rule and reason; exit codes: 0 clean, 1 findings, 2 usage/config error (AC-FA-CLI-001).

What can I do today?

Section rules: honest current state — what runs now, not what is planned. No success claim without a runnable proof (baseline rulebook modul-09-implementierung.md).

  • Check any repository's layering in eight languages (C++/Go/Rust/Kotlin/Java/Python/C#/ TypeScript) from a single .a-check.ymldocker run ... ghcr.io/pt9912/a-check against the pinned digest in version.md.
  • Wire it into a make target in one line: --print-mk emits the ready-made a-check.mk fragment; the committed file and the emitted one are byte-identical, and a gate proves it.
  • Run it hermetically: the scan needs no network (--network none), reads only, and never writes into the repository it checks.
  • See the graph instead of a list — --print-graph renders the layer edges.
  • Two real consumers run it today: b-cad (C++) and belief-agent (Kotlin/KMP).

What is not there yet is named where it belongs: open requirements live in spec/lastenheft.md, open observations in docs/plan/planning/observations.md.

Why a-check?

Four functionally overlapping arch-check.sh variants grew across the sibling repositories — C++ via #include heuristics (b-cad), Go via go list (d-check), Rust via use heuristics (grid-guide), Kotlin via Gradle module boundaries (d-migrate): four languages, four mechanisms, the same seven rules. a-check replaces them with one tool:

  • Configuration instead of fork: repo-specific layer/tech rules live declaratively in .a-check.yml (AC-FA-CONF-001), not in copied scripts.
  • One distribution path: a digest-pinned container image plus a shipped a-check.mk instead of N maintained copies (AC-FA-DIST-001).

It is the architecture counterpart to d-check (doc references): the same founding logic (replace a family of drifting scripts with one tool), one abstraction level higher.

Core idea

Architecture is an import graph with checkable invariants. Whether the core stays pure, an adapter imports laterally, or a layer edge runs against its direction is machine-decidable — a-check turns these invariants into a gate instead of a review opinion.

The rule is report, never repair: a-check is a pure read-only tool. The heuristic boundary (text-based, not a full parser per language) is disclosed, not hidden; an allowlist/marker exception is configurable (AC-QA-02).

What makes it trustworthy?

  • Determinism: identical input ⇒ byte-identical, stably sorted output (AC-QA-01).
  • Hermetic & network-less: never writes into the checked repo, runs with --network none on distroless/static (AC-QA-02).
  • No silent defaults: any invalid .a-check.yml aborts with exit 2 (strict decode, AC-FA-CONF-001).
  • Reproducible: the image and a-check.mk reference a @sha256: digest (AC-QA-03).
  • Dogfooding: a-check checks its own hexagonal architecture on every make arch-check — against the self-configuration, 0 findings.

Usage

Against the published image (digest-pinned, network-less, read-only):

docker run --rm --network none -v "$PWD:/src:ro" \
 ghcr.io/pt9912/a-check@sha256:34d3dfb50e44d99ea735186a35e1040589c4681dcfa2a51ed0f2aaea718cdd2d /src

Consumers wire a-check in as a make a-check gate — without a script copy: the shipped a-check.mk (produced by a-check --print-mk) is include-d, plus an .a-check.yml. A_CHECK_IMAGE is pinned to the release's @sha256: digest (AC-FA-DIST-001, AC-QA-03); raising the pin is a deliberate commit. The release process is described in docs/user/releasing.md.

Locally (dogfooding, no pull):

make build # build the static/distroless image
make arch-check # a-check checks itself (network-less, read-only)

Configuration (.a-check.yml)

In the repo root; strictly decoded (unknown key ⇒ exit 2):

version: 1
languages:
 go: ["**/*.go"]
layers:
 core: ["internal/core/**"]
 ports: ["internal/ports/**"]
 adapters: ["internal/adapters/**"]
edges:
 - {from: adapters, to: ports}
 - {from: ports, to: core} # ports may reference domain types
 # - {from: adapters, to: core} # if adapters reference domain types directly
tech:
 - {pattern: "net/http", adapter: adapters/http} # substring (default)
 # - {pattern: "Q[A-Za-z]", adapter: adapters/ui, match: regex} # RE2 regex (e.g. Qt)

The full schema is in the specification §SPEC-CONF-001; a living example is this repo's self-configuration. a-check --print-config prints a commented skeleton.

Getting started

Document Content
docs/user/benutzerhandbuch.md User manual (German) — installation, usage, .a-check.yml, troubleshooting
docs/user/releasing.md Release process — tagging, GHCR, digest pin
spec/lastenheft.md Requirements (AC-FA-*, AC-QA-*), acceptance criteria
spec/spezifikation.md Algorithms, .a-check.yml schema, exit codes (SPEC-*)
spec/architecture.md Hexagon components and roles (ARC-*)
docs/plan/adr/README.md Architecture decisions (ADR index)
harness/README.md Harness entry: source precedence, guides, sensors
AGENTS.md Briefing for AI coding agents, hard rules
CHANGELOG.md Change history

The specification, requirements and user manual are maintained in German. The AC-*/SPEC-*/ARC-* anchors above therefore point to German headings.

Development

The host needs only git, GNU make, bash and Docker (AGENTS.md §3.1).

make help # available targets
make gates # all inner gates (lint/test/coverage-gate/arch-check/doc-check/gate-consistency/guard-selftest)
make ci # gates + image-test (CI-equivalent); make trace-check checks commit IDs

License

This project is licensed under the MIT License.

About

Cross-language hexagonal-architecture checker — deterministic, read-only, text-heuristic; shipped as a digest-pinned container image.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /