# 项目状态管理 + 快速恢复协议(v0.6) **问题**: 当前 PRD 大师没有"项目状态文件"。企业家中断 3 天回来,Controller 只能靠**读 conversation.md + 猜**来恢复上下文——慢且不可靠。 每个项目目录维护一个 `state.json`,跟踪当前阶段、工作类型、流程模式、契约 revision、未解决问题和上次行动。 --- ## state.json 结构 ```json { "state_schema_version": 3, "workflow_version": "0.6", "project_name": "fba-smart-restock", "project_started_at_utc": "2026-05-23T10:00:00Z", "last_updated_at_utc": "2026-05-23T14:32:00Z", "work_type": "feature", "workflow_mode": "standard", "contract_revision": 3, "source_ids_changed": ["AC-F03-01"], "current_stage": "4.5", "current_substep": "v1-user-decision", "completed_stages": ["0", "1", "2", "3", "4.1", "4.2", "4.3", "4.4"], "skipped_stages": [], "next_action": { "type": "user_decision", "description": "等企业家拍板:V1 方案对吗?", "askuserquestion_options": ["接受 V1 走终稿", "继续吵一轮", "大方向调整"] }, "open_questions": [ {"id": "OQ-7", "title": "批量导出是否进入 MVP", "kind": "decision", "category": "scope", "priority": "P1", "depends_on": [], "owner": "user", "status": "pending_user"} ], "key_decisions_made": [ {"id": "D-1", "decision": "v1 用虚拟数据集 + 影子真实 SKU", "stage": "1", "rationale": "..."}, {"id": "D-2", "decision": "每日决策(不是每周)", "stage": "1"} ], "category": "saas", "prd_type": "feature", "agents_used": { "lead_pm_calls": 5, "reviewer_calls": 8, "author_calls": 0, "total_tokens_estimated": 250000 }, "deliverables": { "scene_anchor": "scene-anchor.md", "proposal_v0": "proposal-v0.md", "proposal_v1": "proposal-v1.md", "debate_log": "debate-log.md", "assumptions": "assumptions.md", "conversation": "conversation.md", "evidence": ["evidence/competitors.md", "evidence/benchmark.md"], "drafts": [], "final_prd": null, "requirements_contract": null, "requirements_analysis": null, "bugfix_contract": null, "prd_summary": null, "prd_dev": null, "ppt_outline": null, "ppt_pages": [] }, "user_inputs_log": [ {"stage": "1.1", "timestamp": "...", "summary": "选 SaaS 品类"}, {"stage": "1.2", "timestamp": "...", "summary": "选 CEO 拍板模式"} ] } ``` ### 阶段 1 前沿如何保存 `open_questions` 是未决节点和依赖关系的唯一事实源,不另建第二棵树。每个未决节点必须包含: - `depends_on`:它依赖的未决节点 ID;依赖节点仍在 `open_questions` 时,本节点不能进入前沿; - `owner`:`agent` 表示 AI 应自行查证;`user` 或具体的用户侧角色表示需要用户本人或其组织提供证据; - `status`:用户节点用 `pending_user`;AI 事实节点用 `pending_research` 或 `researching`。已解决节点直接移出 `open_questions`。 阻塞方向的事实节点还要保存 `evidence_needed`、`acceptance_threshold` 和 `due_by`;`owner` 必须指向真正能取得证据的人或 Agent。这样“需要验证”才是可执行任务,而不是一句悬空备注。 事实查证节点严格使用下面的字段名和值,不得自行改成 `type`、`evidence_required`、`deadline`、`awaiting_evidence` 等近义字段: ```json { "id": "OQ-8", "title": "夜间 CSV 是否满足审批前检查的数据新鲜度", "kind": "fact", "category": "system_dependency", "priority": "P1", "depends_on": [], "owner": "企业 IT 数据负责人", "status": "pending_user", "evidence_needed": "一周导出时间戳与审批入队时间样本", "acceptance_threshold": "95% 的数据延迟不超过 2 小时", "due_by": "3 个工作日内" } ``` 阶段 1 的 `next_action` 保存**本轮实际前沿快照**,用于中断后原样恢复,不替代 `open_questions`: ```json "next_action": { "type": "stage1_frontier", "description": "等待用户回答当前前沿;事实查证并行进行", "question_ids": ["OQ-7", "OQ-9"], "research_ids": ["OQ-8"] } ``` `question_ids` 只包含本轮实际问给用户的节点;`research_ids` 包含已经派发、尚未完成的事实查证,不论负责人是 AI 还是用户侧角色。即使当前只是在等待事实查证,`next_action.type` 仍使用 `stage1_frontier`,不得发明另一种类型。每次用户回答或查证返回后,先更新 `open_questions`,再按依赖关系重算并覆盖 `next_action`。用户要求分批回答时,`question_ids` 可以是完整可问前沿的子集;不得加入依赖仍未解决的节点。 恢复旧状态时,如果 OQ 缺少 `status`,按 `owner=user → pending_user`、`owner=agent → pending_research` 补齐;如果阶段 1 的 `next_action` 不是 `stage1_frontier`,从 `open_questions` 重算后再继续,不向用户重复已解决的问题。 ## Controller 何时更新 state.json - 每次阶段切换(如 0→1、4.6→5.1) - 每次跑完 agent(更新 agents_used) - 每次企业家/技术负责人拍板且满足「关键决策闸门」时(写入 key_decisions_made;普通确认不写) - 阶段 1 每次回答后重算决策树:新增未决节点、移除已解决节点,并为 OQ 标记 `kind=fact|decision`、依赖、优先级和责任人 - 用户暂停时,把本轮 `question_ids` 和仍在运行的 `research_ids` 写入 `next_action`;只要仍有阻塞阶段 2 的 P0/P1 OQ,就不得把阶段 1 标记完成 - 每次输出文件(更新 deliverables) - 每次切换 work_type/workflow_mode 或需求 revision(更新 contract_revision/source_ids_changed) **写入方式**:用 Read + Write 原子操作(先读再覆盖)。 ## 启动协议改进 当用户说"启动 PRD 大师"或"继续上次的 PRD"时,Controller: ### Step 0: 先识别旧状态 若 `workflow_version` 缺失或早于 `0.5`,不要直接解释旧数字阶段:旧阶段 2(调研)映射到新阶段 3,旧 3.x(方案辩论)映射到新 4.x,旧 4(Demo)只保留为历史产物,旧 5.x 保持不变。保留所有交付物,不覆盖用户内容。 未完成项目如果 `scene-anchor.md` 中缺少「价值论证(阶段 2 已确认)」,把它设为迁移后的 `next_action`,完成价值论证后再回到映射前的进度;已完成的旧项目只标记 `legacy_completed_without_value_stage`,不强行重开。 从 v0.5 或更早状态升级到 v0.6 时,保留阶段、交付物、决定和未决节点;按本文件规则补齐 OQ 的 `status` 与事实查证字段,并把阶段 1 的 `next_action` 重算为 `stage1_frontier`。迁移完成后写入 `state_schema_version=3`、`workflow_version=0.6` 和迁移说明,不重复询问已经解决的问题。 ### Step 1: 扫描已有项目 ```bash ls -d */ # 找出所有项目(每个项目=工作区下一个以项目名命名的目录) ``` 每个项目读 `state.json`,按 `last_updated_at_utc` 倒序。 ### Step 2: 用 AskUserQuestion 让用户选 ``` question: "我看到你有几个进行中的项目" options: - "继续 fba-smart-restock(上次到阶段 4.5,2 天前)" - "继续 xxx-xxx(上次到阶段 1.3,1 周前)" - "开始新项目" ``` ### Step 3a: 选"继续" Controller 读对应 state.json 的 `next_action` 字段,**直接执行那个 action**(如发对应 AskUserQuestion)。 同时给企业家一份"上次进度回顾"行动卡: ``` 📌 你上次的项目: fba-smart-restock(FBA 智能补货决策引擎) 📍 上次进度:阶段 4.5(V1 方案待确认) 🎯 已完成: 价值论证、调研和四方评审三轮博弈 ⏸ 暂停原因: 你说"我先想想" 🔄 现在你需要做的: {next_action.description} 📚 你想先看历史吗? - 看场景锚点 scene-anchor.md - 看 V1 方案 proposal-v1.md - 看仍待拍板的 OPEN_QUESTION ``` ### Step 3b: 选"开始新项目" 先判定 `work_type=feature|bugfix`;Feature 再选择 `standard|quick|tech-constrained`,写入 state 后执行对应协议。 ## 快速恢复的 3 种场景 ### 场景 A: 1 小时内继续 直接读 state.json 的 `next_action`,立刻执行。无需任何展示。 ### 场景 B: 1 天-1 周回来 展示"上次进度回顾"行动卡(见 Step 3a),让用户决定是否需要先回看历史。 ### 场景 C: 1 周以上回来 主动展示: - 上次场景锚点(提醒"你当时想的是这个") - 上次 V1 方案 - 上次未解决的 OPEN_QUESTION - 询问"过去 X 天有什么变化吗?要更新场景理解吗?" 如果用户说"有变化"→ 回到阶段 0 重做激进抽取(输入 = 老场景 + 新变化) --- ## state.json 跟 conversation.md 的区别 | 文件 | 用途 | 写入方式 | |------|------|---------| | `state.json` | 结构化状态(机器读) | Controller 自动维护 | | `conversation.md` | 完整对话存档(人读) | Controller 累加追加 | state.json 是 conversation.md 的"索引"。conversation.md 是史诗,state.json 是 TOC。 ## 兜底机制 如果 state.json 损坏或缺失: ```python # Controller 启动时 if not state_json.exists(): # 重建:扫描 deliverables 目录推断状态 if output/bugfix.md exists: state.work_type = "bugfix" elif output/requirements.md exists: state.work_type = "feature" if output/ppt.md exists and every page p01..pNN declared in ppt.md exists: state.current_stage = "6.3" elif output/ppt.md exists: state.current_stage = "6.2" elif output/requirements.md exists: state.current_stage = "需求契约已生成" elif output/PRD详细版.md exists: state.current_stage = "PRD 已生成,待需求契约" elif drafts/r3-*.md exists: state.current_stage = "5.3" elif proposal-v1.md exists: state.current_stage = "4.5" elif scene-anchor.md contains "价值论证(阶段 2 已确认)": state.current_stage = "3" elif scene-anchor.md exists: state.current_stage = "1.5" else: state.current_stage = "0" ``` ## 工作量 新增维护成本:每次阶段切换额外 1 个 Write 调用。 回报: - 中断恢复体验大幅改善 - 多项目并行管理变可能 - 教学/分析用(统计每阶段 token 消耗、平均时长等)