Restore calendar helper behavior to main, finalize reviewed alias/guard decisions, cover payload and dry-run paths, and record the local migration freeze checkpoint.
11 KiB
Spec:参数幻觉治理 —— 受审命令范围内的概念归一化
- 状态:Frozen,最终回归通过
- 分支:
fix/param-hallucination - 评测来源:
param_alias_map_merged_20260720(440 条 badcase)及参数幻觉分析报告
1. 目标与边界
本次工作的目标是提高已知参数幻觉的执行成功率,并重点避免“参数被错误归一后成功执行”。主要方案是:
- 以
internal/cli/param_concepts.json作为 reviewed 参数概念与逐命令决策源。 - 只在概念明确列出的真实 Cobra 命令上做 build-time 归约,生成逐命令别名/保护表。
- 在现有 PreParse 流水线中把安全别名改写为 canonical flag。
- 对语义不完整、存在歧义或仍待确认的名字 fail closed,不进入自动执行。
本次不以“内部路径与历史实现完全一致”为目标。有明确收益且通过语义审查、最终 payload 验证的行为变化可以接受;但必须满足本文的安全边界。
本次不做:
- 不解决命令或接口本身缺少能力的红类问题。
- 不改 Schema/Catalog wire contract。
- 不把所有产品的 hidden flag、fallback、helper Go 文件清理作为交付范围。
- 不将 Calendar 试点扩展为全 Calendar 或全产品治理。
- 不做值转换、单位换算或需要补充第二个参数的复杂推理。
2. 最终链路
用户/Agent argv
│
├─ Cobra Traverse:定位真实叶子命令并读取真实 flags
│
└─ PreParse(同一个 Context)
1. AliasHandler
处理 camelCase/snake_case/kebab-case 等形态差异
2. SemanticAliasHandler
按“精确命令路径”读取 generatedParamAliases
├─ alias → 改写为 canonical flag
├─ blocked → 保持原样并写入 ProtectedFlags
└─ ambiguous → 保持原样并写入 ProtectedFlags
3. StickyHandler
拆分安全的粘连参数;不得处理 ProtectedFlags
4. ParamNameHandler
处理普通近似拼写;不得处理 ProtectedFlags
5. 检测 alias/canonical 冲突
同一 canonical 出现两个不同拼写时直接报错
│
├─ Cobra ParseFlags:只解析归一化后的 canonical/native flags
├─ RunE:现有 helper 读取 canonical/native 值并校验
└─ MCP/HTTP payload:只包含命令原本定义的最终接口字段
归一化参数名只影响 Cobra 解析前的 argv。它不会向 RunE 或 MCP payload 注入新的业务字段;RunE 仍按原有 canonical flag 构造请求。对已保留的真实 hidden/native flag,归一化体系不抢占其原生路径。
3. Reviewed 源与生成物
3.1 概念
每个概念包含:
type Concept struct {
ID string
Denotes string
CanonicalHint string
Members []string
Excludes []string
Commands []string // 精确、受审、可运行的 Cobra 叶子路径
Risk string
}
commands 是强制字段。概念只允许在这些精确路径上参与归约;新命令不会因为碰巧出现同名 flag 就自动获得所有概念别名。这一约束用于阻断全局词汇碰撞,例如:
from在时间查询中可能表示开始时间,在邮件中可能表示发件人。name可能是名称,也可能被某些接口错误地当作 ID。time不足以说明 RFC3339、毫秒时间戳或日期边界。
概念成员仍需全局唯一;同一概念内 members 与 excludes 不得重叠。
3.2 逐命令覆盖
command_overrides 只表达当前命令的特殊决策:
bind:把真实 generic flag 绑定到一个概念。scoped_aliases:明确的命令局部 alias → real flag。block:语义不完整或错误映射,禁止自动处理。ambiguous:存在多个合理含义,禁止自动选择。confirm/investigate:待审状态;不得生成可执行 alias。
当前 reviewed 源不允许残留 confirm=true 或 investigate=true。未来若再次引入,归约器也必须将相关名字置为保护态而不是激活。
3.3 生成物
internal/generator/cmd_param_aliases 使用真实 app.NewRootCommand():
- 校验每个
commands路径存在且是可运行叶子。 - 校验概念在该命令上至少命中一个真实 member 或 reviewed bind。
- 用共享的
cmdutil.Morph归一名称。 - 一个概念只命中一个可见真实 flag 时,生成安全 alias。
- 命中多个可见真实 flag 时,必须有精确
ambiguous决策,否则生成失败。 scoped_aliases/bind目标必须是真实 flag。- alias、blocked、ambiguous 不得互相重叠,也不得覆盖真实 canonical/native flag。
输出 internal/cli/param_aliases_generated.go 是确定性生成物,不得手改。
4. 映射准入规则
名称相似不是准入依据。自动映射必须同时满足:
- 同一实体:源与目标表达同一个业务对象。
- 同一卡数:单值不能静默转成列表,列表不能静默缩成单值。
- 同一值域/格式:日期、RFC3339、Unix 毫秒等不能只换名字就互换。
- 同一单位:秒、毫秒、数量、页号等不能做 name-only 映射。
- 单参数可完成:若正确语义需要补充另一个参数,则必须 block。
- 目标是该命令真实 flag,且最终 payload 字段已核对。
- 写命令需要逐命令说明,并以 mock caller 断言最终 payload。
4.1 本次重点审计结论
| 风险 | 决策 | 例子 |
|---|---|---|
| 单数/复数 | 拆成不同概念或 block | user_id 与 user_ids、dept_id 与 dept_ids |
| ID/名称 | 只有源代码/接口证明同实体才开放 | contact +resolve-dept --query → --name 可开放;list-sub-depts --name → --dept 被 block |
| 时间格式 | 只保留值格式不变的命令局部映射 | Calendar --date → --start 由相同 ISO 解析与 payload 验证;list-by-sender --time 被 block |
| 分页基数 | 页号、页索引、条数、游标分开 | page-index 不再等同 page-number;count 不并入 limit 概念 |
| 值单位 | 不做隐式换算 | name-only 归一化不得改变秒/毫秒或日期/时间戳 |
| 多参数转换 | block | before-block-id 实际需要 --ref-block 和 --where before |
| 机器人身份 | 不把 code 与 ID 混用 | robot-id 不再归入 robot_code |
已存在的真实 hidden/native compatibility flag 不由本体系重新解释。它仍由现有 Cobra/RunE 路径负责,避免中央规则改变原命令已有语义。
5. 保护与冲突规则
5.1 blocked / ambiguous
SemanticAlias 命中保护项时:
- 不改写 argv。
- 把 morphed flag 写入
Context.ProtectedFlags。 - Sticky 与 ParamName 必须跳过该名字。
- Cobra 最终返回 unknown flag。
- 最终错误使用 generated table 给出结构化
blocked_flag/ambiguous_flag原因并引导该命令的--help;不得再给最近邻猜测。
裸 -- 是流水线终止符。它之后的内容视为 positional data,任何 handler 都不得继续当作 flag 处理。
5.2 alias 与 canonical 同时出现
若 argv 同时包含指向同一 canonical 的两个不同拼写,例如:
--date A --start B
--start B --date A
无论顺序、无论值是否相同,一律在 PreParse 返回 FlagConflictError,RunE 不执行。这样不会由“最后一个参数获胜”静默决定结果,也避免将来不同 pflag 类型产生不一致行为。
同一个拼写重复出现仍保持 Cobra 原有语义,本次不额外改变。
6. Calendar 边界结论
internal/helpers/calendar.go 保持 main 原有实现,不迁移或删除它手写的 hidden compatibility flags 与 flagOrFallback 链。现存真实 flag 继续由 Cobra/RunE 原生处理,中央体系不得覆盖或重新解释。
中央归一化只补充该命令没有注册的 reviewed spelling,例如:
date→startfrom/since→start
Calendar 原生兼容参数和中央 alias 的端到端测试都必须验证最终仍只形成正确的 startTime、endTime、calendarId、cursor、limit payload。本次不要求任何 skill/helper 迁移 hidden flag 与 fallback。
7. 测试与门禁
| 层级 | 验证 |
|---|---|
| reviewed 源 | closed schema、命令范围非空、成员/排除约束、无待审项 |
| 归约器 | 精确命令准入、单/多命中、真实目标、真实 flag 不被覆盖、分类互斥 |
| handler 链 | protected 状态贯穿 Semantic/Sticky/ParamName、裸 --、冲突双顺序 |
| fixture | 每条 badcase 走真实 RunPreParseArgs 与真实 Cobra ParseFlags |
| 最终执行 | 代表性读命令 Calendar 与写命令 chat send 走真实 RunE + mock caller,并断言最终 payload |
| 最终错误 | blocked/ambiguous 使用 reviewed 错误路由,不回落到 generic fuzzy suggestion |
| policy | dictionary contract、全量 Cobra co-occurrence、fixture、generated drift |
| 回归 | CLI 契约、Skill static、Skill --mock E2E |
fixture 只有“被测参数名”而没有每个业务命令的完整必填业务数据,因此全量 fixture 的执行边界是 Cobra 解析;真实 RunE/payload 由有完整 argv 的代表性读写测试承担。二者组合覆盖从输入到最终请求的完整链路,同时避免 fixture 触发真实外部写操作。
8. 对原有链路的可能影响
允许且有收益的影响:
- 受审命令开始接受明确安全的语义别名。
- Calendar 保留原生 hidden flag/fallback,同时接受不覆盖真实 flag 的 reviewed 中央 alias。
- alias/canonical 混传从顺序覆盖变为确定性报错。
- 某些曾被普通 fuzzy handler 猜中的危险名字现在明确失败。
需要持续约束的影响:
- 不能因为新增命令或真实 flag 而自动扩大概念覆盖;必须显式加入
commands。 - 不能让中央 alias 覆盖现存真实 flag。
- 不能降低 Cobra required 约束或绕过 RunE 校验/确认逻辑。
- 写命令的新映射必须审查最终接口字段,不能只断言 argv 被改写。
- 生成表、reviewed 源与运行时必须共用
cmdutil.Morph,避免 build/runtime 漂移。
9. 回退
最终冻结检查点只提交在本地 fix/param-hallucination 分支,不推送、不合并、不修改 main。此前已经存在的同名远端分支予以保留;GitHub PR #744 已关闭,最终冻结提交与标签均不发布到远端。
- 本地提交后发现问题:对本次 commit 执行
git revert <sha>,保留完整可审计历史。 - 如果日后已经合入 main:仍可在 main 上
git revert <merge-or-commit-sha>,再走正常审核与发布流程。 - reviewed 源与
param_aliases_generated.go必须一起回退,或回退源后重新生成并通过 drift gate。 calendar.go不属于本次最终交付改动;回退中央体系时无需再单独恢复 Calendar helper。
10. 验收标准
- 已知 fixture 全部通过。
- 未确认、语义不完整或需要值/多参数转换的映射不会自动执行。
- blocked/ambiguous 不会被后续 fuzzy handler 改写。
- alias/canonical 冲突确定性失败且不进入 RunE。
- 代表性读、写命令最终 payload 正确。
- 参数概念、co-occurrence、生成漂移、CLI 契约及 Skill 回归门禁通过。
- 改动集中在中央归一化体系,不开展全产品 helper 清理。