# RUNTIME GUARDRAILS ## 1. 目的 - 本文档承接 PMFlow 的长运行边界、跨链路守门规则与已知运行假设。 - `AGENTS.md` 保留必须立即遵守的摘要规则;本文件提供更细的运行时约束与环境边界。 - `CLAUDE.md` 只保留当前架构摘要、关键入口和高价值提醒;长清单统一收口到这里。 ## 2. 同步规则 - 任何影响运行边界、守门策略、失败语义、已知环境假设的改动,都必须同步更新: - `AGENTS.md` - `docs/architecture/RUNTIME_GUARDRAILS.md` - 任何影响目录结构、模块归属与关键入口的改动,还必须同步更新: - `CLAUDE.md` - `docs/architecture/ARCHITECTURE_INVENTORY.md` - 任何影响主链路由、函数名、运行时流向的改动,还必须同步更新: - `docs/architecture/DATAFLOW.md` - `backend/.openclaw/pmflow-routing-rules.json` ## 3. 核心运行边界 ### 3.1 平台与写路径 - 数据库写操作必须通过 Alembic migration,禁止直接 `ALTER TABLE`。 - 运行期禁止 DDL;仅迁移路径允许执行 `CREATE/ALTER/DROP/...`。 - 运行环境数据库仅允许 PostgreSQL(`postgresql+asyncpg`),禁止回落 SQLite。 - 新增接口必须遵循响应包络:`{code, message, data}`。 - 禁止在 API 层写业务逻辑;业务逻辑归属 `services/`。 - 禁止在前端组件内直接调用 `fetch`,必须通过 `frontend/src/api/` 封装层。 - 飞书回复必须经过 `feishu_reply_outbox`,禁止同步直接发送。 - 飞书回执发送仅允许 `main.py` 的 drain loop 作为消费者,禁止在业务路径即时派发发送任务。 - 所有写接口必须落审计日志(`operation_logs`),至少包含 `trace_id/interface_path/caller`。 - `created_at_beijing` 为计算属性返回,禁止新增数据库物理列。 ### 3.2 核心业务零兜底 - 模型失败、超时、空响应、结构化解析失败时,必须显式返回真实失败原因。 - 禁止使用固定兜底文案、模板句子、占位字段或 stub 数据冒充成功结果。 - 核心业务完成态不得仅按字段非空判定;必须能区分“真实生成 / 人工填写 / 模板占位 / 生成失败”。 - 技术层 fallback 仅允许用于重试、缓存、解析修复、传输兼容等基础设施环节,禁止上浮为用户可见业务结论。 - AI Steward 与其它生成链的成功/失败判定必须优先使用结构校验、字段完整性和证据一致性。 ### 3.3 业务动作归因主链 - 运行时业务动作归因必须优先走: - 对象/上下文绑定 - `SemanticContextPacket` - `SemanticDecision` - gatekeeper - 用户前台允许以内置 AI 会话作为主入口,但该入口必须绑定正式业务上下文与业务对象,优先服务于 `query.read_only / requirement_plan / project.create / signal.create / followup.*` 等主链,禁止演化为脱离 PMFlow 业务对象的泛化聊天产品。 - 新增 AI 前台能力时,必须优先接入“消息/上下文 -> 语义识别 -> 业务对象/草稿 -> 审计/幂等/确认 -> 入库/执行”链路;不得只停留在对话文本层或仅新增孤立聊天能力而不进入正式业务闭环。 - `backend/app` 运行时代码不得再沉淀会直接拍板 `project.create / signal_source.onboard / followup.* / query vs execute` 的中文关键词、正则、`looks_like_*`、`*_HINTS/*_KEYWORDS` 规则仓。 - 协议级锚点(`reply_to_message_id/button/work_item_id`)、租户权限、幂等等确定性规则可以保留,但展示反馈、草稿确认/修改/取消、followup 动作归类、`query vs execute` 不能再由关键词最终拍板。 - 若问题根因属于“动作路由错误 / 上下文劫持 / 独立业务流误触发”,主修法必须优先落在 ingress 分流、active topic/draft 检测、`SemanticContextPacket` 组包、`SemanticDecision` 结构化判断与 gatekeeper 放行条件。 - `workflow_semantic_planner` 当前职责是 packet / bundle 组装、兼容层收口与冷启动接入,不再作为新的关键词仓。 ### 3.4 LLM 与模型路由 - `llm_service` 运行时路由必须显式传入 `routing_meta`,至少统一: - `tier_alias` - `response_contract` - `fallback_policy` - `execution_mode` - 禁止再通过函数名片段、hint 常量或模板词在底层推断 tier、结构化输出或 fallback 策略。 - 所有 LLM 调用禁止静默兜底与 stub 假成功;low 失败时必须优先强制升级到 high 重试并保留低/高两段日志,high 仍失败时才显式报错。 - 用户可见问答链路(`function_name` 含 `answer/reply/qa`)禁止使用 `reasoning_content` 回退,避免思考过程外漏。 - `integrations(type='model_routing')` 的 runtime tier override 不得把 `adaptive_rag_answer_normal` / `adaptive_rag_answer_deep` 这类用户可见 QA 主函数降级到 `low`。 - 模型默认值与 provider/tier 映射以 `backend/.openclaw/pmflow-routing-rules.json` 为唯一配置源。 ### 3.5 Requirement Plan / Draft / Followup - `requirement_plan` 必须是多轮状态机,不得退回单轮模板问答。 - `MountedTopicWorkspace.plan_status` 必须显式落库区分 `idle / collecting / options_ready / plan_ready / awaiting_execute_confirm / suspended`。 - `requirement_plan` 的 A/B/C 可以固定为用户可见骨架,但业务选项、推荐项、理由和代价必须走“上下文包 -> 模型结构化决策 -> gatekeeper -> 渲染”。 - 正在收敛中的 `requirement_plan` 必须支持碎片化回复,不能因缺少新的 `semantic_bundle` 回落到普通 query。 - 用户显式说“聊个新需求 / 另一个需求 / 跟上一个无关”时,必须先清掉继承的旧 `current_project_id`。 - 裸 `A/B/C/确认/你自行推荐` 这类低信息量回复,如果没有命中当前 active requirement session 或待确认草稿,必须明确提示当前没有进行中的收敛轮次或草稿。 - 草稿确认只认显式 `reply_to_message_id` + 明确草稿动作,或显式 `work_item_id`。 - 用户显式 `reply/thread` 某条已绑定回复并要求“基于当前信息出草稿”时,主链必须先尝试从该 reply 命中的 mounted context 升格生成 requirement-plan 草稿;若上下文不足,必须显式失败,禁止回落到 `query.answer` 冒充“草稿已生成”。 - 用户在显式 `reply/thread` 的同一需求线程里已经完成 `A/B/C` 选项收敛后,后续碎片化追问必须先尝试把该 reply 命中的 chat context 升格成 requirement-plan workspace,再走 `requirement_plan` 主链;禁止继续落到通用 `query.answer` 并把代码路径、内部函数名或工程证据泄漏到用户可见答案里。 - 用户对 requirement-plan 轮次回复 `A/B/C` 协议时,识别范围必须覆盖裸 `A/B/C`、`我选C`、`选C`、`就C吧`、`先按C` 等显式选项回复;这些协议消息必须优先使用上一轮真实选项表(`round_option_maps`)解释该选择。 - requirement-plan 的选项协议识别属于协议层,不属于业务语义拍板;运行时代码必须复用单点协议解析器输出结构化 `choice + remaining_text`,禁止在各入口重新散落正则或关键词规则来解释这类协议回复。 - 若后续需要在任何运行时模块新增正则/关键词驱动的协议或业务语义判断,必须先经 Host 明确确认;未经确认禁止新增。协议层优先使用单点结构化 parser、state machine、上下文快照或显式 option map,若证据不足必须显式失败,禁止再用扩词表、补正则或前缀枚举做“最小修补”。 - requirement-plan 低信息量选项回复若缺少上一轮真实选项表,只能显式失败或重新发起该轮次,禁止回退到通用 IT 项目默认映射误译用户选择。 - AI PMO ingress 的 mixed sidecar 预检查不得拦截显式 `reply/thread` 下的低信息量协议回复(如 `A/B/C`、`我选C`、`就C吧`);这类消息必须优先交给 active-context / requirement-plan 主链处理,禁止先生成 `[回答]...[已收到需求]` 的 mixed 拼接回复污染主结果。 - orphan requirement-plan followup 在显式 `reply/thread` 存在时,必须先尝试从 reply 命中的 chat context 恢复或升格 requirement workspace;只有恢复失败时才允许回“当前没有进行中的 A/B/C 收敛轮次”。 - Feishu 显式 `reply/thread` 到机器人消息时,ingress 与 mounted runtime 必须先通过 `feishu_reply_outbox.sent_message_id -> source_message_id` 归一化 `root_message_id/reply_to_message_id`,并在后续 active-context / requirement-plan / draft 主链里复用同一份 canonical thread context;禁止直接用机器人 `sent_message_id` 新开 chat topic,导致 requirement-plan / draft 线程分叉。 - requirement-plan 的唯一业务真源固定为 `MountedDraftWorkspace.requirement_card`:收敛轮次、已确认字段、`round_option_maps`、`last_round_options`、`source_material` 等业务状态只能从 draft 或结构化 `requirement_plan_context` 恢复;`mounted_topic_workspaces.facts_json` 只允许保留线程索引级最小字段(当前限定为 `title / plan_profile`),`work_items.execution_result` 与 `mounted_conversation_runs.final_reply` 仅作审计/回放,禁止再从 assistant prose、topic facts 或 run 文案反推需求字段。 - requirement-plan 的运行时路由命名也必须单独收口:收敛轮次统一写 `requirement_plan.collect`,草稿确认前的结构化草稿统一写 `requirement_plan.draft`;`query.answer` 只保留给通用问答,禁止在 requirement-plan 主链里继续借用旧 query route 记账。 - 飞书历史队列协议已停用:卡片动作与文本 followup 只允许走 `work_item_id + work_item.resume/draft_confirm` 主链。 - AI PMO 写操作默认先生成草稿并进入 `draft_pending_confirm`,未确认前禁止自动执行入库。 - `project_create.create` 与 requirement draft confirm 的任务拆解是从属子步骤,不再允许阻塞项目、主信号、来源挂载与宪章的确定性创建。任务生成链必须先按 `routing_meta(tier_alias=low, response_contract=structured, execution_mode=local_planner)` 尝试,并在结构质量不足、空任务、不可映射技能或 provider 失败时升级 `high`;若高阶仍失败,运行时必须显式写回 `task_generation.status=pending` 与真实失败原因,保持 `draft_pending_confirm` 可重试,禁止返回默认任务、模板任务或把整条确认入库伪装成成功/失败错态。 ### 3.6 AdaptiveRAG / Query 主链 - `POST /rag/ask` 在命中 `business_review/correction_escalation` 时,必须强制留在 `query.read_only` 主链,禁止误送到写操作草稿链。 - Feishu 新消息即使被低阶 LLM 先判成写动作,只要统一语义规划层命中 `requirement_plan/business_review/correction_escalation`,就必须在 ingress 阶段强制拉回受控问答主链;其中 requirement-plan 收敛轮次必须落到 `requirement_plan.collect / requirement_plan.draft`,不得再回写为 `query.answer`。 - 飞书群聊 `query/followup` 同步直答只允许显式触发:`@PMFlow`、显式 `reply_to_message_id`、卡片动作或显式 `work_item_id`;无显式触发时不得同步直答,也不得写入 followup QA 桶。 - Feishu `query/followup` 会话键在命中 `reply/thread` 锚点时必须优先使用 thread key;仅在没有显式锚点时才回落到默认的 `chat + sender` scope key。 - AdaptiveRAG 命中显式 `reply/thread` 锚点后,问题改写必须优先使用该锚点;`session_state.last_subject / last_entity_ids` 只允许在没有显式锚点时参与续写,禁止旧会话主题覆盖显式引用上下文。 - 飞书与 AI PMO 入口(含 `message_intent=mixed`)问答链路必须绕过 deterministic/snapshot 快路径,统一落到场景化 Prompt 生成。 - 通用行业趋势问答不得注入数据库、项目历史或外部实时搜索结果;只有显式带项目上下文时才允许走 `external_trend`。 - mixed 场景回复必须强制两段格式输出:`[回答]` 与 `[已收到需求] ...,已入库处理`。 ### 3.7 Signal / Project / SSTC / Briefing - `SignalSourceRegistry` 仅作为信号源接入/幂等内部表;用户可见的项目“信号源/信号”统一落到正式 `Signal`。 - `create_project_from_natural_language` 必须支持透传 `requested_member_user_ids`,草稿确认时必须把推荐负责人并入项目创建事务。 - AI Steward `project-from-text` 归一化阶段必须优先走人员能力图谱,禁止绕过能力图谱直接拍脑袋分配。 - AI PMO `signal.create` 在用户显式要求“先分析再入库 / 自行分析”时,若批量结构化分析失败,必须返回失败安全态。 - SSTC 宪章 AI 预填充必须输出并持久化 `field_status/field_evidence/readiness/derived_artifacts`;总确认前必须校验 `readiness`。 - SSTC 发布验证清单必须优先消费 `derived_artifacts.verification_metrics`,禁止回退默认验收项。 - 老板晨报链路只允许 `BOSS/ADMIN` 访问;`snapshot/live` 语义必须分离。 - `daily-briefing-v2` 必须复用同一份租户级简报内核,禁止老板晨报与每日简报各自维护独立统计口径。 - 晨报/日报导出首版只允许前端“当前所见”打印导出,禁止新增后端二进制 PDF 生成服务。 ### 3.8 Feedback / Training / Prompt Registry - 只读问答链路的 prompt 读取优先级固定为: - prompt registry manifest 校验 - active prompt release - 代码 seed prompt fallback - 回复质量迭代与训练管线的原始反馈入口统一复用 `feedback_center_records / qa_records / ai_call_logs`。 - 训练/微调 artifact 必须先进入 `trained_model_artifacts -> trained_model_deployments` 候选链路,再绑定到 `low/high` 逻辑槽位。 - training deployment 的 `accepted` 决策默认受 acceptance gate 约束。 ## 4. 已知运行边界与假设 - 飞书回调字段可能缺失文件名/大小,仅保证 `attachment_id/key/type` 可用。 - 真实飞书网页 E2E 依赖本机已登录的 Chrome/Feishu 会话。 - 真实飞书网页 E2E 只负责浏览器发消息与页面诊断,结果校验统一走数据库探针。 - 显式命名的新项目请求不得仅因正文出现历史项目标题就自动绑定已有 `project_id`。 - 项目创建返回的 `signal_sources` 仅作为 AI Steward 创建结果区的内联展示;项目看板与 SSTC 信号阶段统一只读正式 `Signal`。 - 老板晨报首版的 `external_metrics` 只返回占位区块,不接 CRM / BI / 收入系统。 - `daily-briefing-v2` 与老板晨报当前只做同会话内 `snapshot/live` 同步,不引入 WebSocket 推送。 - 飞书长连接 websocket 在本地/CI 环境默认使用 `certifi` CA bundle 作为信任链。 - 飞书长连接状态分为两层:`last_received_*` 表示 SDK 已收到事件,`last_event_at` 表示 worker 完成处理。 - LLM 主链按 `OPENCLAW_ROUTING_ENABLED` 走 OpenClaw 路由规则;请求超时统一以 `LLM_REQUEST_TIMEOUT` 环境变量为准。 - 路由配置唯一真源固定为 `backend/.openclaw/pmflow-routing-rules.json`。 - World Model 静态层已接入 Redis 缓存(`wm:static:{tenant_id}:{project_id}`,TTL 600s),写操作后主动 invalidate,动态层不缓存。 - 本地 `ollama` 仅允许知识库问答链路使用,且必须通过 `llm_engine.settings.enable_local_kb_qa` 显式开启。 - IT 五轮 requirement plan 现以 `MountedDraftWorkspace.active_work_item_id + latest_*_message_id` 锚定当前 active draft;历史未绑定这些字段的旧草稿不会自动认领。 ## 5. 维护建议 - 想看“必须立即遵守的规则”:先看 `AGENTS.md` - 想看“当前架构说明和关键入口”:看 `CLAUDE.md` - 想看“长运行边界、守门规则和已知环境假设”:看本文档