codependix-triage
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseActing on a codependix failure
处理 codependix 失败
Codependix reports a handful of distinct outcomes, and reading which one
occurred is most of the work. Start by separating them: a boundary
violation is a real edge in real code, a stale export is drift, a
failure is a project that never got as far as producing one, and a run that
wrote nothing at all is usually neither.
Codependix 会报告几种彼此不同的结果,而判断究竟发生了哪一种,就是这项工作的主要部分。先将它们区分开:**边界违规(boundary violation)**是实际代码中的实际边,**过期导出(stale export)**是漂移,**失败(failure)**是根本未走到生成导出这一步的项目,而完全没有写入任何内容的运行通常两者都不是。
A boundary violation
边界违规
--check boundariesThis is the one finding a re-run never fixes. Nothing is stale and nothing
needs regenerating: the edge is in the code, and one of two things has to give.
- Remove the edge. Usually the right answer, and usually smaller than it
looks — move a type into a file, invert a dependency, or lift a shared piece into a package both ends may reach.
*.types.ts - Change the rule, when the rule is what is wrong. That is a deliberate
decision to write down in , with the reason, not a quiet widening of a selector until the run goes green.
codependix.config.ts
Never narrow a selector, add an exclusion, or delete a rule purely to make a
failing check pass. A gate loosened to pass is a gate that no longer protects
anything, and the next reader has no way to tell it was ever meant to.
If the violation is at the level and mentions an edge with no import
statement behind it, that is the point of the level: an
entry is a real project-graph edge, and
cannot see it. Remove the entry, or the rule
has to change.
nximplicitDependencies@nx/enforce-module-boundaries--check boundaries**这是重新运行永远无法修复的一类发现。**这里没有 stale 内容,也不需要重新生成:边就在代码中,因此必须在以下两者之间作出调整。
- **移除该边。**通常这是正确做法,而且改动通常比看上去小——将某个 type 移入 文件、反转依赖关系,或将共享部分提取到两端都可依赖的 package 中。
*.types.ts - 修改规则,如果错误的是规则本身。这应当是一个有意作出的决定,并将原因写入 ,而不是悄悄扩大 selector,直到运行变绿。
codependix.config.ts
绝不要仅仅为了让失败的检查通过,就缩小 selector、添加 exclusion 或删除规则。为通过检查而放宽的 gate 已经失去任何保护作用,而下一位读者也无从得知它原本是否用于守护某项约束。
如果违规位于 层级,并且提到一条背后没有 import 语句的边,这恰恰说明了这个层级的用途: 条目是真实的 project-graph 边,而 看不到它。请移除该条目,或者修改规则。
nximplicitDependencies@nx/enforce-module-boundariesA stale --check reports
--check reports过期的 --check reports
--check reportsOne or more configured exports disagree with a freshly built graph. The run
names the projects.
Re-run . That is the entire fix. The graphs move with the
workspace they describe, so a project graph that changed makes every export
that drew it stale — which is drift to refresh, not a defect to investigate.
--writeNever hand-edit inside the anchor markers. The next replaces the
block wholesale, so an edited diagram is a diff that silently disappears on the
following run. The same goes for a standalone Markdown file: codependix owns
its whole contents.
--writeTwo more things a stale check does not mean:
- It is not a conformetry conformance difference. The /
codependix:startmarkers are codependix's own syntax and carry no dependency on anycodependix:endpackage. Running a conformance check, or reaching for a conformetry generator, fixes nothing here.conformetry-* - It is not evidence of a missing anchor. A project that has never been exported has no block to compare, and reports stale like any other drift.
一个或多个已配置的 export 与刚构建的图不一致。运行结果会列出相关项目。
**重新运行 。这就是完整的修复方式。**图会随其描述的工作区一起变化,因此 project graph 的改变会让所有基于它绘制的 export 变为 stale——这属于应当刷新的漂移,而不是需要调查的缺陷。
--write**绝不要在 anchor 标记内手动编辑。**下一次 会整体替换该块,因此手工编辑过的 diagram 只是一处 diff,会在后续运行中悄无声息地消失。独立的 Markdown 文件也一样:其全部内容完全由 codependix 管理。
--writestale 检查还 不 表示另外两件事:
- 它不表示 conformetry 一致性差异。/
codependix:start标记是 codependix 自己的语法,不依赖任何codependix:endpackage。运行 conformance check,或改用 conformetry generator,在这里都解决不了问题。conformetry-* - **它也不能证明缺少 anchor。**从未导出过的项目没有可比较的块,与其他漂移一样会报告为 stale。
A project that failed
失败的项目
A failure is collected per project and reported by name. One project failing
does not stop the rest — every remaining project in that pass still runs, and
all four graph-type passes are attempted regardless of whether an earlier one
failed. So a run naming three failures is three things to fix, not one flaky
run to retry.
失败信息会按项目收集并逐个报告。一个项目失败不会阻止其他项目运行——该轮中的其余项目仍会继续执行,而且无论前面的 graph type 是否失败,四种 graph type 任务都会全部尝试。因此,一次运行报告三个失败,就表示有三件事需要修复,而不是一次不稳定的运行需要重试。
The Markdown file does not exist
Markdown 文件不存在
The only anchor problem that fails outright. A missing anchor block is
auto-created on ; a missing file is not, because a project with no
readme at all is a more serious problem than an unplaced block, and inventing
the file would mean authoring a document nobody asked for.
--writeCreate the file — a project readme with at least a heading — and re-run.
这是唯一会直接导致失败的 anchor 问题。缺少 anchor 块时, 会自动创建;缺少文件时则不会,因为一个完全没有 readme 的项目比未正确放置的块更严重,而擅自创建文件等于编写一份无人要求的文档。
--write创建该文件——项目 readme 至少包含一个 heading——然后重新运行。
A missing anchor block, on --write
--write在 --write
时缺少 anchor 块
--writeNot a failure. creates it, at one of exactly two safe places:
--write- Appended to the end of the file as a new section, with an intro line and a
## 🕸️ Codependixfor the graph type.### <Subheading> - Inserted as a new at the end of an existing
### <Subheading>section, when an earlier graph type already created one.## 🕸️ Codependix
It never places a block anywhere else in a document someone else is authoring,
and never duplicates the heading. If the block landed somewhere you did not
want it, move the whole marker pair by hand once and every later
replaces the content in place.
--write这不是失败。 会创建该块,并且只会将其放在两个安全位置之一:
--write- 作为新的 section 追加到文件末尾,其中包含一行引导内容,以及 graph type 对应的
## 🕸️ Codependix。### <Subheading> - 当更早的 graph type 已创建 section 时,作为新的
## 🕸️ Codependix插入现有 section 的末尾。### <Subheading>
它绝不会把块放到他人正在编写的文档中的其他任何位置,也绝不会重复 heading。如果块出现在不希望它出现的位置,可以手动整体移动一次 marker 对,之后每次 都会在原位替换其中的内容。
--writeA NestJS project that failed to boot its container
启动容器失败的 NestJS 项目
The NestJS pass explores a project's container in preview mode, which
registers every module and provider without instantiating any of them. A
project building a options factory never has a
database contacted, so what breaks this pass is always something that throws
while modules are being registered — a module whose static argument
reads a variable that is absent, a top-level throw in a module file, or a
project whose root module does not export what the pass expects. Look there.
TypeOrmModule.forRootAsyncforRootAn application is rooted in and its export; a
library package with no such file is rooted in a synthetic module built from
every it defines, so a module file that cannot be imported on its
own fails a library that an application would not notice.
src/main.module.tsMainModule*.module.tsTwo fixes that look plausible and are not: starting or seeding a database (the
pass never contacts one), and building the project first (it imports the
project's own TypeScript module sources directly).
If the CLI is being run from TypeScript sources through some other loader,
check that decorator metadata survives it: NestJS constructor injection reads
metadata that plain type-stripping erases, and the failure looks like a
container that cannot resolve its own providers. The published
binary registers a decorator-preserving loader itself; a hand-rolled invocation
has to do the same.
codependixNestJS 任务会以预览模式探查项目的 container,期间会注册所有 module 和 provider,但不会实例化其中任何一个。即使项目构建了 options factory,该过程也绝不会连接数据库。因此,导致此任务出问题的始终是 module 在_注册_期间抛出的异常,例如某个 module 的 static 参数读取了不存在的变量、module 文件顶层直接抛出异常,或者项目的 root module 未导出任务所期望的内容。应重点检查这些位置。
TypeOrmModule.forRootAsyncforRootapplication 以 及其 export 为根;没有该文件的 library package 则以一个合成 module 为根,该 module 由它定义的所有 构建。因此,一个无法单独导入的 module 文件会使 library 失败,而 application 可能根本注意不到。
src/main.module.tsMainModule*.module.ts有两种看似合理但实际无效的修复方式:启动或填充数据库(该任务绝不会连接数据库),以及先构建项目(它会直接导入项目自己的 TypeScript module 源码)。
如果 CLI 正通过其他 loader 从 TypeScript 源码运行,请检查 decorator metadata 能否在转换后保留:NestJS constructor injection 会读取 metadata,而仅剥离类型的转译流程会将其擦除;此时故障表现为 container 无法解析自己的 provider。已发布的 binary 会自行注册保留 decorator 的 loader;自行拼装的调用方式也必须做到这一点。
codependixA rejected command line
被拒绝的命令行
--checkboundariesreports- — a bare
--check needs a value, or one whose value is only separators. Name the set; do not drop the flag. Read as "gate nothing" it would be a gate that cannot fail.--check - — a name from another tool.
--check does not accept "..."is codometer's andlimitsis callidescope's; onlydepthis shared.reports - — an export cannot be stale in the run that just wrote it.
--write cannot be combined with --check reportsis legal.--write --check boundaries - Naming neither nor
--checkis asked about at a terminal, and refused everywhere else — including any run an agent or a CI job makes, since neither has a terminal to answer on. Nothing is inferred and no default write happens.--write
Every mistake on one command line is collected before any is reported, so two
complaints are two things to fix rather than two runs.
The command is , not bare : a command line with no
subcommand is rejected by the argument parser before any of this applies.
codependix mapcodependix--checkboundariesreports- ——只写了一个裸
--check needs a value,或者它的值仅包含分隔符。请指定集合,不要删除该 flag。如果将其理解为“不对任何内容设置 gate”,那它就是一个永远不会失败的 gate。--check - ——名称来自其他工具。
--check does not accept "..."属于 codometer,limits属于 callidescope;只有depth是共用的。reports - ——刚完成写入的 export 不可能处于 stale 状态,因此不能同时使用这两个参数。
--write cannot be combined with --check reports是合法的。--write --check boundaries - 如果既未指定 也未指定
--check,在终端中会就此询问,而在其他任何地方都会拒绝执行——包括 Agent 或 CI job 发起的任何运行,因为二者都没有终端可用来回答。系统不会推断任何选项,也不会默认执行 write。--write
同一条命令行中的所有错误都会在其他错误被报告前一次性收集,因此两条报错表示需要修复两个问题,而不是需要运行两次。
命令是 ,而不是裸 :没有指定 subcommand 的命令行会在上述规则生效前被参数解析器拒绝。
codependix mapcodependixA --write
that produced no files
--write未生成任何文件的 --write
--writeThe quietest outcome, and almost never a bug: the run exits 0, reports that
every configured export is current, and writes nothing, because nothing was
configured. Every unset defaults to , and a project
resolving to is left out of the results entirely rather than reported
as up to date — so projects in the report means codependix was configured
to produce nothing.
target"none""none"0Work down this list before suspecting the tool:
- Was a configuration file found at all? An absent one is legal and
silent. Name it with to make its absence fail loudly instead.
--config - Is set? A graph type carrying destinations but no
targetstill resolves totarget."none" - Is the field spelled ?
defaultsis stripped as an unknown key and has no effect.default - Does the configuration name an at all? It defaults to nothing, so a configuration naming only
includeselects no project and exports nothing. The run warns —defaults— and still exits zero, and🕸️ Selected no project to exportstays green either way, because it judges every project regardless of--check boundaries. Writeincludefor whole-workspace coverage.include: ["**"] - Do the projects match , and escape
include? Both match against a project's Nx name and its workspace-relative root.exclude - Is the workspace root? It is what every project's path resolves against, not a subtree to scan — Nx resolves the graph itself from the process working directory. Pointed at a single project's folder, the run still reads the whole graph but resolves every project underneath that folder, so exports land somewhere unexpected or fail on a readme that is not there.
--directory
The skill covers each of those fields.
codependix-configure这是最不显眼的结果,而且几乎从来不是 bug:运行以 0 退出,报告所有已配置的 export 都是最新状态,却没有写入任何内容,因为根本没有配置任何输出目标。每个未设置的 都默认为 ,而解析为 的项目会完全从结果中排除,不会被报告为最新状态——因此,报告中显示 0 个项目,意味着 codependix 被配置为不生成任何内容。
target"none""none"怀疑工具之前,请按以下列表逐项检查:
- **是否确实找到了配置文件?**配置文件不存在是合法且静默的。使用 指定其路径,可以让缺失情况明确报错。
--config - **是否设置了 ?**一个带有 destinations、但没有
target的 graph type 最终仍会解析为target。"none" - 字段是否拼写为 ?
defaults会被当作未知 key 移除,因此不起作用。default - **配置中是否指定了 ?**它默认为空,因此只命名了
include的配置不会选中任何项目,也不会导出任何内容。运行会发出警告——defaults——但仍以 0 退出;而且无论是否设置🕸️ Selected no project to export,include都会保持绿色,因为它会判断每个项目。要覆盖整个工作区,请写入--check boundaries。include: ["**"] - **项目是否匹配 ,并避开
include?**两者都会针对项目的 Nx name 和 workspace-relative root 进行匹配。exclude - **是否指向工作区 root?**它是所有项目路径的解析基准,而不是用于扫描的 subtree——Nx 会根据进程工作目录解析 graph 本身。如果将它指向单个项目的文件夹,运行仍会读取整个 graph,但会把该文件夹下的每个项目都解析到这个路径基准上,导致 export 落在意外的位置,或因找不到 readme 而失败。
--directory
codependix-configureA configuration that was rejected
被拒绝的配置
Validation refuses two destination mismatches rather than silently exporting
half of what was asked for: a or target with no
destination, and a or target with no
destination. A destination naming neither an nor a
is refused for the same reason — nothing would say where the export goes.
"both""json"json"both""markdown"markdownmarkdownanchorpath校验会拒绝两类 destination 不匹配,而不是只静默导出所要求内容的一半:target 为 或 ,却没有 destination;target 为 或 ,却没有 destination。出于同样的原因,如果 destination 既未指定 ,也未指定 ,校验也会拒绝,因为它无法确定 export 的写入位置。
"both""json"json"both""markdown"markdownmarkdownanchorpathWhose problem the graph is
图所反映的问题由谁负责
A finished export is a description, not a verdict — an export gates nothing
about a codebase's shape, and only a declared boundary rule does. A diagram
that shows something alarming (a cycle, a project depending on far more than
expected) is a real finding about the code even when no rule condemns it, and
the fix belongs in the code rather than in the configuration that exported
it. Reach for the skill to read what the graph is
actually saying before changing anything.
codependix-navigate完成的 export 是一份描述,不是一份裁决——export 不会针对代码库的结构设置任何 gate,只有已声明的 boundary rule 才会。即使没有任何规则判定某个 diagram 中的内容有问题,只要它显示了令人担忧的结构,例如环,或某个项目依赖了远超预期的其他项目,这仍然是关于代码的真实发现。修复应当落在代码中,而不是用于导出它的配置中。进行任何更改之前,请使用 skill 读懂 graph 实际表达的内容。
codependix-navigate