[Architecture] 核心契约:.graphspec/ 里面的数据长什么样?(Schema V1 脑暴) #8
Replies: 4 comments
-
基于文件依赖树
filenode
有的文件可能只是 types,interfaces,或者 controller,handler,或者 pkg other ... 基于 domain(偏业务)(UML)展示数据流、函数依赖关系 modulenode
deps传什么数据 业务模型 |
Beta Was this translation helpful? Give feedback.
-
|
这份基础数据结构设计非常轻量,出发点很好,但如果要支撑未来的“渐进式披露”以及作为 AI Agent (MCP) 的标准契约,现有的 核心接口草案的 3 个致命缺陷
关于前后端交互方式的抉择为了实现架构目标,方案 B(CLI 启动本地服务器,增量拉取)是绝对的必选项。 方案 A(注入全量静态 JS)只适合轻量级的一次性分析报告。由于 GraphSpec 旨在接入 MCP 并支持渐进式披露,你需要一个可以随时响应局部查询(如: GraphSpec 核心模型详细文档 (Schema Definition)基于将物理视图(FileNode)与业务视图(ModuleNode)解耦的思路,以下是重构后具备高扩展性的 TypeScript Schema 定义: /**
* -----------------------------------------
* 1. 基础枚举与公共定义
* -----------------------------------------
*/
// 节点的基础物理分类
export enum FileNodeType {
FILE = 'file',
NPM_PACKAGE = 'npm_package', // 外部依赖
EXTERNAL_GLOBAL = 'external_global', // 如 window, document
}
// 节点的基础逻辑/业务分类
export enum LogicNodeType {
MODULE = 'module', // 业务领域/子图
COMPONENT = 'component', // UI 组件
SERVICE = 'service', // 业务服务
TYPES = 'types', // 纯类型定义
CONTROLLER = 'controller',
UNKNOWN = 'unknown',
}
// 边的类型:描述依赖的本质
export enum EdgeType {
IMPORT_DEFAULT = 'import_default',
IMPORT_NAMED = 'import_named',
IMPORT_TYPE = 'import_type', // 仅类型依赖,运行时无关联
DYNAMIC_IMPORT = 'dynamic_import', // 异步加载,利于按需分析
DATA_FLOW = 'data_flow', // UML 数据流向
COMPOSITION = 'composition', // 包含关系 (父子)
}
/**
* -----------------------------------------
* 2. 关系(Edge)定义:将连线实体化
* -----------------------------------------
*/
export interface GraphEdge {
id: string; // e.g., 'edge_src_to_dst'
sourceId: string; // 发起依赖的节点 ID
targetId: string; // 被依赖的节点 ID
type: EdgeType;
metadata?: {
isCyclic?: boolean; // 是否构成循环依赖
importedNames?: string[]; // 具体引入了哪些变量/函数
};
}
/**
* -----------------------------------------
* 3. 节点(Node)体系设计
* -----------------------------------------
*/
// 基础节点
interface BaseNode {
id: string; // 唯一标识符,基于 hash 或标准化后的路径
name: string; // 节点展示名
description?: string; // 留给 AI Agent 自动生成的摘要坑位
}
// 物理文件节点 (基于文件依赖树)
export interface FileNode extends BaseNode {
kind: 'file'; // 区分基类类型
fileType: FileNodeType;
path: string; // 相对路径或 npm 包名
extension: string; // .ts, .tsx, .js
exports: string[]; // 对外暴露的 API/变量名
metadata: {
linesOfCode: number;
lastModified?: number;
complexityScore?: number; // 预留给 AI 的圈复杂度评分
};
}
// 业务模块节点 (基于 Domain 视图,支持子图)
export interface ModuleNode extends BaseNode {
kind: 'module'; // 区分基类类型
logicType: LogicNodeType;
domain: string; // 归属的业务领域,如 'UserAuth'
childrenIds: string[]; // 包含的子节点 ID(可以是 FileNode 或下级 ModuleNode,实现渐进式披露)
entryPoint?: string; // 该模块的主入口节点 ID (如 index.ts 的 FileNode ID)
metadata: {
businessRule?: string; // AI 理解业务逻辑的切入点
isPublicApi: boolean; // 是否对外暴露为公共服务
};
}
export type GraphNode = FileNode | ModuleNode;
/**
* -----------------------------------------
* 4. 根结构(Manifest):输出的最终数据契约
* -----------------------------------------
*/
export interface GraphManifest {
version: string; // Schema 版本号,保证向前兼容
project: {
name: string;
rootPath: string;
analyzedAt: string; // ISO 8601 时间戳
};
nodes: Record<string, GraphNode>; // 拍平的节点字典,O(1) 查找,按需拉取
edges: Record<string, GraphEdge>; // 拍平的边字典
}改进优势解析
|
Beta Was this translation helpful? Give feedback.
-
|
点一个节点通过节点找到所有相关内容 |
Beta Was this translation helpful? Give feedback.
-
|
相当于 uml 图的结构化版本,定结构化的数据结构 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
背景
前两个 Discussion 明确了我们要“按需加载”且“只读展示 JS/TS 项目”。
现在进入技术硬骨头:当我们在 macOS 终端运行
graphspec init后,.graphspec/目录下生成的数据格式,就是连接 CLI 引擎、本地前端页面、以及未来 AI Agent (MCP) 的唯一契约。讨论点:如何设计这个 JSON/YAML?
1. 数据的颗粒度问题
我们是存完整的 AST(抽象语法树),还是只存高维度的 Node(节点)和 Edge(边)?
考虑到要让未来的 AI 能够轻松读懂(Token 不能爆炸),我倾向于只存轻量级的元数据。
2. 核心 Interface 草案(请大家 Review 找茬):
3. 前后端交互方式 本地的 React 页面怎么拿到这份数据?
data.js注入到前端页面里,前端纯静态。请回复:
技术同学请重点 review 上面的 Interface 草案,指出它的缺陷(比如:怎么表达循环依赖?怎么表达外部 npm 包依赖?)。
🤖 给 AI 的 Prompt(用于生成结构建议):
Beta Was this translation helpful? Give feedback.
All reactions