完整的 AI Coding 平台需要把客户端、上下文、模型、工具、状态图、Sandbox 和评估连接成一个系统。用户提交 Issue 或编辑请求后,平台定位相关代码,形成受限 Patch,执行测试与审查,再按实际权限交付修改。

系统架构的重点是明确数据与控制边界:代码版本从哪里来,谁拥有任务状态,哪些操作可以执行,失败怎样恢复,以及提交是否对应已经验证的产物。单个模型回答正确,不能代替整条链路的验证。

分层架构

平台可以划分为 Client、Gateway、Engine、Sandbox 四层。

AI Coding 平台分层

层次 主要职责 关键数据
Client IDE、CLI、任务输入、差异预览与交互 文件版本、光标、选择范围
Gateway 认证、租户、限流、任务接收和事件流 task_id、身份、状态入口
Engine RAG、MCP、Skill、Agent 图和 Checkpoint 目标、证据、Patch、运行状态
Sandbox 隔离应用候选代码并执行测试 环境版本、退出码、日志与报告

客户端可以偏重实时编辑辅助,也可以仅提交远端长任务。Cursor、Windsurf、Claude Code、Devin 等产品展示了不同交互形态,但不能仅凭产品名称推断其全部私有架构。自研系统应根据代码位置、部署需求和交付方式取舍。

这些交付形态可以组合不同能力:

形态 主要能力 与用户的关系
IDE 辅助 光标补全、局部编辑、实时索引、Diff 预览 围绕当前编辑持续提供建议
CLI Agent 文件搜索、AST 导航、按需 Skill、受控终端 以任务和命令结果组织交互
云端任务 独立运行环境、长任务、编译测试与浏览器验证 用户提交目标并查看进展与产物
协同编辑 多文件 Patch、变更预览、审批和撤销 同步用户编辑与 Agent 候选变化

浏览器验证可以检查前端页面、交互与控制台错误,但也需要明确目标环境和权限。人类编辑与 Agent 修改同时发生时,应核对文档版本,防止候选覆盖刚保存的变化。

持久化状态、事件记录与产物存储属于跨层基础设施。网关多副本不应各自维护互相矛盾的任务状态,Worker 重启也不应使任务从状态库消失。

代码感知

IDE 插件可以复用 LSP 提供的符号、定义、引用和诊断能力。TypeScript、Pyright、gopls 等语言服务帮助客户端理解不同语言,而不必为每种语言重写语法器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import * as vscode from "vscode";

/** 在文件保存时采集符号与诊断,交给应用的同步接口。 */
export function registerContextSync(
context: vscode.ExtensionContext,
sendUpdate: (update: object) => Promise<void>,
): void {
const disposable = vscode.workspace.onDidSaveTextDocument(
async (document) => {
const symbols = await vscode.commands.executeCommand<
vscode.DocumentSymbol[]
>("vscode.executeDocumentSymbolProvider", document.uri);
const diagnostics = vscode.languages.getDiagnostics(document.uri);

await sendUpdate({
uri: document.uri.toString(),
version: document.version,
symbols: symbols ?? [],
diagnostics: diagnostics.map((item) => ({
message: item.message,
severity: item.severity,
start: item.range.start,
end: item.range.end,
})),
});
},
);
context.subscriptions.push(disposable);
}

sendUpdate 由插件实现,负责授权、序列化和上传。文件保存事件只能取得已保存时点,处理未保存内容时还要监听变更,并采用去抖、版本比较和取消旧任务。

符号与诊断不是完整源码或完整调用图。插件应保留工作区、语言、文档版本和关联 Commit,避免远端使用已过期的行号生成 Patch。

增量索引

本地或服务端索引需要感知新增、修改和删除。内容哈希或 Merkle Tree 可以定位变化,Tree-sitter 可按语法结构解析不同语言,向量索引则支持语义检索。

一次增量更新应完成读取版本、解析、抽取符号、更新分块和使旧结果失效。删除文件时也要删除相关向量与依赖边,不能只持续追加新内容。

Skeleton保留类、函数签名和必要说明,适合提供辅助依赖;主修改文件、复杂实现和相关测试则可能需要全文。压缩签名不能替代真实实现,也不能保证所有动态调用都被理解。

下面用 Python 标准 AST 演示符号与签名抽取。多语言工程可以用 Tree-sitter 的语言语法和 Query 执行相应操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import ast


class SymbolExtractor(ast.NodeVisitor):
"""提取 Python 类与函数的限定名、签名和源码范围。"""

def __init__(self):
self.scope = []
self.symbols = []

def visit_ClassDef(self, node: ast.ClassDef):
"""保存类名并继续访问类内部的符号。"""
self.symbols.append({
"name": ".".join([*self.scope, node.name]),
"kind": "class",
"start_line": node.lineno,
"end_line": node.end_lineno,
})
self.scope.append(node.name)
self.generic_visit(node)
self.scope.pop()

def visit_FunctionDef(self, node: ast.FunctionDef):
"""保留参数、返回标注和 Docstring,而不复制完整函数体。"""
returns = ast.unparse(node.returns) if node.returns else None
self.symbols.append({
"name": ".".join([*self.scope, node.name]),
"kind": "async_function" if isinstance(node, ast.AsyncFunctionDef) else "function",
"parameters": ast.unparse(node.args),
"returns": returns,
"docstring": ast.get_docstring(node),
"start_line": node.lineno,
"end_line": node.end_lineno,
})
self.scope.append(node.name)
self.generic_visit(node)
self.scope.pop()

visit_AsyncFunctionDef = visit_FunctionDef


def extract_symbols(source: str) -> list[dict]:
"""解析语法树后返回结构化符号信息。"""
visitor = SymbolExtractor()
visitor.visit(ast.parse(source))
return visitor.symbols

结果还需绑定文件路径、内容哈希与版本。Tree-sitter 的字节位置与文本编辑器的字符位置不总是相同,Unicode 内容尤其需要准确转换。反射、配置和运行时依赖应结合搜索与测试补充。

任务网关

耗时的 Agent 任务可以通过“接收任务—入队—返回 task_id—Worker 执行”的方式解耦。网关负责身份、输入大小、租户限流和预算,Worker 负责实际图运行。

1
2
3
4
5
6
{
"task_id": "repair-42",
"status": "accepted",
"status_url": "/tasks/repair-42",
"events_url": "/tasks/repair-42/events"
}

任务状态可以包括 queued、running、waiting_approval、succeeded、failed、cancelled。客户端连接断开后,任务是否继续或取消应由策略决定。

FastAPI BackgroundTasks 适合轻量的进程内后台工作,不能直接提供跨进程持久任务队列。长任务需要队列、确认、重投与幂等,例如由 Celery 或持久工作流协调。内存中的 asyncio.create_task 也不能保证服务重启后继续执行。

分布式限流可以使用 Redis 统一计数或 Token Bucket,但检查与扣减需要原子处理。网关限制请求频次,运行时还要限制每个任务的步骤、Token、并发和工具费用。

流式通信

SSE适合服务端向客户端推送事件,WebSocket适合需要持续双向通信的场景。SSE 不是双向通道,用户补充、取消和审批可以通过独立 HTTP 请求发送。

1
2
3
4
5
6
7
8
id: 17
event: tool_result
data: {"task_id":"repair-42","tool":"pytest","status":"failed"}

id: 18
event: task_state
data: {"task_id":"repair-42","status":"repairing","attempt":2}

每个 SSE 事件以空行结束,可以带 ID 支持续传。重连后应从已保存事件继续,而不是重新启动同一任务。还需心跳、代理缓冲、连接超时、客户端鉴权和慢消费者的背压处理。

事件可以表达阶段、工具请求、执行结果、产物和错误。对用户展示可核验的进展与简要解释,不必把模型全部内部推理、敏感参数或完整日志直接输出。

能力组合

平台中的六类能力承担不同职责:

能力 在平台中的作用
Prompt 定义目标、范围和输出契约
MCP 发现与调用外部资源和工具
Codebase RAG 定位相关文件、符号和测试
Skill 组织复用流程、校验和执行规则
Graph 管理状态、分支、循环和恢复
Sandbox / Harness 隔离执行并验证任务行为

MCP 工具与模型原生 Tool Calling 需要适配,但协议一致不等于业务语义一致。RAG 为 Skill 提供真实资料,Skill 的 dry_run 与 Guard 检查执行条件,Graph 根据结果路由,Sandbox 返回真实测试观察。

从外部 Server 发现工具后,仍需名称空间、过滤、权限和参数验证。工具返回的恶意文本不能成为新的系统规则,凭证也应留在受控服务配置中。

Context 打包

Context Packager把主文件、依赖 Skeleton、测试、诊断和历史失败组织成有限上下文。先按相关性选材料,再计算实际 Token;预算还应包括 System Prompt、工具 Schema、消息封装和预留输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from dataclasses import dataclass
from typing import Callable
from xml.etree import ElementTree as ET


@dataclass(frozen=True)
class ContextFile:
"""保留文件身份、版本和正文,便于验证生成依据。"""

path: str
language: str
revision: str
content: str


def package_context(
files: list[ContextFile],
count_tokens: Callable[[str], int],
max_tokens: int,
) -> tuple[str, list[str]]:
"""按优先级加入完整文件,预算不足时记录未纳入的路径。"""
if max_tokens <= 0:
raise ValueError("max_tokens must be positive")
root = ET.Element("context")
skipped = []
for item in files:
element = ET.SubElement(root, "file", {
"path": item.path,
"language": item.language,
"revision": item.revision,
})
element.text = item.content
candidate = ET.tostring(root, encoding="unicode")
if count_tokens(candidate) > max_tokens:
root.remove(element)
skipped.append(item.path)
result = ET.tostring(root, encoding="unicode")
if count_tokens(result) > max_tokens:
raise ValueError("Budget cannot hold the context envelope")
return result, skipped

count_tokens 应由目标模型分词器实现,例如匹配的 tiktoken 编码;不能把字符数除以常数当作所有语言和模型的精确计数。未纳入文件需要显式记录,必要时触发后续检索。

ElementTree 转义正文与属性,避免源码破坏 XML 结构。XML 是资料边界表达,不能独立防止 Prompt Injection。内容截断还应避免破坏必要函数、表格或标签结构。

MCP 桥接

桥接器完成初始化、能力发现、Schema 转换和执行结果映射。下面展示 stdio 连接的基本生命周期。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client


async def call_mcp_tool(
parameters: StdioServerParameters,
tool_name: str,
arguments: dict,
):
"""在受控服务连接中发现并调用明确工具。"""
async with stdio_client(parameters) as (read_stream, write_stream):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
available = await session.list_tools()
names = {tool.name for tool in available.tools}
if tool_name not in names:
raise ValueError("Tool is not exposed by this server")
result = await session.call_tool(tool_name, arguments=arguments)
return result

这是每次创建连接的简单示例,长任务可以复用会话,但需要健康检查、超时和释放。远程服务的传输应按支持版本选择,历史 SSE 与 Streamable HTTP 不应混用配置。

Server 名称与工具名称需要稳定映射,返回的 isError、内容类型和结构化结果应保留。未知工具不能自动回退到任意 Shell,模型提供的服务地址也不能自行成为可信连接。

System Prompt

Coding Agent 的任务模板需要表达角色、允许范围、工具、测试和失败处理。要求应能对应宿主的实际检查,不能只依靠模型遵守。

1
2
3
4
5
6
7
8
9
10
11
12
<coding_task>
<goal>修复给定 Issue,保持未涉及接口和行为兼容。</goal>
<scope>仅修改已授权文件,保留已有测试与安全规则。</scope>
<workflow>
读取相关实现和测试,建立失败基线。
生成最小 Unified Diff,在隔离环境验证。
测试失败时依据真实诊断修正,预算耗尽则停止。
</workflow>
<output>
返回候选补丁、关键假设、验证结果和未解决事项。
</output>
</coding_task>

工程可以参考代码助手的交互方式,但不应把示例模板当成产品真实的私有 System Prompt。内部推理文本不构成验证结果,测试字段必须来自实际执行。

Patch 验证

Unified Diff描述文件与局部 Hunk 的变化。--- 与 +++ 标识旧新文件,@@ 表达行范围,空格、- 和 + 分别表示上下文、删除和新增。

1
2
3
4
5
6
7
--- a/calculate.py
+++ b/calculate.py
@@ -1,2 +1,4 @@
def average(values):
+ if not values:
+ return 0.0
return sum(values) / len(values)

应用前需要检查目标路径、Base Commit、文件哈希、Hunk 上下文和修改规模。生成语法合法不代表行为正确,语法预检应与测试和接口检查分开。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import ast
import difflib
from pathlib import PurePosixPath


def make_python_patch(path: str, before: str, after: str) -> str:
"""先检查候选语法,再按标准格式生成局部差异。"""
if not path or any(char in path for char in ("\\", "\n", "\r", "\x00")):
raise ValueError("Patch path must use a single POSIX line")
target = PurePosixPath(path)
if target.is_absolute() or ".." in target.parts:
raise ValueError("Patch path must stay within the project")
ast.parse(after, filename=path)
return "".join(difflib.unified_diff(
before.splitlines(keepends=True),
after.splitlines(keepends=True),
fromfile=f"a/{path}",
tofile=f"b/{path}",
n=3,
))

这是 Python 单文件候选生成示例,不是完整的多语言 Patch 引擎。AST 不能替代类型检查、编译或运行测试,其他语言应使用相应解析器。应用 Diff 可以先使用 git apply --check 验证,再在任务工作区执行,避免直接正则覆盖文件全文。

Workspace 事务

多文件任务应固定不可变基线,使用独立工作区保存候选。测试、审查与提交都对应同一组变化,失败时只清理或恢复本任务范围。

1
2
3
4
5
记录 Base Commit 和当前授权范围。
为任务创建独立 worktree、clone 或沙箱文件系统。
检查并应用 Patch,记录变更文件与内容摘要。
执行语法、测试和安全验证。
通过后形成候选 Commit;失败则保留诊断并回收工作区。

git stash create 不应被简单理解为可恢复全部工作区的事务:它未必覆盖未跟踪和忽略文件,空变化也可能不产生快照。reset --hard 在共享工作区可能覆盖用户修改,不能把它作为未经限定的 Undo。

一个 Git Commit 可以把已暂存文件作为一个版本提交,但不能同时原子修改数据库、发信和远端 PR。外部操作需要明确提交顺序、幂等标识和补偿策略。

测试反馈

Sandbox Tester 准备指定版本与依赖,应用候选 Patch,运行规定命令,并返回结构化报告。

1
2
3
4
5
6
7
8
9
10
11
{
"base_commit": "base-version",
"patch_digest": "patch-hash",
"environment": "test-image-version",
"status": "failed",
"exit_code": 1,
"failed_tests": ["test_empty_input"],
"stdout_ref": "artifact:stdout",
"stderr_ref": "artifact:stderr",
"duration_seconds": 2.4
}

测试失败可能出现在 stdout,也可能出现在 stderr,不能只读取一条错误流。还需区分测试断言、环境准备失败、无测试收集、超时和进程崩溃。

E2B 或其他 Sandbox 的 SDK 需要按版本配置创建、网络、文件和销毁;不能把 Docker 的 network_mode="none" 当成所有服务通用参数。诊断可以变成 Observation,条件边在有限次数内返回 Coder。

通过现有测试不代表所有行为正确。候选修改应保持既有回归、补充相关边界,并检查测试有没有被删改来隐藏失败。

HITL 审批

需要批准的修改在真实提交、外部写入或合并前挂起。审批内容至少包括目标版本、Patch 摘要、影响范围、验证报告和风险。

人工修改 Patch 后,旧测试与审批失效,需要重新验证。interrupt() 保存待办,update_state() 形成新版本,恢复时核对审批身份、任务归属与当前产物。

审批可以来自 CLI 或业务界面,但不能以模型自报“已批准”代替真实操作。长期等待使用持久状态,不依赖一个数日不关闭的终端进程。

Trace 与状态

Tracing记录一次请求的阶段关系,Checkpoint保存任务状态,两者相关但不是同一个对象。trace_id 标识一条链路,thread_id 标识可跨多轮运行的状态历史,task_id 表达业务任务。

重试、审批恢复和分支可以产生新 Trace,因此不宜强制它们永久使用同一个 ID。可以在 Span 和任务记录中保存关联字段,用来从日志定位检查点与产物。

OpenTelemetry 可以贯穿 Java 网关、Python Worker、模型请求和 Sandbox,LangSmith 等工具可以记录 Agent 轨迹。记录应包含版本、阶段、耗时、结果和父子关系,敏感正文和凭证需要控制采集与访问。

指标归因

Prometheus 与 Grafana 可以观察请求、Token、费用、错误和延迟。输入、输出、缓存 Token 及工具费用需要分别统计,TTFT 与任务总耗时也应区分。

C=Tin106pin+Tout106pout+Ctools+Csandbox.C=\frac{T_{in}}{10^6}p_{in} +\frac{T_{out}}{10^6}p_{out} +C_{tools}+C_{sandbox}.

公式中的单价是业务配置,具体模型还可能有缓存、批处理或其他计费方式。实际监控应以返回用量和账单规则为依据。

Counter 表示累计用量,Histogram 表示耗时分布。标签宜使用稳定模型、服务或有限租户分组,不宜为每个 task_id 创建一条高基数时间序列;逐任务成本可以进入专门明细存储。告警只负责通知,预算拦截还需在运行控制器中实际实施。

质量评估

HumanEval主要评价函数级代码生成,SWE-bench围绕真实仓库 Issue 和测试环境评价修复。任务输入、环境、测试与报告不同,不能用相同标签掩盖判分差异。

**Fail-to-Pass(F2P)**要求原失败测试通过,**Pass-to-Pass(P2P)**要求原已通过行为仍然成立。只检查新用例会漏掉回归,只检查旧用例又可能没有验证 Issue。

Pass@1 是固定任务集的一次尝试成功率;单个 Patch 的 pytest 通过与否不能直接称为整个平台“Pass@1=100%”。Pass@k 还需要明确候选数量、判分和样本量。

Judge 评审

LLM-as-a-Judge 可以用 Rubric 检查正确性、安全与架构规范,并返回结构化意见。它适合补充审查,不能替代测试、静态分析或真实授权。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"verdict": "REJECTED",
"scores": {
"correctness": 3,
"security": 2,
"maintainability": 4
},
"findings": [
{
"severity": "CRITICAL",
"file": "repository.py",
"rule": "SQL_PARAMETERIZATION",
"reason": "外部输入直接拼入 SQL",
"evidence": "第 28 行查询构造"
}
],
"uncertainties": []
}

评分量表需要明确分值意义、证据要求和无法判断的状态。固定 JSON 只保证可解析性,低 temperature 也不能证明裁判客观。应与人工标注和硬断言校准,监测裁判偏差及被 Patch 内容注入的风险。

Failure Fixture

失败回放应固定初始 State、Base Commit、Patch、依赖锁文件、镜像、工具观察和模型响应。只保存异常文字无法重建完整环境。

可以分别运行两类实验:Replay使用录制响应检查控制逻辑,Live Eval使用当前模型重新生成以评价能力变化。前者可重复且不调用模型,但后者不能被“零 Token 回放”替代。

Fixture 应脱敏并版本管理,测试范围包括异常分支、缺失输出和错误工具请求。回放时未知调用需要失败,而不是偷偷访问真实支付、数据库或 GitHub 服务。

CI Gate

CI 将测试、扫描和评估结果转换成必需检查。只有仓库分支保护或 Ruleset 要求相应 Check 成功,失败退出码才会真正阻止合并。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
name: AI quality gate
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
jobs:
quality:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Verify candidate
run: python scripts/ci_gate.py

这是工作流骨架,ci_gate.py 需要由工程实现,且将第三方 Action 固定到审核过的版本或提交。检查应针对当前 PR Commit,不使用旧版本的成功报告。运行不可信代码时不要提供写令牌或敏感环境变量。

聚合成功率可以有项目阈值,但还需检查关键任务回归、成本、延迟和样本量。课程里的 95% 或固定影子次数应视为示例策略,不能直接成为所有系统的发布标准。

安全检查

Semgrep 可按规则扫描源码,Gitleaks 可检查潜在 Secrets,其他依赖和运行检查补充不同风险。OWASP 是风险与实践体系,不是一个自动完成所有验证的扫描器。

扫描结果应包含规则、文件、位置和证据,并映射到修复或停止分支。没有发现不代表不存在漏洞,误报需要受控审核,扫描失败也不能当成通过。

检查除了当前差异,还应考虑依赖、配置和必要历史。Secrets 不应被复制进 Prompt、Fixture、日志或 PR 评论,工具凭证也不应暴露给生成代码。

Shadow 与 Canary

Shadow Run旁路运行新版本并比较结果,不影响真实交付且应阻断写副作用。Canary让有限真实流量进入新版本,需要发布范围和回退条件。

asyncio.create_task 会使用计算、网络和存储资源,并不意味着主流程完全没有影响。影子运行应限制容量、脱敏数据、控制费用,并禁止重复发信、提 PR 或修改真实对象。

比较时固定问题类别和基线,检查质量、尾延迟、成本、拒绝和恢复;平均指标改善不能掩盖关键业务退化。达到预设要求后再逐渐增加流量,出现问题可回退到明确版本。

Webhook 入口

Issue 可以通过 GitHub Webhook 触发任务。先验证原始请求体的 HMAC SHA-256,再检查事件、action、仓库与任务权限,最后持久入队。

1
2
3
4
5
6
7
8
9
10
11
import hashlib
import hmac
import re


def verify_webhook(body: bytes, signature: str, secret: bytes) -> bool:
"""对原始字节验签,使用恒定时间比较避免普通字符串比较。"""
if not secret or re.fullmatch(r"sha256=[0-9a-f]{64}", signature) is None:
return False
expected = "sha256=" + hmac.new(secret, body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)

验签前不能先重新序列化 JSON,否则字节可能变化。签名证明请求来源和完整性,不替代仓库授权,也不自动防重放。X-GitHub-Delivery 可参与幂等去重,重复投递不应创建第二个修复任务。

Issue 正文可能来自不可信用户,不能把其中的“直接合并”“读取密钥”等要求提升成系统权限。Triage 负责识别类型、适用范围和是否需要补充信息。

影响定位

Scope 节点组合 Codebase RAG、符号检索与 MCP 依赖查询:主编辑文件给出相关完整实现,辅助依赖提供 Skeleton,测试和配置补足运行关系。

需要记录当前 Commit、文件哈希、检索命中与覆盖不足。Patch 生成期间仓库变化时,应重新核对范围;新版本不能沿用旧行号和测试结果。

检索不到关键定义时,系统应继续读取或说明无法完成,不应通过猜测 API 填补缺失。上下文打包还需保留排除的内容,便于下一轮有目标地补充。

Capstone 流程

综合流程可以组织为 Ingestion → Triage → Scope → Context → Coder → Test → Review → Delivery。图中的合并是可能的交付动作,必须满足当前仓库的授权和规则。

Issue 到 PR 控制流程

Coder Subgraph 根据目标、证据和前次错误生成 Unified Diff。语法预检失败回到 Coder;Sandbox 返回测试失败后,依据剩余次数和预算决定修复或停止。通过后执行安全扫描和 Reviewer,再形成可审查的 PR。

整个运行要保存同一候选的 Base Commit、Patch 摘要、测试、扫描和审批。Reviewer 提出新修改后,应重新测试该版本,不能用前一个 Patch 的报告批准后一个。

交付权限

创建分支、提交 Commit、创建 PR、批准 PR 和合并是不同操作。自动化身份需要分别满足权限与策略,不能因为模型输出 APPROVED 就获得合并权。

Squash Merge 可以压缩已验证提交历史,但不会修复补丁本身,也不能替代必要审核。自审限制、Required Reviews、Required Checks 和版本更新都会影响实际可合并性。

即使使用自动合并,也应等待当前 Commit 的必要检查与审批。未满足条件时保留候选和诊断,而不是扩大令牌权限或绕过分支保护。

架构验收

课程的整体要求可以归纳到可检查的系统边界:

方面 应具备的能力
契约与职责 Prompt 输出契约,模型与执行分工,Skill 封装
协议与证据 MCP 接入,Codebase RAG,明确文件与版本
业务控制 受控事务、授权入口、Graph 条件路由与终止
运行恢复 Checkpoint、Time Travel、子状态隔离、循环与预算
执行验证 Sandbox、Fixture、真实测试与安全检查
治理演进 Trace、Metrics、Evals、CI 和受控发布

这些要求对应课程中的结构化契约、职责解耦、协议、事实依据、能力封装、事务授权、有环图、显式终止、快照、历史分支、多 Agent 隔离、循环拦截、沙箱、Harness、观测与评估十六个要点。

系统可靠性来自版本、状态、权限和验证证据之间的一致性。最终交付应是可审查、可复现并受授权约束的修改,而不只是模型生成的一段代码。