跳到内容
当前位置:首页>教案>AI编程经验总结:把能写代码变成可靠地写代码

AI编程经验总结:把能写代码变成可靠地写代码

  • 2026-11-05 02:11:08
AI编程经验总结:把能写代码变成可靠地写代码

QUOTE

工具会过时,解决问题的思路不会变。

本文看点

01

概念底座:Agent与Harness

02

问题梳理:过度服务、自作聪明、隐藏假设、全局缺失

03

实践经验:加限制、先规划、用工具、工作流协作

00

CODE QUALITY

开篇:代码质量问题

当前AI编程技术发展迅速,但评价AI写出的代码有三个递进的问题:能不能写出来,写得快不快,写出来的东西敢不敢应用在产品上。

三个问题,技术瓶颈各不相同,当前模型的生成能力已经越过可用线,但是生成的代码最终能不能被合入主干,应用在产品上,还有以下几个问题要考虑解决:需求有没有写清楚、执行有没有偏离,结果有没有被独立校验。

前两个问题,换更强的模型、完善的上下文管理就能解决;第三个问题主要技术手段是外围机制,约束、验证、留痕,这些不会随模型升级自动出现。

这篇文章不评测工具,更多的是基于本人这几个月的实践经验整理的一些提高AI编程质量的经验总结:理解Agent和Harness,正确高效的使用Agent,单模块团队协作规范、工作流设计等。由于跨业务模块,企业部门协作的AI研发平台,要考虑各种研发平台扩展,不同业务领域接口,涉及到的范围更广和更复杂,本文不做扩展。

AI编程对于个人开发效率的提高是毋庸置疑的,单人几个月时间完成了过去需要几个人至少一年甚至更长时间的代码开发,而且还构建了一套完善的开发环境工具,模块代码单测平均覆盖率也可以达到90%以上。但是整体的代码质量,团队协作开发,还是要考虑很多方面:架构的合理性,开发标准规范化,代码功能验证手段,知识沉淀积累等。

01

AI AGENT

AI Agent:三个组件与一个循环

1.1 一个公式:LLM + 上下文 + 工具

现代Agent的最小工程实现可以写成一个公式:Agent = LLM + 上下文 + 工具。公式描述的是Agent边界之内的组成,不包含与之交互的环境。三个组件各有明确职责:

直觉理解
实现组件
学术对应
职责
大脑
LLM
策略(Policy)
决定下一步做什么:理解意图、拆解任务、判断是否调用工具
眼睛
上下文
观察与历史
把环境返回的观察与已有历史组织成当前决策所需的信息
手脚
工具与适配器
观察 / 行动接口
规定可以读取哪些观察、发出哪些行动,以及接口格式

Agent与环境是闭环交互的两方:环境返回观察,Agent依据上下文选择行动,行动改变环境状态,新状态产生下一次观察。这划定了工程手段的作用位置:能改的是Agent这一侧的观察与行动接口,改不了环境本身的状态转移规律。

1.2 观察空间与动作空间:能力的主要杠杆

观察通道与动作接口共同构成Agent与外部世界的边界。由此得到一条对工程实践最重要的推论:

  • 没有通过观察通道进入上下文的信息,对模型而言等同于不存在;

  • 没有被动作接口允许的操作,模型即使知道该怎么做,也只能停留在文字建议上。

所以在底层模型固定时,提升任务表现最主要的手段是扩展观察空间与动作空间。许多看似需要更强模型才能解决的问题,实质是接口问题:把任务所需的数据纳入上下文,或把所需操作封装成工具,原本不可解的任务就可能变为可解。产品能力的演进多数可以还原为这两个空间的扩张。

1.3 ReAct循环与上下文的两段结构

Agent执行任务的核心模式是ReAct(Reasoning + Acting):模型先思考当前该做什么,再调用工具行动,然后观察返回结果并继续思考,循环直到不再产生工具调用。

每一次调用时,模型接收的完整上下文由两部分构成:

Agent的上下文 = 静态前缀 + 轨迹

静态前缀包含系统提示词与工具定义,全程不变。轨迹是不断增长的动态消息历史,包含用户消息、模型回复与工具执行结果。

trajectory = [user_request]repeat:    context = stable_prefix + trajectory    decision = Model(context)    trajectory.append(decision)    if decision has no tool call:        return decision.answer    for call in decision.tool_calls:       # 无依赖的调用可并行        validated_call = Harness.validate(call)        observation = Environment.execute(validated_call)        trajectory.append(observation)

在这种设计中上下文不断追加,每次调用都能看到完整轨迹,清楚任务进行到哪一步、此前尝试过什么;轨迹的结构化也便于解释、调试与聚合分析。代价也随之而来:轨迹只增不减,而上下文窗口是有限的。

1.4 上下文哪些内容能省,哪些不能

轨迹只增不减,窗口却有限,于是必须做取舍:删掉哪一部分,代价最小。

系统性消融实验(逐一去掉一类上下文内容,观察行为变化)给出的结论是:各类内容并不等价,衡量标准是它承载的信息能否从别处重建:

被去掉的组件
后果
工具定义
行动能力丧失,但模型不会沉默,照样给出格式工整、语气笃定的答案,数据来自参数记忆
工具执行结果
闭环失效,盲目执行,反复重试直至耗尽迭代预算
思考过程
若"为什么"可从"发生了什么"重建,丢掉几乎没有代价
历史消息
冗余操作增加,同样的错误会重复

对工程实践最关键的一条是:"给出了回答"不等于"完成了任务"。 上下文残缺时典型的失败不是报错退出,而是一个看上去毫无破绽的答案。提示词里"不得自行估计"这类约束只能降低编造概率,无法消除。

这张表也是所有上下文管理手段的依据:能被重建的内容可以压缩甚至丢弃,承载不可替代信息的内容必须保留。

1.5 模型即Agent,与更新路径

先进模型通过后训练把工具调用内化为原生能力:何时调用、调哪个、传什么参数,都由模型自己决定。但要分清归属:写进参数的是决策,工具本身及其执行仍在模型之外——真实实现、沙盒环境、调用的发起与结果回传,都由外围基础设施完成。

相应地,Agent的行为改变有三条路径,按持续时间与可回滚程度排列:

路径
生效范围
特点
上下文内适应
当前任务
示例与检索结果进入上下文立即生效;快速低成本,随会话结束消失
外部制品更新
跨任务持久
策略写进Prompt或Skill,确定性流程写成程序;可审计、可修订、可回滚
模型参数更新
模型本体
用于难以显式表达的高维能力;部署成本高,泛化强

本文后续大部分经验都落在第二条上:把规则、契约与验证写成可执行、可审计的外部产物,而不是依赖模型临场发挥或等待模型迭代。

02

HARNESS ENGINEERING

Harness:模型之外、Agent边界之内

第一节说明Agent由什么构成,本节说明它在生产环境里靠什么变得可靠:Harness。

2.1 Harness是什么:一条边界

从工程视角可以把LLM抽象为核心组件Model,把Agent边界内负责支撑模型运行、以及模型与环境交互的代码、配置和服务统称为Harness。生产形态的完整组成是:

Agent = Model + Harness
Harness = 上下文管理 + 工具接口 + 约束 + 验证 + 纠正
Agent ↔ Environment

两个公式是同一事物在两种抽象层次上的描述:Agent = LLM + 上下文 + 工具是最小工程实现,Agent = Model + Harness是它在生产形态下的展开。

Harness原指马具:不是限制马奔跑,而是把力量引导到正确方向。模型是那匹强大但不可预测的马,Harness是把它的能力引导成可靠任务执行的工程外壳。

Harness不是"模型之外的一切",而是"Agent边界内、模型之外":

属于 Harness
属于 Environment
工具定义、调用适配器
沙箱内随行动变化的文件与进程
沙箱的权限与重置机制
外部数据库、网页、用户
上下文组装、循环与状态维护
物理或仿真世界

2.2 让Agent从"能做事"到"可靠地做事"的要素

功能
职责与核心原则
实际例子
Context(上下文)
提供感知信息,让每个决策点基于足够信息判断
系统提示词、知识库、状态栏、旁路查询
Tools(工具接口)
提供观察与行动手段;命名直观、参数有例子、边界有说明
MCP工具、代码解释器、搜索工具
Constrain(约束)
设定行为边界;故障安全默认值,所有能力默认关闭、显式开放
每个工具默认需授权才能执行
Verify(验证)
自动判断结果对错;安全检查只看结构化数据,不看模型自由生成的文本
Linter、类型检查、调用结果校验
Correct(纠正)
出错时自动修正或回退;确认无法恢复之前不暴露中间态
静默重试、接续生成、连续失败回退人工

五个要素构成闭环:上下文与工具让Agent能做事;约束预防错误,验证发现偏差,纠正使闭环成立,三者让Agent不做错事。生产级系统的重心在后三者。

2.3 相关核心概念区别

涉及到Agent的概念比较多,有LLM、Prompt、Rules、Skill、MCP、Subagent、Hook、Harness。下表是这些概念的区别对比:

概念
解决的问题
落在哪一格
本质
失效条件
LLM
生成
Model本身
概率模型,预测下一个token
天生不确定;同一输入两次结果可不同
Prompt
单次指令
上下文管理
一次性注入的文本
会话结束即消失
Rules
常驻约束
上下文管理
每次会话自动注入的前缀文本
上下文变长后被腐化;模型可选择性遵守
Skill
可复用纪律
上下文管理
按需加载的模块化指令
依赖模型主动识别;弱模型会跳过
MCP
工具接入
工具接口
标准化的外部能力调用协议
只给能力不给约束;接入越多上下文越重
Subagent
上下文隔离
上下文管理
带独立上下文的子 Agent,只回传结论
子任务必须可脱手完成;回传过粗会丢关键证据
Hook
把软约束变硬约束
约束 + 纠正
生命周期固定点位上触发的确定性脚本
只覆盖有脚本的点位;脚本写错会静默放行
Harness
运行与治理
总称
上述各项加上约束、验证、纠正的编排者
缺失时,其余各项都是散的

Hook是这套体系里唯一不经过模型的机制。前面几个概念最终都要落到上下文里,由模型读取后决定是否遵守;Hook不进上下文,它在Agent生命周期的固定点位(工具调用前后、会话结束、任务提交)执行一段确定性脚本,可以阻止动作、注入反馈或强制改写输入。因此它是软约束与硬约束的分界线:写在规则文件里的"禁止强制推送"是建议,注册在调用前的Hook是拦截。

下表是与Hook相关的机制,这些机制共同构成约束的执行面:

机制
作用位置
特点
权限与沙箱
执行层
白名单与最小权限凭证,默认关闭、显式开放
只读审查进程
执行层
独立于主上下文的评审者,只看产物与结构化参数
CI与流水线检查
交付层
不依赖任何一次会话,是唯一完全脱离模型判断的强制点
数据层约束
数据层
行级安全策略与校验器;上层全部失效,越权仍在这里被拒绝

判断一条约束是否真的生效,标准只有一个:它被无视时,是否有一个不经过模型的机制拦得住。

两个易混点需要单独说明。

其一,MCP只解决"能做什么",不解决"该不该做"。 接入外部系统属于能力扩张,不在约束层。Agent接入十余个MCP后表现明显下降,原因是工具描述本身占用上下文,且不会提示此刻哪个工具不该用。能力越多,约束层的负担越重。

其二,Harness是总称,不是某个具体文件。 一份CLAUDE.md是Harness的一部分,pre-commit钩子是,CI流水线也是。判断标准是:它是否在Agent边界内、模型之外做事。

2.4 工具的类别与规模

"工具"常被理解为"能调用的函数",这个理解过窄。按调用方向划分有五类:感知(获取信息,控制输出量防上下文爆炸)、执行(改变世界,安全约束是核心)、协作(驱动其他Agent或人类)、用户沟通(异步触达)、事件触发(声明关心的事件,由外部回调唤醒)。编码Agent日常的读写文件、执行命令、搜索主要落在前两类。

工具规模本身就会影响正确性:数量过多时,即使最先进的模型也容易在工具选择上出错;全部平铺进上下文还要占去大量token。工具使用的优化策略主要是以下三条:

层次
做法
索引化
只暴露工具名称索引,需要时再查定义
检索式预筛选
按语义相似度先筛候选再注入
主动发现
只留基础工具与一个"工具搜索"元工具

Skill的实现策略更轻量:启动时只看到一份薄目录(每个Skill的名称与描述,合计数百token),当前上下文真的需要时才读取正文。专用工具要达到同样的渐进式披露,必须在工具之外另建一层检索基础设施。这就是Skill比同等数量的MCP工具省上下文的原因。

2.5 范式演进:五层包含关系

回顾AI应用工程的发展,具有一条清晰的演进路线,后者包含前者:

提示工程       优化输入给模型的自然语言指令 └ 上下文工程    系统管理模型能看到的所有信息    └ Harness工程   扩展到Agent如何组织模型运行并与环境交互       └ Loop工程     跨轮次的持续自主运转          └ Graph工程   把循环、确定性程序与人工审批组织成显式执行图

当各家模型的能力趋于接近,竞争优势转移到模型之外的工程实践。

关于模型变强之后Harness是否会被吃掉:结论是会,但被吃掉的部分有明确范围。凡是给模型能力短板打补丁的适配层,few-shot示例、"一步一步思考"这类提示技巧、输出格式修复与JSON解析容错,都已被指令微调、推理能力与结构化输出内化。未被内化的是约束与验证:业务约束与团队偏好无法一次写进参数,且训练以月为单位推进,跟不上工程现场的变化速度。

模型当前的能力边界,就是Harness当前的价值所在。每一轮内化消灭的是脚手架,不是缰绳。

2.6 Harness构建原则与护栏

保持简单。 每多一层抽象,都会成为后续调试时新的盲区。

保持透明。 显式展示规划步骤、执行日志与决策轨迹。黑箱里的错误一旦发生,外部观察者既无法定位也无法纠正。

设计好ACI(Agent-Computer Interface)。工具应对应Agent的目标而非底层API操作,从Agent视角而非程序员视角设计接口。容易误用的地方要从设计上让错误无法发生,设计实现防呆机制。模型与工具之间唯一的沟通通道就是接口本身,模糊的接口会被模型放大成系统性错误。

工具描述层面有两条实用规则:

  • 列出边界条件比描述能力更重要。 多数调用失败的根因不是模型不知道工具能做什么,而是不知道工具不能做什么。

  • 参数说明用具体例子代替抽象规范。 为每个工具附1至5个真实调用示例,可将调用准确率大幅提升。

护栏按被绕过的难度分为三层,越靠下的层越不依赖模型自身的判断:

层
管什么
机制
上下文层
模型能看到什么
相关性分类器、安全分类器、内容审核、正则与黑名单
执行层
模型能做什么
工具风险评级、独立审查进程、最小权限凭证、沙箱隔离
数据层
世界最终能被改成什么样
行级安全策略、约束与校验器、受控视图

上下文层有结构性上限:处在同一个上下文里的Agent,很难判断自己是否已被注入;执行层的复核必须由上下文之外的机制完成。数据层的价值在于不依赖上面两层:即使提示注入得手、生成的代码漏写了权限判断,越权操作仍会在数据层被拒绝。评估护栏还要防另一类失败——误拒绝:不能只测"该拒的是否被拦截",还要测"明确允许的是否能正常完成"。

03

FAILURE MODES

AI编程的问题:过度服务、自作聪明、隐藏假设、缺乏"全局视野"

"敢不敢合入主干"是一句直觉判断,拆开之后是三条可判定标准:

判定
问的具体是什么
典型失败形态
能不能跑
行为正确,边界条件正确,且测试真的有效
覆盖率达标但断言不严谨;判定条件被改过仍能通过
能不能改
结构清晰,重复率低,抽象层次合理,与既有约定一致
同一功能多套实现;每次新需求都另起炉灶
能不能负责
改动有据可查,有独立验证证据,出问题可定位、可回退、可审计
说不清改了什么;只有作者自己确认过没问题

三条都过关,才能"敢"。前两条多数团队已经在管,真正稀缺的是第三条:而且前两条会随模型变强自发改善,第三条不会,它的证据在工程机制里,不建就没有。

下表是AI出现的典型异常问题。

症状
病根
缺失的 Harness 组件
聊着聊着偏离最初目标
上下文腐化:装得下但找不到了
上下文管理
长会话后推翻早前已同意的决策
注意力被噪声抢占
上下文管理 + 约束
换会话即失忆,约定需人肉重申
状态活在对话里,未落盘
上下文管理(持久化)
覆盖率数字达标但测试是"圆"出来的
概率模型会优化它能观测的指标
验证
模型自评"没问题"
写与评是同一个Agent
验证(角色隔离)
代码重复率持续上升
局部最优不等于全局最优
约束 + 验证

3.1 上下文过长导致的腐化,而非遗忘

长上下文里表现下降,通常不是遗忘,而是上下文腐化(Context Rot)。两者的区别很重要:溢出是"装不下了",腐化是"装得下但找不到了"。后者更隐蔽,Agent表面上仍在工作,决策质量却在下降。

机制上的原因是:一,注意力权重被分摊到更多token上,每个token 获得的权重变小;二,无关内容的占比上升,偶尔才用到的知识每次都加载、稳定规则与动态状态混在一起,有用部分越来越难被注意到。

还有一层更根本的机制:注意力机制擅长在已有内容里查找,不擅长在一次前向传播里主动归纳统计——上下文学习更接近检索而非推理。因此"把更多信息塞进上下文"的收益存在上限,主动提炼出高密度结论("目前已知:A 是……,还缺 C")比堆原文有效得多。这也解释了为什么"把规则写清楚"本身无效:清楚不等于有权重,规则还在上下文里,权重掉下去了。

对策方向因此确定:不是增加规则数量(那只会加速腐化),而是:

  • 减少常驻量:只把稳定规则放进静态前缀,其余按需加载;
  • 提高信息密度:把需要思考才能得到的结论显式提炼出来;
  • 隔离优于压缩:让大体积中间信息根本不进入主上下文。委派一个子Agent 在代码库中大范围搜索,主上下文只增加两条消息——一条任务描述、一条结论,中间过程的数万token随子Agent的上下文一起被丢弃。

3.2 概率模型会优化你能观测的东西

LLM是概率模型。

相同输入,不同输出。"上次让它这么做是对的"不构成任何保证。

给什么指标,就优化什么指标。 只提"测试覆盖率达标",覆盖率会被做上去,至于测试本身是否有效,不在优化目标内。当验收阈值以脚本默认值的形式存在时,模型可以通过修改判定条件让检查通过,覆盖率照样达标,检查形同虚设。修正方式是把阈值移到独立的红线配置,任何改动触发门禁,工作流停下等待人工确认。

由此得到一条硬规则:凡是可被模型观测到的验收标准,都必须设计成它无法单独篡改的形式。

3.3 模型不能给自己当裁判

同一个Agent既写代码又做评审,结论几乎总是"没问题"。这不是欺骗,是自我确认偏差:它评审的是自己刚刚构建的东西,带着同一条推理路径。

规则只有一条:写与评必须是两个独立上下文。

3.4 局部最优,全局恶化

模型写的局部代码通常质量不错,但每个新需求对它都是一次重新开始。项目越大,需要遵守的既有准则越多,一旦检索词过窄或根本没检索到类似实现,就会自行另起炉灶。更麻烦的是正反馈:当它发现同一功能已有多种实现时,不收敛,反而叠加补丁。

04

CONSTRAINTS FIRST

经验一:给Agents加限制

约束成本最低,收益最直接。多数团队做不好这一层,原因不是没写规则,而是规则写得不可执行。

4.1 规则的三条写法原则

原则一:写成可判定的,不要写成好听的

反例(不可判定)
正例(可判定)
代码要简洁
200行能完成的事若你用了500行的方案,重写
不要过度设计
不为单次使用的代码引入抽象;不添加未被要求的配置项
注意边界情况
信任边界处的校验、防止数据丢失的错误处理,永远不删
保持一致性
复用代码库已有helper,按周围代码的用法使用

差别在于:前者需要模型做主观判断,后者照做即可判定是否违反。

原则二:声明"什么时候可以不遵守"

一套偏谨慎的规则若对所有任务一视同仁,模型会走向全遵守或全无视两个极端。好的规则自己声明边界,例如"这些准则偏向谨慎而非速度,琐碎任务请自行判断"。

原则三:把成功标准写进任务,而不是写进流程

弱成功标准
强成功标准
加上参数校验
为非法输入写测试,然后让它通过
修掉这个bug
写一个能复现它的测试,然后让它通过
重构X
重构前后测试都要通过

强成功标准让模型能自主循环,弱成功标准迫使它反复回来确认。

4.2 可参考的限制模板

首先是Karpathy Guidelines,这是一套由Andrej Karpathy(前Tesla AI总监、OpenAI创始成员)总结的行为指南,专门针对使用LLM进行代码编写的场景。

它源于Karpathy对LLM编码陷阱的大量观察。不同于传统的编码规范(如 Google Style Guide),这套指南不是关于命名规范或代码格式,而是关于如何思考和行动。核心哲学是:偏向谨慎而非速度。宁可多花一分钟思考,也不要花一天时间修复原本可以避免的问题。

https://github.com/multica-ai/andrej-karpathy-skills.git

Karpathy Guidelines共四条,覆盖最高频失效点:

  • 编码前先思考。 核心要点:明确说明你的假设;如果不确定,主动问;如果有多种解释,列出来,不要默默选择一个;如果有更简单的方案,说出来;
  • 简单优先。核心要点:只写被要求的功能;不为"将来可能需要"添加功能;不为"灵活性"添加配置项;如果200行可以写成50行,重写;
  • 外科手术式改动。 核心要点:不"顺便"修复其他问题,不重写不相关的代码,匹配现有代码风格,即使你不会这样做,只删除你自己引入的无用代码;
  • 目标驱动执行。 核心要点:将模糊的任务转化为可验证的目标,先写测试,再写实现,为多步骤任务制定简要计划;
然后是Ponytail,核心主张是:能一行代码搞定,绝不多写一行。在AI正式编写代码之前,先执行多轮自我审查,优先复用现有能力,从源头减少冗余产出。 治理AI的过度开发,重复实现、复杂实现等问题。和Karpathy Guidelines简单优先原则异曲同工。
https://github.com/DietrichGebert/ponytail.git
对方案要懒,对改动本身不能懒。决策顺序可直接提取为规则:
  • 这东西真的需要存在吗?(跳过没人要求的特性、选项、灵活性) 
  • 代码库里已经有了吗?(用现有的 helper/组件/服务/模式) 
  • 标准库或平台特性有吗?(除非项目有自己的约定) 
  • 已装的依赖能解决吗?(永远不为几行代码加新依赖) 
  • 能写成一眼看懂的一行吗? 
  • 否则:写能工作的最少代码。
Karpathy Guidelines改的是决策过程,Ponytail改的是产出代码量。

4.3 Rule未程序化,等于未写

用自然语言写约束、指望模型自觉遵守,是规则落地最常见的弯路——真正让它生效的往往是后来补上的hook和lint。因为Linter与CI给出的是"做不了",提示词给出的是"建议别做"。能机器判定的才叫规则,只能靠模型的那叫建议。推荐是把可机器化的规则全部移出提示词:
// 例:把"禁止高危操作"从提示词搬进配置{  "permissions": {    "deny": ["Bash(git push --force*)", "Bash(rm -rf *)"],    "allow": ["Bash(npm test*)", "Bash(openspec validate*)"]  }}

判断标准很简单:这条规则能不能写成一条机器判定。能写成就移出提示词;写不成的留在提示词里,并接受它只是一句建议。

05

PLAN MODE

经验二:优先使用PLAN模式,先规划再执行

工作流框架并不适用于所有场景。修改一个函数、增加一个参数、修复一个明确的缺陷,引入工作流框架有时过于复杂。但"简单"不等于"可以直接开写"。这一层的两个核心动作是:先规划,再强化验证。前者决定"能不能改"的方向是否正确,后者决定"能不能跑"的证据是否真实。

5.1 PLAN模式:暂扣执行权

PLAN模式指:让Agent在本轮只读、只分析、只规划,不修改代码。产出一份计划和一组待确认问题,确认后进入执行。

这一步的价值在于改变默认行为。模型的默认反应是"拿到需求就动手",PLAN模式不增加能力,只把默认路径从执行改为规划。一个PLAN轮次应要求回答三件事:

  • 准备修改哪些位置:调用方、测试、fixture、配置、导出,列全;
  • 遇到了哪些歧义:存在多种理解时列出,不能默选一个;
  • 每一步的验证方式,格式统一为"步骤 → verify: 检查项"。
第2条最关键。模型不会主动承认自己没想清楚,除非"暴露不确定性"被写进流程。

5.2 强化验证:不止看覆盖率

验证要自动化,但自动化的指标必须选对。覆盖率只能证明"覆盖到了",不能证明"测到了点上"。 当同一模型既写实现又写测试,容易产出定制化断言:错误的行为、错误的参数,测试一样通过。

解法是变异测试:自动把源码故意改坏(把 > 改成 >=、反转条件),再跑完整测试。测试没有失败,说明断言不够严谨,需要重新设计测试用例。

5.3 人工验收:上移一层,而非逐行阅读

模型产出速度持续提升,逐行读完再合入已不现实,瓶颈转移为"读懂才能放心"。业界有两种取向:

  • Addy Osmani:工程师不退出代码审查,而是上移一层,抽查代码、审计方案,把有限的注意力投向更关键的位置。

  • Antirez:基本不读代码,只控制模型的想法与设计。前提是有能力判断方向是否正确,且存在可靠的检测机制。

可行方案是四类读物的优先级排序:验证需求与设计 → 裁决分歧 → 精读关键路径代码 → 查看验收报告。 注意力按此顺序分配。目的不是取消代码阅读,而是把逐行阅读从机械性内容中解放出来。

https://addyosmani.com/blog/agentic-code-review/
https://antirez.com/news/169

06

CONTEXT WINDOW

经验三:熟练使用现有指令,把上下文窗口管起来

前面两个实践经验聚焦在解决"做什么"和"怎么做",这个经验解决一个日常问题:同一件事做到一半,这段对话该怎么处置。

主流编程Agent都内置了若干上下文管理指令。它们常被当作功能开关使用,实际上做的是同一类工作,管理上下文窗口。区别在于对"历史"的处置方式:分叉是复制,无损、开新分支;压缩是摘要,有损、单线继续。以下以具备完整实现的一类编程Agent为例说明,具体命令名以所用工具为准。

6.1 窗口是双重约束,不只是容量

窗口之所以需要主动管理,是因为它同时构成两类约束:

质量约束。经验上存在一个推理质量较高的区间(约150k token量级),超出之后退化的表现是注意力被稀释、约束被忽略,而不是报错。
成本约束。对话是append-only的,每一轮都要把完整历史重发一遍。死胡同、被否掉的方案、跑偏的调试一旦进入主线,之后每一轮都要为它们付费,并且没有"只删这一段"的手段。

因此每个上下文动作都是在做一笔显式交易。六种常见动作按信息保全程度排列:

动作
信息
噪声
余量
代价
继续(Continue)
完整(一手)
多
小
窗口持续收紧
分叉(fork)
完整(复制)
两条分支各自独立
大
总量翻倍;文件改动不隔离
压缩(compact)
有损摘要
少
大
决策的"为什么"被压平
清空(clear)
零
零
全窗口
不可逆地丢失 why
交接(handoff)
有损,但可移植
少
大
只值得用于跨 harness、跨目录、跨人
子代理(subagent)
主线不动
主线不增
大
子任务必须可脱手完成

分叉与压缩正是"无损但更贵"与"便宜但失真"的两端。

6.2 分叉与压缩:两个端点

分叉保留源会话的完整历史,从同一出发点开一条独立会话,用于探索替代方案而不破坏原来的讨论;两条分支都继承源会话的Agent与模型配置。它有两个边界要记住:不隔离文件改动——同一目录或Worktree下的分叉会改同一批文件,要隔离代码只能新建Worktree;不省token——历史原样复制一份,两条分支各付一次,解决不了窗口不够用的问题。它真正划算的地方在于:探索的账记在一条可丢弃的分支上,主线保持干净的一手记录;且两条分支共享同一份前缀,Prompt Cache仍然可用,成本远低于"新开会话再解释一遍背景"。

压缩把较早的历史总结成摘要,释放上下文空间。窗口填满时Agents本来就会自动压缩,手动执行的价值不在"能否压缩",而在由人来选择时机与保留内容。它同样有两个边界:有损——摘要会把"为什么这么决策"压成结论,典型的失败形态是对一个被压平的决策极度自信地做错。压缩只能在阶段边界做——任务中途压缩会切断线索,中途要么继续,要么把剩余工作拆给子代理。

6.3 决策顺序

按顺序判断,规则如下:

分叉不在这五档之内,因为它解决的是另一类问题:同一Agents、同一目录、还要保留完整推理链的分支比较。典型用法是在当前设计的基础上比较另一套方案,同时明令不改任何文件。

6.4 落盘优先于压缩

压缩只能释放空间,不能承担记忆责任。 压缩必然丢失的是"为什么",而这恰恰是ADR、spec、契约文件应该承载的内容。把决策写进文件之后,压缩就不必再为保留这些决策负责;反之,若所有决策只活在对话里,任何一次压缩或清空都会造成不可逆的信息损失。

操作顺序是:先落盘,再压缩。阶段结束时的动作是把结论写进仓库,然后才考虑是否需要压缩窗口。这也解释了为什么把"外部产物更新"列为跨任务持久化的主要路径:它是唯一不随上下文处置而丢失的机制。

07

DUAL-LAYER WORKFLOW

经验四:使用工作流,规范团队开发标准,保证代码质量

当任务跨会话、跨人、需要留痕时。意图与验收标准必须落盘,使其不依赖任何一次对话而存在。而且多人协作开发,需要统一规则和标准,保证团队的代码交付质量。

当前针对编程的工作流Skills有很多,比如OpenSpec / Spec Kit:侧重上下文管理(spec/规范)和约束(Constitution、变更管理),让Agent先明确“干什么”再动手;Superpowers:侧重约束(强制七阶段流程)和验证(强制 TDD、两阶段代码审查),让Agent“不做错事”;MattPocock/Skills:侧重工具接口(工程技能模块)和需求澄清、实现验证(grill-me需求审查、TDD),把工程实践编码为可调用模块;Addyosmani/agent-skills:把资深工程师的工作流(spec → plan → build → verify → review → ship)编码成结构化的Skill,让编码Agent在开发的每个阶段都能一致地执行这些工作流与质量门禁。

上述每个Skill都非常优秀,在不同的应用场景下都可以发挥巨大的作用。作为使用者,不需要也不建议每个Skill都安装使用,根据使用习惯或者团队模块需求,选择合理的Skill就行。下文根据本人实际使用经验,说明如何根据开发需求组合、修改这些工作流Skill。

本人在实际开发中,主要使用了OpenSpec和MattPocock/Skills,并根据实际使用需求完成了工作流修改和组合。下面主要是针对这套方案的说明和思路。

7.1 两个工具分别解决什么

OpenSpec
MattPocock Skills
定位
产物框架
行为纪律库
回答的问题
要做什么,做完如何证明
这段代码写得够不够格
核心产出
proposal.md / specs/ design.md / tasks.md / archive/
符合标准的代码,GLOSSARY.md、ADR、review报告
事实来源
规格(代码是派生输出)
代码(规格是对齐工具)
强制力来源
CLI校验,确定性,可挂CI
模型遵从,无程序强制
https://github.com/Fission-AI/OpenSpec.git
https://github.com/mattpocock/skills.git

OpenSpec的优势:变更制品结构化,validate --strict提供不经过模型的结构校验,可直接接入CI;归档目录带日期、delta回写specs,天然审计留痕。

OpenSpec的短板:只校验结构,不评价代码质量,也没有TDD纪律;并发执行能力弱;上下文管理停留在提示级——官方文档建议"实现前清空上下文",属于人工约定而非机制;依赖强推理模型,弱模型上明显退化。

MattPocock的优势:覆盖实现全链路——带阻塞边的ticket拆分、TDD红-绿-重构、调试决策树、双轴review;ready frontier模型允许多个实现子代理在各自worktree上并行;上下文管理在机制级——子代理使用新鲜上下文,配合上下文指针与统一术语表;统一语言与领域建模有方法论支撑。

MattPocock的短板:无持久化状态机,产物就是仓库里的普通文件,跨会话恢复靠人;无可挂CI的确定性校验;无归档与审计留痕;重度依赖worktree与后台子代理,在能力较弱的harness上退化为串行。

7.2 组合的必要性

团队单用任一技能,在否些方面都存在缺陷:

环节
单用OpenSpec
单用MattPocock
组合
意图与验收落盘
有
无
OpenSpec承担
可挂CI的确定性校验
validate --strict
无
OpenSpec承担
跨会话恢复与审计
制品在仓库,可追溯
无状态机
OpenSpec承担
TDD与代码质量纪律
无
有
MattPocock承担
多任务并发执行
弱
ready frontier + worktree
MattPocock承担
调试与架构治理
无
有
MattPocock承担
验证
结构校验 + 一致性核对
双轴 review(Standards / Spec)
两者职责不同,都必须执行

两个Skill部分实现存在重叠,组合必然有代价,主要冲突有两处:

上下文膨胀。 两套规则文件同时进入上下文,会加重上下文的负担。

流程主导权。 双方都有"我来编排流程"的倾向,不人为划定主从,必然打架。因此组合的必要性不只是能力互补,还包括一件必须主动做的事:划定主从边界。

7.3 组合方案:需要考虑哪些方面

组合两个工具的本质,是定义一套跨工具的约束结构。下面几个方面是需要处理的内容,每个方面给的是思路与判据,可以根据团队实际使用调整设计。

一:先定职责

  • OpenSpec管"写下来":行为契约、变更制品、阶段状态、归档生命周期。
  • Matt管"写得好":任务拆分、TDD、实现编排、双轴评审。
  • ADR架构关键决策管"为什么":长期架构决策及其权衡。
  • GLOSSARY.md术语表管"词是什么":领域术语的唯一含义。
其中ADR、GLOSSARY.md是Matt产生的架构相关产物,四条边界清楚之后,冲突的处置就有依据:属于"为什么"的问题回到决策记录,属于"是什么"的问题回到行为契约,属于"这次怎么改"的问题回到变更目录。多数项目文档混乱的根源是这四件事被写进同一份文件,而它们的生命周期不同:
术语表       这个词是什么意思?       → 长期决策记录     为什么这么架构?         → 长期,靠新增记录supersede行为契约     系统当前必须怎样表现?    → 持续演进变更目录     这次要改什么、怎么改?    → 随变更归档

由此得到以下设计规则:

  • OpenSpec执行流程是唯一主时间轴:propose -> validate -> apply -> verify -> archive。
  • Matt/to-tickets是进入apply的准备闸门:implement -> tdd -> code-review在apply内执行,不得跳过、替换或重排OpenSpec阶段。
  • OpenSpec tasks.md是任务标题、验收条件和完成状态的事实源。

  • tickets/是Matt的执行投影,不得改变tasks.md的验收语义。

  • 每个Scenario的独立THEN必须能翻译为至少一个可执行断言。

  • 已接受ADR不得被spec或实现静默推翻;改变决策必须新增superseding ADR。

二:指令分层

Agent约束来自以下几类指令,作用域与加载时机各不相同,在团队项目中使用时,需要综合考虑“4.2限制模板“和Skill的配合。

层
作用域
加载时机
管什么
用户级指令
跨仓库
每次会话常驻
通用行为纪律与人格模式,即第4章两份模板的落点
项目级指令
本仓库
按路径或语义惰性加载
语言、框架、构建、提交约定
项目入口
本仓库
每次会话
路由与禁令,不复述内容,项目根目录AGENTS.md
项目契约
本仓库
被显式要求时读
接口协议与完成门禁,AGENTS.md路由到项目存放位置
技能
跨仓库/本仓库
描述常驻、正文按语义触发
动作入口
生成期注入
仅制品生成时
生成制品与指令时整段注入
制品写法规则与阶段闸门,OpenSpec/config.yaml

三:证据策略

单向数据流。 契约是事实源,执行票据是投影。投影可补充"怎么做",不得新增、弱化或改写验收语义,否则"实施时偷偷放宽验收"在机械层无法被发现。改验收的唯一合法路径是先改契约再重新投影。

新增行为必须附失败记录。 新增可观察行为的覆盖项必须附一条失败证据(命令、非零退出、诊断输出),否则红绿无从区分,测试可以是事后补的。已有行为允许复用既有成功证据,不强迫造红。

评审范围要固定基点与边界。 以固定基点到工作区的完整差异为准:已跟踪与已暂存全收,相关未跟踪文件显式列出,构建输出显式排除。默认以 HEAD 为基准的三点差异会漏掉未提交实现,而这恰恰是常态。

评审轴可扩展。 除规范符合度与契约忠实度两轴外,可按需增加"架构决策一致性":相关决策是否已识别、是否违反已接受决策、改变决策是否有 superseding记录。

关键动作核验两次且不合并。 以归档为例:同步主契约之前验一次,同步之后、移动目录之前再验一次。第二次不是重复——同步会改写主契约,第一次看到的与最终落地的未必一致;若合并成最后验一次,同步阶段可能已经在错误基线上动了主契约。

四:上下文、冲突与边界

由于组合使用会重新编排上游技能的使用策略,修改一些产物的默认位置,所以针对OpenSpec和Matt的原始技能,需要区分使用。而且Matt/Skill是通用实现,直接接入OpenSpec流水线会出现产物落点不一致、语义双向污染、指令重复三类问题。需要逐项处理。

类别
判据
典型
直接可用
不写死路径、不产生未授权副作用
TDD、需求对齐、领域建模、调试
Matt/grill-with-docs domain-modeling
OpenSpec/explore
 只作参考
结论可用但范围或落点不满足
代码评审Matt/code-review
需适配
输出落点在项目约定目录之外
任务票据生成Matt/to-tickets
禁止
自行创建分支、worktree、合并与PR;在既有契约之外再造一份计划源
并发编排、规格生成Matt/to-spec
禁止重跑
会用上游种子模板覆盖项目适配文件
初始化脚本Matt/setup-matt-pocock-skills

Matt/Skill需要的最小指令集如下:

setup-matt-pocock-skills    # 必须最先执行,生成项目约定,单个项目执行一次grill-with-docs             # 需求对齐与术语统一to-tickets                  # 带阻塞边的任务图implement-spec              # ready frontier并发编排tdd                         # 红-绿-重构code-review                 # 双轴评审diagnosing-bugs             # 调试决策树improve-codebase-architecture  # 周期性架构勘察

OpenSpec初始化之后,会在项目目录下生成如下文件夹,用来保存变更文件。

openspec/├── config.yaml              # 项目配置├── specs/                   # 已生效的能力规格│   └── .gitkeep             # 空目录锚点└── changes/                 # 进行中的变更    └── archive/             # 已归档变更        └── .gitkeep         # 空目录锚点

Matt执行setup-matt-pocock-skills之后,会在项目目录下生成如下文件夹,用来记录ADR架构决策、agents定义路由等文件,在项目根目录下生成GLOSSARY.md术语表。

docs/├── adr/                     # 编号架构决策记录└── agents/                  # agent 工作流与票据协议    ├── domain.md            # 如何消费本仓库领域文档(GLOSSARY / ADR / 语言政策)    ├── issue-tracker.md     # Matt票据的本地Markdown存放与流转规则    └── triage-labels.md     # `/triage`五个角色对应的 label 字符串

所以使用openspec文件夹保存项目修改变更和能力规格,使用Matt的相关文件保存架构相关文档,但是由于Matt/to-tickets技能默认是将文件保存在项目根目录.scratch/<feature>/issues/。

这些属于单次变更记录而且和OpenSpec changes相关,所以需要修改docs/agents/issue-tracker.md,将文件保存迁移到openspec/changes/<change-id>/tickets/。

openspec/changes/<change-id>/    ├── tickets/      ← to-tickets的输出    ├── review.md     ← code-review双轴结论    └── tasks.md      ← 事实源,由OpenSpec生成

Matt/to-tickets生成的ticket是tasks.md的投影,只能补充"怎么做",不得新增、弱化或改写验收语义。投影不能反向修改事实源——这条单向数据流需要写进Skill说明,否则模型会在实现阶段自行调整验收条件。

Matt/code-review的Spec轴回答"是否忠实实现了原始契约",需要把结论落盘为结构化条目,供OpenSpe的verify阶段读取。约定格式:

# review.md## Standards 轴- [ ] 无重复实现 / 复用既有 helper- [ ] 错误处理未越界## Spec 轴- [ ] Scenario: 目标 App 未安装 → 断言存在且通过- [ ] 未实现项:无## 结论PASS / FAIL(FAIL 需列出违反的具体条目)

五:最终设计清单

开发的过程按照阶段,可以分为:需求->设计->实现->验证->审核。所以工作流的设计实现也是按照这个流程完成。工作流程如下:

项目Agent相关文档规范设计如下:

GLOSSARY.md                     这个词是什么意思?       长期docs/adr/                       为什么这么架构?         长期,靠新增 ADR supersedeopenspec/specs/                 系统当前必须怎样表现?    持续演进openspec/changes/<change-id>/   这次要改什么、怎么改?    随变更归档    ├── proposal.md   本次的问题、范围、影响    ├── specs/        本次行为契约 delta    ├── design.md     本次实现设计    ├── tasks.md      任务、验收条件、完成状态    ├── tickets/      to-tickets 的投影    └── review.md     双轴评审证据

定义三个交接接口,工具组合的难点不在安装,在交接格式。必须自己定义三处:

  • 接口 1:tasks.md → tickets。 约定每个二级标题对应一个ticket,每个 checkbox对应一条验收条件,阻塞边从章节语义依赖或显式标注 <!-- blocks: G-1 --> 读取。

  • 接口 2:Scenario → 测试。 约定每个Scenario的THEN子句必须能翻译成至少一个可执行断言,执行层据此生成失败测试(红),再实现(绿)。

  • 接口 3:review.md → verify。 verify阶段读取review.md做最后一公里核对,通过后归档。

组合Skill实现五个指令,完成交接接口、执行、验收的流程触发。更多集中在流程靠后阶段。

指令
语义
是否带项目门禁
prepare

生成并校验项目 ticket projection

是
apply

在ticket、blocker和项目开发约束下调用implement / tdd

是
review

调用code-review并补齐ADR、范围和snapshot约束

是
verify

运行项目自有的OpenSpec、ticket、evidence校验

是
archive

verify、sync、再次verify后归档

是

使用OpenSpec和Matt原始指令如下,主要集中在需求、设计、实现等阶段。

指令
语义
是否带项目门禁
Matt

to-tickets、implement、tdd、code-review

否
OpenSpec

openspec-propose、openspec-apply-change、openspec-sync-specs、openspec-archive-change

否

上述所有的设计都是针对Agent读取使用,考虑到项目需要有开发人员参与,所以根据开发过程中的文档类别,设计了更完善的文档归档策略。

要解决的问题
文档归属
约束

系统现在是什么结构,边界在哪

docs/architecture/

只写跨多个 change 仍成立的架构事实;实施过程、验收数据和历史差异不进这里

现在怎么做这件事,命令和参数是什么

docs/guides/

命令、路径、参数或配置语义变化时同步更新;失效的步骤直接删除

有哪些方案,证据和取舍是什么

docs/explorations/

明确 Status、Conclusion 和 Next destination,不直接承诺当前行为;已落地或被推翻的直接删除

这件事做到哪一步,下一位怎么接

docs/handoffs/

只记录短期交接现场,不替代任务系统或长期设计;完成后删除

这个问题为什么发生,怎么防复发

docs/lessons/

只沉淀跨问题可复用的经验;单次审计的过程记录不写进来

文档流转按以下边界执行:

完成工作流设计之后,需要考虑一个实际问题,真正企业级别的代码,几十个模块,几万行代码,一堆历史文档。Agent如何快速地找到合适的东西,如何降低Token消耗,是两个必须考虑的问题。所以需要给工作流添加知识图谱,经过评估选用Graphify和CodeGraph。

维度
Graphify
CodeGraph
需求
文档经验知识检索
代码结构理解
核心能力
多模态支持
Tree-sitter静态分析+图遍历
LLM依赖
低
零
存储
JOSN文件
SQLite
License
MIT
MIT

Graphify和CodeGraph作为可选的"知识感知层",通过MCP协议提供服务。工作流各阶段的规范文件里加上"优先用知识图谱查询,不可用时回退grep/Read"的指引。编排层不需要知道底层是SQLite还是JSON,只管调MCP工具。

https://github.com/Graphify-Labs/graphify.git
https://github.com/colbymchenry/codegraph.git

最后在AGENTS.md中完成项目规范的路由和规范定义,由于在项目中涉及多个文档的编写和阶段流转,一个值得注意的细节时,将文档根据不同的类型规范使用不用的语言,便于开发者阅读和避免流程歧义,类似如下规范:

Agent instructions and workflow contracts use English. Domain and behavior prose usesChinese. OpenSpec structural keywords, code identifiers, paths, commands, API names, andprotocol fields remain unchanged. See docs/agents/domain.md for the document language policy.

08

CLOSING NOTES

写在最后

约束比能力重要。 模型能力已经越过可用线,产出质量取决于外围套了多少层可靠机制。

软约束必须配硬执行。 写进CLAUDE.md的规则,若没有一个不经过模型就能执行的检查兜底,只是一句建议。

验证必须独立于实现者。 三条里优先级最高的一条:模型不能给自己当裁判,人也不能因为"看起来对"就放行。

写代码的成本在下降。没有跟着变便宜的是另外几件事:把需求想清楚、在开发过程中守住工程判断、把最终结果验清楚。

技术发展迅速,对于开发者和公司,都需要根据技术发展调整自己的开发方式和组织方式。

参考来源:

李博杰《深入理解 AI Agent:设计原理与工程实践》

Addy Osmani《Agentic Code Review》

Antirez《Control the ideas, not the code》

往期推荐:

读懂Agent AI:大模型长出身体的两年

AI写代码越快,越要重视软件的设计哲学

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-11-06 19:56:46 HTTP/1.1 GET : http://a.sjds.net/a/543014.html
  2. 运行时间 : 0.078744s [ 吞吐率:12.70req/s ] 内存消耗:4,717.96kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=8d3df5588afde817210a0fd5b903bc4c
  1. /www/wwwroot/a.sjds.net/public/index.php ( 0.79 KB )
  2. /www/wwwroot/a.sjds.net/vendor/autoload.php ( 0.17 KB )
  3. /www/wwwroot/a.sjds.net/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /www/wwwroot/a.sjds.net/vendor/composer/platform_check.php ( 0.90 KB )
  5. /www/wwwroot/a.sjds.net/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /www/wwwroot/a.sjds.net/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /www/wwwroot/a.sjds.net/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /www/wwwroot/a.sjds.net/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /www/wwwroot/a.sjds.net/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /www/wwwroot/a.sjds.net/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /www/wwwroot/a.sjds.net/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /www/wwwroot/a.sjds.net/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /www/wwwroot/a.sjds.net/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /www/wwwroot/a.sjds.net/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /www/wwwroot/a.sjds.net/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /www/wwwroot/a.sjds.net/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /www/wwwroot/a.sjds.net/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /www/wwwroot/a.sjds.net/app/provider.php ( 0.19 KB )
  23. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /www/wwwroot/a.sjds.net/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /www/wwwroot/a.sjds.net/app/common.php ( 0.03 KB )
  27. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /www/wwwroot/a.sjds.net/config/app.php ( 0.95 KB )
  30. /www/wwwroot/a.sjds.net/config/cache.php ( 0.78 KB )
  31. /www/wwwroot/a.sjds.net/config/console.php ( 0.23 KB )
  32. /www/wwwroot/a.sjds.net/config/cookie.php ( 0.56 KB )
  33. /www/wwwroot/a.sjds.net/config/database.php ( 2.48 KB )
  34. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /www/wwwroot/a.sjds.net/config/filesystem.php ( 0.61 KB )
  36. /www/wwwroot/a.sjds.net/config/lang.php ( 0.91 KB )
  37. /www/wwwroot/a.sjds.net/config/log.php ( 1.35 KB )
  38. /www/wwwroot/a.sjds.net/config/middleware.php ( 0.19 KB )
  39. /www/wwwroot/a.sjds.net/config/route.php ( 1.89 KB )
  40. /www/wwwroot/a.sjds.net/config/session.php ( 0.57 KB )
  41. /www/wwwroot/a.sjds.net/config/trace.php ( 0.34 KB )
  42. /www/wwwroot/a.sjds.net/config/view.php ( 0.82 KB )
  43. /www/wwwroot/a.sjds.net/app/event.php ( 0.25 KB )
  44. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /www/wwwroot/a.sjds.net/app/service.php ( 0.13 KB )
  46. /www/wwwroot/a.sjds.net/app/AppService.php ( 0.26 KB )
  47. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /www/wwwroot/a.sjds.net/vendor/services.php ( 0.14 KB )
  53. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /www/wwwroot/a.sjds.net/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /www/wwwroot/a.sjds.net/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /www/wwwroot/a.sjds.net/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /www/wwwroot/a.sjds.net/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /www/wwwroot/a.sjds.net/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /www/wwwroot/a.sjds.net/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /www/wwwroot/a.sjds.net/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /www/wwwroot/a.sjds.net/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /www/wwwroot/a.sjds.net/app/Request.php ( 0.09 KB )
  84. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /www/wwwroot/a.sjds.net/app/middleware.php ( 0.25 KB )
  86. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /www/wwwroot/a.sjds.net/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /www/wwwroot/a.sjds.net/route/app.php ( 1.72 KB )
  100. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /www/wwwroot/a.sjds.net/app/controller/Index.php ( 4.81 KB )
  104. /www/wwwroot/a.sjds.net/app/BaseController.php ( 2.05 KB )
  105. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /www/wwwroot/a.sjds.net/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /www/wwwroot/a.sjds.net/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /www/wwwroot/a.sjds.net/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /www/wwwroot/a.sjds.net/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /www/wwwroot/a.sjds.net/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /www/wwwroot/a.sjds.net/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /www/wwwroot/a.sjds.net/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /www/wwwroot/a.sjds.net/runtime/temp/64ad42204038485b18ca907186edb47b.php ( 8.05 KB )
  140. /www/wwwroot/a.sjds.net/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000470s ] mysql:host=172.18.0.4;port=3306;dbname=a_sjds;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000930s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000421s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000354s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000565s ]
  6. SELECT * FROM `set` [ RunTime:0.000287s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000589s ]
  8. SELECT * FROM `article` WHERE `id` = 543014 LIMIT 1 [ RunTime:0.000600s ]
  9. UPDATE `article` SET `lasttime` = 1793966206 WHERE `id` = 543014 [ RunTime:0.002394s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000381s ]
  11. SELECT * FROM `article` WHERE `id` < 543014 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000631s ]
  12. SELECT * FROM `article` WHERE `id` > 543014 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000531s ]
  13. SELECT * FROM `article` WHERE `id` < 543014 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.001079s ]
  14. SELECT * FROM `article` WHERE `id` < 543014 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000700s ]
  15. SELECT * FROM `article` WHERE `id` < 543014 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000883s ]
0.091868s