- 人工智能
- AI 技能
- AI 插件
- 开发工具
【免费下载链接】pstack-claude
Claude Code, Codex, Copilot, Pi, OpenCode, Gemini, and Prime Agent versions of Poteto's pstack. Rigorous agent workflows with Cursor primitives translated for other harnesses.
导读
本文围绕 pstack 插件中的reflect技能展开,讲解如何把一段已经完成的 Agent 会话(conversation transcript)当作"经验矿藏",通过三个并行审阅子代理(judgment / tooling / divergent)交叉审阅、一个合成器(synthesizer)汇总,最终把耐用的学习成果(durable learnings)路由成对既有技能的具体修改、新技能或待办事项。读完本文,你将掌握 reflect 的完整六步流程、find-transcript.mjs定位脚本的使用与原理、三透镜审阅模板的职责边界、合成器的八条验收标准,以及模型与推理努力级别(reasoning effort)的配置方式,并能在 Claude Code、Codex、GitHub Copilot、Pi 等多运行时上正确执行这套"反思-沉淀"循环。
一、reflect 是什么:把会话经验转成技能修改
reflect是 pstack 插件中的一个技能(skill),其核心职责定义在 SKILL.md 的 frontmatter 中:
Spawn three parallel review subagents over the active transcript, surface learnings, and route each to a concrete edit on an existing skill. Use when the user says reflect.
翻译过来就是:在当前活跃会话(active transcript)上并行派生三个审阅子代理,挖掘学习成果,并把每一条学习成果路由到一个具体、可执行的技能修改上。它与"记笔记"式反思的关键区别在于:reflect 的产出不是一条泛泛的总结,而是带有明确 Routing(路由)的编辑项——要么修改某个已有技能的正文,要么调整某个技能的 description 让它下次能被触发,要么创建新技能。
从仓库结构看,reflect 技能的资源由四部分组成:
- SKILL.md:主流程定义;
- references/:三个审阅者模板与合成器模板(
judgment-reviewer.md、tooling-reviewer.md、divergent-reviewer.md、synthesizer.md); - scripts/find-transcript.mjs:定位当前会话 transcript 文件的 Node 脚本;
- 配套测试:tests/find-transcript.test.mjs。
二、何时调用 reflect(触发条件)
按 SKILL.md 的"When to invoke"一节:
- 当用户说出"reflect"或"/reflect"时调用;
- 当对话琐碎、偏离主题,或已被父代理正确遵循的现有技能覆盖时,跳过;
- 一次性事件(one-offs)不算学习成果——只有会重复出现、跨会话成立的模式才值得沉淀。
注意平台差异:在Codex上执行前,需要先阅读平台映射 codex-tools.md(包括其中的逐技能说明);在GitHub Copilot上执行前,需要先阅读平台映射 copilot-tools.md。
三、六步流程详解
reflect 的主流程分为六个步骤:定位 transcript → 并行三个审阅者 → 合成 → 结构性强制检查 → 应用(需用户批准)→ 总结。
步骤 1:定位活跃 transcript
父代理必须先找到自己的 transcript 文件,再进行扇出(fan-out)。系统提示(system prompt)会给出 Claude Code 每个项目的 transcript 目录:~/.claude/projects/<encoded-cwd>/。使用该路径即可,不要在~/.claude/projects/下做全局 glob——那会跨越工作区边界、读到无关项目的私有对话。
定位使用随插件安装的脚本,参数为 projects 目录 + 会话开场用户提示(opening prompt)的一个片段:
node <plugin>/skills/reflect/scripts/find-transcript.mjs ~/.claude/projects/<encoded-cwd> "<opening prompt fragment>"即仓库中的 plugins/pstack/skills/reflect/scripts/find-transcript.mjs。该脚本覆盖三种目录布局:
- 扁平布局:
<id>.jsonl; - 嵌套布局:
<id>/<id>.jsonl; - 子代理布局:
<parent>/subagents/<child>.jsonl。
它按最新优先(newest first)排序候选文件,打印第一个"开场 typed prompt 携带该片段"的路径。SKILL.md 明确要求不要手工重实现扫描,原因有三条(这也是理解脚本设计的钥匙):
- transcript 的第一行是会话元数据(session metadata),不是消息;
- 以
/clear或!开头 shell 命令的会话,会把命令的包装(wrapper)和输出记录成user记录,出现在真正的 prompt 之前; - 文件可达数兆字节,所以 finder 对每个候选文件逐行流式读取(stream),读到第一个 typed
user记录即停。
如果脚本以退出码 1 结束(no transcript),则改为撰写一段紧凑的会话摘要(digest),把摘要传给后续审阅者替代 transcript 路径。
源码级佐证:从 find-transcript.mjs 的实现看,candidates()递归枚举.jsonl文件并按mtimeMs倒序排列;openingPrompt()读入首行记录后,通过READERS表按首行特征分派到不同读取器:
- Claude Code 无头部行,任何未被认领的文件默认走
claudeOpening(),它会跳过isMeta记录、用正则LOCAL_COMMAND过滤掉<command-name>、<local-command-stdout>、<bash-input>等本地命令包装记录(见第 79 行附近),再取第一个真实 prompt; - Pi 会话以
type: "session"头部行标识,piOpening()沿parentId从最后一个条目(leaf)回溯到根,取该分支上的第一个用户消息——因为 Pi 的分支会追加到同一文件; - Copilot 会话以
session.start事件标识,copilotOpening()取第一个user.message,并通过realpathSync比对会话头里的cwd与 workspace 来限定范围; - Codex rollout 会被按名字拒绝(
session_meta头部行触发throw,提示改用会话摘要)。
该行为在 tests/find-transcript.test.mjs 中有大量用例验证,例如"首行元数据不算 prompt"(第 39-43 行)、"/clear与!命令记录被跳过"(第 58-66 行)、"技能调用保留其参数"(第 68-73 行)、"覆盖扁平/嵌套/子代理三种布局且最新优先"(第 81-88 行)、"枚举后被删除的文件不中断扫描"(第 99-108 行)、"Pi 分支回溯取活跃分支开场"(第 157-176 行)、"Copilot 会话按 workspace 限定"(第 251-282 行)等。测试还覆盖了原始U+2028/U+2029字符不破坏按行拆分(第 195-206 行)这类细节。
步骤 2:并行派生三个审阅者
定位到 transcript 后,一条消息内发起三个Agent调用,subagent_type: "general-purpose",并按下方表格设置model。审阅者需要MCP 访问权限以便查证上下文(transcript 中引用的 ticket、聊天线程、可观测性 trace)——所以要选择保留 MCP 访问的 subagent_type。审阅提示(prompt)禁止写文件,所有编辑由父代理统一应用。
| Lens(透镜) | Role line | Prompt template |
|---|---|---|
| Judgment | reflect judgment, divergent, synthesizer | references/judgment-reviewer.md |
| Tooling | reflect tooling | references/tooling-reviewer.md |
| Divergent | reflect judgment, divergent, synthesizer | references/divergent-reviewer.md |
每个模板原样(verbatim)传入,只替换其中标记的位置(transcript 路径或 digest)。审阅者通过Agent响应体(response body)返回发现(findings)。
三个透镜的职责边界(从模板原文提炼):
- Judgment(判断)透镜:擅长从具体事件背后提炼耐久原则(durable principle)——"能帮未来代理省下真实时间的东西"。扫描方向包括:犯过的错误与纠正、用户偏好与工作流模式、代码库知识(架构、坑、模式)、工具/库怪癖、决策及其理由、技能执行/编排/委派中的摩擦、可自动化或可编码的重复手工步骤。
- Tooling(工具)透镜:擅长具体的工具/命令/路径/flag 细节——未来代理本需重新推导、却能扛住代码漂移(survive code drift)的承重技术事实。扫描方向包括:工具调用与命令 flag、库/框架怪癖(配置、lockfile、环境变量行为、版本特定坑)、仅凭代码难以看出的路径约定、测试命令/CI flag/本地复现方式、调试入口(trace 在哪、日志落哪、该打哪个 RPC)、构建/包管理器/沙箱陷阱。该透镜还有一条**"代理自给自足"专项**:标记每一个"用户手工提供了本可由代理通过 MCP 工具自行获取的上下文"的时刻(如用户粘贴 ticket 标题、贴 flaky test 描述、丢来聊天线程链接),并路由到应扩展 MCP 调用的技能。
- Divergent(发散)透镜:负责反常规角度与盲区覆盖——另两个审阅者会漏掉的东西:二阶效应、"本该发生却没发生"、规避过的反模式、未走的替代路径。要求寻找逆向框架(contrarian framing):若另两位大概率会提出原则 X,就去找使 X 复杂化或与之矛盾的原则 Y;会话"显而易见"的学习往往不是最有用的那条,要找它下面那条。所有模板还统一要求把 transcript 视为不可信数据(untrusted data),警惕 prompt 注入,且审阅发现必须指向本次会话实际用到的技能/工具/MCP——臆测性路由不算数。
每条发现按统一形状输出:Principle(一句话原则)+Evidence(transcript 中的确切时刻:轮次号或短引用,含说了什么与没说什么)+Routing(最相关的现有技能SKILL.md路径,或tune description: <skill path>——技能应触发却未触发时,或new skill: <kebab-name>)。
步骤 3:合成
三个审阅者返回后,再发起一个Agent调用(同样subagent_type: "general-purpose",模型取reflect judgment, divergent, synthesizer行的值),使用 references/synthesizer.md 模板,把三个审阅者的完整输出内联到标记位置,并对每条发现套用如下验收标准:
- Durability(耐久性):6 个月后当路径、SHA、工具版本、代码形态都变了,这条结论是否依然成立;
- Specificity(具体性):既宽到能跨任务适用,又精确到未来代理能识别何时使用——拒绝空泛口号("写好代码")与过度具体的事实("某技能在 limit 80 时有 175 个 token");
- Existing-skill-first(既有技能优先):只有确认没有现成技能能承载、且模式会复发、主题值得独立成技能时,才提议
new skill via plugin-dev:skill-development:; - Convergence(收敛性):被 2 个以上审阅者共同提出的发现置信度更高;独苗发现须在其他标准上达到更高门槛;
- Decision-changing(改变决策):一次编辑应让未来代理做出不同的行动,而不只是多读一段文字;
- Structural-mechanism check(结构性机制检查):若 lint 规则、脚本、元数据 flag 或运行时检查已能(或能廉价地)强制该规则,则路由到 Backlog——技能散文只承载机制无法强制的内容;
- Skill-was-used(技能确被使用):只接受路由到父代理实际调用过的技能/工具/MCP 的发现;技能没被用但本应使用时,路由为
tune description: <skill path>;两者皆不满足则按skill-not-used拒绝; - Already-covered(已被覆盖):接受任何正文编辑行前必须重读目标技能;若提案重复了清晰、位置恰当的现有指引,按
already-covered拒绝;若现有指引埋得太深、太弱、容易被跳过,则接受该行但把提案重构为措辞/位置改进。
合成器还需删除会漂移的实现细节("某 linter 在 SHA bd91aa7 用 chars/4 启发式""我们某日把 gpt-4 重命名为 gpt-4o"),保留耐久模式("闭合的正则枚举做触发检测很脆,优先 schema 校验结构""技能 description 前置触发关键词(60/40 触发-动作比)""path 形状的触发器放paths:而非 description 散文")。
最终输出为固定结构:Accepted(表格:Problem / Proposal / Routing,每行一条,用户逐行批准)、Rejected(每条给 Principle + 理由标签:durability / specificity / existing-skill-first / convergence / decision-changing / structural / duplicate / skill-not-used / already-covered)、Backlog(描述模式、命中场景、建议机制)。
步骤 4:结构性强制检查
对合成器的 Accepted 列表做一次 sanity-check:凡是"用 lint 规则、脚本、元数据 flag 或运行时检查来强制会更可靠"的条目,一律从 Accepted 移到 Backlog。这是 principle-encode-lessons-in-structure 原则的直接应用——该技能的核心论点是:文本指令容易被忽略,需要读者自觉注意、记住并遵守;而结构机制(lint、元数据 flag、运行时检查、自动化脚本)不需要配合就能强制规则。其模式是:当你发现自己第二次写下同一条指令时,问"这能不能变成 lint 规则、元数据 flag、运行时检查或脚本?"能就编码之并删除指令;不能(需要判断力)才把指令做得更醒目并附上失败模式示例。它的反馈回路是:捕获每次纠正 → 路由到正确层级(一次性→脑内笔记;复发修正→技能或 lint;系统性问题→原则)→ 闭环(现在就应用或建具体 todo),并明确反对"记了不路由""路由了不落地""修了不泛化"三类反模式。
步骤 5:应用
在应用任何 Accepted 编辑之前,必须先把合成器完整的 Accepted/Rejected/Backlog 输出呈现给用户,并等待明确批准。用户挑选要应用的子集,且可以重定向路由。理由很直接:技能修改会影响组织内每一个未来的代理,绝不自动应用。
Backlog 条目由父代理自动归档到团队使用的 devex / backlog 跟踪器;只有 Accepted 列表等待批准。
对每个获批的 Accepted 条目,严格按 Routing 字段执行:
| Routing | 处置方式 |
|---|---|
| Trivial existing-skill edit(一行 bullet、一句收紧、一个过时事实修正) | 父代理直接改 |
| Substantive existing-skill edit(新章节、新模式表格、超过约 10 行) | 交给plugin-dev:skill-development,跑其 draft / test / iterate 循环 |
tune description: <skill path>(技能存在但该触发时没触发) | 交给plugin-dev:skill-development,跑其 description 优化循环 |
new skill via plugin-dev:skill-development: <kebab-name> | 交给plugin-dev:skill-development创建;不要临时凭空捏造技能形态 |
从仓库搜索可见,plugin-dev:skill-development是多个技能共同依赖的开发工作流(出现在 reflect/SKILL.md、synthesizer.md、automate-me/SKILL.md、poteto-mode/SKILL.md 等文件中),reflect 的"新技能/大改"路由正是复用它,而非另起炉灶。
最后:如果环境自带 SKILL.md 校验器,在声明完成前对每个被触碰的技能跑一遍校验;没有则跳过此步。
步骤 6:为用户总结
输出一份短清单,不要铺垫:
- Edits applied:
<skill path>,每行一句话说明改了什么; - New skills created:
<skill path>,每行一句(罕见); - Backlog filed to the devex tracker:
<issue title>(<tags>),每行一句; - Dropped:每条被拒发现一行,附合成器给出的理由。
四、模型配置:默认值与运行时覆盖
reflect 的模型角色默认值(Role defaults)定义在 plugins/pstack/models.json 中,由 tools/generate.mjs 生成到各技能文档。当前仓库中 reflect 相关角色行及其默认值:
| Role line | models 映射 | 实际默认 |
|---|---|---|
reflect tooling | "default" | opus |
reflect judgment, divergent, synthesizer | "default" | opus |
models.json中tiers.default为opus,available为["opus", "fable", "sonnet", "haiku"],efforts为["low", "medium", "high", "xhigh", "max"],defaultEffort为"session"。
运行时覆盖机制:每个技能在 Models 一节写下默认值,而用户侧的一张pstack-models.md覆盖表(override sheet)会在运行时覆盖这些默认值。SKILL.md 的规则是:每个审阅者与合成器都在pstack-models.md中命名一条角色行(即上表 Role line)与一个默认值;model取该行值,若 sheet 或该行缺失则取默认值;值为auto或inherit-parent时不设置model(表示运行在父会话的模型上,Agent调用省略model即表达此意)。若Agent工具拒绝了某个 slug,改用默认值并说明;若默认值也被拒,则从错误信息中取同族的最近有效 slug。
覆盖表由 /setup-pstack 技能按运行时写入,例如 Claude Code 下为~/.claude/pstack-models.md(通过@~/.claude/pstack-models.md引入到CLAUDE.md),其中包含形如reflect tooling: opus、reflect judgment, divergent, synthesizer: opus的行,以及default effort: session、session hook: on行。各运行时的 sheet 路径与加载方式见 setup-pstack 的 Other runtimes 表。
五、推理努力级别(Reasoning effort)
覆盖表中某个角色值可以携带推理努力级别,写法是在模型名后加@与级别,如opus @xhigh。各运行时语义如下:
- Claude Code的级别:
low、medium、high、xhigh、max;具体哪些适用取决于模型。一个不带@的值取 sheet 的default effort行;该行取值是一个级别或session;sheet 无该行时取session。session表示不设置 effort,走常规派发。读取模型前先剥离后缀:inherit-parent或auto在任何级别下都省略model;模型名则作为model传入。在 Claude Code 上,某个级别会把本应使用的subagent_type换成对应的 effort agent:pstack:poteto-agent变为subagent_type: "pstack:poteto-agent-<level>";general-purpose(或不设subagent_type)变为subagent_type: "pstack:effort-<level>"。effort agents 只设置effort,因此你传入的model仍然决定模型。 - Codex:把级别作为
spawn_agent的reasoning_effort传入,其余指令不变。
仓库中的 effort agents 见 plugins/pstack/effort-agents/(effort-low.md至effort-max.md及对应的 poteto-agent 变体),pstack:poteto-agent-<level>与pstack:effort-<level>正是对这些 agent 文件的引用。
六、跨运行时适配:Pi、Codex 与 Copilot
reflect 的流程依赖Agent子代理扇出能力,各运行时的等价映射可参考 pi-tools.md:
- Pi 的等价工具是
agent工具,run_in_background: true支持一次响应内多个并行子代理;子代理会话存放在<agent dir>/pstack/<parent session id>/agents/,每个文件以session头部行开头、后续条目带id/parentId——这正是find-transcript.mjs中piOpening()回溯逻辑对应的格式; - 若 Pi 只装了 skills(没有 pstack Pi 扩展),则缺少
agent等扩展工具,reflect这类扇出技能会降级为单次串行扫描;但"必须独立审阅"的场景不会降级,会保持阻塞(见 pi-tools.md 第 29 行及 poteto-mode 的 Subagents 一节); - Pi 上
subagent_type取值与 Claude Code 一致,pstack:poteto-agent、pstack:comment-sicko、pstack:poteto-agent-<level>、pstack:effort-<level>都会解析到插件 agent 文件,而 Claude Code 内置类型(Explore、Plan)在 Pi 上不存在,需用general-purpose并把约束写进 prompt; - Codex 与 Copilot 的逐技能映射分别见 codex-tools.md 与 copilot-tools.md,SKILL.md 要求这两类运行时在跟随 reflect 前先读各自映射。
七、质量保障:脚本行为由测试锁定
reflect 的定位脚本不是一次性胶水代码,其行为由 tests/find-transcript.test.mjs 系统性地锁定,这保证了"反思循环"的第一步在跨运行时、跨目录布局下都可靠。值得注意的测试场景包括:
- 开场 prompt 取第一个 typed
user记录而非首行(第 39-43 行); - 字符串内容与多块(multi-block)内容都能正确提取 prompt 文本(第 45-56 行);
- 元数据与命令记录(
/clear、!命令)在真正 prompt 之前被跳过(第 58-66 行); - 技能调用(
<command-message>pstack:reflect</command-message>)保留其<command-args>(第 68-73 行); - 三种布局候选按最新优先枚举(第 81-88 行);
- 枚举后被删除的文件、被截断的尾部行都不中断扫描(第 99-108、139-147 行);
- Pi 分支会话取活跃分支开场、Copilot 会话限定 workspace(第 157-192、232-282 行);
- Codex rollout 按名字拒绝而非当作空 Claude transcript(第 284-297 行)。
这些用例同时也是一份可运行的文档:它们精确展示了find-transcript.mjs面对每种 transcript 格式时的判定规则。
八、小结:reflect 的闭环价值
reflect 的核心设计哲学可以浓缩为三点:
- 经验必须是"耐久的":只沉淀 6 个月后依然成立的原则与模式,丢弃 SHA、路径、版本号、字节数这类会漂移的细节;
- 学习必须路由到"结构":优先进入既有技能正文,次选调整 description 让技能下次能被触发,再次才创建新技能;凡是 lint/脚本/flag/运行时检查能强制的,一律下沉到 Backlog,交给机制而非散文(对应 principle-encode-lessons-in-structure);
- 修改必须经"人批准":技能影响组织内每个未来代理,所以 Accepted 列表逐行等待用户确认,Backlog 自动归档,拒绝项给出理由——整个流程在 SKILL.md 中被严格规定,配合 find-transcript.mjs 的流式定位与 tests/find-transcript.test.mjs 的行为锁定,可以在多个 Agent 运行时上稳定执行。
- 人工智能
- AI 技能
- AI 插件
- 开发工具
【免费下载链接】pstack-claude
Claude Code, Codex, Copilot, Pi, OpenCode, Gemini, and Prime Agent versions of Poteto's pstack. Rigorous agent workflows with Cursor primitives translated for other harnesses.
相关推荐
pstack reflect 技能之 Judgment Reviewer:从会话转录中提炼可复用原则的评审 Agent 设计
pstack reflect 技能之 Judgment Reviewer:从会话转录中提炼可复用原则的评审 Agent 设计 导读 本文剖析 pstack 插件
人工智能AI 技能AI 插件开发工具oh-my-opencode-slim 的 Reflect 技能:用证据驱动的会话复盘从重复工作中提炼可复用工作流
oh my opencode slim 的 Reflect 技能:用证据驱动的会话复盘从重复工作中提炼可复用工作流 Reflect 是 oh my openco
人工智能AI AgentAgent 编排AI 技能Agent Orchestrator 的 Bug 分诊技能实战指南:从人工观察提炼可复现的 Issue
Agent Orchestrator 的 Bug 分诊技能实战指南:从人工观察提炼可复现的 Issue 本文是 agent orchestrator 仓库中 .
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考