diff --git a/docs/external/architecture-brief.zh.md b/docs/external/architecture-brief.zh.md new file mode 100644 index 0000000..80a7a77 --- /dev/null +++ b/docs/external/architecture-brief.zh.md @@ -0,0 +1,68 @@ +# 虚拟电厂 AI 平台 — 系统架构 + +**基于光明电力大模型的虚拟电厂多时空协同智能运营平台** + +--- + +本平台是面向湖北虚拟电厂运营的 AI 协同决策与受控执行系统。五类 LLM 智能体生成市场申报、调度方案与负荷控制计划;任何对外效果产生之前,都必须经过一条确定性的可信执行链。三条设计承诺定义了整个架构: + +- **两平面分离,唯一通道。** 慢速的认知平面(LLM 智能体,分钟到天)与快速的控制平面(确定性执行,秒级)严格分离,可信执行链是两者之间唯一的通道。 +- **LLM 不算数。** 申报价格、电量与控制设定值只能来自版本化的预测、优化与仿真工具;Proposal 中的每一个数值字段都是对某次已记录工具调用的引用。 +- **包络自治。** 人工审批的对象是包络(带有效期的边界授权),而不是每一笔动作。包络内的动作经规则校核与仿真验证后自动放行,其余一律升级人工。包络从空集起步,仅凭证据放宽。 + +## 1. 系统上下文 + +![系统上下文](img/zh/01-system-context.png) + +平台向上对接省级交易平台、调度/负荷管理系统与计量结算系统,向下聚合可调资源(现状 31 MW,目标不低于 80 MW)。运营人员通过运营工单台工作:每一项 AI 产出都挂在一张有明确目标、责任人和期限的工单之下。平台是既有 3060 平台之上的叠加层:复用主数据与权限体系,并把所有申报与控制动作收敛到唯一一条留痕通道,使任何动作都无法绕过可信执行链。 + +## 2. Agent Runtime + +![Agent Runtime](img/zh/02-agent-runtime.png) + +工作流才是入口,Agent 不是。每个业务流程(日前申报、复盘、日内纠偏)都是一条确定性、可持久化的步骤链,Agent 只在特定步骤被调用,并且只能使用白名单内的工具:产出数字的计算类 Skill,以及按需获取细节的只读检索工具。周期触发与事件触发直接实例化流程模板,全程不经过 LLM;只有人工请求经过路由 Agent,而路由 Agent 的输出被 schema 约束为「已注册模板 id + 参数」。LLM 决定「做什么」,工作流引擎决定「怎么做」。每一次触发、步骤、工具调用、状态迁移、审批与许可都写入事件溯源日志。 + +## 3. 上下文管理与记忆 + +![上下文与记忆](img/zh/03-context-memory.png) + +每个 Agent 步骤的上下文由上游的确定性步骤组装:读取带版本号的账本、不可变快照、由模板显式声明的语义记忆,以及生效中的知识条目。Agent 不选择自己的基线上下文,因此每次决策都从可复现的起点出发。Agent 输出中的数字只能以对工具调用血缘的引用形式出现,由组装器解引用填值——这意味着 LLM 文本不可能把任何数字带进 Proposal。 + +上下文按**渐进式披露**构建。基线是精简的:摘要、标识符,以及该步骤所需的少量数字,按保守的上下文窗口设计。更多细节通过**智能体检索工具**按需披露:只读、白名单化的注册表工具,如规则检索、账本读取、快照获取、预测查询,Agent 在需要时可以调用。每次检索连同输入输出记录到血缘,因此「Agent 当时看到了什么」可以完整重放;提示注入防线把检索到的内容一律当作数据,而非指令。同一原则也贯穿运营界面:AI 结论卡片先给出结论,展开后才显示背后的工具输出与数据来源。 + +三层记忆各有不同的生命周期。工作记忆只存活于单个任务;情景记忆就是事件日志与时序库,永久保存,通过查询而非召回使用;语义记忆存放 D+1 复盘写回的结构化经验,版本化,并由各流程模板显式注入。运营事实的权威存储永远是领域数据库,而不是智能体记忆。 + +## 4. 可信执行链与状态机 + +![可信执行链](img/zh/04-safety-chain.png) + +一切拟执行动作都是一个 `Proposal`:带类型化载荷、完整血缘与不可变摘要。所有 Proposal 类型共用同一条生命周期工作流: + +| 环节 | 内容 | +|---|---| +| 规则校核 | 确定性政策包:合规性、约束、账本一致性、血缘完整性、职责分离 | +| 仿真验证 | 申报类做收益回测,控制类做功率平衡;仿真告警一票升级人工 | +| 包络检查 | 落在已批准包络内:自动放行并完整留痕;否则工作流挂起,进入工单台审批收件箱 | +| 人工审批 | 由身份与发起链路分离的审批人恢复工作流;审批绑定摘要与有效窗口 | +| 现势复核 | 下发前即时重验:资源在线、约束仍满足、证据未变化;否则置为 `STALE` 重新走链 | +| 许可与放行 | 签发 `ExecutionPermit`:短时效、可吊销、摘要一致;网关只受理 `(Proposal, ExecutionPermit)` 对 | + +挂起中的审批可跨进程重启存活。许可吊销是最快的回退手段:网关立即拒收后续指令,边缘终端退回上一批准计划或安全曲线。 + +## 5. 技术栈 + +![技术栈](img/zh/05-tech-stack.png) + +Runtime、智能体、工作流、领域 schema 与确定性服务均为 TypeScript + Mastra,看重的是类型化工具契约与持久化的挂起/恢复能力;专业模型 Skill 是 Python HTTP 服务。LLM 调用经由面向能力的抽象层与模型路由器,后端从开发期的商用 API、预生产的本地开源模型,切换到生产环境的光明电力大模型适配器,业务代码零改动。Runtime 还提供 LLM 不可用时的降级模式:预测、优化、校核、审批、申报与控制全部无需 LLM 即可运行。框架大约解决三分之一的问题,差异化资产是自建的确定性服务。 + +## 6. 接口与契约 + +![接口与契约](img/zh/06-contracts.png) + +手写的 zod schema 是唯一事实来源。构建时导出 JSON Schema 到入库的 contracts 目录,再据此生成 pydantic 模型,禁止手改。黄金样例(含正例与反例)由 TypeScript 与 Python 两端 CI 各自校验,任何结论不一致即构建失败。平台内部,每条信任边界都是一个 LLM 不可调用的端口:Proposal 提交、政策引擎、仿真、包络、授权、网关、账本、证据与工单台。数据表示纪律也是契约的一部分:金额与电量用定点小数字符串、单位编进字段名、UTC 时间戳、时段用日期加序号、全部 ID 为字符串、枚举全大写。 + +## 7. 评测驱动的开发过程 + +![评测驱动开发](img/zh/07-eval-driven.png) + +由于每个决策都能从留存证据完整重放,审计留痕本身就是评测数据集。四层评测对象用于定位问题:L1 LLM 任务,L2 专业模型 Skill,L3 可信执行链正确性(每条不变式至少一个自动化测试),L4 通过影子运行与历史回测衡量的端到端决策质量。评测就是变更门禁:提示词变更须通过 L1 任务集与 L4 回测;后端切换须通过 L1 全集与 L4 影子对比;Skill 升版必须在同一次变更中更新其已提交的 L2 基线;政策包升版须规则测试全绿;包络放宽仅凭 L4 影子或在线数据审批。每条复盘结论都会成为候选评测用例,失败案例持续喂养下一版基线。 diff --git a/docs/external/diagrams/gen.mjs b/docs/external/diagrams/gen.mjs index 4647484..e1703db 100644 --- a/docs/external/diagrams/gen.mjs +++ b/docs/external/diagrams/gen.mjs @@ -1,16 +1,23 @@ import { writeFileSync } from 'node:fs' +import zh from './zh.mjs' + +// usage: node gen.mjs [en|zh] +const LOCALE = process.argv[3] || 'en' +const T = (s) => (LOCALE === 'zh' ? (zh[s] ?? s) : s) +// approximate rendered width: CJK glyphs are ~1em, Latin ~0.55em +const tw = (s, size) => [...s].reduce((w, ch) => w + (/[\u3000-\u9fff\uff00-\uffef]/.test(ch) ? size * 1.0 : size * 0.55), 0) const C = { ink: '#1B2331', ink2: '#4A5568', ink3: '#7A8494', line: '#B9C2CE', teal: '#2C6B70', tealSoft: '#E4F0F0', amber: '#B86A14', amberSoft: '#F7ECDD', slate: '#EEF1F5', red: '#A23B3B', redSoft: '#F6E3E3', white: '#FFFFFF', } -const FONT = 'font-family="Helvetica Neue,Helvetica,Arial,sans-serif"' +const FONT = 'font-family="Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Arial,sans-serif"' const esc = (s) => s.replace(/&/g, '&').replace(//g, '>') function text(x, y, s, { size = 13, fill = C.ink, anchor = 'middle', weight = 400, mono = false, italic = false } = {}) { - const fam = mono ? 'font-family="Menlo,SFMono-Regular,Consolas,monospace"' : '' - return `${esc(s)}` + const fam = mono ? 'font-family="Menlo,SFMono-Regular,Consolas,PingFang SC,monospace"' : '' + return `${esc(T(s))}` } // title + sub lines centered in box function box(x, y, w, h, title, sub = [], o = {}) { @@ -23,15 +30,15 @@ function box(x, y, w, h, title, sub = [], o = {}) { s += text(x + w / 2, cy, title, { size: tsize, fill: tcolor, weight: 600, mono }) for (const l of sub) { cy += lh; s += text(x + w / 2, cy, l, { size: ssize, fill: scolor }) } if (tag) { - const tw = tag.length * 7 + 14 - s += `` + text(x + w - tw / 2 - 6, y + 4, tag, { size: 10, fill: C.white, weight: 700 }) + const tagw = tw(T(tag), 10) * 1.15 + 14 + s += `` + text(x + w - tagw / 2 - 6, y + 4, tag, { size: 10, fill: C.white, weight: 700 }) } return s } function group(x, y, w, h, label, o = {}) { const { stroke = C.line, fill = 'none', color = C.ink3 } = o return `` + - text(x + 12, y + 18, label.toUpperCase(), { size: 10.5, fill: color, anchor: 'start', weight: 700 }) + text(x + 12, y + 18, LOCALE === 'zh' ? label : label.toUpperCase(), { size: LOCALE === 'zh' ? 11.5 : 10.5, fill: color, anchor: 'start', weight: 700 }) } function arrow(x1, y1, x2, y2, label = '', o = {}) { const { dashed = false, both = false, color = C.ink2, lx = 0, ly = -6, path = null, lsize = 11.5, lfill = C.ink2 } = o @@ -39,8 +46,8 @@ function arrow(x1, y1, x2, y2, label = '', o = {}) { let s = `` if (label) { const mx = (x1 + x2) / 2 + lx, my = (y1 + y2) / 2 + ly - const tw = label.length * 6.4 + 8 - s += `` + text(mx, my + 2, label, { size: lsize, fill: lfill }) + const lw = tw(T(label), lsize) + 8 + s += `` + text(mx, my + 2, label, { size: lsize, fill: lfill }) } return s } @@ -83,7 +90,7 @@ const out = {} b += box(980, 360, 190, 80, 'Flexible resources', ['PV · storage · EV charging', 'HVAC · industrial · microgrids'], { fill: C.white }) b += arrow(630, 440, 630, 465) b += arrow(360, 400, 360, 140, '', { path: 'M360,400 L345,400 L345,140 L360,140', dashed: true }) - b += `execution feedback` + b += `${T('execution feedback')}` b += text(1075, 470, '31 MW today → ≥ 80 MW target', { size: 11, fill: C.ink3 }) out['01-system-context'] = svg(1200, 550, b) } diff --git a/docs/external/diagrams/render.sh b/docs/external/diagrams/render.sh index cb0f678..ad85621 100755 --- a/docs/external/diagrams/render.sh +++ b/docs/external/diagrams/render.sh @@ -3,14 +3,18 @@ set -euo pipefail cd "$(dirname "$0")" CHROME="${CHROME:-/Applications/Google Chrome.app/Contents/MacOS/Google Chrome}" -tmp=$(mktemp -d) -node gen.mjs "$tmp" >/dev/null -for f in "$tmp"/*.html; do - n=$(basename "${f%.html}") - dims=$(grep -o 'width="[0-9]*" height="[0-9]*" font' "$f" | head -1 | grep -o '[0-9]*' | tr '\n' ' ') - set -- $dims - "$CHROME" --headless=new --disable-gpu --hide-scrollbars --force-device-scale-factor=2 \ - --window-size="$1,$2" --screenshot="../img/$n.png" "$f" >/dev/null 2>&1 +for locale in en zh; do + out=../img; [ "$locale" = zh ] && out=../img/zh + mkdir -p "$out" + tmp=$(mktemp -d) + node gen.mjs "$tmp" "$locale" >/dev/null + for f in "$tmp"/*.html; do + n=$(basename "${f%.html}") + dims=$(grep -o 'width="[0-9]*" height="[0-9]*" font' "$f" | head -1 | grep -o '[0-9]*' | tr '\n' ' ') + set -- $dims + "$CHROME" --headless=new --disable-gpu --hide-scrollbars --force-device-scale-factor=2 \ + --window-size="$1,$2" --screenshot="$out/$n.png" "$f" >/dev/null 2>&1 + done + rm -rf "$tmp" done -rm -rf "$tmp" -ls ../img +ls ../img ../img/zh diff --git a/docs/external/diagrams/zh.mjs b/docs/external/diagrams/zh.mjs new file mode 100644 index 0000000..06ef2a9 --- /dev/null +++ b/docs/external/diagrams/zh.mjs @@ -0,0 +1,252 @@ +// Chinese labels for the external diagrams. Keys are the English strings in gen.mjs. +// Code identifiers (state names, ports, tech names) are intentionally left untranslated. +export default { + // 01 system context + 'External systems': '外部系统', + 'Trading platform': '交易平台', + 'bids · clearing · disclosures': '申报 · 出清 · 信息披露', + 'Dispatch / load mgmt': '调度 / 负荷管理系统', + 'regulation requests': '调节指令与需求', + 'Metering / settlement': '计量结算系统', + 'meter data · statements': '计量数据 · 结算单', + 'Weather & market data': '气象与行情数据', + 'read-only feeds': '只读数据源', + 'VPP AI Platform': '虚拟电厂 AI 平台', + 'Cognitive plane': '认知平面', + 'five LLM agents · agent runtime · workflows': '五类 LLM 智能体 · Agent Runtime · 工作流', + 'minutes to days': '分钟 ~ 天', + 'Safety chain': '可信执行链', + 'rule check → simulation → envelope / human approval → fresh check → permit': '规则校核 → 仿真验证 → 包络检查 / 人工审批 → 现势复核 → 执行许可', + 'deterministic · the only path between planes': '确定性 · 两平面之间唯一通道', + 'Control plane': '控制平面', + 'execution engine · edge terminals · seconds': '执行引擎 · 边缘控制终端 · 秒级', + 'Data foundation': '数据底座', + 'time-series · relational · knowledge/vector · feature store · event log': '时序库 · 关系库 · 知识库/向量库 · 特征库 · 事件日志', + 'Proposal (digest + lineage)': 'Proposal(摘要 + 血缘)', + 'bid + permit': '申报 + 许可', + 'Operators': '运营人员', + 'Case Desk · approvals': '运营工单台 · 审批', + 'scenario forks · AI cards': '情景分支 · AI 结论卡片', + 'Flexible resources': '可调资源', + 'PV · storage · EV charging': '光伏 · 储能 · 充电桩', + 'HVAC · industrial · microgrids': '空调 · 工业负荷 · 微网园区', + 'execution feedback': '执行反馈', + '31 MW today → ≥ 80 MW target': '现状 31 MW → 目标 ≥ 80 MW', + 'LLM': 'LLM', + 'NO LLM': '无 LLM', + + // 02 agent runtime + 'Task triggers': '任务触发', + 'Scheduled': '周期触发', + 'day-ahead 06:00 · bid window · D+1 review': '日前 06:00 · 申报窗口 · D+1 复盘', + 'Event': '事件触发', + 'deviation · resource offline · clearing': '偏差超阈 · 资源离线 · 出清', + 'Manual': '人工触发', + 'operator question or task': '运营人员提问或下达任务', + 'Router agent': '路由 Agent', + 'intent → template id + params': '意图 → 模板 id + 参数', + 'schema-constrained enum': '输出受 schema 枚举约束', + 'Workflow engine': '工作流引擎', + 'deterministic step chains': '确定性步骤链', + 'durable · suspend/resume': '持久化 · 可挂起/恢复', + 'one template per business process': '每个业务流程一个模板', + 'no LLM in the path': '路径上无 LLM', + 'rule-matched': '规则匹配', + 'Agent step': 'Agent 步骤', + 'one of five agents, invoked at a step': '五类智能体之一,在特定步骤被调用', + 'tools whitelisted per agent': '每个 Agent 的工具集为白名单', + 'Tool registry': '工具注册表', + 'typed, versioned skill contracts': '类型化、版本化的 Skill 契约', + 'every call snapshotted into lineage': '每次调用快照写入血缘', + 'Python skill services': 'Python Skill 服务', + 'forecast · MILP · simulation': '预测 · MILP 优化 · 仿真', + 'Proposal → safety chain': 'Proposal → 可信执行链', + 'numbers dereferenced from lineage': '数字从血缘解引用取得', + 'Event log (event-sourced): triggers, steps, tool calls, transitions, approvals, permits, receipts': '事件日志(事件溯源):触发、步骤、工具调用、状态迁移、审批、许可、回执', + 'LLM involved': 'LLM 参与', + 'Deterministic': '确定性', + 'Workflows are the entry point, not agents. The LLM decides what to do (pick a template); the engine decides how, step by step.': '工作流才是入口,Agent 不是。LLM 决定「做什么」(选模板),工作流引擎决定「怎么按步骤做」。', + + // 03 context & memory + 'Context assembly for one agent step · deterministic baseline + progressive disclosure': '单个 Agent 步骤的上下文组装 · 确定性基线 + 渐进式披露', + 'Position ledger': '持仓账本', + 'versioned read': '带版本号读取', + 'Time-series / snapshots': '时序库 / 快照', + 'immutable, checksummed': '不可变、带校验和', + 'Semantic memory': '语义记忆', + 'lessons declared by template': '由流程模板显式声明注入的经验', + 'Knowledge base (RAG)': '知识库(RAG)', + 'effective rules only': '仅检索生效中的规则条目', + 'fetchContext step (deterministic, reproducible)': 'fetchContext 步骤(确定性、可复现)', + 'compact baseline: summaries, identifiers, the few figures a step needs': '精简基线:摘要、标识符,以及该步骤所需的少量数字', + 'Agentic retrieval tools · read-only · whitelisted · every call logged into lineage': '智能体检索工具 · 只读 · 白名单 · 每次调用写入血缘', + 'rule retrieval · ledger read · snapshot fetch · forecast lookup — detail disclosed on demand, retrieved content tagged as data': '规则检索 · 账本读取 · 快照获取 · 预测查询 —— 细节按需披露,检索内容标记为数据而非指令', + 'prose + tool calls': '文字说明 + 工具调用', + 'numbers only as': '数字只能以', + '{toolCallId, path}': '{toolCallId, path}', + 'references': '引用形式出现', + 'Assembler': '组装器', + 'dereferences refs': '从血缘记录中', + 'from recorded lineage': '解引用填值', + '→ Proposal': '→ Proposal', + 'LLM text cannot': 'LLM 文本无法', + 'carry a number': '带入任何数字', + 'Three memory layers': '三层记忆', + 'Working memory': '工作记忆', + 'current task context, intermediate results': '当前任务上下文与中间结果', + 'runtime memory · task lifetime': 'Runtime 内存 · 任务级生命周期', + 'step-to-step parameters preferred over memory': '步骤间传参优先,能不进记忆就不进', + 'Episodic memory': '情景记忆', + 'operating states, trading, control, responses': '运行状态、交易、控制、用户响应', + 'event log + time-series · permanent (audit)': '事件日志 + 时序库 · 永久保存(审计)', + 'queried through fetchContext, not recalled': '经 fetchContext 确定性查询,不做自动召回', + 'structured lessons from D+1 review': 'D+1 复盘沉淀的结构化经验', + 'knowledge + strategy store · versioned': '知识库 + 策略库 · 版本化', + 'written by ReviewFinding, injected explicitly': '由 ReviewFinding 写入,按模板显式注入', + 'Authoritative facts live in the domain database, never in agent memory (invariant I8). No automatic memory recall feeds production decisions.': '运营事实的权威存储是领域数据库,而非智能体记忆(不变式 I8)。生产决策不依赖任何自动记忆召回。', + + // 04 safety chain + 'agent output': 'Agent 生成', + 'policy pack': '政策包校核', + 'backtest / balance': '收益回测 / 功率平衡', + 'within bounds?': '是否在包络内', + 'auto or human': '自动或人工', + 're-verify state': '重验现势', + 'permit issued': '签发执行许可', + 'gateway accepts': '网关凭许可受理', + 'Safety chain · deterministic · shared by every proposal type': '可信执行链 · 确定性 · 所有 Proposal 类型共用', + 'suspended run · Case Desk inbox': '工作流挂起 · 进入工单台审批收件箱', + 'outside envelope': '包络外', + 'sim warning': '仿真告警', + 'human resume': '人工裁决恢复', + 'approver ≠ originator (I1)': '审批人 ≠ 发起链路(I1)', + 'within envelope → AUTO_APPROVED': '包络内 → AUTO_APPROVED', + 'rule failure': '规则不通过', + 'human rejects': '人工驳回', + 'evidence changed': '实质证据已变化', + 're-enter chain': '重新走链', + '→ ExecutionReport → review': '→ ExecutionReport → 复盘', + 'Approval binds to the proposal digest and a validity window (I3). Gateways accept only (Proposal, ExecutionPermit): short-lived, revocable, digest-matched (I4).': '审批绑定 Proposal 的不可变摘要与有效窗口(I3)。网关只受理 (Proposal, ExecutionPermit):短时效、可吊销、摘要一致(I4)。', + 'Simulation warnings always escalate to a human. No code path lets the AI reach APPROVED. Envelopes start empty and widen only on shadow-run evidence.': '仿真告警一票升级人工。不存在任何让 AI 到达 APPROVED 的代码路径。包络从空集起步,仅凭影子运行证据放宽。', + + // 05 tech stack + 'OPERATOR UI': '运营界面', + 'RUNTIME': 'RUNTIME', + 'SERVICES': '确定性服务', + 'CONTRACTS': '契约', + 'SKILLS': 'SKILLS', + 'DATA': '数据', + 'LLM BACKENDS': 'LLM 后端', + 'Case Desk': '运营工单台', + 'approval inbox · case view · lineage expansion': '审批收件箱 · 工单视图 · 血缘展开', + 'AI insight cards': 'AI 结论卡片', + 'read-only projections in existing business pages': '嵌入既有业务页面的只读投影', + 'TypeScript + Mastra': 'TypeScript + Mastra', + 'workflows (durable suspend/resume)': '工作流(持久化挂起/恢复)', + 'agents as controlled steps · tool registry': 'Agent 作为受控步骤 · 工具注册表', + 'Trigger service': '触发服务', + 'cron · event bus consumers': '定时 · 事件总线消费者', + 'router agent for manual requests': '人工请求经路由 Agent', + 'LLM port': 'LLM 抽象层', + 'capability interface + model router': '能力接口 + 模型路由器', + 'LLM-down mode for degraded runs': 'LLM 不可用时的降级运行模式', + 'Policy engine': '政策包引擎', + 'versioned, tested policy packs': '版本化、带测试的政策包', + 'Envelope + authority': '包络 + 授权服务', + 'envelope match · fresh check · permits': '包络匹配 · 现势复核 · 执行许可', + 'Ledger + lineage': '账本 + 血缘', + 'position cascade · snapshots · assembler': '持仓约束级联 · 快照 · 组装器', + 'Gateways + Case Desk': '网关 + 工单台', + 'file export · simulation · cases': '文件导出 · 仿真网关 · 工单', + 'Domain schemas (zod)': '领域 schema(zod)', + 'single source of truth': '唯一事实来源', + 'JSON Schema': 'JSON Schema', + 'exported, committed, versioned': '构建导出、入库、版本化', + 'Golden fixtures': '黄金样例', + 'validated by both CIs': '两端 CI 共同校验', + 'Python services (FastAPI)': 'Python 服务(FastAPI)', + 'load / PV / price forecasts with quantiles': '负荷 / 光伏 / 电价预测(带分位数区间)', + 'bid MILP · dispatch MILP · potential · report': '报价 MILP · 调度 MILP · 潜力辨识 · 报告生成', + 'Generated pydantic models': '生成的 pydantic 模型', + 'never hand-edited': '禁止手改', + 'PostgreSQL + pgvector': 'PostgreSQL + pgvector', + 'relational · knowledge · outbox events': '关系数据 · 知识库 · outbox 事件', + 'TimescaleDB / IoTDB': 'TimescaleDB / IoTDB', + 'telemetry curves': '遥测曲线', + 'Object storage': '对象存储', + 'snapshots · archives': '快照 · 归档', + 'Kafka (phase 2)': 'Kafka(二期)', + 'outbox relay, same interface': 'outbox 中继,消费者接口不变', + 'Commercial API': '商用 API', + 'development': '开发期', + 'Local open model': '本地开源模型', + 'pre-production': '预生产', + 'GuangMing Power LLM': '光明电力大模型', + 'production, on-prem adapter': '生产环境,本地化部署适配器', + 'Backend swaps are gated by the L1 evaluation set and an L4 shadow comparison, not judgment. About a third of the platform is framework; the differentiating parts are the deterministic services.': '切换 LLM 后端以 L1 评测集与 L4 影子对比为门禁,而非主观判断。框架约解决三分之一的问题,差异化资产是自建的确定性服务。', + + // 06 contracts + 'Contract pipeline (one source of truth)': '契约管线(唯一事实来源)', + 'zod schemas': 'zod schemas', + 'packages/domain · hand-written': 'packages/domain · 唯一手写处', + 'build export': '构建导出', + 'contracts/ · committed · versioned': 'contracts/ · 入库 · 版本化', + 'codegen': '代码生成', + 'pydantic models': 'pydantic models', + 'generated · never hand-edited': '生成物 · 禁止手改', + 'valid + invalid samples per object': '每类对象的正例 + 反例', + 'TS CI and Python CI both validate every fixture; any disagreement fails the build': 'TS CI 与 Python CI 各自校验全部样例;两端结论不一致即构建失败', + 'Ports = trust boundaries (deterministic, not exposed to the LLM)': '端口 = 信任边界(确定性,不暴露给 LLM)', + 'the only way into the safety chain': '进入可信执行链的唯一入口', + 'rule check and simulation': '规则校核与仿真验证', + 'envelope match · fresh check · permits · revoke': '包络匹配 · 现势复核 · 签发/吊销许可', + 'accepts (Proposal, ExecutionPermit) only': '只受理 (Proposal, ExecutionPermit)', + 'versioned ledger · event-sourced evidence': '带版本账本 · 事件溯源证据', + 'open · read · apply command · watch': '开单 · 读取 · 执行命令 · 订阅', + 'Cross-process interfaces and data representation rules': '跨进程接口与数据表示纪律', + 'TS runtime → Python skills': 'TS Runtime → Python Skills', + 'HTTP/JSON, schema-validated both ends': 'HTTP/JSON,两端按 schema 校验', + 'Case Desk / front end → runtime': '工单台 / 前端 → Runtime', + 'HTTP/JSON approvals and case API': 'HTTP/JSON 审批与工单 API', + 'anti-corruption adapters, raw + translated logged': '防腐层适配器,原始报文与转换对象双向留痕', + 'Edge control link': '边缘控制链路', + 'grid protocol stack, outside the JSON domain': '国网标准协议栈,不属于 JSON 契约域', + 'Money, energy and prices as fixed-point decimal strings · units in field names (power_mw, price_yuan_per_mwh) · ISO 8601 UTC · intervals as {date, interval_index}': '金额 / 电量 / 电价用定点小数字符串 · 单位编进字段名(power_mw, price_yuan_per_mwh)· ISO 8601 UTC · 时段用 {date, interval_index}', + 'all IDs strings · enums UPPER_SNAKE · breaking schema changes bump the major version and ship a migration note': '全部 ID 为字符串 · 枚举 UPPER_SNAKE · 破坏性 schema 变更须升主版本并附迁移说明', + + // 07 eval-driven + 'Four evaluation layers': '四层评测对象', + 'End-to-end decision quality': '端到端决策质量', + 'shadow run · historical backtest · counterfactual attribution': '影子运行 · 历史回测 · 反事实归因', + 'Safety chain correctness': '可信执行链正确性', + 'policy pack tests · invariant tests I1–I8 · red-team cases': '政策包测试 · 不变式测试 I1–I8 · 红队用例', + 'Professional-model skills': '专业模型 Skill', + 'MAPE · interval coverage · solver quality vs. bounds': 'MAPE · 区间覆盖率 · 求解质量对比上下界', + 'LLM tasks': 'LLM 任务', + 'routing accuracy · schema compliance · numeric consistency': '路由准确率 · schema 合规率 · 数字一致性', + 'A problem at L4 is localised to the layer that caused it.': 'L4 出问题时可定位到引起它的那一层。', + 'Change gates: what must pass before a change ships': '变更门禁:什么变更必须通过什么评测', + 'Prompt / agent instructions': '提示词 / Agent 指令', + 'L1 task set + L4 fixed-day backtest, no regression': 'L1 相关任务集 + L4 固定历史日回测无回退', + 'LLM backend switch': 'LLM 后端切换', + 'full L1 set + L4 shadow comparison vs. baseline': 'L1 全集 + L4 影子对比达到基线约定比例', + 'Skill model upgrade': 'Skill 模型升版', + 'all L2 metrics for that skill + downstream L4 backtest': '该 Skill 的 L2 全指标 + 下游 L4 回测', + 'Policy pack upgrade': '政策包升版', + 'L3 pack tests green + impact analysis on pending proposals': 'L3 政策包测试全绿 + 存量 Proposal 影响分析', + 'Contract schema change': '契约 schema 变更', + 'golden fixtures on both sides + compatibility check': '双端黄金样例 + 兼容性检查', + 'Envelope widening': '包络放宽', + 'L4 shadow / online evidence only — no data, no widening': '仅凭 L4 影子 / 在线数据审批 —— 无数据不放宽', + 'The audit trail is the evaluation dataset': '审计留痕即评测数据集', + 'Production run': '生产运行', + 'event log + immutable snapshots': '事件日志 + 不可变快照', + 'Replay datasets': '历史重放集', + 'representative days, frozen': '固化的代表日', + 'Eval run (archived)': '评测运行(留档)', + 'committed baseline, CI --check': '已提交基线,CI --check', + 'ReviewFinding': 'ReviewFinding', + 'D+1 attribution': 'D+1 偏差归因', + 'New eval cases': '新评测用例', + 'every finding → candidate case': '每条复盘结论 → 候选用例', +} diff --git a/docs/external/img/01-system-context.png b/docs/external/img/01-system-context.png index fd9b197..a1e86da 100644 Binary files a/docs/external/img/01-system-context.png and b/docs/external/img/01-system-context.png differ diff --git a/docs/external/img/02-agent-runtime.png b/docs/external/img/02-agent-runtime.png index c859ee7..f8bfdea 100644 Binary files a/docs/external/img/02-agent-runtime.png and b/docs/external/img/02-agent-runtime.png differ diff --git a/docs/external/img/03-context-memory.png b/docs/external/img/03-context-memory.png index 37ebf43..aefb0d7 100644 Binary files a/docs/external/img/03-context-memory.png and b/docs/external/img/03-context-memory.png differ diff --git a/docs/external/img/04-safety-chain.png b/docs/external/img/04-safety-chain.png index 7cbf7e6..96627be 100644 Binary files a/docs/external/img/04-safety-chain.png and b/docs/external/img/04-safety-chain.png differ diff --git a/docs/external/img/05-tech-stack.png b/docs/external/img/05-tech-stack.png index 2e2aa1c..7a41c24 100644 Binary files a/docs/external/img/05-tech-stack.png and b/docs/external/img/05-tech-stack.png differ diff --git a/docs/external/img/06-contracts.png b/docs/external/img/06-contracts.png index a65d7db..80f9f2e 100644 Binary files a/docs/external/img/06-contracts.png and b/docs/external/img/06-contracts.png differ diff --git a/docs/external/img/07-eval-driven.png b/docs/external/img/07-eval-driven.png index 8b0daf0..477563d 100644 Binary files a/docs/external/img/07-eval-driven.png and b/docs/external/img/07-eval-driven.png differ diff --git a/docs/external/img/zh/01-system-context.png b/docs/external/img/zh/01-system-context.png new file mode 100644 index 0000000..1b092b9 Binary files /dev/null and b/docs/external/img/zh/01-system-context.png differ diff --git a/docs/external/img/zh/02-agent-runtime.png b/docs/external/img/zh/02-agent-runtime.png new file mode 100644 index 0000000..8667d99 Binary files /dev/null and b/docs/external/img/zh/02-agent-runtime.png differ diff --git a/docs/external/img/zh/03-context-memory.png b/docs/external/img/zh/03-context-memory.png new file mode 100644 index 0000000..b2b8027 Binary files /dev/null and b/docs/external/img/zh/03-context-memory.png differ diff --git a/docs/external/img/zh/04-safety-chain.png b/docs/external/img/zh/04-safety-chain.png new file mode 100644 index 0000000..b2eb124 Binary files /dev/null and b/docs/external/img/zh/04-safety-chain.png differ diff --git a/docs/external/img/zh/05-tech-stack.png b/docs/external/img/zh/05-tech-stack.png new file mode 100644 index 0000000..0d3847e Binary files /dev/null and b/docs/external/img/zh/05-tech-stack.png differ diff --git a/docs/external/img/zh/06-contracts.png b/docs/external/img/zh/06-contracts.png new file mode 100644 index 0000000..b350b6b Binary files /dev/null and b/docs/external/img/zh/06-contracts.png differ diff --git a/docs/external/img/zh/07-eval-driven.png b/docs/external/img/zh/07-eval-driven.png new file mode 100644 index 0000000..076c967 Binary files /dev/null and b/docs/external/img/zh/07-eval-driven.png differ