Skill: Change Writer
SkillDocs & knowledgeWrite change proposals with impact analysis following OpenLogos delta workflow. Use when the project lifecycle is active and source code or methodology documents need modification.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Skill: Change Writer skill
What this skill tells your AI
The instructions your AI receives, as published by miniidealab/openlogos in skills/change-writer/SKILL.md and read by ahel’s review.
辅助填写变更提案——分析变更影响范围,生成结构化的 proposal.md 和按阶段拆解的 tasks.md,确保变更可追溯、影响可控。
触发条件
- 用户刚运行完
openlogos change <slug>并希望 AI 帮忙填写提案 - 用户描述需要修改、新增或删除某个场景/功能
- 用户提到"变更提案"、"change proposal"、"迭代"、"改需求"
前置依赖
- 项目已初始化(
logos/logos.config.json存在) - 变更提案目录已由 CLI 创建(
logos/changes/<slug>/存在) - 主文档可读(
logos/resources/中有已生效的文档)
如果前置条件不满足,提示用户先运行 openlogos change <slug> 创建提案目录。
核心能力
- 理解用户描述的变更意图
- 扫描
logos/resources/中的现有文档,定位受影响范围 - 根据变更传播规则判断变更类型(需求级 / 设计级 / 接口级 / 部署级 / 代码级)
- 判断本次变更是否需要部署、是否需要数据迁移、是否需要 smoke 验证
- 生成符合规范的 proposal.md
- 按变更类型自动拆解 tasks.md
执行步骤
Step 1: 理解变更意图
与用户确认以下信息(信息不足则追问,最多 2 轮):
- 变更是什么:要新增、修改还是删除什么?
- 变更原因:为什么要做这个变更?来自需求反馈、Bug 还是优化?
- 关联场景:涉及哪些已有场景编号(S01, S02...)?
Step 2: 分析影响范围
扫描 logos/resources/ 中的文档,确定影响范围:
- 读取需求文档(
prd/1-product-requirements/),检查相关场景定义 - 读取产品设计(
prd/2-product-design/),检查相关功能规格和原型 - 读取技术方案(
prd/3-technical-plan/),检查相关架构、时序图、部署方案 - 读取 API 文档(
api/),检查相关端点 - 读取 DB 文档(
database/),检查相关表结构 - 读取编排测试(
scenario/),检查相关测试用例 - 读取 smoke 测试用例(
test/smoke/),检查部署后冒烟覆盖是否需要更新
Step 3: 判断变更类型
参照变更传播规则确定变更类型及最小更新范围:
| 变更类型 | 最少需要更新 |
|---|---|
| 需求级变更 | 全链路(需求 → 设计 → 架构 → 部署 → API/DB → 测试 → 编排 → 代码) |
| 设计级变更 | 原型 + 场景 + API/DB + 测试/编排 + 代码 + 部署影响分析 |
| 接口级变更 | API/DB + 编排 + 代码 + 部署影响分析 |
| 部署级变更 | 部署方案 + smoke 用例 + [deploy] 任务 |
| 代码级修复 | 代码 + 重新验收 + 部署影响分析 |
Step 4: 生成 proposal.md
按以下模板生成,写入 logos/changes/<slug>/proposal.md:
# 变更提案:[变更名称]
## 变更原因
[为什么要做这个变更?来源于哪个需求/反馈/Bug?]
## 变更类型
[需求级 / 设计级 / 接口级 / 部署级 / 代码级]
## 变更范围
- 影响的需求文档:[列表,精确到文件名和章节]
- 影响的功能规格:[列表]
- 影响的业务场景:[场景编号列表]
- 影响的部署方案:[列表]
- 影响的 API:[端点列表]
- 影响的 DB 表:[表名列表]
- 影响的编排测试:[列表]
- 影响的 smoke 测试:[列表]
## 部署影响
- 是否需要部署:是 / 否
- 部署原因:[说明为什么需要或不需要部署]
- 影响环境:[本地 / 测试 / 预发 / 生产 / 无]
- 是否涉及数据迁移:是 / 否
- 是否需要回滚预案:是 / 否
- 是否需要 smoke:是 / 否
## 变更概述
[用 1-3 段话概述具体改什么]
生成 proposal.md 后必须先保留部署决策结论,Step 5 生成 tasks.md 时必须与该结论一致。
Step 5: 生成 tasks.md
根据变更类型和影响范围,使用结构化 section 格式生成任务清单。完整格式规范见 spec/tasks-spec.md。
禁止在 tasks.md 中写入 verify / smoke / 人工验证类条目——这些属于独立 CLI 操作节点。tasks.md 只追踪 delta、代码和部署执行任务。
⛔ 严禁在
write-tasks阶段规划或填写[code]切片(enforce-slice-stage-ordering / split-slice-planner-stage):write-tasks节点只产## [delta]/## [deploy]。## [code]切片由独立环节slice-planner在 merge / no-delta spec-complete 之后、对已定稿规格 + 真实测试 ID 划分(见skills/slice-planner/SKILL.md)。即使某些切片此刻看起来"显而易见",也绝不在此处写任何[code]条目——提前填充会被 CLI 在openlogos merge进入 spec-complete 前自动清理作废:把[code]重置为占位并把旧内容备份到提案目录CODE_AUTORESET(可追溯、非无痕删除,见spec/flow-spec.md§12.7)。清理不阻断流程、无人值守自愈,但你提前划的切片一律作废——因为它是对未定稿规格 + 占位测试 ID 划的,信息不全必然切错。本步骤只保留空## [code]标题(切片项不在 plan 段填写,由 spec-complete 后 slice-planner 划分);下方模板中的[code]块仅示意最终形态。⚠️
## [code]标题行必须保留(fix-nodelta-proposal-routing):write-tasks产出的tasks.md至少要含一个## [tag]section 标题,否则parseTaskSections返回null、派生降级为「旧格式兜底」而误判为delta-writing(把纯代码提案错误派到write-delta节点、无人值守下死锁)。因此:有[delta]的提案[code]标题可留空或省略(已有[delta]标题);无[delta]的纯代码提案必须写出空的## [code]标题行(标题在、条目空,由 no-deltaSPEC_MERGED后的 slice-planner 填切片)。
格式规则:
## [delta] <描述>section:只列 delta 文档产出任务,每条对应一个 delta 文件## [code] <描述>section:launched 变更下不在 plan 段填写,由 merge 后的slice-planner产出;只列代码实现任务,直接修改源文件,不产出 delta## [deploy] <描述>section:只列部署执行任务,只能在 verify PASS 后、人类明确确认后执行- 不需要部署的提案不得创建
[deploy]section - 需要部署的提案必须创建
[deploy]section - 需要部署的提案必须在
[delta]section 中包含部署方案和 smoke 用例变更(如受影响) - 严禁混用:delta 任务不得写入
[code]section,代码任务不得写入[delta]section
部署决策一致性自检(强制):
生成 proposal.md 和 tasks.md 后,必须逐项检查:
| 检查项 | 合法状态 |
|---|---|
proposal.md 声明 是否需要部署:否 | tasks.md 不存在 [deploy] section |
proposal.md 声明 是否需要部署:是 | tasks.md 必须存在 [deploy] section |
proposal.md 声明 是否需要 smoke:是 | proposal.md 必须同时声明 是否需要部署:是 |
proposal.md 声明无需部署 | 不得在 [code] 或 [delta] 中写部署执行任务 |
若自检失败,必须先修正 proposal.md 或 tasks.md,不得继续产出 delta。
需要部署的变更模板([code] 块示意,merge 后由 slice-planner 填写):
# 实现任务
## [delta] 规格变更
- [ ] 产出 delta 文件到 `deltas/prd/3-technical-plan/3-deployment/` — 更新部署方案
- [ ] 产出 delta 文件到 `deltas/test/smoke/` — 更新部署后冒烟测试用例
## [deploy] 部署任务
- [ ] 按部署方案部署到 staging
- [ ] 确认迁移、配置、服务启动和回滚预案
需求级 / 设计级变更模板(有 delta + 有代码;[code] 由 merge 后 slice-planner 填写):
# 实现任务
## [delta] 规格变更
- [ ] 产出 delta 文件到 `deltas/prd/1-product-requirements/` — 更新需求文档中 S0x 的验收条件
- [ ] 产出 delta 文件到 `deltas/prd/1-product-requirements/` — 在场景总览表中新增/修改场景
- [ ] 产出 delta 文件到 `deltas/prd/2-product-design/1-feature-specs/` — 更新功能规格中 S0x 的交互设计
- [ ] 产出 delta 文件到 `deltas/prd/2-product-design/2-page-design/` — 更新原型
- [ ] 产出 delta 文件到 `deltas/prd/3-technical-plan/1-architecture/` — 更新技术架构
- [ ] 产出 delta 文件到 `deltas/prd/3-technical-plan/2-scenario-implementation/` — 更新 S0x 的时序图
- [ ] 产出 delta 文件到 `deltas/api/` — 更新 API YAML
- [ ] **验证 API YAML** — `logos/resources/api/` 下所有文件必须为有效 YAML 且符合 OpenAPI 3.x 规范(所有包含 `:` 或特殊字符的 `description`/`summary` 值必须用双引号包裹)
- [ ] 产出 delta 文件到 `deltas/database/` — 更新 DB DDL
- [ ] 产出 delta 文件到 `deltas/scenario/` — 更新编排测试用例
纯代码修复模板(无 delta;保留空 ## [code] 标题,切片由 no-delta merge 后 slice-planner 填写):
# 实现任务
## [code] 代码实现
(本段在 plan 段留空:无 `[delta]` 时不进入 `write-delta`,但仍需执行 no-delta `openlogos merge <slug>` 写入 `SPEC_MERGED`,表示 spec-complete 已完成;随后由 `slice-planner` 基于已完成 spec-complete 的规格与真实测试 ID 划分 `[code]` 切片。此处仅保留 `## [code]` 标题,勿提前填写切片项。)
为什么保留空
## [code]并仍需 no-delta merge:## [code]标题用于表达code_required==true与后续切片承载区;no-deltaSPEC_MERGED用于表达“规格阶段已完成且本次无文档 delta”。两者缺一不可。change-writer不得把无[delta]解释为可直接进入plan-slices,也不得提前填写[code]切片。
有 delta 的代码必需提案也必须保留 [code] 标题(fix-missing-code-section-slice-gate):
在 split-slice-planner-stage 下,change-writer 仍然严禁在 plan 段填写 [code] 切片条目;但“保留空 ## [code] 标题”和“提前填写切片条目”是两件不同的事。
- 凡 proposal / 用户描述 / delta 任务表明后续需要代码实现,
tasks.md必须保留空## [code] 代码实现标题。 - 该规则同时适用于有
[delta]的代码级提案和无[delta]的纯代码提案。 - 如果
[delta]会新增或修改UT-*/ST-*/SMOKE-*测试用例,且这些用例需要业务代码、测试代码、runner、reporter 或 golden 落地,则必须保留空## [code]标题。 ## [code]标题下只能写占位说明,不得写任何- [ ]切片任务;真实切片由 merge 后slice-planner统一填写。
推荐占位:
## [code] 代码实现
(本段在 plan 段留空:本提案需要代码实现,但 `[code]` 切片由 merge 后的 `slice-planner` 基于已合并规格和真实 UT/ST ID 统一规划。此处仅保留 `## [code]` 标题,勿提前填写切片项。)
缺失 ## [code] 标题会让后续状态派生失去“需要切片”的结构锚点。在有 [delta] 且新增测试规格的代码级提案中,缺失标题不得被下游解释为“无需代码”;但 change-writer 必须从产物源头减少这种异常态。若不确定是否需要代码,优先保留空 ## [code] 标题,让 merge 后的 slice-planner 基于已合并规格和真实测试 ID 作最终规划。
Step 5 补充:[code] 良构切片(已迁至 slice-planner)
split-slice-planner-stage 起,
[code]切片划分整体迁出 change-writer,由独立环节slice-planner在 merge 之后决定(见skills/slice-planner/SKILL.md)。原"六维打分 + 良构切片"规则连同新增的"垂直/横向判别器"和"删后续证伪门"全部归 slice-planner 维护,是 launched 变更下[code]切片的唯一事实源。
为什么迁出:切片在 plan 段(merge 前)产出,会对未合并规格 + 占位测试 ID划分,信息不全易切错(实测曾切成横向分层)。挪到 merge 后,slice-planner 对已合并规格 + 真实 UT/ST ID切,并以删后续证伪门强制每片自闭环。
change-writer 在 launched 下不再产出、不再打分、不再划分 [code] 切片。
Step 6: 产出 Delta 文件
触发时机:tasks.md 填写完成、用户确认提案后,按 [delta] section 的任务清单逐项产出 delta 文件。
重要:只执行 [delta] section 中的任务。[code] section 的任务在规格合并(SPEC_MERGED)后才开始执行。
目录映射
Delta 文件写入 logos/changes/<slug>/deltas/ 下对应子目录,与合并目标一一对应:
| 目标目录 | Delta 子目录 |
|---|---|
logos/resources/prd/ | deltas/prd/ |
logos/resources/api/ | deltas/api/ |
logos/resources/database/ | deltas/database/ |
logos/resources/scenario/ | deltas/scenario/ |
logos/resources/test/ | deltas/test/ |
项目根 spec/(方法论规范,权威) | deltas/spec/ |
项目根 skills/(Skill 文档,权威) | deltas/skills/ |
根权威 → dogfood 副本为单向同步:
deltas/spec/与deltas/skills/的合并目标是项目根spec/、skills/;logos/spec/、logos/skills/是 merge 后由既有同步机制再生成的副本,不得作为 delta 直接目标。该映射与 CLIDELTA_TO_RESOURCE常量保持一致(一致性由回归测试锚定)。
prd/ 下按子目录进一步对应:
| 目标主文档子目录 | Delta 子目录 |
|---|---|
logos/resources/prd/1-product-requirements/ | deltas/prd/1-product-requirements/ |
logos/resources/prd/2-product-design/1-feature-specs/ | deltas/prd/2-product-design/1-feature-specs/ |
logos/resources/prd/2-product-design/2-page-design/ | deltas/prd/2-product-design/2-page-design/ |
logos/resources/prd/3-technical-plan/1-architecture/ | deltas/prd/3-technical-plan/1-architecture/ |
logos/resources/prd/3-technical-plan/2-scenario-implementation/ | deltas/prd/3-technical-plan/2-scenario-implementation/ |
logos/resources/prd/3-technical-plan/3-deployment/ | deltas/prd/3-technical-plan/3-deployment/ |
logos/resources/test/smoke/ | deltas/test/smoke/ |
代码实现(src/、test/)不产出 delta,直接修改源文件。
部署相关行为规范:
- 需要部署时,必须产出部署方案 delta
- 需要部署且 smoke 覆盖受影响时,必须产出 smoke 测试用例 delta
- 不允许把部署执行命令写入
[code]section - 不允许 AI 在 delta-writing 阶段执行部署命令
文件命名
与目标主文档同名(含子目录层级)。例如:
- 目标:
logos/resources/api/core-api.yaml→ delta:deltas/api/core-api.yaml - 目标:
logos/resources/prd/1-product-requirements/core-01-requirements.md→ delta:deltas/prd/1-product-requirements/core-01-requirements.md - 目标:
logos/resources/test/core-S01-test-cases.md→ delta:deltas/test/core-S01-test-cases.md
文件格式
每个 delta 文件使用 ADDED / MODIFIED / REMOVED / REMOVED-ITEMS 标记,每个标记块对应主文档中的一个章节:
## ADDED — [新增章节标题]
[新增的完整内容]
## MODIFIED — [修改章节标题]
[修改后的完整内容,merge 时替换主文档中同名章节]
## REMOVED — [删除章节标题]
[说明删除原因,merge 时删除主文档中同名章节;建议列出该节 ID 供审计]
## REMOVED-ITEMS — [被删条目所在章节锚]
[纯声明性标记,merge 不据其执行编辑:逐行点名被删 ID]
守恒写作规范(S37,merge-conservation-archive-audit,强制):
-
MODIFIED 必须携带整节全量内容——它是整章节替换,不是"只写改动的部分"。凡目标章节内未变更的结构化条目(测试表 ID 行、场景表行、编号小节),必须原样抄入 MODIFIED 块的对应结构位置;漏抄 = 隐式删除,会被 change-lint L8 与
openlogos merge双侧拒绝。注意:仅在散文里提及 ID 不算保留——守恒按结构位置计数(测试表 ID 首列、场景标题/表行首列、标题行节号)。 -
删除整个章节用既有
REMOVED — <唯一章节锚>(语义不变,整节删除;该节 ID 随节显式删除)。 -
删除章节内部分条目必须成对写:
MODIFIED — <章节锚>携带删除后剩余的全量内容 +REMOVED-ITEMS — <同一章节锚>逐行点名被删 ID,固定语法:## MODIFIED — 四、smoke runner 覆盖强制规则发布后冒烟用例 > 二、冒烟测试用例补充 [该小节删除后剩余的全量内容] ## REMOVED-ITEMS — 四、smoke runner 覆盖强制规则发布后冒烟用例 > 二、冒烟测试用例补充 - SMOKE-core-31 — runner 覆盖检查项已由 SMOKE-core-51 取代REMOVED-ITEMS 是纯声明(merge 不据其编辑),点名 ID 必须属于锚定章节;只点名不配 MODIFIED、或点名别的章节的 ID,都会被拒绝。
-
章节锚必须唯一可定位:目标标题在主文档中重复时(如 smoke 规格中
二、冒烟测试用例补充出现 7 次),必须用标题路径锚父级标题 > 目标标题;锚解析不到或命中多个会被 fail-closed 拒绝(delta_section_anchor_unresolvable),不要指望工具猜。 -
产出 delta 前先读目标主文档被触及章节,抄录其全部既有结构化 ID 清单核对一遍——"合并后这些 ID 是否都有去处(结构位置保留 / REMOVED-ITEMS 点名 / 随整节 REMOVED 删除)"。
-
无稳定 ID 的散文改写不受机器门约束,但同样不得借 MODIFIED 顺手删除与本次变更无关的内容。
行为规范
- 每完成一个 delta 文件,立即将
tasks.md中对应条目从[ ]更新为[x] - 禁止直接修改
logos/resources/下的主文档——所有规格变更必须通过 delta 文件,由openlogos merge统一合并 - 全部 delta 产出完成后,提醒用户明确授权运行
openlogos merge <slug>
Step 6 补充:plan 门与 delta / no-delta spec-complete 时机
change-flow-redesign 把前段流程拆为 plan{写提案, 划分tasks} → spec{写delta 或 no-delta spec-complete} → merge/spec-complete,并在 plan 出口新增「批准方案」人类门。split-slice-planner-stage 起,[code] 切片划分移出 plan 门,改在 spec-complete 后 slice 段由 slice-planner 产出。
- 有
[delta]的提案:plan 门确认后,change-writer 只按[delta]section 产出 delta 文件;全部完成后提醒用户或 driver 执行openlogos merge <slug>。 - 无
[delta]的纯代码提案:change-writer 不产 delta;plan 门确认后,下一步是 no-deltaopenlogos merge <slug>写入SPEC_MERGED,再由slice-planner规划[code]。 - 任意代码提案:测试 ID 未稳定时不得进入
plan-slices,不得用占位 ID 预写切片。
Step 6 补充二:GUI 项目提案阶段前置 UI/UX 原型(proposal-ui-ux-first)
对已 launched 的 GUI 产品项目(网站 / 桌面应用 / 移动 App),当本次变更触及界面时,change-writer 在提案阶段(plan 节点、plan-exit 门前)就用 ui-ux-pro-max 设计系统产出界面原型,使用户在批准提案时(面板已渲染原型的前提下)连界面一起确认,避免「批准后自动实现才发现界面不对」的高成本返工。复用现有 plan-exit(批准方案)门——不新增门态、不新增确认标记、不新增 ui/ 目录。 非 GUI 项目(纯 CLI / API / 纯后端服务 / Skills)整个特性不启用,本节全部跳过、流程零改动。
本节只定义 change-writer 侧的 producer 产出职责与可交付要求;driver 在 plan 节点派发 change-writer 产原型(producer dispatch)、面板渲染原型、批准时写 provenance 均归 runlogos 关联 change
ui-ux-first-panel,本节不含其实现。
① 触发条件:先判 product_type,再判本次是否动界面(去循环依赖)
判定在 plan 阶段由 change-writer 执行,分两层,依据是「提案意图 + 已规划的 [delta] 目标」,而非扫描尚不存在的 delta 文件内容(plan 阶段无 delta 可扫,「先 delta 还是先原型」构成循环依赖,故不扫 delta 内容):
- 先判
product_type是否 ∈ GUI:从logos/logos-project.yaml的product_type/tech_stack读取。- ✅ GUI 类:Web 应用 / 移动应用 / 桌面应用(Electron / Tauri / SwiftUI / Jetpack Compose / Qt / WPF / GTK 等)/ 混合型中含 GUI 交付物的部分。
- ❌ 非 GUI 类:纯 CLI / Library / AI Skills / 纯 API 服务 / 纯后端服务(
service:常驻 worker / 定时循环任务 / 消息消费者等,无对外接口)—— 整节跳过、ui_impact恒为false、不注入声明段。
- 再判本次是否动界面(仅当
product_type ∈ GUI):- 依据 = 提案意图 +
tasks.md已规划的[delta]目标是否命中2-page-design/,或命中含交互变更的 feature-specs delta。命中即强制判为「动了界面」(ui_impact:true)。 - 窄例外(命中
2-page-design/时):仅当目标为页面原型产物(.html,或含pages声明)才强制ui_impact:true;若目标是纯 CLI 体验文本规格(.md且无pages声明),不强制ui_impact:true。 - 不扫描尚不存在的 delta 内容(去循环依赖)。
- 可选多 agent 复核默认关,可由 driver 派发。
- 依据 = 提案意图 +
判定容错优先流程平滑:作为增益功能,判错代价可控(顶多多画一次或退回重设),不追求绝对严谨。
② change-writer 作为 plan 节点 producer,被 driver 在 plan-exit 门前 dispatch 产原型
- 原型产出是 plan 节点门前的普通内容生成,授权状态与「写
proposal.md/tasks.md」完全相同——不新增授权、不新增门。唯一人类确认点仍是plan-exit。 - driver 在 plan 节点判定
ui_impact:true且前置能力就绪时,派发 change-writer(用 ui-ux-pro-max)在plan-exit前产出原型(producer dispatch)。这属既有 plan 节点执行范围,driver 实现归 runlogosui-ux-first-panel。 - change-writer 的写入由 guard 的 plan 阶段写入 allowlist(仅放行
deltas/prd/2-product-design/2-page-design/*.html) 授权;其余deltas/**在 plan 阶段仍禁止写入,越界路径被 guard 拒。 --auto下plan-exit(skippable:true)自动放行,但原型已在门前产出、provenance 已记录。
③ ui-ux-pro-max 生成步骤(调用设计系统)
复用 product-designer 的 Step 5a UI/UX 子流程(见 skills/product-designer/SKILL.md),在提案阶段前移使用:
- 从提案意图 + Phase 1 需求文档提取关键词:产品类型(SaaS / e-commerce / dashboard / portfolio 等)+ 行业 + 风格倾向。
- 调用
ui-ux-pro-max获取设计系统(风格 + 调色板 + 字体配对 + 登陆页模式 + 反模式清单),并落地design-system.json令牌(此为正常路径,置design_system_mode: generated):python3 logos/skills/ui-ux-pro-max/scripts/search.py "<product_type> <industry> <style_keywords>" --design-system -p "<项目名>" - 以设计系统为视觉基础,为结构化声明清单里的每个页面(每条
id/prototype)产出裸 HTML 原型(关键几屏 + 各交互状态:空态 / 加载 / 正常 / 错误 / 边界态)。
④ 可交付要求:声明清单 == 产出文件(F1 R5,逐页 + 非空 + 令牌)
「文件存在」只是弱收敛(文件可能为空、非 ui-ux-pro-max 产物、或声明多页只产一页)。change-writer 的可交付标准收紧为:
- 逐页非空:UI/UX 变更声明段声明的每一个页面(结构化清单中每条
id/prototype记录),都在deltas/prd/2-product-design/2-page-design/下有 basename 精确匹配的非空原型文件(不是「至少一个文件」)。 - 令牌追溯(仅
design_system_mode: generated):design_system_mode: generated时,提案目录logos/changes/<slug>/下留存合法非空design-system.json(ui-ux-pro-max 令牌),把每个原型系到设计系统。design_system_mode: fallback时不产 / 不要求design-system.json、禁伪造令牌(详见 ⑥)。 - 完整性判据(三方对账,按 basename 集合):(i)
proposal.md声明段ui_impact+ 结构化声明页清单(每条的prototypebasename);(ii)2-page-design/下实际产出的原型文件 basename;(iii) merge 落盘 / 面板渲染对象。声明清单 basename 集合 == 产出文件 basename 集合 为完整性判据(排序无关;重复 / 额外 / 缺失均失败);不一致 = 节点未收敛(advisory)。PLAN_APPROVED.pages/hashes复用同一 basename 键。 - 该可交付要求由 overlay-add 节点
write-ui-prototype的done_when: cmd:<check-ui-prototype>做富对账作为plan-exit前的机器收敛条件——命令exit 0节点才 done、plan 子流程才完成、plan-exit 门才可放行。checker 按design_system_mode分流:generated→ 合法非空design-system.json(令牌)+ 逐页非空 + 声明清单==产出文件(basename 集合一致)→exit 0;generated但无令牌 → fail closed。fallback→ 必须有非空design_system_fallback_reason(如「Python3 缺失」),禁伪造令牌、不要求design-system.json,逐页非空 + 清单一致即exit 0(不阻塞、plan-exit 可到达)。- 其它值 / 缺
design_system_mode字段 → fail closed。
- 残差(如实标注):「HTML 是否真出自 ui-ux-pro-max」除
design-system.json令牌可追溯外无法纯机器证明——这是既有 acceptance 口径下的荣誉制 + 令牌追溯限制,如实记录、非遗漏。
⑤ 原型作为 page-design delta 产出 + 填写声明段
- 原型路径:直接作为 page-design delta 写入
logos/changes/<slug>/deltas/prd/2-product-design/2-page-design/core-NN-<slug>.html(裸 HTML,可直接 iframe 渲染)。 - 不新增
ui/目录、复用现有 delta 路径映射(deltas/prd/** → resources/prd/**):面板已用readDir(deltas/**/*)列出可直接渲染。但原型资产的落盘不复用scanDeltas/merge-executor 的整份拷贝路径——所有ui_impact原型一律由openlogos merge内专用事务落盘入口commitVerifiedPrototypes()统一提交(严格模式对 staged 字节做 hash 校验 + 原子提交;advisory 模式同一入口、不做严格 hash 校验),merge-executor 绝不触碰原型资产、无第二条绕过路径。「复用路径映射」仅指无额外人工步骤,非「无新代码路径」。 - 填写声明段:在
proposal.md的「UI/UX 变更声明」段写入:ui_impact:布尔(本次是否触及界面,权威意图源 / 单一事实源)。design_system_mode:generated | fallback(是否走了设计系统的单一权威事实源)。generated时同时产出design-system.json;fallback时须填design_system_fallback_reason且不产 / 不要求design-system.json(见 ⑥)。- 结构化声明页清单:本次原型应覆盖的每个页面 / 屏幕作为一条结构化记录填写——每页一个唯一
id、精确的prototypebasename(仅文件名,禁../ 子目录,扩展名必须.html,全清单唯一)、一句话description:
以- id: <unique-page-id> prototype: core-NN-<slug>.html description: <一句话>prototypebasename 集合保证「声明清单 == 产出文件」可机器判定(排序无关;重复 / 额外 / 缺失均失败)。
proposal.md保持 markdown 结构不变,避免打断 CLI / runlogos 对 proposal 的解析。声明段是下游flow-derive/ guard / 面板 / checker 的唯一意图事实源,不引入第二处判定。
⑥ Python3 降级:置 design_system_mode: fallback(通用风格兜底,不阻塞、不产令牌)
检测不到 python3 时跳过 ui-ux-pro-max 调用,提示用户「检测到 ui-ux-pro-max 依赖的 Python 3 不可用。原型将使用通用风格生成。如需专业级设计系统建议,请安装 Python 3 后重试。」:
- 原型用通用风格继续产出结构化声明清单里的每个页面,不阻塞、不报错。
- 在声明段置
design_system_mode: fallback并填design_system_fallback_reason(如「Python3 缺失」);此情形下不产出 / 不要求design-system.json令牌,禁伪造令牌。 - 此时 checker
check-ui-prototype走fallback分支:只要design_system_fallback_reason非空、逐页非空、声明清单 == 产出文件(basename 集合一致)即exit 0——不因缺design-system.json而阻塞,plan-exit 门可到达。这消解了「降级不产令牌,但done_when却强制要design-system.json→ 卡死」的矛盾。 - 正常路径(
python3可用、走了设计系统)则置design_system_mode: generated并产出design-system.json(见 ③ / ④),checker 走generated分支要求合法非空令牌。 - 与提案「Python3 缺失时以通用风格兜底并标注,不阻塞」的口径一致。
Step 6 补充三:决策记录沉淀(S38,decision-record-capability)
来源变更:decision-record-capability(社区 RFC issue #12 补充观察)。承接 S37 archive audit-only 契约——决策理由不能只活在归档的 proposal 里。
设计决策的理由若只写进 proposal 的「变更原因」,归档后即失联、archive 删除即彻底消失。为把「为什么这样设计」沉淀为可检索的活文档,change-writer 在提案阶段判断本次是否立下值得长期复盘的拍板决策;若有,产出决策记录。
① 何时升格为决策记录(升格判据)
「变更原因」是每案必填的叙述性动机——留在 proposal.md,不复制进 resources。决策记录是少数值得长期复盘的拍板,满足任一即升格:
- 立了未来变更必须遵守的不变量 / 约束;
- 在真实备选之间做了取舍,且被否选项将来可能被重新提出(记下理由以免反复争论);
- 跨多个规格 / 组件。
一句话测试:「读合并后的规格本身,能否还原这个 why?」——能→不升格;规格只说 what、而 why 与被否方案会随 proposal 归档丢失→才升格。明确不升格:bug 修复、机械重构、发版 bump、trivial 改动。宁缺毋滥——每个提案都写决策记录会把 archive 的检索污染搬进 resources,违背本能力初衷。
② 产出方式(可选章节 + deltas/decisions/)
- 判定需要升格时,在
proposal.md新增可选章节「## 已确定的设计决策」:每条含拟定DXX、决策一句话、理由摘要。拟定号仅为占位、不硬编定死——最终DXX由 merge-executor 在 apply 时按分配公式定号:base = max(configured_next_id ?? 1, max(【已落盘】DXX,空集=0)+1)(基准只含已落盘、不纳入本批待落盘 DXX,delta-r2 F5),候选按稳定序第i条expected_i = base + i,校验「文件名==标题==expected_i」、拒重复。 - 在
tasks.md[delta]规划决策记录 delta:deltas/decisions/<module>-DXX-<slug>.md(目录映射deltas/decisions/ → logos/resources/decisions/;该类别须先由 decision-record-capability 的代码注册,注册前会被判delta_path_invalid,delta-r1 F1)。 - 决策记录文档结构(标准 ADR 变体,见 feature-specs §2.34.2):状态(
proposed/accepted/superseded by DYY)、背景、决策(一句话可引用)、理由(含关键论据与实证)、备选方案(被否选项 + 否掉原因)、影响面(约束哪些规格 / 代码 / 流程)、来源(提案 slug + issue 链接)。 DXX全局唯一,由logos-project.yaml的decision_counter.next_id维护(对齐scenario_counter/feature_counter的「AI 维护、CLI 不取号」语义);取号 / 递增在 merge-executor apply 时(不是openlogos merge,delta-r1 F2),见skills/merge-executor/SKILL.md。- 不含「已确定的设计决策」章节的提案:不产决策记录、全流程零负担;决策记录走既有 delta → merge → merge-executor apply 通道,不新增
openlogos decisionCLI 命令。
③ 推翻旧决策(superseded,不删除)
新决策推翻旧决策时不删除旧记录:用 MODIFIED 携旧记录整条剩余全量、仅把「状态」改为 superseded by DYY,并在新记录「来源」引用旧 DXX。DXX 纳入 S37 守恒门 ID 注册表——决策记录条目删除必须显式(REMOVED / REMOVED-ITEMS 点名),隐式删除会被 change-lint L8 / merge 拒绝。
④ change-lint 提示(warning 级)
proposal 含「已确定的设计决策」章节但 [delta] 无 deltas/decisions/ 任务时,openlogos change-lint 产 warning(decision_record_section_without_delta,走独立 warnings[] 通道,不改 exit code、不阻断门)——提醒补决策记录 delta 或移除该决策章节。它是提醒而非硬门(「是否值得记决策」是判断题、非机器可判定事实)。
Step 7: 引导后续操作(链式驱动)
提供一条可直接执行的提示词,让用户一句话启动全部任务的链式执行:
- 需求级 / 设计级变更(多任务):建议用户说「按 tasks.md 帮我逐步更新 S0x 的所有受影响文档」
- 代码级修复(少任务):建议用户说「帮我修复 S0x 的 [问题描述] 并重新验收」
链式执行的行为规范:
- AI 读取
tasks.md,按顺序逐项执行 - 每完成一项任务,立即将
tasks.md中该项从[ ]更新为[x](AI 主动执行,无需用户提醒) - 每完成一项任务,汇报修改摘要,并自动提示「继续下一项?」
- 用户说「继续」或给出调整意见后,执行下一项
- 全部任务完成后,提醒用户明确授权运行
openlogos merge <slug>
关键原则:不要让用户手动跟踪任务清单——AI 应主动驱动流程。
openlogos merge 和 openlogos archive 是人类确认点:
- AI 未经用户明确授权不得自行执行这两个命令
- 用户明确要求执行(包括使用
/openlogos:merge、/openlogos:archiveslash command)时,AI 可以代为执行 - 不得在"顺手完成流程"、"按流程走完"、"继续"等隐式场景中自动触发
两档模式(半自动 / 全自动)的授权语义:
- 半自动 / 手动(无
--auto):所有人类确认点行为完全不变——merge、部署执行、smoke、archive、git push仍各自停在对应门,逐次等人类明确授权。 - 全自动 / 无人值守(
openlogos next --auto):--auto的含义被重定义为一次性的 standing run-scoped 授权——用户选择--auto即在本次运行域内一次性授权全链路自动到底,无需对每道门逐次再确认。
全自动 --auto 下的自动放行范围(依据 spec/change-management.md §143「无人值守 skip-gate 例外」):
spec出口门(spec-exit,审 delta + 授权合并)与deliver入口门(deliver-entry,部署执行)这两道skippable:true门可被**编排器(driver)**自动放行。据此openlogos merge由编排器凭本次next --auto响应的gate_auto_passed=true执行,无需逐次人类授权。- 「代码已绿后的盖章 / 发布」4 样红线在全自动下由 standing 授权自动放行:
openlogos verify、openlogos smoke、openlogos archive、git push。它们均属"代码已收敛/已绿之后"的盖章或发布动作,--auto下凭用户选择--auto这一次性授权放行,半自动 / 手动下仍逐次须人类明确授权。 - 可跳门每次放行向
GATE_AUTO_PASSED追加一行审计(append-only,历史审计行不构成对后续动作的授权);git push无需任何 marker / guard 改动——plugin/bin/guard-check的安全白名单本就含^git push、PreToolUse guard 从不拦截git push,全自动下它是否执行纯由生成进 AGENTS.md / CLAUDE.md 的指令文本授权。 - 被派发的 change-writer agent 自身仍不直接执行
openlogos merge:产出全部 delta 后停手、把控制权交回编排器,由编排器走自动合并。这与默认/手动模式下"提醒用户授权"并不矛盾——--auto只是把"授权"前置到了用户选择--auto这一步。 - 硬红线(任何模式都绝不自动放行,含
--auto):gate:implement:loop-exhausted(未收敛 / 未绿代码,默认skippable:false)。这是唯一在--auto下也始终须人类明确授权的门,现有逻辑一字不改——自动放行只发生在"代码已绿"之后,绝不跨越"代码未绿"这条线。
merge 后的后续提示应按半 / 全自动两档区分:
- 半自动 / 手动:
- 不需要部署:实现代码 → 用户授权
openlogos verify→ 用户授权openlogos archive→(如需)用户确认git push - 需要部署:实现代码 → 用户授权
openlogos verify→ 用户明确授权部署 → 用户授权openlogos smoke→ 用户授权openlogos archive→(如需)用户确认git push
- 不需要部署:实现代码 → 用户授权
- 全自动
--auto:代码绿后verify/ 部署执行 /smoke/archive/git push均由 standing 授权经编排器自动放行(可跳门逐次写GATE_AUTO_PASSED审计;git push由 guard 本就放行 + 指令文本授权,不涉及任何 marker),无需逐次人类授权;唯独loop-exhausted(代码未绿)仍停门等人类。
AI 只负责驱动内容修改。半自动 / 手动下不得在未获明确授权的情况下推进提案状态;全自动 --auto 无人值守下,对 spec-exit / deliver-entry 两道可跳门,以及代码绿后的 verify / smoke / archive / git push 的放行均属 §143 standing 授权范围内的自动推进,放行依据为本次 next --auto 响应的 gate_auto_passed=true(git push 由 guard 本就放行、全自动下纯由指令文本授权,无需 marker / guard 改动),但 loop-exhausted 永不在自动放行之列。
输出规范
- 文件格式:Markdown
- 存放位置:
logos/changes/<slug>/ - 文件名:
proposal.md和tasks.md(覆盖 CLI 生成的模板)
实践经验
- 宁可高估影响范围:漏掉一个环节的更新比多检查一遍更危险
- 变更类型决定工作量:帮助用户在动手前理解改一个需求可能需要全链路更新
- tasks.md 是执行清单:每完成一项打一个
[x],方便追踪进度 - 小变更也走流程:看似"只改一行 API"的变更,可能影响编排测试和代码
推荐提示词
以下提示词可以直接复制给 AI 使用:
填写提案:
帮我填写变更提案 <slug>我要给 S02 登录场景加一个记住密码功能,帮我分析影响范围这个 Bug 修复只涉及代码层,帮我快速写个提案
执行任务(提案填写完成后):
按 tasks.md 帮我逐步更新 S02 的所有受影响文档帮我修复 S02 登录接口的 500 错误并重新验收
硬性交付门:openlogos change-lint(Step 5 / Step 6 完成后强制)
change-lint-shift-left 起,本 Skill 的自检从「逐项人工核对」升格为机器硬门。适用于 Step 5(
proposal.md+tasks.md生成完毕、含部署决策一致性自检表核对之后)与 Step 6(全部 delta 文件产出完毕之后)两个交付点。
规则(强制):
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 72
- Forks
- 6
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
change-writer- Source
- github.com/miniidealab/openlogos