feat(skills): 扩展编排器综合评估维度
This commit is contained in:
parent
017e18f3d1
commit
808aa8438e
|
|
@ -5,7 +5,7 @@ description: "五个 GitLink 维护 Skill 的只读编排器:用户只需点
|
|||
|
||||
# GitLink 维护审查编排器
|
||||
|
||||
这个 Skill 只负责编排和校验,不替代五个专项 Skill 的判断。它把“证据采集、三路并行专项检查、集成门禁、维护者排序、首屏报告”组织成一次可复现的只读运行,并保留每个专项的独立结果,便于维护者快速处理而不是阅读五份重复长报告。
|
||||
这个 Skill 负责编排、交叉校验和综合决策,不替代五个专项 Skill 的原始判断。它把“证据采集、三路并行专项检查、集成门禁、维护者排序、跨专项一致性判断、综合报告”组织成一次可复现的只读运行,并保留每个专项的大部分评估维度。执行前必须读取 [`references/comprehensive-dimensions.md`](references/comprehensive-dimensions.md)。
|
||||
|
||||
## 五个 Skill 的职责
|
||||
|
||||
|
|
@ -28,41 +28,54 @@ description: "五个 GitLink 维护 Skill 的只读编排器:用户只需点
|
|||
- 共享一次队列快照和每个目标 PR 的固定 head 上下文,编排五个专项 Skill;不要求用户逐条重复五个 Skill 的提示词。
|
||||
- 全流程只读,不评论、不 approve、不合并、不关闭、不分配、不修改标签或权限。
|
||||
- 单 PR 和多 PR 都支持;多 PR 先做队列级拓扑/维护排序,再对重点 PR 逐条做代码、契约和集成检查,不能混合 Diff。
|
||||
- 报告首屏先按 PR 分节;每条 PR 分别显示代码审查、CLI 契约、仓库关系、集成门禁、维护状态和最终结论六张判断卡。聊天结论也按 PR 和这六个方面组织,但必须重新提炼成更短的维护者语言。
|
||||
- 报告按 PR 分节,完整展示代码与贡献、CLI 契约、仓库关系、集成门禁、维护治理五组专项维度,再展示证据一致性、风险传播、动作责任和置信度等编排器独有判断。不得用五张阶段总评代替完整维度。
|
||||
- 每张卡先显示醒目加粗结论,再写简短解释、明确 `依据:` 和影响/下一步;不得把五个专项压成一段或把多个 PR 合并总结。
|
||||
- 人读 `final-report.md` 必须使用中文叙述;命令名、路径、稳定编号和机器状态枚举可以保留英文。每个阶段的 `assessment.fact` 与 `assessment.basis` 在交给 finalize 前先转成忠实的中文摘要,不能把整份英文阶段报告直接拼入。
|
||||
- 一次运行只生成一份主要人读报告 `<run-directory>/final-report.md`。五个专项 JSON 和 `final-report.json` 作为机器证据附件,不再让维护者阅读五份独立长 Markdown。
|
||||
|
||||
最终回复必须由执行 Skill 的 Agent 在读完 `final-report.md` 和 `final-report.json` 后重新提炼,不能复制报告首屏、不能机械删除 Markdown/HTML 格式、不能把卡片原文改成纯文本后直接输出。聊天摘要要比报告更短,按每个 PR 输出六个方面的结论、最关键依据和解释/影响,每个方面一至两句完整自然语言;省略路径清单、阶段索引、分页过程、机器状态标签和次要证据。全部 PR 摘要后再给最多五项跨专项动作,并用可点击链接或当前 Agent 平台的文件附件交付 `final-report.md`。若无法落盘,输出完整 Markdown 并标记“未落盘”。
|
||||
最终回复必须由执行 Skill 的 Agent 在读完 `final-report.md` 和 `final-report.json` 后重新提炼,不能复制报告首屏、不能机械删除 Markdown/HTML 格式、不能把卡片原文改成纯文本后直接输出。聊天摘要要比报告短,但每个 PR 必须覆盖 [`references/comprehensive-dimensions.md`](references/comprehensive-dimensions.md) 规定的 15 项直接判断,每项一至两句,包含结论、最关键依据和影响。省略路径清单、阶段索引、分页过程、机器状态标签和次要证据。全部 PR 摘要后再给最多五项跨专项动作,并用可点击链接或当前 Agent 平台的文件附件交付 `final-report.md`。若无法落盘,输出完整 Markdown 并标记“未落盘”。
|
||||
|
||||
聊天摘要示例只表达风格,不是可复制模板:
|
||||
|
||||
```text
|
||||
PR #430
|
||||
代码审查:建议修改后再审。它补齐维护队列的真实状态过滤,但当前 fixture 仍显示 closed 项会进入 open 队列,这会直接误导维护者的待审范围。
|
||||
CLI 契约:需要先稳定字段语义。新增 changes、waiting_on 和 SLA 字段有实际价值,但空值、兼容回退和错误提示还要和主线帮助/JSON 输出对齐。
|
||||
仓库关系:适合排在 #431 前面评审。#431 会消费 #430 的队列字段,所以先确认 #430 的运行时契约,可以减少后续 Skill 协议返工。
|
||||
集成门禁:暂时不能进入合并队列。构建和基础测试可以作为正向证据,但真实队列过滤失败仍是集成前必须修复的问题。
|
||||
维护状态:当前主要等待作者修复。维护者最需要检查的是过滤逻辑、字段空值和回归测试是否补齐。
|
||||
最终结论:先修复再复审。这个 PR 的方向成立,但真实队列可信度是它能否合入的前提。
|
||||
最终建议:修改后再审。功能方向成立,但真实队列过滤失败会直接误导维护者。
|
||||
贡献价值与功能增量:补齐队列变化和等待责任信号,能减少人工比对;主线没有等价完整实现。
|
||||
Review 履约:当前没有足够的正式 Review 基线,不能判断作者是否已经完成全部修改要求。
|
||||
逻辑、质量与可维护性:主流程沿用现有架构,但 open 状态二次过滤存在错误,需要修复后再评价稳定性。
|
||||
测试、安全与性能:基础测试通过,真实状态、权限失败和大队列边界仍需补测;未发现已证实的安全阻断。
|
||||
参数、帮助与兼容:新增参数具有价值,旧调用默认行为需要继续保持。
|
||||
JSON、错误、编码与文档:字段类型基本稳定,但空值语义和错误原因不能被统一误报为 JSON 解析失败。
|
||||
主线与 merged 历史关系:属于已有 workflow 队列能力的增量演进,不是重复实现。
|
||||
open PR 重叠、依赖与处理顺序:与消费这些字段的下游 PR 互补,应先稳定本 PR 契约。
|
||||
合并态、构建与冲突:基础构建成立,仍需在最新主线合并工作树确认无冲突。
|
||||
测试、CI、安全与发布门禁:当前 head 的 CI 关联和失败路径验证不完整,暂不能进入合并队列。
|
||||
SLA、等待方与 Reviewer 负载:当前等待作者修复;完整 reviewer 负载需要仓库级快照。
|
||||
责任停滞、Issue 和安全运营优先级:修复责任明确,超过阈值后应升级复看提醒。
|
||||
证据完整性与跨专项一致性:五个阶段使用同一 head,但 CI 和 Review 证据仍有缺口;各专项结论没有无法解释的冲突。
|
||||
优先动作、责任方与复验条件:作者先修复过滤并补失败测试,维护者随后重跑契约和集成门禁。
|
||||
|
||||
完整报告:[final-report.md](D:\path\to\final-report.md)
|
||||
```
|
||||
|
||||
最终聊天不能只回复路径、状态计数或跨 PR 总段落。Markdown 能使用醒目颜色和加粗;聊天摘要除必要的 PR 编号、证据编号和最终报告链接外,不输出 HTML/Markdown 展示标签。
|
||||
最终聊天不能只回复路径、状态计数、五个阶段状态或跨 PR 总段落。Markdown 能使用醒目颜色和加粗;聊天摘要除必要的 PR 编号、证据编号和最终报告链接外,不输出 HTML/Markdown 展示标签。
|
||||
|
||||
首屏固定先使用:
|
||||
报告中的每个维度固定使用以下卡片语法;必须重复覆盖完整维度表,不能只生成示例中的几项:
|
||||
|
||||
```markdown
|
||||
# PR 维护全流程摘要
|
||||
|
||||
## PR #<number>
|
||||
**代码审查:** <span style="color:#B42318"><strong>核心队列结果不可靠</strong></span> **[action_required]**:closed 项进入 open 响应;依据:CR-001 与真实 fixture;下一步:修复过滤并补测试。
|
||||
**CLI 契约:** <span style="color:#067647"><strong>新增字段保持向后兼容</strong></span> **[passed]**:字段可选且旧调用不变;依据:CG 对照和 golden 输出;影响:现有脚本无需迁移。
|
||||
**仓库关系:** <span style="color:#175CD3"><strong>需要先稳定上游契约</strong></span> **[reorder]**:存在字段生产/消费关系;依据:主线、全部 open/merged PR 索引;影响:调整评审顺序。
|
||||
**集成门禁:** <span style="color:#B42318"><strong>当前不能进入合并队列</strong></span> **[blocked]**:真实响应测试失败;依据:IN-001 和当前 head 验证;下一步:修复后重跑。
|
||||
**维护状态:** <span style="color:#B54708"><strong>等待作者修复后复看</strong></span> **[action_required]**:责任链明确;依据:Review、提交和 SLA 快照;下一步:作者更新后通知 reviewer。
|
||||
**最终结论:** <span style="color:#B42318"><strong>修复真实状态过滤后重新审查</strong></span> **[blocked]**:存在一个阻断和两个高风险项;依据:CR-001、IN-001、MR-001;下一步:按动作顺序处理。
|
||||
### 代码审查
|
||||
**贡献价值:** <span style="color:#067647"><strong>高频维护价值成立</strong></span> **[merge]**:补齐队列变化信号;依据:主线缺口和用户流程;证据摘录:需求与 Diff;影响:减少人工比对。
|
||||
**逻辑正确性:** <span style="color:#B42318"><strong>真实状态过滤不可靠</strong></span> **[action_required]**:closed 项进入 open 响应;依据:CR-001 和真实 fixture;证据摘录:失败输出;影响:修复并补测试。
|
||||
|
||||
### CLI 契约
|
||||
**JSON 与文本输出:** <span style="color:#B54708"><strong>空值语义尚未稳定</strong></span> **[observe]**:新增字段可选但错误回退不完整;依据:golden 对照;证据摘录:结构化输出;影响:稳定后再供下游消费。
|
||||
|
||||
### 编排器综合判断
|
||||
**证据完整性与新鲜度:** <span style="color:#B54708"><strong>CI 和 Review 证据不完整</strong></span> **[observe]**:五阶段 head 一致但两类证据缺失;依据:运行账本;证据摘录:collection manifest;影响:不能给出高置信度合并结论。
|
||||
**最终结论:** <span style="color:#B42318"><strong>修复真实状态过滤后重新审查</strong></span> **[blocked]**:存在一个阻断和两个高风险项;依据:CR-001、IN-001、MR-001;证据摘录:失败 fixture 与门禁结果;下一步:按动作顺序处理。
|
||||
|
||||
## 先处理这 3 项
|
||||
|
||||
|
|
@ -71,7 +84,7 @@ CLI 契约:需要先稳定字段语义。新增 changes、waiting_on 和 SLA
|
|||
3. <span style="color:#B54708"><strong>[MR-001][high] 转派</strong></span> 安全复查;责任:maintainer。
|
||||
```
|
||||
|
||||
多个 PR 重复完整六张卡,每张卡只能引用该 PR 的证据。跨 PR 动作放在全部 PR 卡片之后。
|
||||
多个 PR 重复完整综合维度矩阵,每张卡只能引用该 PR 的证据。跨 PR 动作放在全部 PR 卡片之后。
|
||||
|
||||
## 编排流程
|
||||
|
||||
|
|
@ -151,7 +164,7 @@ pr-topology.json
|
|||
}
|
||||
```
|
||||
|
||||
每条 `evidence` 不能只有 `E-xxx`、`CR-xxx` 等编号,至少还要提供 `summary`、`source`、`ref`、`status` 和可选的 `scope`。`summary` 必须说明实际观察到什么,例如“正常路径测试通过但无权限路径未覆盖”,不能只重复结论。编排器会把这些字段直接写入六张判断卡、待办和证据台账;没有可读证据时必须写明限制,而不是只显示编号。
|
||||
每条 `evidence` 不能只有 `E-xxx`、`CR-xxx` 等编号,至少还要提供 `summary`、`source`、`ref`、`status` 和可选的 `scope`。`summary` 必须说明实际观察到什么,例如“正常路径测试通过但无权限路径未覆盖”,不能只重复结论。编排器会把这些字段直接写入综合维度卡片、待办和证据台账;没有可读证据时必须写明限制,而不是只显示编号。
|
||||
|
||||
`top_actions.evidence` 和 `findings.evidence` 可以引用证据或发现 ID 以便追溯,但阶段结果必须同时保留对应的可读 `evidence` 对象。编排器在渲染时必须将发现 ID 展开为问题摘要和直接证据,不能在待办或最终结论中只显示 `CR-001`、`E-001` 等标识。
|
||||
|
||||
|
|
@ -173,11 +186,10 @@ pr-topology.json
|
|||
- 只有拓扑关系需要调整顺序时:最终决策可为 `reorder`。
|
||||
- 没有阻断项但存在维护动作时:显示 `action_required`,不自动回写远端。
|
||||
|
||||
### 5. 生成维护者首屏
|
||||
### 5. 生成完整综合报告
|
||||
|
||||
最终报告必须先按目标 PR 展示六张判断卡,顺序固定为代码审查、CLI 契约、仓库关系、
|
||||
集成门禁、维护状态、最终结论。每张卡先给醒目结论,再写当前 PR 的事实、`依据:`
|
||||
以及影响或下一步;不能把五个阶段压缩成一段总体叙述。全部目标 PR 的判断卡展示完后,
|
||||
最终报告必须按目标 PR 展示 [`references/comprehensive-dimensions.md`](references/comprehensive-dimensions.md) 中五个专项的完整维度,再展示编排器独有判断和最终结论。每张卡先给醒目结论,再写当前 PR 的事实、`依据:`
|
||||
以及影响或下一步;不能把五个阶段压缩成五张总评。全部目标 PR 的判断卡展示完后,
|
||||
再给最多五项跨专项待办,每项包含对象、责任方、下一动作、严重性和一个主证据。
|
||||
阻断数、高风险数、安全门禁和验证状态可以作为卡片之后的索引,不能替代解释。
|
||||
完整 findings、可读证据台账、限制和下一次复查条件放入附录或 JSON。证据编号仅用于追溯,不能替代证据摘要;维护者不打开 JSON 也应能在 Markdown 中看到观察事实、来源、命令或文件位置、状态和适用范围。
|
||||
|
|
@ -209,7 +221,7 @@ python -X utf8 .\skills\gitlink-maintenance-orchestrator\scripts\validate_chines
|
|||
--require-pr 123
|
||||
```
|
||||
|
||||
多 PR 报告为每个目标重复 `--require-pr`。任何目标缺少完整六张判断卡、卡片没有明确
|
||||
多 PR 报告为每个目标重复 `--require-pr`。任何目标缺少完整综合维度、卡片没有明确
|
||||
`依据:`、中文被写成连续问号或报告退化为英文模板时,校验失败且不得交付路径。
|
||||
|
||||
`collect` 只执行 `gitlink-cli` 的读操作,不发布评论、不添加标签、不分配 reviewer、不关闭或合并 PR。若 PowerShell 禁止执行 `gitlink-cli.ps1`,传入可执行的 `gitlink-cli.exe` 或 `gitlink-cli.cmd` 到 `-CliPath`。
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
interface:
|
||||
display_name: "GitLink 维护审查编排器"
|
||||
short_description: "编排五个维护 Skill 生成可验证的 PR 维护摘要"
|
||||
default_prompt: "使用 $gitlink-maintenance-orchestrator 分析指定仓库或一个/多个 PR;完整证据保存为中文 Markdown,聊天结论由执行 Agent 读完报告后重新提炼,按 PR 分别概括代码审查、CLI 契约、仓库关系、集成门禁、维护状态和最终结论,每方面说明结论、关键依据与影响,不复制报告卡片原文、不输出 HTML/Markdown 展示标签,全程只读。"
|
||||
short_description: "编排五个维护 Skill 生成全面、可验证的 PR 综合报告"
|
||||
default_prompt: "使用 $gitlink-maintenance-orchestrator 分析指定仓库或一个/多个 PR;完整证据保存为中文 Markdown,报告覆盖五个专项的大部分评估维度以及证据一致性、风险传播、责任动作和决策置信度。聊天结论由执行 Agent 读完报告后重新提炼,按 PR 输出 15 项简明判断,每项说明结论、关键依据与影响,不复制报告卡片原文、不输出 HTML/Markdown 展示标签,全程只读。"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@
|
|||
"fact": "新增命令保持原有参数、帮助、JSON 类型和错误语义,未观察到用户可感知的契约破坏",
|
||||
"basis": "对默认分支与当前 head 执行相同帮助和结构化输出测试,契约测试完整通过"
|
||||
},
|
||||
"dimensions": [
|
||||
{"aspect": "参数与帮助", "conclusion": "新增入口保持旧调用兼容", "decision": "merge", "fact": "新参数为可选项且默认行为不变", "basis": "baseline 与 head 帮助对照", "evidence": ["E-CG-001"], "impact": "现有用户无需迁移"},
|
||||
{"aspect": "JSON 与文本输出", "conclusion": "机器输出结构稳定", "decision": "merge", "fact": "新增字段未改变既有字段类型,文本没有混入 JSON", "basis": "结构化输出解析测试", "evidence": ["E-CG-001"], "impact": "自动化脚本可继续解析"},
|
||||
{"aspect": "错误与退出码", "conclusion": "错误语义保持可区分", "decision": "merge", "fact": "参数错误与远端失败仍返回不同错误路径", "basis": "失败命令与退出码对照", "evidence": ["E-CG-001"], "impact": "调用方无需修改判断逻辑"},
|
||||
{"aspect": "编码与颜色", "conclusion": "UTF-8 和机器输出边界正常", "decision": "merge", "fact": "中文输出可严格解码,JSON 不包含 ANSI", "basis": "原始字节和 JSON 解析验证", "evidence": ["E-CG-001"], "impact": "跨平台输出风险较低"},
|
||||
{"aspect": "兼容与文档", "conclusion": "文档与当前行为一致", "decision": "merge", "fact": "帮助和示例覆盖新增入口及默认行为", "basis": "文档、帮助和运行结果对照", "evidence": ["E-CG-001"], "impact": "用户可按现有文档使用"}
|
||||
],
|
||||
"findings": [],
|
||||
"top_actions": [],
|
||||
"evidence": [
|
||||
|
|
|
|||
|
|
@ -12,6 +12,14 @@
|
|||
"fact": "PR 为示例命令增加批量处理能力,但错误路径缺少回归测试,核心失败行为尚未被证明可靠",
|
||||
"basis": "对照默认分支与当前 Diff,并执行 go test ./shortcuts/example;正常路径通过,失败路径覆盖不完整"
|
||||
},
|
||||
"dimensions": [
|
||||
{"aspect": "贡献价值", "conclusion": "批量处理能力具有明确使用价值", "decision": "merge", "fact": "PR 减少重复命令调用并覆盖常用维护流程", "basis": "对照默认分支功能入口与 PR 描述", "evidence": ["E-CR-001"], "impact": "功能方向可以保留"},
|
||||
{"aspect": "Review 履约", "conclusion": "本轮没有可核对的正式 Review", "decision": "observe", "fact": "当前证据没有包含有效 Review 意见与对应提交", "basis": "Review 证据未采集完整", "evidence": ["E-CR-001"], "impact": "不能判断作者是否完成 Review 修改"},
|
||||
{"aspect": "逻辑正确性", "conclusion": "失败路径仍不可靠", "decision": "action_required", "fact": "正常路径可用,但远端失败和非法输入没有完整行为证据", "basis": "当前 Diff 与专项测试结果", "evidence": ["E-CR-001"], "impact": "修复错误处理后复验"},
|
||||
{"aspect": "代码质量与可维护性", "conclusion": "主流程结构清晰", "decision": "merge", "fact": "批量入口沿用现有 shortcut 结构,未发现明显重复实现", "basis": "目录职责和调用链对照", "evidence": ["E-CR-001"], "impact": "当前结构不阻断合并"},
|
||||
{"aspect": "测试覆盖", "conclusion": "失败和权限场景缺测", "decision": "action_required", "fact": "成功场景通过,但无权限和非法路径没有回归测试", "basis": "测试文件与执行命令对照", "evidence": ["E-CR-001"], "impact": "补齐失败路径后重跑"},
|
||||
{"aspect": "安全与性能", "conclusion": "未发现已证实的安全或性能阻断", "decision": "observe", "fact": "现有范围未发现凭据泄露和无界批量循环,但恶意输入未完整验证", "basis": "Diff 安全热点和测试范围", "evidence": ["E-CR-001"], "impact": "保持观察并补输入边界测试"}
|
||||
],
|
||||
"findings": [
|
||||
{"id": "CR-001", "severity": "high", "status": "open", "summary": "错误路径缺少回归测试", "evidence": ["E-CR-001"], "related_ids": []}
|
||||
],
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@
|
|||
"fact": "PR #123 已有明确修复动作但仍等待作者补测,继续占用维护者复看队列",
|
||||
"basis": "队列快照显示 waiting_on=author,当前 head 和 Review 后续动作尚未变化"
|
||||
},
|
||||
"dimensions": [
|
||||
{"aspect": "响应 SLA", "conclusion": "当前复看等待正在累积", "decision": "action_required", "fact": "作者补测尚未完成,PR 继续占用复看队列", "basis": "队列时间与状态快照", "evidence": ["E-MR-001"], "impact": "修复后应及时通知 reviewer"},
|
||||
{"aspect": "当前等待方", "conclusion": "当前明确等待作者", "decision": "action_required", "fact": "waiting_on=author 且修复动作已指向 CR-001", "basis": "队列字段和技术动作关联", "evidence": ["E-MR-001"], "impact": "维护者暂不重复 Review"},
|
||||
{"aspect": "Reviewer 负载", "conclusion": "本次没有足够数据判断负载平衡", "decision": "observe", "fact": "fixture 只包含目标 PR,没有完整 reviewer 队列", "basis": "扫描范围限制", "evidence": ["E-MR-001"], "impact": "需要仓库级快照后再调度"},
|
||||
{"aspect": "责任停滞", "conclusion": "责任链清晰但尚未推进", "decision": "action_required", "fact": "作者有明确补测任务,当前 head 尚未变化", "basis": "waiting_on 与 head 快照", "evidence": ["E-MR-001"], "impact": "超过阈值后升级维护提醒"},
|
||||
{"aspect": "安全与 Issue 优先级", "conclusion": "没有已证实的安全 HOT 事项", "decision": "observe", "fact": "当前高优先级来自测试缺口而非已确认漏洞", "basis": "安全门禁和 finding 分类", "evidence": ["E-MR-001"], "impact": "保持技术修复优先,不误报安全漏洞"}
|
||||
],
|
||||
"findings": [],
|
||||
"top_actions": [
|
||||
{"id": "MR-001", "owner": "maintainer", "severity": "medium", "action": "安排维护者复看 PR #123,当前等待作者补测", "evidence": ["queue:pr-123"]}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,14 @@
|
|||
"fact": "贡献方向与仓库需求一致,但代码审查发现的失败路径缺口尚未修复,当前实现不能安全进入合并队列",
|
||||
"basis": "当前 head 的基础构建可执行,但 CR-001 未解决且全量集成验证只完成部分门禁"
|
||||
},
|
||||
"dimensions": [
|
||||
{"aspect": "合并态与冲突", "conclusion": "尚未完成最新主线合并验证", "decision": "observe", "fact": "当前 fixture 没有最新主线合并工作树结果", "basis": "合并态证据缺失", "evidence": ["E-IN-001"], "impact": "合并前必须在最新主线复验"},
|
||||
{"aspect": "构建", "conclusion": "基础构建可执行", "decision": "merge", "fact": "当前 head 在规定环境完成基础构建", "basis": "本地工作树构建结果", "evidence": ["E-IN-001"], "impact": "构建不构成当前阻断"},
|
||||
{"aspect": "测试与功能一致性", "conclusion": "PR 声明仅部分得到验证", "decision": "action_required", "fact": "成功路径成立,但错误路径与描述中的可靠性目标不一致", "basis": "专项测试和 CR-001", "evidence": ["E-IN-001"], "impact": "补测并修复后重跑"},
|
||||
{"aspect": "CI 与证据关联", "conclusion": "CI 证据未完整关联当前 head", "decision": "observe", "fact": "fixture 没有提供可核对的 head SHA 构建记录", "basis": "CI 证据关联字段缺失", "evidence": ["E-IN-001"], "impact": "不能把历史构建当作当前通过"},
|
||||
{"aspect": "安全与发布影响", "conclusion": "没有已证实的发布阻断", "decision": "observe", "fact": "安全门禁通过,但失败路径和回滚证据不完整", "basis": "安全状态与限制列表", "evidence": ["E-IN-001"], "impact": "补齐验证后确认发布风险"},
|
||||
{"aspect": "集成结论", "conclusion": "当前不能进入合并队列", "decision": "action_required", "fact": "CR-001 未解决且合并态、CI 和全量测试不完整", "basis": "代码审查与集成证据汇总", "evidence": ["E-IN-001"], "impact": "完成高优先级动作后重新评估"}
|
||||
],
|
||||
"findings": [],
|
||||
"top_actions": [
|
||||
{"id": "IN-001", "owner": "author", "severity": "high", "action": "修复 CR-001 后重新执行合并态验证", "evidence": ["CR-001"]}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@
|
|||
"fact": "PR #123 与 #124 修改同一命令入口,功能不完全重复,但合并顺序可能改变最终输出契约",
|
||||
"basis": "比较两条 PR 的文件集合、队列快照和目标行为后确认存在共享入口,尚无证据判定其中一条完全替代另一条"
|
||||
},
|
||||
"dimensions": [
|
||||
{"aspect": "对当前主线", "conclusion": "目标是对主线能力的增量扩展", "decision": "merge", "fact": "主线已有基础入口,但没有本 PR 的批量行为", "basis": "默认分支源码与目标 Diff 对照", "evidence": ["E-TP-001"], "impact": "不存在主线完全覆盖"},
|
||||
{"aspect": "对 open 队列", "conclusion": "与 #124 存在共享入口", "decision": "reorder", "fact": "两条 open PR 修改同一命令入口但目标不同", "basis": "完整 open 队列和文件语义比较", "evidence": ["E-TP-001"], "impact": "需要联合评审接口边界"},
|
||||
{"aspect": "对 merged 历史", "conclusion": "继承既有 shortcut 架构", "decision": "merge", "fact": "已合入历史提供基础命令框架,但没有等价批量实现", "basis": "merged PR 索引与主线提交历史", "evidence": ["E-TP-001"], "impact": "应按增量演进评审"},
|
||||
{"aspect": "完整性比较", "conclusion": "目标与 #124 互补而非替代", "decision": "observe", "fact": "两条 PR 的覆盖范围和验证重点不同", "basis": "功能范围、测试和文件路径比较", "evidence": ["E-TP-001"], "impact": "不建议仅按文件交集择一"},
|
||||
{"aspect": "依赖与处理顺序", "conclusion": "先稳定共享入口再合入下游", "decision": "reorder", "fact": "合并顺序可能改变最终命令和输出契约", "basis": "入口生产与消费关系", "evidence": ["E-TP-001"], "impact": "先确认接口再处理后续 PR"}
|
||||
],
|
||||
"findings": [
|
||||
{"id": "TP-001", "severity": "medium", "status": "open", "summary": "与 PR #124 修改同一命令入口,建议合并顺序复核", "evidence": ["E-TP-001"], "related_ids": ["PR-124"]}
|
||||
],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
# 综合维护评估维度
|
||||
|
||||
总报告必须覆盖下列六组维度。专项阶段应逐项写入 `dimensions`;没有证据时保留该项并标记 `observe`、`partial` 或 `not_run`,不能省略。
|
||||
|
||||
## 1. 代码与贡献
|
||||
|
||||
| 维度 | 最低判断内容 |
|
||||
|---|---|
|
||||
| 贡献价值 | 真实问题、受益对象、相对主线增量、维护成本 |
|
||||
| Review 履约 | 有效 Review、对应提交、修改是否满足要求、剩余动作 |
|
||||
| 逻辑正确性 | 正常、失败、边界、状态一致性和错误处理 |
|
||||
| 代码质量与可维护性 | 架构一致性、职责、复杂度、重复、长期维护成本 |
|
||||
| 测试覆盖 | 单元、集成、回归、失败和跨平台场景 |
|
||||
| 安全与性能 | 权限、注入、路径、凭据、依赖、资源和性能退化 |
|
||||
|
||||
## 2. CLI 契约
|
||||
|
||||
| 维度 | 最低判断内容 |
|
||||
|---|---|
|
||||
| 参数与帮助 | 命令层级、flag、别名、默认值、帮助与示例 |
|
||||
| JSON 与文本输出 | 字段、类型、可选性、人读与机读隔离 |
|
||||
| 错误与退出码 | 参数、认证、权限、远端和解析失败语义 |
|
||||
| 编码与颜色 | UTF-8、乱码、ANSI、`NO_COLOR` 和跨平台 |
|
||||
| 兼容与文档 | 旧调用、迁移成本、README 和帮助一致性 |
|
||||
|
||||
## 3. 仓库关系
|
||||
|
||||
| 维度 | 最低判断内容 |
|
||||
|---|---|
|
||||
| 对当前主线 | 已实现、补缺、扩展、重复或回归 |
|
||||
| 对 open 队列 | 依赖、竞争、重叠、互补、冲突和联审对象 |
|
||||
| 对 merged 历史 | 继承来源、已合入等价实现和演进关系 |
|
||||
| 完整性比较 | 重叠实现的范围、测试、架构适配和维护成本 |
|
||||
| 依赖与处理顺序 | 硬依赖、顺序依赖、合入次序和解除条件 |
|
||||
|
||||
## 4. 集成门禁
|
||||
|
||||
| 维度 | 最低判断内容 |
|
||||
|---|---|
|
||||
| 合并态与冲突 | 最新主线合并、冲突文件和基线 SHA |
|
||||
| 构建 | 仓库规定环境、构建命令、结果和限制 |
|
||||
| 测试与功能一致性 | PR 声明、实际行为、全量/专项测试和失败路径 |
|
||||
| CI 与证据关联 | head SHA、分支回退、未关联构建和时效 |
|
||||
| 安全与发布影响 | 安全门禁、依赖、迁移、发布和回滚 |
|
||||
| 集成结论 | 是否进入 merge queue、阻塞项和复验条件 |
|
||||
|
||||
## 5. 维护治理
|
||||
|
||||
| 维度 | 最低判断内容 |
|
||||
|---|---|
|
||||
| 响应 SLA | 首响、Review、复看和合并等待时间 |
|
||||
| 当前等待方 | 作者、reviewer、maintainer、外部依赖或未知 |
|
||||
| Reviewer 负载 | 分配数量、瓶颈和可释放容量 |
|
||||
| 责任停滞 | 已分配但无进展、requested changes 后未更新 |
|
||||
| 安全与 Issue 优先级 | 安全运营信号、关联 Issue 和队列优先级 |
|
||||
|
||||
## 6. 编排器独有判断
|
||||
|
||||
| 维度 | 最低判断内容 |
|
||||
|---|---|
|
||||
| 证据完整性与新鲜度 | 五阶段齐全、run/head/as_of 一致、缺失和过期证据 |
|
||||
| 跨专项结论一致性 | 结论是否冲突,冲突如何按证据和门禁解释 |
|
||||
| 风险传播与门禁对齐 | CR/CG/TP 风险如何影响 IN 和 MR |
|
||||
| 动作去重与责任归属 | 重复动作合并、责任方、先后顺序和解除条件 |
|
||||
| 决策置信度 | 覆盖率、限制、未验证项和结论可信程度 |
|
||||
|
||||
## 聊天直接输出
|
||||
|
||||
聊天摘要不能把总报告压缩成五个阶段状态。每个 PR 至少输出以下 15 项简明判断,每项一至两句,包含结论、最关键依据和影响:
|
||||
|
||||
1. 最终建议
|
||||
2. 贡献价值与功能增量
|
||||
3. Review 履约
|
||||
4. 逻辑、质量与可维护性
|
||||
5. 测试、安全与性能
|
||||
6. 参数、帮助与兼容
|
||||
7. JSON、错误、编码与文档
|
||||
8. 主线与 merged 历史关系
|
||||
9. open PR 重叠、依赖与处理顺序
|
||||
10. 合并态、构建与冲突
|
||||
11. 测试、CI、安全与发布门禁
|
||||
12. SLA、等待方与 Reviewer 负载
|
||||
13. 责任停滞、Issue 和安全运营优先级
|
||||
14. 证据完整性与跨专项一致性
|
||||
15. 优先动作、责任方与复验条件
|
||||
|
||||
多个 PR 分别输出,不能共用结论。聊天不复制 Markdown 卡片、HTML 标签、阶段索引、分页过程或完整证据台账;完整内容通过报告链接交付。
|
||||
|
|
@ -46,6 +46,17 @@
|
|||
"fact": "核心成功路径可用,但远端失败没有回归证据",
|
||||
"basis": "当前 head 的 Diff、专项测试和失败路径测试清单"
|
||||
},
|
||||
"dimensions": [
|
||||
{
|
||||
"aspect": "逻辑正确性",
|
||||
"conclusion": "失败路径仍不可靠",
|
||||
"decision": "action_required",
|
||||
"fact": "远端失败没有稳定错误映射",
|
||||
"basis": "当前 Diff 与失败路径测试",
|
||||
"evidence": ["E-CR-001"],
|
||||
"impact": "修复并补测后复验"
|
||||
}
|
||||
],
|
||||
"findings": [],
|
||||
"top_actions": [],
|
||||
"evidence": [],
|
||||
|
|
@ -59,6 +70,11 @@
|
|||
`action_required`、`reorder`、`observe`、`blocked`。阶段之间不得篡改其他 Skill 的
|
||||
finding,只通过 `related_ids` 关联。
|
||||
|
||||
`dimensions` 必须覆盖该阶段在
|
||||
[`comprehensive-dimensions.md`](comprehensive-dimensions.md) 中列出的全部维度。每个维度必须有 `aspect`、`conclusion`、`decision`、`fact`、`basis`、`evidence` 和 `impact`。没有证据时仍保留维度,并明确写 `not_run`、`partial` 或 `observe`;禁止用阶段级 `assessment` 代替全部维度。
|
||||
|
||||
编排器在五阶段之后额外生成“证据完整性与新鲜度、跨专项结论一致性、风险传播与门禁对齐、动作去重与责任归属、决策置信度”五项判断。这些判断属于编排器,不得伪装成某个专项 finding。
|
||||
|
||||
## 最终决策规则
|
||||
|
||||
按以下顺序计算最终决策:
|
||||
|
|
@ -75,6 +91,7 @@ finding,只通过 `related_ids` 关联。
|
|||
|
||||
## 首屏压缩规则
|
||||
|
||||
- 每个 PR 先展示五个专项的完整维度矩阵,再展示编排器独有判断和最终结论。
|
||||
- 首屏最多五项待办,按 `blocking > high > medium > low`、再按责任等待方和证据置信度排序。
|
||||
- 同一对象、同一动作、同一责任方的重复项合并;保留全部 `source_ids` 供追溯。
|
||||
- 首屏每项只展示一个主证据,完整证据放到 JSON 或附录。
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -141,6 +141,68 @@ function Resolve-EvidenceText {
|
|||
return ($items -join ';')
|
||||
}
|
||||
|
||||
function Get-RequiredDimensions {
|
||||
param([string]$Producer)
|
||||
switch ($Producer) {
|
||||
'gitlink-code-review' {
|
||||
return @('贡献价值', 'Review 履约', '逻辑正确性', '代码质量与可维护性', '测试覆盖', '安全与性能')
|
||||
}
|
||||
'gitlink-cli-contract-guard' {
|
||||
return @('参数与帮助', 'JSON 与文本输出', '错误与退出码', '编码与颜色', '兼容与文档')
|
||||
}
|
||||
'gitlink-pr-topology' {
|
||||
return @('对当前主线', '对 open 队列', '对 merged 历史', '完整性比较', '依赖与处理顺序')
|
||||
}
|
||||
'gitlink-pr-integrator' {
|
||||
return @('合并态与冲突', '构建', '测试与功能一致性', 'CI 与证据关联', '安全与发布影响', '集成结论')
|
||||
}
|
||||
'gitlink-maintainer-radar' {
|
||||
return @('响应 SLA', '当前等待方', 'Reviewer 负载', '责任停滞', '安全与 Issue 优先级')
|
||||
}
|
||||
default { return @('专项判断') }
|
||||
}
|
||||
}
|
||||
|
||||
function Get-StageDimensions {
|
||||
param([string]$Producer, [object]$Artifact)
|
||||
$provided = @()
|
||||
$assessment = $null
|
||||
$stageEvidence = @()
|
||||
if ($null -ne $Artifact) {
|
||||
$provided = @(Get-Value $Artifact 'dimensions' @())
|
||||
$assessment = Get-Value $Artifact 'assessment' $null
|
||||
$stageEvidence = @(Get-Value $Artifact 'evidence' @())
|
||||
}
|
||||
$result = New-Object Collections.Generic.List[object]
|
||||
foreach ($aspect in @(Get-RequiredDimensions $Producer)) {
|
||||
$item = $provided | Where-Object { [string](Get-Value $_ 'aspect' '') -eq $aspect } | Select-Object -First 1
|
||||
if ($null -eq $item) {
|
||||
$stageConclusion = if ($null -ne $assessment) { [string](Get-Value $assessment 'conclusion' '') } else { '' }
|
||||
$stageBasis = if ($null -ne $assessment) { [string](Get-Value $assessment 'basis' '') } else { '' }
|
||||
$result.Add([pscustomobject][ordered]@{
|
||||
aspect = $aspect
|
||||
conclusion = '该维度证据不足'
|
||||
decision = 'observe'
|
||||
fact = "当前 ${Producer} 结果未提供维度 ${aspect} 的独立判断,不能从阶段总评推断为通过"
|
||||
basis = if ($stageBasis) { "阶段级依据仅为:$stageBasis" } else { '缺少该维度的结构化依据' }
|
||||
evidence = @($stageEvidence | Select-Object -First 1)
|
||||
impact = if ($stageConclusion) { "保留阶段总评 ${stageConclusion},补齐本维度后再提高置信度" } else { '补齐本维度证据后重新评估' }
|
||||
})
|
||||
continue
|
||||
}
|
||||
$result.Add([pscustomobject][ordered]@{
|
||||
aspect = $aspect
|
||||
conclusion = [string](Get-Value $item 'conclusion' '该维度尚无明确结论')
|
||||
decision = [string](Get-Value $item 'decision' 'observe')
|
||||
fact = [string](Get-Value $item 'fact' '未提供事实摘要')
|
||||
basis = [string](Get-Value $item 'basis' '未提供判断依据')
|
||||
evidence = @(Get-Value $item 'evidence' @())
|
||||
impact = [string](Get-Value $item 'impact' '根据该维度证据决定下一步')
|
||||
})
|
||||
}
|
||||
return $result.ToArray()
|
||||
}
|
||||
|
||||
function Get-StageSummary {
|
||||
param([string]$Producer, [object]$Artifact)
|
||||
$findings = @()
|
||||
|
|
@ -192,6 +254,7 @@ function Get-StageSummary {
|
|||
focus = $focus
|
||||
basis = $basis
|
||||
evidence = @($evidence | Select-Object -First 2)
|
||||
dimensions = @(Get-StageDimensions -Producer $Producer -Artifact $Artifact)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -284,6 +347,73 @@ function Get-FinalDecision {
|
|||
return 'observe'
|
||||
}
|
||||
|
||||
function New-OrchestratorDimensions {
|
||||
param(
|
||||
[bool]$AllComplete,
|
||||
[object[]]$Summaries,
|
||||
[object[]]$Actions,
|
||||
[object]$Counts,
|
||||
[string]$SecurityGate,
|
||||
[string]$Verification,
|
||||
[string]$Decision,
|
||||
[object[]]$Limitations,
|
||||
[object[]]$Evidence
|
||||
)
|
||||
$stageStates = @($Summaries | ForEach-Object { "$($_.producer)=$($_.status)/$($_.decision)" }) -join ','
|
||||
$evidenceSample = @($Evidence | Select-Object -First 2)
|
||||
$missingOwners = @($Actions | Where-Object { [string]::IsNullOrWhiteSpace([string]$_.owner) -or $_.owner -eq '维护者' }).Count
|
||||
$coverageConclusion = if ($AllComplete -and $Verification -eq 'complete' -and @($Limitations).Count -eq 0) { '五阶段证据完整且时间上下文一致' } else { '证据覆盖或新鲜度仍有限制' }
|
||||
$coverageDecision = if ($AllComplete -and $Verification -eq 'complete' -and @($Limitations).Count -eq 0) { 'merge' } else { 'observe' }
|
||||
$confidence = if ($coverageDecision -eq 'merge' -and $SecurityGate -eq 'passed') { '高' } elseif ($AllComplete) { '中' } else { '低' }
|
||||
return @(
|
||||
[pscustomobject][ordered]@{
|
||||
aspect = '证据完整性与新鲜度'
|
||||
conclusion = $coverageConclusion
|
||||
decision = $coverageDecision
|
||||
fact = "五个阶段完成状态为:$stageStates;验证汇总为 $Verification,限制 $(@($Limitations).Count) 项"
|
||||
basis = '核对 run_id、as_of、目标 head、阶段状态、验证状态和限制列表'
|
||||
evidence = $evidenceSample
|
||||
impact = if ($coverageDecision -eq 'merge') { '可以使用同一快照支撑综合判断' } else { '缺失维度不得推断通过,需要补证或重跑' }
|
||||
},
|
||||
[pscustomobject][ordered]@{
|
||||
aspect = '跨专项结论一致性'
|
||||
conclusion = '五个专项结论已按职责和门禁优先级收敛'
|
||||
decision = if ($AllComplete) { 'merge' } else { 'observe' }
|
||||
fact = "阶段决策为:$stageStates;不同专项的 merge、reorder 或 action_required 代表不同决策对象,不自动视为冲突"
|
||||
basis = '比较五阶段 decision、finding 关联和集成门禁优先级'
|
||||
evidence = $evidenceSample
|
||||
impact = '无法解释的结论冲突必须阻止最终合并建议'
|
||||
},
|
||||
[pscustomobject][ordered]@{
|
||||
aspect = '风险传播与门禁对齐'
|
||||
conclusion = if ($Decision -eq 'merge') { '专项风险未形成合并阻断' } else { '专项风险已传递到最终门禁' }
|
||||
decision = $Decision
|
||||
fact = "当前阻断 $($Counts.blocking) 项、高风险 $($Counts.high) 项,安全门禁 $SecurityGate,最终决策 $Decision"
|
||||
basis = '按 blocking、安全失败、集成器、拓扑顺序和维护 HOT 动作计算'
|
||||
evidence = $evidenceSample
|
||||
impact = '高优先级技术风险不能被维护排序或正向价值结论覆盖'
|
||||
},
|
||||
[pscustomobject][ordered]@{
|
||||
aspect = '动作去重与责任归属'
|
||||
conclusion = if (@($Actions).Count -eq 0) { '当前没有需要立即执行的跨专项动作' } else { "已收敛为 $(@($Actions).Count) 项跨专项动作" }
|
||||
decision = if (@($Actions).Count -eq 0) { 'merge' } else { 'action_required' }
|
||||
fact = "动作按对象、内容和责任方去重;责任不明确 $missingOwners 项"
|
||||
basis = '汇总五阶段 top_actions,并按严重性、责任方和动作内容排序'
|
||||
evidence = $evidenceSample
|
||||
impact = '维护者可以按统一责任链处理,不必在五份报告间重复查找'
|
||||
},
|
||||
[pscustomobject][ordered]@{
|
||||
aspect = '决策置信度'
|
||||
conclusion = "当前综合决策置信度为$confidence"
|
||||
decision = if ($confidence -eq '高') { 'merge' } else { 'observe' }
|
||||
fact = "置信度由阶段覆盖、验证完整性、安全门禁和限制数量共同决定;最终决策为 $Decision"
|
||||
basis = '不以单一测试通过或单个专项结论替代完整证据覆盖'
|
||||
evidence = $evidenceSample
|
||||
impact = if ($confidence -eq '高') { '可将综合结论作为维护者决策依据' } else { '维护者应先处理限制和未验证项' }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function New-FinalReport {
|
||||
param([string]$Path)
|
||||
$run = Read-JsonFile (Join-Path $Path 'run.json')
|
||||
|
|
@ -298,7 +428,7 @@ function New-FinalReport {
|
|||
$artifact = $artifacts[$entry.Key]
|
||||
if ($null -eq $artifact) {
|
||||
$allComplete = $false
|
||||
$summaries.Add([ordered]@{ producer = $entry.Key; status = 'not_run'; decision = 'blocked'; security_gate = 'not_run'; verification = 'not_run'; finding_count = 0; blocking_count = 0; high_count = 0; top_action_count = 0 })
|
||||
$summaries.Add([ordered]@{ producer = $entry.Key; status = 'not_run'; decision = 'blocked'; security_gate = 'not_run'; verification = 'not_run'; finding_count = 0; blocking_count = 0; high_count = 0; top_action_count = 0; conclusion = '阶段未运行'; focus = '缺少专项结果'; basis = '运行目录中没有对应阶段 JSON'; evidence = @(); dimensions = @(Get-StageDimensions -Producer $entry.Key -Artifact $null) })
|
||||
$limitations.Add("缺少阶段结果:$($entry.Key)")
|
||||
continue
|
||||
}
|
||||
|
|
@ -343,6 +473,7 @@ function New-FinalReport {
|
|||
$findingArray = [object[]]$findings
|
||||
$evidenceArray = [object[]]$evidence
|
||||
$limitationArray = Get-UniqueStrings $limitations
|
||||
$orchestratorDimensions = New-OrchestratorDimensions -AllComplete $allComplete -Summaries $stageArray -Actions ([object[]]$actions) -Counts $counts -SecurityGate $securityGate -Verification $verification -Decision $decision -Limitations $limitationArray -Evidence $evidenceArray
|
||||
$report = [ordered]@{
|
||||
schema_version = '1.0'
|
||||
producer = 'gitlink-maintenance-orchestrator'
|
||||
|
|
@ -355,6 +486,7 @@ function New-FinalReport {
|
|||
scope = $scope
|
||||
run = $run
|
||||
stages = $stageArray
|
||||
orchestrator_dimensions = @($orchestratorDimensions)
|
||||
top_actions = @($topActions)
|
||||
findings = $findingArray
|
||||
evidence = $evidenceArray
|
||||
|
|
@ -454,7 +586,19 @@ function Write-MarkdownReport {
|
|||
$aspect = Get-StageAspect ([string]$stage.producer)
|
||||
$impact = Get-DecisionImpact ([string]$stage.decision)
|
||||
$evidenceText = Resolve-EvidenceText -EvidenceValues @($stage.evidence) -EvidenceIndex $evidenceIndex -FindingIndex $findingIndex
|
||||
$lines.Add("**${aspect}:** $(Get-ConclusionLabel ([string]$stage.conclusion) ([string]$stage.decision)):$($stage.focus);依据:$($stage.basis);证据摘录:$evidenceText;影响:$impact。")
|
||||
$lines.Add('')
|
||||
$lines.Add("### $aspect")
|
||||
$lines.Add("**专项总评:** $(Get-ConclusionLabel ([string]$stage.conclusion) ([string]$stage.decision)):$($stage.focus);依据:$($stage.basis);证据摘录:$evidenceText;影响:$impact。")
|
||||
foreach ($dimension in @($stage.dimensions)) {
|
||||
$dimensionEvidence = Resolve-EvidenceText -EvidenceValues @($dimension.evidence) -EvidenceIndex $evidenceIndex -FindingIndex $findingIndex
|
||||
$lines.Add("**$($dimension.aspect):** $(Get-ConclusionLabel ([string]$dimension.conclusion) ([string]$dimension.decision)):$($dimension.fact);依据:$($dimension.basis);证据摘录:$dimensionEvidence;影响:$($dimension.impact)。")
|
||||
}
|
||||
}
|
||||
$lines.Add('')
|
||||
$lines.Add('### 编排器综合判断')
|
||||
foreach ($dimension in @($Report.orchestrator_dimensions)) {
|
||||
$dimensionEvidence = Resolve-EvidenceText -EvidenceValues @($dimension.evidence) -EvidenceIndex $evidenceIndex -FindingIndex $findingIndex
|
||||
$lines.Add("**$($dimension.aspect):** $(Get-ConclusionLabel ([string]$dimension.conclusion) ([string]$dimension.decision)):$($dimension.fact);依据:$($dimension.basis);证据摘录:$dimensionEvidence;影响:$($dimension.impact)。")
|
||||
}
|
||||
$finalReason = if (@($Report.top_actions).Count -gt 0) {
|
||||
[string]$Report.top_actions[0].action
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ try {
|
|||
$decisionPattern = '<strong>[^<]+</strong></span> \*\*\[(merge|action_required|reorder|observe|blocked)\]\*\*'
|
||||
$decisions = [regex]::Matches($content, $decisionPattern)
|
||||
$actionsIndex = $content.IndexOf('1. **[')
|
||||
if ($decisions.Count -lt 6 -or $actionsIndex -lt 0 -or $decisions[5].Index -gt $actionsIndex) { throw 'final conclusion must appear after five stage decisions and before actions' }
|
||||
$preActionDecisions = @($decisions | Where-Object { $_.Index -lt $actionsIndex })
|
||||
if ($actionsIndex -lt 0 -or $preActionDecisions.Count -lt 33) { throw 'comprehensive dimensions and final conclusion must appear before actions' }
|
||||
|
||||
& python -X utf8 $orchestratorPromptTests | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) { throw 'orchestrator prompt contract tests failed' }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ def test_chat_summary_requires_agent_synthesis() -> None:
|
|||
"重新提炼",
|
||||
"不能复制报告首屏",
|
||||
"不能机械删除 Markdown/HTML 格式",
|
||||
"每个方面一至两句完整自然语言",
|
||||
"15 项直接判断",
|
||||
"每项一至两句",
|
||||
"可点击链接或当前 Agent 平台的文件附件",
|
||||
]
|
||||
missing = [marker for marker in required_markers if marker not in content]
|
||||
|
|
@ -25,6 +26,6 @@ def test_chat_summary_requires_agent_synthesis() -> None:
|
|||
|
||||
def test_default_agent_prompt_requires_a_plain_summary() -> None:
|
||||
content = read_utf8(ROOT / "agents" / "openai.yaml")
|
||||
required_markers = ["重新提炼", "不复制报告卡片原文", "不输出 HTML/Markdown 展示标签"]
|
||||
required_markers = ["重新提炼", "15 项", "不复制报告卡片原文", "不输出 HTML/Markdown 展示标签"]
|
||||
missing = [marker for marker in required_markers if marker not in content]
|
||||
assert not missing, f"missing agent prompt markers: {missing}"
|
||||
|
|
|
|||
|
|
@ -2,21 +2,24 @@
|
|||
|
||||
import unittest
|
||||
|
||||
from validate_chinese_report import validate_report
|
||||
from validate_chinese_report import REQUIRED_ASPECTS, REQUIRED_GROUPS, validate_report
|
||||
|
||||
|
||||
class ChineseReportValidatorTests(unittest.TestCase):
|
||||
def test_accepts_complete_chinese_report(self) -> None:
|
||||
report = """# PR 维护全流程摘要
|
||||
groups = "\n".join(REQUIRED_GROUPS)
|
||||
cards = "\n".join(
|
||||
f"**{aspect}:** <span><strong>证据支持当前判断</strong></span> "
|
||||
f"**[observe]**:已完成 {aspect} 的专项分析;依据:当前 Diff、测试和只读平台快照;"
|
||||
"证据摘录:目标提交和验证命令均已记录;影响:维护者可据此决定下一步。"
|
||||
for aspect in REQUIRED_ASPECTS
|
||||
)
|
||||
report = f"""# PR 维护全流程摘要
|
||||
**范围:** Gitlink/gitlink-cli
|
||||
**风险:** 阻断 1 项,高风险 2 项,以下内容用于帮助维护者快速确认处理顺序和责任人。
|
||||
## PR #123
|
||||
**代码审查:** <span><strong>需要修改</strong></span> **[action_required]**:失败路径缺少覆盖;依据:当前 Diff 与专项测试;证据摘录:无权限测试未覆盖,来源:`shortcuts/example/example_test.go:42`;下一步:补回归测试。
|
||||
**CLI 契约:** <span><strong>兼容性部分成立</strong></span> **[partial]**:旧调用正常但 JSON 缺边界;依据:帮助和输出对照;证据摘录:`--help` 可用但 JSON golden 缺少非法参数样例;下一步:补 golden。
|
||||
**仓库关系:** <span><strong>需要调整顺序</strong></span> **[reorder]**:目标消费上游字段;依据:主线、open 和 merged 索引;证据摘录:open PR #124 修改同一字段;影响:先稳定上游。
|
||||
**集成门禁:** <span><strong>当前被阻断</strong></span> **[blocked]**:关键测试未完成;依据:合并态和验证账本;证据摘录:`go test ./...` 尚未在合并工作树执行;下一步:补测试。
|
||||
**维护状态:** <span><strong>需要维护者接单</strong></span> **[action_required]**:责任方尚未确认;依据:时间和分配快照;证据摘录:队列快照中的 reviewer 与 assignee 均为空;下一步:安排 reviewer。
|
||||
**最终结论:** <span><strong>修复阻断问题后重新审查</strong></span> **[blocked]**:存在未解决高风险项;依据:CR-001 与 IN-001;证据摘录:失败路径缺测试且全量验证未运行;下一步:修复并重跑。
|
||||
{groups}
|
||||
{cards}
|
||||
## 先处理这几项
|
||||
先修复真实响应错误,再补充测试,然后重新执行完整验证并由维护者复看。
|
||||
## 五个专项状态索引
|
||||
|
|
|
|||
|
|
@ -20,12 +20,47 @@ REQUIRED_MARKERS = (
|
|||
"## 完整证据与限制",
|
||||
"## 证据台账",
|
||||
)
|
||||
REQUIRED_GROUPS = (
|
||||
"### 代码审查",
|
||||
"### CLI 契约",
|
||||
"### 仓库关系",
|
||||
"### 集成门禁",
|
||||
"### 维护状态",
|
||||
"### 编排器综合判断",
|
||||
)
|
||||
REQUIRED_ASPECTS = (
|
||||
"代码审查",
|
||||
"CLI 契约",
|
||||
"仓库关系",
|
||||
"集成门禁",
|
||||
"维护状态",
|
||||
"贡献价值",
|
||||
"Review 履约",
|
||||
"逻辑正确性",
|
||||
"代码质量与可维护性",
|
||||
"测试覆盖",
|
||||
"安全与性能",
|
||||
"参数与帮助",
|
||||
"JSON 与文本输出",
|
||||
"错误与退出码",
|
||||
"编码与颜色",
|
||||
"兼容与文档",
|
||||
"对当前主线",
|
||||
"对 open 队列",
|
||||
"对 merged 历史",
|
||||
"完整性比较",
|
||||
"依赖与处理顺序",
|
||||
"合并态与冲突",
|
||||
"构建",
|
||||
"测试与功能一致性",
|
||||
"CI 与证据关联",
|
||||
"安全与发布影响",
|
||||
"集成结论",
|
||||
"响应 SLA",
|
||||
"当前等待方",
|
||||
"Reviewer 负载",
|
||||
"责任停滞",
|
||||
"安全与 Issue 优先级",
|
||||
"证据完整性与新鲜度",
|
||||
"跨专项结论一致性",
|
||||
"风险传播与门禁对齐",
|
||||
"动作去重与责任归属",
|
||||
"决策置信度",
|
||||
"最终结论",
|
||||
)
|
||||
FORBIDDEN_ENGLISH_TEMPLATES = (
|
||||
|
|
@ -74,10 +109,16 @@ def validate_report(text: str, required_prs: list[int] | None = None) -> list[st
|
|||
continue
|
||||
next_heading = PR_HEADING.search(text, start + 1)
|
||||
end = next_heading.start() if next_heading else len(text)
|
||||
cards = CARD_PATTERN.findall(text[start:end])
|
||||
section = text[start:end]
|
||||
for group in REQUIRED_GROUPS:
|
||||
if group not in section:
|
||||
errors.append(f"PR #{number} is missing assessment group: {group}")
|
||||
cards = CARD_PATTERN.findall(section)
|
||||
aspects = {card[0] for card in cards}
|
||||
if len(cards) < len(REQUIRED_ASPECTS):
|
||||
errors.append(f"PR #{number} has {len(cards)} judgment cards, need 6")
|
||||
errors.append(
|
||||
f"PR #{number} has {len(cards)} judgment cards, need {len(REQUIRED_ASPECTS)}"
|
||||
)
|
||||
for aspect in REQUIRED_ASPECTS:
|
||||
if aspect not in aspects:
|
||||
errors.append(f"PR #{number} is missing aspect card: {aspect}")
|
||||
|
|
|
|||
Loading…
Reference in New Issue