264 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
topic: prompt治理
canonical: true
date: 2026-06-24
---
# Prompt 治理 · 生成引擎设计文档
> 🚧 **架构演进中** —— 廉价线 **gameDefinition 已废(错误路线),现行 = A-model 写真 `src/`**;tier2 富游戏自治轨建设中(0 号 spike accept)。文中结论可能随推进变化,以子树 [README](README.md) / 运行时 SoT [`agentic运行时架构图说`](agentic运行时架构图说.md) 与最新裁定为准。
> **这是什么**绘境AI 生成引擎里「Prompt 治理」这一子系统的设计文档,回答"**为什么把 prompt 当成一份正式契约来管、它长什么样、改一条 prompt 要过哪些关、人在什么环节介入**"。
> **给谁看**:负责生成主线的后端工程师、写 prompt 的工位负责人、做架构评审的人,以及想搞清楚"生成质量为什么可控、可回归"的新同事。
> **怎么读**:先读 §1 建立"prompt 为什么要当契约管"的整体认知,再看 §2 的数据流图理解它在生成链路里的位置;§4 是这套体系的心脏(改一条 prompt 的四道关),§6 讲人怎么介入;想要落地细节从 §3、§5 看接口与目录结构。
生成引擎是绘境AI 护城河的关键路径,而 prompt 是这条路径上**最容易失控的一环**。模型每天在变、链路上有十几个地方会调用它、一句话改动就可能让生成质量悄悄塌掉。这份文档讲的就是:如何把这堆散落、易变、改了没人知道的文本,收成一份**可版本化、改动可自动回归、人能在关键节点把关**的工程资产。
---
## 1. 一句话与核心理念:Prompt 是第 8 类契约
绘境AI 把所有 prompt 统一收进 git 仓库的 `contracts/prompts/` 目录,作为整个项目的**单一事实源**(single source of truth,意为"这件事只有一个权威出处,别处都不算数")。这个决策有一个明确的定位——**Prompt 是项目的第 8 类契约资产**。
要理解这句话的份量,得先解释"契约"在本项目里是什么。绘境AI 在开工第一天(内部称 Day-0)就锁定了 7 类跨端契约:API 接口定义、数据库迁移脚本、客户端 SDK、游戏产物包格式、事件埋点、生成任务的 job/callback 协议、广告位定义。它们的共同特征是:**多个团队都依赖它、谁都不能私自改、改了必须走评审**。把 prompt 提升为"第 8 类契约",就是宣布:**prompt 和数据库 schema、API 定义是同一个等级的东西,不再是某个工程师藏在代码里、想改就改的字符串。**
为什么必须这么管?因为生成主线是一条多步、多模型的流水线,prompt 的数量和形态会持续膨胀。如果没有单一事实源,会同时出现三个致命问题:**改了没人知道**(prompt 内嵌在某个节点代码里,改动不留痕)、**改了无法验证**(没有基线,不知道这次改动让质量变好还是变坏)、**跨链路无法统一治理**(同一类约束散落在十几个地方,改一处漏九处)。
这套体系的核心承诺,可以浓缩成一条纪律:
> **每条 prompt 都绑定一份完整契约——输入 Schema + 输出 Schema + 硬约束块 + Golden 样本集 + owner + version;运行时按 `id@version` 加载注入,绝不在编排内核里内嵌。**
这里有两个名词先解释清楚:**Schema**(模式)是一份机器可读的"格式说明书",规定输入/输出必须长什么样,不符合就报错;**Golden 样本集**(也叫黄金集)是一组"标准答案"——固定的输入配上期望的产物,用来在每次改动后自动比对"还对不对"。"按 `id@version` 加载"的意思是:prompt 像一个带版本号的库依赖,代码只持有它的编号(如 `config.clicker-designer@1.1.0`),真正的文本从 Registry(注册表,即上面那个目录)里取——这样换 prompt 不用重新编译代码,改文本即生效。
这条"能力增强放壳层、不动内核"的纪律,和生成引擎其它子系统是一脉相承的:生成逻辑藏在 job/callback 契约之后、框架可替换而业务契约不变;同理,prompt 藏在 Registry 之后,文本可迭代而调用代码不变。
> **引擎上下文纠偏(2026-06-12 立、2026-06-25 框架 reframe 更新)**:本体系的**核心理念——Prompt 即第 8 契约 / Registry / eval 门禁 / HITL——现行有效、永久不变**。但本文涉及"注入到哪个引擎、由哪个框架编排"的具体载体,按现行架构理解:**Dify(一个可视化 LLM 工作流编排平台)和 OpenGame(一个文生游戏代码的第三方服务)已降级为远期增强、从未在 MVP 部署**;当前 Tier1(第一梯队、即 MVP 生产主线)的生成主线是 **new-api 网关 + agent 把代码写进插件库**(new-api = 绘境AI 内部统一的模型成本/凭证网关,所有模型调用都走它;插件库引擎 = LittleJS 增强发行版)。编排框架早期用的是 SAA 裸 StateGraph(SAA = Spring AI Alibaba,阿里的 Spring 生态 AI 编排框架),2026-06-25 已收敛到 **AgentScope**(自治 agent 框架),SAA 随之降为最低优先级、留作远期适配验证。下文凡提"注入目标",按此理解;**治理机制本身与载体无关,完全不变。**
---
## 2. 数据流:Prompt 治理在生成链路里的位置
把 Prompt 治理放进生成主线来看,它扮演的是一个**横切的供给与把关层**:一边给生成链路供给 prompt 文本,一边在 prompt 变更进入生产前拦一道质量门。下面这张图描述了这两条数据流——左侧是**运行时供给**(实线),右侧是**变更治理**(从一个 Pull Request 出发的虚线闭环)。
```mermaid
flowchart LR
subgraph SOT["单一事实源"]
GIT["contracts/prompts/<br/>(git 仓库 · 第 8 类契约)"]
end
subgraph RUNTIME["运行时供给(实线)"]
LOADER["PromptRegistryLoader<br/>加载 / 渲染器(aigc 壳层)"]
NODE["编排框架各节点<br/>(render / design / generate / qa ...)"]
MODEL["new-api 网关<br/>→ 大模型"]
end
subgraph GOV["变更治理(虚线闭环)"]
PR["Prompt 改动 PR<br/>(必须升 version)"]
CI["prompt-eval CI<br/>(PR 触发)"]
GATE["四道闸<br/>Schema / 成功率 / 回归 diff / 成本延迟"]
HUMAN["人工抽检<br/>(HITL 把关)"]
MERGE["合入 → 部署同步"]
end
GIT -->|"按 id@version 读"| LOADER
LOADER -->|"渲染后注入"| NODE
NODE --> MODEL
PR -.->|触发| CI
CI -.->|读基线 + 跑样本| GIT
CI -.-> GATE
GATE -.->|全绿| HUMAN
HUMAN -.->|批准| MERGE
MERGE -.->|更新| GIT
TEL["telemetry 行为指标<br/>(线上真实表现)"] -.->|反哺改进| PR
style GIT fill:#d6eaf8
style GATE fill:#f9e79f
style HUMAN fill:#fadbd8
```
读这张图抓住三点就够了:
- **供给侧是只读的、轻量的。** 生成链路的每个节点要 prompt 时,经 `PromptRegistryLoader`(加载器)按编号从 Registry 取文本、填入变量、注入给模型。Registry 是一份**文件契约,不是一个服务**——所以它不引入新的跨模块强耦合,也不会成为一个会宕机的依赖。
- **治理侧是闭环的、有门的。** 任何人想改 prompt,都得提一个 PR(Pull Request,代码改动的评审请求),并且**必须升 version**(改了不升版号该被拒)。设计目标是 PR 一提就由持续集成(CI)自动跑"四道闸"——这是本体系最核心的质量门,§4 详述。**现状(2026-07-04 已接线)**:四道闸已焊成 CI,按成本分两段落地。**段 A 离线版本闸**兜闸 0"改正文必升 version",随每次提交自动跑(`contracts/prompts/check_version_bump.py`,挂 pre-commit 与 contract-gates 服务端门,秒级、零成本、不可绕);**段 B 真模型闸**跑闸 1~4(Schema成功率回归 diff成本延迟),对改动的 prompt 拿其金标集真调 MiniMax-M3 判定,由 `prompt-eval` 工作流手动触发(workflow_dispatch),单跑预算硬上限 ≤¥5。判定逻辑是按 registry 契约重建的薄版(早期 W-G1 批跑编排 `evalflow.py` 曾跑出数据,已随 agent-loop-v1 归档、`git show 6d2f8789^:docs/agent-specs/2026-06-09-agent-loop-v1/orchestrator/evalflow.py` 可查,此处不整套复活)。纪律不变:prompt 改动合入前至少真跑一次段 B、四闸全绿再交人工抽检批准,才允许合入并同步到生产。**段 B 只焊 live 消费面**——现行真被生成路径喂 LLM 的是 `01-safety`(合规门)、`09-tier2-richgame` 八条、`04-config/cheap-system`;已下架的 gamedef 四策划模板(clickermergeidletycoon)与 generic-coder STUB 等化石条目显式豁免、不花真模型钱,逐条三态见 [`registry.yaml`](../../../../contracts/prompts/registry.yaml) 头部消费面对账总表。
- **数据回流让 prompt 越改越准。** 线上的 telemetry(遥测,即用户真实行为埋点数据)会反哺回来:哪类 prompt 产出的游戏没人玩、留存差,就成为下一轮改 prompt 的依据。这一条把"治理"从被动防退化,升级成主动求进步。
依赖方向很干净:**壳层 → Registry(读);CI → Registry(读)+ 模型(跑样本);运行时构建流水线 → 测试原子(执行)。** 没有任何一条引入新的服务级强耦合。
---
## 3. Registry 长什么样:目录结构与一条 prompt 的构造
Registry 的物理形态就是 `contracts/prompts/` 下的一棵目录树。它按**生成生命周期的阶段**分目录,每个阶段放该阶段会用到的 prompt。当前实现采用 **8 阶段编号命名**(便于一眼看清执行顺序),其中已入库的几个阶段如下:
```
contracts/prompts/
├── registry.yaml # 索引:所有 prompt 的 id / 版本 / owner / 绑定 schema / eval 集
├── _schemas/ # (规划,未落地)输入 / 输出 JSON Schema(prompt 的格式契约)
│ # 现状:此目录暂缺位,frontmatter 的 schema 字段直接指向真实契约文件(见 §3 示例)
├── 01-safety/ # 创作者输入的安全 / 注入检测(生成链路第 1 道节点)
├── 04-config/ # 各玩法的策划 prompt(clicker / merge / idle / tycoon ... designer)
│ # + generic-coder(P3 编码 prompt,⚠️ 当前为 STUB 占位骨架,待 L1 出正式草案)
├── 06-quality/ # 对抗式质量评审 prompt(adversary-review)
├── 07-fix/ # 按评审意见回灌重出的修订 prompt(design-revise)
└── eval/ # 每条 prompt 的 Golden 样本集,目录名 = prompt id
```
> 阶段编号的完整规划是 `01-safety 02-intent 03-template 04-config 05-asset 06-quality 07-fix 08-meta`;上面只列出当前已落地的几个。其余阶段随生成链路演进逐步迁入,Registry 的设计本就允许增量入库。
>
> **"已入库"≠"已接 live 生成路径",两者要分清**——逐条三态以 [`registry.yaml`](../../../../contracts/prompts/registry.yaml) 头部消费面对账总表为准。① **live 消费面**(真被生成路径喂 LLM)= `01-safety` 合规门、`04-config/cheap-system` 便宜档系统提示、`09-tier2-richgame` 八条富游戏提示。② **化石**:gamedef 时代的四个策划模板(clicker / merge / idle / tycoon)随 gamedef 路线作废已下架,后端模板白名单 `SUPPORTED_TEMPLATE_IDS` 收敛为 `["generic"]`、不再走"填参选模板"那条线;它们连同 06-quality / 07-fix 只留库里作历史留痕,早期由 W-G1 批跑编排(`evalflow.py` 等 `orchestrator/*.py`,已随 agent-loop-v1 归档、`git show 6d2f8789^:docs/agent-specs/2026-06-09-agent-loop-v1/orchestrator/evalflow.py` 可查)消费,不接 live game-cloud、不花真模型钱。③ generic-coder 是 **STUB**:`registry.yaml` 标其 `version 0.0.1 ⚠️ STUB 占位骨架`(仅 frontmatter + 三要点提纲,非正式 prompt),后端入库它只为让加载器 `isReady()` 通过、schema 进校验缓存,**不在进程内拿它喂 LLM**。
**每条 prompt 的构造 = 一段 frontmatter 契约头 + 模板体。** frontmatter(前置元数据,写在文件顶部 `---` 之间的结构化字段)就是这条 prompt 的"契约头",声明它的身份、版本、归属和绑定的 schema/eval。模板体则是真正发给模型的文本,里面带变量槽(运行时填入)。一个示意:
```yaml
---
id: config.clicker-designer # 唯一编号(阶段.角色)
version: 1.1.0 # 语义化版本号,改一字也要升
owner: WS2 # 唯一负责工位(改它必须经其批准)
tier: tier1 # tier1 | tier2 | tier3(梯队)
stage: "04-config" # 所属生命周期阶段
engine: newapi-chat # 目标引擎(单引擎 new-api/SAA 下已退化为假设值,枚举未定,见下注)
input_schema: "../../agent-loop/game-design.schema.json#/properties/idea" # 输入格式契约(真实路径)
output_schema: "../../agent-loop/game-design.schema.json" # 输出格式契约;config 段逐字段真源 = ../../templates/clicker.schema.json
constraints: # 硬约束块(产物必须满足的红线)
- 首屏 ≤ 2MB,总包 ≤ 10MB
- 游戏内零网络请求
eval_set: eval/config.clicker-designer/ # 绑定的 Golden 样本集
guardrails: [injection-detect, schema-validate] # 护栏:注入检测 / schema 校验
---
{{system_prompt}}
... 模板体,带 {{变量槽}} ...
```
frontmatter 里几个字段值得点名:**owner**(归属工位)规定了"谁能改这条 prompt"——本项目把工位编号为 WS1~WS5(WorkStation,工位),改一条 prompt 要经它的 owner 批准,杜绝无主乱改;**tier**(梯队)区分 prompt 的重要性,tier1 是 MVP 生产主线必须治理的,tier2/3 是更长期的增强轨;**constraints**(硬约束块)是产物必须守住的红线(如包体大小、零网络请求),**guardrails**(护栏)是运行时挂的自动检查(如注入检测、schema 校验)。**engine**(目标引擎)在设计期是区分注入载体的必填枚举,但在现行**单引擎**(new-api / SAA)语境下已退化为假设占位值(真实文件里写作 `engine: newapi-chat` 并自注"枚举未定"),不再是有效的区分维度——保留它只为与真实 frontmatter 一致。另注:示例里的 `input_schema` / `output_schema` 指向真实契约文件(`../../agent-loop/game-design.schema.json` 等),因为 §3 目录里那个 `_schemas/` 目录尚未落地(见上文目录树标注)。
`registry.yaml` 是这棵树的总索引,逐条登记每个 prompt 的 id、版本、owner、绑定的 schema 和 eval 目录。它和文件系统的实际内容必须**严格一致**——这份索引↔文件的 version 对账由 `contracts/prompts/check_registry.py` 负责(2026-07-03 已挂 `.githooks/pre-commit` 与 Gitea Actions 服务端门,零依赖、退出码可拦提交;它与 §4 四道闸质量闸各管一摊、互不等待——四道闸尚在接线,version 对账已先行上门),在合入前挡下"配置漂移"(加载器自身只逐模板自检自禁用、不复制此对账逻辑,见 §5/§7)。
---
## 4. 心脏:改一条 prompt 要过的"四道闸"
这套体系真正的价值,在于**让"改 prompt"这件高风险的事变得可回归、可拦截**。机制是:对一条 prompt 跑四道自动闸门,全绿才放行——这套判定逻辑已按 registry 契约重建成薄版并接成 CI(段 A 版本升号闸随提交自动跑、段 B 真模型闸经 `prompt-eval` 工作流 workflow_dispatch 触发,详见 §2;早期 W-G1 批跑编排 `evalflow.py` 曾跑数据)。"四道闸"是本体系的核心门控,逐一解释:
```mermaid
flowchart TB
START["Prompt 改动 PR"] --> V{"version 升了吗?"}
V -- "没升" --> REJECT1["拒绝合入<br/>(version 未变)"]
V -- "升了" --> G1{"闸 1<br/>Schema 校验"}
G1 -- "产物不合 schema" --> REJECT2["拦截 · 报具体字段"]
G1 -- 通过 --> G2{"闸 2<br/>成功率 ≥ 0.8"}
G2 -- "低于阈值" --> REJECT3["拦截 · 质量退化"]
G2 -- 通过 --> G3{"闸 3<br/>回归 diff"}
G3 -- "关键字段变了" --> REJECT4["拦截 · 偏离基线"]
G3 -- 通过 --> G4{"闸 4<br/>成本 / 延迟"}
G4 -- "超出阈值" --> REJECT5["拦截 · 变贵 / 变慢"]
G4 -- "四闸全绿" --> HUMAN["人工抽检(HITL)"]
HUMAN -- "批准" --> MERGE["合入 → 部署同步"]
style HUMAN fill:#fadbd8
style MERGE fill:#a9dfbf
```
- **闸 0 · version 必升(前置硬门)。** 改了 prompt 却没升 `version`,CI 直接卡死。这条看似琐碎,实则是整套版本化治理的地基——没有它,"按 `id@version` 加载"和"回归比对基线"全都失效。
- **闸 1 · Schema 校验。** prompt 产出的结果必须符合它声明的 `output_schema`。不合格就拦截,并**报出具体是哪个字段不对**,而不是只说一句"失败了"。
- **闸 2 · 成功率门(≥ 0.8)。** 拿这条 prompt 跑一遍 Golden 样本集,**成功率必须 ≥ 80%**。这个 0.8 不是随手定的——它直接对齐绘境AI 的 MVP 顶层指标"AI 生成成功率 ≥ 80%"。任何 prompt 改动一旦把成功率拖到这条线以下,就是质量退化,必须拦。
- **闸 3 · 回归 diff(黄金比对)。** 把改动后的产物和基线快照(`baseline/`)逐字段比对,盯住一组**关键字段**(`golden_diff_fields`)。如果这些关键字段相对基线发生了不该有的偏移,说明改动产生了预期外的副作用,拦截。
- **闸 4 · 成本 / 延迟门。** 检查这次改动有没有让生成**变得更贵或更慢**——`max_cost_delta`(成本增量上限)、`max_latency_delta`(延迟增量上限)。因为绘境AI 的整体策略是"便宜模型 + 门兜底",一条让单次生成成本翻倍的 prompt 即使质量没退化,也可能突破成本红线(MVP 基础设施成本 < ¥5000/月),必须把关。
四闸全绿之后,还要过**人工抽检**——这就是下一节要讲的 HITL。**机器闸拦掉的是"可量化的退化",人抽检的是"机器量不出来的味道"**(比如产物虽合规但玩起来无聊)。两者叠加,才构成完整的把关。
> 一个体现纪律的细节:eval 的判定阈值(成功率、关键字段、成本/延迟上限)是写进 prompt 自身契约的(`eval_set` 指向的目录),而不是写死在 CI 脚本里。这样每条 prompt 可以有自己的质量标准,治理框架统一、标准各异。
---
## 5. 接口契约:加载器与测试原子
这套体系对外暴露两组关键契约。第一组是 **prompt 加载器**(设计期称 `PromptRegistryLoader`,现行落地实现为 `PromptResourceLoader`),它是生成链路读取 prompt 的唯一入口,接口形态(契约,非实现)如下:
```
PromptTemplate load(id, version) # 取一条 prompt(含 frontmatter + 模板体);缺失抛 PromptNotFoundException
String render(id, version, vars) # 把变量填进模板,渲染成最终文本
List<PromptMeta> list(stageOrEngine) # 按阶段 / 引擎列出 prompt
boolean validate(PromptTemplate) # 校验 frontmatter 与 schema 绑定是否有效
```
**现行加载策略是"构建期快照、缺失即自禁用"**(对应实现 `PromptResourceLoader`,方案 A):构建时由 maven-resources 插件把 `contracts/prompts/` 与对应 schema 复制进 jar 的 `classpath:wanxiang-contracts/`(jar 内只是构建快照,**git `contracts/` 仍是唯一事实源**——改 prompt = 改原文件 + 升 version + 过四道闸,下次构建部署自动携带新版)。加载器启动时**逐模板自检**,任一模板的 prompt/schema 资源缺失或形态非法,就把整体 `ready` 置为 `false`(自禁用信号),执行器据此永不带病认领任务——不抛异常、不崩进程。
**目标态:采 Langfuse 式的运行时热取,替掉构建期快照。** 对标 2025 收敛的 prompt 热管理标准,"改 prompt 要改原文件、升版本、过四道闸、再重新构建部署才生效"是把一份本该热改的配置钉死在构建期的反模式。目标加载策略是把注册表做成运行时可热取:加载器按 `id@label` 在运行时拉取文本、带缓存 TTL(约 60 秒)与后台刷新、取不到时回落到上一次缓存或内置默认,配置当数据(config-as-data)热改、不重新构建部署。四道闸的治理纪律一条不动——版本化、改动可自动回归、人在关键节点把关全保留,变的只是新版怎么到达运行时:从构建期注入快照,改成运行时按 label 拉取。这与生成运行时架构的 A13 配置注册表(同采 Langfuse 式运行时热取)是同一口径,见 [agentic运行时架构图说 §5.2](agentic运行时架构图说.md);tier2 那条 Python 线的 genconfig 已是雏形,要推广到后端主线。
**热取分 read / write 两路(§6.8 双评审修正,2026-06-24)**:运行时热取只解决"新版怎么到达运行时",**不等于绕过治理**。read path——运行期只拉**已批准版本**(按 production label/version),缓存+回落保证可用;write path——改一条 prompt、调一个生成门阈值,仍走四道闸的 version bump + eval + 灰度 + 人工批准(GitOps 审计留痕),**不 DB 热改、不绕审批**。只有运营降级开关/配额数值这类不影响生成质量与安全的配置才 DB 即时热改。坏版本经 label 秒回退,并记录其生效期间产出的 game_id 以便追溯。这条把 §1"prompt 是影响安全的第 8 契约"与"热取便利"调和:便利在 read,纪律在 write。
> 这里不存在"数据库只读镜像",也没有"运行时回源 git checkout":那是早期设计期契约里设想的载体,工程落地改走了更简单的构建期快照路。`registry.yaml` 与文件的 version 对账由 `check_registry.py` 承担(2026-07-03 已挂 pre-commit + Gitea Actions),加载器不复制治理逻辑。
第二组契约值得专门点名,因为它把"prompt 治理"和"产物质量"接到了一起——这就是 **T-AGC-09 测试脚本原子**(原子 = 生成流水线里一个不可再分的处理单元;T-AGC-09 是它的工序编号)。**注意它当前是设计/规划态契约,尚未实现**(game-cloud 内暂无对应实现);其规划接口形态如下:
```
TestScript generate(GameConfig config) # 输入游戏配置 → 输出测试脚本(启动 / 输入响应 / 边界断言)
// runtime 编译后执行该脚本:通过 = 准许入库;失败 = 拒绝入库 + 原因分类
```
它的意义在于:生成出来的游戏**在入库发布之前,应先被一段自动生成的测试脚本验证"真的能跑"**——能不能启动、按键有没有响应、边界条件会不会崩。跑不过就拒绝入库,并对失败原因分类。这是 prompt 治理体系规划在"产物侧"埋的一道闸:**prompt 把关的是"怎么生成",T-AGC-09 要把关的是"生成出来的到底能不能玩"。**
> **现状口径**:当前真正生效的入库实拦是生成引擎的**九门 harness**(把产物放进真实运行环境自动检验的九道确定性门——见同目录 [README §3.2 区](README.md));T-AGC-09 是产物侧的**规划门**,与九门是同一种工程哲学的延伸(宁可显式拦截,绝不让坏产物进库)。它原设想的落点是 GameConfig 模板这条路的产物自测,而 gamedef/GameConfig 线已废;规划门"产物侧自动验证真能跑"的意图保留,但落到现行 A-model 真 `src/` 产物形态上需重新定义,当前入库实拦仍由九门 harness 承担。
---
## 6. 人在哪里介入:HITL 治理
把 prompt 治理做成纯自动化是危险的——机器闸能量化的退化拦得住,但"产物虽然合规却很无聊""这版文案语气不对"这类**需要人判断的灰色地带**,只能靠人。所以本体系刻意保留了 **HITL**(Human-In-The-Loop,人在环路中)节点,分两侧落地:
- **创作者侧 HITL** 复用生成链路里已有的"重生成 / 锁风"交互:创作者对生成结果不满意时,可以触发重新生成或锁定风格(让后续迭代保持一致的视觉/玩法风格)。这是**面向终端用户**的人在环——用户本身就是质量的一道闸。
- **运营侧 HITL** 是 prompt 变更的批准闭环:运营/工位负责人走"改 prompt → 跑 eval → 人工批准"这条流程。在产品形态上,这最终会落成 game-admin(管理后台)里的一个 prompt 管理页(规划为 P1 优先级);在它就绪之前,**可以先用 PR 流程 + 文档化规范替代**——即四道闸跑完、人在 PR 里 review 批准后合入(正是 §4 那张图最后两步)。
HITL 在整条链路里的位置很明确:**它永远站在机器闸之后**。先让自动化把可量化的退化全拦掉,把通过的候选交给人;人只需在机器认证"没退化"的基础上,判断那些机器判断不了的事。这样既不让人淹没在该由机器做的重复劳动里,也不让纯机器闸放过它根本看不见的问题。
---
## 7. 它怎么坏 & 怎么修:失败路径与回滚
一套治理体系必须诚实回答"它自己出故障时会怎样"。下面是关键失败路径与对应处理——核心原则是**任何治理层的故障都不应该阻断生成主链路**:
| 失败场景 | 处理方式 |
|---|---|
| prompt id/version 不存在 | `load` 抛异常 → 壳层**回退到内置默认 prompt** + 告警,**不中断生成** |
| frontmatter / schema 形态非法 | 加载器启动逐模板自检不过 → 整体 `ready=false` **自禁用**(执行器不带病认领任务),并由 CI 报出具体字段;**不抛异常、不崩进程** |
| eval 跑不通(模型限流 / 超时) | CI 标记 skip + 通知人工兜底审,**不阻塞紧急修复** |
| 改 prompt 未升 version | CI 卡死:version 未变 → 拒绝合入(即 §4 的闸 0) |
| registry.yaml 与文件 version 不一致 | 由 `check_registry.py` 对账拦截(2026-07-03 已挂 pre-commit + Gitea Actions;加载器不复制此治理逻辑,见 §5);合入前挡下漂移 |
回滚同样是分层设计的,**整体回滚成本极低**,因为 Registry 是一个**叠加层**——它叠在原有调用方式之上,而不是替换掉:
- **单条 prompt 回滚**:切换 `version`,或对该 prompt 文件 `git revert`
- **加载机制回滚**:加载器失败时自动回退到内置默认 prompt,生成不中断。
- **整体体系回滚**:关闭 Registry 加载开关,回到 prompt 内嵌在节点里的旧形态——**旧内嵌 prompt 从不删除、只是不被引用**,开关一切回即恢复。
这套"叠加层 + 开关回切"的设计,正是 §1 那条纪律("能力增强放壳层、不动内核")在可靠性维度上的兑现:治理是给生成主线**加的一层保险**,而保险本身坏了,主线照样能跑。
---
## 8. 验收口径:这套体系怎么算"建成了"
最后给出这套体系的完成判据(验收时逐条核对):
1. **入库完整**:Tier1 全链路 prompt 都进了 `contracts/prompts/`,`registry.yaml` 索引完整、与文件一致。
2. **加载跑通**:生成时 prompt 真实来自 Registry(而非节点内嵌),改文件即生效。
3. **门禁生效**:四道闸至少对一条 prompt 生效——**故意改坏一条 prompt,应被四闸拦下;正常改动则放行**(已接成 CI:段 A 版本升号闸随提交跑、段 B `prompt-eval` 真模型闸经 workflow_dispatch 触发;已对 `safety.prompt-check` 兑现——砍坏其判定被闸 3 回归 diff 逮住、正常小改升版放行)。
4. **产物把关**(规划态):T-AGC-09 产出测试脚本、生成流水线在入库前执行它以拦住"不可运行"的产物——此为待达成条件;当前入库实拦由九门 harness 承担(见 §5)。
5. **HITL 闭环可走**:运营能完整走通"改 prompt → eval → 批准"流程(页面或文档化流程均可)。
一句话收尾:**Prompt 治理把生成引擎里最易变、最易失控的一环,变成了和数据库、API 同级的工程契约——可版本化、改动可自动回归、人能在关键节点把关,而这一切都以"不拖慢、不阻断生成主线"为前提。** 这是绘境AI 让一个普通模型稳定产出可上线游戏的关键支撑之一。
---
## 9. 相关文档导航
| 文档 | 关系 |
|---|---|
| [`.agents/skills/prompt-governance.md`](../../../../.agents/skills/prompt-governance.md) | 本体系的可复用操作手册(playbook):新增/修改 prompt、搭 Registry、对接 HITL 的标准步骤 |
| [生成运行时架构](agentic运行时架构图说.md) | 生成主线的编排运行时——prompt 正是注入到这些节点里 |
| [生成引擎主文档](README.md) | 生成引擎整体:一句话怎么变成一款游戏,以及"LLM as 工作室"范式 |
| [`contracts/prompts/registry.yaml`](../../../../contracts/prompts/registry.yaml) | Registry 的实际索引,所有 prompt 的权威登记 |
> **纪律**:本文讲 prompt 治理的**设计与契约**;具体某条 prompt 的内容在 `contracts/prompts/` 各阶段目录里,标准操作步骤在配套 playbook 里。三者各司其职、互不重复。