总结
我现在用最直白、最直接、最不绕弯子的的话告诉你——调研的方案里没有一个能 npm install 直接用的。Daedalus 要解决的问题(AI 代码审查平台的代码结构元数据描述)本身就没人做过一模一样的
> 👇下面是我个人总结的一些可能需要改进的方向
使用的统一的数据结构来描述各种概念
实体各自孤立建模,Crate、Archetype字段形态各异,无法用统一的查询接口遍历"Crate X 依赖哪些 Archetype"。我们需要提供一个基类去继承,如果有需要统一升级的能力,改基类就行可了。孤立建模无法用统一的关系来描述,每两个概念就需要一个关系来表示。
先写一个 TypeScript 层的"统一视图",让现有的 Crate/Archetype 表通过适配器看起来像同一个模型。不是一开始就改数据库 schema。
关系
Conditions
目前只有两种类型,text与archetype_ref,Archetype的Conditions归根结底是结构化的text
比如,我希望使用Archetype/Crate描述一个商品购买卡片,大概长这个样子: 
商品购买卡片定义:
archetype: 组件设计最佳实践
archetype: 商品的定义
text: "卡片必须展示商品图片、名称、当前价格三个核心信息,缺一不可"
archetype:按钮
text: "卡片必须提供至少一个明确的购买操作入口(如「加入购物车」或「立即购买」按钮)"
text: "卡片必须能正确处理以下商品状态:正常售卖、已售罄、已下架、限时折扣中、即将开售"
组件设计最佳实践定义:
text: 组件有明确的单一职责
text: 组件被复用 2 次以上,或有明确的复用潜力
text: 支持 `asChild` 模式(使用 Radix Slot)
archetype: 桶导出
桶导出:
text: 每个目录有 index 文件:存在导出文件的目录必须有 `index.ts`
text: 桶导出文件中禁止使用 `export default`
按钮:
text: 能点击
text: ...
AI看到的:
// archetype 商品购买卡片
{
archetype: {
text: 组件有明确的单一职责
text: 组件被复用 2 次以上,或有明确的复用潜力
text: 支持 `asChild` 模式(使用 Radix Slot)
archetype: {
text: 每个目录有 index 文件:存在导出文件的目录必须有 `index.ts`
text: 桶导出文件中禁止使用 `export default`
}
}
archetype: {
...
}
text: "卡片必须展示商品图片、名称、当前价格三个核心信息,缺一不可"
archetype:{
text: 能点击
text: ...
}
text: "卡片必须提供至少一个明确的购买操作入口(如「加入购物车」或「立即购买」按钮)"
text: "卡片必须能正确处理以下商品状态:正常售卖、已售罄、已下架、限时折扣中、即将开售"
}
我们将这些内容交给AI后,AI 读到了 9 条文本,理解了,然后去读代码,输出审查结果。看起来很美好但是有几个问题:
- 是否真的被复用 2 次以上
- 目录中有没有index文件
- 禁止使用
export default,到底使用了没 - ...
系统自己无法验证任何东西,所有的能力都依托于AI去读text。审查结果需要可验证,约束需要部分可自动化。
所以我们要添加一些新的类型,比如路径,依赖方向,结构化约束,数量约束,联合约束
> 这里的话我想可以直接使用下面的Relation来表示
将关系作为一个实体单列出来并限制
除了已有的Archetype与其Conditions之间的关系,Crate之间,Archetype与Crate之间也存在关系,但他们之间的关系很难通过类似condition_dependencies 中仅存两外键的形式表示。缺少关系语义,是强依赖还是弱引用?为什么依赖?
/**
* 关系类型——描述两个结构单元之间的语义连接
*
* 借鉴:
* - ADL Connector 作为一等公民的设计
* - Backstage 的 well-known relations
* - Property Graph 的有类型有属性边
*/
export const RelationTypeSchema = z.enum([
"dependsOn", // 运行时/编译时依赖(A 需要 B 才能工作)
"dependencyOf", // dependsOn 的反向
"partOf", // A 是 B 的组成部分(A → B 读作"A 属于 B")
"hasPart", // partOf 的反向(B 包含 A)
"implements", // A 实现了 B 定义的接口/契约
"implementedBy", // implements 的反向
"references", // A 引用 B(非依赖性的弱引用)
"referencedBy", // references 的反向
"conformsTo", // A 遵循 B 的约束(Crate → Archetype 的关系)
"conformsFrom", // conformsTo 的反向
"extends", // A 扩展/继承 B
"extendedBy", // extends 的反向
"replaces", // A 替代 B(版本迁移)
"replacedBy", // replaces 的反向
]);
定义Archetype:
// ═══════════════════════════════════════════════════════════
// Archetype: ecommerce-purchase-card
// 定义"一个合格的商品购买卡片应该满足什么条件"
// ═══════════════════════════════════════════════════════════
const purchaseCardArchetype: StructureUnit = {
// ── 基础标识 ──
uid: "archetype:default/ecommerce-purchase-card",
unitKind: "archetype",
unitTypes: ["design-contract", "ui-pattern", "ecommerce"],
displayName: "E-commerce Purchase Card",
description: `商品购买卡片的设计范式。
一个合格的商品购买卡片必须:
- 展示商品的核心信息(图片、名称、价格)
- 提供明确的购买/加入购物车操作
- 对缺货、已下架等状态有对应的 UI 反馈
- 有独立的测试和 Storybook 文档`,
level: "crate",
// ── 边界:这个 Archetype 本身没有代码边界,
// 但它定义了"符合它的 Crate 应该有什么边界" ──
boundary: {
exposes: [
{
name: "ProductPurchaseCard",
interfaceKind: "component",
filePath: "src/components/ProductPurchaseCard/ProductPurchaseCard.tsx",
signature: `(props: ProductPurchaseCardProps) => React.JSX.Element`,
stable: true,
},
],
encapsulations: [
"src/components/ProductPurchaseCard/**",
],
visibility: "public",
},
// ── 扩展属性:这个 Archetype 的额外元数据 ──
properties: {
// 适用范围
applicableTo: ["component", "ui", "ecommerce"],
// 标签
tags: ["purchase", "card", "product", "ecommerce"],
// 示例仓库(如果存在符合此 Archetype 的参考实现)
referenceImplementation: "crate:default/product-purchase-card",
// 所属领域
domain: "ecommerce",
// 版本
version: "1.0.0",
// 来源
_source: "archetypes_table",
},
};
Archetype的Conditions:
const purchaseCardConstraints: Constraint[] = [
// ── 约束 1:文本约束 —— 说出这个 Archetype 的核心要求 ──
{
constraintType: "text",
value: "卡片必须展示商品图片、名称、当前价格三个核心信息,缺一不可",
severity: "error",
},
// ── 约束 2:文本约束 —— 交互行为要求 ──
{
constraintType: "text",
value: "卡片必须提供至少一个明确的购买操作入口(如「加入购物车」或「立即购买」按钮)",
severity: "error",
},
// ── 约束 3:文本约束 —— 状态覆盖要求 ──
{
constraintType: "text",
value: "卡片必须能正确处理以下商品状态:正常售卖、已售罄、已下架、限时折扣中、即将开售",
severity: "warning",
},
// ── 约束 4:引用约束 —— 同时必须遵循「组件设计最佳实践」Archetype ──
{
constraintType: "archetype_ref",
archetypeUid: "archetype:default/component-design-best-practice",
requirement: "must", // 强制依赖——不符合组件规范就不算合格的商品卡片
},
// ── 约束 5:文件路径约束 —— 必须有桶导出文件 ──
{
constraintType: "path_pattern",
pattern: "src/components/ProductPurchaseCard/index.ts",
modifier: "must_exist",
recursive: false,
},
// ── 约束 6:文件路径约束 —— 禁止在 feature 外部直接引用卡片内部文件 ──
{
constraintType: "path_pattern",
pattern: "src/features/*/components/*",
modifier: "must_not_contain",
contentPattern: "from.*ProductPurchaseCard/ProductPurchaseCard\\.tsx",
recursive: false,
},
// ── 约束 7:依赖约束 —— 必须依赖商品数据类型定义 ──
{
constraintType: "dependency",
direction: "depends_on",
targetPattern: "**/types/product*",
cardinality: "at_least_one",
minStrength: "strong",
},
// ── 约束 8:依赖约束 —— 禁止直接依赖后端 SDK ──
{
constraintType: "dependency",
direction: "not_depends_on",
targetPattern: "**/api-client/**",
},
// ── 约束 9:结构化约束 —— 必须有 test 和 stories 文件 ──
{
constraintType: "structural",
rule: "has_tests",
},
// ── 约束 10:结构化约束 ──
{
constraintType: "structural",
rule: "has_stories",
},
// ── 约束 11:结构化约束 —— 必须使用命名导出 ──
{
constraintType: "structural",
rule: "prefer_named_export",
},
// ── 约束 12:结构化约束 —— 不能有循环依赖 ──
{
constraintType: "structural",
rule: "no_circular_deps",
},
// ── 约束 13:数量约束 —— 导出项数量范围 ──
{
constraintType: "quantity",
target: "exports",
operator: "between",
value: 1,
maxValue: 5, // 最多导出 5 个符号(卡片组件 + 最多 4 个子类型)
},
// ── 约束 14:数量约束 —— 依赖数量控制 ──
{
constraintType: "quantity",
target: "dependencies",
operator: "lte",
value: 8, // 商品卡片不应过度依赖外部模块
},
];
Crate定义:
// ═══════════════════════════════════════════════════════════
// Crate: ProductPurchaseCard
// 实际的代码组织单元——包含组件文件及其附属
// ═══════════════════════════════════════════════════════════
const productPurchaseCardCrate: StructureUnit = {
// ── 基础标识 ──
uid: "crate:default/product-purchase-card",
unitKind: "crate",
// ★ 多值类型标签——替代旧的固定枚举
unitTypes: [
"component", // 它是 UI 组件
"ui", // 属于 UI 层
"ecommerce", // 属于电商领域
"card", // 是卡片类组件
],
displayName: "ProductPurchaseCard",
description: `商品购买卡片组件。
展示单个商品的关键购买信息(图片、名称、价格、库存状态),
并提供「加入购物车」和「立即购买」两个操作入口。
支持的商品状态:
- 正常售卖:显示价格和购买按钮
- 已售罄:灰色遮罩 + "已售罄"标签
- 已下架:淡化显示 + "已下架"提示
- 限时折扣:显示原价(划线)+ 折扣价 + 倒计时
- 即将开售:显示预告 + 开售倒计时`,
// ── 层级定位 ──
level: "crate",
parentUid: "repository:default/my-ecommerce-app",
// ── ★ 边界定义:这个 Crate 对外暴露什么、内部封装什么 ──
boundary: {
exposes: [
{
name: "ProductPurchaseCard",
interfaceKind: "component",
filePath: "src/components/ProductPurchaseCard/ProductPurchaseCard.tsx",
signature:
"(props: ProductPurchaseCardProps) => React.JSX.Element",
stable: true,
deprecated: false,
docsUrl: "https://storybook.example.com/?path=/docs/product-purchase-card",
},
{
name: "ProductPurchaseCardProps",
interfaceKind: "type",
filePath: "src/components/ProductPurchaseCard/ProductPurchaseCard.types.ts",
signature: `{
product: Product;
onAddToCart: (productId: string, quantity: number) => void;
onBuyNow: (productId: string) => void;
variant?: "default" | "compact" | "hero";
className?: string;
}`,
stable: true,
},
{
name: "ProductPurchaseCardSkeleton",
interfaceKind: "component",
filePath: "src/components/ProductPurchaseCard/ProductPurchaseCardSkeleton.tsx",
signature: "() => React.JSX.Element",
stable: true,
},
],
encapsulations: [
"src/components/ProductPurchaseCard/**",
"src/components/ProductPurchaseCard/__tests__/**",
"src/components/ProductPurchaseCard/stories/**",
],
// internal = 仅同一个 repository 内的代码可以导入
visibility: "internal",
},
// ── 扩展属性 ──
properties: {
// 技术栈
techStack: ["react", "typescript", "tailwindcss", "framer-motion"],
// 关联的 Storybook 路径
storybookPath: "/story/product-purchase-card--default",
// 负责人
owner: "ui-team",
// 审查状态(飞轮指标)
reviewStats: {
lastReviewAt: "2026-07-01T10:00:00Z",
findingsCount: 2,
severity: "low",
},
},
};
Relation定义:
// ═══════════════════════════════════════════════════════════
// Relation 1: Crate 符合 Archetype
// "ProductPurchaseCard 这个 Crate 遵循了
// ecommerce-purchase-card 这个 Archetype 的设计契约"
// ═══════════════════════════════════════════════════════════
const conformsRelation: Relation = {
id: "rel-card-001",
sourceUid: "crate:default/product-purchase-card",
targetUid: "archetype:default/ecommerce-purchase-card",
relationType: "conformsTo",
properties: {
strength: "strong",
direction: "unidirectional",
reason: "ProductPurchaseCard 是电商商品卡片的标准实现,必须满足所有卡片设计契约",
phase: "compile",
extra: {
conformanceScore: 0.92, // 一致性评分
verifiedAt: "2026-07-01", // 最近一次验证通过时间
verifiedBy: "scan-run-42", // 由哪次审查运行验证
},
},
};
// ── 依赖关系:卡片依赖商品类型定义 ──
const productTypeCrate: StructureUnit = {
uid: "crate:default/product-types",
unitKind: "crate",
unitTypes: ["types", "domain-model"],
displayName: "Product Types",
description: "商品领域的数据类型定义,包括 Product、ProductStatus、Price 等",
level: "crate",
boundary: {
exposes: [
{
name: "Product",
interfaceKind: "type",
filePath: "src/types/product.ts",
signature: `{
id: string;
name: string;
description: string;
images: string[];
price: Price;
status: ProductStatus;
stockQuantity: number;
category: string;
}`,
},
],
encapsulations: ["src/types/product*.ts"],
visibility: "public", // 类型定义应对全仓库公开
},
};
const dependsOnProductTypes: Relation = {
id: "rel-card-002",
sourceUid: "crate:default/product-purchase-card",
targetUid: "crate:default/product-types",
relationType: "dependsOn",
properties: {
strength: "strong",
direction: "unidirectional",
reason: "ProductPurchaseCardProps 引用了 Product 类型,卡片渲染依赖于商品数据结构",
phase: "compile",
},
};
// ── 层级关系:Crate 属于某个 Repository ──
const repository: StructureUnit = {
uid: "repository:default/my-ecommerce-app",
unitKind: "repository",
unitTypes: ["monorepo", "turborepo", "ecommerce"],
displayName: "My E-commerce App",
description: "电商前端应用——包含商品浏览、购物车、下单等完整购买链路",
level: "repository",
boundary: {
exposes: [],
encapsulations: [
"src/**",
"packages/**",
"apps/**",
],
visibility: "public",
},
};
const partOfRepo: Relation = {
id: "rel-card-003",
sourceUid: "crate:default/product-purchase-card",
targetUid: "repository:default/my-ecommerce-app",
relationType: "partOf",
properties: {
strength: "strong",
reason: "商品购买卡片是电商应用的 UI 组件之一",
},
};
// ── 引用关系:Storybook 文档引用了该组件 ──
const storybookPage: StructureUnit = {
uid: "page:default/my-ecommerce-app/storybook/product-card",
unitKind: "page",
unitTypes: ["documentation", "storybook"],
displayName: "ProductPurchaseCard Stories",
level: "page",
};
const referencedByStorybook: Relation = {
id: "rel-card-004",
sourceUid: "page:default/my-ecommerce-app/storybook/product-card",
targetUid: "crate:default/product-purchase-card",
relationType: "references",
properties: {
strength: "weak",
reason: "Storybook 文档引用组件作为演示对象",
},
};
Repository ←─partOf── ProductCard ──conformsTo──→ Archetype
│ │
│ dependsOn archetype_ref
▼ ↓
ProductTypes ComponentDesignBP
▲
│ references (Storybook)
│
StorybookPage
具有通用性
所有参考几乎都是,用户输入->数据实体->产出。 我们项目的过程其实是逆过程,产出->对照实体->输出问题。
用来表述的结构要AI友好
flat tree使用扁平的结构
flat tree 的核心好处:每个元素是一个独立的键值对,LLM 流式生成时不会因为少一个 } 导致整个 JSON 非法。这直接解决了 AI 生成嵌套 JSON 的"括号地狱"问题:
// ❌ 嵌套 JSON(AI 流式生成时容易括号不闭合)
{ "type": "Card", "props": {...}, "children": [
{ "type": "Button", "props": {...}, "children": [
{ "type": "Icon", ... }
]}
]}
// ✅ Flat tree + ID 引用(每个元素独立,ID 引用连接)
{
"root": "card-1",
"elements": {
"card-1": { "type": "Card", "props": {...}, "children": ["btn-1"] },
"btn-1": { "type": "Button", "props": {...}, "children": ["icon-1"] },
"icon-1": { "type": "Icon", "props": {...}, "children": [] }
}
}
Zod Schema = 约束 + 运行时验证
要做好动态类型检验。json-render 的catalog.Validate()、wasp的tsc 类型检查-AI 输出后立即有反馈信号。没有验证层的AI生成是不可靠的。Structureunit 的zod schema应同时承担"给AI 看的 prompt"和"验证AI 输出的guard"双重角色。
表达式用 JSON DSL 而非 JS
{ "$state": "/form/hasError" } // 引用状态
{ "$cond": {...}, "$then": "home", "$else": "outline" } // 条件
这些表达式是纯 JSON 值,不是代码字符串——AI 生成 JSON 远比生成"不会出 bug 的 JavaScript"可靠。
统一的数据结构
这点和上面的一样
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
spec:
type: service
owner: team-a
lifecycle: production
不管你描述的是服务、数据库、API、团队还是文档,全部遵循 apiVersion + kind + metadata + spec 四段式。AI 不需要学习不同的格式——学会了 envelope,就能描述任何软件资产。
toPrompt() 机制
json-render 的杀手锏是 catalog.prompt()——一键把整个数据结构定义编译为 AI 可消费的 system prompt。Daedalus 的 StructureUnit + Relation + Constraint 模型如果真的落地,最核心的 AI 友好设计应该是:
// 定义一个archetype
const archetype = New Archetype({
// init
})
const archetypePrompt = archetype.toPrompt()
// "这个结构单元是一个 React 组件。它必须满足:
// 1. 文件路径匹配 src/components/**/ComponentName.tsx
// 2. 必须有 .test.tsx 和 .stories.tsx 伴随文件
// 3. 只能从 @/ui 导入 UI 组件
// 4. ..."
这样 AI 审查代码时,不是收到一堆自由文本的 Condition,而是被一个结构化的、可验证的、由 Zod schema 约束的 Contract 所引导。这才是"AI 友好"的本质——数据结构的设计本身就是 AI 的 prompt。
有限词汇表
Backstage 的well-known relations、Structurizr的~20种元素、Wasp的固定spec声明类型——词汇表越小,AI 幻觉越少。Relation类型不要做成自由文本,要用discriminatorunion限定。
描述优于代码
所有方案的description 字段都不只是文档——它们是 AI prompt 的原材料。每个结构单元都应该有能让AI理解的语义描述。 Crate/Archetype 的description应该写得像给AI看的一样(目前已经是,但需保持)。
层级路径命名体系
借鉴三个来源:
- Rust
pub use:内部路径和公开路径可以不同 - Backstage
{kind}:{namespace}/{name} - Google AIP Resource Name 的层级路径
> 还有一个小问题,目前的rule,crate与archetype他们的UID都是在前端生成的,这个应该是后端去做的
UID 格式: {kind}:{namespace}/{path}[/{sub-path}...]
部件说明:
kind = [a-z][a-z0-9_-]* -- 结构单元种类
namespace = [a-z][a-z0-9_-]* -- 命名空间(通常=repository 名)
path = [a-z][a-z0-9_/.-]* -- 层级路径
示例:
repository:default/daedalus
crate:default/daedalus-app
crate:default/daedalus-app/src/components/Button
archetype:default/component-design-best-practice
page:default/daedalus-app/src/pages/CrateList
skill:default/react-component-creator ← 未来
item:default/typescript-sword ← 未来