Repository: sverweij/dependency-cruiser
Pull request #888 (2023-12-16 16:46:30)

feat!: makes entries in 'cycle' contain more information (BREAKING for API users)
## Description

- makes getCycle to emit richer content - both a _name_ and _dependencyTypes_ for now, instead of a string.

This is a breaking change on the API _only_ - rules keep the same interface and behavior.

## Motivation and Context

So we can define rules on the additional attributes - prerequisite to fixing #695 

## How Has This Been Tested?

- [x] green ci
- [x] additional automated non-regression tests

## Types of changes

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Documentation only change
- [ ] Refactor (non-breaking change which fixes an issue without changing functionality)
- [x] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would cause existing functionality to change) - on the API only. 

## Checklist

- [x] :book:

  - My change doesn't require a documentation update, or ...
  - it _does_ and I have updated it

- [x] :balance_scale:
  - The contribution will be subject to [The MIT license](https://github.com/sverweij/dependency-cruiser/blob/main/LICENSE), and I'm OK with that.
  - The contribution is my own original work.
  - I am ok with the stuff in [**CONTRIBUTING.md**](https://github.com/sverweij/dependency-cruiser/blob/main/.github/CONTRIBUTING.md).


codeclimate[bot]: Code Climate has analyzed commit 33eca07f and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit 94cd75d4 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit 91303ae9 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit a82fc196 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit fc71fbed and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit 8eef5fba and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit fb5bc040 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit 1e265cee and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit d830e020 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit ae1256a4 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit fadd6ac5 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).

codeclimate[bot]: Code Climate has analyzed commit 8dece3a0 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/sverweij/dependency-cruiser/pull/888).


Patch:
diff --git a/.c8rc.json b/.c8rc.json
index bb36883d..56d01de0 100644
--- a/.c8rc.json
+++ b/.c8rc.json
@@ -1,7 +1,7 @@
 {
   "checkCoverage": true,
   "statements": 99.89,
-  "branches": 98.75,
+  "branches": 98.77,
   "functions": 100,
   "lines": 99.89,
   "exclude": [
diff --git a/Makefile b/Makefile
index 4bc17a68..5b512289 100644
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,7 @@ SCHEMA_SOURCES=tools/schema/baseline-violations.schema.mjs \
 	tools/schema/compound-reaches-type.mjs \
 	tools/schema/configuration.schema.mjs \
 	tools/schema/cruise-result.schema.mjs \
+	tools/schema/mini-dependency-type.mjs \
 	tools/schema/dependencies.mjs \
 	tools/schema/dependency-type.mjs \
 	tools/schema/folders.mjs \
diff --git a/src/cache/cache.mjs b/src/cache/cache.mjs
index eb9c5630..49638697 100644
--- a/src/cache/cache.mjs
+++ b/src/cache/cache.mjs
@@ -30,7 +30,7 @@ const EMPTY_CACHE = {
 
 export default class Cache {
   /**
-   * @param {import("../../types/cache-options.js").cacheStrategyType=} pCacheStrategy
+   * @param {import("../../types/cache-options.mjs").cacheStrategyType=} pCacheStrategy
    * @param {boolean=} pCompress
    */
   constructor(pCacheStrategy, pCompress) {
@@ -43,9 +43,9 @@ export default class Cache {
   }
 
   /**
-   * @param {import("../../types/strict-options.js").IStrictCruiseOptions} pCruiseOptions
-   * @param {import("../../types/dependency-cruiser.js").ICruiseResult} pCachedCruiseResult
-   * @param {import("../../types/dependency-cruiser.js").IRevisionData=} pRevisionData
+   * @param {import("../../types/strict-options.mjs").IStrictCruiseOptions} pCruiseOptions
+   * @param {import("../../types/dependency-cruiser.mjs").ICruiseResult} pCachedCruiseResult
+   * @param {import("../../types/dependency-cruiser.mjs").IRevisionData=} pRevisionData
    * @returns {Promise<boolean>}
    */
   async canServeFromCache(pCruiseOptions, pCachedCruiseResult, pRevisionData) {
@@ -68,8 +68,6 @@ export default class Cache {
         this.revisionData,
       ) &&
       optionsAreCompatible(
-        // @ts-expect-error ts(2345) - it's indeed not strict cruise options,
-        // but it will do for now (_it works_)
         pCachedCruiseResult.summary.optionsUsed,
         pCruiseOptions,
       )
@@ -78,7 +76,7 @@ export default class Cache {
 
   /**
    * @param {string} pCacheFolder
-   * @returns {Promise<import("../../types/dependency-cruiser.js").ICruiseResult>}
+   * @returns {Promise<import("../../types/dependency-cruiser.mjs").ICruiseResult>}
    */
   async read(pCacheFolder) {
     try {
@@ -133,8 +131,8 @@ export default class Cache {
 
   /**
    * @param {string} pCacheFolder
-   * @param {import("../../types/dependency-cruiser.js").ICruiseResult} pCruiseResult
-   * @param {import("../../types/dependency-cruiser.js").IRevisionData=} pRevisionData
+   * @param {import("../../types/dependency-cruiser.mjs").ICruiseResult} pCruiseResult
+   * @param {import("../../types/dependency-cruiser.mjs").IRevisionData=} pRevisionData
    */
   async write(pCacheFolder, pCruiseResult, pRevisionData) {
     const lRevisionData = pRevisionData ?? this.revisionData;
diff --git a/src/enrich/summarize/is-same-violation.mjs b/src/enrich/summarize/is-same-violation.mjs
index 05927afe..7bc32dd0 100644
--- a/src/enrich/summarize/is-same-violation.mjs
+++ b/src/enrich/summarize/is-same-violation.mjs
@@ -1,3 +1,7 @@
+function pluckName({ name }) {
+  return name;
+}
+
 export default function isSameViolation(pLeftViolation, pRightViolation) {
   let lReturnValue = false;
 
@@ -5,9 +9,11 @@ export default function isSameViolation(pLeftViolation, pRightViolation) {
     if (pRightViolation.cycle && pLeftViolation.cycle) {
       lReturnValue =
         pLeftViolation.cycle.length === pRightViolation.cycle.length &&
-        pLeftViolation.cycle.every((pModule) =>
-          pRightViolation.cycle.includes(pModule)
-        );
+        pLeftViolation.cycle
+          .map(pluckName)
+          .every((pModule) =>
+            pRightViolation.cycle.map(pluckName).includes(pModule),
+          );
     } else {
       lReturnValue =
         pLeftViolation.from === pRightViolation.from &&
diff --git a/src/graph-utl/indexed-module-graph.mjs b/src/graph-utl/indexed-module-graph.mjs
index 3e515c25..ff19c359 100644
--- a/src/graph-utl/indexed-module-graph.mjs
+++ b/src/graph-utl/indexed-module-graph.mjs
@@ -6,12 +6,13 @@
  * @typedef {import("../../types/cruise-result.d.mts").IFolder} IFolder
  * @typedef {import("../../types/cruise-result.d.mts").IModule} IModule
  * @typedef {import("../../types/shared-types.d.mts").DependencyType} DependencyType
+ * @typedef {import("../../types/shared-types.d.mjs").IMiniDependency} IMiniDependency
  *
  * @typedef {(IDependency|IFolderDependency) & {name:string; dependencyTypes?: DependencyType[]}} IEdge
  * @typedef {IModule|IFolder} IModuleOrFolder
  * @typedef {IModuleOrFolder & {dependencies: IEdge[]}} IVertex
- * @typedef {{name:string; dependencyTypes: string[];}} IGeldedDependency
  */
+
 export default class IndexedModuleGraph {
   /**
    * @param {IModuleOrFolder} pModule
@@ -55,7 +56,6 @@ export default class IndexedModuleGraph {
   }
 
   /**
-   *
    * @param {string} pName - the name of the module to find transitive dependents of.
    * @param {number} pMaxDepth - the maximum depth to search for dependents.
    *                  Defaults to 0 (no maximum). To only get direct dependents.
@@ -98,7 +98,6 @@ export default class IndexedModuleGraph {
   }
 
   /**
-   *
    * @param {string} pName - the name of the module to find transitive dependencies of.
    * @param {number} pMaxDepth - the maximum depth to search for dependencies
    *                  Defaults to 0 (no maximum). To only get direct dependencies.
@@ -172,47 +171,70 @@ export default class IndexedModuleGraph {
     return lReturnValue;
   }
 
+  /**
+   *
+   * @param {IEdge} pEdge
+   * @returns {IMiniDependency}
+   */
+  #geldEdge(pEdge) {
+    let lReturnValue = {};
+    lReturnValue.name = pEdge.name;
+    lReturnValue.dependencyTypes = pEdge.dependencyTypes
+      ? pEdge.dependencyTypes
+      : [];
+    return lReturnValue;
+  }
+
   /**
    * Returns the first non-zero length path from pInitialSource to pInitialSource
    * Returns the empty array if there is no such path
    *
    * @param {string} pInitialSource The 'source' attribute of the node to be tested
    *                                (source uniquely identifying a node)
-   * @param {string} pCurrentSource The 'source' attribute of the 'to' node to
-   *                                be traversed
+   * @param {IEdge} pCurrentDependency
+   *                                The 'to' node to be traversed as a dependency
+   *                                object of the previous 'from' traversed
    * @param {Set<string>=} pVisited  Technical parameter - best to leave out of direct calls
-   * @return {string[]}             see description above
+   * @return {Array<IMiniDependency>}             see description above
    */
-  #getCycle(pInitialSource, pCurrentSource, pVisited) {
+  #getCycleNew(pInitialSource, pCurrentDependency, pVisited) {
     let lVisited = pVisited || new Set();
-    const lCurrentVertex = this.findVertexByName(pCurrentSource);
-    const lDependencies = lCurrentVertex.dependencies.filter(
+    const lCurrentVertex = this.findVertexByName(pCurrentDependency.name);
+    const lEdges = lCurrentVertex.dependencies.filter(
       (pDependency) => !lVisited.has(pDependency.name),
     );
-    const lInitialAsDependency = lDependencies.find(
+    const lInitialAsDependency = lEdges.find(
       (pDependency) => pDependency.name === pInitialSource,
     );
     if (lInitialAsDependency) {
-      return pInitialSource === pCurrentSource
-        ? [lInitialAsDependency.name]
-        : [pCurrentSource, lInitialAsDependency.name];
+      return pInitialSource === pCurrentDependency.name
+        ? [this.#geldEdge(lInitialAsDependency)]
+        : [
+            this.#geldEdge(pCurrentDependency),
+            this.#geldEdge(lInitialAsDependency),
+          ];
     }
-    return lDependencies.reduce(
+    return lEdges.reduce(
       /**
-       * @param {Array<string>} pAll
+       * @param {Array<IMiniDependency>} pAll
        * @param {IEdge} pDependency
-       * @returns {Array<string>}
+       * @returns {Array<IMiniDependency>}
        */
       (pAll, pDependency) => {
-        if (!pAll.includes(pCurrentSource)) {
-          const lCycle = this.#getCycle(
+        if (!pAll.some((pSome) => pSome.name === pCurrentDependency.name)) {
+          const lCycle = this.#getCycleNew(
             pInitialSource,
-            pDependency.name,
+            pDependency,
             lVisited.add(pDependency.name),
           );
 
-          if (lCycle.length > 0 && !lCycle.includes(pCurrentSource)) {
-            return pAll.concat(pCurrentSource).concat(lCycle);
+          if (
+            lCycle.length > 0 &&
+            !lCycle.some((pSome) => pSome.name === pCurrentDependency.name)
+          ) {
+            return pAll
+              .concat(this.#geldEdge(pCurrentDependency))
+              .concat(lCycle);
           }
         }
         return pAll;
@@ -229,9 +251,17 @@ export default class IndexedModuleGraph {
    *                                (source uniquely identifying a node)
    * @param {string} pCurrentSource The 'source' attribute of the 'to' node to
    *                                be traversed
-   * @return {string[]}             see description above
+   * @return {Array<IMiniDependency>}   see description above
    */
   getCycle(pInitialSource, pCurrentSource) {
-    return this.#getCycle(pInitialSource, pCurrentSource);
+    const lInitialNode = this.findVertexByName(pInitialSource);
+    const lCurrentDependency = lInitialNode.dependencies.find(
+      (pDependency) => pDependency.name === pCurrentSource,
+    );
+
+    if (!lCurrentDependency) {
+      return [];
+    }
+    return this.#getCycleNew(pInitialSource, lCurrentDependency);
   }
 }
diff --git a/src/report/anon/anonymize-path.mjs b/src/report/anon/anonymize-path.mjs
index 40896b92..a5b000a9 100644
--- a/src/report/anon/anonymize-path.mjs
+++ b/src/report/anon/anonymize-path.mjs
@@ -2,7 +2,7 @@ import { anonymizePathElement } from "./anonymize-path-element.mjs";
 
 export const WHITELIST_RE =
   // eslint-disable-next-line security/detect-unsafe-regex
-  /^(|[.]+|~|bin|apps?|cli|src|libs?|configs?|components?|fixtures?|helpers?|i18n|index\.(jsx?|[mc]js|d\.ts|tsx?|vue|coffee|ls)|_?_?mocks?_?_?|node_modules|packages?|package\.json|scripts?|services?|sources?|specs?|_?_?tests?_?_?|types?|uti?ls?)$/;
+  /^(|[.]+|~|bin|apps?|cli|src|libs?|configs?|components?|fixtures?|helpers?|i18n|index\.(jsx?|[mc]js|d\.ts|tsx?|vue|coffee|ls)|_?_?mocks?_?_?|node_modules|packages?|package\.json|scripts?|services?|sources?|specs?|_?_?tests?_?_?|types?|uti?ls?|tools)$/;
 
 /**
  * Kind of smartly anonymizes paths, by
diff --git a/src/report/anon/index.mjs b/src/report/anon/index.mjs
index f5cce2dd..f593ae1b 100644
--- a/src/report/anon/index.mjs
+++ b/src/report/anon/index.mjs
@@ -2,15 +2,26 @@ import has from "lodash/has.js";
 import { anonymizePath, WHITELIST_RE } from "./anonymize-path.mjs";
 
 function anonymizePathArray(pPathArray, pWordList) {
+  // the coverage ignore is here because the || [] branch isn't taken when running
+  // tests and with the current setup of the anonymize module that's not going
+  // to change. Still want to keep the branch from robustness perspective though.
+  /* c8 ignore next 1 */
   return (pPathArray || []).map((pPath) => anonymizePath(pPath, pWordList));
 }
 
+function anonymizeCycleArray(pCycleArray, pWordList, pAttribute = "name") {
+  return (pCycleArray || []).map((pCycle) => ({
+    ...pCycle,
+    [pAttribute]: anonymizePath(pCycle.name, pWordList),
+  }));
+}
+
 function anonymizeDependencies(pDependencies, pWordList) {
   return pDependencies.map((pDependency) => ({
     ...pDependency,
     resolved: anonymizePath(pDependency.resolved, pWordList),
     module: anonymizePath(pDependency.module, pWordList),
-    cycle: anonymizePathArray(pDependency.cycle, pWordList),
+    cycle: anonymizeCycleArray(pDependency.cycle, pWordList),
   }));
 }
 
@@ -74,7 +85,7 @@ function anonymizeFolders(pFolders, pWordList) {
           name: anonymizePath(pDependency.name, pWordList),
         };
         if (lReturnDependencies.cycle) {
-          lReturnDependencies.cycle = anonymizePathArray(
+          lReturnDependencies.cycle = anonymizeCycleArray(
             pDependency.cycle,
             pWordList,
           );
@@ -98,7 +109,7 @@ function anonymizeViolations(pViolations, pWordList) {
       ...pViolation,
       from: anonymizePath(pViolation.from, pWordList),
       to: anonymizePath(pViolation.to, pWordList),
-      cycle: anonymizePathArray(pViolation.cycle, pWordList),
+      cycle: anonymizeCycleArray(pViolation.cycle, pWordList),
     };
     if (pViolation.via) {
       lReturnValue.via = anonymizePathArray(pViolation.via, pWordList);
@@ -145,7 +156,7 @@ function sanitizeWordList(pWordList) {
  * - summary.violations.to
  * - summary.violations.cycle[m]
  *
- * (note: the algorith _removes_ elements from pWordList to prevent duplicates,
+ * (note: the algorithm _removes_ elements from pWordList to prevent duplicates,
  * so if the word list is precious to you - pass a clone)
  *
  * @param {import("../../../types/cruise-result.mjs").ICruiseResult} pResults - the output of a dependency-cruise adhering to ../schema/cruise-result.schema.json
diff --git a/src/report/anon/random-string.mjs b/src/report/anon/random-string.mjs
index 610bd558..999d1111 100644
--- a/src/report/anon/random-string.mjs
+++ b/src/report/anon/random-string.mjs
@@ -42,7 +42,7 @@ function getRandomChar(pChar) {
 
 /**
  * Returns a random string with the same length as pString
- * acii characters - respecting case & numbers + leaving separators
+ * ascii characters - respecting case & numbers + leaving separators
  * (-, _, .) in place
  *
  * hello => tbkwd
diff --git a/src/report/azure-devops.mjs b/src/report/azure-devops.mjs
index 2c5701c9..f2cddf69 100644
--- a/src/report/azure-devops.mjs
+++ b/src/report/azure-devops.mjs
@@ -42,7 +42,9 @@ function formatDependencyViolation(pViolation) {
  * @returns {string}
  */
 function formatCycleViolation(pViolation) {
-  return `${pViolation.from} -> ${pViolation.cycle.join(" -> ")}`;
+  return `${pViolation.from} -> ${pViolation.cycle
+    .map(({ name }) => name)
+    .join(" -> ")}`;
 }
 
 /**
diff --git a/src/report/error-html/utl.mjs b/src/report/error-html/utl.mjs
index d44cb523..5c8e65e9 100644
--- a/src/report/error-html/utl.mjs
+++ b/src/report/error-html/utl.mjs
@@ -30,7 +30,7 @@ function mergeCountsIntoRule(pRule, pViolationCounts) {
 }
 
 function formatCycleTo(pViolation) {
-  return pViolation.cycle.join(" &rightarrow;<br/>");
+  return pViolation.cycle.map(({ name }) => name).join(" &rightarrow;<br/>");
 }
 
 function formatReachabilityTo(pViolation) {
diff --git a/src/report/error.mjs b/src/report/error.mjs
index 10ddd827..868de528 100644
--- a/src/report/error.mjs
+++ b/src/report/error.mjs
@@ -17,6 +17,15 @@ const SEVERITY2CHALK = new Map([
 
 const EXTRA_PATH_INFORMATION_INDENT = 6;
 
+function formatExtraCycleInformation(pCycle) {
+  return EOL.concat(
+    wrapAndIndent(
+      pCycle.map(({ name }) => name).join(` ${figures.arrowRight} ${EOL}`),
+      EXTRA_PATH_INFORMATION_INDENT,
+    ),
+  );
+}
+
 function formatExtraPathInformation(pExtra) {
   return EOL.concat(
     wrapAndIndent(
@@ -39,7 +48,7 @@ function formatDependencyViolation(pViolation) {
 function formatCycleViolation(pViolation) {
   return `${chalk.bold(pViolation.from)} ${
     figures.arrowRight
-  } ${formatExtraPathInformation(pViolation.cycle)}`;
+  } ${formatExtraCycleInformation(pViolation.cycle)}`;
 }
 
 function formatReachabilityViolation(pViolation) {
diff --git a/src/report/teamcity.mjs b/src/report/teamcity.mjs
index 682d2dc1..a4013a88 100644
--- a/src/report/teamcity.mjs
+++ b/src/report/teamcity.mjs
@@ -15,7 +15,7 @@ function severity2teamcitySeverity(pSeverity) {
 function reportRules(pRules, pViolations) {
   return pRules
     .filter((pRule) =>
-      pViolations.some((pViolation) => pRule.name === pViolation.rule.name)
+      pViolations.some((pViolation) => pRule.name === pViolation.rule.name),
     )
     .map((pRule) =>
       tsm.inspectionType({
@@ -23,7 +23,7 @@ function reportRules(pRules, pViolations) {
         name: pRule.name,
         description: pRule.comment || pRule.name,
         category: CATEGORY,
-      })
+      }),
     );
 }
 
@@ -75,20 +75,22 @@ function formatDependencyViolation(pViolation) {
 }
 
 function formatCycleViolation(pViolation) {
-  return `${pViolation.from} -> ${pViolation.cycle.join(" -> ")}`;
+  return `${pViolation.from} -> ${pViolation.cycle
+    .map(({ name }) => name)
+    .join(" -> ")}`;
 }
 
 function formatReachabilityViolation(pViolation) {
   return `${formatDependencyViolation(pViolation)} ${pViolation.via.join(
-    " -> "
+    " -> ",
   )}`;
 }
 
 function formatInstabilityViolation(pViolation) {
   return `${formatDependencyViolation(
-    pViolation
+    pViolation,
   )} (instability: ${formatPercentage(
-    pViolation.metrics.from.instability
+    pViolation.metrics.from.instability,
   )} -> ${formatPercentage(pViolation.metrics.to.instability)})`;
 }
 
@@ -103,7 +105,7 @@ function bakeViolationMessage(pViolation) {
   return formatViolation(
     pViolation,
     lViolationType2Formatter,
-    formatDependencyViolation
+    formatDependencyViolation,
   );
 }
 
@@ -128,7 +130,7 @@ function reportViolations(pViolations, pIgnoredCount) {
         message: bakeViolationMessage(pViolation),
         file: pViolation.from,
         SEVERITY: severity2teamcitySeverity(pViolation.rule.severity),
-      })
+      }),
     )
     .concat(reportIgnoredViolation(pIgnoredCount));
 }
@@ -152,7 +154,7 @@ export default function teamcity(pResults) {
 
   const lRuleSet = pResults?.summary?.ruleSetUsed ?? [];
   const lViolations = (pResults?.summary?.violations ?? []).filter(
-    (pViolation) => pViolation.rule.severity !== "ignore"
+    (pViolation) => pViolation.rule.severity !== "ignore",
   );
   const lIgnoredCount = pResults?.summary?.ignore ?? 0;
 
diff --git a/src/schema/baseline-violations.schema.json b/src/schema/baseline-violations.schema.json
index d8a33034..edf93bbb 100644
--- a/src/schema/baseline-violations.schema.json
+++ b/src/schema/baseline-violations.schema.json
@@ -20,7 +20,7 @@
         "rule": { "$ref": "#/definitions/RuleSummaryType" },
         "cycle": {
           "type": "array",
-          "items": { "type": "string" },
+          "items": { "$ref": "#/definitions/MiniDependency" },
           "description": "The circular path if the violation is about circularity"
         },
         "via": {
@@ -81,6 +81,60 @@
         "instability",
         "folder"
       ]
+    },
+    "MiniDependency": {
+      "type": "object",
+      "description": "A small dependency object with the uniquely identifying name of the module +the dependency types it has relative to the _previous_ module in the chain  it is part of (e.g. a cycle).",
+      "required": ["name", "dependencyTypes"],
+      "additionalProperties": false,
+      "properties": {
+        "name": { "type": "string", "description": "The name of the module" },
+        "dependencyTypes": {
+          "type": "array",
+          "items": { "$ref": "#/definitions/DependencyTypeType" },
+          "description": "The dependency types of the module relative to the previous module in the chain it is a part of (e.g. a cycle)"
+        }
+      }
+    },
+    "DependencyTypeType": {
+      "type": "string",
+      "enum": [
+        "aliased-subpath-import",
+        "aliased-tsconfig-base-url",
+        "aliased-tsconfig-paths",
+        "aliased-tsconfig",
+        "aliased-webpack",
+        "aliased-workspace",
+        "aliased",
+        "amd-define",
+        "amd-require",
+        "amd-exotic-require",
+        "core",
+        "deprecated",
+        "dynamic-import",
+        "exotic-require",
+        "export",
+        "import-equals",
+        "import",
+        "local",
+        "localmodule",
+        "npm-bundled",
+        "npm-dev",
+        "npm-no-pkg",
+        "npm-optional",
+        "npm-peer",
+        "npm-unknown",
+        "npm",
+        "require",
+        "triple-slash-amd-dependency",
+        "triple-slash-directive",
+        "triple-slash-file-reference",
+        "triple-slash-type-reference",
+        "type-import",
+        "type-only",
+        "undetermined",
+        "unknown"
+      ]
     }
   }
 }
diff --git a/src/schema/baseline-violations.schema.mjs b/src/schema/baseline-violations.schema.mjs
index 7ceb392c..7d46d6f8 100644
--- a/src/schema/baseline-violations.schema.mjs
+++ b/src/schema/baseline-violations.schema.mjs
@@ -1,1 +1,1 @@
-/* generated - don't edit */export default {"title":"dependency-cruiser baseline ('known errors') format","$schema":"http://json-schema.org/draft-07/schema#","$id":"https://dependency-cruiser.js.org/schema/baseline-violations.schema.json","$ref":"#/definitions/ViolationsType","definitions":{"ViolationsType":{"type":"array","items":{"$ref":"#/definitions/ViolationType"}},"ViolationType":{"type":"object","required":["from","to","rule"],"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"},"type":{"$ref":"#/definitions/ViolationTypeType"},"rule":{"$ref":"#/definitions/RuleSummaryType"},"cycle":{"type":"array","items":{"type":"string"}},"via":{"type":"array","items":{"type":"string"}},"metrics":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}},"to":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}}}},"comment":{"type":"string"}}},"RuleSummaryType":{"type":"object","required":["name","severity"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"}}},"SeverityType":{"type":"string","enum":["error","warn","info","ignore"]},"ViolationTypeType":{"type":"string","enum":["dependency","module","reachability","cycle","instability","folder"]}}}
\ No newline at end of file
+/* generated - don't edit */export default {"title":"dependency-cruiser baseline ('known errors') format","$schema":"http://json-schema.org/draft-07/schema#","$id":"https://dependency-cruiser.js.org/schema/baseline-violations.schema.json","$ref":"#/definitions/ViolationsType","definitions":{"ViolationsType":{"type":"array","items":{"$ref":"#/definitions/ViolationType"}},"ViolationType":{"type":"object","required":["from","to","rule"],"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"},"type":{"$ref":"#/definitions/ViolationTypeType"},"rule":{"$ref":"#/definitions/RuleSummaryType"},"cycle":{"type":"array","items":{"$ref":"#/definitions/MiniDependency"}},"via":{"type":"array","items":{"type":"string"}},"metrics":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}},"to":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}}}},"comment":{"type":"string"}}},"RuleSummaryType":{"type":"object","required":["name","severity"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"}}},"SeverityType":{"type":"string","enum":["error","warn","info","ignore"]},"ViolationTypeType":{"type":"string","enum":["dependency","module","reachability","cycle","instability","folder"]},"MiniDependency":{"type":"object","required":["name","dependencyTypes"],"additionalProperties":false,"properties":{"name":{"type":"string"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"DependencyTypeType":{"type":"string","enum":["aliased-subpath-import","aliased-tsconfig-base-url","aliased-tsconfig-paths","aliased-tsconfig","aliased-webpack","aliased-workspace","aliased","amd-define","amd-require","amd-exotic-require","core","deprecated","dynamic-import","exotic-require","export","import-equals","import","local","localmodule","npm-bundled","npm-dev","npm-no-pkg","npm-optional","npm-peer","npm-unknown","npm","require","triple-slash-amd-dependency","triple-slash-directive","triple-slash-file-reference","triple-slash-type-reference","type-import","type-only","undetermined","unknown"]}}}
\ No newline at end of file
diff --git a/src/schema/configuration.schema.json b/src/schema/configuration.schema.json
index 979a55fe..c4930fad 100644
--- a/src/schema/configuration.schema.json
+++ b/src/schema/configuration.schema.json
@@ -1003,7 +1003,7 @@
         "rule": { "$ref": "#/definitions/RuleSummaryType" },
         "cycle": {
           "type": "array",
-          "items": { "type": "string" },
+          "items": { "$ref": "#/definitions/MiniDependency" },
           "description": "The circular path if the violation is about circularity"
         },
         "via": {
@@ -1060,6 +1060,20 @@
         "folder"
       ]
     },
+    "MiniDependency": {
+      "type": "object",
+      "description": "A small dependency object with the uniquely identifying name of the module +the dependency types it has relative to the _previous_ module in the chain  it is part of (e.g. a cycle).",
+      "required": ["name", "dependencyTypes"],
+      "additionalProperties": false,
+      "properties": {
+        "name": { "type": "string", "description": "The name of the module" },
+        "dependencyTypes": {
+          "type": "array",
+          "items": { "$ref": "#/definitions/DependencyTypeType" },
+          "description": "The dependency types of the module relative to the previous module in the chain it is a part of (e.g. a cycle)"
+        }
+      }
+    },
     "CacheOptionsType": {
       "type": "object",
       "additionalProperties": false,
diff --git a/src/schema/configuration.schema.mjs b/src/schema/configuration.schema.mjs
index c5049873..7accabe2 100644
--- a/src/schema/configuration.schema.mjs
+++ b/src/schema/configuration.schema.mjs
@@ -1,1 +1,1 @@
-/* generated - don't edit */export default {"title":"dependency-cruiser configuration","$schema":"http://json-schema.org/draft-07/schema#","$id":"https://dependency-cruiser.js.org/schema/configuration.schema.json","type":"object","additionalProperties":false,"properties":{"$schema":{"type":"string"},"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}},"options":{"$ref":"#/definitions/OptionsType"},"extends":{"$ref":"#/definitions/ExtendsType"}},"definitions":{"RuleSetType":{"type":"object","additionalProperties":false,"properties":{"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}}}},"AllowedRuleType":{"oneOf":[{"$ref":"#/definitions/RegularAllowedRuleType"},{"$ref":"#/definitions/ReachabilityAllowedRuleType"}]},"RegularAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"ReachabilityAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"ForbiddenRuleType":{"oneOf":[{"$ref":"#/definitions/RegularForbiddenRuleType"},{"$ref":"#/definitions/ReachabilityForbiddenRuleType"},{"$ref":"#/definitions/DependentsForbiddenRuleType"}]},"RegularForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"DependentsForbiddenRuleType":{"type":"object","required":["module","from"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/DependentsModuleRestrictionType"},"from":{"$ref":"#/definitions/DependentsFromRestrictionType"}}},"ReachabilityForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"RequiredRuleType":{"type":"object","required":["module","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/RequiredModuleRestrictionType"},"to":{"$ref":"#/definitions/RequiredToRestrictionType"}}},"FromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"orphan":{"type":"boolean"}}},"ReachabilityFromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ToRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"couldNotResolve":{"type":"boolean"},"circular":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"$ref":"#/definitions/REAsStringsType"},"exoticRequireNot":{"$ref":"#/definitions/REAsStringsType"},"preCompilationOnly":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"dependencyTypesNot":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"moreThanOneDependencyType":{"type":"boolean"},"license":{"$ref":"#/definitions/REAsStringsType"},"licenseNot":{"$ref":"#/definitions/REAsStringsType"},"via":{"$ref":"#/definitions/REAsStringsType"},"viaOnly":{"$ref":"#/definitions/REAsStringsType"},"viaNot":{"$ref":"#/definitions/REAsStringsType"},"viaSomeNot":{"$ref":"#/definitions/REAsStringsType"},"moreUnstable":{"type":"boolean"}}},"DependentsModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"numberOfDependentsLessThan":{"type":"integer","minimum":0,"maximum":100},"numberOfDependentsMoreThan":{"type":"integer","minimum":0,"maximum":100}}},"DependentsFromRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ReachabilityToRestrictionType":{"required":["reachable"],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"reachable":{"type":"boolean"}}},"RequiredModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"RequiredToRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"DependencyTypeType":{"type":"string","enum":["aliased-subpath-import","aliased-tsconfig-base-url","aliased-tsconfig-paths","aliased-tsconfig","aliased-webpack","aliased-workspace","aliased","amd-define","amd-require","amd-exotic-require","core","deprecated","dynamic-import","exotic-require","export","import-equals","import","local","localmodule","npm-bundled","npm-dev","npm-no-pkg","npm-optional","npm-peer","npm-unknown","npm","require","triple-slash-amd-dependency","triple-slash-directive","triple-slash-file-reference","triple-slash-type-reference","type-import","type-only","undetermined","unknown"]},"REAsStringsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"SeverityType":{"type":"string","enum":["error","warn","info","ignore"]},"OptionsType":{"type":"object","additionalProperties":false,"properties":{"doNotFollow":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundDoNotFollowType"}]},"exclude":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundExcludeType"}]},"includeOnly":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundIncludeOnlyType"}]},"focus":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundFocusType"}]},"reaches":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundReachesType"}]},"highlight":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundHighlightType"}]},"knownViolations":{"$ref":"#/definitions/ViolationsType"},"collapse":{"oneOf":[{"type":"string"},{"type":"integer","minimum":1,"maximum":9}]},"maxDepth":{"type":"integer","minimum":0,"maximum":99},"moduleSystems":{"$ref":"#/definitions/ModuleSystemsType"},"prefix":{"type":"string"},"preserveSymlinks":{"type":"boolean"},"combinedDependencies":{"type":"boolean"},"tsConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"tsPreCompilationDeps":{"oneOf":[{"type":"boolean"},{"type":"string","enum":["specify"]}]},"extraExtensionsToScan":{"type":"array","items":{"type":"string"}},"externalModuleResolutionStrategy":{"type":"string","enum":["node_modules","yarn-pnp"]},"builtInModules":{"type":"object","additionalProperties":false,"properties":{"override":{"type":"array","items":{"type":"string"}},"add":{"type":"array","items":{"type":"string"}}}},"forceDeriveDependents":{"type":"boolean"},"webpackConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"},"env":{"oneOf":[{"type":"object"},{"type":"string"}]},"arguments":{"type":"object"}}},"enhancedResolveOptions":{"type":"object","additionalProperties":false,"properties":{"exportsFields":{"type":"array","items":{"type":"string"}},"conditionNames":{"type":"array","items":{"type":"string"}},"extensions":{"type":"array","items":{"type":"string"}},"mainFields":{"type":"array","items":{"type":"string"}},"mainFiles":{"type":"array"},"aliasFields":{"type":"array","items":{"type":"string"}},"cachedInputFileSystem":{"type":"object","additionalProperties":false,"properties":{"cacheDuration":{"type":"integer","minimum":0,"maximum":1800000}}}}},"babelConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"parser":{"type":"string","enum":["acorn","swc","tsc"]},"exoticRequireStrings":{"type":"array","items":{"type":"string"}},"reporterOptions":{"$ref":"#/definitions/ReporterOptionsType"},"progress":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["cli-feedback","performance-log","ndjson","none"]},"maximumLevel":{"type":"number","enum":[-1,40,50,60,70,80,99]}}},"metrics":{"type":"boolean"},"baseDir":{"type":"string"},"cache":{"oneOf":[{"type":"boolean"},{"type":"string"},{"$ref":"#/definitions/CacheOptionsType"}]}}},"ModuleSystemType":{"type":"string","enum":["cjs","es6","amd","tsd"]},"ModuleSystemsType":{"type":"array","items":{"$ref":"#/definitions/ModuleSystemType"}},"CompoundExcludeType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dynamic":{"type":"boolean"}}},"CompoundDoNotFollowType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"CompoundIncludeOnlyType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundFocusType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"depth":{"type":"number","minimum":1,"maximum":4}}},"CompoundReachesType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundHighlightType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"ReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"anon":{"$ref":"#/definitions/AnonReporterOptionsType"},"archi":{"$ref":"#/definitions/DotReporterOptionsType"},"dot":{"$ref":"#/definitions/DotReporterOptionsType"},"ddot":{"$ref":"#/definitions/DotReporterOptionsType"},"flat":{"$ref":"#/definitions/DotReporterOptionsType"},"markdown":{"$ref":"#/definitions/MarkdownReporterOptionsType"},"metrics":{"$ref":"#/definitions/MetricsReporterOptionsType"},"mermaid":{"$ref":"#/definitions/MermaidReporterOptionsType"},"text":{"$ref":"#/definitions/TextReporterOptionsType"}}},"AnonReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"wordlist":{"type":"array","items":{"type":"string"}}}},"MetricsReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"orderBy":{"type":"string","enum":["instability","moduleCount","afferentCouplings","efferentCouplings","name"]},"hideModules":{"type":"boolean"},"hideFolders":{"type":"boolean"}}},"MarkdownReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"showTitle":{"type":"boolean"},"title":{"type":"string"},"showSummary":{"type":"boolean"},"showSummaryHeader":{"type":"boolean"},"summaryHeader":{"type":"string"},"showStatsSummary":{"type":"boolean"},"showRulesSummary":{"type":"boolean"},"includeIgnoredInSummary":{"type":"boolean"},"showDetails":{"type":"boolean"},"includeIgnoredInDetails":{"type":"boolean"},"showDetailsHeader":{"type":"boolean"},"detailsHeader":{"type":"string"},"collapseDetails":{"type":"boolean"},"collapsedMessage":{"type":"string"},"noViolationsMessage":{"type":"string"},"showFooter":{"type":"boolean"}}},"MermaidReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"minify":{"type":"boolean"}}},"TextReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"highlightFocused":{"type":"boolean"}}},"DotReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"collapsePattern":{"$ref":"#/definitions/REAsStringsType"},"filters":{"$ref":"#/definitions/ReporterFiltersType"},"showMetrics":{"type":"boolean"},"theme":{"$ref":"#/definitions/DotThemeType"}}},"DotThemeType":{"type":"object","additionalProperties":false,"properties":{"replace":{"type":"boolean"},"graph":{"type":"object"},"node":{"type":"object"},"edge":{"type":"object"},"modules":{"$ref":"#/definitions/DotThemeArrayType"},"dependencies":{"$ref":"#/definitions/DotThemeArrayType"}}},"DotThemeArrayType":{"type":"array","items":{"$ref":"#/definitions/DotThemeEntryType"}},"DotThemeEntryType":{"type":"object","additionalProperties":false,"properties":{"criteria":{"type":"object"},"attributes":{"type":"object"}}},"ReporterFiltersType":{"type":"object","additionalProperties":false,"properties":{"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"$ref":"#/definitions/CompoundIncludeOnlyType"},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"}}},"ViolationsType":{"type":"array","items":{"$ref":"#/definitions/ViolationType"}},"ViolationType":{"type":"object","required":["from","to","rule"],"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"},"type":{"$ref":"#/definitions/ViolationTypeType"},"rule":{"$ref":"#/definitions/RuleSummaryType"},"cycle":{"type":"array","items":{"type":"string"}},"via":{"type":"array","items":{"type":"string"}},"metrics":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}},"to":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}}}},"comment":{"type":"string"}}},"RuleSummaryType":{"type":"object","required":["name","severity"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"}}},"ViolationTypeType":{"type":"string","enum":["dependency","module","reachability","cycle","instability","folder"]},"CacheOptionsType":{"type":"object","additionalProperties":false,"properties":{"folder":{"type":"string"},"strategy":{"$ref":"#/definitions/CacheStrategyType"},"compress":{"type":"boolean","default":false}}},"CacheStrategyType":{"type":"string","enum":["metadata","content"]},"ExtendsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}}}
\ No newline at end of file
+/* generated - don't edit */export default {"title":"dependency-cruiser configuration","$schema":"http://json-schema.org/draft-07/schema#","$id":"https://dependency-cruiser.js.org/schema/configuration.schema.json","type":"object","additionalProperties":false,"properties":{"$schema":{"type":"string"},"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}},"options":{"$ref":"#/definitions/OptionsType"},"extends":{"$ref":"#/definitions/ExtendsType"}},"definitions":{"RuleSetType":{"type":"object","additionalProperties":false,"properties":{"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}}}},"AllowedRuleType":{"oneOf":[{"$ref":"#/definitions/RegularAllowedRuleType"},{"$ref":"#/definitions/ReachabilityAllowedRuleType"}]},"RegularAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"ReachabilityAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"ForbiddenRuleType":{"oneOf":[{"$ref":"#/definitions/RegularForbiddenRuleType"},{"$ref":"#/definitions/ReachabilityForbiddenRuleType"},{"$ref":"#/definitions/DependentsForbiddenRuleType"}]},"RegularForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"DependentsForbiddenRuleType":{"type":"object","required":["module","from"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/DependentsModuleRestrictionType"},"from":{"$ref":"#/definitions/DependentsFromRestrictionType"}}},"ReachabilityForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"RequiredRuleType":{"type":"object","required":["module","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/RequiredModuleRestrictionType"},"to":{"$ref":"#/definitions/RequiredToRestrictionType"}}},"FromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"orphan":{"type":"boolean"}}},"ReachabilityFromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ToRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"couldNotResolve":{"type":"boolean"},"circular":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"$ref":"#/definitions/REAsStringsType"},"exoticRequireNot":{"$ref":"#/definitions/REAsStringsType"},"preCompilationOnly":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"dependencyTypesNot":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"moreThanOneDependencyType":{"type":"boolean"},"license":{"$ref":"#/definitions/REAsStringsType"},"licenseNot":{"$ref":"#/definitions/REAsStringsType"},"via":{"$ref":"#/definitions/REAsStringsType"},"viaOnly":{"$ref":"#/definitions/REAsStringsType"},"viaNot":{"$ref":"#/definitions/REAsStringsType"},"viaSomeNot":{"$ref":"#/definitions/REAsStringsType"},"moreUnstable":{"type":"boolean"}}},"DependentsModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"numberOfDependentsLessThan":{"type":"integer","minimum":0,"maximum":100},"numberOfDependentsMoreThan":{"type":"integer","minimum":0,"maximum":100}}},"DependentsFromRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ReachabilityToRestrictionType":{"required":["reachable"],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"reachable":{"type":"boolean"}}},"RequiredModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"RequiredToRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"DependencyTypeType":{"type":"string","enum":["aliased-subpath-import","aliased-tsconfig-base-url","aliased-tsconfig-paths","aliased-tsconfig","aliased-webpack","aliased-workspace","aliased","amd-define","amd-require","amd-exotic-require","core","deprecated","dynamic-import","exotic-require","export","import-equals","import","local","localmodule","npm-bundled","npm-dev","npm-no-pkg","npm-optional","npm-peer","npm-unknown","npm","require","triple-slash-amd-dependency","triple-slash-directive","triple-slash-file-reference","triple-slash-type-reference","type-import","type-only","undetermined","unknown"]},"REAsStringsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"SeverityType":{"type":"string","enum":["error","warn","info","ignore"]},"OptionsType":{"type":"object","additionalProperties":false,"properties":{"doNotFollow":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundDoNotFollowType"}]},"exclude":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundExcludeType"}]},"includeOnly":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundIncludeOnlyType"}]},"focus":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundFocusType"}]},"reaches":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundReachesType"}]},"highlight":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundHighlightType"}]},"knownViolations":{"$ref":"#/definitions/ViolationsType"},"collapse":{"oneOf":[{"type":"string"},{"type":"integer","minimum":1,"maximum":9}]},"maxDepth":{"type":"integer","minimum":0,"maximum":99},"moduleSystems":{"$ref":"#/definitions/ModuleSystemsType"},"prefix":{"type":"string"},"preserveSymlinks":{"type":"boolean"},"combinedDependencies":{"type":"boolean"},"tsConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"tsPreCompilationDeps":{"oneOf":[{"type":"boolean"},{"type":"string","enum":["specify"]}]},"extraExtensionsToScan":{"type":"array","items":{"type":"string"}},"externalModuleResolutionStrategy":{"type":"string","enum":["node_modules","yarn-pnp"]},"builtInModules":{"type":"object","additionalProperties":false,"properties":{"override":{"type":"array","items":{"type":"string"}},"add":{"type":"array","items":{"type":"string"}}}},"forceDeriveDependents":{"type":"boolean"},"webpackConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"},"env":{"oneOf":[{"type":"object"},{"type":"string"}]},"arguments":{"type":"object"}}},"enhancedResolveOptions":{"type":"object","additionalProperties":false,"properties":{"exportsFields":{"type":"array","items":{"type":"string"}},"conditionNames":{"type":"array","items":{"type":"string"}},"extensions":{"type":"array","items":{"type":"string"}},"mainFields":{"type":"array","items":{"type":"string"}},"mainFiles":{"type":"array"},"aliasFields":{"type":"array","items":{"type":"string"}},"cachedInputFileSystem":{"type":"object","additionalProperties":false,"properties":{"cacheDuration":{"type":"integer","minimum":0,"maximum":1800000}}}}},"babelConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"parser":{"type":"string","enum":["acorn","swc","tsc"]},"exoticRequireStrings":{"type":"array","items":{"type":"string"}},"reporterOptions":{"$ref":"#/definitions/ReporterOptionsType"},"progress":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["cli-feedback","performance-log","ndjson","none"]},"maximumLevel":{"type":"number","enum":[-1,40,50,60,70,80,99]}}},"metrics":{"type":"boolean"},"baseDir":{"type":"string"},"cache":{"oneOf":[{"type":"boolean"},{"type":"string"},{"$ref":"#/definitions/CacheOptionsType"}]}}},"ModuleSystemType":{"type":"string","enum":["cjs","es6","amd","tsd"]},"ModuleSystemsType":{"type":"array","items":{"$ref":"#/definitions/ModuleSystemType"}},"CompoundExcludeType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dynamic":{"type":"boolean"}}},"CompoundDoNotFollowType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"CompoundIncludeOnlyType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundFocusType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"depth":{"type":"number","minimum":1,"maximum":4}}},"CompoundReachesType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundHighlightType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"ReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"anon":{"$ref":"#/definitions/AnonReporterOptionsType"},"archi":{"$ref":"#/definitions/DotReporterOptionsType"},"dot":{"$ref":"#/definitions/DotReporterOptionsType"},"ddot":{"$ref":"#/definitions/DotReporterOptionsType"},"flat":{"$ref":"#/definitions/DotReporterOptionsType"},"markdown":{"$ref":"#/definitions/MarkdownReporterOptionsType"},"metrics":{"$ref":"#/definitions/MetricsReporterOptionsType"},"mermaid":{"$ref":"#/definitions/MermaidReporterOptionsType"},"text":{"$ref":"#/definitions/TextReporterOptionsType"}}},"AnonReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"wordlist":{"type":"array","items":{"type":"string"}}}},"MetricsReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"orderBy":{"type":"string","enum":["instability","moduleCount","afferentCouplings","efferentCouplings","name"]},"hideModules":{"type":"boolean"},"hideFolders":{"type":"boolean"}}},"MarkdownReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"showTitle":{"type":"boolean"},"title":{"type":"string"},"showSummary":{"type":"boolean"},"showSummaryHeader":{"type":"boolean"},"summaryHeader":{"type":"string"},"showStatsSummary":{"type":"boolean"},"showRulesSummary":{"type":"boolean"},"includeIgnoredInSummary":{"type":"boolean"},"showDetails":{"type":"boolean"},"includeIgnoredInDetails":{"type":"boolean"},"showDetailsHeader":{"type":"boolean"},"detailsHeader":{"type":"string"},"collapseDetails":{"type":"boolean"},"collapsedMessage":{"type":"string"},"noViolationsMessage":{"type":"string"},"showFooter":{"type":"boolean"}}},"MermaidReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"minify":{"type":"boolean"}}},"TextReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"highlightFocused":{"type":"boolean"}}},"DotReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"collapsePattern":{"$ref":"#/definitions/REAsStringsType"},"filters":{"$ref":"#/definitions/ReporterFiltersType"},"showMetrics":{"type":"boolean"},"theme":{"$ref":"#/definitions/DotThemeType"}}},"DotThemeType":{"type":"object","additionalProperties":false,"properties":{"replace":{"type":"boolean"},"graph":{"type":"object"},"node":{"type":"object"},"edge":{"type":"object"},"modules":{"$ref":"#/definitions/DotThemeArrayType"},"dependencies":{"$ref":"#/definitions/DotThemeArrayType"}}},"DotThemeArrayType":{"type":"array","items":{"$ref":"#/definitions/DotThemeEntryType"}},"DotThemeEntryType":{"type":"object","additionalProperties":false,"properties":{"criteria":{"type":"object"},"attributes":{"type":"object"}}},"ReporterFiltersType":{"type":"object","additionalProperties":false,"properties":{"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"$ref":"#/definitions/CompoundIncludeOnlyType"},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"}}},"ViolationsType":{"type":"array","items":{"$ref":"#/definitions/ViolationType"}},"ViolationType":{"type":"object","required":["from","to","rule"],"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"},"type":{"$ref":"#/definitions/ViolationTypeType"},"rule":{"$ref":"#/definitions/RuleSummaryType"},"cycle":{"type":"array","items":{"$ref":"#/definitions/MiniDependency"}},"via":{"type":"array","items":{"type":"string"}},"metrics":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}},"to":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}}}},"comment":{"type":"string"}}},"RuleSummaryType":{"type":"object","required":["name","severity"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"}}},"ViolationTypeType":{"type":"string","enum":["dependency","module","reachability","cycle","instability","folder"]},"MiniDependency":{"type":"object","required":["name","dependencyTypes"],"additionalProperties":false,"properties":{"name":{"type":"string"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"CacheOptionsType":{"type":"object","additionalProperties":false,"properties":{"folder":{"type":"string"},"strategy":{"$ref":"#/definitions/CacheStrategyType"},"compress":{"type":"boolean","default":false}}},"CacheStrategyType":{"type":"string","enum":["metadata","content"]},"ExtendsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}}}
\ No newline at end of file
diff --git a/src/schema/cruise-result.schema.json b/src/schema/cruise-result.schema.json
index 8e0f6f55..5b630f65 100644
--- a/src/schema/cruise-result.schema.json
+++ b/src/schema/cruise-result.schema.json
@@ -245,7 +245,7 @@
         },
         "cycle": {
           "type": "array",
-          "items": { "type": "string" },
+          "items": { "$ref": "#/definitions/MiniDependency" },
           "description": "If following this dependency will ultimately return to the source (circular === true), this attribute will contain an (ordered) array of module names that shows (one of) the circular path(s)"
         },
         "moduleSystem": { "$ref": "#/definitions/ModuleSystemType" },
@@ -326,6 +326,20 @@
       "description": "How severe a violation of a rule is. The 'error' severity will make some reporters return a non-zero exit code, so if you want e.g. a build to stop when there's a rule violated: use that.",
       "enum": ["error", "warn", "info", "ignore"]
     },
+    "MiniDependency": {
+      "type": "object",
+      "description": "A small dependency object with the uniquely identifying name of the module +the dependency types it has relative to the _previous_ module in the chain  it is part of (e.g. a cycle).",
+      "required": ["name", "dependencyTypes"],
+      "additionalProperties": false,
+      "properties": {
+        "name": { "type": "string", "description": "The name of the module" },
+        "dependencyTypes": {
+          "type": "array",
+          "items": { "$ref": "#/definitions/DependencyTypeType" },
+          "description": "The dependency types of the module relative to the previous module in the chain it is a part of (e.g. a cycle)"
+        }
+      }
+    },
     "FoldersType": {
       "type": "array",
       "description": "A list of folders, as derived from the detected modules, with for each folder a bunch of metrics (adapted from 'Agile software development: principles, patterns, and practices' by Robert C Martin (ISBN 0-13-597444-5). Note: these metrics substitute 'components' and 'classes' from that book with 'folders' and 'modules'; the closest relatives that work for the most programming styles in JavaScript (and its derivative languages).",
@@ -381,7 +395,7 @@
               },
               "cycle": {
                 "type": "array",
-                "items": { "type": "string" },
+                "items": { "$ref": "#/definitions/MiniDependency" },
                 "description": "If following this dependency will ultimately return to the source (circular === true), this attribute will contain an (ordered) array of module names that shows (one of) the circular path(s)"
               },
               "rules": {
@@ -468,7 +482,7 @@
         "rule": { "$ref": "#/definitions/RuleSummaryType" },
         "cycle": {
           "type": "array",
-          "items": { "type": "string" },
+          "items": { "$ref": "#/definitions/MiniDependency" },
           "description": "The circular path if the violation is about circularity"
         },
         "via": {
diff --git a/src/schema/cruise-result.schema.mjs b/src/schema/cruise-result.schema.mjs
index 8c6b71d9..9e60c5a7 100644
--- a/src/schema/cruise-result.schema.mjs
+++ b/src/schema/cruise-result.schema.mjs
@@ -1,1 +1,1 @@
-/* generated - don't edit */export default {"title":"dependency-cruiser output format","$schema":"http://json-schema.org/draft-07/schema#","$id":"https://dependency-cruiser.js.org/schema/cruise-result.schema.json","type":"object","required":["summary","modules"],"additionalProperties":false,"properties":{"modules":{"$ref":"#/definitions/ModulesType"},"folders":{"$ref":"#/definitions/FoldersType"},"summary":{"$ref":"#/definitions/SummaryType"},"revisionData":{"$ref":"#/definitions/RevisionDataType"}},"definitions":{"ModulesType":{"type":"array","items":{"$ref":"#/definitions/ModuleType"}},"ModuleType":{"type":"object","required":["source","dependencies","valid"],"additionalProperties":false,"properties":{"source":{"type":"string"},"valid":{"type":"boolean"},"dependencies":{"$ref":"#/definitions/DependenciesType"},"dependents":{"type":"array","items":{"type":"string"}},"followable":{"type":"boolean"},"matchesDoNotFollow":{"type":"boolean"},"matchesFocus":{"type":"boolean"},"matchesReaches":{"type":"boolean"},"matchesHighlight":{"type":"boolean"},"coreModule":{"type":"boolean"},"couldNotResolve":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"license":{"type":"string"},"orphan":{"type":"boolean"},"reachable":{"type":"array","items":{"$ref":"#/definitions/ReachableType"}},"reaches":{"type":"array","items":{"$ref":"#/definitions/ReachesType"}},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}},"consolidated":{"type":"boolean"},"instability":{"type":"number"},"checksum":{"type":"string"}}},"ReachableType":{"type":"object","required":["value","asDefinedInRule","matchedFrom"],"additionalProperties":false,"properties":{"value":{"type":"boolean"},"asDefinedInRule":{"type":"string"},"matchedFrom":{"type":"string"}}},"ReachesType":{"type":"object","required":["modules","asDefinedInRule"],"additionalProperties":false,"properties":{"modules":{"type":"array","items":{"type":"object","required":["source","via"],"additionalProperties":false,"properties":{"source":{"type":"string"},"via":{"type":"array","items":{"type":"string"}}}}},"asDefinedInRule":{"type":"string"}}},"DependenciesType":{"type":"array","items":{"$ref":"#/definitions/DependencyType"}},"DependencyType":{"type":"object","required":["circular","coreModule","couldNotResolve","dependencyTypes","exoticallyRequired","dynamic","followable","module","moduleSystem","resolved","valid"],"additionalProperties":false,"properties":{"module":{"type":"string"},"protocol":{"type":"string","enum":["data:","file:","node:"]},"mimeType":{"type":"string"},"resolved":{"type":"string"},"coreModule":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"license":{"type":"string"},"followable":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"type":"string"},"matchesDoNotFollow":{"type":"boolean"},"couldNotResolve":{"type":"boolean"},"preCompilationOnly":{"type":"boolean"},"typeOnly":{"type":"boolean"},"circular":{"type":"boolean"},"cycle":{"type":"array","items":{"type":"string"}},"moduleSystem":{"$ref":"#/definitions/ModuleSystemType"},"valid":{"type":"boolean"},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}},"instability":{"type":"number"}}},"DependencyTypeType":{"type":"string","enum":["aliased-subpath-import","aliased-tsconfig-base-url","aliased-tsconfig-paths","aliased-tsconfig","aliased-webpack","aliased-workspace","aliased","amd-define","amd-require","amd-exotic-require","core","deprecated","dynamic-import","exotic-require","export","import-equals","import","local","localmodule","npm-bundled","npm-dev","npm-no-pkg","npm-optional","npm-peer","npm-unknown","npm","require","triple-slash-amd-dependency","triple-slash-directive","triple-slash-file-reference","triple-slash-type-reference","type-import","type-only","undetermined","unknown"]},"ModuleSystemType":{"type":"string","enum":["cjs","es6","amd","tsd"]},"RuleSummaryType":{"type":"object","required":["name","severity"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"}}},"SeverityType":{"type":"string","enum":["error","warn","info","ignore"]},"FoldersType":{"type":"array","items":{"$ref":"#/definitions/FolderType"}},"FolderType":{"type":"object","required":["name","moduleCount"],"additionalProperties":false,"properties":{"name":{"type":"string"},"dependents":{"type":"array","items":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string"}}}},"dependencies":{"type":"array","items":{"type":"object","required":["name","valid","circular"],"additionalProperties":false,"properties":{"name":{"type":"string"},"instability":{"type":"number"},"valid":{"type":"boolean"},"circular":{"type":"boolean"},"cycle":{"type":"array","items":{"type":"string"}},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}}}}},"moduleCount":{"type":"number"},"afferentCouplings":{"type":"number"},"efferentCouplings":{"type":"number"},"instability":{"type":"number"}}},"SummaryType":{"type":"object","required":["violations","error","warn","info","totalCruised","optionsUsed"],"additionalProperties":false,"properties":{"violations":{"$ref":"#/definitions/ViolationsType"},"error":{"type":"number"},"warn":{"type":"number"},"info":{"type":"number"},"ignore":{"type":"number"},"totalCruised":{"type":"number"},"totalDependenciesCruised":{"type":"number"},"ruleSetUsed":{"$ref":"#/definitions/RuleSetType"},"optionsUsed":{"$ref":"#/definitions/OptionsUsedType"}}},"ViolationsType":{"type":"array","items":{"$ref":"#/definitions/ViolationType"}},"ViolationType":{"type":"object","required":["from","to","rule"],"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"},"type":{"$ref":"#/definitions/ViolationTypeType"},"rule":{"$ref":"#/definitions/RuleSummaryType"},"cycle":{"type":"array","items":{"type":"string"}},"via":{"type":"array","items":{"type":"string"}},"metrics":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}},"to":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}}}},"comment":{"type":"string"}}},"ViolationTypeType":{"type":"string","enum":["dependency","module","reachability","cycle","instability","folder"]},"RuleSetType":{"type":"object","additionalProperties":false,"properties":{"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}}}},"AllowedRuleType":{"oneOf":[{"$ref":"#/definitions/RegularAllowedRuleType"},{"$ref":"#/definitions/ReachabilityAllowedRuleType"}]},"RegularAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"ReachabilityAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"ForbiddenRuleType":{"oneOf":[{"$ref":"#/definitions/RegularForbiddenRuleType"},{"$ref":"#/definitions/ReachabilityForbiddenRuleType"},{"$ref":"#/definitions/DependentsForbiddenRuleType"}]},"RegularForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"DependentsForbiddenRuleType":{"type":"object","required":["module","from"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/DependentsModuleRestrictionType"},"from":{"$ref":"#/definitions/DependentsFromRestrictionType"}}},"ReachabilityForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"RequiredRuleType":{"type":"object","required":["module","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/RequiredModuleRestrictionType"},"to":{"$ref":"#/definitions/RequiredToRestrictionType"}}},"FromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"orphan":{"type":"boolean"}}},"ReachabilityFromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ToRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"couldNotResolve":{"type":"boolean"},"circular":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"$ref":"#/definitions/REAsStringsType"},"exoticRequireNot":{"$ref":"#/definitions/REAsStringsType"},"preCompilationOnly":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"dependencyTypesNot":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"moreThanOneDependencyType":{"type":"boolean"},"license":{"$ref":"#/definitions/REAsStringsType"},"licenseNot":{"$ref":"#/definitions/REAsStringsType"},"via":{"$ref":"#/definitions/REAsStringsType"},"viaOnly":{"$ref":"#/definitions/REAsStringsType"},"viaNot":{"$ref":"#/definitions/REAsStringsType"},"viaSomeNot":{"$ref":"#/definitions/REAsStringsType"},"moreUnstable":{"type":"boolean"}}},"DependentsModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"numberOfDependentsLessThan":{"type":"integer","minimum":0,"maximum":100},"numberOfDependentsMoreThan":{"type":"integer","minimum":0,"maximum":100}}},"DependentsFromRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ReachabilityToRestrictionType":{"required":["reachable"],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"reachable":{"type":"boolean"}}},"RequiredModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"RequiredToRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"REAsStringsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"OptionsUsedType":{"type":"object","additionalProperties":false,"properties":{"doNotFollow":{"$ref":"#/definitions/CompoundDoNotFollowType"},"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundIncludeOnlyType"}]},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"},"highlight":{"$ref":"#/definitions/CompoundHighlightType"},"knownViolations":{"$ref":"#/definitions/ViolationsType"},"collapse":{"type":"string"},"maxDepth":{"type":"integer","minimum":0,"maximum":99},"moduleSystems":{"$ref":"#/definitions/ModuleSystemsType"},"prefix":{"type":"string"},"preserveSymlinks":{"type":"boolean"},"combinedDependencies":{"type":"boolean"},"tsConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"tsPreCompilationDeps":{"oneOf":[{"type":"boolean"},{"type":"string","enum":["specify"]}]},"extraExtensionsToScan":{"type":"array","items":{"type":"string"}},"externalModuleResolutionStrategy":{"type":"string","enum":["node_modules","yarn-pnp"]},"builtInModules":{"type":"object","additionalProperties":false,"properties":{"override":{"type":"array","items":{"type":"string"}},"add":{"type":"array","items":{"type":"string"}}}},"forceDeriveDependents":{"type":"boolean"},"webpackConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"},"env":{"oneOf":[{"type":"object"},{"type":"string"}]},"arguments":{"type":"object"}}},"enhancedResolveOptions":{"type":"object","additionalProperties":false,"properties":{"exportsFields":{"type":"array","items":{"type":"string"}},"conditionNames":{"type":"array","items":{"type":"string"}},"extensions":{"type":"array","items":{"type":"string"}},"mainFields":{"type":"array","items":{"type":"string"}},"mainFiles":{"type":"array"},"aliasFields":{"type":"array","items":{"type":"string"}},"cachedInputFileSystem":{"type":"object","additionalProperties":false,"properties":{"cacheDuration":{"type":"integer","minimum":0,"maximum":1800000}}}}},"babelConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"parser":{"type":"string","enum":["acorn","swc","tsc"]},"exoticRequireStrings":{"type":"array","items":{"type":"string"}},"reporterOptions":{"$ref":"#/definitions/ReporterOptionsType"},"progress":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["cli-feedback","performance-log","ndjson","none"]},"maximumLevel":{"type":"number","enum":[-1,40,50,60,70,80,99]}}},"metrics":{"type":"boolean"},"baseDir":{"type":"string"},"cache":{"oneOf":[{"type":"boolean","enum":[false]},{"$ref":"#/definitions/CacheOptionsType"}]},"args":{"type":"string"},"rulesFile":{"type":"string"},"outputTo":{"type":"string"},"outputType":{"$ref":"#/definitions/OutputType"}}},"ModuleSystemsType":{"type":"array","items":{"$ref":"#/definitions/ModuleSystemType"}},"OutputType":{"oneOf":[{"type":"string","enum":["json","html","dot","ddot","cdot","archi","fdot","flat","csv","err","err-long","err-html","teamcity","anon","text","metrics","markdown","mermaid","d2","null"]},{"type":"string","pattern":"^plugin:[^:]+$"}]},"CompoundExcludeType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dynamic":{"type":"boolean"}}},"CompoundDoNotFollowType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"CompoundIncludeOnlyType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundFocusType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"depth":{"type":"number","minimum":1,"maximum":4}}},"CompoundReachesType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundHighlightType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"ReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"anon":{"$ref":"#/definitions/AnonReporterOptionsType"},"archi":{"$ref":"#/definitions/DotReporterOptionsType"},"dot":{"$ref":"#/definitions/DotReporterOptionsType"},"ddot":{"$ref":"#/definitions/DotReporterOptionsType"},"flat":{"$ref":"#/definitions/DotReporterOptionsType"},"markdown":{"$ref":"#/definitions/MarkdownReporterOptionsType"},"metrics":{"$ref":"#/definitions/MetricsReporterOptionsType"},"mermaid":{"$ref":"#/definitions/MermaidReporterOptionsType"},"text":{"$ref":"#/definitions/TextReporterOptionsType"}}},"AnonReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"wordlist":{"type":"array","items":{"type":"string"}}}},"MetricsReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"orderBy":{"type":"string","enum":["instability","moduleCount","afferentCouplings","efferentCouplings","name"]},"hideModules":{"type":"boolean"},"hideFolders":{"type":"boolean"}}},"MarkdownReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"showTitle":{"type":"boolean"},"title":{"type":"string"},"showSummary":{"type":"boolean"},"showSummaryHeader":{"type":"boolean"},"summaryHeader":{"type":"string"},"showStatsSummary":{"type":"boolean"},"showRulesSummary":{"type":"boolean"},"includeIgnoredInSummary":{"type":"boolean"},"showDetails":{"type":"boolean"},"includeIgnoredInDetails":{"type":"boolean"},"showDetailsHeader":{"type":"boolean"},"detailsHeader":{"type":"string"},"collapseDetails":{"type":"boolean"},"collapsedMessage":{"type":"string"},"noViolationsMessage":{"type":"string"},"showFooter":{"type":"boolean"}}},"MermaidReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"minify":{"type":"boolean"}}},"TextReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"highlightFocused":{"type":"boolean"}}},"DotReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"collapsePattern":{"$ref":"#/definitions/REAsStringsType"},"filters":{"$ref":"#/definitions/ReporterFiltersType"},"showMetrics":{"type":"boolean"},"theme":{"$ref":"#/definitions/DotThemeType"}}},"DotThemeType":{"type":"object","additionalProperties":false,"properties":{"replace":{"type":"boolean"},"graph":{"type":"object"},"node":{"type":"object"},"edge":{"type":"object"},"modules":{"$ref":"#/definitions/DotThemeArrayType"},"dependencies":{"$ref":"#/definitions/DotThemeArrayType"}}},"DotThemeArrayType":{"type":"array","items":{"$ref":"#/definitions/DotThemeEntryType"}},"DotThemeEntryType":{"type":"object","additionalProperties":false,"properties":{"criteria":{"type":"object"},"attributes":{"type":"object"}}},"ReporterFiltersType":{"type":"object","additionalProperties":false,"properties":{"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"$ref":"#/definitions/CompoundIncludeOnlyType"},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"}}},"CacheOptionsType":{"type":"object","additionalProperties":false,"properties":{"folder":{"type":"string"},"strategy":{"$ref":"#/definitions/CacheStrategyType"},"compress":{"type":"boolean","default":false}}},"CacheStrategyType":{"type":"string","enum":["metadata","content"]},"RevisionDataType":{"type":"object","required":["SHA1","changes"],"properties":{"SHA1":{"type":"string"},"changes":{"type":"array","items":{"type":"object","required":["name","changeType"],"properties":{"name":{"type":"string"},"changeType":{"type":"string","enum":["added","copied","deleted","modified","renamed","type changed","unmerged","pairing broken","unknown","unmodified","untracked","ignored"]},"oldName":{"type":"string"},"checksum":{"type":"string"},"args":{"type":"array","items":{"type":"string"}},"rulesFile":{"type":"string"}}}}}}}}
\ No newline at end of file
+/* generated - don't edit */export default {"title":"dependency-cruiser output format","$schema":"http://json-schema.org/draft-07/schema#","$id":"https://dependency-cruiser.js.org/schema/cruise-result.schema.json","type":"object","required":["summary","modules"],"additionalProperties":false,"properties":{"modules":{"$ref":"#/definitions/ModulesType"},"folders":{"$ref":"#/definitions/FoldersType"},"summary":{"$ref":"#/definitions/SummaryType"},"revisionData":{"$ref":"#/definitions/RevisionDataType"}},"definitions":{"ModulesType":{"type":"array","items":{"$ref":"#/definitions/ModuleType"}},"ModuleType":{"type":"object","required":["source","dependencies","valid"],"additionalProperties":false,"properties":{"source":{"type":"string"},"valid":{"type":"boolean"},"dependencies":{"$ref":"#/definitions/DependenciesType"},"dependents":{"type":"array","items":{"type":"string"}},"followable":{"type":"boolean"},"matchesDoNotFollow":{"type":"boolean"},"matchesFocus":{"type":"boolean"},"matchesReaches":{"type":"boolean"},"matchesHighlight":{"type":"boolean"},"coreModule":{"type":"boolean"},"couldNotResolve":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"license":{"type":"string"},"orphan":{"type":"boolean"},"reachable":{"type":"array","items":{"$ref":"#/definitions/ReachableType"}},"reaches":{"type":"array","items":{"$ref":"#/definitions/ReachesType"}},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}},"consolidated":{"type":"boolean"},"instability":{"type":"number"},"checksum":{"type":"string"}}},"ReachableType":{"type":"object","required":["value","asDefinedInRule","matchedFrom"],"additionalProperties":false,"properties":{"value":{"type":"boolean"},"asDefinedInRule":{"type":"string"},"matchedFrom":{"type":"string"}}},"ReachesType":{"type":"object","required":["modules","asDefinedInRule"],"additionalProperties":false,"properties":{"modules":{"type":"array","items":{"type":"object","required":["source","via"],"additionalProperties":false,"properties":{"source":{"type":"string"},"via":{"type":"array","items":{"type":"string"}}}}},"asDefinedInRule":{"type":"string"}}},"DependenciesType":{"type":"array","items":{"$ref":"#/definitions/DependencyType"}},"DependencyType":{"type":"object","required":["circular","coreModule","couldNotResolve","dependencyTypes","exoticallyRequired","dynamic","followable","module","moduleSystem","resolved","valid"],"additionalProperties":false,"properties":{"module":{"type":"string"},"protocol":{"type":"string","enum":["data:","file:","node:"]},"mimeType":{"type":"string"},"resolved":{"type":"string"},"coreModule":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"license":{"type":"string"},"followable":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"type":"string"},"matchesDoNotFollow":{"type":"boolean"},"couldNotResolve":{"type":"boolean"},"preCompilationOnly":{"type":"boolean"},"typeOnly":{"type":"boolean"},"circular":{"type":"boolean"},"cycle":{"type":"array","items":{"$ref":"#/definitions/MiniDependency"}},"moduleSystem":{"$ref":"#/definitions/ModuleSystemType"},"valid":{"type":"boolean"},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}},"instability":{"type":"number"}}},"DependencyTypeType":{"type":"string","enum":["aliased-subpath-import","aliased-tsconfig-base-url","aliased-tsconfig-paths","aliased-tsconfig","aliased-webpack","aliased-workspace","aliased","amd-define","amd-require","amd-exotic-require","core","deprecated","dynamic-import","exotic-require","export","import-equals","import","local","localmodule","npm-bundled","npm-dev","npm-no-pkg","npm-optional","npm-peer","npm-unknown","npm","require","triple-slash-amd-dependency","triple-slash-directive","triple-slash-file-reference","triple-slash-type-reference","type-import","type-only","undetermined","unknown"]},"ModuleSystemType":{"type":"string","enum":["cjs","es6","amd","tsd"]},"RuleSummaryType":{"type":"object","required":["name","severity"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"}}},"SeverityType":{"type":"string","enum":["error","warn","info","ignore"]},"MiniDependency":{"type":"object","required":["name","dependencyTypes"],"additionalProperties":false,"properties":{"name":{"type":"string"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"FoldersType":{"type":"array","items":{"$ref":"#/definitions/FolderType"}},"FolderType":{"type":"object","required":["name","moduleCount"],"additionalProperties":false,"properties":{"name":{"type":"string"},"dependents":{"type":"array","items":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string"}}}},"dependencies":{"type":"array","items":{"type":"object","required":["name","valid","circular"],"additionalProperties":false,"properties":{"name":{"type":"string"},"instability":{"type":"number"},"valid":{"type":"boolean"},"circular":{"type":"boolean"},"cycle":{"type":"array","items":{"$ref":"#/definitions/MiniDependency"}},"rules":{"type":"array","items":{"$ref":"#/definitions/RuleSummaryType"}}}}},"moduleCount":{"type":"number"},"afferentCouplings":{"type":"number"},"efferentCouplings":{"type":"number"},"instability":{"type":"number"}}},"SummaryType":{"type":"object","required":["violations","error","warn","info","totalCruised","optionsUsed"],"additionalProperties":false,"properties":{"violations":{"$ref":"#/definitions/ViolationsType"},"error":{"type":"number"},"warn":{"type":"number"},"info":{"type":"number"},"ignore":{"type":"number"},"totalCruised":{"type":"number"},"totalDependenciesCruised":{"type":"number"},"ruleSetUsed":{"$ref":"#/definitions/RuleSetType"},"optionsUsed":{"$ref":"#/definitions/OptionsUsedType"}}},"ViolationsType":{"type":"array","items":{"$ref":"#/definitions/ViolationType"}},"ViolationType":{"type":"object","required":["from","to","rule"],"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"},"type":{"$ref":"#/definitions/ViolationTypeType"},"rule":{"$ref":"#/definitions/RuleSummaryType"},"cycle":{"type":"array","items":{"$ref":"#/definitions/MiniDependency"}},"via":{"type":"array","items":{"type":"string"}},"metrics":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}},"to":{"type":"object","required":["instability"],"additionalProperties":false,"properties":{"instability":{"type":"number"}}}}},"comment":{"type":"string"}}},"ViolationTypeType":{"type":"string","enum":["dependency","module","reachability","cycle","instability","folder"]},"RuleSetType":{"type":"object","additionalProperties":false,"properties":{"forbidden":{"type":"array","items":{"$ref":"#/definitions/ForbiddenRuleType"}},"allowed":{"type":"array","items":{"$ref":"#/definitions/AllowedRuleType"}},"allowedSeverity":{"$ref":"#/definitions/SeverityType"},"required":{"type":"array","items":{"$ref":"#/definitions/RequiredRuleType"}}}},"AllowedRuleType":{"oneOf":[{"$ref":"#/definitions/RegularAllowedRuleType"},{"$ref":"#/definitions/ReachabilityAllowedRuleType"}]},"RegularAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"ReachabilityAllowedRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"comment":{"type":"string"},"scope":{"type":"string","enum":["module","folder"]},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"ForbiddenRuleType":{"oneOf":[{"$ref":"#/definitions/RegularForbiddenRuleType"},{"$ref":"#/definitions/ReachabilityForbiddenRuleType"},{"$ref":"#/definitions/DependentsForbiddenRuleType"}]},"RegularForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/FromRestrictionType"},"to":{"$ref":"#/definitions/ToRestrictionType"}}},"DependentsForbiddenRuleType":{"type":"object","required":["module","from"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/DependentsModuleRestrictionType"},"from":{"$ref":"#/definitions/DependentsFromRestrictionType"}}},"ReachabilityForbiddenRuleType":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"from":{"$ref":"#/definitions/ReachabilityFromRestrictionType"},"to":{"$ref":"#/definitions/ReachabilityToRestrictionType"}}},"RequiredRuleType":{"type":"object","required":["module","to"],"additionalProperties":false,"properties":{"name":{"type":"string"},"severity":{"$ref":"#/definitions/SeverityType"},"scope":{"type":"string","enum":["module","folder"]},"comment":{"type":"string"},"module":{"$ref":"#/definitions/RequiredModuleRestrictionType"},"to":{"$ref":"#/definitions/RequiredToRestrictionType"}}},"FromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"orphan":{"type":"boolean"}}},"ReachabilityFromRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ToRestrictionType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"couldNotResolve":{"type":"boolean"},"circular":{"type":"boolean"},"dynamic":{"type":"boolean"},"exoticallyRequired":{"type":"boolean"},"exoticRequire":{"$ref":"#/definitions/REAsStringsType"},"exoticRequireNot":{"$ref":"#/definitions/REAsStringsType"},"preCompilationOnly":{"type":"boolean"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"dependencyTypesNot":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}},"moreThanOneDependencyType":{"type":"boolean"},"license":{"$ref":"#/definitions/REAsStringsType"},"licenseNot":{"$ref":"#/definitions/REAsStringsType"},"via":{"$ref":"#/definitions/REAsStringsType"},"viaOnly":{"$ref":"#/definitions/REAsStringsType"},"viaNot":{"$ref":"#/definitions/REAsStringsType"},"viaSomeNot":{"$ref":"#/definitions/REAsStringsType"},"moreUnstable":{"type":"boolean"}}},"DependentsModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"numberOfDependentsLessThan":{"type":"integer","minimum":0,"maximum":100},"numberOfDependentsMoreThan":{"type":"integer","minimum":0,"maximum":100}}},"DependentsFromRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"ReachabilityToRestrictionType":{"required":["reachable"],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"},"reachable":{"type":"boolean"}}},"RequiredModuleRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"pathNot":{"$ref":"#/definitions/REAsStringsType"}}},"RequiredToRestrictionType":{"required":[],"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"REAsStringsType":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"OptionsUsedType":{"type":"object","additionalProperties":false,"properties":{"doNotFollow":{"$ref":"#/definitions/CompoundDoNotFollowType"},"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"oneOf":[{"$ref":"#/definitions/REAsStringsType"},{"$ref":"#/definitions/CompoundIncludeOnlyType"}]},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"},"highlight":{"$ref":"#/definitions/CompoundHighlightType"},"knownViolations":{"$ref":"#/definitions/ViolationsType"},"collapse":{"type":"string"},"maxDepth":{"type":"integer","minimum":0,"maximum":99},"moduleSystems":{"$ref":"#/definitions/ModuleSystemsType"},"prefix":{"type":"string"},"preserveSymlinks":{"type":"boolean"},"combinedDependencies":{"type":"boolean"},"tsConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"tsPreCompilationDeps":{"oneOf":[{"type":"boolean"},{"type":"string","enum":["specify"]}]},"extraExtensionsToScan":{"type":"array","items":{"type":"string"}},"externalModuleResolutionStrategy":{"type":"string","enum":["node_modules","yarn-pnp"]},"builtInModules":{"type":"object","additionalProperties":false,"properties":{"override":{"type":"array","items":{"type":"string"}},"add":{"type":"array","items":{"type":"string"}}}},"forceDeriveDependents":{"type":"boolean"},"webpackConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"},"env":{"oneOf":[{"type":"object"},{"type":"string"}]},"arguments":{"type":"object"}}},"enhancedResolveOptions":{"type":"object","additionalProperties":false,"properties":{"exportsFields":{"type":"array","items":{"type":"string"}},"conditionNames":{"type":"array","items":{"type":"string"}},"extensions":{"type":"array","items":{"type":"string"}},"mainFields":{"type":"array","items":{"type":"string"}},"mainFiles":{"type":"array"},"aliasFields":{"type":"array","items":{"type":"string"}},"cachedInputFileSystem":{"type":"object","additionalProperties":false,"properties":{"cacheDuration":{"type":"integer","minimum":0,"maximum":1800000}}}}},"babelConfig":{"type":"object","additionalProperties":false,"properties":{"fileName":{"type":"string"}}},"parser":{"type":"string","enum":["acorn","swc","tsc"]},"exoticRequireStrings":{"type":"array","items":{"type":"string"}},"reporterOptions":{"$ref":"#/definitions/ReporterOptionsType"},"progress":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["cli-feedback","performance-log","ndjson","none"]},"maximumLevel":{"type":"number","enum":[-1,40,50,60,70,80,99]}}},"metrics":{"type":"boolean"},"baseDir":{"type":"string"},"cache":{"oneOf":[{"type":"boolean","enum":[false]},{"$ref":"#/definitions/CacheOptionsType"}]},"args":{"type":"string"},"rulesFile":{"type":"string"},"outputTo":{"type":"string"},"outputType":{"$ref":"#/definitions/OutputType"}}},"ModuleSystemsType":{"type":"array","items":{"$ref":"#/definitions/ModuleSystemType"}},"OutputType":{"oneOf":[{"type":"string","enum":["json","html","dot","ddot","cdot","archi","fdot","flat","csv","err","err-long","err-html","teamcity","anon","text","metrics","markdown","mermaid","d2","null"]},{"type":"string","pattern":"^plugin:[^:]+$"}]},"CompoundExcludeType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dynamic":{"type":"boolean"}}},"CompoundDoNotFollowType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"dependencyTypes":{"type":"array","items":{"$ref":"#/definitions/DependencyTypeType"}}}},"CompoundIncludeOnlyType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundFocusType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"},"depth":{"type":"number","minimum":1,"maximum":4}}},"CompoundReachesType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"CompoundHighlightType":{"type":"object","additionalProperties":false,"properties":{"path":{"$ref":"#/definitions/REAsStringsType"}}},"ReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"anon":{"$ref":"#/definitions/AnonReporterOptionsType"},"archi":{"$ref":"#/definitions/DotReporterOptionsType"},"dot":{"$ref":"#/definitions/DotReporterOptionsType"},"ddot":{"$ref":"#/definitions/DotReporterOptionsType"},"flat":{"$ref":"#/definitions/DotReporterOptionsType"},"markdown":{"$ref":"#/definitions/MarkdownReporterOptionsType"},"metrics":{"$ref":"#/definitions/MetricsReporterOptionsType"},"mermaid":{"$ref":"#/definitions/MermaidReporterOptionsType"},"text":{"$ref":"#/definitions/TextReporterOptionsType"}}},"AnonReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"wordlist":{"type":"array","items":{"type":"string"}}}},"MetricsReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"orderBy":{"type":"string","enum":["instability","moduleCount","afferentCouplings","efferentCouplings","name"]},"hideModules":{"type":"boolean"},"hideFolders":{"type":"boolean"}}},"MarkdownReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"showTitle":{"type":"boolean"},"title":{"type":"string"},"showSummary":{"type":"boolean"},"showSummaryHeader":{"type":"boolean"},"summaryHeader":{"type":"string"},"showStatsSummary":{"type":"boolean"},"showRulesSummary":{"type":"boolean"},"includeIgnoredInSummary":{"type":"boolean"},"showDetails":{"type":"boolean"},"includeIgnoredInDetails":{"type":"boolean"},"showDetailsHeader":{"type":"boolean"},"detailsHeader":{"type":"string"},"collapseDetails":{"type":"boolean"},"collapsedMessage":{"type":"string"},"noViolationsMessage":{"type":"string"},"showFooter":{"type":"boolean"}}},"MermaidReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"minify":{"type":"boolean"}}},"TextReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"highlightFocused":{"type":"boolean"}}},"DotReporterOptionsType":{"type":"object","additionalProperties":false,"properties":{"collapsePattern":{"$ref":"#/definitions/REAsStringsType"},"filters":{"$ref":"#/definitions/ReporterFiltersType"},"showMetrics":{"type":"boolean"},"theme":{"$ref":"#/definitions/DotThemeType"}}},"DotThemeType":{"type":"object","additionalProperties":false,"properties":{"replace":{"type":"boolean"},"graph":{"type":"object"},"node":{"type":"object"},"edge":{"type":"object"},"modules":{"$ref":"#/definitions/DotThemeArrayType"},"dependencies":{"$ref":"#/definitions/DotThemeArrayType"}}},"DotThemeArrayType":{"type":"array","items":{"$ref":"#/definitions/DotThemeEntryType"}},"DotThemeEntryType":{"type":"object","additionalProperties":false,"properties":{"criteria":{"type":"object"},"attributes":{"type":"object"}}},"ReporterFiltersType":{"type":"object","additionalProperties":false,"properties":{"exclude":{"$ref":"#/definitions/CompoundExcludeType"},"includeOnly":{"$ref":"#/definitions/CompoundIncludeOnlyType"},"focus":{"$ref":"#/definitions/CompoundFocusType"},"reaches":{"$ref":"#/definitions/CompoundReachesType"}}},"CacheOptionsType":{"type":"object","additionalProperties":false,"properties":{"folder":{"type":"string"},"strategy":{"$ref":"#/definitions/CacheStrategyType"},"compress":{"type":"boolean","default":false}}},"CacheStrategyType":{"type":"string","enum":["metadata","content"]},"RevisionDataType":{"type":"object","required":["SHA1","changes"],"properties":{"SHA1":{"type":"string"},"changes":{"type":"array","items":{"type":"object","required":["name","changeType"],"properties":{"name":{"type":"string"},"changeType":{"type":"string","enum":["added","copied","deleted","modified","renamed","type changed","unmerged","pairing broken","unknown","unmodified","untracked","ignored"]},"oldName":{"type":"string"},"checksum":{"type":"string"},"args":{"type":"array","items":{"type":"string"}},"rulesFile":{"type":"string"}}}}}}}}
\ No newline at end of file
diff --git a/src/validate/matchers.mjs b/src/validate/matchers.mjs
index 43184bba..d362656d 100644
--- a/src/validate/matchers.mjs
+++ b/src/validate/matchers.mjs
@@ -107,14 +107,18 @@ function toDependencyTypesNot(pRule, pDependency) {
       !intersects(pDependency.dependencyTypes, pRule.to.dependencyTypesNot),
   );
 }
-
+function pluckName({ name }) {
+  return name;
+}
 function toVia(pRule, pDependency, pGroups) {
   return Boolean(
     !pRule.to.via ||
       (pDependency.cycle &&
-        pDependency.cycle.some((pVia) =>
-          pVia.match(replaceGroupPlaceholders(pRule.to.via, pGroups)),
-        )),
+        pDependency.cycle
+          .map(pluckName)
+          .some((pVia) =>
+            pVia.match(replaceGroupPlaceholders(pRule.to.via, pGroups)),
+          )),
   );
 }
 
@@ -122,9 +126,11 @@ function toViaOnly(pRule, pDependency, pGroups) {
   return Boolean(
     !pRule.to.viaOnly ||
       (pDependency.cycle &&
-        pDependency.cycle.every((pVia) =>
-          pVia.match(replaceGroupPlaceholders(pRule.to.viaOnly, pGroups)),
-        )),
+        pDependency.cycle
+          .map(pluckName)
+          .every((pVia) =>
+            pVia.match(replaceGroupPlaceholders(pRule.to.viaOnly, pGroups)),
+          )),
   );
 }
 
@@ -132,9 +138,11 @@ function toViaNot(pRule, pDependency, pGroups) {
   return Boolean(
     !pRule.to.viaNot ||
       (pDependency.cycle &&
-        !pDependency.cycle.some((pVia) =>
-          pVia.match(replaceGroupPlaceholders(pRule.to.viaNot, pGroups)),
-        )),
+        !pDependency.cycle
+          .map(pluckName)
+          .some((pVia) =>
+            pVia.match(replaceGroupPlaceholders(pRule.to.viaNot, pGroups)),
+          )),
   );
 }
 
@@ -142,9 +150,11 @@ function toviaSomeNot(pRule, pDependency, pGroups) {
   return Boolean(
     !pRule.to.viaSomeNot ||
       (pDependency.cycle &&
-        !pDependency.cycle.every((pVia) =>
-          pVia.match(replaceGroupPlaceholders(pRule.to.viaSomeNot, pGroups)),
-        )),
+        !pDependency.cycle
+          .map(pluckName)
+          .every((pVia) =>
+            pVia.match(replaceGroupPlaceholders(pRule.to.viaSomeNot, pGroups)),
+          )),
   );
 }
 
diff --git a/tools/schema/dependencies.mjs b/tools/schema/dependencies.mjs
index 465300fd..0df7a70e 100644
--- a/tools/schema/dependencies.mjs
+++ b/tools/schema/dependencies.mjs
@@ -1,6 +1,7 @@
 import dependencyType from "./dependency-type.mjs";
 import moduleSystemType from "./module-system-type.mjs";
 import ruleSummary from "./rule-summary.mjs";
+import miniDependency from "./mini-dependency-type.mjs";
 
 export default {
   definitions: {
@@ -137,7 +138,7 @@ export default {
         },
         cycle: {
           type: "array",
-          items: { type: "string" },
+          items: { $ref: "#/definitions/MiniDependency" },
           description:
             "If following this dependency will ultimately return to the source " +
             "(circular === true), this attribute will contain an (ordered) array " +
@@ -168,5 +169,6 @@ export default {
     ...dependencyType.definitions,
     ...moduleSystemType.definitions,
     ...ruleSummary.definitions,
+    ...miniDependency.definitions,
   },
 };
diff --git a/tools/schema/folders.mjs b/tools/schema/folders.mjs
index ff75306e..8031340f 100644
--- a/tools/schema/folders.mjs
+++ b/tools/schema/folders.mjs
@@ -1,4 +1,5 @@
 import ruleSummary from "./rule-summary.mjs";
+import miniDependency from "./mini-dependency-type.mjs";
 
 export default {
   definitions: {
@@ -73,7 +74,7 @@ export default {
               },
               cycle: {
                 type: "array",
-                items: { type: "string" },
+                items: { $ref: "#/definitions/MiniDependency" },
                 description:
                   "If following this dependency will ultimately return to the source " +
                   "(circular === true), this attribute will contain an (ordered) array " +
@@ -123,5 +124,6 @@ export default {
       },
     },
     ...ruleSummary.definitions,
+    ...miniDependency.definitions,
   },
 };
diff --git a/tools/schema/mini-dependency-type.mjs b/tools/schema/mini-dependency-type.mjs
new file mode 100644
index 00000000..6d5d1dfc
--- /dev/null
+++ b/tools/schema/mini-dependency-type.mjs
@@ -0,0 +1,29 @@
+import dependencyType from "./dependency-type.mjs";
+
+export default {
+  definitions: {
+    MiniDependency: {
+      type: "object",
+      description:
+        "A small dependency object with the uniquely identifying name of the module +" +
+        "the dependency types it has relative to the _previous_ module in the chain " +
+        " it is part of (e.g. a cycle).",
+      required: ["name", "dependencyTypes"],
+      additionalProperties: false,
+      properties: {
+        name: {
+          type: "string",
+          description: "The name of the module",
+        },
+        dependencyTypes: {
+          type: "array",
+          items: { $ref: "#/definitions/DependencyTypeType" },
+          description:
+            "The dependency types of the module relative to the previous module " +
+            "in the chain it is a part of (e.g. a cycle)",
+        },
+      },
+    },
+    ...dependencyType.definitions,
+  },
+};
diff --git a/tools/schema/violations.mjs b/tools/schema/violations.mjs
index e3a0bf37..2b9641f6 100644
--- a/tools/schema/violations.mjs
+++ b/tools/schema/violations.mjs
@@ -1,5 +1,6 @@
 import ruleSummary from "./rule-summary.mjs";
 import violationType from "./violation-type.mjs";
+import miniDependency from "./mini-dependency-type.mjs";
 
 export default {
   definitions: {
@@ -25,7 +26,7 @@ export default {
         rule: { $ref: "#/definitions/RuleSummaryType" },
         cycle: {
           type: "array",
-          items: { type: "string" },
+          items: { $ref: "#/definitions/MiniDependency" },
           description:
             "The circular path if the violation is about circularity",
         },
@@ -68,5 +69,6 @@ export default {
     },
     ...ruleSummary.definitions,
     ...violationType.definitions,
+    ...miniDependency.definitions,
   },
 };
diff --git a/types/cruise-result.d.mts b/types/cruise-result.d.mts
index a8786dcc..9aa522af 100644
--- a/types/cruise-result.d.mts
+++ b/types/cruise-result.d.mts
@@ -1,6 +1,7 @@
 import type { ICruiseOptions } from "./options.mjs";
 import type { IFlattenedRuleSet } from "./rule-set.mjs";
 import type {
+  IMiniDependency,
   DependencyType,
   ModuleSystemType,
   ProtocolType,
@@ -188,7 +189,7 @@ export interface IDependency {
    * this attribute will contain an (ordered) array of module names that shows (one of) the
    * circular path(s)
    */
-  cycle?: string[];
+  cycle?: IMiniDependency[];
   /**
    * the type of inclusion - local, core, unknown (= we honestly don't know), undetermined (=
    * we didn't bother determining it) or one of the npm dependencies defined in a package.json
@@ -391,7 +392,7 @@ export interface IFolderDependency {
    * this attribute will contain an (ordered) array of module names that shows (one of) the
    * circular path(s)
    */
-  cycle?: string[];
+  cycle?: IMiniDependency[];
   /**
    * an array of rules violated by this dependency - left out if the dependency
    * is valid
diff --git a/types/shared-types.d.mts b/types/shared-types.d.mts
index d10ed812..9fc966ea 100644
--- a/types/shared-types.d.mts
+++ b/types/shared-types.d.mts
@@ -81,3 +81,15 @@ export type ViolationType =
   | "instability";
 
 export type RuleScopeType = "module" | "folder";
+
+export interface IMiniDependency {
+  /**
+   * The name of the module
+   */
+  name: string;
+  /**
+   * The dependency types of the module relative to the previous module " +
+   * in the chain it is a part of (e.g. a cycle)
+   */
+  dependencyTypes: DependencyType[];
+}
diff --git a/types/violations.d.mts b/types/violations.d.mts
index 0387de3e..bcee2131 100644
--- a/types/violations.d.mts
+++ b/types/violations.d.mts
@@ -1,5 +1,5 @@
 import type { IRuleSummary } from "./rule-summary.mjs";
-import type { ViolationType } from "./shared-types.mjs";
+import type { IMiniDependency, ViolationType } from "./shared-types.mjs";
 
 export interface IMetricsSummary {
   from: {
@@ -30,7 +30,7 @@ export interface IViolation {
   /**
    * The circular path if the violation is about circularity
    */
-  cycle?: string[];
+  cycle?: IMiniDependency[];
   /**
    * The path from the from to the to if the violation is transitive
    */


Test patch:
diff --git a/test/cli/__fixtures__/result-has-a-dependency-violation.json b/test/cli/__fixtures__/result-has-a-dependency-violation.json
index 314b372a..50102032 100644
--- a/test/cli/__fixtures__/result-has-a-dependency-violation.json
+++ b/test/cli/__fixtures__/result-has-a-dependency-violation.json
@@ -8605,7 +8605,10 @@
           "name": "src/extract/transpile",
           "instability": 0.6153846153846154,
           "circular": true,
-          "cycle": ["src/extract/transpile", "src/extract/parse"],
+          "cycle": [
+            { "name": "src/extract/transpile", "dependencyTypes": [] },
+            { "name": "src/extract/parse", "dependencyTypes": [] }
+          ],
           "valid": true
         },
         {
@@ -8647,7 +8650,10 @@
           "name": "src/extract/parse",
           "instability": 0.46153846153846156,
           "circular": true,
-          "cycle": ["src/extract/parse", "src/extract/transpile"],
+          "cycle": [
+            { "name": "src/extract/parse", "dependencyTypes": [] },
+            { "name": "src/extract/transpile", "dependencyTypes": [] }
+          ],
           "valid": true
         }
       ],
diff --git a/test/enrich/__mocks__/cycle-fest.mjs b/test/enrich/__mocks__/cycle-fest.mjs
index 111bfa7d..16c9fa68 100644
--- a/test/enrich/__mocks__/cycle-fest.mjs
+++ b/test/enrich/__mocks__/cycle-fest.mjs
@@ -14,7 +14,11 @@ export default [
         exoticallyRequired: false,
         matchesDoNotFollow: false,
         circular: true,
-        cycle: ["src/domain.js", "src/market.js", "src/brand.js"],
+        cycle: [
+          { name: "src/domain.js", dependencyTypes: ["local"] },
+          { name: "src/market.js", dependencyTypes: ["local"] },
+          { name: "src/brand.js", dependencyTypes: ["local"] },
+        ],
         valid: false,
         rules: [
           {
@@ -35,7 +39,10 @@ export default [
         exoticallyRequired: false,
         matchesDoNotFollow: false,
         circular: true,
-        cycle: ["src/market.js", "src/brand.js"],
+        cycle: [
+          { name: "src/market.js", dependencyTypes: ["local"] },
+          { name: "src/brand.js", dependencyTypes: ["local"] },
+        ],
         valid: false,
         rules: [
           {
@@ -63,7 +70,10 @@ export default [
         exoticallyRequired: false,
         matchesDoNotFollow: false,
         circular: true,
-        cycle: ["src/market.js", "src/domain.js"],
+        cycle: [
+          { name: "src/market.js", dependencyTypes: ["local"] },
+          { name: "src/domain.js", dependencyTypes: ["local"] },
+        ],
         valid: false,
         rules: [
           {
@@ -91,7 +101,10 @@ export default [
         exoticallyRequired: false,
         matchesDoNotFollow: false,
         circular: true,
-        cycle: ["src/brand.js", "src/market.js"],
+        cycle: [
+          { name: "src/brand.js", dependencyTypes: ["local"] },
+          { name: "src/market.js", dependencyTypes: ["local"] },
+        ],
         valid: false,
         rules: [
           {
@@ -112,7 +125,10 @@ export default [
         exoticallyRequired: false,
         matchesDoNotFollow: false,
         circular: true,
-        cycle: ["src/domain.js", "src/market.js"],
+        cycle: [
+          { name: "src/domain.js", dependencyTypes: ["local"] },
+          { name: "src/market.js", dependencyTypes: ["local"] },
+        ],
         valid: false,
         rules: [
           {
diff --git a/test/enrich/de-duplicate-violations.spec.mjs b/test/enrich/de-duplicate-violations.spec.mjs
index a8f867f8..b4d37471 100644
--- a/test/enrich/de-duplicate-violations.spec.mjs
+++ b/test/enrich/de-duplicate-violations.spec.mjs
@@ -39,7 +39,16 @@ describe("[U] enrich/de-duplicate-violations", () => {
           severity: "error",
           name: "no-circular",
         },
-        cycle: ["src/report/not/module-utl.js", "src/report/not/index.js"],
+        cycle: [
+          {
+            name: "src/report/not/module-utl.js",
+            dependencyTypes: ["local", "require"],
+          },
+          {
+            name: "src/report/not/index.js",
+            dependencyTypes: ["local", "require"],
+          },
+        ],
       },
       {
         from: "src/report/dot/module-utl.js",
@@ -48,7 +57,16 @@ describe("[U] enrich/de-duplicate-violations", () => {
           severity: "error",
           name: "no-circular",
         },
-        cycle: ["src/report/dot/index.js", "src/report/dot/module-utl.js"],
+        cycle: [
+          {
+            name: "src/report/dot/index.js",
+            dependencyTypes: ["local", "require"],
+          },
+          {
+            name: "src/report/dot/module-utl.js",
+            dependencyTypes: ["local", "require"],
+          },
+        ],
       },
     ];
     deepEqual(deDuplicateViolations(lViolations), lViolations);
@@ -63,7 +81,16 @@ describe("[U] enrich/de-duplicate-violations", () => {
           severity: "error",
           name: "no-circular",
         },
-        cycle: ["src/report/dot/module-utl.js", "src/report/dot/index.js"],
+        cycle: [
+          {
+            name: "src/report/dot/module-utl.js",
+            dependencyTypes: ["local", "require"],
+          },
+          {
+            name: "src/report/dot/index.js",
+            dependencyTypes: ["local", "require"],
+          },
+        ],
       },
       {
         from: "src/report/dot/module-utl.js",
@@ -72,7 +99,16 @@ describe("[U] enrich/de-duplicate-violations", () => {
           severity: "error",
           name: "no-circular",
         },
-        cycle: ["src/report/dot/index.js", "src/report/dot/module-utl.js"],
+        cycle: [
+          {
+            name: "src/report/dot/index.js",
+            dependencyTypes: ["local", "require"],
+          },
+          {
+            name: "src/report/dot/module-utl.js",
+            dependencyTypes: ["local", "require"],
+          },
+        ],
       },
     ];
     const lDeDuplicatedViolations = [
@@ -83,7 +119,16 @@ describe("[U] enrich/de-duplicate-violations", () => {
           severity: "error",
           name: "no-circular",
         },
-        cycle: ["src/report/dot/module-utl.js", "src/report/dot/index.js"],
+        cycle: [
+          {
+            name: "src/report/dot/module-utl.js",
+            dependencyTypes: ["local", "require"],
+          },
+          {
+            name: "src/report/dot/index.js",
+            dependencyTypes: ["local", "require"],
+          },
+        ],
       },
     ];
     deepEqual(deDuplicateViolations(lViolations), lDeDuplicatedViolations);
@@ -98,7 +143,16 @@ describe("[U] enrich/de-duplicate-violations", () => {
           severity: "error",
           name: "no-ride-the-lightning",
         },
-        cycle: ["src/report/dot/module-utl.js", "src/report/dot/index.js"],
+        cycle: [
+          {
+            name: "src/report/dot/module-utl.js",
+            dependencyTypes: ["local", "require"],
+          },
+          {
+            name: "src/report/dot/index.js",
+            dependencyTypes: ["local", "require"],
+          },
+        ],
       },
       {
         from: "src/report/dot/module-utl.js",
@@ -107,7 +161,16 @@ describe("[U] enrich/de-duplicate-violations", () => {
           severity: "error",
           name: "no-circular",
         },
-        cycle: ["src/report/dot/index.js", "src/report/dot/module-utl.js"],
+        cycle: [
+          {
+            name: "src/report/dot/index.js",
+            dependencyTypes: ["local", "require"],
+          },
+          {
+            name: "src/report/dot/module-utl.js",
+            dependencyTypes: ["local", "require"],
+          },
+        ],
       },
     ];
     deepEqual(deDuplicateViolations(lViolations), lViolations);
@@ -130,7 +193,16 @@ describe("[U] enrich/de-duplicate-violations", () => {
           severity: "error",
           name: "no-circular",
         },
-        cycle: ["src/report/dot/module-utl.js", "src/report/dot/index.js"],
+        cycle: [
+          {
+            name: "src/report/dot/module-utl.js",
+            dependencyTypes: ["local", "require"],
+          },
+          {
+            name: "src/report/dot/index.js",
+            dependencyTypes: ["local", "require"],
+          },
+        ],
       },
       {
         from: "src/report/dot/module-utl.js",
@@ -139,7 +211,16 @@ describe("[U] enrich/de-duplicate-violations", () => {
           severity: "error",
           name: "no-circular",
         },
-        cycle: ["src/report/dot/index.js", "src/report/dot/module-utl.js"],
+        cycle: [
+          {
+            name: "src/report/dot/index.js",
+            dependencyTypes: ["local", "require"],
+          },
+          {
+            name: "src/report/dot/module-utl.js",
+            dependencyTypes: ["local", "require"],
+          },
+        ],
       },
     ];
     const lDeDuplicatedViolations = [
@@ -158,7 +239,16 @@ describe("[U] enrich/de-duplicate-violations", () => {
           severity: "error",
           name: "no-circular",
         },
-        cycle: ["src/report/dot/module-utl.js", "src/report/dot/index.js"],
+        cycle: [
+          {
+            name: "src/report/dot/module-utl.js",
+            dependencyTypes: ["local", "require"],
+          },
+          {
+            name: "src/report/dot/index.js",
+            dependencyTypes: ["local", "require"],
+          },
+        ],
       },
     ];
     deepEqual(deDuplicateViolations(lViolations), lDeDuplicatedViolations);
diff --git a/test/enrich/summarize.spec.mjs b/test/enrich/summarize.spec.mjs
index 9ebebc6e..351db3a5 100644
--- a/test/enrich/summarize.spec.mjs
+++ b/test/enrich/summarize.spec.mjs
@@ -92,7 +92,20 @@ describe("[I] enrich/summarize", () => {
             severity: "warn",
             name: "no-circular",
           },
-          cycle: ["src/domain.js", "src/market.js", "src/brand.js"],
+          cycle: [
+            {
+              name: "src/domain.js",
+              dependencyTypes: ["local"],
+            },
+            {
+              name: "src/market.js",
+              dependencyTypes: ["local"],
+            },
+            {
+              name: "src/brand.js",
+              dependencyTypes: ["local"],
+            },
+          ],
         },
         {
           type: "cycle",
@@ -102,7 +115,16 @@ describe("[I] enrich/summarize", () => {
             severity: "warn",
             name: "no-circular",
           },
-          cycle: ["src/market.js", "src/brand.js"],
+          cycle: [
+            {
+              name: "src/market.js",
+              dependencyTypes: ["local"],
+            },
+            {
+              name: "src/brand.js",
+              dependencyTypes: ["local"],
+            },
+          ],
         },
         {
           type: "cycle",
@@ -112,7 +134,16 @@ describe("[I] enrich/summarize", () => {
             severity: "warn",
             name: "no-circular",
           },
-          cycle: ["src/market.js", "src/domain.js"],
+          cycle: [
+            {
+              name: "src/market.js",
+              dependencyTypes: ["local"],
+            },
+            {
+              name: "src/domain.js",
+              dependencyTypes: ["local"],
+            },
+          ],
         },
       ],
       error: 0,
@@ -137,6 +168,7 @@ describe("[I] enrich/summarize", () => {
         ],
       },
     };
+
     const lSummary = summarize(cycleFest, lOptions, ["src"]);
     deepEqual(lSummary, lExpected);
     ajv.validate(cruiseResultSchema, { modules: [], summary: lSummary });
diff --git a/test/graph-utl/__mocks__/cycle-input-graphs.mjs b/test/graph-utl/__mocks__/cycle-input-graphs.mjs
index b7bf7961..a7769a4b 100644
--- a/test/graph-utl/__mocks__/cycle-input-graphs.mjs
+++ b/test/graph-utl/__mocks__/cycle-input-graphs.mjs
@@ -5,6 +5,7 @@ export default {
       dependencies: [
         {
           resolved: "b",
+          dependencyTypes: ["npm"],
         },
       ],
     },
@@ -29,7 +30,14 @@ export default {
       dependencies: [
         {
           resolved: "e",
-          dependencyTypes: ["aliased", "aliased-subpath-import", "local"],
+          exoticallyRequired: false,
+          moduleSystem: "es6",
+          dependencyTypes: [
+            "aliased",
+            "aliased-subpath-import",
+            "local",
+            "import",
+          ],
         },
       ],
     },
@@ -38,6 +46,9 @@ export default {
       dependencies: [
         {
           resolved: "d",
+          exoticallyRequired: false,
+          moduleSystem: "es6",
+          dependencyTypes: ["local", "import"],
         },
       ],
     },
@@ -48,6 +59,7 @@ export default {
       dependencies: [
         {
           resolved: "r",
+          dependencyTypes: ["local"],
         },
       ],
     },
@@ -56,6 +68,7 @@ export default {
       dependencies: [
         {
           resolved: "s",
+          dependencyTypes: ["local"],
         },
       ],
     },
@@ -64,6 +77,7 @@ export default {
       dependencies: [
         {
           resolved: "q",
+          dependencyTypes: ["local"],
         },
       ],
     },
@@ -74,9 +88,11 @@ export default {
       dependencies: [
         {
           resolved: "u",
+          dependencyTypes: ["local"],
         },
         {
           resolved: "v",
+          dependencyTypes: ["npm"],
         },
       ],
     },
@@ -85,6 +101,7 @@ export default {
       dependencies: [
         {
           resolved: "t",
+          dependencyTypes: ["local"],
         },
       ],
     },
@@ -216,21 +233,16 @@ export default {
         {
           resolved: "b",
         },
-      ],
-    },
-    {
-      source: "b",
-      dependencies: [
         {
-          resolved: "a",
+          resolved: "c",
         },
       ],
     },
     {
-      source: "a",
+      source: "b",
       dependencies: [
         {
-          resolved: "c",
+          resolved: "a",
         },
       ],
     },
diff --git a/test/graph-utl/indexed-module-graph.spec.mjs b/test/graph-utl/indexed-module-graph.spec.mjs
index 86b6f0a6..3b9f5594 100644
--- a/test/graph-utl/indexed-module-graph.spec.mjs
+++ b/test/graph-utl/indexed-module-graph.spec.mjs
@@ -408,10 +408,10 @@ describe("[U] graph-utl/indexed-module-graph - getPath", () => {
 
 function getCycle(pGraph, pFrom, pToDep) {
   const lIndexedGraph = new IndexedModuleGraph(pGraph);
-  return lIndexedGraph.getCycle(pFrom, pToDep);
+  return lIndexedGraph.getCycle(pFrom, pToDep).map(({ name }) => name);
 }
 
-describe("[U] graph-utl/indexed-module-graph - getCycle", () => {
+describe("[U] graph-utl/indexed-module-graph - getCycle (algorithm check)", () => {
   it("leaves non circular dependencies alone", () => {
     deepEqual(getCycle(cycleInputGraphs.A_B, "a", "b"), []);
   });
@@ -476,4 +476,46 @@ describe("[U] graph-utl/indexed-module-graph - getCycle", () => {
   it("just returns one cycle when querying a hub node", () => {
     deepEqual(getCycle(cycleInputGraphs.FLOWER, "a", "b"), ["b", "a"]);
   });
+  it("if the 'to' node is not in the graph, it returns []", () => {
+    deepEqual(getCycle(cycleInputGraphs.D_E_D, "d", "not-in-graph"), []);
+  });
+});
+
+function getCycleRich(pGraph, pFrom, pToDep) {
+  const lIndexedGraph = new IndexedModuleGraph(pGraph);
+  return lIndexedGraph.getCycle(pFrom, pToDep);
+}
+
+describe("[U] graph-utl/indexed-module-graph - getCycle (verify the necessary attributes are there)", () => {
+  it("returns the cycle with the 'name' and 'dependencyTypes' attributes added (and none else)", () => {
+    const lCycle = getCycleRich(cycleInputGraphs.D_E_D, "d", "e");
+    deepEqual(lCycle, [
+      {
+        name: "e",
+        dependencyTypes: [
+          "aliased",
+          "aliased-subpath-import",
+          "local",
+          "import",
+        ],
+      },
+      {
+        name: "d",
+        dependencyTypes: ["local", "import"],
+      },
+    ]);
+  });
+  it("returns the cycle with the 'name' and 'dependencyTypes' attributes even when dependencyTypes wasn't defined", () => {
+    const lCycle = getCycleRich(cycleInputGraphs.FLOWER, "a", "b");
+    deepEqual(lCycle, [
+      {
+        name: "b",
+        dependencyTypes: [],
+      },
+      {
+        name: "a",
+        dependencyTypes: [],
+      },
+    ]);
+  });
 });
diff --git a/test/main/__fixtures__/cruise-reporterless/commonjs.json b/test/main/__fixtures__/cruise-reporterless/commonjs.json
index 697bde7b..d07f3d76 100644
--- a/test/main/__fixtures__/cruise-reporterless/commonjs.json
+++ b/test/main/__fixtures__/cruise-reporterless/commonjs.json
@@ -759,8 +759,14 @@
             "valid": false,
             "circular": true,
             "cycle": [
-              "test/main/__mocks__/cruise-reporterless/commonjs/ralucric.js",
-              "test/main/__mocks__/cruise-reporterless/commonjs/circular.js"
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/ralucric.js",
+                "dependencyTypes": ["local", "require"]
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circular.js",
+                "dependencyTypes": ["local", "require"]
+              }
             ],
             "rules": [
               {
@@ -802,8 +808,14 @@
             "valid": false,
             "circular": true,
             "cycle": [
-              "test/main/__mocks__/cruise-reporterless/commonjs/circular.js",
-              "test/main/__mocks__/cruise-reporterless/commonjs/ralucric.js"
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circular.js",
+                "dependencyTypes": ["local", "require"]
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/ralucric.js",
+                "dependencyTypes": ["local", "require"]
+              }
             ],
             "rules": [
               {
@@ -866,9 +878,18 @@
             "valid": true,
             "circular": true,
             "cycle": [
-              "test/main/__mocks__/cruise-reporterless/commonjs/circle-two.js",
-              "test/main/__mocks__/cruise-reporterless/commonjs/circle-three.js",
-              "test/main/__mocks__/cruise-reporterless/commonjs/circle-one.js"
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circle-two.js",
+                "dependencyTypes": ["local", "require"]
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circle-three.js",
+                "dependencyTypes": ["local", "require"]
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circle-one.js",
+                "dependencyTypes": ["local", "require"]
+              }
             ]
           }
         ],
@@ -897,9 +918,18 @@
             "valid": true,
             "circular": true,
             "cycle": [
-              "test/main/__mocks__/cruise-reporterless/commonjs/circle-three.js",
-              "test/main/__mocks__/cruise-reporterless/commonjs/circle-one.js",
-              "test/main/__mocks__/cruise-reporterless/commonjs/circle-two.js"
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circle-three.js",
+                "dependencyTypes": ["local", "require"]
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circle-one.js",
+                "dependencyTypes": ["local", "require"]
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circle-two.js",
+                "dependencyTypes": ["local", "require"]
+              }
             ]
           }
         ],
@@ -926,9 +956,18 @@
             "valid": true,
             "circular": true,
             "cycle": [
-              "test/main/__mocks__/cruise-reporterless/commonjs/circle-one.js",
-              "test/main/__mocks__/cruise-reporterless/commonjs/circle-two.js",
-              "test/main/__mocks__/cruise-reporterless/commonjs/circle-three.js"
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circle-one.js",
+                "dependencyTypes": ["local", "require"]
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circle-two.js",
+                "dependencyTypes": ["local", "require"]
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/commonjs/circle-three.js",
+                "dependencyTypes": ["local", "require"]
+              }
             ]
           }
         ],
diff --git a/test/main/__fixtures__/cruise-reporterless/folder.json b/test/main/__fixtures__/cruise-reporterless/folder.json
index 277c35c9..c4c0dd72 100644
--- a/test/main/__fixtures__/cruise-reporterless/folder.json
+++ b/test/main/__fixtures__/cruise-reporterless/folder.json
@@ -769,8 +769,14 @@
             "instability": 0.875,
             "circular": true,
             "cycle": [
-              "test/main/__mocks__/cruise-reporterless/folder/unstable",
-              "test/main/__mocks__/cruise-reporterless/folder/stable"
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/folder/unstable",
+                "dependencyTypes": []
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/folder/stable",
+                "dependencyTypes": []
+              }
             ],
             "valid": false,
             "rules": [
@@ -800,8 +806,14 @@
             "valid": true,
             "circular": true,
             "cycle": [
-              "test/main/__mocks__/cruise-reporterless/folder/stable",
-              "test/main/__mocks__/cruise-reporterless/folder/unstable"
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/folder/stable",
+                "dependencyTypes": []
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/folder/unstable",
+                "dependencyTypes": []
+              }
             ]
           },
           {
diff --git a/test/main/__fixtures__/cruise-reporterless/typescript.json b/test/main/__fixtures__/cruise-reporterless/typescript.json
index 33e27179..54a5731c 100644
--- a/test/main/__fixtures__/cruise-reporterless/typescript.json
+++ b/test/main/__fixtures__/cruise-reporterless/typescript.json
@@ -209,8 +209,14 @@
             "valid": true,
             "circular": true,
             "cycle": [
-              "test/main/__mocks__/cruise-reporterless/typescript-circular-with-types/B.ts",
-              "test/main/__mocks__/cruise-reporterless/typescript-circular-with-types/A.ts"
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/typescript-circular-with-types/B.ts",
+                "dependencyTypes": ["local", "import"]
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/typescript-circular-with-types/A.ts",
+                "dependencyTypes": ["local", "import"]
+              }
             ]
           }
         ],
@@ -237,8 +243,14 @@
             "valid": true,
             "circular": true,
             "cycle": [
-              "test/main/__mocks__/cruise-reporterless/typescript-circular-with-types/A.ts",
-              "test/main/__mocks__/cruise-reporterless/typescript-circular-with-types/B.ts"
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/typescript-circular-with-types/A.ts",
+                "dependencyTypes": ["local", "import"]
+              },
+              {
+                "name": "test/main/__mocks__/cruise-reporterless/typescript-circular-with-types/B.ts",
+                "dependencyTypes": ["local", "import"]
+              }
             ]
           }
         ],
diff --git a/test/main/__mocks__/dynamic-imports/es/output.json b/test/main/__mocks__/dynamic-imports/es/output.json
index aefa498b..af503a11 100644
--- a/test/main/__mocks__/dynamic-imports/es/output.json
+++ b/test/main/__mocks__/dynamic-imports/es/output.json
@@ -16,9 +16,18 @@
           "matchesDoNotFollow": false,
           "circular": true,
           "cycle": [
-            "src/index.js",
-            "src/dynamic-to-circular.js",
-            "src/circular.js"
+            {
+              "name": "src/index.js",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/dynamic-to-circular.js",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/circular.js",
+              "dependencyTypes": ["local", "dynamic-import"]
+            }
           ],
           "valid": false,
           "rules": [{ "severity": "info", "name": "no-circular" }]
@@ -44,9 +53,18 @@
           "matchesDoNotFollow": false,
           "circular": true,
           "cycle": [
-            "src/dynamic-to-circular.js",
-            "src/circular.js",
-            "src/index.js"
+            {
+              "name": "src/dynamic-to-circular.js",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/circular.js",
+              "dependencyTypes": ["local", "dynamic-import"]
+            },
+            {
+              "name": "src/index.js",
+              "dependencyTypes": ["local", "import"]
+            }
           ],
           "valid": false,
           "rules": [{ "severity": "info", "name": "no-circular" }]
@@ -72,9 +90,18 @@
           "matchesDoNotFollow": false,
           "circular": true,
           "cycle": [
-            "src/circular.js",
-            "src/index.js",
-            "src/dynamic-to-circular.js"
+            {
+              "name": "src/circular.js",
+              "dependencyTypes": ["local", "dynamic-import"]
+            },
+            {
+              "name": "src/index.js",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/dynamic-to-circular.js",
+              "dependencyTypes": ["local", "import"]
+            }
           ],
           "valid": false,
           "rules": [{ "severity": "warn", "name": "no-dynamic" }]
@@ -99,9 +126,18 @@
         "to": "src/index.js",
         "rule": { "severity": "info", "name": "no-circular" },
         "cycle": [
-          "src/index.js",
-          "src/dynamic-to-circular.js",
-          "src/circular.js"
+          {
+            "name": "src/index.js",
+            "dependencyTypes": ["local", "import"]
+          },
+          {
+            "name": "src/dynamic-to-circular.js",
+            "dependencyTypes": ["local", "import"]
+          },
+          {
+            "name": "src/circular.js",
+            "dependencyTypes": ["local", "dynamic-import"]
+          }
         ]
       }
     ],
diff --git a/test/main/__mocks__/dynamic-imports/typescript/output-pre-compilation-deps.json b/test/main/__mocks__/dynamic-imports/typescript/output-pre-compilation-deps.json
index d9b55a1f..9e25a644 100644
--- a/test/main/__mocks__/dynamic-imports/typescript/output-pre-compilation-deps.json
+++ b/test/main/__mocks__/dynamic-imports/typescript/output-pre-compilation-deps.json
@@ -16,9 +16,18 @@
           "matchesDoNotFollow": false,
           "circular": true,
           "cycle": [
-            "src/index.ts",
-            "src/dynamic-to-circular.ts",
-            "src/circular.ts"
+            {
+              "name": "src/index.ts",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/dynamic-to-circular.ts",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/circular.ts",
+              "dependencyTypes": ["local", "dynamic-import"]
+            }
           ],
           "valid": false,
           "rules": [{ "severity": "info", "name": "no-circular" }]
@@ -44,9 +53,18 @@
           "matchesDoNotFollow": false,
           "circular": true,
           "cycle": [
-            "src/dynamic-to-circular.ts",
-            "src/circular.ts",
-            "src/index.ts"
+            {
+              "name": "src/dynamic-to-circular.ts",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/circular.ts",
+              "dependencyTypes": ["local", "dynamic-import"]
+            },
+            {
+              "name": "src/index.ts",
+              "dependencyTypes": ["local", "import"]
+            }
           ],
           "valid": false,
           "rules": [{ "severity": "info", "name": "no-circular" }]
@@ -72,9 +90,18 @@
           "matchesDoNotFollow": false,
           "circular": true,
           "cycle": [
-            "src/circular.ts",
-            "src/index.ts",
-            "src/dynamic-to-circular.ts"
+            {
+              "name": "src/circular.ts",
+              "dependencyTypes": ["local", "dynamic-import"]
+            },
+            {
+              "name": "src/index.ts",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/dynamic-to-circular.ts",
+              "dependencyTypes": ["local", "import"]
+            }
           ],
           "valid": false,
           "rules": [{ "severity": "warn", "name": "no-dynamic" }]
@@ -99,9 +126,18 @@
         "to": "src/index.ts",
         "rule": { "severity": "info", "name": "no-circular" },
         "cycle": [
-          "src/index.ts",
-          "src/dynamic-to-circular.ts",
-          "src/circular.ts"
+          {
+            "name": "src/index.ts",
+            "dependencyTypes": ["local", "import"]
+          },
+          {
+            "name": "src/dynamic-to-circular.ts",
+            "dependencyTypes": ["local", "import"]
+          },
+          {
+            "name": "src/circular.ts",
+            "dependencyTypes": ["local", "dynamic-import"]
+          }
         ]
       }
     ],
diff --git a/test/main/__mocks__/dynamic-imports/typescript/output.json b/test/main/__mocks__/dynamic-imports/typescript/output.json
index c6e8f75e..3956ef39 100644
--- a/test/main/__mocks__/dynamic-imports/typescript/output.json
+++ b/test/main/__mocks__/dynamic-imports/typescript/output.json
@@ -16,9 +16,18 @@
           "matchesDoNotFollow": false,
           "circular": true,
           "cycle": [
-            "src/index.ts",
-            "src/dynamic-to-circular.ts",
-            "src/circular.ts"
+            {
+              "name": "src/index.ts",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/dynamic-to-circular.ts",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/circular.ts",
+              "dependencyTypes": ["local", "dynamic-import"]
+            }
           ],
           "valid": false,
           "rules": [{ "severity": "info", "name": "no-circular" }]
@@ -44,9 +53,18 @@
           "matchesDoNotFollow": false,
           "circular": true,
           "cycle": [
-            "src/dynamic-to-circular.ts",
-            "src/circular.ts",
-            "src/index.ts"
+            {
+              "name": "src/dynamic-to-circular.ts",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/circular.ts",
+              "dependencyTypes": ["local", "dynamic-import"]
+            },
+            {
+              "name": "src/index.ts",
+              "dependencyTypes": ["local", "import"]
+            }
           ],
           "valid": false,
           "rules": [{ "severity": "info", "name": "no-circular" }]
@@ -72,9 +90,18 @@
           "matchesDoNotFollow": false,
           "circular": true,
           "cycle": [
-            "src/circular.ts",
-            "src/index.ts",
-            "src/dynamic-to-circular.ts"
+            {
+              "name": "src/circular.ts",
+              "dependencyTypes": ["local", "dynamic-import"]
+            },
+            {
+              "name": "src/index.ts",
+              "dependencyTypes": ["local", "import"]
+            },
+            {
+              "name": "src/dynamic-to-circular.ts",
+              "dependencyTypes": ["local", "import"]
+            }
           ],
           "valid": false,
           "rules": [{ "severity": "warn", "name": "no-dynamic" }]
@@ -99,9 +126,18 @@
         "to": "src/index.ts",
         "rule": { "severity": "info", "name": "no-circular" },
         "cycle": [
-          "src/index.ts",
-          "src/dynamic-to-circular.ts",
-          "src/circular.ts"
+          {
+            "name": "src/index.ts",
+            "dependencyTypes": ["local", "import"]
+          },
+          {
+            "name": "src/dynamic-to-circular.ts",
+            "dependencyTypes": ["local", "import"]
+          },
+          {
+            "name": "src/circular.ts",
+            "dependencyTypes": ["local", "dynamic-import"]
+          }
         ]
       }
     ],
diff --git a/test/main/main.cruise.dynamic-imports.spec.mjs b/test/main/main.cruise.dynamic-imports.spec.mjs
index 5b968c02..8ae0c4cf 100644
--- a/test/main/main.cruise.dynamic-imports.spec.mjs
+++ b/test/main/main.cruise.dynamic-imports.spec.mjs
@@ -98,8 +98,9 @@ describe("[E] main.cruise - dynamic imports", () => {
       { bustTheCache: true },
     );
 
-    deepEqual(lResult.output, tsOut);
     ajv.validate(cruiseResultSchema, lResult.output);
+
+    deepEqual(lResult.output, tsOut);
   });
 
   it("detects dynamic dependencies in typescript when using tsPreCompilationDeps", async () => {
@@ -134,7 +135,7 @@ describe("[E] main.cruise - dynamic imports", () => {
       { bustTheCache: true },
     );
 
-    deepEqual(lResult.output, tsOutpre);
     ajv.validate(cruiseResultSchema, lResult.output);
+    deepEqual(lResult.output, tsOutpre);
   });
 });
diff --git a/test/report/anon/__fixtures__/cycle.mjs b/test/report/anon/__fixtures__/cycle.mjs
index f3ebdc64..a5a1cc59 100644
--- a/test/report/anon/__fixtures__/cycle.mjs
+++ b/test/report/anon/__fixtures__/cycle.mjs
@@ -14,7 +14,16 @@ export default {
           dynamic: false,
           matchesDoNotFollow: false,
           circular: true,
-          cycle: ["src/foo.js", "src/bar.js"],
+          cycle: [
+            {
+              name: "src/foo.js",
+              dependencyTypes: ["local"],
+            },
+            {
+              name: "src/bar.js",
+              dependencyTypes: ["local"],
+            },
+          ],
           exoticallyRequired: false,
           valid: false,
           rules: [
@@ -42,7 +51,16 @@ export default {
           dynamic: false,
           matchesDoNotFollow: false,
           circular: true,
-          cycle: ["src/bar.js", "src/foo.js"],
+          cycle: [
+            {
+              name: "src/bar.js",
+              dependencyTypes: ["local"],
+            },
+            {
+              name: "src/foo.js",
+              dependencyTypes: ["local"],
+            },
+          ],
           exoticallyRequired: false,
           valid: false,
           rules: [
@@ -78,7 +96,16 @@ export default {
           severity: "warn",
           name: "no-circular",
         },
-        cycle: ["src/foo.js", "src/bar.js"],
+        cycle: [
+          {
+            name: "src/foo.js",
+            dependencyTypes: ["local"],
+          },
+          {
+            name: "src/bar.js",
+            dependencyTypes: ["local"],
+          },
+        ],
       },
       {
         from: "src/foo.js",
@@ -87,7 +114,16 @@ export default {
           severity: "warn",
           name: "no-circular",
         },
-        cycle: ["src/bar.js", "src/foo.js"],
+        cycle: [
+          {
+            name: "src/bar.js",
+            dependencyTypes: ["local"],
+          },
+          {
+            name: "src/foo.js",
+            dependencyTypes: ["local"],
+          },
+        ],
       },
       {
         from: "src/baz.js",
diff --git a/test/report/anon/__fixtures__/folder-cycles.mjs b/test/report/anon/__fixtures__/folder-cycles.mjs
index 8d58f99b..9e0ecfaf 100644
--- a/test/report/anon/__fixtures__/folder-cycles.mjs
+++ b/test/report/anon/__fixtures__/folder-cycles.mjs
@@ -100,7 +100,20 @@ export default {
           name: "foo",
           instability: 0.5,
           circular: true,
-          cycle: ["foo", "qux", "baz"],
+          cycle: [
+            {
+              name: "foo",
+              dependencyTypes: [],
+            },
+            {
+              name: "qux",
+              dependencyTypes: [],
+            },
+            {
+              name: "baz",
+              dependencyTypes: [],
+            },
+          ],
           valid: false,
           rules: [
             {
@@ -127,7 +140,20 @@ export default {
           name: "qux",
           instability: 0.5,
           circular: true,
-          cycle: ["qux", "baz", "foo"],
+          cycle: [
+            {
+              name: "qux",
+              dependencyTypes: [],
+            },
+            {
+              name: "baz",
+              dependencyTypes: [],
+            },
+            {
+              name: "foo",
+              dependencyTypes: [],
+            },
+          ],
           valid: false,
           rules: [
             {
@@ -154,7 +180,20 @@ export default {
           name: "baz",
           instability: 0.5,
           circular: true,
-          cycle: ["baz", "foo", "qux"],
+          cycle: [
+            {
+              name: "baz",
+              dependencyTypes: [],
+            },
+            {
+              name: "foo",
+              dependencyTypes: [],
+            },
+            {
+              name: "qux",
+              dependencyTypes: [],
+            },
+          ],
           valid: false,
           rules: [
             {
@@ -185,7 +224,20 @@ export default {
           severity: "warn",
           name: "no-folder-cycles",
         },
-        cycle: ["foo", "qux", "baz"],
+        cycle: [
+          {
+            name: "foo",
+            dependencyTypes: [],
+          },
+          {
+            name: "qux",
+            dependencyTypes: [],
+          },
+          {
+            name: "baz",
+            dependencyTypes: [],
+          },
+        ],
       },
       {
         type: "cycle",
@@ -195,7 +247,20 @@ export default {
           severity: "warn",
           name: "no-folder-cycles",
         },
-        cycle: ["baz", "foo", "qux"],
+        cycle: [
+          {
+            name: "baz",
+            dependencyTypes: [],
+          },
+          {
+            name: "foo",
+            dependencyTypes: [],
+          },
+          {
+            name: "qux",
+            dependencyTypes: [],
+          },
+        ],
       },
       {
         type: "cycle",
@@ -205,7 +270,20 @@ export default {
           severity: "warn",
           name: "no-folder-cycles",
         },
-        cycle: ["qux", "baz", "foo"],
+        cycle: [
+          {
+            name: "qux",
+            dependencyTypes: [],
+          },
+          {
+            name: "baz",
+            dependencyTypes: [],
+          },
+          {
+            name: "foo",
+            dependencyTypes: [],
+          },
+        ],
       },
     ],
     error: 0,
diff --git a/test/report/anon/__mocks__/cycle.mjs b/test/report/anon/__mocks__/cycle.mjs
index 61218b4c..fc1c8fbf 100644
--- a/test/report/anon/__mocks__/cycle.mjs
+++ b/test/report/anon/__mocks__/cycle.mjs
@@ -1,150 +1,164 @@
 export default {
-  "modules": [
+  modules: [
     {
-      "source": "src/entrypoint.js",
-      "dependencies": [
+      source: "src/entrypoint.js",
+      dependencies: [
         {
-          "resolved": "src/yo.js",
-          "coreModule": false,
-          "followable": true,
-          "couldNotResolve": false,
-          "dependencyTypes": ["local"],
-          "module": "./yo",
-          "moduleSystem": "cjs",
-          "dynamic": false,
-          "matchesDoNotFollow": false,
-          "circular": true,
-          "cycle": ["src/yo.js", "src/entrypoint.js"],
-          "exoticallyRequired": false,
-          "valid": false,
-          "rules": [
+          resolved: "src/yo.js",
+          coreModule: false,
+          followable: true,
+          couldNotResolve: false,
+          dependencyTypes: ["local"],
+          module: "./yo",
+          moduleSystem: "cjs",
+          dynamic: false,
+          matchesDoNotFollow: false,
+          circular: true,
+          cycle: [
+            { name: "src/yo.js", dependencyTypes: ["local"] },
+            { name: "src/entrypoint.js", dependencyTypes: ["local"] },
+          ],
+          exoticallyRequired: false,
+          valid: false,
+          rules: [
             {
-              "severity": "warn",
-              "name": "no-circular"
-            }
-          ]
-        }
+              severity: "warn",
+              name: "no-circular",
+            },
+          ],
+        },
       ],
-      "orphan": false,
-      "valid": true
+      orphan: false,
+      valid: true,
     },
     {
-      "source": "src/yo.js",
-      "dependencies": [
+      source: "src/yo.js",
+      dependencies: [
         {
-          "resolved": "src/entrypoint.js",
-          "coreModule": false,
-          "followable": true,
-          "couldNotResolve": false,
-          "dependencyTypes": ["local"],
-          "module": "./entrypoint",
-          "moduleSystem": "cjs",
-          "dynamic": false,
-          "matchesDoNotFollow": false,
-          "circular": true,
-          "cycle": ["src/entrypoint.js", "src/yo.js"],
-          "exoticallyRequired": false,
-          "valid": false,
-          "rules": [
+          resolved: "src/entrypoint.js",
+          coreModule: false,
+          followable: true,
+          couldNotResolve: false,
+          dependencyTypes: ["local"],
+          module: "./entrypoint",
+          moduleSystem: "cjs",
+          dynamic: false,
+          matchesDoNotFollow: false,
+          circular: true,
+          cycle: [
+            { name: "src/entrypoint.js", dependencyTypes: ["local"] },
+            { name: "src/yo.js", dependencyTypes: ["local"] },
+          ],
+          exoticallyRequired: false,
+          valid: false,
+          rules: [
             {
-              "severity": "warn",
-              "name": "no-circular"
-            }
-          ]
-        }
+              severity: "warn",
+              name: "no-circular",
+            },
+          ],
+        },
       ],
-      "orphan": false,
-      "valid": true
+      orphan: false,
+      valid: true,
     },
     {
-      "source": "src/remi.js",
-      "dependencies": [],
-      "orphan": true,
-      "valid": false,
-      "rules": [
+      source: "src/remi.js",
+      dependencies: [],
+      orphan: true,
+      valid: false,
+      rules: [
         {
-          "severity": "warn",
-          "name": "no-orphans"
-        }
-      ]
-    }
+          severity: "warn",
+          name: "no-orphans",
+        },
+      ],
+    },
   ],
-  "summary": {
-    "violations": [
+  summary: {
+    violations: [
       {
-        "from": "src/entrypoint.js",
-        "to": "src/yo.js",
-        "rule": {
-          "severity": "warn",
-          "name": "no-circular"
+        from: "src/entrypoint.js",
+        to: "src/yo.js",
+        rule: {
+          severity: "warn",
+          name: "no-circular",
         },
-        "cycle": ["src/yo.js", "src/entrypoint.js"]
+        cycle: [
+          { name: "src/yo.js", dependencyTypes: ["local"] },
+          { name: "src/entrypoint.js", dependencyTypes: ["local"] },
+        ],
       },
       {
-        "from": "src/yo.js",
-        "to": "src/entrypoint.js",
-        "rule": {
-          "severity": "warn",
-          "name": "no-circular"
+        from: "src/yo.js",
+        to: "src/entrypoint.js",
+        rule: {
+          severity: "warn",
+          name: "no-circular",
         },
-        "cycle": ["src/entrypoint.js", "src/yo.js"]
+        cycle: [
+          { name: "src/entrypoint.js", dependencyTypes: ["local"] },
+          { name: "src/yo.js", dependencyTypes: ["local"] },
+        ],
       },
       {
-        "from": "src/remi.js",
-        "to": "src/remi.js",
-        "rule": {
-          "severity": "warn",
-          "name": "no-orphans"
-        }
-      }
+        from: "src/remi.js",
+        to: "src/remi.js",
+        rule: {
+          severity: "warn",
+          name: "no-orphans",
+        },
+      },
     ],
-    "error": 0,
-    "warn": 3,
-    "info": 0,
-    "totalCruised": 3,
-    "totalDependenciesCruised": 2,
-    "optionsUsed": {
-      "combinedDependencies": false,
-      "doNotFollow": {
-        "dependencyTypes": [
+    error: 0,
+    warn: 3,
+    info: 0,
+    totalCruised: 3,
+    totalDependenciesCruised: 2,
+    optionsUsed: {
+      combinedDependencies: false,
+      doNotFollow: {
+        dependencyTypes: [
           "npm",
           "npm-dev",
           "npm-optional",
           "npm-peer",
           "npm-bundled",
-          "npm-no-pkg"
-        ]
+          "npm-no-pkg",
+        ],
       },
-      "externalModuleResolutionStrategy": "node_modules",
-      "moduleSystems": ["amd", "cjs", "es6"],
-      "outputTo": "-",
-      "outputType": "json",
-      "preserveSymlinks": false,
-      "rulesFile": ".dependency-cruiser.js",
-      "tsPreCompilationDeps": false,
-      "args": "src"
+      externalModuleResolutionStrategy: "node_modules",
+      moduleSystems: ["amd", "cjs", "es6"],
+      outputTo: "-",
+      outputType: "json",
+      preserveSymlinks: false,
+      rulesFile: ".dependency-cruiser.js",
+      tsPreCompilationDeps: false,
+      args: "src",
     },
-    "ruleSetUsed": {
-      "forbidden": [
+    ruleSetUsed: {
+      forbidden: [
         {
-          "name": "no-circular",
-          "severity": "warn",
-          "comment": "This dependency is part of a circular relationship. You might want to revise your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ",
-          "from": {},
-          "to": {
-            "circular": true
-          }
+          name: "no-circular",
+          severity: "warn",
+          comment:
+            "This dependency is part of a circular relationship. You might want to revise your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ",
+          from: {},
+          to: {
+            circular: true,
+          },
         },
         {
-          "name": "no-orphans",
-          "severity": "warn",
-          "comment": "This dependency is part of a circular relationship. You might want to revise your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ",
-          "from": {
-            "orphan": true
+          name: "no-orphans",
+          severity: "warn",
+          comment:
+            "This dependency is part of a circular relationship. You might want to revise your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ",
+          from: {
+            orphan: true,
           },
-          "to": {}
-        }
-      ]
-    }
-  }
-}
+          to: {},
+        },
+      ],
+    },
+  },
+};
diff --git a/test/report/anon/__mocks__/folder-cycles.mjs b/test/report/anon/__mocks__/folder-cycles.mjs
index 5bf64c89..fe2bec48 100644
--- a/test/report/anon/__mocks__/folder-cycles.mjs
+++ b/test/report/anon/__mocks__/folder-cycles.mjs
@@ -97,7 +97,11 @@ export default {
           name: "cycle-two",
           instability: 0.5,
           circular: true,
-          cycle: ["cycle-two", "cycle-three", "cycle-one"],
+          cycle: [
+            { name: "cycle-two", dependencyTypes: [] },
+            { name: "cycle-three", dependencyTypes: [] },
+            { name: "cycle-one", dependencyTypes: [] },
+          ],
           valid: false,
           rules: [
             {
@@ -124,7 +128,11 @@ export default {
           name: "cycle-three",
           instability: 0.5,
           circular: true,
-          cycle: ["cycle-three", "cycle-one", "cycle-two"],
+          cycle: [
+            { name: "cycle-three", dependencyTypes: [] },
+            { name: "cycle-one", dependencyTypes: [] },
+            { name: "cycle-two", dependencyTypes: [] },
+          ],
           valid: false,
           rules: [
             {
@@ -151,7 +159,11 @@ export default {
           name: "cycle-one",
           instability: 0.5,
           circular: true,
-          cycle: ["cycle-one", "cycle-two", "cycle-three"],
+          cycle: [
+            { name: "cycle-one", dependencyTypes: [] },
+            { name: "cycle-two", dependencyTypes: [] },
+            { name: "cycle-three", dependencyTypes: [] },
+          ],
           valid: false,
           rules: [
             {
@@ -182,7 +194,11 @@ export default {
           severity: "warn",
           name: "no-folder-cycles",
         },
-        cycle: ["cycle-two", "cycle-three", "cycle-one"],
+        cycle: [
+          { name: "cycle-two", dependencyTypes: [] },
+          { name: "cycle-three", dependencyTypes: [] },
+          { name: "cycle-one", dependencyTypes: [] },
+        ],
       },
       {
         type: "cycle",
@@ -192,7 +208,11 @@ export default {
           severity: "warn",
           name: "no-folder-cycles",
         },
-        cycle: ["cycle-one", "cycle-two", "cycle-three"],
+        cycle: [
+          { name: "cycle-one", dependencyTypes: [] },
+          { name: "cycle-two", dependencyTypes: [] },
+          { name: "cycle-three", dependencyTypes: [] },
+        ],
       },
       {
         type: "cycle",
@@ -202,7 +222,11 @@ export default {
           severity: "warn",
           name: "no-folder-cycles",
         },
-        cycle: ["cycle-three", "cycle-one", "cycle-two"],
+        cycle: [
+          { name: "cycle-three", dependencyTypes: [] },
+          { name: "cycle-one", dependencyTypes: [] },
+          { name: "cycle-two", dependencyTypes: [] },
+        ],
       },
     ],
     error: 0,
diff --git a/test/report/azure-devops/__mocks__/circular-deps.mjs b/test/report/azure-devops/__mocks__/circular-deps.mjs
index 16e565a8..0dedd41e 100644
--- a/test/report/azure-devops/__mocks__/circular-deps.mjs
+++ b/test/report/azure-devops/__mocks__/circular-deps.mjs
@@ -14,9 +14,9 @@ export default {
           moduleSystem: "es6",
           valid: true,
           cycle: [
-            "src/some/folder/loop-a.js",
-            "src/some/folder/loop-b.js",
-            "src/some/folder/nested/center.js",
+            { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+            { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
           ],
           rules: [
             {
@@ -42,9 +42,9 @@ export default {
           moduleSystem: "es6",
           valid: true,
           cycle: [
-            "src/some/folder/loop-b.js",
-            "src/some/folder/nested/center.js",
-            "src/some/folder/loop-a.js",
+            { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+            { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
           ],
           rules: [
             {
@@ -70,9 +70,9 @@ export default {
           moduleSystem: "es6",
           valid: false,
           cycle: [
-            "src/some/folder/nested/center.js",
-            "src/some/folder/loop-a.js",
-            "src/some/folder/loop-b.js",
+            { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
           ],
           rules: [
             {
@@ -96,9 +96,9 @@ export default {
           name: "no-circular",
         },
         cycle: [
-          "src/some/folder/loop-a.js",
-          "src/some/folder/loop-b.js",
-          "src/some/folder/nested/center.js",
+          { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+          { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
         ],
       },
       {
@@ -110,9 +110,9 @@ export default {
           name: "no-circular",
         },
         cycle: [
-          "src/some/folder/loop-b.js",
-          "src/some/folder/nested/center.js",
-          "src/some/folder/loop-a.js",
+          { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+          { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
         ],
       },
       {
@@ -124,9 +124,9 @@ export default {
           name: "no-circular",
         },
         cycle: [
-          "src/some/folder/nested/center.js",
-          "src/some/folder/loop-a.js",
-          "src/some/folder/loop-b.js",
+          { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
         ],
       },
     ],
diff --git a/test/report/error-html/__mocks__/orphans-cycles-metrics.mjs b/test/report/error-html/__mocks__/orphans-cycles-metrics.mjs
index f33d25e1..9c915ca6 100644
--- a/test/report/error-html/__mocks__/orphans-cycles-metrics.mjs
+++ b/test/report/error-html/__mocks__/orphans-cycles-metrics.mjs
@@ -1771,7 +1771,13 @@ export default {
           name: "src/extract/transpile",
           instability: 0.25,
           circular: true,
-          cycle: ["src/extract/transpile", "src/extract/parse"],
+          cycle: [
+            {
+              name: "src/extract/transpile",
+              dependencyTypes: ["local", "import"],
+            },
+            { name: "src/extract/parse", dependencyTypes: ["local", "import"] },
+          ],
           valid: false,
           rules: [
             {
@@ -1807,7 +1813,13 @@ export default {
           name: "src/extract/parse",
           instability: 0.36363636363636365,
           circular: true,
-          cycle: ["src/extract/parse", "src/extract/transpile"],
+          cycle: [
+            { name: "src/extract/parse", dependencyTypes: ["local", "import"] },
+            {
+              name: "src/extract/transpile",
+              dependencyTypes: ["local", "import"],
+            },
+          ],
           valid: false,
           rules: [
             {
@@ -1936,7 +1948,13 @@ export default {
           severity: "warn",
           name: "no-folder-cycles",
         },
-        cycle: ["src/extract/transpile", "src/extract/parse"],
+        cycle: [
+          {
+            name: "src/extract/transpile",
+            dependencyTypes: ["local", "import"],
+          },
+          { name: "src/extract/parse", dependencyTypes: ["local", "import"] },
+        ],
       },
       {
         type: "cycle",
@@ -1946,7 +1964,13 @@ export default {
           severity: "warn",
           name: "no-folder-cycles",
         },
-        cycle: ["src/extract/parse", "src/extract/transpile"],
+        cycle: [
+          { name: "src/extract/parse", dependencyTypes: ["local", "import"] },
+          {
+            name: "src/extract/transpile",
+            dependencyTypes: ["local", "import"],
+          },
+        ],
       },
       {
         type: "instability",
diff --git a/test/report/error-html/utl.spec.mjs b/test/report/error-html/utl.spec.mjs
index f6ee2b4c..6db00bf9 100644
--- a/test/report/error-html/utl.spec.mjs
+++ b/test/report/error-html/utl.spec.mjs
@@ -161,7 +161,12 @@ describe("[U] report/error-html/utl", () => {
   it("determineTo - circular violation", () => {
     const lInputViolation = {
       type: "cycle",
-      cycle: ["thing/a", "b", "thingy/bingy/c", "a"],
+      cycle: [
+        { name: "thing/a", dependencyTypes: ["local", "import"] },
+        { name: "b", dependencyTypes: ["local", "import"] },
+        { name: "thingy/bingy/c", dependencyTypes: ["local", "import"] },
+        { name: "a", dependencyTypes: ["local", "import"] },
+      ],
       from: "a",
       to: "thing/a",
     };
diff --git a/test/report/error/__mocks__/circular-deps.mjs b/test/report/error/__mocks__/circular-deps.mjs
index 16e565a8..0dedd41e 100644
--- a/test/report/error/__mocks__/circular-deps.mjs
+++ b/test/report/error/__mocks__/circular-deps.mjs
@@ -14,9 +14,9 @@ export default {
           moduleSystem: "es6",
           valid: true,
           cycle: [
-            "src/some/folder/loop-a.js",
-            "src/some/folder/loop-b.js",
-            "src/some/folder/nested/center.js",
+            { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+            { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
           ],
           rules: [
             {
@@ -42,9 +42,9 @@ export default {
           moduleSystem: "es6",
           valid: true,
           cycle: [
-            "src/some/folder/loop-b.js",
-            "src/some/folder/nested/center.js",
-            "src/some/folder/loop-a.js",
+            { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+            { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
           ],
           rules: [
             {
@@ -70,9 +70,9 @@ export default {
           moduleSystem: "es6",
           valid: false,
           cycle: [
-            "src/some/folder/nested/center.js",
-            "src/some/folder/loop-a.js",
-            "src/some/folder/loop-b.js",
+            { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
           ],
           rules: [
             {
@@ -96,9 +96,9 @@ export default {
           name: "no-circular",
         },
         cycle: [
-          "src/some/folder/loop-a.js",
-          "src/some/folder/loop-b.js",
-          "src/some/folder/nested/center.js",
+          { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+          { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
         ],
       },
       {
@@ -110,9 +110,9 @@ export default {
           name: "no-circular",
         },
         cycle: [
-          "src/some/folder/loop-b.js",
-          "src/some/folder/nested/center.js",
-          "src/some/folder/loop-a.js",
+          { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+          { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
         ],
       },
       {
@@ -124,9 +124,9 @@ export default {
           name: "no-circular",
         },
         cycle: [
-          "src/some/folder/nested/center.js",
-          "src/some/folder/loop-a.js",
-          "src/some/folder/loop-b.js",
+          { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
         ],
       },
     ],
diff --git a/test/report/markdown/__mocks__/orphans-cycles-metrics.mjs b/test/report/markdown/__mocks__/orphans-cycles-metrics.mjs
index f33d25e1..9c915ca6 100644
--- a/test/report/markdown/__mocks__/orphans-cycles-metrics.mjs
+++ b/test/report/markdown/__mocks__/orphans-cycles-metrics.mjs
@@ -1771,7 +1771,13 @@ export default {
           name: "src/extract/transpile",
           instability: 0.25,
           circular: true,
-          cycle: ["src/extract/transpile", "src/extract/parse"],
+          cycle: [
+            {
+              name: "src/extract/transpile",
+              dependencyTypes: ["local", "import"],
+            },
+            { name: "src/extract/parse", dependencyTypes: ["local", "import"] },
+          ],
           valid: false,
           rules: [
             {
@@ -1807,7 +1813,13 @@ export default {
           name: "src/extract/parse",
           instability: 0.36363636363636365,
           circular: true,
-          cycle: ["src/extract/parse", "src/extract/transpile"],
+          cycle: [
+            { name: "src/extract/parse", dependencyTypes: ["local", "import"] },
+            {
+              name: "src/extract/transpile",
+              dependencyTypes: ["local", "import"],
+            },
+          ],
           valid: false,
           rules: [
             {
@@ -1936,7 +1948,13 @@ export default {
           severity: "warn",
           name: "no-folder-cycles",
         },
-        cycle: ["src/extract/transpile", "src/extract/parse"],
+        cycle: [
+          {
+            name: "src/extract/transpile",
+            dependencyTypes: ["local", "import"],
+          },
+          { name: "src/extract/parse", dependencyTypes: ["local", "import"] },
+        ],
       },
       {
         type: "cycle",
@@ -1946,7 +1964,13 @@ export default {
           severity: "warn",
           name: "no-folder-cycles",
         },
-        cycle: ["src/extract/parse", "src/extract/transpile"],
+        cycle: [
+          { name: "src/extract/parse", dependencyTypes: ["local", "import"] },
+          {
+            name: "src/extract/transpile",
+            dependencyTypes: ["local", "import"],
+          },
+        ],
       },
       {
         type: "instability",
diff --git a/test/report/teamcity/__mocks__/circular-deps.mjs b/test/report/teamcity/__mocks__/circular-deps.mjs
index 16e565a8..0dedd41e 100644
--- a/test/report/teamcity/__mocks__/circular-deps.mjs
+++ b/test/report/teamcity/__mocks__/circular-deps.mjs
@@ -14,9 +14,9 @@ export default {
           moduleSystem: "es6",
           valid: true,
           cycle: [
-            "src/some/folder/loop-a.js",
-            "src/some/folder/loop-b.js",
-            "src/some/folder/nested/center.js",
+            { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+            { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
           ],
           rules: [
             {
@@ -42,9 +42,9 @@ export default {
           moduleSystem: "es6",
           valid: true,
           cycle: [
-            "src/some/folder/loop-b.js",
-            "src/some/folder/nested/center.js",
-            "src/some/folder/loop-a.js",
+            { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+            { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
           ],
           rules: [
             {
@@ -70,9 +70,9 @@ export default {
           moduleSystem: "es6",
           valid: false,
           cycle: [
-            "src/some/folder/nested/center.js",
-            "src/some/folder/loop-a.js",
-            "src/some/folder/loop-b.js",
+            { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+            { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
           ],
           rules: [
             {
@@ -96,9 +96,9 @@ export default {
           name: "no-circular",
         },
         cycle: [
-          "src/some/folder/loop-a.js",
-          "src/some/folder/loop-b.js",
-          "src/some/folder/nested/center.js",
+          { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+          { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
         ],
       },
       {
@@ -110,9 +110,9 @@ export default {
           name: "no-circular",
         },
         cycle: [
-          "src/some/folder/loop-b.js",
-          "src/some/folder/nested/center.js",
-          "src/some/folder/loop-a.js",
+          { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
+          { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
         ],
       },
       {
@@ -124,9 +124,9 @@ export default {
           name: "no-circular",
         },
         cycle: [
-          "src/some/folder/nested/center.js",
-          "src/some/folder/loop-a.js",
-          "src/some/folder/loop-b.js",
+          { name: "src/some/folder/nested/center.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-a.js", dependencyTypes: [] },
+          { name: "src/some/folder/loop-b.js", dependencyTypes: [] },
         ],
       },
     ],
diff --git a/test/validate/index.cycle-via-not.spec.mjs b/test/validate/index.cycle-via-not.spec.mjs
index f4111cae..6edc4d6c 100644
--- a/test/validate/index.cycle-via-not.spec.mjs
+++ b/test/validate/index.cycle-via-not.spec.mjs
@@ -2,6 +2,13 @@ import { deepEqual } from "node:assert/strict";
 import parseRuleSet from "./parse-ruleset.utl.mjs";
 import validate from "#validate/index.mjs";
 
+function stringToCycleEntry(pString) {
+  return {
+    name: pString,
+    dependencyTypes: [],
+  };
+}
+
 describe("[I] validate/index dependency - cycle viaNot", () => {
   const lCycleViaNotRuleSet = parseRuleSet({
     forbidden: [
@@ -22,7 +29,9 @@ describe("[I] validate/index dependency - cycle viaNot", () => {
         {
           resolved: "tmp/ba.js",
           circular: true,
-          cycle: ["tmp/ba.js", "tmp/bb.js", "tmp/bc.js", "tmp/a.js"],
+          cycle: ["tmp/ba.js", "tmp/bb.js", "tmp/bc.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -40,7 +49,9 @@ describe("[I] validate/index dependency - cycle viaNot", () => {
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"],
+          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -74,7 +85,7 @@ describe("[I] validate/index dependency - cycle viaNot - with group matching", (
             "src/module-b/bb.js",
             "src/module-b/bc.js",
             "src/module-a/a.js",
-          ],
+          ].map(stringToCycleEntry),
         },
       ),
       {
@@ -96,7 +107,7 @@ describe("[I] validate/index dependency - cycle viaNot - with group matching", (
             "src/module-a/ab.js",
             "src/module-b/bc.js",
             "src/module-a/a.js",
-          ],
+          ].map(stringToCycleEntry),
         },
       ),
       {
@@ -118,7 +129,7 @@ describe("[I] validate/index dependency - cycle viaNot - with group matching", (
             "src/module-a/ab.js",
             "src/module-a/ac.js",
             "src/module-a/a.js",
-          ],
+          ].map(stringToCycleEntry),
         },
       ),
       {
diff --git a/test/validate/index.cycle-via-some-not.spec.mjs b/test/validate/index.cycle-via-some-not.spec.mjs
index a690e669..47b177e3 100644
--- a/test/validate/index.cycle-via-some-not.spec.mjs
+++ b/test/validate/index.cycle-via-some-not.spec.mjs
@@ -2,6 +2,13 @@ import { deepEqual } from "node:assert/strict";
 import parseRuleSet from "./parse-ruleset.utl.mjs";
 import validate from "#validate/index.mjs";
 
+function stringToCycleEntry(pString) {
+  return {
+    name: pString,
+    dependencyTypes: [],
+  };
+}
+
 describe("[I] validate/index dependency - cycle viaSomeNot - with group matching", () => {
   const lCycleButNotViaGroupMatchRuleSet = {
     forbidden: [
@@ -26,7 +33,7 @@ describe("[I] validate/index dependency - cycle viaSomeNot - with group matching
             "src/module-b/bb.js",
             "src/module-b/bc.js",
             "src/module-a/a.js",
-          ],
+          ].map(stringToCycleEntry),
         },
       ),
       {
@@ -54,7 +61,7 @@ describe("[I] validate/index dependency - cycle viaSomeNot - with group matching
             "src/module-a/ab.js",
             "src/module-b/bc.js",
             "src/module-a/a.js",
-          ],
+          ].map(stringToCycleEntry),
         },
       ),
       {
@@ -82,7 +89,7 @@ describe("[I] validate/index dependency - cycle viaSomeNot - with group matching
             "src/module-a/ab.js",
             "src/module-a/ac.js",
             "src/module-a/a.js",
-          ],
+          ].map(stringToCycleEntry),
         },
       ),
       {
@@ -116,7 +123,7 @@ describe("[I] validate/index dependency - cycle viaSomeNot - with group matching
             "src/module-a/ab.js",
             "src/module-a/ac.js",
             "src/module-a/a.js",
-          ],
+          ].map(stringToCycleEntry),
         },
       ),
       {
diff --git a/test/validate/index.cycle-via.spec.mjs b/test/validate/index.cycle-via.spec.mjs
index f48ec408..8ecb2875 100644
--- a/test/validate/index.cycle-via.spec.mjs
+++ b/test/validate/index.cycle-via.spec.mjs
@@ -2,6 +2,13 @@ import { deepEqual } from "node:assert/strict";
 import parseRuleSet from "./parse-ruleset.utl.mjs";
 import validate from "#validate/index.mjs";
 
+function stringToCycleEntry(pString) {
+  return {
+    name: pString,
+    dependencyTypes: [],
+  };
+}
+
 describe("[I] validate/index dependency - cycle via", () => {
   const lCycleViaRuleSet = parseRuleSet({
     forbidden: [
@@ -23,7 +30,9 @@ describe("[I] validate/index dependency - cycle via", () => {
         {
           resolved: "tmp/ba.js",
           circular: true,
-          cycle: ["tmp/ba.js", "tmp/bb.js", "tmp/bc.js", "tmp/a.js"],
+          cycle: ["tmp/ba.js", "tmp/bb.js", "tmp/bc.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -40,7 +49,9 @@ describe("[I] validate/index dependency - cycle via", () => {
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"],
+          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -69,7 +80,9 @@ describe("[I] validate/index dependency - cycle via", () => {
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"],
+          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -103,7 +116,9 @@ describe("[I] validate/index dependency - cycle via - with group matching", () =
         {
           resolved: "tmp/ba.js",
           circular: true,
-          cycle: ["tmp/ba.js", "tmp/bb.js", "tmp/bc.js", "tmp/a.js"],
+          cycle: ["tmp/ba.js", "tmp/bb.js", "tmp/bc.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -120,7 +135,9 @@ describe("[I] validate/index dependency - cycle via - with group matching", () =
         {
           resolved: "tmp/ba.js",
           circular: true,
-          cycle: ["tmp/ba.js", "not-tmp/ab.js", "tmp/bc.js", "tmp/a.js"],
+          cycle: ["tmp/ba.js", "not-tmp/ab.js", "tmp/bc.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -137,7 +154,9 @@ describe("[I] validate/index dependency - cycle via - with group matching", () =
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"],
+          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -166,7 +185,9 @@ describe("[I] validate/index dependency - cycle via - with group matching", () =
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"],
+          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -198,7 +219,9 @@ describe("[I] validate/index dependency - cycle viaOnly", () => {
         {
           resolved: "tmp/ba.js",
           circular: true,
-          cycle: ["tmp/ba.js", "tmp/bb.js", "tmp/bc.js", "tmp/a.js"],
+          cycle: ["tmp/ba.js", "tmp/bb.js", "tmp/bc.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -215,7 +238,9 @@ describe("[I] validate/index dependency - cycle viaOnly", () => {
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"],
+          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -232,7 +257,7 @@ describe("[I] validate/index dependency - cycle viaOnly", () => {
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/ab.js", "tmp/a.js"],
+          cycle: ["tmp/ab.js", "tmp/a.js"].map(stringToCycleEntry),
         },
       ),
       {
@@ -260,7 +285,9 @@ describe("[I] validate/index dependency - cycle viaOnly", () => {
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"],
+          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -293,7 +320,9 @@ describe("[I] validate/index dependency - cycle viaOnly - with group matching",
         {
           resolved: "tmp/ba.js",
           circular: true,
-          cycle: ["tmp/ba.js", "tmp/bb.js", "tmp/bc.js", "tmp/a.js"],
+          cycle: ["tmp/ba.js", "tmp/bb.js", "tmp/bc.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -310,7 +339,9 @@ describe("[I] validate/index dependency - cycle viaOnly - with group matching",
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"],
+          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -327,7 +358,7 @@ describe("[I] validate/index dependency - cycle viaOnly - with group matching",
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/ab.js", "tmp/a.js"],
+          cycle: ["tmp/ab.js", "tmp/a.js"].map(stringToCycleEntry),
         },
       ),
       {
@@ -355,7 +386,9 @@ describe("[I] validate/index dependency - cycle viaOnly - with group matching",
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"],
+          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {
@@ -383,7 +416,9 @@ describe("[I] validate/index dependency - cycle viaOnly - with group matching",
         {
           resolved: "tmp/aa.js",
           circular: true,
-          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"],
+          cycle: ["tmp/aa.js", "tmp/ab.js", "tmp/ac.js", "tmp/a.js"].map(
+            stringToCycleEntry,
+          ),
         },
       ),
       {