decision-page-skill · 证据驱动的交互决策页
使用零依赖 Python 服务与单文件 HTML,把“调研 → 理解 → 拍板 → 回填执行”做成可审计的本地流程。服务只绑定 127.0.0.1,与具体智能体或 CLI 无关。
硬性门槛
- 先调研,后请求决策。 不得先让用户在信息不足的空壳选项中选择,再事后补证据。
- 让页面自洽。 用户不打开外部文档,也应能理解为何要决策、各方案的收益和代价、推荐成立的前提、尚存的不确定性。
- 验证理解,不只要求“已阅读”。 每项至少设置一道针对关键事实或取舍的理解题;答对后才解锁选项。不得把“是否同意推荐方案”当作理解题。
- 如实标注证据边界。 区分已验证事实、推断和未知;不得伪造来源或用来源数量替代证据质量。
- 使用实际 CLI 名称。 页面名称由运行时自动探测或
--agent-name显式传入;不得在模板中写死某个智能体品牌。
工作流
1. 完成调研门槛
先收集每项决策真正需要的信息:
- 检查项目中的源码、配置、日志、计划、约束和已有决策,确认实际现状而非只依赖用户的一句话描述。
- 对可能变化、自己不确定或风险较高的事实,查询当前的一手或权威来源;记录可追溯的文件路径、文档章节或 URL,以及核对日期。
- 比较 2–4 个互斥且覆盖合理路径的选项。逐项写明收益、代价或风险、依赖、可逆性以及不适用条件。
- 给出一个明确推荐,同时写清推荐成立的前提;将影响选择但尚未验证的内容列入
uncertainties。
仅当用户能从页面回答以下问题时,才算“信息充分”:为什么现在必须决策;每个方案得到什么、牺牲什么;推荐基于哪些约束;什么新事实会改变推荐;仍有哪些未知。如果关键未知足以使比较失真,继续调研或先向用户说明阻塞,不得要求拍板。
2. 放置模板
把 templates/decide.py 与 templates/decisions.html 复制到项目内同一目录:
- Git 仓库:优先放在
docs/decisions/或项目既有治理目录,并遵守分支、评审和提交规范。 - 非仓库场景:放在任务工作目录。
数据文件默认与脚本同目录,也可统一用 --dir <数据目录> 指定。
3. 生成并校验 decisions.json
使用 v2 数据契约。下面是一项决策的最小结构;需要完整范例时读取 examples/demo/decisions.json:
{
"schemaVersion": 2,
"title": "项目名",
"subtitle": "本批决策的共同背景",
"decisions": [
{
"id": "D1",
"title": "一句话标题",
"doc": "相关本地文档(可选)",
"background": "现状、约束与为什么现在需要决策。",
"research": {
"summary": "调研后的综合判断。",
"checkedAt": "YYYY-MM-DD",
"evidence": [
{
"finding": "已验证的结论",
"impact": "它如何影响本次选择",
"source": "本地路径、文档章节或 URL"
}
],
"uncertainties": ["仍未验证但可能改变选择的事项"]
},
"recommendationReason": "推荐方案、成立前提,以及何时应改选。",
"allowCustom": true,
"options": [
{
"key": "A",
"label": "方案 A",
"desc": "一句话定位",
"benefits": ["主要收益"],
"costs": ["主要代价或风险"],
"recommended": true
},
{
"key": "B",
"label": "方案 B",
"desc": "一句话定位",
"benefits": ["主要收益"],
"costs": ["主要代价或风险"]
}
],
"understandingChecks": [
{
"id": "U1",
"question": "哪项事实最可能改变当前推荐?",
"options": [
{"key": "A", "label": "事实 A"},
{"key": "B", "label": "事实 B"}
],
"answer": "B",
"explanation": "解释关键取舍;答错时帮助用户重新理解,而不是只判错。"
}
],
"status": "open"
}
]
}
保持以下质量要求:
- 每项恰好一个
recommended: true,并用recommendationReason说明理由和前提。 evidence每条同时包含结论、决策影响和来源;checkedAt反映本次实际核对日期。uncertainties可以为空,但只能在认真检查后留空;不得用空数组隐藏未知。- 理解题检查关键事实、风险或推荐前提,答案必须能从页面调研信息中推出。高风险、难逆转或信息密集的决策应设置多道题。
- 选项应互斥并覆盖合理路径;自定义选项不等于可以省略明显方案。
生成后必须先运行:
python3 <目录>/decide.py validate --dir <数据目录>
校验不通过时修复所有问题,不得把未通过的页面交给用户。
4. 启动并核对运行时身份
在后台启动服务:
python3 <目录>/decide.py --dir <数据目录>
# 可选:--port N、--no-browser、--idle-timeout N
服务会从父进程和环境变量探测当前 CLI,并打印 当前 CLI:<名称>。发送页面地址前核对该名称;若探测错误或回退为“智能体”,使用实际 CLI 的显示名称重启:
python3 <目录>/decide.py --dir <数据目录> --agent-name "<当前 CLI 名称>"
# 也可设置 DECISION_PAGE_AGENT_NAME
不要把示例中的某个品牌复制为默认值。页面从 /api/state.runtime.agentName 读取名称并同步更新标题、聊天状态和通知文案。
服务默认打开 http://127.0.0.1:8765。它只监听本机;不要改为 0.0.0.0。默认在页面关闭且无请求 3600 秒后退出,--idle-timeout 0 可关闭自动退出。
5. 值守提问与保存事件
使用当前 CLI 可用的后台或流式执行能力运行:
python3 <目录>/decide.py watch --dir <数据目录>
如不便常驻,则在继续工作的间隙周期调用:
python3 <目录>/decide.py poll --dir <数据目录>
事件格式为 QUESTION #<id>: ... 或 SAVED: ...,游标保存在数据目录的 .decide-watch.json,默认只消费新增事件。
收到 QUESTION 后:
- 读取
chat.jsonl获取完整上下文。 - 先回答已有证据能支持的部分;若问题暴露信息缺口,继续调研,不得凭印象补全。
- 如证据、推荐、选项或理解题发生变化,编辑
decisions.json并重新运行validate。页面会热更新并清除旧版本的选择和理解状态;已经保存的旧结论也会标为失效并要求重新确认。 - 用 stdin 方式回复,避免 shell 引号问题:
python3 <目录>/decide.py reply - --dir <数据目录> <<'EOF'
回答内容;支持 **加粗**、`代码`、列表和代码块。
EOF
回复要及时、具体,并说明新增证据是否改变推荐。不得为了让用户尽快选择而弱化风险或未知。
收到 SAVED 后进入下一步。服务端会再次校验资料版本、选项和理解答案,不信任浏览器传来的展示文本;过期资料无法保存。
6. 回填并执行
- 读取
decisions-log.md最新的<!-- 待智能体回填 -->条目。 - 核对其中的选择、调研日期、资料版本和理解确认记录。
- 将结论回填到项目的决策表、计划或待办,解锁对应工作。
- 把注释原地改为
已回填(日期),再按结论执行。
watch/poll 只按新增 ## 日志条目触发;原地修改回填标记不会重放历史。
7. 收尾
决策完成后停止 watch 或轮询,结束后台 decide.py 服务,并确认所有日志条目已回填。保留 decisions.json 的 status: "decided" 与 result;后续更新文件时不得覆盖已有结果。
文件契约与注意事项
| 文件 | 写入方 | 作用 |
|---|---|---|
decisions.json |
当前智能体 | 调研、选项、理解题与决策状态;修改即热更新 |
chat.jsonl |
页面写 user;reply 写 assistant |
浏览器与值守会话的消息通道;不要手工伪造 user 行 |
decisions-log.md |
页面保存接口追加 | 跨会话持久契约,应纳入项目治理记录 |
- 所有子命令都接受
--dir <数据目录>,服务、值守、回复和校验必须指向同一目录。 - 页面不能通过
file://直接使用,必须由decide.py提供服务。 - 决策资料变更会产生新版本摘要;浏览器会清除旧理解状态、使基于旧资料的已保存结论失效,服务端也会拒绝旧版本提交。
- 简单单项、低风险二选一可直接对话确认;一旦累计多项或需要背景比较,必须使用本技能的页面和调研门槛。