@codependix/boundaries
v0.0.32
Published
Boundary rule validation, forbid/allow rule enforcement, and cycle detection for Codependix graphs
Maintainers
Readme
🚧 Codependix Boundaries
Evaluates declared rules against a graph codependix already built, and reports the edges and cycles that break them.
Codependix draws graphs at three levels and says nothing about whether their
shape is allowed. This turns it from a documentation tool into a gate, at all
three levels — Nx project edges, NestJS module edges, and file-level import
edges, judged separately per language even though TypeScript and Python are
exported together as one fileImports graph type.
codependix map --check boundaries --config projects/configuration/codependix.config.tsWhy not an ESLint rule
@nx/enforce-module-boundaries reads import statements, one file at a time.
Three facts it structurally cannot see:
- Implicit edges. An Nx
implicitDependenciesentry creates a project-graph edge with no import statement to flag.NeighborhoodEdgealready carriesimplicit, so codependix holds a fact the lint rule has no way to reach. - A NestJS module edge is a container fact, not a source fact.
NestjsProjectService.exploreProjectreports what the container resolved, so a dynamic module, aforRootAsync, or a conditionally composed import produces an edge noimportstatement expresses. - A rule can be about the graph rather than the edge. A cycle, or a project's dependents, is a statement about a shape, and a rule that sees one file at a time cannot make one.
What this deliberately does not replace: the layered depConstraints
graph in
projects/configuration/eslint.config.ts, which
reports at the import site with a line number, and dependency-cruiser's
no-circular, which is already this repository's file-cycle gate.
The two were checked against each other rather than assumed equivalent. All 32
of this repository's depConstraints translate mechanically —
onlyDependOnLibsWithTags is an allow rule, notDependOnLibsWithTags is a
forbid rule, and an empty onlyDependOnLibsWithTags is a forbid reaching
everything — and with edges: { implicit: false } all 32 pass, exactly as
ESLint reports them. Without that narrowing one more edge is reported:
conformetry-examples → conformetry-cli, declared by an implicitDependencies
entry with no import statement behind it. Its own depConstraint comment says
that dependency should not exist, and ESLint has nothing to flag. Whether that
is a finding or a false positive is the question edges exists to let a rule
answer.
The rule model
Rules are declared in codependix.config.ts, keyed by the graph level that
judges them — nestjsModules, nxProjects, and fileImports, which nests by
language as { typescript, python } since no edge ever crosses the two. A
level declaring no rule is never built at all, which is what keeps the gate
affordable: judging the NestJS level means booting every container in
preview mode.
Two shapes and three kinds — an access rule, written as from/to with the
verdict running one way or the other, and an acyclic rule scoped by nodes:
| Kind | Reports |
| ---- | ------- |
| forbid | An edge whose source matches from and whose target matches to |
| allow | An edge leaving from for anywhere to does not claim |
| acyclic | A cycle among the nodes nodes selects, defaulting to every node |
An access rule may also narrow which edges it judges, rather than which nodes it selects:
| edges | Judges |
| ------- | ------ |
| unset | every edge — the stricter reading, and the right default for a rule about what a project may depend on |
| { implicit: false } | only edges backed by an import statement — exactly what an @nx/enforce-module-boundaries depConstraint sees |
| { implicit: true } | only edges an implicitDependencies entry declares and no import backs |
Only the Nx level draws an implicit edge; every other level's edges are read as explicit.
Each rule carries a name and, optionally, a message saying why it exists.
The message is appended to the generated sentence rather than replacing
it, so no wording a configuration chooses can cost a report the rule that
fired and both ends of what it fired on.
Selectors
One node shape covers three vocabularies, and every field is a list of globs
matched with path.matchesGlob:
| Field | Matches | Available at |
| ----- | ------- | ------------ |
| id | The node's identifier — a project name, a file path, or a module class name | every level |
| path | A workspace-relative project root, or a project-relative file path | nxProjects, fileImports.typescript, fileImports.python |
| project | The Nx project a node belongs to | nxProjects, fileImports.typescript, fileImports.python |
| tags | The node's Nx tags; one tag matching is enough | nxProjects |
Every field a selector states must match — the fields narrow each other.
Within one field, one glob matching is enough. A selector naming a field its
level does not carry matches nothing rather than everything: a path rule
evaluated against a NestJS module graph, which carries no file paths, selects
no module instead of silently selecting all of them. A selector stating no
field at all is refused by the configuration schema, since it reads exactly
like a typo.
The two halves, and the one seam between them
src/modules/boundaries/ evaluates rules and knows nothing about workspaces: a
BoundaryGraph and a list of rules go in, and violations come out.
src/modules/boundary-check/ is what turns a real workspace into those graphs
— one adapter per level, plus the orchestration around them.
BoundaryGraph is the seam, and it is deliberately not any of the four real
graph types. Each adapter flattens a Neighborhood, a NestjsModuleGraph, or
an import graph into it, so rule evaluation never sees @nx/devkit,
@nestjs/core, or typescript and could be lifted out again without
touching a rule.
BoundaryCheckService.run walks the four levels in BOUNDARY_LEVEL_ORDER —
cheapest first — and skips any level with no declared rules before building
anything. That is what keeps the gate affordable: judging the NestJS level
means booting every container in preview mode, and judging the TypeScript level
means building a ts.Program per project. A workspace declaring only Nx rules
pays for neither. Each level also isolates one project's failure to that
project, so a container that will not boot is collected as a
BoundaryCheckFailure while every other project is still judged.
Nothing here depends on @codependix/cli — the host calls in, never the
reverse — and a rule in projects/configuration/codependix.config.ts says so, so the
two cannot close a cycle.
Test
nx run codependix-boundaries:vitest👔 Conformetry
This project was generated from the nestjs-service-project conformetry template.
🕸️ Codependix
Dependency graphs exported by codependix, regenerated by nx run configuration:codependix:write.
Nx Neighborhood
graph LR
codependix_boundaries["codependix-boundaries"]
codependix_cli["codependix-cli"]
codependix_configuration["codependix-configuration"]
codependix_core["codependix-core"]
codependix_examples["codependix-examples"]
codependix_file_imports["codependix-file-imports"]
codependix_nestjs_modules["codependix-nestjs-modules"]
codependix_nx_projects["codependix-nx-projects"]
codependix_output["codependix-output"]
codependix_boundaries --> codependix_configuration
codependix_boundaries --> codependix_core
codependix_boundaries --> codependix_file_imports
codependix_boundaries --> codependix_nestjs_modules
codependix_boundaries --> codependix_nx_projects
codependix_cli --> codependix_boundaries
codependix_examples --> codependix_boundaries
codependix_output --> codependix_boundaries
classDef subject fill:#7c3aed,color:#fff,stroke:#4c1d95,stroke-width:2px
class codependix_boundaries subjectNestJS Module Graph
flowchart LR
BoundariesModule
BoundaryCheckModule
ConfigurationModule
InputModule
LoggerModule([LoggerModule])
ModuleGraphModule
NeighborhoodModule
NestjsProjectModule
OverrideResolutionModule
PythonModule
RunContextModule
TypescriptModule
WorkspaceGraphModule
BoundaryCheckModule --> BoundariesModule
BoundaryCheckModule --> ModuleGraphModule
BoundaryCheckModule --> NeighborhoodModule
BoundaryCheckModule --> NestjsProjectModule
BoundaryCheckModule --> PythonModule
BoundaryCheckModule --> TypescriptModule
BoundaryCheckModule --> WorkspaceGraphModule
ConfigurationModule --> InputModule
ConfigurationModule --> OverrideResolutionModule
RunContextModule --> ConfigurationModule
RunContextModule --> NeighborhoodModule
WorkspaceGraphModule --> NeighborhoodModuleRounded modules are global: every module can inject them, so their edges are left out.
File Imports
graph LR
file_callidescope_config_ts["callidescope.config.ts"]
file_codependix_config_ts["codependix.config.ts"]
file_codometer_config_ts["codometer.config.ts"]
file_eslint_config_ts["eslint.config.ts"]
file_src_index_ts["src/index.ts"]
file_src_modules_boundaries_boundaries_constants_ts["src/modules/boundaries/boundaries.constants.ts"]
file_src_modules_boundaries_boundaries_module_ts["src/modules/boundaries/boundaries.module.ts"]
file_src_modules_boundaries_boundaries_module_unit_test_ts["src/modules/boundaries/boundaries.module.unit.test.ts"]
file_src_modules_boundaries_boundaries_service_ts["src/modules/boundaries/boundaries.service.ts"]
file_src_modules_boundaries_boundaries_service_unit_test_ts["src/modules/boundaries/boundaries.service.unit.test.ts"]
file_src_modules_boundaries_boundaries_types_ts["src/modules/boundaries/boundaries.types.ts"]
file_src_modules_boundaries_boundary_cycles_service_ts["src/modules/boundaries/boundary-cycles.service.ts"]
file_src_modules_boundaries_boundary_cycles_service_unit_test_ts["src/modules/boundaries/boundary-cycles.service.unit.test.ts"]
file_src_modules_boundaries_boundary_report_service_ts["src/modules/boundaries/boundary-report.service.ts"]
file_src_modules_boundaries_boundary_report_service_unit_test_ts["src/modules/boundaries/boundary-report.service.unit.test.ts"]
file_src_modules_boundaries_boundary_selector_service_ts["src/modules/boundaries/boundary-selector.service.ts"]
file_src_modules_boundaries_boundary_selector_service_unit_test_ts["src/modules/boundaries/boundary-selector.service.unit.test.ts"]
file_src_modules_boundary_check_boundary_check_constants_ts["src/modules/boundary-check/boundary-check.constants.ts"]
file_src_modules_boundary_check_boundary_check_module_ts["src/modules/boundary-check/boundary-check.module.ts"]
file_src_modules_boundary_check_boundary_check_module_unit_test_ts["src/modules/boundary-check/boundary-check.module.unit.test.ts"]
file_src_modules_boundary_check_boundary_check_service_ts["src/modules/boundary-check/boundary-check.service.ts"]
file_src_modules_boundary_check_boundary_check_service_unit_test_ts["src/modules/boundary-check/boundary-check.service.unit.test.ts"]
file_src_modules_boundary_check_boundary_check_types_ts["src/modules/boundary-check/boundary-check.types.ts"]
file_src_modules_boundary_check_boundary_failure_service_ts["src/modules/boundary-check/boundary-failure.service.ts"]
file_src_modules_boundary_check_boundary_failure_service_unit_test_ts["src/modules/boundary-check/boundary-failure.service.unit.test.ts"]
file_src_modules_boundary_check_boundary_graph_service_ts["src/modules/boundary-check/boundary-graph.service.ts"]
file_src_modules_boundary_check_boundary_graph_service_unit_test_ts["src/modules/boundary-check/boundary-graph.service.unit.test.ts"]
file_src_modules_boundary_check_boundary_outcome_report_service_ts["src/modules/boundary-check/boundary-outcome-report.service.ts"]
file_src_modules_boundary_check_boundary_outcome_report_service_unit_test_ts["src/modules/boundary-check/boundary-outcome-report.service.unit.test.ts"]
file_src_modules_run_context_run_context_constants_ts["src/modules/run-context/run-context.constants.ts"]
file_src_modules_run_context_run_context_module_ts["src/modules/run-context/run-context.module.ts"]
file_src_modules_run_context_run_context_module_unit_test_ts["src/modules/run-context/run-context.module.unit.test.ts"]
file_src_modules_run_context_run_context_service_ts["src/modules/run-context/run-context.service.ts"]
file_src_modules_run_context_run_context_service_unit_test_ts["src/modules/run-context/run-context.service.unit.test.ts"]
file_src_modules_run_context_run_context_types_ts["src/modules/run-context/run-context.types.ts"]
file_testing_mocks_ts["testing/mocks.ts"]
file_testing_setup_ts["testing/setup.ts"]
file_vite_config_ts["vite.config.ts"]
file_vitest_config_ts["vitest.config.ts"]
file_src_modules_boundaries_boundaries_module_ts --> file_src_modules_boundaries_boundaries_service_ts
file_src_modules_boundaries_boundaries_module_ts --> file_src_modules_boundaries_boundary_cycles_service_ts
file_src_modules_boundaries_boundaries_module_ts --> file_src_modules_boundaries_boundary_report_service_ts
file_src_modules_boundaries_boundaries_module_ts --> file_src_modules_boundaries_boundary_selector_service_ts
file_src_modules_boundaries_boundaries_module_unit_test_ts --> file_src_modules_boundaries_boundaries_module_ts
file_src_modules_boundaries_boundaries_module_unit_test_ts --> file_src_modules_boundaries_boundaries_service_ts
file_src_modules_boundaries_boundaries_module_unit_test_ts --> file_src_modules_boundaries_boundary_cycles_service_ts
file_src_modules_boundaries_boundaries_module_unit_test_ts --> file_src_modules_boundaries_boundary_report_service_ts
file_src_modules_boundaries_boundaries_module_unit_test_ts --> file_src_modules_boundaries_boundary_selector_service_ts
file_src_modules_boundaries_boundaries_service_ts --> file_src_modules_boundaries_boundaries_constants_ts
file_src_modules_boundaries_boundaries_service_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundaries_boundaries_service_ts --> file_src_modules_boundaries_boundary_cycles_service_ts
file_src_modules_boundaries_boundaries_service_ts --> file_src_modules_boundaries_boundary_selector_service_ts
file_src_modules_boundaries_boundaries_service_unit_test_ts --> file_src_modules_boundaries_boundaries_service_ts
file_src_modules_boundaries_boundaries_service_unit_test_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundaries_boundaries_service_unit_test_ts --> file_src_modules_boundaries_boundary_cycles_service_ts
file_src_modules_boundaries_boundaries_service_unit_test_ts --> file_src_modules_boundaries_boundary_selector_service_ts
file_src_modules_boundaries_boundary_cycles_service_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundaries_boundary_cycles_service_unit_test_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundaries_boundary_cycles_service_unit_test_ts --> file_src_modules_boundaries_boundary_cycles_service_ts
file_src_modules_boundaries_boundary_report_service_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundaries_boundary_report_service_unit_test_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundaries_boundary_report_service_unit_test_ts --> file_src_modules_boundaries_boundary_report_service_ts
file_src_modules_boundaries_boundary_selector_service_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundaries_boundary_selector_service_unit_test_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundaries_boundary_selector_service_unit_test_ts --> file_src_modules_boundaries_boundary_selector_service_ts
file_src_modules_boundary_check_boundary_check_constants_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundary_check_boundary_check_module_ts --> file_src_modules_boundaries_boundaries_module_ts
file_src_modules_boundary_check_boundary_check_module_ts --> file_src_modules_boundary_check_boundary_check_service_ts
file_src_modules_boundary_check_boundary_check_module_ts --> file_src_modules_boundary_check_boundary_failure_service_ts
file_src_modules_boundary_check_boundary_check_module_ts --> file_src_modules_boundary_check_boundary_graph_service_ts
file_src_modules_boundary_check_boundary_check_module_ts --> file_src_modules_boundary_check_boundary_outcome_report_service_ts
file_src_modules_boundary_check_boundary_check_module_unit_test_ts --> file_src_modules_boundary_check_boundary_check_module_ts
file_src_modules_boundary_check_boundary_check_module_unit_test_ts --> file_src_modules_boundary_check_boundary_check_service_ts
file_src_modules_boundary_check_boundary_check_module_unit_test_ts --> file_src_modules_boundary_check_boundary_failure_service_ts
file_src_modules_boundary_check_boundary_check_module_unit_test_ts --> file_src_modules_boundary_check_boundary_graph_service_ts
file_src_modules_boundary_check_boundary_check_module_unit_test_ts --> file_src_modules_boundary_check_boundary_outcome_report_service_ts
file_src_modules_boundary_check_boundary_check_service_ts --> file_src_modules_boundaries_boundaries_service_ts
file_src_modules_boundary_check_boundary_check_service_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundary_check_boundary_check_service_ts --> file_src_modules_boundary_check_boundary_check_constants_ts
file_src_modules_boundary_check_boundary_check_service_ts --> file_src_modules_boundary_check_boundary_check_types_ts
file_src_modules_boundary_check_boundary_check_service_ts --> file_src_modules_boundary_check_boundary_failure_service_ts
file_src_modules_boundary_check_boundary_check_service_ts --> file_src_modules_boundary_check_boundary_graph_service_ts
file_src_modules_boundary_check_boundary_check_service_unit_test_ts --> file_src_modules_boundaries_boundaries_service_ts
file_src_modules_boundary_check_boundary_check_service_unit_test_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundary_check_boundary_check_service_unit_test_ts --> file_src_modules_boundary_check_boundary_check_service_ts
file_src_modules_boundary_check_boundary_check_service_unit_test_ts --> file_src_modules_boundary_check_boundary_check_types_ts
file_src_modules_boundary_check_boundary_check_service_unit_test_ts --> file_src_modules_boundary_check_boundary_failure_service_ts
file_src_modules_boundary_check_boundary_check_service_unit_test_ts --> file_src_modules_boundary_check_boundary_graph_service_ts
file_src_modules_boundary_check_boundary_check_types_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundary_check_boundary_failure_service_ts --> file_src_modules_boundary_check_boundary_check_constants_ts
file_src_modules_boundary_check_boundary_failure_service_ts --> file_src_modules_boundary_check_boundary_check_types_ts
file_src_modules_boundary_check_boundary_failure_service_unit_test_ts --> file_src_modules_boundary_check_boundary_check_types_ts
file_src_modules_boundary_check_boundary_failure_service_unit_test_ts --> file_src_modules_boundary_check_boundary_failure_service_ts
file_src_modules_boundary_check_boundary_graph_service_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundary_check_boundary_graph_service_unit_test_ts --> file_src_modules_boundary_check_boundary_graph_service_ts
file_src_modules_boundary_check_boundary_outcome_report_service_ts --> file_src_modules_boundaries_boundary_report_service_ts
file_src_modules_boundary_check_boundary_outcome_report_service_ts --> file_src_modules_boundary_check_boundary_check_constants_ts
file_src_modules_boundary_check_boundary_outcome_report_service_ts --> file_src_modules_boundary_check_boundary_check_types_ts
file_src_modules_boundary_check_boundary_outcome_report_service_unit_test_ts --> file_src_modules_boundaries_boundaries_types_ts
file_src_modules_boundary_check_boundary_outcome_report_service_unit_test_ts --> file_src_modules_boundaries_boundary_report_service_ts
file_src_modules_boundary_check_boundary_outcome_report_service_unit_test_ts --> file_src_modules_boundary_check_boundary_check_types_ts
file_src_modules_boundary_check_boundary_outcome_report_service_unit_test_ts --> file_src_modules_boundary_check_boundary_outcome_report_service_ts
file_src_modules_run_context_run_context_module_ts --> file_src_modules_run_context_run_context_service_ts
file_src_modules_run_context_run_context_module_unit_test_ts --> file_src_modules_run_context_run_context_module_ts
file_src_modules_run_context_run_context_module_unit_test_ts --> file_src_modules_run_context_run_context_service_ts
file_src_modules_run_context_run_context_service_ts --> file_src_modules_run_context_run_context_constants_ts
file_src_modules_run_context_run_context_service_ts --> file_src_modules_run_context_run_context_types_ts
file_src_modules_run_context_run_context_service_unit_test_ts --> file_src_modules_run_context_run_context_service_ts⏲️ Codometer
Project
Measured Targets
TypeScript
JavaScript
Python
JSON
YAML
TOML
Shell
SQL
HCL
CSS
Conventions
Jupyter
Markdown
🔭 Callidescope
Call stacks traced through projects/ic-suite/codependix/codependix-boundaries, deepest first. Each frame shows what it takes, what it returns, and what its documentation says.
| Measure | Value | | --- | --- | | Callables | 139 | | Files | 25 | | Calls traced | 158 | | Call stacks | 7 | | Deepest stack | 12 | | Stacks through recursion | 0 | | Unfollowable calls | 2 |
Limits
What this project is judged against, as declared in its own callidescope.config.ts.
| Limit | Value |
| --- | --- |
| maximumDepth | 12 |
| maximumBreadth | 7 |
Call stacks (depth)
1. BoundaryCheckService.nestjsModules — depth ≥ 12 · orphan-root
🚀 BoundaryCheckService.nestjsModules(levelArguments: LevelCheckArguments): Promise<BoundaryLevelOutcome> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:170]
└─> BoundaryCheckService.runNestjsLevel(args: LevelCheckArguments): Promise<BoundaryLevelOutcome> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:183]
↳ Judges every `framework:nestjs` project's module graph.
└─> BoundaryCheckService.runProjectLevel(…): Promise<BoundaryLevelOutcome> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:254]
↳ Judges every project in the build set at one level, isolating each project's failure.
└─> BoundariesService.evaluate(args: EvaluateBoundariesArguments): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:258]
↳ Every violation one graph's rules report, in the order the rules were declared.
└─> BoundariesService.flatMap(…)(this: undefined, rule: CodependixBoundaryRule): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:259]
└─> BoundariesService.evaluateAcyclicRule(…): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:174]
↳ Reports every cycle an `acyclic` rule's selected nodes still form, each charged to every project owning a node on it:…
└─> BoundarySelectorService.selectIds(…): Set<string> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:106]
↳ The ids of every node a selector claims.
└─> BoundarySelectorService.filter(…)(node: BoundaryNode): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:116]
└─> BoundarySelectorService.matches(node: BoundaryNode, selector: CodependixBoundarySelector): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:86]
↳ Whether a selector claims a node.
└─> BoundarySelectorService.matchesTags(…): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:59]
↳ Whether a node carries a tag matching one of a list of globs.
└─> BoundarySelectorService.some(…)(glob: string): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:71]
└─> BoundarySelectorService.some(…)(tag: string): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:72]2. BoundaryCheckService.python — depth ≥ 12 · orphan-root
🚀 BoundaryCheckService.python(levelArguments: LevelCheckArguments): Promise<BoundaryLevelOutcome> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:173]
└─> BoundaryCheckService.runPythonImportsLevel(args: LevelCheckArguments): Promise<BoundaryLevelOutcome> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:285]
↳ Judges every `language:python` project's file-level import graph.
└─> BoundaryCheckService.runProjectLevel(…): Promise<BoundaryLevelOutcome> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:254]
↳ Judges every project in the build set at one level, isolating each project's failure.
└─> BoundariesService.evaluate(args: EvaluateBoundariesArguments): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:258]
↳ Every violation one graph's rules report, in the order the rules were declared.
└─> BoundariesService.flatMap(…)(this: undefined, rule: CodependixBoundaryRule): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:259]
└─> BoundariesService.evaluateAcyclicRule(…): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:174]
↳ Reports every cycle an `acyclic` rule's selected nodes still form, each charged to every project owning a node on it:…
└─> BoundarySelectorService.selectIds(…): Set<string> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:106]
↳ The ids of every node a selector claims.
└─> BoundarySelectorService.filter(…)(node: BoundaryNode): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:116]
└─> BoundarySelectorService.matches(node: BoundaryNode, selector: CodependixBoundarySelector): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:86]
↳ Whether a selector claims a node.
└─> BoundarySelectorService.matchesTags(…): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:59]
↳ Whether a node carries a tag matching one of a list of globs.
└─> BoundarySelectorService.some(…)(glob: string): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:71]
└─> BoundarySelectorService.some(…)(tag: string): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:72]3. BoundaryCheckService.typescript — depth ≥ 12 · orphan-root
🚀 BoundaryCheckService.typescript(levelArguments: LevelCheckArguments): Promise<BoundaryLevelOutcome> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:175]
└─> BoundaryCheckService.runTypescriptImportsLevel(args: LevelCheckArguments): Promise<BoundaryLevelOutcome> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:299]
↳ Judges every TypeScript project's file-level import graph.
└─> BoundaryCheckService.runProjectLevel(…): Promise<BoundaryLevelOutcome> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:254]
↳ Judges every project in the build set at one level, isolating each project's failure.
└─> BoundariesService.evaluate(args: EvaluateBoundariesArguments): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:258]
↳ Every violation one graph's rules report, in the order the rules were declared.
└─> BoundariesService.flatMap(…)(this: undefined, rule: CodependixBoundaryRule): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:259]
└─> BoundariesService.evaluateAcyclicRule(…): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:174]
↳ Reports every cycle an `acyclic` rule's selected nodes still form, each charged to every project owning a node on it:…
└─> BoundarySelectorService.selectIds(…): Set<string> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:106]
↳ The ids of every node a selector claims.
└─> BoundarySelectorService.filter(…)(node: BoundaryNode): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:116]
└─> BoundarySelectorService.matches(node: BoundaryNode, selector: CodependixBoundarySelector): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:86]
↳ Whether a selector claims a node.
└─> BoundarySelectorService.matchesTags(…): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:59]
↳ Whether a node carries a tag matching one of a list of globs.
└─> BoundarySelectorService.some(…)(glob: string): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:71]
└─> BoundarySelectorService.some(…)(tag: string): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:72]4. BoundaryCheckService.nxProjects — depth 11 · orphan-root
🚀 BoundaryCheckService.nxProjects(levelArguments: LevelCheckArguments): BoundaryLevelOutcome [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:172]
└─> BoundaryCheckService.runNxLevel(args: LevelCheckArguments): BoundaryLevelOutcome [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:209]
↳ Judges the whole-workspace Nx project graph, drawn over the build set so no edge from a judged project into a…
└─> BoundariesService.evaluate(args: EvaluateBoundariesArguments): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:258]
↳ Every violation one graph's rules report, in the order the rules were declared.
└─> BoundariesService.flatMap(…)(this: undefined, rule: CodependixBoundaryRule): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:259]
└─> BoundariesService.evaluateAcyclicRule(…): BoundaryViolation[] [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:174]
↳ Reports every cycle an `acyclic` rule's selected nodes still form, each charged to every project owning a node on it:…
└─> BoundarySelectorService.selectIds(…): Set<string> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:106]
↳ The ids of every node a selector claims.
└─> BoundarySelectorService.filter(…)(node: BoundaryNode): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:116]
└─> BoundarySelectorService.matches(node: BoundaryNode, selector: CodependixBoundarySelector): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:86]
↳ Whether a selector claims a node.
└─> BoundarySelectorService.matchesTags(…): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:59]
↳ Whether a node carries a tag matching one of a list of globs.
└─> BoundarySelectorService.some(…)(glob: string): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:71]
└─> BoundarySelectorService.some(…)(tag: string): boolean [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:72]5. BoundaryCheckService.buildGraph — depth 9 · orphan-root
🚀 BoundaryCheckService.buildGraph(project: PythonProject): BoundaryGraph [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:289]
└─> PythonService.buildGraph(project: PythonProject): PythonImportGraph [projects/ic-suite/codependix/codependix-file-imports/src/modules/python/python.service.ts:39]
↳ Builds a Python project's internal file-level import Graph.
└─> PythonImportGraphService.buildGraph(project: PythonProject): PythonImportGraph [projects/ic-suite/codependix/codependix-file-imports/src/modules/python/python-import-graph.service.ts:180]
↳ Builds a Python project's internal file-level import Graph.
└─> PythonImportGraphService.flatMap(…)(this: undefined, sourceFileName: string): PythonImportGraphEdge[] [projects/ic-suite/codependix/codependix-file-imports/src/modules/python/python-import-graph.service.ts:185]
└─> PythonImportGraphService.collectEdgesForFile(…): PythonImportGraphEdge[] [projects/ic-suite/codependix/codependix-file-imports/src/modules/python/python-import-graph.service.ts:64]
↳ Collects every internal import edge one source file declares.
└─> PythonImportParserService.parseImportSpecifiers(source: string): PythonImportSpecifier[] [projects/ic-suite/codependix/codependix-file-imports/src/modules/python/python-import-parser.service.ts:158]
↳ Parses every module-level import statement in a Python source file.
└─> PythonImportParserService.parseStatement(statement: string): PythonImportSpecifier[] [projects/ic-suite/codependix/codependix-file-imports/src/modules/python/python-import-parser.service.ts:126]
↳ Parses one joined statement into the module(s) it names.
└─> PythonImportParserService.parseImportStatement(statement: string): PythonImportSpecifier[] [projects/ic-suite/codependix/codependix-file-imports/src/modules/python/python-import-parser.service.ts:105]
↳ Parses a joined `import <specifiers>` statement.
└─> PythonImportParserService.map(…)(modulePath: string): { level: number; modulePath: string; } [projects/ic-suite/codependix/codependix-file-imports/src/modules/python/python-import-parser.service.ts:122]6. BoundaryCheckService.buildGraph — depth ≥ 7 · orphan-root
🚀 BoundaryCheckService.buildGraph(project: TypescriptProject): BoundaryGraph [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:303]
└─> TypescriptService.buildGraph(projectProgram: TypescriptProjectProgram): TypescriptImportGraph [projects/ic-suite/codependix/codependix-file-imports/src/modules/typescript/typescript.service.ts:44]
↳ Builds a project's internal file-level import Graph from its program.
└─> TypescriptImportGraphService.buildGraph(projectProgram: TypescriptProjectProgram): TypescriptImportGraph [projects/ic-suite/codependix/codependix-file-imports/src/modules/typescript/typescript-import-graph.service.ts:185]
↳ Builds a project's internal file-level import Graph from its program.
└─> TypescriptImportGraphService.listOwnedSourceFileNames(projectProgram: TypescriptProjectProgram): string[] [projects/ic-suite/codependix/codependix-file-imports/src/modules/typescript/typescript-import-graph.service.ts:122]
↳ Lists a program's own source files, excluding declaration files. `program.getRootFileNames()` is the same file list…
└─> TypescriptImportGraphService.resolveOwnedFileNames(projectProgram: TypescriptProjectProgram): Set<string> [projects/ic-suite/codependix/codependix-file-imports/src/modules/typescript/typescript-import-graph.service.ts:156]
↳ Resolves the real, absolute file names a program owns.
└─> TypescriptImportGraphService.map(…)(fileName: string): string [projects/ic-suite/codependix/codependix-file-imports/src/modules/typescript/typescript-import-graph.service.ts:162]
└─> TypescriptProjectService.toRealPath(filePath: string): string [projects/ic-suite/codependix/codependix-file-imports/src/modules/typescript/typescript-project.service.ts:122]
↳ Resolves a path through symlinks, which is how pnpm workspaces link.7. BoundaryCheckService.buildGraph — depth ≥ 5 · orphan-root
🚀 BoundaryCheckService.buildGraph(project: NestjsProject): Promise<BoundaryGraph> [projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:187]
└─> ModuleGraphService.buildGraph(tree: NestjsExploredModule[], projectName: string): NestjsModuleGraph [projects/ic-suite/codependix/codependix-nestjs-modules/src/modules/module-graph/module-graph.service.ts:168]
↳ Reduces an explored container to a Graph of its module imports.
└─> ModuleGraphService.collectEdgesAndNodes(…): { connectedModuleNames: Set<string>; edges: NestjsModuleGraphEdge[]; nodes: NestjsModuleGraphNode[]; } [projects/ic-suite/codependix/codependix-nestjs-modules/src/modules/module-graph/module-graph.service.ts:49]
↳ Walks the tree into the edges worth drawing and the nodes they touch.
└─> ModuleGraphService.addNode(name: string, declaringFile: string): void [projects/ic-suite/codependix/codependix-nestjs-modules/src/modules/module-graph/module-graph.service.ts:61]
└─> ModuleGraphService.some(…)(node: NestjsModuleGraphNode): boolean [projects/ic-suite/codependix/codependix-nestjs-modules/src/modules/module-graph/module-graph.service.ts:64]Breadth
| Callable | Breadth | Calls directly | Location |
| --- | --- | --- | --- |
| RunContextService.build | 7 | RunContextService.loadConfiguration, NeighborhoodService.readProjectGraph, RunContextService.resolveProjectGraphPath, NeighborhoodService.readProjects, RunContextService.loadProjectConfigurations, RunContextService.resolveProjectSets, RunContextService.resolveEnabledGraphTypes | projects/ic-suite/codependix/codependix-boundaries/src/modules/run-context/run-context.service.ts:246 |
| BoundaryCheckService.run | 6 | BoundaryCheckService.graphTypeForLevel, BoundaryCheckService.rulesForLevel, BoundaryCheckService.runLevel, BoundaryCheckService.judge, BoundaryCheckService.flatMap(…), BoundaryCheckService.flatMap(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:330 |
| BoundaryOutcomeReportService.renderMarkdown | 6 | BoundaryOutcomeReportService.findWorkspaceFailures, BoundaryOutcomeReportService.flatMap(…), BoundaryOutcomeReportService.flatMap(…), BoundaryOutcomeReportService.findProjectFailures, BoundaryOutcomeReportService.renderWorkspaceGroup, BoundaryOutcomeReportService.map(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-outcome-report.service.ts:240 |
| Callable | Breadth | Calls directly | Location |
| --- | --- | --- | --- |
| BoundariesService.evaluateAccessRule | 5 | BoundariesService.indexNodes, BoundariesService.judgesEdge, BoundariesService.resolveNode, BoundarySelectorService.matches, BoundariesService.buildAccessViolation | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:137 |
| BoundaryCheckService.runNxLevel | 5 | BoundaryGraphService.buildNxGraph, WorkspaceGraphService.buildWorkspaceGraph, BoundariesService.evaluate, BoundaryFailureService.collect, BoundaryCheckService.map(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:209 |
| BoundaryOutcomeReportService.renderProjectGroup | 5 | BoundaryOutcomeReportService.map(…), BoundaryOutcomeReportService.filter(…), BoundaryOutcomeReportService.map(…), BoundaryOutcomeReportService.filter(…), BoundaryOutcomeReportService.findProjectFailures | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-outcome-report.service.ts:122 |
| BoundariesService.evaluateAcyclicRule | 4 | BoundariesService.indexNodes, BoundarySelectorService.selectIds, BoundaryCyclesService.findCycles, BoundariesService.map(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:174 |
| BoundaryFailureService.resolveOwnerProject | 4 | NeighborhoodService.resolveDependencyClosure, BoundaryFailureService.filter(…), BoundaryFailureService.readFramePath, BoundaryFailureService.findProjectHolding | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-failure.service.ts:127 |
| BoundarySelectorService.selectIds | 3 | BoundarySelectorService.map(…), BoundarySelectorService.map(…), BoundarySelectorService.filter(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:106 |
| BoundariesService.map(…) | 3 | BoundariesService.buildMessage, describeCycle, BoundariesService.chargeProjects | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:186 |
| BoundaryCheckService.judge | 3 | BoundaryCheckService.map(…), BoundaryCheckService.map(…), BoundaryCheckService.map(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:101 |
| BoundaryCheckService.buildGraph | 3 | BoundaryGraphService.buildNestjsGraph, ModuleGraphService.buildGraph, NestjsProjectService.exploreProject | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:187 |
| BoundaryCheckService.buildGraph | 3 | BoundaryGraphService.buildTypescriptImportGraph, TypescriptService.buildGraph, TypescriptService.buildProgram | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:303 |
| RunContextService.resolveBuildProjects | 3 | NeighborhoodService.resolveDependencyClosure, RunContextService.map(…), RunContextService.filter(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/run-context/run-context.service.ts:128 |
| RunContextService.resolveProjectSets | 3 | RunContextService.selectProjects, emptySelectionError, RunContextService.resolveBuildProjects | projects/ic-suite/codependix/codependix-boundaries/src/modules/run-context/run-context.service.ts:191 |
| BoundaryCyclesService.findCycles | 2 | BoundaryCyclesService.buildAdjacency, BoundaryCyclesService.walk | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-cycles.service.ts:127 |
| BoundarySelectorService.matches | 2 | BoundarySelectorService.matchesGlobs, BoundarySelectorService.matchesTags | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:86 |
| BoundariesService.buildAccessViolation | 2 | BoundariesService.buildMessage, BoundariesService.chargeProjects | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:58 |
| BoundariesService.chargeProjects | 2 | BoundariesService.map(…), BoundariesService.toSorted(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:113 |
| BoundariesService.flatMap(…) | 2 | BoundariesService.evaluateAcyclicRule, BoundariesService.evaluateAccessRule | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:259 |
| BoundaryFailureService.findProjectHolding | 2 | BoundaryFailureService.filter(…), BoundaryFailureService.toSorted(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-failure.service.ts:51 |
| BoundaryGraphService.buildNxGraph | 2 | BoundaryGraphService.map(…), BoundaryGraphService.map(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-graph.service.ts:101 |
| BoundaryCheckService.runNestjsLevel | 2 | BoundaryCheckService.runProjectLevel, NestjsProjectService.discoverProjects | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:183 |
| BoundaryCheckService.runProjectLevel | 2 | BoundariesService.evaluate, BoundaryFailureService.collect | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:254 |
| BoundaryCheckService.runPythonImportsLevel | 2 | BoundaryCheckService.runProjectLevel, PythonService.discoverProjects | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:285 |
| BoundaryCheckService.buildGraph | 2 | BoundaryGraphService.buildPythonImportGraph, PythonService.buildGraph | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:289 |
| BoundaryCheckService.runTypescriptImportsLevel | 2 | BoundaryCheckService.runProjectLevel, TypescriptService.discoverProjects | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-check.service.ts:299 |
| BoundaryOutcomeReportService.map(…) | 2 | BoundaryOutcomeReportService.renderBullet, BoundaryOutcomeReportService.renderViolation | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-outcome-report.service.ts:130 |
| BoundaryOutcomeReportService.map(…) | 2 | BoundaryOutcomeReportService.renderBullet, BoundaryOutcomeReportService.renderFailure | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-outcome-report.service.ts:135 |
| BoundaryOutcomeReportService.renderWorkspaceGroup | 2 | BoundaryOutcomeReportService.map(…), BoundaryOutcomeReportService.findWorkspaceFailures | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-outcome-report.service.ts:166 |
| BoundaryOutcomeReportService.map(…) | 2 | BoundaryOutcomeReportService.renderBullet, BoundaryOutcomeReportService.renderFailure | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-outcome-report.service.ts:167 |
| BoundaryOutcomeReportService.buildReport | 2 | BoundaryOutcomeReportService.map(…), BoundaryOutcomeReportService.map(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundary-check/boundary-outcome-report.service.ts:187 |
| RunContextService.findUnmatchedSelection | 2 | RunContextService.filter(…), RunContextService.filter(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/run-context/run-context.service.ts:299 |
| BoundaryCyclesService.recordCycle | 1 | BoundaryCyclesService.buildCycleKey | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-cycles.service.ts:73 |
| BoundaryCyclesService.walk | 1 | BoundaryCyclesService.recordCycle | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-cycles.service.ts:91 |
| BoundarySelectorService.matchesGlobs | 1 | BoundarySelectorService.some(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:37 |
| BoundarySelectorService.matchesTags | 1 | BoundarySelectorService.some(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:59 |
| BoundarySelectorService.some(…) | 1 | BoundarySelectorService.some(…) | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:71 |
| BoundarySelectorService.filter(…) | 1 | BoundarySelectorService.matches | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundary-selector.service.ts:116 |
| BoundariesService.map(…) | 1 | BoundariesService.resolveNode | projects/ic-suite/codependix/codependix-boundaries/src/modules/boundaries/boundaries.service.ts:120 |
| BoundariesService.indexNodes | 1 | BoundariesService.map(…) | `projects/ic-suite/codependix/codependix-boun
