== LeafSpec command framework (internal/helpers/leaf.go) ==
Declarative command construction: LeafSpec/LeafFlag/NewLeafCommand with
Call (pluggable dispatch), LeafInt, PostMount, Trim, Validate. Collapses
per-command hand-written required validation, alias/env fallback, value
transform, and toolArgs assembly into one declarative path.
== devapp migration (28/31 commands) ==
All MCP-direct devapp leaf commands migrated to LeafSpec. Factories
(devAppCall/devAppCallCursor/devAppMeta) fold 33 repeated closures.
fakeDevAppRunner asserts toolArgs for every migrated command. 4 complex
commands (delete/robot submit/result/config) kept hand-written.
== Schema generation/consumption separation ==
- gen.go: isolated //go:generate pragmas from business code.
- command_meta.go: ResolveMeta(cliPath) -> CommandMeta{Identity,Safety,Selection}.
- command_safety.go: SafetyForCLIPath + RenderSafetyAnnotation; safety metadata
flows from embedded catalog into --help output.
- calendar.go HelpFunc fix: delegates to root HelpFunc at help-time.
- schema_catalog_structure.go: closed catalog structure validation gate.
== Registry + catalog per-product sharding ==
schema_command_registry and schema_catalog split into per-product shards,
eliminating concurrent-PR merge conflicts on these files.
== MCP metadata refresh tool ==
cmd/fetch_mcp_metadata: iterates 26 MCP server endpoints, merges with previous
data for cross-server interface_ref. make fetch-mcp-metadata target.
== AGENTS.md ==
Documents the generation/consumption split.
Verified: make policy exit 0, drift zero, all tests pass.
20 KiB
DWS Agent Schema 统一方案
1. 核心定义
DWS Schema 是当前二进制公开 CLI 的版本化 Agent 执行契约。它描述真实 Cobra 命令,并补充 Agent 选择、参数映射、组合约束、安全确认和接口事实。
设计遵循三条硬规则:
- Schema 描述 CLI,不制造 CLI。
CommandRegistry、manual hint、metadata 和 Catalog 都不能凭空创建 Cobra 命令或 flag;registry 中的每个路径都必须精确绑定真实 runnable Cobra leaf。 - 所有来源只解析一次。 来源经过统一 resolver 进入 typed
SchemaRegistry,所有查询、导出和门禁都消费同一个SchemaRegistry/SchemaIndex。 - Registry-first,Catalog 只出不进。 reviewed
CommandRegistry是稳定 command identity/navigation 的唯一事实源;schema_catalog/(catalog.json+ 每产品tools/<product>.json)和其他生成 JSON 只是下游发布物,不能成为命令、metadata 或下一轮 Catalog 的来源。运行时 production loader 解码 embedded snapshot 只是交付边界,不是 source resolution。
Schema 不调用 MCP tools/list,不访问网络,也不读取用户本地 discovery cache。
2. 单向数据流
schema_command_registry.json (reviewed CommandRegistry source)
+ reviewed manual command additions
|
v
EffectiveCommandRegistry
|
v
exact binder to live Cobra tree
+ native identity consistency assertions
|
v
BoundCommandRegistry
|
+----------------------+
|
skills/mono Markdown + internal/cli/schema_hints/*.json |
+ schema_mcp_metadata.json |
| |
v |
Agent-metadata normalization |
| |
v |
schema_agent_metadata/*.json |
(generated normalized input) |
| |
+-----------------------+
|
live Cobra flag facts / typed parameter metadata
+ schema_hints/metadata/*.json (reviewed parameter overlay + safety)
+ schema_hints/selection/*.json (reviewed Agent selection prose)
+ schema_parameter_bindings.json (reviewed flag -> RPC property)
+ schema_mcp_metadata.json (pinned, sanitized interface facts)
+ normalized Agent metadata
|
v
source adapters + resolvers
|
v
one typed SchemaRegistry
(one ToolSpec per command)
+
typed SchemaIndex
+-----------+-----------+
| |
v v
build-time typed gates snapshot serializer
|
v
schema_catalog/
(catalog.json + tools/<product>.json,
release output only)
|
v
go:embed -> typed loader
|
v
SchemaRegistry + SchemaIndex
|
+---------------------+------------------+
| | |
overview/product/group leaf --all
projections projection full projection
| | |
+---------------------+------------------+
|
v
runtime query + delivery gates
--help 是 Cobra 自身的人类可读投影,不从 Catalog 生成。Schema projections 和 --help 共享同一真实 Cobra 命令面,但承担不同职责。Binder 之后不得再从 annotation、manual hint 或生成 JSON 重新解析 command identity。
3. 与 Lark 的关系
DWS 与 Lark 保持架构同构,而不是强行复制字段:
| Lark 分层 | DWS 对应层 |
|---|---|
| typed command/metadata registry | EffectiveCommandRegistry、BoundCommandRegistry 与最终 SchemaRegistry |
| navigation catalog/index | 从同一 ToolSpec 派生的 SchemaIndex |
| schema renderer/envelope | overview、product/group、leaf、--all projections |
共同点是:强类型 registry 持有已审核、已绑定、已解析的事实,index 只负责确定性导航,renderer 只投影,不重新读取来源或做 precedence。DWS 的 base Registry 与 reviewed manual command additions 在绑定前合并为唯一的 EffectiveCommandRegistry,因此不存在 “native-first”、“legacy registry fallback” 或 Catalog fallback。
DWS 内部 resolved model 为:
SchemaRegistry
-> []ProductSpec
-> []ToolSpec
-> ToolIdentitySpec
-> []ParameterSpec
-> RuntimeSchemaConstraints + []RuntimeSchemaPositional
-> SafetySpec
-> InterfaceSpec
-> SelectionSpec
-> map[field]FieldProvenance
字段合并和 precedence 在进入该模型前完成。map[string]any/flat JSON 只允许存在于 renderer 和 snapshot/wire boundary,不能作为内部 resolver、navigation 或 gate 的第二套数据模型。
DWS 当前对外仍保留兼容 wire:leaf 使用 flat parameters,安全和选择字段也保持现有键名。架构对齐不等于未版本化地切换到 Lark inputSchema/outputSchema/_meta envelope;若未来提供该格式,应作为明确版本的新投影,并保留现有兼容输出。
4. 来源职责
| 来源 | 负责内容 | 明确不负责 |
|---|---|---|
schema_command_registry.json |
reviewed CommandRegistry:稳定 canonical identity、primary CLI path、alias、exposure 和导航 |
创建 Cobra 命令/flag、参数、安全、endpoint/token |
| reviewed manual command additions | 将一个精确存在的 runnable Cobra leaf 合并进 EffectiveCommandRegistry;必须 reviewed 且带 reason |
运行时 fallback、覆盖冲突 identity、创建命令 |
| Go/Cobra | 路径是否真实可执行、Cobra 接受的 flag、CLI 类型/默认值、执行校验、help 文本 | 稳定 canonical identity、Agent 场景选择、虚构 RPC |
| native Schema identity annotations | implementation-side consistency evidence;存在时必须与 EffectiveCommandRegistry 精确一致 |
提供、补全、推断或覆盖 identity |
schema_hints/metadata/*.json parameter overlays |
精确覆盖现有 flag 的描述、映射、类型和 required 语义;并承载 safety / runtime_gate / interface |
创建命令/flag、绕过 completeness、虚构 RPC |
| typed parameter metadata / constraints | required_when、one-of、互斥、联动、格式、枚举、位置参数 |
命令 identity |
schema_parameter_bindings.json |
稳定 CLI flag 到 RPC property 的映射 | 命令发现、risk 推断 |
schema_mcp_metadata.json |
pinned RPC identity、接口描述和脱敏参数事实 | CLI identity、运行时路由、risk 推断 |
schema_hints/selection/*.json |
reviewed selection prose(summary / use_when / avoid_when / examples) | 创建 Cobra 命令或参数、改写 safety |
| Skills/Markdown | 产品路由、工作流和使用建议 | 命令存在性和 flag 事实 |
schema_catalog/(catalog.json + tools/.json)及其他 generated JSON |
resolved registry 的兼容发布序列化;运行时由 production loader 解回 typed registry/index | generation/source resolution 输入、identity fallback、手工修复源 |
schema_command_registry.json 承载 reviewed CommandRegistry。Manual command addition 先以确定性规则合并进 effective registry;从 binder 开始,下游只看到一个稳定 identity/navigation 模型。旧 wire 中的 surface_hash / surface_tools 字段仅为兼容名称,语义已经是 effective Registry hash/coverage,不构成第二事实源。
5. 统一解析与 precedence
5.1 Identity
- Reviewed base
CommandRegistry是 stable canonical identity、primary path、alias 和 navigation 的唯一基础事实源。 - Reviewed manual command addition 只能引用精确存在的 runnable Cobra leaf;它在绑定前合并进
EffectiveCommandRegistry。若与 base Registry 的 identity/path/alias 冲突,生成失败,不能按 precedence 静默覆盖。 - Binder 必须把 effective entry 的 primary path 和每个 alias 精确解析到同一个真实 executable leaf;stale path、phantom path、重复 identity 或 alias collision 全部失败。
- Native identity annotation 是可选的一致性证据:存在时必须与 effective entry 精确一致;缺失不触发补写、推断或 fallback。
- Public runnable Cobra leaf 未进入 effective registry 时,必须存在 exact、reviewed、带 reason 的 exclusion;不得用 prefix/wildcard 排除。
- Identity 不做名称推断,不从 Catalog/generated metadata fallback,也没有多来源 winner。
删除 native materialization 前已做写入审计:旧
ApplyNativeRuntimeSchemaContracts 的唯一写操作是对已存在命令调用
AttachRuntimeSchema,只写 command identity 的 product/tool/source annotation;
它不写 flag property/type/required、constraints、positionals、title/description
或 interface mapping。这些字段原本已分别由 parameter binding/metadata、
constraint、Cobra help 和 interface resolver 提供,因此删除该过渡层没有数据迁移缺口。
CI 同时禁止重新加入 generated native contracts 或 materialization 入口。
CommandRegistry 输入审计
schema_command_registry.json 是 reviewed source,不是生成快照。它必须保留
$schema: ./schema_command_registry.schema.json。该 JSON Schema 对 root、product
和 CommandSpec 全部使用 additionalProperties: false,并约束:
- canonical identity、
source_product_id和精确 CLI path 的格式; aliases唯一且不能复用 primary path;visibility只允许public | compat | internal,省略时明确归一化为public;- primary path、alias、canonical 和 product 之间无法由 JSON Schema 表达的 交叉约束,继续由 Go strict loader 和 Cobra binder fail-closed 校验。
Registry semantic hash 覆盖 canonical、primary CLI path、alias 集合、
source_product_id 和 normalized visibility。格式、顺序以及省略的等价默认值
不改变 hash;上述任一稳定契约字段变化都必须改变 hash。测试逐字段验证这一点,
不使用当前命令数量作为常量。
普通 go generate ./internal/cli 只把 Registry 作为 validation-only 输入并生成
Agent metadata/Catalog 等单向下游资产,不生成或覆盖 Registry。drift policy 在生成
前后对 reviewed Registry 做 byte-for-byte guard;独立的
check-schema-command-registry.sh 在 interface/provenance/Catalog policy 之前检查
JSON 输入契约、禁用旧 native materialization 符号,并从 Registry 动态计算审计
数量,不能硬编码某次快照的 tool count。
5.2 Parameter
每个字段按明确的来源 precedence 选择一次,并把 winner、候选值和来源写入 provenance。precedence 与值无关:不能因为 required=true 看起来更严格就让它越级获胜。更高优先级的 reviewed manual override 可以把 required、映射、interface type 或描述调高,也可以调低。
实现中的参数字段顺序固定为:
reviewed manual > versioned binding > command constraint > typed metadata
> native/Cobra contract > ToolSchemaHint > MCP metadata
> inference/default
命令 title / description 使用独立但同样确定的文本顺序:
reviewed ToolSchemaHint > command-specific Cobra Help > MCP metadata > inference
因此多个 CLI leaf 复用同一个 RPC 时,通用 RPC 文案只能作为未选中的
provenance candidate 保留;参数级 RPC 文案可进入 interface_description,
但不得覆盖 leaf 自己的标题和执行语义。
Cobra hard-required 是独立的 executable fact,并通过 cli_required/provenance 保留;它不应在 renderer 中再次静默改写已经解析的 Agent projection。
5.3 Safety、selection 与 interface
effect、risk、confirmation、idempotency、selection 和 interface disposition 同样按 source precedence 解析,而不是按值的“严格程度”合并。更高优先级的 reviewed explicit/manual source 可以升高或降低最终值;同 precedence 的不同值必须报冲突。
最终 interface disposition 还必须满足 conflict matrix:
mode与availability正交:mode只允许mcp | local | composite,availability只允许available | unavailable;unavailable不是第四种 mode。mcp + available:只表示命令可由一个 pinned、参数可映射且语义等价的interface_ref完整表达;本地 wrapper 只是固定默认值或投影返回值时,也必须先证明参数和执行语义没有漂移。local + available:仅用于纯本地进程、静态数据或策略操作,不得携带 directinterface_ref;“远端 RPC 尚未进入 pinned metadata”不能归类为 local。composite + available:用于多 RPC、条件路由、本地投影,或 reviewed unpinned remote adapter;不得用单个interface_ref冒充完整实现,且必须提供 reviewed reason。未来需要表达多个 RPC 时使用单独的复合接口模型。- 任意合法 mode +
unavailable:不得携带interface_ref,必须提供明确 reason,并且 Agent 不得把它当作可用接口。
6. Schema、Help 与业务数据边界
| 问题 | 事实源 |
|---|---|
| 当前二进制是否暴露命令、Cobra 接受哪些 flags | dws <path> --help |
| Agent 选哪个命令、参数映射/required/约束、risk/confirmation | 对应 leaf dws schema "<path>" |
| 钉钉中的文档、文件、日程、消息等实际数据 | 真正执行 dws doc read、dws drive search 等 read/search/list 命令 |
Schema 和 Help 冲突是契约漂移,不能静默猜测:
- 执行参数以 Cobra 实际接受的 flags 为准;不要发送 Help 中不存在的 flag。
- 安全语义冲突时不要采用更宽松值。先按更保守的解释确认;如果无法确定安全执行方式,停止并报告漂移。
- Schema/Help 只完成命令发现和契约读取。需要业务结果时,必须继续执行真实 read/search/list 命令。
上述运行时漂移策略不改变构建期的 value-neutral precedence;前者是在契约已经互相矛盾时保护用户,后者是在确定性生成同一契约。
7. 查询投影
dws schema # 产品紧凑概览
dws schema calendar # 产品摘要
dws schema "calendar event" # 分组摘要
dws schema "calendar event create" # 完整 leaf
dws schema "calendar event create" --compact # 支持:裁掉 provenance/debug 字段
dws schema --all # 所有工具的完整 leaf 导出
schema list 是根概览的兼容入口。
schema --all 必须包含最终 SchemaIndex 中每个 tool 的完整 leaf 参数、约束和安全语义;无业务参数的命令也要包含空 parameters 对象。它用于审计、CI 和参数防丢 baseline,但输出很大,普通 Agent 命令发现不得使用,应按 overview -> product/group -> leaf 渐进查询。
--compact 当前受支持,适合减少常规 leaf 查询上下文。schema --all --compact 也可执行,但会移除 provenance/debug 和接口映射字段,不能作为完整兼容性 baseline。
兼容旧二进制时,如果 Schema 查询返回 unknown_flag: --compact,只去掉 --compact 重试同一个查询。这是展示能力降级,不代表 leaf 缺失,也不能改用 Schema 查询业务数据。
8. 生成与发布
当 Cobra、flag、identity、binding、manual hint、Agent hint 或 Skill 发生变化时:
-
审核真实 Cobra 变化,确认命令和 flag 已实际存在。新增或修改稳定 command identity、primary CLI path 或 alias 时,精确编辑 reviewed
CommandRegistry(当前持久化文件为schema_command_registry.json)。参数、Skill 或 metadata 单独变化时不要机械改写 Registry,也不要从旧 Catalog 反向生成它。 -
仅对明确例外使用 reviewed manual command addition;它必须精确引用现有 runnable leaf、带 reason,并在生成时归一化进
EffectiveCommandRegistry。Native identity annotation 若存在,应作为与 Registry 一致的实现断言维护,而不是用来 materialize identity。 -
生成 Agent metadata:
make generate-schema-agent-metadata -
从统一 typed registry 生成最终 Catalog:
make generate-schema-catalog
也可以运行 go generate ./internal/cli 生成正常发布资产。生成文件包括:
internal/cli/schema_agent_metadata/index.jsoninternal/cli/schema_agent_metadata/<product>.jsoninternal/cli/schema_agent_metadata_audit.jsoninternal/cli/schema_catalog/catalog.json(全局信封 + Catalog)internal/cli/schema_catalog/tools/<product>.json(每产品 leaf ToolSpecs,按产品分片以免并发 PR 冲突)
只编辑来源;不要手工编辑 Agent metadata 或 Catalog 输出。
9. Completeness 与 final-delivery invariant
门禁必须验证最终交付对象,而不是某个中间层或数量:
- 每个 public runnable Cobra leaf 要么能通过最终 embedded
SchemaIndex查询,要么有 exact、reviewed、带 reason 的 exclusion。 - 每个最终 canonical path、primary CLI path 和 alias 都必须解析到同一个可执行 leaf;不得有 phantom path 或 collision。
EffectiveCommandRegistry、SchemaRegistry/SchemaIndex、Agent metadata 和 Catalog canonical sets 必须精确一致,不能只比较 count。- Leaf payload、
--all中对应 tool 和 Catalog full tool 必须是同一个 resolvedToolSpec的内容级等价投影,并通过 production loader round-trip。 - overview/product/group summary 与 Catalog summary 必须等于同一个
ToolSpec.ToSummaryPayload();alias 查询只允许cli_path和is_alias这两个视图字段变化。 - 每个最终字段及 parameter field 的 provenance winner value 必须与 delivered value 精确一致;不能只验证 provenance source、count 或字段是否存在。
- 每个 MCP
interface_ref必须在 pinned interface registry 精确存在;local/composite/unavailable 必须满足同一 conflict matrix。 --all的 tool set 必须与最终 index 一对一,且每个工具包含完整参数契约。- 连续两次生成必须字节稳定,提交的生成物不得漂移。
推荐本地验证:
make generate-schema-agent-metadata
make generate-schema-catalog
./scripts/policy/check-generated-drift.sh
./scripts/policy/check-schema-catalog.sh
go test ./internal/cli ./internal/app ./internal/generator/... -count=1
10. 明确禁止
- 运行时调用 MCP
tools/list或访问网络生成 Schema。 - 从
schema_catalog/等生成 JSON 反向创建/补齐 Cobra leaf、flag、CommandRegistry 或下一轮 Catalog。 - 把 native annotation、legacy registry 或 Catalog 当作 identity fallback;或在
EffectiveCommandRegistry之后再次选择 identity winner。 - renderer、query 或 gate 在
SchemaRegistry之后重新读取 source 并做第二次 merge。 - 用 prefix/wildcard exclusion 隐藏未来命令。
- 让 manual hint、CommandRegistry 或 interface metadata 宣称一个不存在的命令、flag 或 RPC 可用。
- 把
schema --all当作普通业务数据查询,或把其完整结果无条件注入 Agent 上下文。