Architecture conformance
Declare which services may depend on which others, then continuously check the live system graph against those rules. Your team's architecture lint, plus automatic dependency-cycle detection.
Workspaces let you declare, in .repowise-workspace.yaml, which services
are allowed to depend on which others, then continuously check the live
system graph against those rules. This is
your team's architecture lint: the intended architecture, expressed
as code, verified on every update.
Declaring rules
Conformance rules live in a conformance: block in the workspace config
(no separate file). Each rule has a source matcher, a target
matcher, and an allow flag:
repos:
- path: web
alias: frontend
tags: [ui, edge]
- path: services/db
alias: db
tags: [data]
conformance:
rules:
# Deny rules (allow defaults to false): the dependency is a violation.
- source: frontend
target: db
description: The UI must call the API, never the database directly.
- source: "*"
target: legacy-payments
# Tag-based: nothing in the "ui" tier may depend on the "data" tier...
- source: "tag:ui"
target: "tag:data"
# ...except migrations, which are explicitly allowed (an exception).
- source: migrations
target: db
allow: trueA matcher resolves against service nodes in the system graph:
| Matcher form | Matches |
|---|---|
* | every service |
tag:<name> | every service whose repo declares that tag (see tags: on each repo) |
| anything else | a glob over the node id, repo alias, and display name (frontend, api::*, *-worker) |
A rule with allow: false (the default) is a deny rule: a
structural dependency from a matching source to a matching target is a
violation. A rule with allow: true is an exception that whitelists
an otherwise-denied edge. Only structural edges (HTTP, gRPC, event,
package, db) are evaluated; behavioral co-change is never treated as a
dependency.
Dependency cycles
Independently of any rules, conformance detects circular
dependencies among services over structural edges (A → B → … → A). A
cycle means the services cannot be built, deployed, or reasoned about
independently. Cycle detection runs even with zero rules declared, so
every workspace gets it for free.
Using it
CLI
repowise workspace check prints violations and cycles and exits
non-zero when any are found, so it gates CI:
repowise workspace check # human-readable report; exit 1 on findings
repowise workspace check --json # raw report JSON (still exits 1 on findings)It recomputes from the persisted system graph, so editing rules and re-running picks them up without a full re-index.
REST
GET /api/workspace/conformance returns the report from the most recent
update, filterable by repo.
MCP
get_conformance exposes violations
and cycles to an agent. The get_risk PR-mode
directive gains conformance_violations and dependency_cycles blocks
for the findings the diff's repo participates in.
Conformance view
The web UI's Conformance page renders a dependency-structure matrix (DSM): services on both axes, each filled cell a dependency tinted by transport, with rule violations ringed red and cycle cells amber. Governance panels list the violations and cycles. Violations also badge the offending edges on the Live System Map (toggle Conformance), reusing the same additive overlay as the breaking-change guard.
Because repowise workspace check exits non-zero on any finding, wiring
it into CI turns your declared architecture into a gate: a pull request
that introduces a forbidden dependency or a new cycle fails the build.
Breaking-change guard
Did a provider change in a way that actually breaks its consumers? On every workspace update, freshly-extracted contracts are diffed against the previous index and each incompatible change is reported with the exact consumer files it endangers.
Architecture metrics
The one evaluative read of the whole system, propagation cost, the cyclic core, per-service roles, and a deterministic 1-10 architecture score. Standard architecture-complexity metrics computed over the system graph, no LLM.