codependix-export

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Running a codependix export

运行 codependix 导出

Codependix reads what each project in an Nx workspace depends on and renders it four ways — the Nx project graph, a NestJS project's module graph, a TypeScript project's file-level import graph, and a Python project's — then delivers each one to whichever destinations the configuration names for that project: a JSON file, a Markdown anchor block spliced into an existing file, or both.
codependix 会读取 Nx workspace 中每个项目的依赖关系,并以四种方式呈现——Nx project graph、NestJS 项目的 module graph、TypeScript 项目的 file-level import graph,以及 Python 项目的 file-level import graph——然后将每一种图交付到配置为该项目指定的 destination:JSON 文件、拼接进现有文件的 Markdown anchor block,或两者兼有。

The configuration decides everything

配置决定一切

There is no flag that selects a graph type, and no per-graph-type subcommand. Which graphs run, for which projects, and where each export lands is entirely a function of
codependix.config.ts
. Looking for
--nestjs
,
--imports
, or
--only nx
is looking for something that does not exist.
The corollary is the failure mode worth learning first:
A workspace with no configuration file resolves every graph type for every project to
target: "none"
and produces nothing.
The run succeeds, exits 0, logs that every configured export is current, and writes no files — because nothing was configured. That is correct behavior, not a bug.
So a
--write
that wrote nothing is a configuration question, never a debugging one. Before looking for a defect, confirm in this order:
  1. A configuration file was actually found — an absent one is legal and silent, while a
    --config
    path that was named explicitly and does not exist fails loudly.
  2. The graph types you expected carry a
    target
    other than
    "none"
    , which is what every unset target defaults to.
  3. The projects you expected match the configured
    include
    globs and no
    exclude
    glob.
    include
    defaults to nothing, so a configuration that never names one selects no project at all — the run warns, and still exits zero.
The
codependix-configure
skill covers all three.
没有用于选择图类型的 flag,也没有按图类型划分的 subcommand。 运行哪些图、针对哪些项目运行,以及每份 export 写到哪里,完全由
codependix.config.ts
决定。寻找
--nestjs
、
--imports
或
--only nx
,等于寻找一个并不存在的东西。
由此产生了一个最值得优先掌握的 failure mode:
没有配置文件的 workspace 会将每个项目的每一种图类型都解析为
target: "none"
,因而不产生任何内容。
运行成功,退出码为 0,并记录每个 configured export 都是最新的,同时没有写入任何文件——因为根本没有配置任何内容。这是正确行为,不是 bug。
因此,一个没有写入任何内容的
--write
是配置问题,而不是调试问题。在查找 defect 前,请按以下顺序确认:
  1. 确实找到了配置文件——缺少配置文件是合法且静默的,而显式指定的
    --config
    路径若不存在则会明确报错。
  2. 预期图类型的
    target
    不是
    "none"
    ;所有未设置的 target 默认都是
    "none"
    。
  3. 预期项目与配置的
    include
    globs 匹配,且未被任何
    exclude
    glob 排除。
    include
    默认不包含任何内容,因此,从未指定
    include
    的配置不会选中任何项目——运行会发出警告,并仍以零退出。
codependix-configure skill 涵盖了这三项。

One
--write
, and two things
--check
can gate

一个
--write
,以及
--check
可把控的两类结果

--check
takes a comma-separated set, and naming the set is what selects which finding fails the run.
ModeMeaning
--check boundaries
Fails on an edge or a cycle breaking a declared rule. Reads no destination and writes nothing
--check reports
Fails on a configured destination no longer holding what a fresh run would write
--write
Writes every configured export
The two
--check
names exist because the findings belong on opposite sides of a pull request. A broken boundary is caused by the branch and fixed by the branch, so it gates every branch. A stale export moves with the workspace it describes, so gating it on a branch fails every branch that changed a project graph rather than anything the branch did.
reports
is deliberately spelled the same as callidescope's and codometer's, because it is the same finding.
Combinations:
  • --write --check boundaries
    is legal — a boundary has no destination to be stale.
  • --write --check reports
    is refused — an export cannot be stale in the run that just wrote it.
  • A bare
    --check
    , or one whose value is only commas, is refused.
    Read as "gate nothing" it would be a gate that cannot fail. If a run is rejected with
    --check needs a value
    , the fix is to name the set, not to drop the flag.
  • Naming neither
    --check
    nor
    --write
    is asked which was meant, as a three-item menu. No mode is ever inferred and no default write happens.
An agent should always name the mode explicitly. There is no flag that suppresses the prompt, because an agent's run has no terminal to draw it on: that run fails immediately, naming the flag it wanted. Reading that failure as a broken tool is the mistake to avoid — it is a missing flag, and the fix is to add
--check <set>
or
--write
.
Two options qualify whichever mode was picked:
OptionMeaning
--config [config]
Path to a
codependix.config.ts
. Searched for upward from the directory when omitted
-d, --directory [directory]
Workspace root whose Nx project graph this run reads. Defaults to the working directory
bash
codependix map --write
codependix map --check boundaries --directory . --config configuration/codependix.config.ts
codependix map --check reports --directory . --config configuration/codependix.config.ts
--check
接受一组以逗号分隔的值;指定该组值即决定哪类 finding 会使运行失败。
模式含义
--check boundaries
当 edge 或 cycle 违反已声明规则时失败。不读取任何 destination,也不写入任何内容
--check reports
当 configured destination 不再包含新运行将写入的内容时失败
--write
写入每一个 configured export
这两个
--check
名称之所以存在,是因为这些 finding 位于 pull request 的两侧。broken boundary 由 branch 引入,也应由 branch 修复,因此它要 gate 每一个 branch。stale export 会随其所描述的 workspace 一起变化,因此在某个 branch 上 gate stale export,会让每个改动了 project graph 的 branch 都失败,而与该 branch 具体改了什么无关。
reports
特意与 callidescope 和 codometer 的拼写保持一致,因为它们表示的是同一种 finding。
组合方式:
  • --write --check boundaries
    合法——boundary 本身没有 destination,因此不存在 stale 问题。
  • --write --check reports
    会被拒绝——刚完成写入的 export 不可能在同一次运行中处于 stale 状态。
  • 不带值的
    --check
    ,或值中只有逗号的
    --check
    ,都会被拒绝。
    如果将其理解为“什么都不 gate”,它就成为一个永远无法失败的 gate。如果运行因
    --check needs a value
    而被拒绝,修复方法是指定集合,而不是删掉 flag。
  • 既不指定
    --check
    也不指定
    --write
    时,会以包含三个选项的菜单来_询问_你的意图。系统绝不会推断 mode,也绝不会默认执行写入。
Agent 始终应明确指定 mode。 没有 flag 可以抑制该提示,因为 Agent 的运行没有可供其绘制菜单的 terminal:这种运行会立即失败,并指出它希望使用的 flag。把该失败误读为工具损坏是错误的;实际上只是缺少 flag,修复方法是添加
--check <set>
或
--write
。
无论选择哪种 mode,都可以使用以下两个 option:
Option含义
--config [config]
codependix.config.ts
的路径。省略时,从指定目录逐级向上搜索
-d, --directory [directory]
本次运行读取 Nx project graph 时使用的 workspace 根目录。默认为当前工作目录
bash
codependix map --write
codependix map --check boundaries --directory . --config configuration/codependix.config.ts
codependix map --check reports --directory . --config configuration/codependix.config.ts

Codependix reads the Nx project graph

Codependix 读取 Nx project graph

This is the trait that separates it from measurement tools that walk a directory. Nx resolves the project graph itself, from the process working directory — no flag points at it. What
--directory
names is the workspace root every project's path is resolved against, and the directory the configuration search starts from.
So
--directory
is not a subtree to scan, and pointing it at a single project's folder does not export that project alone. It makes every project's root resolve underneath that folder, and the exports land in the wrong place — or fail on a readme that is not there — while the graph itself is unaffected.
Run codependix from the workspace root, pass
--directory .
, and select projects through the configuration's
include
/
exclude
globs, or through
--projects
/
--tags
, rather than through the directory.
这一特性使它区别于那些遍历目录的 measurement tools。Nx 会自行从进程工作目录解析 project graph——没有 flag 指向该目录。
--directory
指定的是解析每个项目路径时所依据的 workspace 根目录,也是配置搜索的起始目录。
因此,
--directory
不是要扫描的 subtree;将它指向单个项目的文件夹,并不会只导出该项目。它会让所有项目的根路径都解析到该文件夹之下,于是 export 会落到错误位置——或者因找不到 README 而失败——而 graph 本身不受影响。
从 workspace 根目录运行 codependix,传入
--directory .
,并通过配置的
include
/
exclude
globs,或通过
--projects
/
--tags
选择项目,而不是通过 directory 选择。

Graphing a workspace the process is not standing in

为进程当前不所在位置的 workspace 生成图

A configuration may name a
projectGraph
file to read instead of resolving one:
ts
{ projectGraph: "artifacts/graph.json" }
It is a path, relative to the workspace root, to the JSON that
nx graph --file=graph.json
emits. That is the only way to graph a workspace the process is not inside — a job that checked out one repository and graphs another, or a run with no Nx workspace under it at all. The path resolves against the same root every export path does, and a supplied graph's node roots are workspace-relative and resolve underneath it too.
It is a configuration field rather than a flag: what graph a run reads is a property of the workspace being described, and pinning it once is what a job graphing a fixed checkout wants.
A supplied graph is trusted, not validated. Nx wrote it, so its contents are taken as given; only a file that is not a project graph at all is refused, by name, rather than crashing later with nothing pointing at the file. A stale or hand-edited graph will produce a diagram that is wrong rather than one that fails.
Two things still need real files on disk regardless, so a supplied graph does not make a whole run workspace-free: the
nestjs
level boots each container, and the
imports
level builds a real
ts.Program
. The
nx
level reads only the graph.
配置可以通过
projectGraph
字段指定一个文件,以供读取,而不再自行解析:
ts
{ projectGraph: "artifacts/graph.json" }
它是相对于 workspace 根目录的路径,指向
nx graph --file=graph.json
输出的 JSON。这是为进程不位于其中的 workspace 生成图的唯一方式——例如,一个 job 检出了某个 repository,却要为另一个 repository 生成图;或者某次运行之下根本没有 Nx workspace。该路径与其他所有 export 路径一样,基于同一个根目录解析;所提供 graph 中的节点根路径也相对于 workspace,并且同样解析到该根目录之下。
它是一个配置字段而不是 flag:一次运行读取什么 graph,取决于被描述的 workspace;而只需将其固定一次,正是为固定 checkout 生成图的 job 所需要的。
所提供的 graph 会被信任,而不会验证。 它由 Nx 写入,因此其内容被视为既定事实;只有完全不是 project graph 的文件才会被按名称拒绝,而不是稍后崩溃且没有任何信息指向该文件。stale 或手工编辑过的 graph 会生成错误的 diagram,而不是生成一个失败的 diagram。
无论如何,仍有两项操作需要磁盘上的真实文件,因此提供 graph 并不能让整个运行无需 workspace 中的文件:
nestjs
level 会启动每个 container,
imports
level 会构建真正的
ts.Program
。
nx
level 只读取 graph。

Four graph types, plus the workspace

四种图类型,以及 workspace

Each is keyed by name in the configuration:
KeyWhat it exportsWhich projects appear
nx
A project's one-hop Neighborhood — what it depends on, and what depends on itEvery project the Nx graph knows, except the workspace root itself
nestjs
A project's NestJS module import graphOnly projects tagged
framework:nestjs
imports
A project's own file-level TypeScript import graphEvery project carrying its own
tsconfig.json
pythonImports
The Python equivalent, parsed from
import
/
from ... import
statements
Only projects tagged
language:python
The whole-workspace Nx graph is configured separately, under
workspace.nx
. It is exported once for the repository rather than once per project, has no per-project override, and is unaffected by
include
/
exclude
. Its node set is what
--projects
/
--tags
narrow — see below.
Participation is per graph type and is not one rule. A project a given graph type does not apply to simply never appears in that type's results, which is why configuring a graph type for every project costs nothing: a project with no NestJS container is absent from the NestJS pass rather than failing it.
每一种图都在配置中按名称进行键控:
Key导出内容出现的项目
nx
某个项目的单跳 Neighborhood——它依赖什么,以及什么依赖它Nx graph 已知的所有项目,但不包括 workspace 根自身
nestjs
某个项目的 NestJS module import graph仅带
framework:nestjs
标签的项目
imports
某个项目自身的 file-level TypeScript import graph每个自带
tsconfig.json
的项目
pythonImports
Python 的等价图,从
import
/
from ... import
statements 解析
仅带
language:python
标签的项目
整个 workspace 的 Nx graph 通过
workspace.nx
单独配置。它是为整个 repository 导出一次,而不是为每个项目导出一次;没有 per-project override,并且不受
include
/
exclude
影响。它的 node set 正是
--projects
/
--tags
所缩小的范围——见下文。
是否参与按图类型分别决定,并非一条统一规则。 如果某个项目不适用某一种图类型,它就完全不会出现在该类型的结果中。因此,为每个项目配置一种图类型并无额外成本:没有 NestJS container 的项目只会从 NestJS pass 中缺席,而不会导致该 pass 失败。

--projects
and
--tags
select projects from the command line

--projects
和
--tags
从 command line 选择项目

Both take a comma-separated list, and both do two things at once:
bash
codependix map --write --projects widgets,tools/reporting
codependix map --write --tags framework:nestjs,language:python
They widen what gets exported. A project participates when anything claims it — an
include
glob, a
--projects
glob, or a
--tags
tag. The flags add to what the configuration already selected rather than replacing it, so
--projects widgets
on a workspace whose
include
is
["**"]
exports exactly what it did before.
exclude
still wins over all three: a flag that could resurrect an excluded project would make
exclude
advisory.
--projects
matches the way
include
does, as a glob against a project's name or its workspace-relative root, so
--projects packages/*
and
--projects codependix-*
both work and mean what they look like.
--tags
matches a project's own Nx tags exactly.
They narrow what gets drawn and judged. Naming a selection also narrows the whole-workspace graph's node set and every level
--check boundaries
judges to the selected projects. Naming neither selects everything, which is why the default behavior of both is unchanged.
⚠️ A narrowed gate sees fewer edges.
--check boundaries
is the branch gate, so a CI job that passes
--projects
or
--tags
is asking for a smaller check than a whole-workspace run, and a green result means less. Use them to narrow a local run; leave them off in CI unless narrowing is the point.
include
/
exclude
never do this — they decide which projects have exports written for them, and have never reached the workspace graph or the gate. That difference is the whole reason the flags exist as flags rather than as configuration fields.
Two flags rather than Nx's own
--projects=tag:foo
spelling, deliberately: each shows up in
--help
under its own name. Do not "fix" the divergence.
两者都接受一个以逗号分隔的列表,并且都会同时完成两件事:
bash
codependix map --write --projects widgets,tools/reporting
codependix map --write --tags framework:nestjs,language:python
它们会扩展被导出的范围。 只要有任意一项认领某个项目,该项目就会参与——即
include
glob、
--projects
glob 或
--tags
tag。这些 flag 是在配置已选择内容的基础上追加,而不是替换。因此,在
include
为
["**"]
的 workspace 上使用
--projects widgets
,导出的内容仍与之前完全相同。
exclude
仍优先于三者:如果某个 flag 能让已排除的项目复活,
exclude
就只是建议性规则了。
--projects
的匹配方式与
include
相同,都是针对项目的名称或 workspace 相对根路径进行 glob 匹配,因此
--projects packages/*
和
--projects codependix-*
都能正常工作,其含义也与写法一致。
--tags
则与项目自身的 Nx tags 精确匹配。
它们会缩小绘制和判定范围。 指定一个 selection,也会缩小整个 workspace graph 的 node set,以及
--check boundaries
在每个 level 上判定的项目范围。若两者都未指定,则选择全部,这也是两者的默认行为。
⚠️ 缩小后的 gate 会看到更少的 edge。
--check boundaries
是 branch gate,因此在 CI job 中传入
--projects
或
--tags
,是在要求比整个 workspace 运行更小的检查范围;绿色结果所代表的范围也更小。用它们缩小 本地 运行;除非缩小范围本身就是目的,否则在 CI 中不要使用它们。
include
/
exclude
从不具有这种作用——它们决定哪些项目会写入 exports,而且从未影响 workspace graph 或 gate。正是这一差异,才让这两个功能以 flag 形式存在,而不是配置字段。
这里刻意使用两个 flag,而不是 Nx 自身的
--projects=tag:foo
写法:这样每个 flag 都会在
--help
中以自己的名称出现。不要“修正”这种差异。

What the run reports

运行会报告什么

Every pass is attempted regardless of whether an earlier one failed, and one project's failure is isolated to that project — a missing README, or a NestJS project that fails to boot its container, is collected as a failure while every other project still runs.
--write
either fully succeeds or names exactly which projects failed.
Three findings are reported separately, and any one of them fails the run:
  • Failures — projects that raised before their exports could be resolved, or whose graph could not be built to judge.
  • Stale exports — under
    --check reports
    , configured exports that disagree with a freshly built graph.
  • Boundary violations — under
    --check boundaries
    , edges and cycles breaking a declared rule. Each names its level, its scope, the rule, both endpoints, and whatever the rule says about why it exists. They go to the console and the exit code and nowhere else: a list of things currently wrong is not a document worth publishing.
A project resolving to
target: "none"
is left out of the results entirely rather than reported as up to date, so an exit code depends only on exports codependix was actually configured to produce. A
--check
run reporting
0
projects is telling you it was configured to produce nothing.
无论前一个 pass 是否失败,每个 pass 都会尝试执行,而且单个项目的 failure 会被隔离在该项目上——例如缺少 README,或某个 NestJS 项目无法启动 container,这些都会被收集为 failure,而其他所有项目仍会继续运行。
--write
要么完全成功,要么准确指出哪些项目失败了。
以下三类 findings 会分别报告,其中任意一类都会使运行失败:
  • 失败——在 exports 得以解析之前抛出异常的项目,或无法构建 graph 供判定的项目。
  • 过期导出——在
    --check reports
    下,与新构建 graph 不一致的 configured exports。
  • 边界违规——在
    --check boundaries
    下,违反已声明规则的 edges 和 cycles。每项都会指出其 level、scope、规则、两个端点,以及规则中关于其为何存在的全部说明。它们只反映在 console 输出和 exit code 中,不会进入其他地方:一份当前存在问题的列表,不值得作为文档发布。
解析为
target: "none"
的项目会被完全排除在结果之外,而不是报告为已是最新;因此,退出码只取决于 codependix 实际配置为要产出的 exports。报告
0
个项目的
--check
运行是在告诉你:它被配置为不产出任何内容。

Reading an export

读取 export

A Markdown destination writes a Mermaid diagram. In anchor mode the diagram is spliced between two HTML comment markers naming the anchor:
markdown
<!-- codependix:start name="codependix-nx-projects" -->
```mermaid
graph LR
  widgets["widgets"]
  logger["logger"]
  widgets --> logger
  classDef subject fill:#7c3aed,color:#fff,stroke:#4c1d95,stroke-width:2px
  class widgets subject
```
<!-- codependix:end name="codependix-nx-projects" -->
The highlighted
subject
node is the project the Neighborhood is centered on. Node identifiers are sanitized from names and paths, so read the quoted label rather than the identifier.
A JSON destination writes the graph's own shape — an Nx Neighborhood carries
dependencies
,
dependents
,
edges
, and
projectName
; an import graph carries
fileNames
,
edges
,
isolatedFileNames
, and
projectName
; a NestJS module graph adds
ambientModuleNames
for the global modules whose edges were deliberately left out of the diagram.
For using a committed graph to answer a question about the codebase — what depends on this, what a rename would touch, whether an import cycle is real — reach for the
codependix-navigate
skill.
Markdown destination 会写入 Mermaid diagram。在 anchor mode 下,diagram 会拼接在两个以 anchor 命名的 HTML comment markers 之间:
markdown
<!-- codependix:start name="codependix-nx-projects" -->
```mermaid
graph LR
  widgets["widgets"]
  logger["logger"]
  widgets --> logger
  classDef subject fill:#7c3aed,color:#fff,stroke:#4c1d95,stroke-width:2px
  class widgets subject
```
<!-- codependix:end name="codependix-nx-projects" -->
高亮的
subject
节点是作为该 Neighborhood 中心的项目。节点 identifiers 会根据名称和路径进行清理,因此应读取引号中的 label,而不是 identifier。
JSON destination 会写入 graph 自身的结构——Nx Neighborhood 包含
dependencies
、
dependents
、
edges
和
projectName
;import graph 包含
fileNames
、
edges
、
isolatedFileNames
和
projectName
;NestJS module graph 还会为那些刻意未在 diagram 中呈现 edges 的 global modules 添加
ambientModuleNames
。
如果想使用已提交的 graph 回答代码库相关问题——什么依赖它、重命名会影响什么、import cycle 是否真实存在——请使用 codependix-navigate skill。

Never hand-edit inside the markers

绝不要手工编辑 markers 内部的内容

The next
--write
replaces an anchor block wholesale. A diagram edited by hand is a diff that silently disappears on the following run, and reviewers see a change that reverts itself for no visible reason.
Re-running
--write
is the entire fix for a stale
--check reports
.
It is never the fix for a
--check boundaries
failure — that is a real edge in real code, and writing an export does not remove it. Reach for the
codependix-triage
skill for either one, and for
codependix-configure
to read or change the rules themselves.
下一次
--write
会整体替换 anchor block。手工编辑过的 diagram 所产生的 diff 会在下一次运行时悄无声息地消失,代码 reviewer 只会看到一处没有可见原因便自行回退的变更。
重新运行
--write
是修复 stale
--check reports
的全部办法。
它绝不是修复
--check boundaries
失败的办法——后者意味着真实代码中确实存在 edge,而写出 export 并不会将其移除。无论是哪一种问题,都应使用 codependix-triage skill;要读取或修改规则本身,则使用 codependix-configure。