mcpField
C
codependix-export

codependix-export

github.com/organizzolini开发0280 次安装今天更新
代码仓库

关于 codependix-export

用于在 Nx 工作区运行 Codependix 导出与检查的技能,涵盖 Nx、NestJS、TypeScript 和 Python 依赖图,并通过配置及命令行选择控制运行。

主要功能

  1. 01导出四类依赖图
  2. 02写入 JSON 和 Markdown 报告
  3. 03检查已声明的边界规则
  4. 04检查报告是否过期
  5. 05按名称、glob 或标签选择项目

适用场景

  1. 01将配置的图写入项目文件
  2. 02按依赖边界规则设置运行门禁
  3. 03检查已提交报告是否过期
  4. 04从指定项目图生成其他工作区的图

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/organizzolini/codebase --skill codependix-export

安装后在 Claude Code 中输入/codependix-export确认已加载。

详细介绍

运行 codependix 导出

Codependix 会读取 Nx 工作区中每个项目所依赖的内容,并以四种方式呈现:Nx 项目图、NestJS 项目的模块图、TypeScript 项目的文件级导入图,以及 Python 项目的图;随后,会将每张图导出到该项目配置指定的目标位置:JSON 文件、插入现有文件的 Markdown 锚点块,或两者兼有。

配置决定一切

没有用于选择图类型的标志,也没有按图类型划分的子命令。 哪些图会运行、针对哪些项目,以及每次导出会保存到哪里,完全由 codependix.config.ts 决定。寻找 --nestjs、--imports 或 --only nx,就是在寻找不存在的东西。

首先需要了解的失败情形是:

如果配置没有选择任何项目,所有项目的所有图类型都会解析为 target: "none",不会产生任何输出。 运行会成功,退出码为 0,日志会显示每项已配置的导出均为最新状态,但不会写入任何文件——因为没有配置任何内容。这是正确行为,不是 bug。

因此,--write 没有写入任何内容时,问题一定出在配置上,而不是调试上。查找缺陷前,请按以下顺序确认:

  1. --config 指向的是你想要的文件。该标志为必填项,且指定的文件必须存在;因此,未指定文件或文件不存在时,运行会明确报错,而不是不写入任何内容——但如果指定了错误的文件,效果就和空配置一样。
  2. 你预期的图类型所对应的 target 不是 "none";所有未设置的目标默认值都是 "none"。
  3. 你预期的项目与配置的 include glob 匹配,且不匹配任何 exclude glob。include 默认不包含任何内容,因此,如果配置从未指定任何项目,就不会选择任何项目——运行会发出警告,但仍以 0 退出。

codependix-configure 技能涵盖以上三点。

一次 --write,以及 --check 可以把关的两类问题

--check 接受一个逗号分隔的集合,指定集合即可选择哪些问题会导致运行失败。

模式含义
--check boundaries遇到违反已声明规则的边或环时失败。不读取目标位置,也不写入任何内容
--check reports配置的目标位置不再保存全新运行会写入的内容时失败
--write写入所有已配置的导出内容

之所以有两个 --check 名称,是因为这两类问题属于拉取请求的两侧。边界问题由分支引起,也由分支修复,因此会对每个分支进行把关。过时的导出内容会随着其所描述的工作区变化,因此若在分支上对此进行把关,任何更改了项目图的分支都会失败,而不论分支实际做了什么。reports 的拼写特意与 callidescope 和 codometer 相同,因为它们指的是同一种问题。

组合方式:

  • --write --check boundaries 合法 — 边界问题没有目标位置,因此不会过时。
  • --check boundaries 也接受 --format、--json-output 和 --markdown-output,用于将其问题打印为报告 — 参见下文的 边界报告。
  • 不接受 --write --check reports — 刚刚写入的导出内容不可能在同一次运行中变得过时。
  • 不带值的 --check,或值中只有逗号的 --check,均不接受。 如果将其理解为“不把关任何内容”,它就会变成一个永远不会失败的把关条件。如果运行因 --check needs a value 被拒绝,正确的修复方式是指定集合,而不是删除该标志。
  • 如果既未指定 --check,也未指定 --write,系统会询问用户要使用哪一种模式,并提供三个选项。系统绝不会推断模式,也不会默认执行写入。

Agent 应始终明确指定模式。 没有可以隐藏提示的标志,因为 Agent 的运行没有终端可供显示提示:运行会立即失败,并指出它需要哪个标志。不要误以为这是工具故障 — 缺少的是标志,修复方法是添加 --check <set> 或 --write。

无论选择哪种模式,都可以使用以下两个选项进行限定,第一个选项为必填项:

选项含义
--config <config>必填。 codependix 配置文件的路径,先相对于工作目录解析,再相对于工作区根目录解析。若省略,运行会失败;不会搜索配置文件
-d, --directory [directory]本次运行读取其 Nx 项目图的工作区根目录。默认为工作目录
codependix map --write --config configuration/codependix.config.ts
codependix map --check boundaries --directory . --config configuration/codependix.config.ts
codependix map --check reports --directory . --config configuration/codependix.config.ts

Codependix 读取 Nx 项目图

这是它区别于遍历目录的测量工具的特性。Nx 会从进程的工作目录解析项目图本身 — 没有标志可以指定项目图的位置。--directory 指定的是解析每个项目路径时所依据的工作区根目录。它与配置文件的位置无关:配置文件位置始终由 --config 路径指定。

因此,--directory 不是要扫描的子树;将其指向单个项目的文件夹,也不会只导出该项目。它会让每个项目的根目录都在该文件夹下解析,导致导出内容写入错误位置 — 或因 README 不在该处而失败 — 同时项目图本身不受影响。

从工作区根目录运行 codependix,传入 --directory .,然后通过配置中的 include/exclude glob,或通过 --projects/--tags 选择项目,而不是通过目录选择。

为进程当前不在其中的工作区绘制图表

配置可以指定一个 projectGraph 文件来读取,而不是解析生成一个:

{ projectGraph: "artifacts/graph.json" }

这是相对于工作区根目录的路径,指向 nx graph --file=graph.json 输出的 JSON。这是为进程当前不在其中的工作区绘制图表的唯一方式——例如,某个任务检出了一个仓库,却要为另一个仓库绘制图表;或者运行环境下根本没有 Nx 工作区。该路径与所有导出路径一样,相对于同一个根目录解析;所提供图表中的节点根目录也相对于工作区解析,并且解析结果位于该目录之下。

这是一个配置字段,而不是标志:运行读取哪个图表,取决于所描述的工作区;将其固定配置一次,正是为固定检出目录绘制图表的任务所需的做法。

所提供的图表会被信任,而不会经过验证。 既然它由 Nx 写入,其内容就会被视为可信;只有完全不是项目图表的文件才会被拒绝,并明确指出文件名,而不是等到稍后崩溃时却没有任何信息指向该文件。过时或手动编辑过的图表会生成错误的示意图,而不会导致运行失败。

无论如何,仍有两种情况需要磁盘上存在真实文件,因此提供图表并不能让整个运行过程脱离工作区:nestjs 层级会启动每个容器,而 imports 层级会构建真实的 ts.Program。nx 层级只读取图表。

四种图表类型,以及整个工作区

配置中以名称为键来指定每种类型:

键导出内容包含哪些项目
nx项目的单跳邻域——它依赖哪些项目,以及哪些项目依赖它Nx 图表所知的所有项目,但不包括工作区根目录本身
nestjs项目的 NestJS 模块导入图仅包含带有 framework:nestjs 标签的项目
imports项目自身的文件级 TypeScript 导入图所有带有自身 tsconfig.json 的项目
pythonImportsPython 对应图表,根据 import / from ... import 语句解析仅包含带有 language:python 标签的项目

整个工作区的 Nx 图表在 workspace.nx 下单独配置。它针对整个仓库导出一次,而不是针对每个项目各导出一次;它没有针对单个项目的覆盖配置,也不受 include / exclude 影响。其节点集合可由 --projects / --tags 缩小范围——见下文。

每种图表类型分别决定项目是否参与,并没有统一规则。 某个项目如果不适用于某种图表类型,就永远不会出现在该类型的结果中。因此,为每个项目都配置一种图表类型不会带来任何额外开销:没有 NestJS 容器的项目会直接从 NestJS 处理流程中排除,而不会导致失败。

--projects and --tags 从命令行选择项目

两者都接受逗号分隔的列表,并且都会同时做两件事:

codependix map --write --projects widgets,tools/reporting --config configuration/codependix.config.ts
codependix map --write --tags framework:nestjs,language:python --config configuration/codependix.config.ts

它们会扩大导出的范围。 只要有任意内容声明了某个项目,该项目就会参与:include glob、--projects glob 或 --tags 标签。标志会在配置已选内容的基础上追加,而不是替换它,因此,对于 include 为 ["**"] 的工作区,使用 --projects widgets 导出的内容与之前完全相同。exclude 仍优先于这三者:如果标志能让已排除的项目重新加入,exclude 就只能算是建议。

--projects 的匹配方式与 include 相同:将 glob 与项目的名称或相对于工作区的根目录进行匹配,因此 --projects packages/* 和 --projects codependix-* 都有效,且含义一目了然。--tags 则与项目自身的 Nx 标签进行精确匹配。

它们会缩小绘制和判定的范围。 指定选择项也会将整个工作区图的节点范围缩小到所选项目,并使这些项目成为 --check boundaries 唯一判定的对象。如果两者都未指定,则会选择所有项目,因此默认行为保持不变。

门禁会基于这些项目及其依赖关系构建。 --check boundaries 会基于所选项目及其所有传递依赖项,为每个级别构建图,并将每项发现归属到相应项目:循环归属到循环中的每个项目,禁止的边归属到其源项目,容器启动失败归属到容器项目。只有归属到所选项目的发现才会导致运行失败;仅归属到依赖项的发现会作为不会导致失败的备注记录为 “in dependency”。--no-dependencies 只基于所选项目构建——速度更快,但离开所选范围的边不会绘制出来,因此未能发现通过依赖项闭合的循环。--no-dependencies 运行成功所代表的含义不如默认运行成功:请仅在本地迭代时使用它。

如果选择项一个都未匹配,就会被拒绝,无论处于何种模式:拼错的名称、没有项目使用的标签,或工作区根目录(它永远不是可选项目),都会作为被拒绝的命令行以非零状态退出,并指出相关模式,而不是通过一个什么都没判定的门禁。

如果选择项只匹配了一部分,则会发出警告,而非拒绝。 --projects widgets,typo 会判定 widgets,并在 stderr 上记录警告 🕸️ Ignored selection entries that matched no project。警告会列出未匹配任何项目的 projects 和 tags,并附上检查拼写的 hint。退出码保持不变,因此,拼错的条目与有效条目并列时,会显示在日志中,而不会影响判定结果。

include/exclude 从不这样做——它们决定为哪些项目写入导出内容,并且从未作用于工作区图或门禁。正因如此,这些标志才会作为标志存在,而不是配置字段。

特意使用两个标志,而非 Nx 自带的 --projects=tag:foo 写法:两者会以各自的名称显示在 --help 中。不要“修复”这种差异。

一次门禁一个项目

--check boundaries --projects <name> 是可在普通 shell 中运行的单项目门禁,Nx 工作区则会自动推断该门禁。@codependix/nx 插件会为每个由 project.json 描述的项目添加一个带缓存的 codependix-gate 目标,但工作区根目录除外。它会在工作区根目录下,借助 NestJS 所需的保留装饰器加载器,准确运行该命令;该加载器由插件通过自身依赖注册:

nx run lexico-entities:codependix-gate   # one project
nx affected -t codependix-gate           # only what a change touched

每个项目的门禁都会因归属于该项目的问题而失败。因此,边界损坏时,失败的是拥有该边的项目,以及环上的每个项目,而不是一个无法指出具体项目的全工作区任务。仅仅基于损坏项目进行构建的依赖项目会将问题作为说明输出,并通过门禁;失败的是损坏项目自身的门禁,因此要重现失败,请运行问题中指出的项目的门禁。

缓存键由项目、其依赖项、配置和 codependix 命令行决定,不包括测试文件。如果某个门禁的选择范围不同于它自身的项目,它判断的项目就不在这些输入所覆盖的范围内,因此绝不会从缓存中重放;只判断自身项目的门禁则照常缓存。该目标没有声明任何配置,因此,使用 --configuration=check 运行聚合器时会回退到默认配置,callidescope 的 callidescope-gate 就是如此。在此仓库中,guard-code 依赖于它。全工作区的 configuration:codependix 目标只负责写入:它会在默认分支发布导出内容,不执行任何门禁。

运行报告的内容

无论之前的步骤是否失败,都会尝试运行每个步骤;某个项目的失败也只会影响该项目——缺少 README,或 NestJS 项目无法启动其容器,都会被记录为失败,而其他每个项目仍会继续运行。--write 要么完全成功,要么准确列出失败的项目。

报告会分别列出三类问题,其中任何一类都会导致运行失败:

  • 失败 — 在解析导出内容之前发生异常的项目,或无法构建图以进行判断的项目。
  • 过期导出内容 — 在 --check reports 模式下,配置的导出内容与新构建的图不一致。
  • 边界违规 — 在 --check boundaries 模式下,违反已声明规则的边和环。每项都会指出其级别、范围、规则、两个端点、归属的一个或多个项目,以及规则中说明其存在原因的内容。它们会输出到控制台并影响退出代码;只有在 --format、--json-output 或 --markdown-output 要求生成报告时,才会写入报告。当前存在问题的列表不值得作为文档提交,因此 --write 插入 README 的导出内容绝不会包含它。

解析为 target: "none" 的项目会完全从结果中排除,而不会被报告为最新;因此,退出代码只取决于 codependix 实际配置为生成的导出内容。--check 运行报告的项目数为 0,表示系统没有配置任何生成内容。

边界报告

使用 --check boundaries 运行时,添加 --format json、--json-output <path> 或 --markdown-output <path>,即可将检查结果打印为报告。在 JSON 中,报告位于与图类型并列的 boundaries 键下;在 Markdown 中,报告位于 ### Boundaries 小节中。仅运行 --check boundaries 不会导出任何内容,因此只会打印报告。不添加上述任一标志时,仅检查边界的运行 不会打印任何内容;同时执行导出时,则照常打印图。

codependix map --check boundaries --projects lexico-entities --format json --config configuration/codependix.config.ts

boundaries.judgedProjects 列出其检查结果会导致运行失败的项目。violations 和 failures 中的每个条目都包含被计入的 projects 和一个 verdict:fail 会导致运行失败;note 表示某个受评项目的依赖项中存在检查结果,但不会导致运行失败。failures 条目——即无法启动的容器——还会在其失败所涉及的类属于另一个项目,而非容器所属项目时,注明 ownerProject。查看 fail 条目, 并将 note 条目视为该依赖项自身门禁的事项。

如果在 nxProjects 层级失败(无法构建 Nx 项目图),则会将其计入每个受评项目,因为无法对其中任何项目进行评估。受评项目不止一个时,报告会显示为 all N judged projects,而非项目列表;Markdown 报告会将其在 #### All judged projects 下列出一次,而不是在每个项目下重复列出。JSON 会保留完整的 projects 数组。其他所有层级都会按项目分别构建图,因此该层级的失败(包括无法启动的容器)只会计入对应的一个项目。项目符号的错误文本会保留换行,并缩进显示在项目符号下方;--> 会写作 --&gt;,以免文本意外结束 HTML 注释。

阅读导出内容

Markdown 目标会写入 Mermaid 图。在锚点模式下,图会插入到两个用于标明锚点的 HTML 注释标记之间:


```mermaid
graph LR
  widgets["widgets"]
  logger["logger"]
  widgets --> logger
  classDef subject fill:#7c3aed,color:#fff,stroke:#4c1d95,stroke-width:2px
  class widgets subject
```

高亮的 subject 节点是 Neighborhood 的中心项目。节点标识符会根据名称和路径进行规范化,因此请阅读引号中的标签,而非标识符。

JSON 目标会写入图自身的结构:Nx Neighborhood 包含 dependencies、dependents、edges 和 projectName;导入图包含 fileNames、edges、isolatedFileNames 和 projectName;NestJS 模块图会额外包含 ambientModuleNames,用于列出其边被有意排除在图外的全局模块。

要使用已提交的图来解答有关代码库的问题——有哪些内容依赖于此、重命名会影响哪些内容、某个导入循环是否真实存在——请使用 codependix-navigate 技能。

切勿手动编辑标记之间的内容

下一次 --write 会整体替换锚点区块。手动编辑的图会成为一项差异,并在下一次运行时悄然消失;评审者会看到一个无故自行撤销的更改。

重新运行 --write 是修复过时的 --check reports 的唯一方法。 它绝不能用于修复 --check boundaries 失败——那是实际代码中的真实边,而写入导出内容并不会将其移除。无论是处理哪种情况,都请使用 codependix-triage 技能;要阅读或更改规则本身,则请使用 codependix-configure 技能。

评论

支持 Markdown