@callidescope/nx
v0.0.30
Published
Nx plugin providing project-scoped call-stack tracing and depth gating along Nx dependency graphs
Maintainers
Readme
🔭🧬 Callidescope Nx
An Nx plugin that traces call stacks per project, following the Nx dependency graph.
Canonical documentation for call-stack tracing, configuration, depth and breadth analysis, and report formats is in the
@callidescope/cli README.
@callidescope/cli is Nx-free on purpose: it takes --directories, each one a path holding its own tsconfig.json, so it
works in any TypeScript workspace whether or not Nx is anywhere near it. This
package is the one place in the toolchain that knows Nx exists, and the only
one that depends on @nx/devkit.
It adds two things the core CLI cannot know about:
- A target on every project, so the workspace's task runner does the
selecting —
nx affected,--projects=tag:…, caching, and all. - Dependency-aware scope, so a run over one project is scoped to everything that project depends on rather than to the project alone.
Install
npm install --save-dev @callidescope/nxRegister it in nx.json:
{
"plugins": [
{
"plugin": "@callidescope/nx",
"options": {
"configurationPath": "projects/configuration/callidescope.config.ts"
}
}
]
}| Option | Meaning |
| ------ | ------- |
| configurationPath | Required. Where the workspace callidescope configuration lives. Nothing is searched for: a registration that omits it is refused, naming this option. The refusal is decided by @callidescope/configuration, which every surface shares |
| traceTargetName | Name of the inferred trace target. trace when omitted |
| depthTargetName | Name of the inferred depth target. depth when omitted |
| breadthTargetName | Name of the inferred breadth target. breadth when omitted |
| gateTargetName | Name of the inferred gate target. gate when omitted |
The target names are short because they read better on the command line than repeating the tool's name on both sides of the colon. Rename any of them from the registration if a workspace already uses one.
Usage
Four targets are inferred onto every project holding a tsconfig.json, so
selection is Nx's job rather than a flag of this package's own:
nx run callidescope-nx:trace # one project, with its dependencies
nx run-many -t trace # the workspace
nx run-many -t trace --projects=tag:type:package # a category
nx affected -t trace # only what changednx run callidescope-nx:depth --addresses="projects/ic-suite/callidescope/callidescope-nx/src/modules/projects/projects.service.ts#ProjectsService.resolveDependencyClosure"
nx run callidescope-nx:breadth --addresses="src/foo.service.ts#FooService.bar"
# Several at once, which is what a rename spanning a handful of them needs
nx run callidescope-nx:depth --addresses="src/a.service.ts#A.b,src/c.service.ts#C.d"| Target | Answers |
| ------ | ------- |
| gate | Whether anything in the project broke the limits it is held to |
| trace | Every call stack in the project, and which ones broke a limit |
| depth | Every stack above and below each callable — callers up to a root, callees down to a leaf |
| breadth | Each callable's direct callers and callees, side by side |
depth and breadth take the same <file>#<qualified-name> addresses the
callidescope command does — the form every printed stack already uses — and
the same comma-separated --addresses flag it takes them through. Through the
plugin they resolve against the project and its dependencies rather than the
whole workspace, which is both faster and the set the addresses belong to.
Every address must resolve, or the task prints nothing. A report covering
only the addresses that were understood, under a task Nx recorded as
successful, is worse than a failed one; each unmatched address is named and
the task fails. Under --format=json the report is always an array, whatever
the address count, matching what the command line prints.
Unlike the command line, a missing --addresses is refused rather than
prompted for: a task runner has nobody to ask.
The gate
gate is the one of the four a pipeline is meant to read an exit code from,
and the only one that prints nothing but its findings — the stacks and callables that
decided the verdict, rather than every stack in the project. nx affected -t gate
therefore gates a branch by the projects it changed, and the task that fails is
named after the project that regressed, which one workspace-wide task never
could.
A dependency's breach is that dependency's gate's business. The trace
reaches into the projects a gate's project depends on, because a stack that
stops at a package boundary measures the wrong thing — but the verdict covers
only the projects the task was scoped to. This is the line the publishing side
already draws, one step further along: measurement reaches into dependencies,
publishing does not, and judging does not either. Nothing escapes a verdict,
because nx affected selects a changed dependency too and its own gate names
it. trace narrows its verdict the same way, so the two targets on one project
can never disagree about whose regression it was; its report still shows the
whole closure, since only the verdict narrows.
Depth is gated always, breadth wherever a limit exists. Not two modes to be
selected between: maximumDepth has a default, so every project has a number
and is judged by it, while maximumBreadth has none at any level — so a project
that declared no breadth limit is judged against Infinity and can produce no
breadth finding at all.
A gate that opened none of the judged project's own files fails. A project
reporting zero files of its own is not a clean project — it is a project
nothing looked at, and a green task there would say the opposite with nothing
in the output to correct it. The callidescope command fails the same case for
the same reason.
trace prints that same block and passes on it — the one rule the two
targets act on differently, and the only place their verdicts part. A project
the configuration excludes reads nothing of its own by definition and is given
no gate for exactly that reason, so failing its trace as well would leave
the one target it has permanently red for being configured as it was asked to
be, and a red task that is always red is one a reader learns to ignore. It
still prints, because whether a project's own code was read is a fact about the
run either way and a reader has to be able to see it. Everything else — a stack
over a depth limit, a callable over a breadth limit, a run that read nothing at
all — fails both.
Asked per judged project, not of the whole run, because narrowing the
verdict made those two different questions. A project with dependencies has a
non-empty run whatever became of its own sources, so an exclude that
over-matches — which a project's own callidescope.config.* may write — leaves
it owning no report content, owning no finding, and passing green over code
nothing read. Demonstrated: projects/ic-suite/codometer/codometer-output given
{"exclude": ["**"]} of its own traces its dependency's 102 callables and
contributes none, which is a green gate on the run-wide question and a red one
on this. The projects that went unread are named back, since --projects may
judge several.
Files rather than callables, which is the weaker question and the right
one. A project can hold files that declare no callable at all — one whose
tsconfig.json names only its own configuration files and its tests is the
shape, and this repository has five — and those files were read, so a verdict
on them is a verdict on something. Asking for a callable fails all five for
holding no functions, which is a finding about nothing. The cost, stated
plainly: a project whose sources are excluded while a configuration file of its
own survives counts as read.
Two adjacent cases fail alongside it, each saying what happened rather than failing mutely: a run that read nothing at all, which is what an unread leaf project looks like, and an Nx selection that resolved to no directory.
Its cache key names the project's own callidescope.config.* alongside the
workspace configuration, so editing one project's limits re-runs that project's
gate and no other project's. A dependency's sources are covered by ^default,
because a run measures its dependencies even though it does not judge them.
Two projects are deliberately skipped by all four targets: the workspace-root
project, whose targets would trace everything under one uncacheable task, and
any project with no tsconfig.json, whose targets would be permanently
empty. A project the configuration excludes — exclude or excludeFrom in
the workspace file — additionally gets no gate: its own code is never traced,
so a gate there would own no finding at all and report green for code it never
read. It keeps the three that print something, trace included, which is what
the unread exemption above is there to preserve: projects/ic-suite/callidescope/callidescope-examples
is the case, and its stacks are still a report a reader can open.
Why the trace follows dependencies
nx run callidescope-cli:trace traces callidescope-cli and
everything it depends on, resolved transitively from the Nx project graph.
A call stack runs downward — a command calls into the service it was injected with, which lives in a package it depends on — so a trace that stopped at a project's own boundary would measure the wrong thing.
A trace does not stop there without this plugin.
@callidescope/cli builds a TypeScript
program for every project the directories it was given transitively import, so
a call into a dependency resolves to a real frame whether or not Nx is
involved. Measured on this package,
callidescope --config projects/configuration/callidescope.config.ts --directories projects/ic-suite/callidescope/callidescope-nx and
nx run callidescope-nx:trace report the same 575 callables across 185 files
in 7 projects.
What the Nx graph decides is which projects the run is scoped to rather
than merely reaches. This executor writes nothing anywhere — it renders one
report and prints it — so the distinction costs nothing here, and widening the
selection changes only which projects seed the closure. It is the command-line
host that acts on it: a --write run there publishes a ## 🔭 Callidescope
section into a scoped project's README.md and leaves a reached one's to the
run that is scoped to it. The graph also names dependencies no import closure
can find — an implicit dependency, or an edge that exists only at run time.
The two sets are not the same. The Nx graph gives callidescope-nx six
projects; the import closure reaches seven, adding codometer-configuration,
which this project's tsconfig.json pulls in through its own
codometer.config.ts — a file the manifest has no reason to mention.
Dependencies, never dependents: a project's dependents call into it and add no frames below it.
Pass --withDependencies=false to scope the run to the selected projects
alone. The closure below them is built either way, so what changes is which
projects the run calls its own — not how far a stack runs.
Executor options
nx run logging:trace --tags=type:package
nx run logging:depth --addresses="a.ts#A.b" --projects=callidescope-cliAll three executors take the same scoping options.
| Option | Meaning |
| ------ | ------- |
| addresses | depth and breadth only, and required: the callables to look up, comma-separated |
| projects | Nx project names to resolve against, replacing the target's own project |
| tags | Nx project tags, selecting every project carrying any of them |
| withDependencies | Widen along the Nx dependency graph. true by default |
| format | markdown, mermaid, or json |
| configuration | Required, and written onto every inferred target from the registration's configurationPath. A hand-written target must name it itself, or is refused naming this option |
--projects and --tags union rather than intersect, and a project reached
both ways is still traced once. --tags matches any of the tags given,
because Nx tag families are mutually exclusive on a single project — nothing is
both type:application and type:package, so requiring all of them would
select nothing.
Prefer Nx's own --projects=tag:… on run-many for ordinary selection; these
options exist for a target that wants to declare a fixed scope in its
project.json.
Nothing resolves silently to less
A project name the workspace does not have, or a tag no project carries, fails the task and names the workspace's actual vocabulary. Narrowing the run instead would let it pass while measuring less than it was asked to — and a report of what a run did cover cannot show you what it did not.
As a library
The Nx-graph reading is a NestJS provider, for a host that would rather import it than run a task:
import { resolveProjectsService } from "@callidescope/nx";
const projectsService = await resolveProjectsService();
const graph = await projectsService.readProjectGraph();
const names = projectsService.resolveDependencyClosure({
graph,
projectNames: ["callidescope-cli"],
});
const directories = projectsService.toDirectories({ graph, projectNames: names });readProjectGraph is the only method that touches Nx at run time; every
resolution rule takes the graph as an argument, so it can be exercised without
a workspace to build one from.
Packages
| Package | Role |
| ------- | ---- |
| @callidescope/nx | Nx plugin: per-project trace targets, resolved through the Nx graph |
| @callidescope/cli | Orchestrates a run: traces the workspace, plans what to check, and reports |
| @callidescope/configuration | Reads callidescope.config.ts and resolves the limits |
| @callidescope/graph | Builds the call graph from traced source and measures depth and breadth |
| @callidescope/output | Renders findings into markdown, mermaid, and JSON |
Test
nx run callidescope-nx:vitestContributing
nx run callidescope-nx:lint-code --configuration=checkLicense
MIT — see LICENSE.
👔 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
callidescope_cli["callidescope-cli"]
callidescope_configuration["callidescope-configuration"]
callidescope_core["callidescope-core"]
callidescope_graph["callidescope-graph"]
callidescope_nx["callidescope-nx"]
callidescope_output["callidescope-output"]
logging["logging"]
callidescope_nx --> callidescope_cli
callidescope_nx --> callidescope_configuration
callidescope_nx --> callidescope_core
callidescope_nx --> callidescope_graph
callidescope_nx --> callidescope_output
callidescope_nx --> logging
classDef subject fill:#7c3aed,color:#fff,stroke:#4c1d95,stroke-width:2px
class callidescope_nx subjectNestJS Module Graph
flowchart LR
AddressLookupModule
AddressModule
AddressReportModule
CallablesModule
CallidescopeModule
ClassesModule
ConfigurationFileModule
ConfigurationModule
DocumentationModule
EdgesModule
EntriesModule
FlagResolutionModule
GraphModule
InputModule
LoggerModule([LoggerModule])
MainModule
OptionsModule
OutputJsonModule
OutputMarkdownModule
PluginModule
ProgramModule
ProjectReportsModule
ProjectsModule
ReportFindingsModule
ReportModule
RunConfigurationModule
RunPlanModule
SignaturesModule
WorkspaceModule
WriteDestinationsModule
AddressLookupModule --> CallablesModule
AddressLookupModule --> CallidescopeModule
AddressLookupModule --> ConfigurationModule
AddressModule --> AddressLookupModule
AddressModule --> AddressReportModule
AddressModule --> GraphModule
AddressReportModule --> ReportModule
CallablesModule --> ProgramModule
CallablesModule --> WorkspaceModule
CallidescopeModule --> CallablesModule
CallidescopeModule --> ClassesModule
CallidescopeModule --> ConfigurationModule
CallidescopeModule --> EdgesModule
CallidescopeModule --> EntriesModule
CallidescopeModule --> GraphModule
CallidescopeModule --> OutputJsonModule
CallidescopeModule --> OutputMarkdownModule
CallidescopeModule --> ProgramModule
CallidescopeModule --> ProjectReportsModule
CallidescopeModule --> ReportFindingsModule
CallidescopeModule --> ReportModule
CallidescopeModule --> WorkspaceModule
CallidescopeModule --> WriteDestinationsModule
ConfigurationModule --> ConfigurationFileModule
ConfigurationModule --> InputModule
ConfigurationModule --> RunPlanModule
EdgesModule --> CallablesModule
EdgesModule --> ClassesModule
EdgesModule --> ProgramModule
EdgesModule --> WorkspaceModule
EntriesModule --> CallablesModule
GraphModule --> DocumentationModule
GraphModule --> EdgesModule
GraphModule --> SignaturesModule
MainModule --> AddressModule
MainModule --> PluginModule
OptionsModule --> ConfigurationModule
PluginModule --> CallidescopeModule
PluginModule --> ConfigurationModule
PluginModule --> OptionsModule
PluginModule --> ProjectReportsModule
PluginModule --> ProjectsModule
PluginModule --> ReportModule
PluginModule --> RunConfigurationModule
PluginModule --> WorkspaceModule
ProgramModule --> WorkspaceModule
ProjectReportsModule --> GraphModule
ProjectReportsModule --> SignaturesModule
RunConfigurationModule --> ConfigurationModule
RunPlanModule --> FlagResolutionModule
WriteDestinationsModule --> OutputJsonModule
WriteDestinationsModule --> OutputMarkdownModule
WriteDestinationsModule --> ReportModuleRounded 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_callidescope_nx_module_ts["src/callidescope-nx.module.ts"]
file_src_executors_address_types_ts["src/executors/address.types.ts"]
file_src_executors_breadth_executor_ts["src/executors/breadth/executor.ts"]
file_src_executors_breadth_executor_unit_test_ts["src/executors/breadth/executor.unit.test.ts"]
file_src_executors_depth_executor_ts["src/executors/depth/executor.ts"]
file_src_executors_depth_executor_unit_test_ts["src/executors/depth/executor.unit.test.ts"]
file_src_executors_gate_executor_integration_test_ts["src/executors/gate/executor.integration.test.ts"]
file_src_executors_gate_executor_ts["src/executors/gate/executor.ts"]
file_src_executors_gate_executor_types_ts["src/executors/gate/executor.types.ts"]
file_src_executors_gate_executor_unit_test_ts["src/executors/gate/executor.unit.test.ts"]
file_src_executors_manifest_unit_test_ts["src/executors/manifest.unit.test.ts"]
file_src_executors_trace_executor_ts["src/executors/trace/executor.ts"]
file_src_executors_trace_executor_types_ts["src/executors/trace/executor.types.ts"]
file_src_executors_trace_executor_unit_test_ts["src/executors/trace/executor.unit.test.ts"]
file_src_index_ts["src/index.ts"]
file_src_index_unit_test_ts["src/index.unit.test.ts"]
file_src_modules_address_address_constants_ts["src/modules/address/address.constants.ts"]
file_src_modules_address_address_module_ts["src/modules/address/address.module.ts"]
file_src_modules_address_address_service_ts["src/modules/address/address.service.ts"]
file_src_modules_address_address_service_unit_test_ts["src/modules/address/address.service.unit.test.ts"]
file_src_modules_address_address_types_ts["src/modules/address/address.types.ts"]
file_src_modules_address_address_utilities_ts["src/modules/address/address.utilities.ts"]
file_src_modules_address_address_utilities_unit_test_ts["src/modules/address/address.utilities.unit.test.ts"]
file_src_modules_options_options_constants_ts["src/modules/options/options.constants.ts"]
file_src_modules_options_options_module_ts["src/modules/options/options.module.ts"]
file_src_modules_options_options_service_ts["src/modules/options/options.service.ts"]
file_src_modules_options_options_service_unit_test_ts["src/modules/options/options.service.unit.test.ts"]
file_src_modules_options_options_types_ts["src/modules/options/options.types.ts"]
file_src_modules_plugin_plugin_context_utilities_ts["src/modules/plugin/plugin-context.utilities.ts"]
file_src_modules_plugin_plugin_context_utilities_unit_test_ts["src/modules/plugin/plugin-context.utilities.unit.test.ts"]
file_src_modules_plugin_plugin_constants_ts["src/modules/plugin/plugin.constants.ts"]
file_src_modules_plugin_plugin_module_ts["src/modules/plugin/plugin.module.ts"]
file_src_modules_plugin_plugin_service_ts["src/modules/plugin/plugin.service.ts"]
file_src_modules_plugin_plugin_service_unit_test_ts["src/modules/plugin/plugin.service.unit.test.ts"]
file_src_modules_plugin_plugin_types_ts["src/modules/plugin/plugin.types.ts"]
file_src_modules_plugin_plugin_utilities_ts["src/modules/plugin/plugin.utilities.ts"]
file_src_modules_projects_projects_constants_ts["src/modules/projects/projects.constants.ts"]
file_src_modules_projects_projects_module_ts["src/modules/projects/projects.module.ts"]
file_src_modules_projects_projects_service_ts["src/modules/projects/projects.service.ts"]
file_src_modules_projects_projects_service_unit_test_ts["src/modules/projects/projects.service.unit.test.ts"]
file_src_modules_projects_projects_types_ts["src/modules/projects/projects.types.ts"]
file_src_modules_run_configuration_run_configuration_constants_ts["src/modules/run-configuration/run-configuration.constants.ts"]
file_src_modules_run_configuration_run_configuration_module_ts["src/modules/run-configuration/run-configuration.module.ts"]
file_src_modules_run_configuration_run_configuration_service_ts["src/modules/run-configuration/run-configuration.service.ts"]
file_src_modules_run_configuration_run_configuration_service_unit_test_ts["src/modules/run-configuration/run-configuration.service.unit.test.ts"]
file_src_modules_run_configuration_run_configuration_types_ts["src/modules/run-configuration/run-configuration.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_callidescope_nx_module_ts --> file_src_modules_address_address_module_ts
file_src_callidescope_nx_module_ts --> file_src_modules_plugin_plugin_module_ts
file_src_executors_breadth_executor_ts --> file_src_executors_address_types_ts
file_src_executors_breadth_executor_ts --> file_src_modules_address_address_utilities_ts
file_src_executors_breadth_executor_unit_test_ts --> file_src_executors_breadth_executor_ts
file_src_executors_breadth_executor_unit_test_ts --> file_src_modules_address_address_utilities_ts
file_src_executors_depth_executor_ts --> file_src_executors_address_types_ts
file_src_executors_depth_executor_ts --> file_src_modules_address_address_utilities_ts
file_src_executors_depth_executor_unit_test_ts --> file_src_executors_depth_executor_ts
file_src_executors_depth_executor_unit_test_ts --> file_src_modules_address_address_utilities_ts
file_src_executors_gate_executor_integration_test_ts --> file_src_executors_gate_executor_ts
file_src_executors_gate_executor_integration_test_ts --> file_src_executors_gate_executor_types_ts
file_src_executors_gate_executor_integration_test_ts --> file_src_modules_plugin_plugin_constants_ts
file_src_executors_gate_executor_integration_test_ts --> file_src_modules_projects_projects_service_ts
file_src_executors_gate_executor_ts --> file_src_executors_gate_executor_types_ts
file_src_executors_gate_executor_ts --> file_src_modules_plugin_plugin_context_utilities_ts
file_src_executors_gate_executor_ts --> file_src_modules_plugin_plugin_constants_ts
file_src_executors_gate_executor_ts --> file_src_modules_plugin_plugin_utilities_ts
file_src_executors_gate_executor_unit_test_ts --> file_src_executors_gate_executor_ts
file_src_executors_gate_executor_unit_test_ts --> file_src_modules_options_options_service_ts
file_src_executors_gate_executor_unit_test_ts --> file_src_modules_plugin_plugin_constants_ts
file_src_executors_gate_executor_unit_test_ts --> file_src_modules_plugin_plugin_service_ts
file_src_executors_gate_executor_unit_test_ts --> file_src_modules_plugin_plugin_types_ts
file_src_executors_trace_executor_ts --> file_src_executors_trace_executor_types_ts
file_src_executors_trace_executor_ts --> file_src_modules_plugin_plugin_context_utilities_ts
file_src_executors_trace_executor_ts --> file_src_modules_plugin_plugin_utilities_ts
file_src_executors_trace_executor_unit_test_ts --> file_src_executors_trace_executor_ts
file_src_executors_trace_executor_unit_test_ts --> file_src_modules_options_options_service_ts
file_src_executors_trace_executor_unit_test_ts --> file_src_modules_plugin_plugin_service_ts
file_src_executors_trace_executor_unit_test_ts --> file_src_modules_plugin_plugin_types_ts
file_src_index_ts --> file_src_modules_plugin_plugin_context_utilities_ts
file_src_index_ts --> file_src_modules_plugin_plugin_constants_ts
file_src_index_unit_test_ts --> file_src_index_ts
file_src_index_unit_test_ts --> file_src_modules_plugin_plugin_service_ts
file_src_index_unit_test_ts --> file_src_modules_plugin_plugin_types_ts
file_src_modules_address_address_module_ts --> file_src_modules_address_address_service_ts
file_src_modules_address_address_service_ts --> file_src_modules_address_address_types_ts
file_src_modules_address_address_service_unit_test_ts --> file_src_modules_address_address_service_ts
file_src_modules_address_address_utilities_ts --> file_src_executors_address_types_ts
file_src_modules_address_address_utilities_ts --> file_src_modules_plugin_plugin_context_utilities_ts
file_src_modules_address_address_utilities_ts --> file_src_modules_plugin_plugin_utilities_ts
file_src_modules_address_address_utilities_unit_test_ts --> file_src_modules_address_address_service_ts
file_src_modules_address_address_utilities_unit_test_ts --> file_src_modules_address_address_utilities_ts
file_src_modules_address_address_utilities_unit_test_ts --> file_src_modules_options_options_service_ts
file_src_modules_address_address_utilities_unit_test_ts --> file_src_modules_plugin_plugin_service_ts
file_src_modules_address_address_utilities_unit_test_ts --> file_src_modules_plugin_plugin_types_ts
file_src_modules_options_options_module_ts --> file_src_modules_options_options_service_ts
file_src_modules_options_options_service_ts --> file_src_modules_options_options_constants_ts
file_src_modules_options_options_service_ts --> file_src_modules_options_options_types_ts
file_src_modules_options_options_service_unit_test_ts --> file_src_modules_options_options_constants_ts
file_src_modules_options_options_service_unit_test_ts --> file_src_modules_options_options_service_ts
file_src_modules_plugin_plugin_context_utilities_ts --> file_src_callidescope_nx_module_ts
file_src_modules_plugin_plugin_context_utilities_ts --> file_src_modules_address_address_service_ts
file_src_modules_plugin_plugin_context_utilities_ts --> file_src_modules_options_options_service_ts
file_src_modules_plugin_plugin_context_utilities_ts --> file_src_modules_plugin_plugin_constants_ts
file_src_modules_plugin_plugin_context_utilities_ts --> file_src_modules_plugin_plugin_service_ts
file_src_modules_plugin_plugin_context_utilities_ts --> file_src_modules_plugin_plugin_types_ts
file_src_modules_plugin_plugin_context_utilities_ts --> file_src_modules_projects_projects_service_ts
file_src_modules_plugin_plugin_context_utilities_unit_test_ts --> file_src_modules_address_address_service_ts
file_src_modules_plugin_plugin_context_utilities_unit_test_ts --> file_src_modules_options_options_service_ts
file_src_modules_plugin_plugin_context_utilities_unit_test_ts --> file_src_modules_plugin_plugin_context_utilities_ts
file_src_modules_plugin_plugin_context_utilities_unit_test_ts --> file_src_modules_plugin_plugin_service_ts
file_src_modules_plugin_plugin_context_utilities_unit_test_ts --> file_src_modules_projects_projects_service_ts
file_src_modules_plugin_plugin_module_ts --> file_src_modules_options_options_module_ts
file_src_modules_plugin_plugin_module_ts --> file_src_modules_plugin_plugin_service_ts
file_src_modules_plugin_plugin_module_ts --> file_src_modules_projects_projects_module_ts
file_src_modules_plugin_plugin_module_ts --> file_src_modules_run_configuration_run_configuration_module_ts
file_src_modules_plugin_plugin_service_ts --> file_src_modules_options_options_constants_ts
file_src_modules_plugin_plugin_service_ts --> file_src_modules_options_options_service_ts
file_src_modules_plugin_plugin_service_ts --> file_src_modules_options_options_types_ts
file_src_modules_plugin_plugin_service_ts --> file_src_modules_plugin_plugin_constants_ts
file_src_modules_plugin_plugin_service_ts --> file_src_modules_plugin_plugin_types_ts
file_src_modules_plugin_plugin_service_ts --> file_src_modules_projects_projects_service_ts
file_src_modules_plugin_plugin_service_ts --> file_src_modules_run_configuration_run_configuration_service_ts
file_src_modules_plugin_plugin_service_unit_test_ts --> file_src_modules_options_options_service_ts
file_src_modules_plugin_plugin_service_unit_test_ts --> file_src_modules_plugin_plugin_constants_ts
file_src_modules_plugin_plugin_service_unit_test_ts --> file_src_modules_plugin_plugin_service_ts
file_src_modules_plugin_plugin_service_unit_test_ts --> file_src_modules_plugin_plugin_types_ts
file_src_modules_plugin_plugin_service_unit_test_ts --> file_src_modules_projects_projects_service_ts
file_src_modules_plugin_plugin_service_unit_test_ts --> file_src_modules_run_configuration_run_configuration_service_ts
file_src_modules_plugin_plugin_types_ts --> file_src_modules_plugin_plugin_constants_ts
file_src_modules_plugin_plugin_utilities_ts --> file_src_modules_plugin_plugin_context_utilities_ts
file_src_modules_plugin_plugin_utilities_ts --> file_src_modules_plugin_plugin_types_ts
file_src_modules_projects_projects_module_ts --> file_src_modules_projects_projects_service_ts
file_src_modules_projects_projects_service_ts --> file_src_modules_projects_projects_types_ts
file_src_modules_projects_projects_service_unit_test_ts --> file_src_modules_projects_projects_service_ts
file_src_modules_run_configuration_run_configuration_module_ts --> file_src_modules_run_configuration_run_configuration_service_ts
file_src_modules_run_configuration_run_configuration_service_ts --> file_src_modules_run_configuration_run_configuration_types_ts
file_src_modules_run_configuration_run_configuration_service_unit_test_ts --> file_src_modules_run_configuration_run_configuration_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/callidescope/callidescope-nx, deepest first. Each frame shows what it takes, what it returns, and what its documentation says.
| Measure | Value | | --- | --- | | Callables | 74 | | Files | 38 | | Calls traced | 109 | | Call stacks | 6 | | Deepest stack | 17 | | Stacks through recursion | 0 | | Unfollowable calls | 1 |
Limits
What this project is judged against, as declared in its own callidescope.config.ts.
| Limit | Value |
| --- | --- |
| maximumDepth | 17 |
| maximumBreadth | 7 |
Call stacks (depth)
1. breadthExecutor — depth ≥ 17 · orphan-root
🚀 breadthExecutor(…): Promise<{ success: boolean; }> [projects/ic-suite/callidescope/callidescope-nx/src/executors/breadth/executor.ts:15]
↳ Prints each named callable's direct callers and callees side by side — the two questions a rename or a refactor needs…
└─> runAddressExecutor(…): Promise<{ success: boolean; }> [projects/ic-suite/callidescope/callidescope-nx/src/modules/address/address.utilities.ts:19]
↳ Runs the address lookups on behalf of the `depth` or `breadth` executor.
└─> AddressService.runDepth(args: LookupArguments): Promise<LookupResult> [projects/ic-suite/callidescope/callidescope-nx/src/modules/address/address.service.ts:152]
↳ Prints every call stack above and below each callable.
└─> AddressService.locate(…): Promise<string | { identified: { address: string; id: string; }[]; workspace: LocatedWorkspace; }> [projects/ic-suite/callidescope/callidescope-nx/src/modules/address/address.service.ts:74]
↳ Traces the selection, then matches every address against it.
└─> AddressLookupService.locate(options: AddressCommandOptions): Promise<LocatedWorkspace> [projects/ic-suite/callidescope/callidescope-cli/src/modules/address-lookup/address-lookup.service.ts:87]
↳ Loads the configuration and traces the workspace, matching nothing yet.
└─> CallidescopeService.locate(args: TraceArguments): Promise<LocateOutcome> [projects/ic-suite/callidescope/callidescope-cli/src/modules/callidescope/callidescope.service.ts:394]
↳ Collects every callable and assembles the graph over them, without running the analysis a full trace does.
└─> GraphAssemblyService.assemble(args: AssembleGraphArguments): AssembledGraph [projects/ic-suite/callidescope/callidescope-graph/src/modules/graph/graph-assembly.service.ts:43]
↳ Builds the call graph and everything derived from it.
└─> EdgesService.build(args: BuildEdgesArguments): EdgeCollection [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:251]
↳ Builds every edge in the graph, and records the calls it could not.
└─> EdgesService.buildSiteEdges(…): { edges: CallEdge[]; unresolved: UnresolvedCall[]; } [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:59]
↳ Turns one call site into the edges and non-resolutions it produced.
└─> EdgesService.resolveSite(…): ResolvedCallSite | undefined [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:226]
↳ Resolves one call site, choosing the right strategy for its shape.
└─> SymbolResolutionService.resolve(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:267]
↳ Resolves a call expression to every declaration it can reach.
└─> SymbolResolutionService.resolveSymbol(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:165]
↳ Resolves an already-identified callee symbol to its declarations.
└─> SymbolResolutionService.resolveThroughHierarchy(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:217]
↳ Expands an interface or abstract member to its implementations.
└─> ClassesService.resolveImplementations(…): ImplementationLookup [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:204]
↳ Finds the concrete declarations one interface member resolves to.
└─> ClassesService.flatMap(…)(this: undefined, candidate: ts.ClassDeclaration): ts.Declaration[] [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:232]
└─> ClassesService.readMemberDeclarations(…): Declaration[] [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:148]
↳ Reads one member's concrete declarations off a candidate class.
└─> ClassesService.filter(…)(member: ts.PropertyDeclaration | ts.MethodDeclaration): boolean [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:162]2. depthExecutor — depth ≥ 17 · orphan-root
🚀 depthExecutor(…): Promise<{ success: boolean; }> [projects/ic-suite/callidescope/callidescope-nx/src/executors/depth/executor.ts:15]
↳ Prints every call stack above and below each named callable — every caller chain up to a root, every callee chain down…
└─> runAddressExecutor(…): Promise<{ success: boolean; }> [projects/ic-suite/callidescope/callidescope-nx/src/modules/address/address.utilities.ts:19]
↳ Runs the address lookups on behalf of the `depth` or `breadth` executor.
└─> AddressService.runDepth(args: LookupArguments): Promise<LookupResult> [projects/ic-suite/callidescope/callidescope-nx/src/modules/address/address.service.ts:152]
↳ Prints every call stack above and below each callable.
└─> AddressService.locate(…): Promise<string | { identified: { address: string; id: string; }[]; workspace: LocatedWorkspace; }> [projects/ic-suite/callidescope/callidescope-nx/src/modules/address/address.service.ts:74]
↳ Traces the selection, then matches every address against it.
└─> AddressLookupService.locate(options: AddressCommandOptions): Promise<LocatedWorkspace> [projects/ic-suite/callidescope/callidescope-cli/src/modules/address-lookup/address-lookup.service.ts:87]
↳ Loads the configuration and traces the workspace, matching nothing yet.
└─> CallidescopeService.locate(args: TraceArguments): Promise<LocateOutcome> [projects/ic-suite/callidescope/callidescope-cli/src/modules/callidescope/callidescope.service.ts:394]
↳ Collects every callable and assembles the graph over them, without running the analysis a full trace does.
└─> GraphAssemblyService.assemble(args: AssembleGraphArguments): AssembledGraph [projects/ic-suite/callidescope/callidescope-graph/src/modules/graph/graph-assembly.service.ts:43]
↳ Builds the call graph and everything derived from it.
└─> EdgesService.build(args: BuildEdgesArguments): EdgeCollection [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:251]
↳ Builds every edge in the graph, and records the calls it could not.
└─> EdgesService.buildSiteEdges(…): { edges: CallEdge[]; unresolved: UnresolvedCall[]; } [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:59]
↳ Turns one call site into the edges and non-resolutions it produced.
└─> EdgesService.resolveSite(…): ResolvedCallSite | undefined [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:226]
↳ Resolves one call site, choosing the right strategy for its shape.
└─> SymbolResolutionService.resolve(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:267]
↳ Resolves a call expression to every declaration it can reach.
└─> SymbolResolutionService.resolveSymbol(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:165]
↳ Resolves an already-identified callee symbol to its declarations.
└─> SymbolResolutionService.resolveThroughHierarchy(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:217]
↳ Expands an interface or abstract member to its implementations.
└─> ClassesService.resolveImplementations(…): ImplementationLookup [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:204]
↳ Finds the concrete declarations one interface member resolves to.
└─> ClassesService.flatMap(…)(this: undefined, candidate: ts.ClassDeclaration): ts.Declaration[] [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:232]
└─> ClassesService.readMemberDeclarations(…): Declaration[] [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:148]
↳ Reads one member's concrete declarations off a candidate class.
└─> ClassesService.filter(…)(member: ts.PropertyDeclaration | ts.MethodDeclaration): boolean [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:162]3. gateExecutor — depth ≥ 15 · orphan-root
🚀 gateExecutor(…): Promise<{ success: boolean; }> [projects/ic-suite/callidescope/callidescope-nx/src/executors/gate/executor.ts:31]
↳ Fails one project's task when its call stacks broke the limits it is held to.
└─> PluginService.runGate(args: RunGateArguments): Promise<RunTraceResult> [projects/ic-suite/callidescope/callidescope-nx/src/modules/plugin/plugin.service.ts:430]
↳ Traces the resolved directories and judges what it found against the limits every project in scope declared.
└─> CallidescopeService.trace(args: TraceArguments): Promise<TraceOutcome> [projects/ic-suite/callidescope/callidescope-cli/src/modules/callidescope/callidescope.service.ts:408]
↳ Traces a workspace and returns everything the run found.
└─> CallidescopeService.analyze(…): AnalyzeOutcome [projects/ic-suite/callidescope/callidescope-cli/src/modules/callidescope/callidescope.service.ts:295]
↳ Derives every finding from the collected callables.
└─> GraphAssemblyService.assemble(args: AssembleGraphArguments): AssembledGraph [projects/ic-suite/callidescope/callidescope-graph/src/modules/graph/graph-assembly.service.ts:43]
↳ Builds the call graph and everything derived from it.
└─> EdgesService.build(args: BuildEdgesArguments): EdgeCollection [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:251]
↳ Builds every edge in the graph, and records the calls it could not.
└─> EdgesService.buildSiteEdges(…): { edges: CallEdge[]; unresolved: UnresolvedCall[]; } [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:59]
↳ Turns one call site into the edges and non-resolutions it produced.
└─> EdgesService.resolveSite(…): ResolvedCallSite | undefined [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:226]
↳ Resolves one call site, choosing the right strategy for its shape.
└─> SymbolResolutionService.resolve(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:267]
↳ Resolves a call expression to every declaration it can reach.
└─> SymbolResolutionService.resolveSymbol(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:165]
↳ Resolves an already-identified callee symbol to its declarations.
└─> SymbolResolutionService.resolveThroughHierarchy(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:217]
↳ Expands an interface or abstract member to its implementations.
└─> ClassesService.resolveImplementations(…): ImplementationLookup [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:204]
↳ Finds the concrete declarations one interface member resolves to.
└─> ClassesService.flatMap(…)(this: undefined, candidate: ts.ClassDeclaration): ts.Declaration[] [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:232]
└─> ClassesService.readMemberDeclarations(…): Declaration[] [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:148]
↳ Reads one member's concrete declarations off a candidate class.
└─> ClassesService.filter(…)(member: ts.PropertyDeclaration | ts.MethodDeclaration): boolean [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:162]4. traceExecutor — depth ≥ 15 · orphan-root
🚀 traceExecutor(…): Promise<{ success: boolean; }> [projects/ic-suite/callidescope/callidescope-nx/src/executors/trace/executor.ts:25]
↳ Traces one selection of Nx projects with callidescope.
└─> PluginService.runTrace(args: RunTraceArguments): Promise<RunTraceResult> [projects/ic-suite/callidescope/callidescope-nx/src/modules/plugin/plugin.service.ts:475]
↳ Traces the resolved directories and renders the report.
└─> CallidescopeService.trace(args: TraceArguments): Promise<TraceOutcome> [projects/ic-suite/callidescope/callidescope-cli/src/modules/callidescope/callidescope.service.ts:408]
↳ Traces a workspace and returns everything the run found.
└─> CallidescopeService.analyze(…): AnalyzeOutcome [projects/ic-suite/callidescope/callidescope-cli/src/modules/callidescope/callidescope.service.ts:295]
↳ Derives every finding from the collected callables.
└─> GraphAssemblyService.assemble(args: AssembleGraphArguments): AssembledGraph [projects/ic-suite/callidescope/callidescope-graph/src/modules/graph/graph-assembly.service.ts:43]
↳ Builds the call graph and everything derived from it.
└─> EdgesService.build(args: BuildEdgesArguments): EdgeCollection [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:251]
↳ Builds every edge in the graph, and records the calls it could not.
└─> EdgesService.buildSiteEdges(…): { edges: CallEdge[]; unresolved: UnresolvedCall[]; } [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:59]
↳ Turns one call site into the edges and non-resolutions it produced.
└─> EdgesService.resolveSite(…): ResolvedCallSite | undefined [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/edges.service.ts:226]
↳ Resolves one call site, choosing the right strategy for its shape.
└─> SymbolResolutionService.resolve(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:267]
↳ Resolves a call expression to every declaration it can reach.
└─> SymbolResolutionService.resolveSymbol(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:165]
↳ Resolves an already-identified callee symbol to its declarations.
└─> SymbolResolutionService.resolveThroughHierarchy(…): ResolvedCallSite [projects/ic-suite/callidescope/callidescope-graph/src/modules/edges/symbol-resolution.service.ts:217]
↳ Expands an interface or abstract member to its implementations.
└─> ClassesService.resolveImplementations(…): ImplementationLookup [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:204]
↳ Finds the concrete declarations one interface member resolves to.
└─> ClassesService.flatMap(…)(this: undefined, candidate: ts.ClassDeclaration): ts.Declaration[] [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:232]
└─> ClassesService.readMemberDeclarations(…): Declaration[] [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:148]
↳ Reads one member's concrete declarations off a candidate class.
└─> ClassesService.filter(…)(member: ts.PropertyDeclaration | ts.MethodDeclaration): boolean [projects/ic-suite/callidescope/callidescope-graph/src/modules/classes/classes.service.ts:162]5. anonymous — depth ≥ 8 · orphan-root
🚀 anonymous(…): Promise<CreateNodesResultArray> [projects/ic-suite/callidescope/callidescope-nx/src/index.ts:59]
└─> PluginService.inferTargets(args: InferTargetsArguments): Promise<Map<string, InferredTargets>> [projects/ic-suite/callidescope/callidescope-nx/src/modules/plugin/plugin.service.ts:336]
↳ Infers this plugin's targets onto every project holding a `tsconfig.json`.
└─> PluginService.buildExclusionFilter(…): Promise<FileFilter> [projects/ic-suite/callidescope/callidescope-nx/src/modules/plugin/plugin.service.ts:92]
↳ Builds the predicate deciding which projects the workspace configuration keeps out of every trace.
└─> ConfigurationService.loadConfigurationFile(args: LoadConfigurationArguments): Promise<L