mcpField
P
project-validator

project-validator

github.com/datex测试与质量92 次安装
代码仓库

关于 project-validator

project-validator 是面向 Datex Studio 的项目级只读检查技能,适合在合并批次或发布前审查分支配置。它从分支导出配置,并执行五类跨组件检查,补充单文件验证无法发现的问题。

主要功能

  1. 01从分支枚举并导出配置
  2. 02执行五类项目级检查
  3. 03检查描述与类型引用
  4. 04预检 OData 架构和查询
  5. 05按检查类别整理问题清单
  6. 06只读运行,不修改分支

适用场景

  1. 01合并前检查一批配置
  2. 02发布前扫描整个项目
  3. 03仅检查指定配置类型
  4. 04定位跨文件引用或架构问题

安装

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

$npx skills add https://github.com/datex/skills --skill project-validator

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

详细介绍

项目验证器

针对 Datex Studio 分支进行项目级 lint 检查。分支是真实来源:验证器通过 dxs source explore configs 枚举分支中的配置,并通过 dxs source document build(CLI 的离线分析路径)将其批量导出到临时目录,然后针对该临时导出运行五项跨组件检查——这些检查无法通过逐文件验证单独完成。返回按检查类型分组的结构化只读待办清单。绝不修改分支,也绝不将本地 src/ 检出目录视为权威来源。

这是项目级验证器。它与逐文件验证相辅相成:component-validator 根据特定类型的规则表端到端审核单个组件文件;本技能则审核整个项目(或指定范围的子集),查找只有跨文件检查时才会出现的问题——例如失效的 objectType 引用、与实时架构不匹配的 OData 查询、偏离已声明 outParams 的数据源查询选项等。这两项技能旨在配合使用——每个文件编写完成后使用 component-validator,合并一批更改或发布版本前使用 project-validator。

另请参阅: component-validator — 根据各类型的创建规则表审核单个文件。在编写或修改任何组件后使用。本技能是它在项目级别的对应工具。

另请参阅: component-wiring-check — 追踪特定的跨组件引用约定。本技能覆盖面更广(涵盖整个项目的 5 类问题),但检查较浅(lint 级别,而非深入的连线追踪)。

另请参阅: post-edit-verification — 写入单个文件后的快速检查。其范围与本技能不同,检查也更轻量。

依赖项

  • datex-studio-conventions — defaults.md(描述 ≤100 个字符、描述必填)、file-format.md(configurationTypeId 表、后缀规则)、naming-conventions.md(类型标识规则)。以下检查所执行的规则均来自这些文档。
  • datex-studio-shared / datex-studio-runtime — 用于解析流程代码的分支设置基础工具和平台运行时全局对象(例如解析 $flow.inParams.<name> 和 $flow.outParams.<name> 引用)。
  • component-validator — 逐文件配套工具,范围相邻。当项目验证器发现某个文件局部违规,而创建技能的规则表中详细记录了该问题时,应将用户引导至 component-validator 进行深入审核。
  • schema-explorer — 用于 OData 预检(检查 4)。项目验证器不得将原始架构文档加载到父上下文中——始终将实体、属性和导航项查询委托给 schema-explorer。
  • codebase-research — 当某项发现需要基于依据只读检查支持上下文时调用(例如从分支获取 *-customType 配置,以确认枚举的允许值)。可选,按需使用。

模式

这是只读的项目 lint 检查。不要修改任何文件。不要运行会更改分支状态的命令(不得使用 upsert、--fix 或写入操作)。验证器只负责报告;由父级决定如何处理发现的问题,并将修复任务交回相应的创建者/编辑器技能。

工作流

1. 确定范围

验证器始终针对一个分支运行(遵循 datex-studio-shared/branch-setup.md 来确定分支 ID——切勿自行假设)。调用方还需提供以下选项之一:

  • all(默认)— 分支上的所有自有配置。
  • 一个检查名称 — descriptions、schema、types、metadata、result-shapes。仅针对整个项目运行该项检查。
  • 一个范围子集 — 一种或多种配置类型(例如 grid、datasource),或名称模式。仅在该子集中运行全部五项检查(或指定的检查)。

如果调用方的要求不明确(例如只说“验证项目”),则默认检查分支上的所有自有配置,并在输出中说明所选范围。

2. 枚举并导出目标配置(来自分支)

分支是唯一可信来源——不要遍历本地的 src/ 检出目录。通过 CLI 获取配置:

# List what's on the branch (optionally filter by type / owned-only / scope)
dxs source explore configs --branch <branchId> --owned-only

# Bulk-export every config to a THROWAWAY temp dir for offline analysis
dxs source document build --branch <branchId> --include-summaries -o "$TMP/dxs-validate"

document build 会在 $TMP/dxs-validate/<App>/<branchId>/local/<type>/<referenceName>.yaml 下为每个配置写入一个文件。这些临时导出文件是检查唯一会读取或搜索的文件——搜索刚获取的临时文件是允许的做法;搜索持久化的 src/ 树则不允许。完成后删除临时目录。

在 dxs < 0.5.4 中,此导出会悄无声息地不完整——需要 dxs ≥ 0.5.4。 库发现逻辑依赖于一个 applicationId,而从设置/引用迁移到 AppConfig 时,每个引用行中的这个字段都被移除了,因此 document build 只会遍历分支本身;由于每次分支遍历都会按设计排除外部配置,所有库配置都不会出现在导出中——命令退出码为 0,且没有任何警告。将名称解析到被引用的包中的检查(types、schema、result-shapes)随后会把这些缺失项视为“组件缺失”,并产生误报。较旧版本生成的干净运行结果不代表任何信息,不能视为通过:请升级(dxs update)。从 0.5.4 起,导出会包含库分支,并会针对仍无法定位的库打印 Warning: could not resolve library '<name>' to a branch——这同样意味着存在缺口,只是这次会在运行过程中报告,请据此确定受影响检查的范围。

按类型对导出的配置分组(导出文件已按类型放在不同文件夹中,且每个配置都带有 configurationTypeId):

  • footprintflow — 操作(*-footprintFlow)
  • flow — 函数(*-flow)
  • customtype — 接口 / 枚举(*-customType)
  • footprintdatasource — Footprint 级 OData 数据源
  • datasource — 云级数据源(OData 或由 flow 提供支持)
  • selector、storage、grid、form、editor、hub、backendtest

类型与表格不匹配的配置记为 unknown component type 并跳过(不要因此阻止运行)。

3. 运行 5 项检查

针对枚举出的文件运行每项检查。顺序不限;可先运行成本最低的检查。将发现项收集为结构化列表,绝不就地编辑。

4. 报告

按照下方的输出格式部分编写待办清单。按检查类型对发现项分组。最后用一行总结(total files checked、passes、warnings、failures)。除一句简短的指引外,不要提出修复建议。

5 项检查

1. 描述验证(descriptions)

扫描对象: 每个组件文件(所有上述后缀)。

规则(来自 datex-studio-conventions/defaults.md 和 file-format.md):

  • description 不得为 null。
  • description 不得为 ""(空字符串)。
  • description 必须不超过 100 个字符。这是 Footprint 端 SQL 列的硬性上限——超出上限会导致导入因 SQL 截断错误而失败。

严重程度:

  • description 为 null 或 "" → 失败。
  • description 超过 100 个字符 → 失败(不是警告——导入会失败)。
  • description 存在且未超出上限 → 通过。

输出行:

[pass] i_awi_configuration-customType.json — "Allocation config interface" (35 chars)
[FAIL] my_action-footprintFlow.json — description is null
[FAIL] orders_grid-grid.json — description is 137 chars (cap is 100)
2. Schema 与代码对齐(schema)

**扫描对象:**操作文件(*-footprintFlow.json)和函数文件(*-flow.json)。

**检查内容:**声明的 inParams / outParams JSON 与嵌入的 TypeScript 代码是否一致;代码位于 nodes[0].stepConfig.executeCodeConfig.code(根据 codebase-research 中记录的模式,流程代码位于 JSON 内部,而非 JSON 顶层)。

流程:

  1. 从 JSON 中解析 inParams[] 和 outParams[]。
  2. 提取嵌入的代码字符串(对于多步骤流程,遍历 nodes[*])。
  3. 使用启发式匹配,检查代码中的 $flow.inParams.<id> 引用是否对应每个已声明的 inParam.id。
  4. 使用启发式匹配,检查代码中的 $flow.outParams.<id> 引用是否对应每个已声明的 outParam.id。
  5. 查找代码中没有对应声明的 $flow.inParams.<name> 或 $flow.outParams.<name> 引用。

严重级别:

  • 已声明的 inParam 未在代码中引用 → 警告(可能是有意保留,以兼容旧版本、供将来使用,或用于外部连线)。
  • 已声明的 outParam 从未在代码中赋值 → 警告。
  • 代码引用了没有对应声明的 $flow.inParams.<name> / $flow.outParams.<name> → 失败(会导致运行时错误或静默返回 undefined)。

**注意:**这只是启发式字符串匹配,并非 TypeScript 编译器。发现误报时可以将其列为警告,由调用方判断每条警告是否属实。没有基于源代码的确凿证据时,不要将警告升级为失败。

输出行:

[warn] plan_inventory_consumption_action — inParam 'unused_param' declared but not referenced in code
[FAIL] commit_allocation_plan_action — code references $flow.inParams.foo but 'foo' is not declared in inParams
3. 类型解析(types)

**扫描对象:**每个组件文件。在 JSON 中查找任意位置的 "objectType": "<Package>.<TypeName>" 值(通常位于 inParams[*].objectType、outParams[*].objectType、objectTypeDef.properties[*].objectType 以及嵌套的数据源结构中)。

**规则:**每个被引用的 <Package>.<TypeName> 都必须能解析为以下类型之一:

  • 当前分支上由当前包拥有的 <TypeName> customType 配置(临时导出中的 customtype/<TypeName>-customType.* 条目;等价查询为 dxs source explore configs --branch <id> --type customtype --search <TypeName>),或
  • 项目所依赖的其他包拥有的类型(将未知包视为“超出范围,不报告”,除非调用方明确要求追查跨包引用)。

流程:

  1. 确定当前包(从该包的一个组件文件中读取;通过文件夹约定进行交叉核对)。
  2. 收集所有已扫描组件文件中的每个 objectType 字符串。
  3. 对每个包内引用,验证分支上是否存在对应的 <TypeName> customType 配置(位于临时导出的 customtype/ 文件夹中)。**快速解析捷径:**一次性获取分支的命名法注册表 — dxs configuration nomenclature -b <branchId> 会返回扁平的 <Package>.<Type> 目录(枚举成员位于 constantValues 中),可一次性检查每个 objectType 是否存在,而无需逐个类型执行 dxs source explore 查询。参见 ../datex-studio-shared/context-navigation.md#discovering-custom-types-and-enum-members。
  4. 报告无法解析的引用。

严重级别:

  • 引用当前包中的类型,但分支上没有对应的 customType 配置 → 失败。
  • 引用的包不属于项目 → 警告(可能是拼写错误,也可能是合法的外部包)。

输出行:

[FAIL] orders_grid-grid.json — references `Allocations.i_unknown_type`, no i_unknown_type-customType.json found
[warn] import_orders_action-footprintFlow.json — references `ExternalPkg.i_thing`; ExternalPkg is unknown to this project
4. OData 架构预检(metadata)

扫描: OData 数据源文件——*-footprintDatasource.json,以及 type 为 "oDataQuery" 的 *-datasource.json 文件。跳过由流程支持的数据源。

流程:

  1. 解析连接。 每个数据源都引用一个连接(连接 ID 或连接名称)。从文件中确定连接。如果有歧义,请询问调用方要针对哪个连接进行验证。
  2. 每次实体 / 属性 / 导航查找都委托给 schema-explorer。不要将原始 OData 元数据文档加载到父上下文中——schema-explorer 会返回简洁的结构化答案,并处理连接解析和 FootPrintApi 特殊情况。
  3. 对每个 OData 数据源:
    • 确认 OData 架构中存在 paths[0].entitySet 中的 entitySet。
    • 确认 queryOptions.selects 中的每个属性都存在于实体类型中。
    • 确认 queryOptions.filters 中引用的每个属性(筛选表达式操作数)都存在于实体类型中。
    • 确认 queryOptions.expands 中的每个导航属性都存在于实体类型中。
  4. 报告不匹配项。

严重程度:

  • 缺少实体集 → 失败。
  • 缺少 select / filter 属性 → 失败。
  • expand 中缺少导航属性 → 失败。
  • 架构查找失败(连接无法访问、架构未加载)→ 警告,并注明无法对此文件运行检查。单个连接无法访问时,不要判定整个运行失败——记录警告并继续。

输出行:

[FAIL] fpds_get_material-footprintDatasource.json — entitySet 'Materials' not found in schema (did you mean 'Material'?)
[FAIL] ds_orders_grid-datasource.json — selects: property 'CustomeName' not on entity 'Orders' (typo?)
[warn] ds_legacy_thing-datasource.json — could not reach connection 'LegacyProd'; check skipped
5. 结果形状同步(result-shapes)

扫描: 所有数据源文件(包括 *-datasource.json 和 *-footprintDatasource.json,以及 OData 和由流程支持的数据源)。

规则: 数据源的查询端形状(queryOptionsObjectTypeDef)和面向使用者的形状(outParams[0].objectTypeDef)必须一致。一侧的每个属性都应在另一侧有匹配项,且 id 和 type 相同。这两项声明不一致,是“数据源在 Studio 预览中正常工作,但会导致使用者出错”的典型故障模式。

流程:

  1. 从文件中读取 queryOptionsObjectTypeDef.properties[]。
  2. 从文件中读取 outParams[0].objectTypeDef.properties[]。
  3. 按 id 配对属性。
  4. 标记一侧存在但另一侧没有对应项的属性,或 id 配对项中 type 不同的属性。

严重程度:

  • 属性仅存在于一侧,另一侧缺失 → 失败。
  • 属性配对项的 type 不匹配 → 失败。
  • 属性配对项的 id 和 type 相同,但顺序 / 元数据不同 → 小问题。

输出行:

[FAIL] ds_open_orders-datasource.json — `queryOptionsObjectTypeDef.OrderId` is `int32`, `outParams[0].objectTypeDef.OrderId` is `string`
[FAIL] fpds_lots-footprintDatasource.json — `outParams[0].objectTypeDef` declares property `LotCode`, missing from `queryOptionsObjectTypeDef`

输出格式

按检查类型分组列出发现项,顺序与上述五项检查一致。每组内先列失败项,再列警告,最后列小问题。通过项行可选——调用方要求详细运行时包含,否则在默认 lint 摘要中省略。始终以一行摘要结尾。

## 1. Description Validation
  [FAIL] my_action-footprintFlow.json — description is null
  [FAIL] orders_grid-grid.json — description is 137 chars (cap is 100)
  [pass] i_awi_configuration-customType.json — "Allocation config interface" (35 chars)
  ...

## 2. Schema-Code Alignment
  [FAIL] commit_allocation_plan_action — code references $flow.inParams.foo but 'foo' is not declared in inParams
  [warn] plan_inventory_consumption_action — inParam 'unused_param' declared but not referenced

## 3. Type Resolution
  [FAIL] orders_grid-grid.json — references `Allocations.i_unknown_type`, no i_unknown_type-customType.json found

## 4. OData Schema Pre-Flight
  [FAIL] fpds_get_material-footprintDatasource.json — entitySet 'Materials' not found (did you mean 'Material'?)
  [warn] ds_legacy_thing-datasource.json — could not reach connection 'LegacyProd'; check skipped

## 5. Result-Shape Sync
  [FAIL] ds_open_orders-datasource.json — `OrderId` type drift: query=int32, outParams=string

## Summary
  files checked: 142
  passes: 128
  warnings: 7
  failures: 7
  scope: all

如果检查已运行且未发现问题,请在相应标题下写 (no issues),而不要省略该标题——明确标注为空比不作说明更清晰。

规则

  • 只读。 不要修改任何文件。不要自动修复。不要运行会修改内容的 dxs 命令。验证器的任务是报告问题;由父级(或用户)决定后续操作。
  • 列出待办,不要重写。 每条发现都应是一行引用,包含文件路径和简短的证据行。不要提供冗长的代码建议或拟议的 JSON。如果修复方式不明显,请指出负责该修复的对应创建者技能(例如“交由 datasource-creator 处理”),而不是描述修复本身。
  • 将 OData 架构交给 schema-explorer。 绝不要将原始 OData 元数据载入父级上下文。这是 Datex Studio 工作中最严重的上下文污染反模式。
  • 启发式检查只能发出警告,不能判定失败。 尤其是架构与代码对齐检查,它是字符串匹配 lint,不是编译器。对于“可能确有问题”的情况使用 warning,只有证据明确无误时才使用 fail。
  • 遵守范围限制。 调用方指定检查名称时,只运行该检查。调用方指定子树时,只遍历该子树。不要自行扩大范围。
  • 不要猜测意图。 如果违规可能是有意为之(例如为外部接线而保留的 inParam,或出于前瞻性考虑而声明范围宽于查询的 outParams),应附注并标记为警告,而不是失败。
  • 每次调用只运行一次。 不要反复运行验证器,直到“全部通过”。列出待办后交由父级决定是否继续迭代。
  • 以分支为准。 使用 dxs source explore configs / dxs source document build 从分支枚举并导出配置。不要将本地 src/ 检出内容视为权威来源。
  • 不得写入分支,不得提供修复补丁。 唯一允许的本地产物是临时的 dxs source document build 导出文件,检查会读取该文件,完成后应将其删除。报告直接放在响应正文中返回——不要创建 references/、日志或补丁文件。

评论

支持 Markdown