Documentation
¶
Overview ¶
本文件实现 diff 回灌基线(spec §7):分支合并回 main 后,把分支视图 机械併入 baseline,让基线保鲜成为流程副产物。
职责:Absorb(纯函数併入)、SaveGraph(原子写盘) 边界:不删 diff 文件、不取 git 信息——那是 cmd 层的编排;
不校验 diff 合法性——调用方先过 ValidateDiff
本文件实现目标图对实际图的契约对照(spec §5)。
职责:Check——归域、逐边判定、legacy 预算结算,产出 Report 边界:不做 I/O、不打日志——纯函数,可观测性由返回的 Report 承担;
加载与退出码语义在 cmd 层
domains.go —— 领域层的投影:把视图按领域聚合成带统计的领域树。
职责:领域树结构(parent/children)、每个领域的成员统计与对外接口清单 边界:只读视图,不改数据、不打日志、不做网络;领域一律读自数据的 domains 段, **不按包名或容器名推导**——推导出来的层级会被人和 agent 当成真实架构。 与前端 web/src/app/codegraph/domains.ts 的「跨领域边 / 对外接口」判定规则 必须一致,两侧分叉就是 bug。
本文件实现数据契约文件的加载:baseline、单个 diff、视图列表。
职责:读文件 + json.Unmarshal + 带路径上下文的错误 边界:不校验引用完整性(validate.go 的事)、不合并(merge.go 的事)
本文件实现「基准 + 差异 → 视图」的合并(spec §3.2 的渲染时合并)。
职责:Merge 产出带 Status 标记的 View;删除的对象保留并标 deleted,
供消费方画红虚线——直接剔除会让"删了什么"不可见
边界:不做查询(query.go);diff 的合法性由 ValidateDiff 把关,
Merge 对非法引用宽容跳过(渲染路径不因脏数据崩)
本文件实现视图上的邻域查询:多源 BFS,下游为正距离、上游为负距离。
职责:Resolve(id/名字 → 节点 id)、Neighborhood(chain/who-calls/并集共用核心) 边界:不做布局(消费方的事);deleted 节点/边不参与遍历(它们只是渲染残影)
本文件实现保鲜检测:节点声称的 file:line 与真实源码对不上即 stale。
为什么这么设计(spec §7):过期的图比没有图更糟——agent 信了它就省了验证。 节点刻意不存源码正文,file:line 是唯一锚点,所以校验它就是校验图的新鲜度。
职责:CheckStale——按廉价规则逐节点比对 边界:不重扫、不修复,只报告;unscanned 节点跳过(没人声称它是新鲜的)
本文件实现目标图 target.json 的模型、加载与校验(spec docs/superpowers/specs/2026-08-21-codegraph-target-check-design.md §4)。
职责:类型定义、LoadTarget、ValidateTarget、归域 DomainOf(Task 2) 边界:不做对照(check.go);不写文件——target 是人写的,程序只读
Package codegraph 实现代码图数据契约的模型与算法:加载、校验、合并、查询、保鲜。
职责:
- 解析目标仓库 codegraph/baseline.json 与 codegraph/diffs/<view>.json
- 基准 + 差异合并出视图;BFS 邻域查询(chain / who-calls / 并集 / 深度)
- file:line 签名保鲜检测
边界:
- 不依赖 handoff 任何内部包(agentd/store/client)——数据契约独立是 spec 2026-08-19-codegraph-design §2 的硬约束,本包必须能原样搬进任何工具
- 不产出数据:扫描由 AI executor 完成(见 docs/codegraph-scan-recipe.md)
- 不做网络:一切输入都是本地文件
本文件实现引用完整性校验:图与 diff 里的一切引用必须落在已定义的对象上。
职责:Validate(基线自查)、ValidateDiff(diff 相对基线自查) 边界:不查 file:line 真实性(stale.go 的事)、不修数据,只报告
Index ¶
- func ListViews(repoRoot string) ([]string, error)
- func Resolve(v *View, arg string) (string, error)
- func SaveGraph(repoRoot string, g *Graph) error
- func Validate(g *Graph) []string
- func ValidateDiff(g *Graph, d *Diff) []string
- func ValidateTarget(t *Target) []string
- type Assignment
- type Container
- type Contract
- type Diff
- type Domain
- type DomainStat
- type Edge
- type Finding
- type Graph
- type Meta
- type Node
- type Report
- type Result
- type ResultNode
- type StaleNode
- type Target
- type TargetDomain
- type TargetMeta
- type TestRef
- type View
- type ViewEdge
- type ViewNode
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Resolve ¶
Resolve 把命令行参数解析成节点 id:先按 id 精确匹配,再按 name 精确匹配。 name 多义或未命中时报错并列出近似候选(contains,最多 5 个),方便 agent 自纠。
func SaveGraph ¶ added in v0.3.9
SaveGraph 原子写 repoRoot/codegraph/baseline.json:同目录临时文件 + rename—— 写盘半途失败不得留下截断的基线(生命周期中断族)。缩进单空格与既有基线一致。
func ValidateDiff ¶
ValidateDiff 检查 diff 相对基线的引用完整性。 检查项:nodesModified/nodesDeleted 引用的节点必须在基线里; edgesAdded/edgesDeleted 两端必须在「基线 ∪ nodesAdded」里; nodesAdded 的 container 必须存在。
func ValidateTarget ¶ added in v0.3.9
ValidateTarget 校验目标图内部一致性,返回问题清单(空 = 合法)。
Types ¶
type Assignment ¶ added in v0.3.9
Assignment 例外文件的显式归域,优先级高于 paths 规则。
type Container ¶
type Container struct {
Label string `json:"label"`
Kind string `json:"kind"`
Entry bool `json:"entry,omitempty"`
// Domain 是所属领域 id,必须是**叶子**领域。空串只在整图没有 domains 段时
// 合法(旧扫描数据,消费方降级为单领域视图)。
Domain string `json:"domain,omitempty"`
}
Container 是分组盒子(struct 一级,见 spec §3.1)。
type Contract ¶ added in v0.3.9
type Contract struct {
From string `json:"from"`
To string `json:"to"`
Entries []string `json:"entries,omitempty"`
Interfaces []string `json:"interfaces,omitempty"`
LegacyBudget int `json:"legacyBudget,omitempty"`
}
Contract 一个允许的跨域依赖方向 from → to。 Entries:允许 call 边进入的 to 域容器 Label 清单(pkg.Receiver 规范形)。 Interfaces:允许 to 域跨域实现的 from 域接口节点 Name 清单(回调契约面)。 LegacyBudget:不走声明入口的存量直调边上限;缺省 0 = 硬拦(与缺失同义,spec §4)。
type Diff ¶
type Diff struct {
View string `json:"view"`
Base string `json:"base,omitempty"`
Summary string `json:"summary,omitempty"`
NodesAdded map[string]Node `json:"nodesAdded,omitempty"`
NodesModified map[string]Node `json:"nodesModified,omitempty"`
NodesDeleted []string `json:"nodesDeleted,omitempty"`
EdgesAdded []Edge `json:"edgesAdded,omitempty"`
EdgesDeleted []Edge `json:"edgesDeleted,omitempty"`
ImplementsAdded []Edge `json:"implementsAdded,omitempty"`
ImplementsDeleted []Edge `json:"implementsDeleted,omitempty"`
}
Diff 是 codegraph/diffs/<view>.json:某分支/plan 相对基准的差异声明。
type Domain ¶
type Domain struct {
Label string `json:"label"`
Kind string `json:"kind"`
Summary string `json:"summary,omitempty"`
Desc string `json:"desc,omitempty"`
Parent string `json:"parent,omitempty"`
}
Domain 是一个领域:领域图的一级组织单位,可嵌套。
领域由扫描产出、人可在入库后修改(spec §3.1)。Parent 串成树,为空即顶层。 容器只能挂叶子领域——挂在中间层的容器既不属于本级全景、也进不了任何子领域, 会静默从图里消失,所以 Validate 把它当错误报出来而不是默默丢掉。
type DomainStat ¶
type DomainStat struct {
ID string `json:"id"`
Label string `json:"label"`
Kind string `json:"kind"`
Summary string `json:"summary,omitempty"`
Desc string `json:"desc,omitempty"`
Parent string `json:"parent,omitempty"`
Children []string `json:"children"`
Containers []string `json:"containers"`
Funcs int `json:"funcs"`
Models int `json:"models"`
Entries int `json:"entries"`
Unscanned int `json:"unscannedEntries"`
Interfaces []string `json:"interfaces"`
}
DomainStat 是一个领域的展示投影:元信息 + 结构位置 + 成员统计。
统计只算**直属容器**里的节点:父领域的数字不含子领域,读数不会重复计入。 Interfaces 是本领域中被其他领域调用到的节点 id(即「对外开放接口」)。
func DomainTree ¶
func DomainTree(v *View) []DomainStat
DomainTree 把视图投影成领域列表,按 id 升序;列表内各切片字段也按字典序排序, 保证同一份数据每次输出一致(CLI 输出要能直接 diff)。
视图没有领域段时返回 nil——调用方据此降级为单领域视图,不要自行编造领域。
type Finding ¶ added in v0.3.9
type Finding struct {
Kind string `json:"kind"`
From string `json:"from,omitempty"`
To string `json:"to,omitempty"`
Edge *Edge `json:"edge,omitempty"`
Detail string `json:"detail"`
}
Finding 一条对照发现。Kind 取值: fail 侧:new-direction(无契约方向)/ off-entry 归并进 legacy 或 over-budget / off-interface(未声明的跨域实现)/ over-budget(legacy 超预算) warn 侧:legacy(预算内直调计数)/ outside-file(图外文件)/ dead-rule(规则未命中任何节点)/ dead-assembly(组装点条目未命中任何节点文件)
type Graph ¶
type Graph struct {
Meta Meta `json:"meta"`
// Domains 是领域段,可为空——空即「该图未划分领域」,消费方降级为单领域视图。
// **不得按包名伪造领域**:伪造出来的层级会被人和 agent 当成真实架构读。
Domains map[string]Domain `json:"domains,omitempty"`
Containers map[string]Container `json:"containers"`
Nodes map[string]Node `json:"nodes"`
Edges []Edge `json:"edges"`
// Implements 是接口满足边 [实现, 接口]。与 Edges 分列是 wire 兼容决策
//(Edge 是二元组塞不进 kind 字段,spec §3);语义上它们是 kind=implements 的边。
Implements []Edge `json:"implements,omitempty"`
}
Graph 是 codegraph/baseline.json 的顶层结构。 顶层 "diffs" 字段是早期原型的兼容残留,一期忽略:视图一律来自 diffs/目录。
type Meta ¶
type Meta struct {
Project string `json:"project"`
Branch string `json:"branch"`
Commit string `json:"commit"`
ScannedAt string `json:"scannedAt"`
Generator string `json:"generator"`
}
Meta 是图的来源信息。
type Node ¶
type Node struct {
Kind string `json:"kind"`
Container string `json:"container"`
Order int `json:"order,omitempty"`
Name string `json:"name"`
File string `json:"file"`
Line int `json:"line"`
Signature string `json:"signature,omitempty"`
SignatureOld string `json:"signatureOld,omitempty"` // 仅出现在 diff 的 nodesModified 里
Params [][]string `json:"params,omitempty"` // [名, 类型, 说明]
Returns string `json:"returns,omitempty"`
Summary string `json:"summary,omitempty"`
Tests []TestRef `json:"tests,omitempty"`
Fields [][]string `json:"fields,omitempty"` // model 专用: [名, 类型, 说明]
Unscanned bool `json:"unscanned,omitempty"`
}
Node 是图节点,Kind 三选一:entry / func / model。 不存源码——消费方按 File:Line 实时读取,这同时是保鲜检测的抓手。
type Report ¶ added in v0.3.9
type Report struct {
Fails []Finding `json:"fails"`
Warns []Finding `json:"warns"`
LegacyHits map[string]int `json:"legacyHits,omitempty"` // "from->to" → 命中数
}
Report 是 Check 的产出。Fails 非空即闸门不过(cmd 层译成非零退出码)。
type Result ¶
type Result struct {
View string `json:"view"`
Foci []string `json:"foci"`
Nodes []ResultNode `json:"nodes"`
Edges []ViewEdge `json:"edges"`
UnscannedEntries int `json:"unscannedEntries"`
Warning string `json:"warning,omitempty"`
}
Result 是一次邻域查询的完整结果。 UnscannedEntries/Warning 让消费方能区分「查询无结果」与「根本没扫」—— 这是 spec §6 的硬要求,agent 拿掉这个信息会写出漏影响面的 plan。
type ResultNode ¶
ResultNode 是查询结果里的节点:id + 与焦点的 BFS 距离(下游正、上游负)。
type StaleNode ¶
type StaleNode struct {
ID string `json:"id"`
File string `json:"file"`
Line int `json:"line"`
Reason string `json:"reason"`
}
StaleNode 描述一个失鲜节点及原因。
func CheckStale ¶
CheckStale 逐节点做三级廉价校验:文件存在 → 行号在界内 → 行窗口(line-1..line+1)里能找到名字 token。entry 只做前两级 (注册行长相多样,token 检查会假红);func/model 检查 token: func 取 Name 最后一个 '.' 之后的段("Client.Dispatch" → "Dispatch"), model 取整名。文件按缓存读,同文件多节点只读一次。
type Target ¶ added in v0.3.9
type Target struct {
Meta TargetMeta `json:"meta"`
Domains []TargetDomain `json:"domains"`
Assignments []Assignment `json:"assignments,omitempty"`
Assembly []string `json:"assembly,omitempty"`
Contracts []Contract `json:"contracts,omitempty"`
}
Target 是 codegraph/target.json 的顶层结构:事前基准。
func LoadTarget ¶ added in v0.3.9
LoadTarget 读取 repoRoot/codegraph/target.json。 文件缺失或解析失败都是显式错误——check 的调用方绝不允许把「无基准」 当「通过」(spec §5 反静默约定)。
type TargetDomain ¶ added in v0.3.9
type TargetDomain struct {
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Paths []string `json:"paths"`
Note string `json:"note,omitempty"`
}
TargetDomain 一个声明的域。Type 二选一:logic / boundary(分域协议的域类型标注)。
type TargetMeta ¶ added in v0.3.9
TargetMeta 目标图来源信息。
type TestRef ¶
type TestRef struct {
Name string `json:"name"`
File string `json:"file"`
Snippet string `json:"snippet,omitempty"`
}
TestRef 关联一个测试函数。File 形如 "pkg/x_test.go:41"。
type View ¶
type View struct {
Name string `json:"view"`
// Domains 原样来自基线:diff 只改节点与边,不改领域划分。
Domains map[string]Domain `json:"domains,omitempty"`
Containers map[string]Container `json:"containers"`
Nodes map[string]ViewNode `json:"nodes"`
Edges []ViewEdge `json:"edges"`
Implements []ViewEdge `json:"implements"`
}
View 是合并后的图视图。