Skip to main content

ovecc architecture diff

The reflexion report between the contract and the stored graph, in the Murphy/Notkin/Sullivan vocabulary: what you declared, what the code actually does, and every place the two disagree.

Usage: ovecc architecture diff [OPTIONS]

The contract file is re-read on every run and judged against the persisted graph, so editing architecture.toml never requires re-indexing. The same findings also land in violations and gate at each ovecc index.

Example

$ ovecc architecture diff
Architecture contract: 13 components, 25/25 declared dependencies implemented, mode new-violations

Files outside every component (1):
[Low] 1 file(s) belong to no component
npm/ovecc/bin/ovecc.js

Components that change together without depending on each other (2):
[Low] graph and parser change together without depending on each other
crates/ovecc-graph/src/dupes.rs (with crates/ovecc-parser/src/tokenize.rs in 5 commits (6bb034a0, ccf12c8e, cb0c6e87, 386878d0, 7a029512))
crates/ovecc-graph/src/cycles.rs (with crates/ovecc-parser/src/tokenize.rs in 4 commits (6bb034a0, cb0c6e87, 386878d0, 7a029512))

3 finding(s).

Convergences:
db -> core (41 import(s))
graph -> core (14 import(s))
parser -> core (12 import(s))
rules -> core (30 import(s))
rules -> graph (1 import(s))
...

A breach names the file and the import behind it:

Divergences (1):
[High] cli -> parser is not in the contract
crates/ovecc-cli/src/render.rs:12 (ovecc_parser::outline)

The verdicts

VerdictSeverityMeans
convergenceDeclared and implemented, with the import count
divergenceHighAn import the contract does not allow
forbidden dependencyHighAn import a cannot_depend_on names outright
restricted accessHighAn import of a component whose consumed_by does not admit it
required dependencyHighA file never makes a must_depend_on import
slice isolationHighAn import between sibling slices of a slices = true component
interface bypassHighAn import that skips a component's declared entry files
deprecated useMediumA dependency marked deprecated = true is still imported
external denyMediumAn external package the contract bans
capabilityMediumA denied ambient capability, with the exact API and line
complexity budgetMediumA function over the component's per-function ceiling
coverage floorMediumA component under its min_coverage
unassignedLow / HighFiles no component claims, per the unassigned policy
absenceLowA declared edge no import implements (contract hygiene)

restricted-access and forbidden-dependency replace the divergence the edge would otherwise have been — a sharper answer, not an extra one.

mode = "warn" caps everything at Low, so nothing gates.

Behavioral coupling

One verdict reads no code at all. Behavioral coupling names two components the contract declares independent, that no import connects, whose files the history keeps changing in the same commits. No static analysis can see it: the only witness is the commits, and they come with the finding.

Two components must share at least two coupled file pairs before it is reported — one is an accident, and the honest exception is real (a version field every implementer of a protocol must bump).

It is Low by default, under every gate's threshold, because the deviation is a question for the reader. In the contract:

coupling = "medium" # or "high" — put it in the gate
coupling = "off" # stop reporting it

See coupling for the underlying file-pair signal.

Options

OptionEffect
--format json|markdownStructured output for tooling or a PR comment

Plus the global options.