# Pipeline OA Event Flow

Pipeline 的最终控制模型必须是 100% OA 事件流驱动。开发过程可以分阶段迁移，但交付态不能保留中间态、双写语义、点对点控制通道或依赖旧事件的永久兜底；任何阶段性兼容只能作为局部迁移手段，必须在同一重构闭环内被删除并由 E2E 证明已退出。

## Core Principles

- 统一 `oa-event-flow` 微服务是跨业务 OA 事件存储、tag 订阅和统计投影基础设施；Pipeline backend 在其上实现 Pipeline runtime 的唯一控制总线。node、monitor、runner、UniDesk frontend 和 CLI 都只能通过 OA 事件表达事实、订阅事实或发出控制意图。
- Node 之间不得直接启动、暂停、重试或通知彼此；monitor 不得绕过 OA 直接控制 runner；frontend 不得直接写 Pipeline `.state`、prompt 文件、命令队列或 worker 状态文件。
- 事实事件只描述已经发生的事实，策略判断由 OA 加载 Pipeline config/topology 后完成；`node-finished` 不得携带 `legacy audit policy flag`、`nextNodeIds`、`shouldStartDownstream` 这类控制决策字段。
- 控制行为必须由 OA 控制/管理事件表达，例如 start downstream、pause、resume、single-step、append prompt、guide、modify、approve、redo/restart、skip、cancel 和 retry。
- 如果 procedure 或 monitor 结束后缺少预期 OA 提交，runner 必须把它视为可恢复的 OA contract failure：在重试预算内通过 OA 事件写入明确反馈并启动 fresh attempt，不能直接把一次缺失提交升级成最终失败；预算耗尽后才 fail closed。
- UI、CLI、E2E 和调试工具都应消费统一 OA 归一化读接口、`oa-event-flow` 事件表/tag stream 或通过 OA 控制 API 写入事件，不得解析 monitor 文本、worker log、runner 私有文件或旧 JSONL 文件来反推控制语义。
- 旧的本地文件传输通道必须完全退出控制路径：不得创建、轮询或依赖 `control-prompts.jsonl`、`monitor-prompts.jsonl`、`monitor-control`、`control-events.jsonl`、monitor stop 文件、`.state/pipeline-runs/{runId}/control/commands/` 或给 monitor 容器挂载可读 `/pipeline-state` 来完成 prompt、stop、guide、approve、redo/restart、append 或 UI/Gantt 事件取证。

## Benchmark Prompt And Skill Boundary

- Pipeline benchmark 的入口 `task` prompt 必须保持需求导向：描述要恢复的用户可见行为、输入输出和验收目标，不得为了某个 PikaBench 或其他切片在任务 prompt 中写入内部流程控制、精确补丁路线、已知失败符号、采样 item id、隐藏 oracle 细节或上一轮失败诊断。
- Dispatch/repair procedure prompt 只能声明角色、作用域、OA 提交、分支规范、通用验证习惯和安全边界；不得在失败后通过追加“定向解题 prompt”把单个 benchmark 的答案固化进 procedure config。
- 历史运行中沉淀出的可复用经验必须进入版本化 skill 或机械 quality gate：skill 承载领域经验和源码形态经验，gate 只给出可判定的机器证据。若经验不能泛化为 skill/gate，应视为本轮人工调参，不得计入组件贡献。
- 消融实验必须保留干净边界：同一个前门需求 prompt、同一个拓扑和同一个 scorer 下，注入经验型 skill 的 variant 可以使用该 skill；`no-skill` variant 必须能真正移除这部分经验。如果无 skill 仍因 prompt 中残留定向答案而达到满分，该消融结果无效。
- 对 PikaBench-4/PikaBench-8 这类 Pipeline benchmark，若满分依赖把 `list.pop`、`max/min` 等具体修复路线直接写入任务/dispatch/repair prompt，应先把这些路线改写为泛化的 PikaPython benchmark skill 经验，再重跑 baseline 与 no-skill 对照。

## Benchmark Train/Valid Isolation

- 任何用于迭代优化 Pipeline、skill、gate 或 monitor 的 benchmark 切片，都必须在优化前固定一个不重合的 valid holdout；只看 train 满分不能证明泛化。
- PikaBench-4 是当前优先的短循环抗过拟合 benchmark；pipeline config 必须显式声明 `train-banch` 与 `valid-banch`（可保留兼容 alias），分别绑定 `pikabench-4` train scorer/prompt 与 `pikabench-4-valid` scorer/prompt，避免把单一 bench 当作泛化证据。PikaBench-8 只能在 4-item train/valid 先稳定出分后用于更慢的确认。
- Train 与 valid 必须使用同一个 pipeline id、同一拓扑、同一模型、同一重试预算、同一 monitor 策略、同一 merge gate 和同一 per-node quality gate；只允许前门任务 prompt 与最终 scorer/benchmark oracle 不同。
- Train 运行可以完整取证：trace、OA record、node log、gate evidence、scorer failed case 和 artifact 都可以用于分析和改进通用机制。
- Valid 运行在优化期间只能读最终聚合 score，例如 `4/4` 或 `8/8`；不得查看 valid trace、OA record、node log、gate artifact、scorer stdout、failed case id、hidden filter、intermediate file 或生成报告。
- 机制贡献或泛化结论必须以 train 和 valid 同时达到目标分作为验收；若 train 达标而 valid 未达标，结论只能写作过拟合或未通过验证，不能继续用 valid 细节调参。

## Benchmark Execution And Model Quota

- Benchmark execution depends on develop-ready environment readiness. Large optional dependency payloads used by the benchmark build, such as PikaPython `port/linux/package/lvgl/lvgl`, must be pre-cloned or pre-installed by the referenced environment repo Dockerfile in a cacheable layer. Procedure nodes, evidence gates, and scorers must not clone those dependencies ad hoc during the run, because transient network failures then become false benchmark failures and repeated clones defeat Docker build cache.
- If a benchmark stalls or returns a low score because an environment dependency such as LVGL could not be cloned, classify it as infrastructure failure first. The preferred fix is to update the environment repo so the dependency is already present in the develop-ready image and its Dockerfile layer can be reused by subsequent train/valid/evidence builds; shrinking the benchmark denominator is only a diagnostic shortcut after the environment contract is fixed.
- MiniMax quota 是 benchmark 调度资源，不是跳过 Pipeline 实跑的理由。MiniMax 当前按约 5 小时窗口刷新；在窗口内不用完的额度会过期浪费，因此有明确实验问题、修复验证或消融对照时，应在额度可用时启动对应 Pipeline，而不是因担心“额度用完”而空等。
- 成本意识体现在缩小实验切片、减少无效重复、记录 quota/耗时/attempt 和优先跑最小可判定对照；不得把成本意识解释为不跑 baseline、修复后不重跑或不跑关键消融。
- 如果运行中发现 MiniMax quota 已耗尽，应立即转入离线工作：整理已有 scorer/artifact/OA/gate/monitor 证据，定位基础设施与组件边界问题，准备下一轮最小 run plan。等 quota 刷新后必须继续从该 plan 恢复实跑验证。
- 如果 MiniMax quota 在运行中的 node 内耗尽，quota sleep/retry 的墙钟时间不得计入该 node 的 active timeout；否则一次 quota 暂停会被错误放大为 pipeline node 超时，阻塞 score 产出。
- 消融或 benchmark 报告必须区分“quota 暂停”和“实验终止”：因额度耗尽暂停时，结论只能基于已有结果明确标注为临时分析，不能把未跑对照写成已验证结论。

## Event Identity And Tags

- 每条事件必须满足统一 OA envelope：稳定 `eventId`、`type`、`createdAt`、`sourceKind`、`sourceId`、`aggregateType`、`aggregateId`、`correlationId`、可选 `causationId`、`tags` 和 `payload`，用于排序、幂等、回放和追踪控制来源；共享字段契约见 `docs/reference/oa-event-flow.md`。
- Pipeline 后端必须自动附加 scope tag：`service:pipeline`、`pipeline:{pipelineId}`、`epoch:{runId}`，node 相关事件还必须带 `node:{nodeId}`；attempt/procedure 相关事件应带 `attempt:{attemptId}` 或 `procedure:{procedureRunId}`。
- Monitor 在 config 中只声明要订阅的业务 tag 或事件类型，OA backend 在订阅时自动追加当前 `pipeline:{pipelineId}` 与 `epoch:{runId}` 限制，避免不同 pipeline 或 epoch 串流。
- 一次 epoch 应绑定 config snapshot 或 config version；OA 的审核、拓扑推进、并发和单步策略都以该快照为准，避免运行中配置漂移导致控制解释不一致。
- 控制事件必须有幂等键，重复投递同一个 start、approve、redo/restart 或 append prompt 时，OA 应识别为同一意图而不是重复启动或重复写入。

## Fact Events

- `node-started`、`node-finished`、`node-failed`、`node-cancelled`、`node-long-running-observation` 等事实事件用于记录运行状态，不承担流程推进决策。
- `node-finished` 是中性完成事实，包含 node id、procedure run id、status、timestamps、outputs summary 和诊断摘要；它不描述是否需要审核，也不直接声明下游节点。
- 长任务观察事件只在 node 未进入终态时触发，默认节奏为 2、5、10、20 分钟，之后每 20 分钟循环；固定 30 秒 monitor 周期不得作为正式机制保留。
- `legacy batch completion gate` 只能作为派生统计或兼容只读事件，不能作为流程推进门禁；下游推进由每个 `node-finished` 加 OA config/topology 判断完成。
- 如果 node 完成后需要 monitor 审核，UI 中仍只应保留这一条 `node-finished` 作为完成/等待审核的事实点，不再创建独立的 `legacy node audit request event` 或 `legacy monitor audit request event` 事实点。

## No-Audit Flow

1. Runner 观察到 node 进入终态，并把中性 `node-finished` 事实推入 OA backend。
2. OA backend 记录事件，加载该 epoch 的 config snapshot 和 topology。
3. OA 判定该 node 不需要 monitor 审核，且下游依赖已满足。
4. OA 产生下游 `start-node` 控制事件。
5. Runner 只消费 OA 控制事件来启动下游 node，并把启动结果再写回 OA 事件流。

## Audit Flow

1. Runner 把中性 `node-finished` 事实推入 OA backend。
2. OA backend 记录事件，并按 config snapshot 判定该 node completion 需要 monitor 审核。
3. Monitor 通过 OA 订阅收到同一 scope 下的 `node-finished` 事实和 prompt；是否需要审核来自 OA policy，不来自 `node-finished.detail`。
4. Monitor 通过 OA skill 或等价 OA 控制 API 发出 `approve`、`modify`、`redo/restart`、`reject` 等管理事件。
5. OA backend 记录 monitor 决策，按 config/topology 产生 start downstream、reset downstream、restart target 或 stop/pause 等后续控制事件。
6. Runner 只消费 OA 控制事件执行后续动作，执行结果继续回写 OA 事件流。

## Single-Step And Debug Flow

- 单步运行、人工放行、暂停、恢复、重试、跳过和取消都必须建模为 OA 控制事件；不得通过调试 HTTP 端点直接修改 runner 内存状态。
- CLI 和 UniDesk frontend 的 node 精细控制面板只能调用 Pipeline 后端的 OA 控制 API；后端可保留 `node-control` 路由名，但路由内部必须写入 OA 事件并由 OA dispatcher 执行。
- Debug 工具可以读取事件流、config snapshot 和归一化状态机结果，但不得维护另一套流程推进逻辑。

## Rendering Contract

- UniDesk Pipeline UI 只消费 Pipeline 后端根据 OA 事件流生成的 snapshot、Gantt DTO、node detail 和 control history，不直接消费旧 monitor append 文件语义。
- 甘特图中的执行条、prompt 点、monitor 决策点、长任务观察箭头和人工控制箭头都必须来自 OA 事件或 OA 派生 DTO。
- 有 monitor 的 pipeline 中，monitor node 固定在甘特图第 1 列，其余 node 再按拓扑上游到下游向右排列。
- `node-long-running-observation` 必须画从被观察 node 到 monitor node 的观察连线；被观察 node 上不得额外绘制“观察来源”点，因为点只代表真实行为。
- Running node 必须显示从实际开始时间延伸到当前时间的实时闪动执行条；相邻 OpenCode step 之间的真实空闲区间必须留白，不能被连续装饰线误渲染为执行。
- 审核开启时不得同时渲染 `node-finished` 和独立 audit-request 点；node completion 是唯一完成/等待审核点，monitor 的 approve/modify/redo/restart 是后续独立控制点。

## Migration And Completion Gates

- 分阶段重构只允许按“统一 oa-event-flow schema 文档与测试门禁 -> Pipeline/Code Queue 事实事件写入 -> OA dispatcher 接管 Pipeline 控制 -> UI/CLI 改为 OA 读写 -> 删除旧事件、旧统计和旧控制路径”的方向前进，不得把双写/双读作为最终设计。
- 远端 Pipeline 尚未直接发布到主 server `oa-event-flow` 时，可以通过主 server Pipeline snapshot bridge 把 `/api/snapshot` 与 `/api/oa-event-flow/diagnostics` 形成的结构化运行事实以 `service:pipeline`、`pipeline:{pipelineId}` 和 `epoch:{runId}` tag 写入统一事件表；该 bridge 是迁移期单一路径接入层，只能保持幂等可见性，不能成为新的控制权威，也不得保留 ledger/snapshot 双路径 fallback。Pipeline 直接发布统一事件后必须删除该 bridge。
- 完成态必须删除或禁用以下残留：`legacy detail audit policy flag` 作为权威策略字段、`legacy node audit request event` / `legacy monitor audit request event` 独立审核请求事件、`legacy batch completion gate` 控制推进、monitor 直接调用 runner、node 直接启动下游、frontend/CLI 直接写 `.state` 文件。
- 完成态还必须删除文件传输残留：`PIPELINE_MONITOR_APPEND_FILE`、`PIPELINE_MONITOR_STOP_FILE`、`PIPELINE_MONITOR_CONTROL_DIR`、`PIPELINE_NODE_PROMPT_APPEND_FILE`、`control-events.jsonl`、`runControlEventFile`、`appendJsonLine`、`readJsonLineRecords`、`readPromptAppendFile`、`parseCommandFile`、`parseMonitorCommandFile`、`readMonitorCommands`、`fallbackMonitorInterventions`、`syntheticMonitorStopPrompt` 以及 monitor 的 `/pipeline-state` 挂载都不得出现在运行代码中。
- E2E 必须覆盖有审核与无审核两条链路：无审核时由 OA 从 `node-finished` 推进下游；有审核时由 monitor 经 OA 控制事件推进下游；事件都必须带 `pipeline:{pipelineId}` 与 `epoch:{runId}` tag。
- Pipeline 甘特图 E2E 必须证明没有重复审核点、长任务观察有连线且无来源伪点、running node 有实时条、OpenCode step 空闲区间留白、控制箭头来自 OA 控制事件。
- 代码检查应优先使用防回归搜索或原入口验证，防止重新引入 `legacy audit policy flag` 权威字段、旧 audit-request 事件、`legacy batch completion gate` 推进逻辑或非 OA 控制写路径；除非用户明确要求，不新增测试脚本。
