Files
Agent-System/.doc/system-design/2026-09-20-stage-backtrack-and-impact-loop-design.md
weichenandCursor 54c8a3d107 docs(design): specify stage backtrack and impact loop
Record how later materials can affect earlier stages without hard gates, and split the implementation into planned slices.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 15:09:06 +00:00

16 KiB
Raw Permalink Blame History

阶段回溯与影响闭环设计

状态: accepted(设计;未改业务代码)
日期: 2026-09-20
分支: feature/stage-backtrack-design
基线: 功能启用与文档影响整改方案 Track T(五表 project_trace_*)
决策方式: 2026-09-20 grill 三轮;本文只记录已定决策与由其直接推出的实现约束


1. 要解决的三件事

  1. 阶段推进已存在,不重做。 创建者把当前阶段推进到下一阶段。门禁、三权审批、创建者独占推进保持现状。
  2. 修改之后要能很快看出波及面。 小队编制完成或成员改了材料、需求、对话结论之后,助手给出:可能影响哪些文档与条目、风险是什么、建议下一步做什么。
  3. 后面阶段的新材料可能反过来碰前面已完成阶段。 系统要标出来,并提供两条处置路径,但不把人锁死在流程里。

松散约束的总原则:信号自动产生,状态改变必须有人拍板。 未处理的影响不阻止推进。

2. 已定决策

议题 决定
方案基线 沿用五表追踪索引,回溯层共用同一影响内核
回溯形态 双层:L1 文档修订(默认)+ L2 再打开阶段(重路径)
再打开时的文档 选择性解锁:勾选的文档退回 drafting,其余保持 approved
下游已完成阶段 保持 completed,加「待复核」软标记;再次推进时二次确认
待复核闭环 仅人工:明确「无需变更」,或已经发起修订。禁止自动清除
分析触发 混合:文档修订/批准、阶段推进、对话结论沉淀自动跑;参谋与 API 可随时手动跑
门禁 全域统一松散,含医疗域 rdev。未复核不阻塞推进
L2 发起权 受影响文档的编制/审核/批准人可申请;创建者批准后执行。创建者也可直接发起
候选边裁决 不新增 trace_reviewer。由下游文档编制人确认或否决;无编制人时由创建者裁决
留存 project_trace_* 与本设计新增的申请/标记表定为合规业务记录(record)。随项目保留,禁止当可丢缓存随意删后重建
对话 纳入桥接:参谋可一键生成受控文档修订提案,人拍板后才改正文
试点 main + software_delivery 先行,rdev 后跟
本轮范围 设计与任务拆分。不写业务代码,不改 production_ready

本决定不签 D7 对话留存 ADR。该 ADR 仍是 pending-compliance-signoff。这里只给追踪索引和回溯记录分类,不授权任何物理删除。

3. 现状里可复用的部分

能力 位置 本设计怎么用
创建者推进 + 文档须 approved internal/projectinstance/stage_service.go AdvanceStage;gate.go evaluateStageReadiness 保持。软标记只增加二次确认,不改变 Ready 的文档条件
阶段只前进 internal/projectinstance/stage_store.go AdvanceStage;状态仅 pending/active/completed/skipped L2 增加一条受控回退,不开放任意回跳
文档驳回回 drafting internal/docgov/state_machine.go L1 继续走提案/驳回。L2 解锁用新的审计动作,不伪装成驳回
变更提案 internal/docgov ChangeProposal;ImpactAnalysis 现为自由文本 提案仍由编制人拍板。影响正文改由报告里的确定性事实供给,提案文本只作说明
文档级血缘 document_lineage;CheckAndPropagateStale;目前实质只有 test_manager 一条边 保留「消费了哪一版文档」。条目边解释「为什么影响到这一处」
版本账本 document_snapshots / document_change_events 影响分析读已提交 diff,不重扫工作区全文
预留实例状态 awaiting_stage_confirmation project_workflow_instances.status;代码从未写入 本设计不占用。 它会把整条实例停住,和松散约束相反
阶段就绪待办 stage_advance_requests L2 申请单独成表,形态对齐,不复用推进待办

4. 影响分析闭环

4.1 触发

来源 方式 写什么
人工修订提交、Agent 正式提交、导入提交 自动,挂现有 change event / outbox 一份影响报告
文档变为 approved 自动 上游批准可能让下游条目变脏;出报告,不自动改下游正文
阶段 advance 成功 自动 对照本阶段新批准内容,标出已完成上游/下游里被碰到的条目
对话结论被标为可沉淀(见 §7) 自动 只出报告与修订提案草案,不改受控正文
参谋「分析这次修改的影响」或 API 手动 同一份报告结构

失败、索引未完成、调用者看不见目标,三种情况必须分开。禁止把 index_pending / partial / failed 显示成「无影响」。语义沿用整改方案里的七种影响状态:confirmed_impact、possible_impact、dependency_unchanged、no_known_dependencies、index_pending、partial、failed。

4.2 内核

  • 事实来自五表:条目身份、不可变修订、关系边、人工决议、索引覆盖状态。模型见整改方案 §4,本文不另起一套表。
  • 从变更所触及的条目做有界反向遍历,默认深度 3,必须检测环。
  • 服务端计算受影响集合、影响状态和风险下限。模型只能写人能读的解释,不能把 possible_impact 改成 confirmed_impact,也不能压低风险。
  • 向量相似只生产 model_candidate 边。未确认前只贡献 possible_impact。

4.3 报告给人看的内容

  1. 这次改了什么(旧值 → 新值,或「无结构化 diff」)。
  2. 受影响的文档、条目、所在阶段,以及影响状态。
  3. 风险下限和依据(例如已批准下游仍引用旧修订)。
  4. 不确定的部分(候选边、索引未覆盖)。
  5. 建议的下一步,每条都是可点的动作,而不是一段无法执行的文字。

建议动作只有三类:无需变更(清除对应软标记)、发起 L1 修订提案、申请 L2 再打开。点下去只创建草案或申请,随后重新检查权限、职责、租约和版本。

5. 双层回溯

flowchart TD
    changeEvent["修改事件"] --> analysis["影响分析"]
    analysis --> report["影响报告"]
    report --> l1["L1 修订提案"]
    report --> mark["下游待复核标记"]
    l1 --> mark
    report -->|"需要重编或新文档"| request["L2 申请"]
    request --> creatorOk["创建者批准"]
    creatorOk --> reopen["上游阶段再打开"]
    reopen --> unlock["只解锁勾选文档"]
    unlock --> squad["可重跑小队"]
    squad --> reapprove["重新审批后阶段再次完成"]
    mark --> clear["人工闭环"]

5.1 L1:文档修订(默认)

阶段状态不动,completed 保持 completed。

  • 受影响且已批准的文档:走现有变更提案或新版本修订,编制人决定是否改。
  • 未批准、仍在 drafting 的文档:不额外解锁,编制人按原职责改。
  • 适用:措辞、单条需求、验收标准、引用关系的局部更新。
  • 对接:internal/docgov 提案与 internal/docrevision 人工修订。不新增阶段状态。

5.2 L2:再打开阶段(重路径)

只在需要重跑小队、补一篇文档,或修订范围大到不适合在锁定正文上打补丁时使用。

确认态不放在实例状态上。 新增 stage_reopen_requests(对齐 stage_advance_requests):

字段要点 说明
阶段实例 必须当前是 completed
申请人 该阶段某份受影响文档的 author / reviewer / approver,或创建者
勾选文档 准备退回 drafting 的 doc task;空列表拒绝
理由 必填,写入审计
状态 pending → approved / rejected / cancelled

创建者直接发起时,同一事务内写入并批准,不给自己再排一个待办。其他人发起时保持 pending,直到创建者批准。

批准后,同一事务:

  1. 该阶段 completed → active。
  2. 勾选文档执行新动作 reopen_for_revision:approved → drafting,解锁正文,记原因、操作者和前一个 snapshot。未勾选的文档保持 approved 且继续锁定。
  3. 不把阶段内其他文档打回,不把下游阶段改成 pending,不把实例改成 awaiting_stage_confirmation。
  4. config_revision 递增,沿用现有乐观锁。

允许两个「活」阶段并存。 推进游标仍是 position 最大、状态不是 completed/skipped 的阶段。被再打开的上游是附加可编辑阶段,界面标成「再打开」,不抢下游正在进行的编制。这样后面的阶段不用停下来等前面重走一遍。

再打开阶段再次推进时:

  • 门禁只要求本次被解锁的文档重新 approved。本来就保持 approved 的文档不再卡一次。
  • 创建者确认后,该阶段回到 completed。
  • 这次推进不自动清除下游「待复核」标记。

被解锁文档可以按原 executor 重跑小队;未解锁任务不得被这次重跑覆盖。

5.3 为什么不用驳回代替 L2 解锁

驳回表示审核/批准没通过。再打开是「前面已经生效,现在因新材料要改一版」。审计、通知和责任人都不该写成驳回。reopen_for_revision 单独留痕,目标状态同样是 drafting。

6. 待复核软标记

新增 stage_recheck_marks,挂在阶段实例上:

  • 产生:影响报告判定某已完成阶段的文档或条目受到 confirmed_impact 或未决 possible_impact。同一阶段、同一来源报告只保留一条未关闭标记。
  • 含义:请人看一眼。阶段仍是 completed,文档仍是原状态。
  • 推进:GetStageReadiness 仍可 Ready=true。若目标阶段或它依赖的已完成上游带未关闭标记,响应增加 requires_recheck_ack=true。AdvanceStage 在带上 acknowledge_recheck=true 后才执行,并记下「创建者已知悉」。知悉不等于闭环。
  • 清除:只有人写下 no_change 决议,或针对该标记发起了 L1 提案 / L2 申请。发起即清除「还没人理」的状态;后续修订失败不会把标记偷偷清掉——提案被拒或 L2 被拒时标记重新打开。
  • 禁止:上游出现新 snapshot、文档被批准、索引重建完成,都不得自动清除。

医疗域同样不把未关闭标记变成硬门禁。已知取舍见 §10。

7. 对话桥接

今天对话只能把消息收成自由文档,不能直接改受控文档。本设计补一条提案桥,不补一条直写桥。

意图 行为
project.impact.analyze 只读。对当前对话里点名的修改、文档或条目出影响报告
project.doc.revise_propose 创建修订提案或 agent candidate。编制人在文档侧确认后才进入正文

约束:

  • 参谋只能看见调用者有权看的文档和条目。
  • 意图注册方式对齐 internal/intent/registry.go 里的 project.stage.advance:写意图 RequiresConfirm=true。
  • 执行入口对齐 internal/chat/action_executor.go:确认前零业务写。
  • 自由文档沉淀保留,作为不进入受控台账的旁路。

8. 候选边由谁裁决

整改方案 §7 推荐的项目级 trace_reviewer 不实施。

  • explicit_reference、workflow_consumption、rule 边由抽取器直接成为已确认边。
  • model_candidate 由下游文档当前编制人确认或否决,写入 project_trace_edge_decisions。
  • 该文档 DutyMode=none 或没有编制人时,由项目创建者裁决。
  • 未决候选只产生 possible_impact。
  • 全局管理员不因管理员身份获得项目内文档或候选的确认权。
  • 确认事务仍须校验项目、条目、两端文档属于同一项目,且操作者看得到下游文档。源端文档不可见时,不展示其标题和正文,只保留「存在一条不可见上游」的计数,避免侧信道。

9. 留存

数据 类别 规则
project_trace_items / item_revisions / edges record 随项目保留。可做审计过的修复重放(从源 snapshot + 决议账本重建派生列),不可先删光再当缓存重建
project_trace_edge_decisions record,且是决议权威 修复重放必须原样带回确认、否决、撤销
project_trace_index_state record 覆盖水位属于合规轨迹的一部分,不单独丢弃
stage_reopen_requests、stage_recheck_marks record 与阶段实例同寿命
影响报告 沿用现有 change report 留存 不因索引重建覆盖历史时间线

源文档因依法清除而删除时:条目改为 tombstone,边和决议保留,影响报告保留 digest,不级联物理删除。具体清除仍等 D7 合规签字,本决定不打开删除开关。

这覆盖整改方案审阅的第二项遗留,并取代该方案 §10「条目、修订、关系和索引状态是可重建投影、可丢弃」的表述。人工决议单独权威这一点不变。

10. 已知取舍

全域松散是刻意的。医疗设计控制(rdev)里,上游需求变了而下游验证方案仍显示已完成,合规上应有人复核。本系统选择:

  • 不替合规官拦截推进;
  • 把待复核做成推进前必须看见并确认的提示,而不是可折叠的小字;
  • 保留申请、解锁、知悉、闭环的全部审计,供事后检查。

若以后要为某个工作流打开硬门禁,应做成该工作流 manifest 上的可选开关,默认关闭。首期不做这个开关,避免现在就分叉成两套门禁。

11. 模块对接

模块 改动面 切片
internal/docrevision 提交后出报告;风险与影响状态已有雏形(impact.go、risk.go) T1
internal/projectworkflow lineage 继续记文档版本消费;stale 不再是唯一影响类型 T1
新追踪存储(整改方案五表) 迁移、抽取 UR/RS/REQ/TC、项目页 T2
internal/projectinstance stage_reopen_requests、阶段 completed→active、选择性解锁、推进知悉 B1
internal/docgov reopen_for_revision;提案桥接 B1 / B3
web 工作流条与文档栏 再打开申请、勾选解锁、待复核二次确认 B1 / B2
internal/intent + internal/coordinator + internal/chat 两个新意图 B3
追踪查询 深度 3 反向遍历、候选治理 UI T3

试点验收只覆盖 main 与 software_delivery。抽取器可以识别已出现的 UR/RS/REQ/TC,但 rdev 的阶段再打开不在首期验收里。software_delivery 的 D0 变更说明继续作为人写的变更叙述,不替代影响报告。

12. 实施顺序

  1. T1 把还没接上的提交来源(人工修订、导入、聊天侧正式提交)收进同一份影响报告。已完成的 lineage 鉴权、proposed/authoritative 报告、PI 叙事裁剪不重做。
  2. T2 五表、键投影、项目「需求与影响」页。D7 追踪分类已在本文决定,不再等对话 ADR。
  3. B1 L2 再打开。可与 T2 并行,但报告里的「申请 L2」按钮等 T1 报告存在后再接。
  4. B2 软标记与二次确认。依赖 B1 的阶段读写,不依赖多跳。
  5. B3 对话桥。依赖 T2 的条目身份才能「触及条目」;在此之前只允许对文档出提案。
  6. T3 多跳与候选边。依赖 T2。

切片任务见 .doc/ops/short-term/2026-09-20-stage-backtrack-*.md 与 2026-09-20-impact-loop-t1.md、2026-09-20-project-trace-index-t2.md、2026-09-20-trace-multihop-t3.md。

13. 非目标

  • 不改创建者推进权和文档三权状态机的既有转移。
  • 不把已完成阶段自动打回,不级联冻结下游。
  • 不新增 trace_reviewer 角色。
  • 不在本轮启用硬门禁,不为 rdev 单独做拦截。
  • 不把对话直接写入受控正文。
  • 不签整份 D7,不执行物理删除,不改 production_ready。
  • 不在本设计任务里改 internal/ 或 web/。