Govern cycle exceptions
Not every dependency cycle is a defect. Some are deliberate architecture; others are debt you have chosen to carry for now. AtlasArc records both as precise, reviewable governance without changing application source or build files.
The Governance hub keeps three different repository concerns explicit: .atlasarc/governance/scope.json defines which evidence is evaluated, .atlasarc/governance/cycles.json records reviewed cycle decisions inside that evidence, and .atlasarc/views.json shares optional investigation starting postures. They are separate because only the first two affect CI.
Cycle governance is Free end to end
Free includes the complete author-commit-enforce path: inspect, create, edit, reclassify, validate, reload, and remove basic repository scope and cycle decisions; commit the public documents; then enforce them with AtlasArc.io CI. The full workspace accelerates that same model with advanced registry review and search, drift triage, guided repair and reconciliation, bulk Debt onboarding and cleanup, structural audit views, and Shared Views. Follow the whole free route, or use the sections below for the workflow itself without an access label repeated on every control.
Choose the right kind of cycle control
- Safe Haven: remembered, workspace-scoped decluttering with broad package or source-folder reach. Use it when cycles through a familiar area obscure the rest of your cycle view. It does not record a fine-grained architectural decision, and the CI evaluator does not read it.
- Shared investigation view: committed collaboration state in
.atlasarc/views.json. Use it to help a teammate reopen the same Root or Pin, lens, filters, and presentation. It never changes CI scope. - Repository scope rule: a durable evidence-boundary decision in
.atlasarc/governance/scope.json. Use it for generated, vendored, or deliberately fenced architecture units that the IDE, reports, and CI must all leave outside analysis. - Governance record: precise Intentional or Debt treatment in
.atlasarc/governance/cycles.json, with a required reason and optional ticket. Use its finer evidence scope, searchable register, evaluation status, and repair lifecycle locally; commit the file when other developers and CI should use the same decision.
A Safe Haven answers “keep cycles through this broad area out of my way.” A cycle record answers “treat this specific evidence as Intentional or Debt, and remember why.” A shared view answers “reopen this investigation.” Repository scope answers “not in the evidence our repository governs.” Committing a cycle record adds collaboration, version history, and CI enforcement; it is not what makes the record useful.
Define repository analysis scope first
Repository scope is applied before metrics, cycle detection, cycle-decision matching, whole-model reports, the configured evaluator used by JUnit or the standalone CLI, or the ArchUnit adapter. When a semantic rule matches a package or TypeScript source folder, AtlasArc removes that unit and every dependency entering or leaving it. Scope is therefore policy, not a visual filter and not an accepted finding. In the Exclusions sidebar, View only keeps ordinary hiding visual; Analysis scope shows this policy and routes changes through the Governance hub.
{
"$schema": "https://atlasarc.io/schemas/repository-scope-v1.schema.json",
"schemaVersion": 1,
"exclusions": {
"generated-adapters": {
"selector": {
"kind": "jvm-package-pattern",
"module": "billing",
"pattern": "com.acme.billing.generated.**"
},
"reason": "Generated from the reviewed billing API contract."
}
}
}
Patterns use literal segments, * for one segment, and ** for zero or more. JVM rules distinguish an exact module, every owner (*), and legitimately module-less evidence, so equal package names in sibling modules never merge. TypeScript rules use normalized repository-relative source-folder paths.
Open Cycle Governance to add or remove rules and inspect their measured impact. AtlasArc shows matched and stale rules, retained and excluded unit/reference totals, and the scope revision. A missing file means the full acquired architecture is in scope. Invalid, unreadable, or Git-ignored policy fails closed: AtlasArc stops before a new acquisition, marks any retained prior view with a red Policy lamp, and blocks governance writes plus whole-model reports until the file is repaired. The exact contract is repository-scope-v1.schema.json.
Share an investigation, not a build policy
After arranging a useful Root or Pin, lens, filters, hierarchy compaction, heatmap or lens presentation, and exact local package exclusions, open Cycle Governance → Shared investigation views and choose Save current view. A Root or Pin can name a JVM module, JVM package, or TypeScript source folder. The committed preset gives teammates a named starting point for the same architectural question.
Applying a preset replaces your current setup with an ordinary editable copy. That's it: you are not entering a special mode. A Shared View never selects or reruns Analysis Source, so analyze the source you want first and then apply the preset to that open model. AtlasArc resolves every required Root or Pin target before changing anything. If a module, package, or source folder was renamed or removed, Apply explains which target is unavailable and leaves your current view alone. Change controls, use Reset View, apply another preset, or reapply the same one whenever you want its saved posture back. None of those local changes rewrites views.json. Update from current is the explicit revision-guarded repository change.
Semantic view exclusions resolve against the current model when you apply the preset and then behave like ordinary exact view-only exclusions. Reapply the preset to resolve them again after the model changes. Derived cycle-group numbers, machine-local paths, canvas pan/zoom, ambiguous free-form exclusions, and machine-local or Custom Hotspots axes are not durable preset identity. A Shared View can preserve a built-in Hotspots Map preset, a Galaxy continuation with its depth direction and Routes setting, or a named Galaxy preset. Camera position and point selection remain local. If the recorded Hotspots state is unavailable for the current analysis, AtlasArc explains the mismatch and leaves the current view alone instead of substituting another metric. The JUnit adapter, standalone evaluator, and ArchUnit adapter never read views.json. Whole-model reports ignore view-only hiding; a Current Investigation report reproduces the effective local posture without claiming a preset is still active. The exact document contract is repository-views-v1.schema.json.
Record and review a decision
- Analyze the current Java, Kotlin, or TypeScript source and select a problem-cycle edge or one of its concrete references.
- Choose Record cycle decision….
- Select the scope and, where applicable, owner side. Check the plain-English summary, classify the decision as Intentional or Debt, add the required reason, and optionally add a ticket.
- Choose Record acceptance. AtlasArc writes directly and refuses to overwrite a concurrent edit.
- Re-analyze or reload governance and review the resulting status. Commit the file when the decision should be versioned, shared, or enforced in CI.
Owner side records where responsibility sits for a broader scope: source covers dependencies leaving the selected code; target covers dependencies entering it. An individual dependency already identifies both sides, so AtlasArc hides the owner control for that scope.
Choose Intentional or Debt
Both classifications accept reviewed dependency evidence, so that evidence no longer keeps a fully governed cycle in the problem graph or fails the matching CI rule. The classification records what the decision means; it does not erase the structural dependency.
| Classification | Choose it when | What AtlasArc preserves |
|---|---|---|
| Intentional | The dependency is a deliberate architectural relationship you do not plan to remove. | It renders in muted green and remains inspectable as accepted structure. |
| Debt | You tolerate the dependency for now but believe it should change. Record the reason and add a ticket when one exists. | It renders in muted amber and remains visible in debt counts, lists, reports, and governance review. |
When the answer changes, use the governance review to reclassify the existing record. AtlasArc changes the kind in place and preserves the stable record ID; deleting and recreating the decision is unnecessary. If active records overlap, Debt wins, so a broader or later Intentional record cannot hide known debt.
Use only evidence the backend can prove
| Analysis backend | Supported v1 governance evidence |
|---|---|
| Java bytecode | Package, type, member, and individual-dependency evidence when stable identities are present. |
| Kotlin bytecode | Package architecture units plus type, function, property, constructor, member, and individual-dependency evidence when present. |
| TypeScript artifact | Source-folder, source-file, individual import, and dependency-kind evidence such as runtime, type-only, dynamic import, or re-export. |
TypeScript v1 does not pretend that dependency-cruiser artifacts provide stable class or function identities. Kotlin package governance does not require a source declaration site: the package is an AtlasArc architecture unit.
For JVM whole-project analysis, module labels keep governance decisions scoped to the intended module. A package decision for acceptance.shared.left in orders does not govern the package with the same name in billing. A selector that could refer to both is ambiguous and suppresses nothing.
Structural truth stays visible
Governance changes which dependencies remain cycle problems; it does not rewrite the structural graph. A governed dependency remains available for inspection and reporting even when it no longer keeps a cycle warning red.
Coverage is conservative at reference level: every concrete reference behind an architecture edge must be governed or otherwise suppressed before that edge leaves problem-cycle detection. One uncovered reference keeps the edge eligible for a red cycle. In short: red wins.
If removing one fully governed edge breaks a cycle, the red warning disappears even though the structural dependency still exists. This keeps warnings actionable without pretending the code relationship vanished.
Repair stale records explicitly
Every record is checked against current evidence. Only an active record covers dependencies. AtlasArc reports resolved, missing-source, missing-target, partial, ambiguous, unsupported, and invalid records without silently retargeting or deleting them.
- Resolved: the governed dependency no longer exists; review and remove the record when that is intentional.
- Missing source/target: an identity moved or disappeared; inspect candidates before retargeting.
- Partial: only some recorded reference evidence still matches; uncovered evidence remains a problem.
- Ambiguous: a JVM selector could refer to packages in more than one module. The record suppresses nothing until you choose the intended source and target modules.
- Unsupported or invalid: the backend cannot prove the requested scope, or the record does not satisfy the schema. It suppresses nothing until corrected.
Review and maintain the repository document
Open Cycle Governance from the shared toolbar in any lens. The dialog starts with every record collapsed. Search by dependency identity, module, rationale, ticket, dependency kind, status, or diagnostic. Its count pills filter all records, Intentional, Debt, stale or invalid, and not evaluated; changing a filter closes the expanded item so the result is easy to rescan.
Expand one record to see its decision rationale, current evaluation, and a compact read-only topology diagram of the matched dependency evidence. Expanding another closes the first. From that item you can:
- mark an active record as Debt or Intentional without deleting and recreating it;
- retarget a missing source or target from candidates found in current evidence;
- resolve an ambiguous JVM selector by choosing the intended source and target modules from the dependency evidence AtlasArc found;
- remove the record, reload an externally changed document, or open the JSON file.
AtlasArc offers only module pairs supported by current dependency evidence. Reclassification and evidence-backed retargeting apply directly. Removal uses an inline destructive confirmation. If the file changed since the dialog loaded, AtlasArc refuses the stale write.
Establish the existing cycle-debt baseline
For a brownfield repository, the governance hub can turn the current backlog into the starting line for CI. After you analyze a current, stable Analysis Source with exact dependency evidence, the panel above the register shows the ungoverned problem cycles in that graph, the narrow cycle-breaking edge set selected by AtlasArc, and the exact Debt records required on those edges. The source can be a selected JVM module, the whole JVM project, or a configured TypeScript source. It does not accept every edge in an SCC. You can keep the standard reason, replace it, and optionally apply one ticket before choosing Add N debt records.
The action adds one individual-dependency Debt decision per current reference on the selected cycle-breaking edges and preserves every existing record, including records outside this Analysis Source. It does not broadly accept a package, mark generated decisions Intentional, hide structural dependencies, or display a file-diff ceremony. AtlasArc refuses to offer the write for an auto-discovered TypeScript source that has not been configured, stale or incomplete evidence, missing module attribution, invalid governance, an ignored or read-only file, or another named safety failure. Opening the dialog alone never changes the repository.
Review and commit the resulting cycles.json, then enable the ordinary read-only CI evaluation. The same workflow is available without IntelliJ through the explicit atlasarc-ci baseline command.
File ownership and merge behavior
The schema is versioned at https://atlasarc.io/schemas/cycle-governance-v1.schema.json. Records are keyed objects rather than one large array, so independent branch additions stay local in review. AtlasArc writes deterministic UTF-8/LF JSON with sorted record and reference IDs.
Keep generated dependency evidence separate from policy and decisions under .atlasarc/. The governance file must remain Git-trackable even if you keep a decision uncommitted while working. AtlasArc owns valid writes; manual editing is possible but is not the intended workflow. Invalid scope fails authoritative analysis closed; invalid shared views have no effect and can never weaken CI.
Enforce the same decisions in CI
AtlasArc.io CI is the Apache-2.0 enforcement side of this workflow. It needs no IntelliJ runtime or paid plugin license. The configured evaluator reads current Java/Kotlin bytecode or TypeScript dependency-cruiser artifacts. Run it in-process through the JUnit adapter for ordinary tests or as the standalone CLI for process exits and machine output. Existing JVM ArchUnit suites can apply the same governance as a native rule over their imported classes.
All three integrations read committed repository scope and cycle decisions and use the same public engine as the IDE. Shared views and local Safe Havens are never consumed by CI. If scope or evidence is invalid, module ownership is ambiguous, or a cycle record is invalid, evaluation fails closed rather than reporting a false clean result.
See the AtlasArc.io CI guide for the integration chooser, Maven distribution, public source, evaluator configuration, output formats, and exit codes. To place the complete configured verdict in the test lifecycle, start with the JUnit recipe. Teams that already use ArchUnit can follow the ArchUnit recipe.
Where to go next
Start cycle triage with Find cyclic dependencies, see the public product summary under Govern intentional exceptions, or review Handling large projects for ways to reduce a crowded model before recording decisions.