{"author":{"id":"4e3fvwoonbfzbvqtdwehr2fzdp","name":"陈成","avatar_url":"https://lh3.googleusercontent.com/a/ACg8ocLP6uaUWVTzl3dUQgZAldOJdTbU_NCUcOxb0Jx1K5CuD97UlDiQ=s96-c","handle":"sorrycc"},"mine":false,"report":{"topic_id":"pl3gagh2wsbh","markdown":"# pstack 仓库与 Lauren 推文分析\n\n分析日期 2026 年 10 月 22 日。分析查阅了 [backnotprop/pstack](https://github.com/backnotprop/pstack)（提交 [`e44668c`](https://github.com/backnotprop/pstack/commit/e44668c2aad92eacf4e84df47984121fefb11b82)）、对照了上游 [cursor/plugins/pstack](https://github.com/cursor/plugins/tree/main/pstack)，用 bird 逐条阅读了 19 条相关推文，还读了 Lauren 的两篇长文《The Complete Guide to pstack》[Pt. 1](https://x.com/poteto/status/2094457600259842065) 和 [Pt. 2](https://x.com/poteto/status/2097732320606507506)，以及最近两周她本人和其他用户关于 pstack 的推文。另外看了她 9 月 21 日发在 X 上的 [38 分钟演讲视频](https://x.com/poteto/status/2102050467505430555)，原本是给 Cursor Compile London 准备的；转写由 Whisper 自动生成，专有名词可能不准。推文日期按 UTC 记。产能、质量数字都是作者自述。\n\n## 先说结论\n\npstack 的核心不是 56 个技能，而是一条顺序：先让代理能自己跑起并操作你的应用（验证技能 + feature map），再用 `/poteto-mode` 让它按任务类型走固定流程，最后才谈并行和自动合并。没有第一步，后面的多代理流程只会更贵，不会更可信。Lauren 自己在 Pt. 1 里也是这么排的。她在 9 月的演讲里分得更清楚：验证管\"对不对\"，pstack 管\"好不好\"（性能、代码质量），两样都有才够。那场演讲标题是 2,500 个 PR，但 pstack 只讲了一小段，她自己说\"今天不多讲这个插件\"，产能主要归到验证、给代理设计的架构和自动派活的外循环上。\n\n对 Claude Code 用户，有两件需要注意的事。一是默认配置里的 Grok 模型在 Claude Code 里会被映射成\"沿用父模型\"，`/arena`、`/architect`、`/interrogate` 这些靠\"不同模型家族互相评审\"的流程会退化成同一家族自评。二是 `/poteto-mode` 本身约 3,600 个英文词，每个 `poteto-agent` 子代理都被要求完整读一遍，子代理越多，固定上下文成本线性增加。值得用，但最好挑着用。\n\n## 来源链：谁在维护什么\n\n```\nLauren Tan（@poteto）\n  └─ cursor/plugins/pstack        原始版本，Cursor 插件，0.15.30\n       └─ backnotprop/pstack      Michael Ramos 的镜像，0.15.28\n            · upstream 分支：上游原样\n            · main 分支：upstream + 通用化改写\n            · 安装：npx skills add backnotprop/pstack\n```\n\nLauren 以前在 React 团队，后来去 Cursor 做 Agents Window 的性能。Cursor 现在并入了 SpaceX AI，她在那边做 Grok Bot。默认配置混用 Claude 和 Grok 就是这个原因：Grok 是她公司自己的模型，这个组合首先反映她的工作环境，不一定适合其他宿主。\n\n镜像的价值是让 Claude Code、Codex、Pi 等宿主能直接装。代价是多一层同步延迟，以及改写本身可能偏离原意。[MIRROR.md](https://github.com/backnotprop/pstack/blob/main/MIRROR.md) 写明了同步方法，冲突时\"保留 Cursor 的新含义，再套用通用措辞\"。Lauren 在推文里说通过 Grok Bot 或 Cursor 安装会自动更新，[镜像则要等维护者手动同步](https://x.com/poteto/status/2110047891201114165)。\n\n更新很快。10 月 4 日发 0.15.9，10 月 22 日上游已到 0.15.30，18 天二十来个补丁版本。这对试用是好事，对把它固化进团队流程的人是个提醒：技能文本随时在变，评测结果也会跟着变。\n\n## 仓库结构\n\n仓库包含56 个技能（其中 24 个 `principle-*`），`poteto-mode` 下 23 个 playbook，两个代理定义（`poteto-agent`、`comment-sicko`），一套只适用于 Cursor 的 Benny 自动化，`docs/guide/` 下 10 章指南，MIT 许可。\n\n各部分的量级大致如下：\n\n| 部分 | 规模 | 什么时候进上下文 |\n| --- | --- | --- |\n| `poteto-mode/SKILL.md` | 约 3,600 词 | 每次 `/poteto-mode`；每个 `poteto-agent` 子代理也要读 |\n| 单个 playbook | 300 到 2,700 词（bug-fix 368，orchestrate 2,692） | 按任务类型选中后 |\n| 原则 | 24 个，合计约 5,100 词 | 主文件只放索引，要求\"应用哪个就完整读哪个\" |\n| 全部 SKILL.md + playbook | 约 49,500 词 | 不会一次全读 |\n\n`poteto-mode` 按任务类型路由到不同的 playbook。几条值得注意的硬规则：要问用户\"选哪个方案\"之前，先判断这个问题能不能靠跑一下得到答案，能的话就走 Prototype playbook 去试，不要问人；任何代码先说出数据结构；跨函数边界的改动先走 `/architect`；提交前过 `deslop`，review 前过 `/no-comments`；答复里要点名哪个原则改变了哪个决定，并且只能点名本会话里真读过的原则。最后一条是很实用的防糊弄设计。\n\n## 两篇长文中的方法\n\nLauren 的两篇长文详细介绍了具体方法，也说明了 pstack 想解决什么。\n\n**Pt. 1：验证是一切的前提（8 月 31 日）。** 她把验证技能当作\"关键基础设施\"，甚至建议给它排 oncall。具体做法有三点。\n\n第一，把操作应用做成一个小 CLI，而不是让代理每次临时写脚本去点按钮。这对应原则 [Build the Lever](https://github.com/backnotprop/pstack/blob/main/skills/principle-build-the-lever/SKILL.md)。她列了这个 CLI 应有的特征：可组合、有破坏性副作用的命令带 `--dry-run`、用子命令逐步暴露功能、错误信息告诉代理该怎么做、`--help` 详细、输出 JSON。\n\n第二，feature map。每个功能写清楚\"用户从哪进、怎么用、用 CLI 怎么驱动、有哪些坑\"。她称之为\"物化的记忆\"：代码是团队决策的投影，feature map 是它的压缩版，放在技能里所有人共享。她公开了一个[虚构应用 Atlas 的示例](https://github.com/poteto/verification-skill-example)。\n\n第三，技术栈会影响代理生产力。Electron 和 Web 有 CDP，iOS 有模拟器；运行时越难调试、越难控制，代理越难用。她甚至说值得为此自建调试工具或换技术栈。这个判断很激进，但逻辑一致。\n\n**Pt. 2：用代码做计划（9 月 9 日）。** 主题是\"监督比你聪明的人\"。\n\n- 先对齐意图。让代理\"用自己的话复述问题\"（后来做成 `/in-your-own-words`），既能早发现误解，也避免自己的假设把代理带偏。\n- 补上下文。`/teach` 调 `/how`（追运行机制）和 `/why`（从 git、PR 评论、Linear、Notion、Slack、Sentry 等查动机），`/recall` 从历史会话捞上下文。\n- 计划靠原型而不是长文档。她明确反对对抽象计划做对抗式评审，理由是代理会臆想风险、为不会发生的边界情况设计防护。替代做法是 Prototype playbook 做两三个可切换的变体，用验证技能截图测量，再由 `/architect` 让多个模型家族各出一版类型签名级的设计，交叉评判后再实现，设计错了就推倒。\n- 真要计划文档，就用 multi-phase-plan playbook，每一项都以\"实际运行验证过\"为完成标准，再用 `check-plan.mjs` 检查格式。大项目的计划临时提交进仓库，做完就删。\n\n这两篇解释了 README 里\"没有 planning 技能\"的说法：不是不计划，是把计划换成可运行的东西。\n\n## 在 Claude Code 里实际会发生什么\n\n[`docs/harness/claude-code.md`](https://github.com/backnotprop/pstack/blob/main/docs/harness/claude-code.md) 是镜像加的映射表。读完后几处影响比较大。\n\n**多模型评审会退化。** 默认角色配置是代码类任务用 `grok-4.7-xhigh-fast`，判断和写作用 `claude-opus-5-5-xhigh`，arena、architect、interrogate 的评审团各放一个 Claude 和一个 Grok。映射表规定非 Claude 模型在 Claude Code 里\"省略 `model`，沿用会话模型\"，默认的 Grok 直接写成 `inherit-parent`。结果是评审团里两个席位跑同一家族。`poteto-mode` 自己写着\"第二意见是同一提示换一个模型，一致才是强信号\"，这个前提在纯 Claude 环境里打了折扣。要找回多样性，得让子代理调用外部 CLI（Codex、Gemini 等），pstack 本身不提供。\n\n**cloud agent 变成 worktree。** 映射表把 `environment: \"cloud\"` 换成 `isolation: \"worktree\"`。而 Lauren 在 Pt. 1 里专门劝人别用 worktree 做并行，说它吃磁盘和机器资源，本地大概十个就到头。她宣传的\"每个代理一台机器、录屏截图、半夜自己合并\"依赖 Cursor 云代理，Claude Code 本地跑拿不到这部分。\n\n**技能互相调用靠读文件。** 因为 55 个技能都禁止模型自动调用，Claude Code 的 Skill 工具会拒绝它们，映射表让代理直接 `Read` 对应的 `SKILL.md`。能用，但比原生调用多一步，也多吃上下文。\n\n**Cursor 专有步骤会跳过。** Automations、Bugbot、云代理面板都会被替换成一行 \"Skipped in Claude Code\"。`/maintain-verification-skill` 作为每日自动任务这件事，在 Claude Code 里要自己用 cron 或别的调度去补。\n\n**外循环不在 pstack 里。** 演讲里她讲了另一层：Grok Bot 接 Slack、Datadog、Sentry、PlanetScale，用 routines 订阅 Slack 线程和 Sentry 告警，自动触发云代理去复现 bug、开 PR，再配合 Cursor automations 和 SDK 自建的 bot。这一层 pstack 不提供，Claude Code 也没有现成对应物，要自己搭。\n\n## 成本：已知数字和一个独立样本\n\n成本来源有两层。一层是固定上下文，主会话读 `poteto-mode` 加若干原则和 playbook，每个 `poteto-agent` 子代理再读一遍 `poteto-mode`。另一层是子代理数量。Lauren 说[成本主要来自大量子代理](https://x.com/poteto/status/2110498629307990461)，建议跑 `/setup-pstack` 选预算，并在会话开头告诉代理别开大规模 swarm。预算档位只调推理强度（max / xhigh / high / medium），不减少子代理个数。\n\n我只找到一个第三方的量化对比。用户 @dwkim601 [用 claude-sonnet-5-5 跑了 5 个带隐藏测试的小任务](https://x.com/dwkim601/status/2113002041991926194)，不加 pstack 和加 `poteto-mode` 都是 15/15 通过，后者花费 3.455 美元，前者 2.435 美元，约 1.4 倍。他自己也说任务太简单，说明不了难题上的效果。这个样本很小，但方向和直觉一致：简单任务上 pstack 主要是额外成本，收益要到需要复现、验证、设计取舍的任务上才可能体现。Lauren 说她[对自己的技能做评测](https://x.com/poteto/status/2109912648116826250)，还说过一次[精简 10% 且行为无损](https://x.com/poteto/status/2109116030761230571)，但没有公开评测数据。\n\n另外两条用户反馈指向同一个外部风险：Cursor 订阅方案调整后，有用户说[用不了 Opus 5.5](https://x.com/antoniolorusso/status/2112973440923693268)，也有人问[第三方模型受限后 pstack 是否会调整](https://x.com/Zeez0321/status/2113065638755541362)。pstack 的默认配置绑定了具体模型名，宿主的模型政策一变，效果就会变。\n\n## 推文里的工程判断\n\nLauren 的推文还涉及以下工程判断。\n\n**把反复纠正变成结构。** [四级顺序](https://x.com/poteto/status/2089067865098113024)：用架构或数据结构根除 \u003e lint 或测试让 CI 拦截 \u003e 技能或规则 \u003e 人工 review。她把第四级标成\"ngmi\"。`/correct` 回看代理反复犯的错，用架构、类型和检查去修。她给过一段[可以直接用的提示词](https://x.com/poteto/status/2106542593656111276)，要求代理翻历史提交找常见陷阱，用原型回答自己的开放问题，带着数据回来给人审。\n\n演讲里最具体的例子是 Dune，Grok Bot 的客户端框架。出发点是代理爱走捷径，那就让捷径本身是正确的路；代价是人写起来很难受，好处是上下文很少的代理，或者设计师、PM 驾驶的代理，默认也能写对。三条原则：删掉已有技术债；每件事只留一种写法，用 CI 和 lint 引着代理走；看到坏模式先写 lint 规则止血，之后再让代理清理，让代码库一直处在\"代理照抄也没问题\"的状态。一个落地例子是用导入依赖图强制隔开 Electron 主进程和渲染进程，因为 Cursor Agents Window 出过慢代码被误引入渲染线程的问题，而渲染线程每帧只有 16ms（60fps）或 8ms（120fps）。她强调重点不在 Dune 本身，而在于把原本散在 code review 评论里的经验写进框架。\n\n**删注释。** 她主张[禁止并删除大部分代码注释](https://x.com/poteto/status/2110149626133438732)，理由是代理爱模仿现有代码，一条解释临时绕过方案的注释会被当成模板扩散。演讲里给了起因：在 Cursor 代码库里，代理会拿周围的注释当理由，不去解决根本问题，贴个临时补丁了事。所以 Dune 直接禁止写注释。`/no-comments` 会保留解释浏览器怪癖这类必要注释，其余尝试从根上解决。这个立场有争议，她在回复里承认[不是非黑即白](https://x.com/poteto/status/2110165682302447699)。\n\n**验证是近似。** [验证推文](https://x.com/poteto/status/2109436202554372476)说得很克制：验证产物要证明工作正确、符合意图、比读整个 PR 更好审；同时承认不是所有领域都容易验证，验证也会错，\"和相信人类真的跑过自己写的代码没什么区别\"。\n\n**形式化验证还在 beta。** [`/create-formal-verification-skill`](https://github.com/backnotprop/pstack/blob/main/skills/create-formal-verification-skill/SKILL.md) 只有 41 行。关键要求是先挑单元测试够不着、出错代价高的性质；事件顺序类问题默认用 TLA+；没有现成验证器的语言要明说，并改用生成输入测真实代码；每个性质都要在一个故意改坏的版本上失败过，证明检查本身有效。上游在 10 月 19 日补了 TLA+ 默认值和无验证器时的回退，又加了 `maintain-formal-verification-skill`，说明这块还在快速调整。\n\n**产能数字一直在涨，而且口径不统一。** 8 月 19 日说[上个月 1,000 个 PR](https://x.com/poteto/status/2090141955695198633)，8 月 31 日 Pt. 1 说\"每月 2,000 个\"，9 月 21 日说[上个月 2,500 个](https://x.com/poteto/status/2102050467505430555)。她在 Pt. 1 里也说过 PR 数曾是她眼里的虚荣指标。这些数字依赖 Grok Bot 团队的代码库、Cursor 云代理、接着 Slack 和 Sentry 自动派活的外循环，以及她本人的判断力，不能当作安装 pstack 的预期收益。\n\n## 社区反应\n\n最近两周的讨论以称赞为主，Taylor Otwell 说\"pstack is the new solid\"，Uncle Bob 说原则里有\"非常重要的智慧\"。也有人把它移植到 [DeepSeek Harness](https://x.com/monkeyin_92/status/2113105674557411541) 和 Codex。批评集中在细节，比如有设计师[不满 `/unslop` 要求把弯引号换成直引号](https://x.com/dvsch/status/2113130048668463260)。还有用户说 Grok Bot 加 Cursor 云代理的组合[多数时候很慢](https://x.com/chrisdrit/status/2113060804018974833)，需要人在环路里时他宁可开 CLI 自己引导，方向明确后再交给云代理和 pstack。这和 Lauren 自己说的\"[开头给足方向，之后放手](https://x.com/poteto/status/2107567417316831523)\"其实是一回事。\n\n## 怎么用\n\n1. **先不装全套。** Lauren 自己建议[从零技能开始观察失败模式](https://x.com/poteto/status/2098637947021205856)。镜像 README 列了 16 个可以单独装的技能，比如 `correct`、`in-your-own-words`、`arena`、`unslop`。\n2. **第一件正事是验证技能。** 跑 `/create-verification-skill`，重点打磨它生成的 CLI，再让 feature map 覆盖核心路径。在 Claude Code 里，每日维护要自己排程。\n3. **`/poteto-mode` 只给难任务。** 复现型 bug、跨模块设计、性能问题值得用；改文案、小修小补不值得。开头加一句\"不要开大规模子代理\"。\n4. **在 Claude Code 里补模型多样性。** 如果在意 arena、architect、interrogate 的评审质量，考虑让其中一个席位调用外部模型 CLI，否则要接受它们是同一家族的自评。\n5. **固定版本。** 镜像和上游都改得快。团队使用时记下提交号，升级前用自己的几个代表任务对比一下。\n\n## 我（AI）的判断\n\npstack 最能直接带走的是三样东西：验证 CLI 加 feature map 这套做法、\"能跑出答案的问题不要问人\"这条路由规则、以及把反复纠正沉淀成架构和 lint 的习惯。这三样不依赖 Cursor，也不需要装全套技能。\n\n它的多代理、多模型部分是为 Cursor 云代理加 Claude/Grok 混合模型设计的。离开这个环境，尤其在纯 Claude Code 本地跑时，并行能力和评审多样性都会缩水，成本却不会等比例下降。唯一的公开第三方对比显示简单任务上贵 40% 且没有收益，难任务上的效果目前只有作者自述。\n\n所以我会先花一两天把一个核心功能做成代理能自己跑通、能截图取证的路径，再挑一个反复出现的代理错误用 `/correct` 试一次。这两步做完，就能看出整套 pstack 在自己的代码库里值不值。\n","html":"\u003c!doctype html\u003e\n\u003chtml lang=\"zh-CN\" class=\"js\"\u003e\n\u003chead\u003e\n\u003cmeta charset=\"utf-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\u003e\n\u003ctitle\u003epstack 仓库与 Lauren 推文分析\u003c/title\u003e\n\u003clink rel=\"preconnect\" href=\"https://fonts.googleapis.com\"\u003e\n\u003clink rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin\u003e\n\u003clink href=\"https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@600;900\u0026family=JetBrains+Mono:wght@400;600\u0026display=swap\" rel=\"stylesheet\"\u003e\n\u003cstyle\u003e\n:root{\n  --paper:#f5f1ea; --card:#fffdf9; --ink:#1c1a17; --ink2:#4a463f; --muted:#857e73; --line:#e3dccf;\n  --accent:#c2410c; --accent-soft:#fbe7dc; --teal:#0f766e; --teal-soft:#dcefeb; --warn:#a16207; --warn-soft:#fbf1d6;\n  --bar:#c2410c; --bar2:#d9cfc0; --grid:#e8e1d5;\n  --serif:\"Noto Serif SC\",\"Songti SC\",serif;\n  --sans:-apple-system,BlinkMacSystemFont,\"PingFang SC\",\"Hiragino Sans GB\",\"Microsoft YaHei\",sans-serif;\n  --mono:\"JetBrains Mono\",ui-monospace,SFMono-Regular,Menlo,monospace;\n}\n@media (prefers-color-scheme:dark){:root{\n  --paper:#15130f; --card:#1e1b16; --ink:#efe9df; --ink2:#c9c1b4; --muted:#8f877a; --line:#353027;\n  --accent:#f0743a; --accent-soft:#3a2216; --teal:#4cc2b2; --teal-soft:#17302c; --warn:#e3b341; --warn-soft:#332910;\n  --bar:#f0743a; --bar2:#4a4338; --grid:#2c2821;\n}}\n*{box-sizing:border-box}\nhtml{scroll-behavior:smooth;background:var(--paper)}\nbody{margin:0;color:var(--ink);background:var(--paper);font:16px/1.85 var(--sans);-webkit-font-smoothing:antialiased}\na{color:var(--accent);text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--accent) 35%,transparent)}\na:hover{border-bottom-color:var(--accent)}\ncode{font:.86em var(--mono);background:color-mix(in srgb,var(--ink) 7%,transparent);padding:.1em .38em;border-radius:5px;overflow-wrap:anywhere}\np{margin:.8em 0}\nstrong{font-weight:650}\n\n#progress{position:fixed;top:0;left:0;height:3px;width:0;background:var(--accent);z-index:50}\n\n/* layout */\n.wrap{max-width:1180px;margin:0 auto;padding:0 24px;display:grid;grid-template-columns:200px minmax(0,1fr);gap:56px}\nnav.toc{position:sticky;top:32px;align-self:start;padding-top:48px;font-size:.84rem}\nnav.toc .lbl{font:600 .7rem var(--mono);letter-spacing:.14em;color:var(--muted);text-transform:uppercase;margin-bottom:10px}\nnav.toc a{display:block;border:0;color:var(--muted);padding:5px 0 5px 12px;border-left:2px solid var(--line);line-height:1.4}\nnav.toc a.on{color:var(--ink);border-left-color:var(--accent)}\nmain{min-width:0;padding-bottom:120px}\n@media (max-width:920px){.wrap{grid-template-columns:minmax(0,1fr)}nav.toc{display:none}}\n\n/* hero */\nheader.hero{padding:72px 0 40px;border-bottom:1px solid var(--line);margin-bottom:28px}\n.kicker{font:600 .75rem var(--mono);letter-spacing:.16em;color:var(--accent);text-transform:uppercase}\nh1{font:900 clamp(2.2rem,5vw,3.6rem)/1.15 var(--serif);margin:14px 0 18px;letter-spacing:-.01em}\nh1 em{font-style:normal;color:var(--accent)}\n.lede{font-size:1.12rem;color:var(--ink2);max-width:40em}\n.chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:22px}\n.chip{font:.78rem var(--mono);padding:4px 10px;border:1px solid var(--line);border-radius:999px;color:var(--ink2);background:var(--card)}\n.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1px;background:var(--line);border:1px solid var(--line);border-radius:14px;overflow:hidden;margin-top:36px}\n.stat{background:var(--card);padding:18px 18px 16px;min-width:0}\n.stat b{display:block;font:900 2rem/1.1 var(--serif);color:var(--ink)}\n.stat b small{font-size:.9rem;color:var(--muted);font-weight:600}\n.stat span{font-size:.8rem;color:var(--muted);line-height:1.4;display:block;margin-top:6px}\n\n/* sections */\nsection{padding:44px 0 8px;scroll-margin-top:16px}\nh2{font:900 1.75rem/1.3 var(--serif);margin:0 0 6px;display:flex;align-items:baseline;gap:14px}\nh2 .n{font:600 .8rem var(--mono);color:var(--accent);letter-spacing:.1em}\n.sub{color:var(--muted);margin:0 0 22px;font-size:.95rem}\nh3{font:600 1.1rem/1.4 var(--serif);margin:28px 0 8px}\n.card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:22px 24px;min-width:0}\n.grid2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}\n.grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}\n@media (max-width:720px){.grid2,.grid3{grid-template-columns:minmax(0,1fr)}}\n.tag{display:inline-block;font:600 .7rem var(--mono);letter-spacing:.08em;padding:2px 8px;border-radius:6px;text-transform:uppercase}\n.tag.o{background:var(--accent-soft);color:var(--accent)}\n.tag.t{background:var(--teal-soft);color:var(--teal)}\n.tag.w{background:var(--warn-soft);color:var(--warn)}\n.note{font-size:.88rem;color:var(--muted)}\nfigure{margin:22px 0;min-width:0}\nfigcaption{font-size:.82rem;color:var(--muted);margin-top:10px}\nsvg{max-width:100%;height:auto;display:block}\nsvg text{font-family:var(--sans)}\n.callout{border-left:3px solid var(--accent);background:var(--accent-soft);padding:14px 18px;border-radius:0 10px 10px 0;margin:18px 0}\n.callout.t{border-color:var(--teal);background:var(--teal-soft)}\n\n/* order flow */\n.flow{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;margin:8px 0 18px;counter-reset:s}\n.step{position:relative;padding:22px 22px 20px;background:var(--card);border:1px solid var(--line);min-width:0}\n.step:first-child{border-radius:14px 0 0 14px;border-top:4px solid var(--accent)}\n.step:nth-child(2){border-left:0;border-top:4px solid color-mix(in srgb,var(--accent) 60%,var(--line))}\n.step:last-child{border-left:0;border-radius:0 14px 14px 0;border-top:4px solid var(--line)}\n.step .num{font:900 2.4rem/1 var(--serif);color:color-mix(in srgb,var(--accent) 30%,transparent)}\n.step h4{margin:8px 0 6px;font:600 1.05rem var(--serif)}\n.step p{margin:0;font-size:.9rem;color:var(--ink2)}\n.step .q{margin-top:12px;font:600 .78rem var(--mono);color:var(--accent)}\n.step:not(:last-child)::after{content:\"→\";position:absolute;right:-13px;top:50%;transform:translateY(-50%);width:26px;height:26px;border-radius:50%;background:var(--paper);border:1px solid var(--line);display:grid;place-items:center;font-size:.85rem;color:var(--muted);z-index:2;line-height:24px;text-align:center}\n@media (max-width:720px){.flow{grid-template-columns:minmax(0,1fr)}.step{border-radius:0!important;border-left:1px solid var(--line)!important}.step:first-child{border-radius:14px 14px 0 0!important}.step:last-child{border-radius:0 0 14px 14px!important}.step:not(:last-child)::after{content:\"↓\";right:auto;left:50%;top:auto;bottom:-13px;transform:translateX(-50%)}}\n\n/* compare table */\n.cmp{width:100%;border-collapse:separate;border-spacing:0;font-size:.9rem}\n.cmpwrap{overflow-x:auto;border:1px solid var(--line);border-radius:14px;background:var(--card)}\n.cmp th,.cmp td{padding:14px 16px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}\n.cmp tr:last-child td{border-bottom:0}\n.cmp thead th{font:600 .74rem var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--muted);background:color-mix(in srgb,var(--ink) 3%,transparent)}\n.cmp td:first-child{font-weight:650;white-space:nowrap}\n.cmp .arrow{color:var(--muted);text-align:center;width:28px;padding-left:0;padding-right:0}\n.cmp .lose{color:var(--warn)}\n\n/* ladder */\n.ladder{display:grid;gap:8px}\n.rung{display:grid;grid-template-columns:44px minmax(0,1fr) auto;align-items:center;gap:14px;padding:14px 18px;border-radius:12px;border:1px solid var(--line);background:var(--card)}\n.rung .lv{font:900 1.5rem var(--serif);color:var(--accent)}\n.rung .t{font-weight:650}\n.rung .d{font-size:.84rem;color:var(--muted)}\n.meter{width:120px;height:8px;border-radius:4px;background:var(--grid);overflow:hidden}\n.meter i{display:block;height:100%;background:var(--accent);border-radius:4px}\n.rung.ngmi{background:transparent;border-style:dashed}\n.rung.ngmi .lv{color:var(--muted)}\n@media (max-width:560px){.meter{width:60px}}\n\n/* quotes */\n.quote{font:600 1.05rem/1.6 var(--serif)}\n.who{font-size:.8rem;color:var(--muted);margin-top:8px}\n\n/* howto */\nol.howto{list-style:none;padding:0;margin:0;display:grid;gap:12px;counter-reset:h}\nol.howto li{counter-increment:h;display:grid;grid-template-columns:52px minmax(0,1fr);gap:16px;background:var(--card);border:1px solid var(--line);border-radius:14px;padding:18px 20px}\nol.howto li::before{content:counter(h,decimal-leading-zero);font:900 1.6rem/1 var(--serif);color:var(--accent);padding-top:4px}\nol.howto h4{margin:0 0 4px;font:600 1.02rem var(--serif)}\nol.howto p{margin:0;font-size:.92rem;color:var(--ink2)}\n\n.take{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;margin:18px 0}\n.take .card{border-top:4px solid var(--accent)}\n.take .card b{font:900 2rem var(--serif);color:color-mix(in srgb,var(--accent) 40%,transparent);display:block;line-height:1}\n@media (max-width:720px){.take{grid-template-columns:minmax(0,1fr)}}\n.verdict{margin-top:24px;padding:28px 30px;border-radius:16px;background:var(--ink);color:var(--paper)}\n.verdict p{margin:0;font:600 1.12rem/1.75 var(--serif)}\n.verdict .k{font:600 .72rem var(--mono);letter-spacing:.14em;color:var(--accent);text-transform:uppercase;margin-bottom:10px}\n\n/* chart hover */\n.hov{cursor:default}\n.hov:hover rect.m,.hov:hover circle.m{filter:brightness(1.12)}\n#tip{position:fixed;pointer-events:none;background:var(--ink);color:var(--paper);font-size:.8rem;padding:6px 10px;border-radius:8px;opacity:0;transition:opacity .12s;z-index:60;max-width:260px;line-height:1.5}\nfooter{border-top:1px solid var(--line);padding:28px 0;color:var(--muted);font-size:.82rem}\n\n/* motion */\n.js .reveal{opacity:0;transform:translateY(18px);transition:opacity .7s ease var(--d,0s),transform .8s cubic-bezier(.2,.7,.2,1) var(--d,0s)}\n.js .reveal.in{opacity:1;transform:none}\n.js .gx,.js .gy{transform-box:fill-box;transition:transform .9s cubic-bezier(.2,.8,.2,1) var(--d,0s)}\n.js .gx{transform-origin:left center;transform:scaleX(0)}\n.js .gy{transform-origin:center bottom;transform:scaleY(0)}\n.js .in .gx,.js .in .gy{transform:none}\n.js .lbl-fade{opacity:0;transition:opacity .4s ease var(--d,0s)}\n.js .in .lbl-fade{opacity:1}\n.js .draw{stroke-dasharray:1;stroke-dashoffset:1;transition:stroke-dashoffset 1.4s cubic-bezier(.4,0,.2,1) .2s}\n.js .in .draw{stroke-dashoffset:0}\n.js .meter i{transform-origin:left;transform:scaleX(0);transition:transform 1s cubic-bezier(.2,.8,.2,1) var(--d,.15s)}\n.js .in .meter i{transform:none}\n.ants{animation:ants 1.2s linear infinite}\n@keyframes ants{to{stroke-dashoffset:-20}}\n.pulse{transform-box:fill-box;transform-origin:center;animation:pulse 2.4s ease-in-out infinite}\n@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.15)}}\n.js header.hero\u003e*{animation:rise .8s cubic-bezier(.2,.7,.2,1) both}\n.js header.hero\u003e*:nth-child(2){animation-delay:.08s}.js header.hero\u003e*:nth-child(3){animation-delay:.16s}.js header.hero\u003e*:nth-child(4){animation-delay:.24s}.js header.hero\u003e*:nth-child(5){animation-delay:.32s}.js header.hero\u003e*:nth-child(6){animation-delay:.4s}\n@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}\n.card,.rung,ol.howto li{transition:transform .25s ease,border-color .25s ease,box-shadow .25s ease}\n.card:hover,ol.howto li:hover{transform:translateY(-2px);border-color:color-mix(in srgb,var(--accent) 40%,var(--line));box-shadow:0 10px 30px -18px color-mix(in srgb,var(--ink) 50%,transparent)}\n.rung:hover{transform:translateX(4px)}\nnav.toc a{transition:color .2s,border-color .2s}\n@media (prefers-reduced-motion:reduce){\n  .js .reveal,.js .gx,.js .gy,.js .lbl-fade,.js .draw,.js .meter i{opacity:1!important;transform:none!important;stroke-dashoffset:0!important;transition:none!important}\n  .ants,.pulse,.js header.hero\u003e*{animation:none!important}\n  .card:hover,.rung:hover,ol.howto li:hover{transform:none}\n}\n@media print{.js .reveal,.js .gx,.js .gy,.js .lbl-fade,.js .meter i{opacity:1!important;transform:none!important}.js .draw{stroke-dashoffset:0!important}}\n\u003c/style\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003cdiv id=\"progress\"\u003e\u003c/div\u003e\n\u003cdiv id=\"tip\"\u003e\u003c/div\u003e\n\u003cdiv class=\"wrap\"\u003e\n\u003cnav class=\"toc\" aria-label=\"目录\"\u003e\n  \u003cdiv class=\"lbl\"\u003e目录\u003c/div\u003e\n  \u003ca href=\"#s1\"\u003e先说结论\u003c/a\u003e\n  \u003ca href=\"#s2\"\u003e来源链\u003c/a\u003e\n  \u003ca href=\"#s3\"\u003e仓库结构\u003c/a\u003e\n  \u003ca href=\"#s4\"\u003e两篇长文的方法\u003c/a\u003e\n  \u003ca href=\"#s5\"\u003e在 Claude Code 里\u003c/a\u003e\n  \u003ca href=\"#s6\"\u003e成本\u003c/a\u003e\n  \u003ca href=\"#s7\"\u003e工程判断\u003c/a\u003e\n  \u003ca href=\"#s8\"\u003e社区反应\u003c/a\u003e\n  \u003ca href=\"#s9\"\u003e怎么用\u003c/a\u003e\n  \u003ca href=\"#s10\"\u003e我的判断\u003c/a\u003e\n\u003c/nav\u003e\n\n\u003cmain\u003e\n\u003cheader class=\"hero\"\u003e\n  \u003cdiv class=\"kicker\"\u003eRepo teardown · 2026-10-22\u003c/div\u003e\n  \u003ch1\u003epstack 仓库与\u003cbr\u003e\u003cem\u003eLauren\u003c/em\u003e 推文分析\u003c/h1\u003e\n  \u003cp class=\"lede\"\u003epstack 的核心不是 56 个技能，而是一条顺序：先让代理自己跑起并操作你的应用，再按任务类型走固定流程，最后才谈并行和自动合并。\u003c/p\u003e\n  \u003cdiv class=\"chips\"\u003e\n    \u003cspan class=\"chip\"\u003e\u003ca href=\"https://github.com/backnotprop/pstack\"\u003ebacknotprop/pstack\u003c/a\u003e @ \u003ca href=\"https://github.com/backnotprop/pstack/commit/e44668c2aad92eacf4e84df47984121fefb11b82\"\u003ee44668c\u003c/a\u003e\u003c/span\u003e\n    \u003cspan class=\"chip\"\u003e上游 \u003ca href=\"https://github.com/cursor/plugins/tree/main/pstack\"\u003ecursor/plugins/pstack\u003c/a\u003e\u003c/span\u003e\n    \u003cspan class=\"chip\"\u003e19 条推文\u003c/span\u003e\n    \u003cspan class=\"chip\"\u003e长文 \u003ca href=\"https://x.com/poteto/status/2094457600259842065\"\u003ePt. 1\u003c/a\u003e / \u003ca href=\"https://x.com/poteto/status/2097732320606507506\"\u003ePt. 2\u003c/a\u003e\u003c/span\u003e\n    \u003cspan class=\"chip\"\u003e\u003ca href=\"https://x.com/poteto/status/2102050467505430555\"\u003e38 分钟演讲\u003c/a\u003e\u003c/span\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"stats\"\u003e\n    \u003cdiv class=\"stat\"\u003e\u003cb\u003e56\u003c/b\u003e\u003cspan\u003e技能，其中 24 个 \u003ccode\u003eprinciple-*\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\n    \u003cdiv class=\"stat\"\u003e\u003cb\u003e23\u003c/b\u003e\u003cspan\u003e\u003ccode\u003epoteto-mode\u003c/code\u003e 下的 playbook\u003c/span\u003e\u003c/div\u003e\n    \u003cdiv class=\"stat\"\u003e\u003cb\u003e3,600\u003csmall\u003e 词\u003c/small\u003e\u003c/b\u003e\u003cspan\u003e每个子代理都要读一遍的 \u003ccode\u003epoteto-mode\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\n    \u003cdiv class=\"stat\"\u003e\u003cb\u003e~21\u003c/b\u003e\u003cspan\u003e18 天内的补丁版本（0.15.9 → 0.15.30）\u003c/span\u003e\u003c/div\u003e\n    \u003cdiv class=\"stat\"\u003e\u003cb\u003e1.4×\u003c/b\u003e\u003cspan\u003e唯一第三方样本里的成本倍数，通过率相同\u003c/span\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  \u003cp class=\"note\" style=\"margin-top:22px\"\u003e分析查阅了镜像仓库与上游，用 bird 逐条阅读了 19 条相关推文，读了《The Complete Guide to pstack》两篇长文和最近两周她本人及其他用户关于 pstack 的推文，还看了她 9 月 21 日发在 X 上的演讲视频（原本是给 Cursor Compile London 准备的；转写由 Whisper 自动生成，专有名词可能不准）。推文日期按 UTC 记。产能、质量数字都是作者自述。\u003c/p\u003e\n\u003c/header\u003e\n\n\u003c!-- 1 --\u003e\n\u003csection id=\"s1\"\u003e\n  \u003ch2\u003e\u003cspan class=\"n\"\u003e01\u003c/span\u003e先说结论\u003c/h2\u003e\n  \u003cp class=\"sub\"\u003e顺序比技能数量重要。没有第一步，后面的多代理流程只会更贵，不会更可信。\u003c/p\u003e\n  \u003cdiv class=\"flow\"\u003e\n    \u003cdiv class=\"step\"\u003e\u003cdiv class=\"num\"\u003e1\u003c/div\u003e\u003ch4\u003e验证技能 + feature map\u003c/h4\u003e\u003cp\u003e让代理能自己跑起并操作你的应用，截图取证。\u003c/p\u003e\u003cdiv class=\"q\"\u003e管\"对不对\"\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv class=\"step\"\u003e\u003cdiv class=\"num\"\u003e2\u003c/div\u003e\u003ch4\u003e\u003ccode\u003e/poteto-mode\u003c/code\u003e\u003c/h4\u003e\u003cp\u003e按任务类型路由到固定流程（playbook）。\u003c/p\u003e\u003cdiv class=\"q\"\u003e管\"好不好\"：性能、代码质量\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv class=\"step\"\u003e\u003cdiv class=\"num\"\u003e3\u003c/div\u003e\u003ch4\u003e并行与自动合并\u003c/h4\u003e\u003cp\u003e多代理、云代理、半夜自己合并。\u003c/p\u003e\u003cdiv class=\"q\" style=\"color:var(--muted)\"\u003e前两步都有才谈得上\u003c/div\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  \u003cp\u003eLauren 在 Pt. 1 里就是这么排的。她在 9 月的演讲里分得更清楚：验证管\"对不对\"，pstack 管\"好不好\"，两样都有才够。那场演讲标题是 2,500 个 PR，但 pstack 只讲了一小段，她自己说\"今天不多讲这个插件\"，产能主要归到验证、给代理设计的架构和自动派活的外循环上。\u003c/p\u003e\n  \u003ch3\u003e对 Claude Code 用户，两件事要注意\u003c/h3\u003e\n  \u003cdiv class=\"grid2\"\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag w\"\u003e评审退化\u003c/span\u003e\u003cp\u003e默认配置里的 Grok 在 Claude Code 里会被映射成\"沿用父模型\"，\u003ccode\u003e/arena\u003c/code\u003e、\u003ccode\u003e/architect\u003c/code\u003e、\u003ccode\u003e/interrogate\u003c/code\u003e 这些靠不同模型家族互评的流程，会变成同一家族自评。\u003c/p\u003e\u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag w\"\u003e上下文成本\u003c/span\u003e\u003cp\u003e\u003ccode\u003e/poteto-mode\u003c/code\u003e 本身约 3,600 个英文词，每个 \u003ccode\u003epoteto-agent\u003c/code\u003e 子代理都要完整读一遍。子代理越多，固定成本线性增加。值得用，但最好挑着用。\u003c/p\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/section\u003e\n\n\u003c!-- 2 --\u003e\n\u003csection id=\"s2\"\u003e\n  \u003ch2\u003e\u003cspan class=\"n\"\u003e02\u003c/span\u003e来源链：谁在维护什么\u003c/h2\u003e\n  \u003cp class=\"sub\"\u003e一个原始版本，一个通用化镜像，中间隔着手动同步。\u003c/p\u003e\n  \u003cfigure class=\"card\" style=\"padding:18px\"\u003e\n    \u003csvg viewBox=\"0 0 760 270\" role=\"img\" aria-label=\"来源链：Lauren 维护 cursor/plugins/pstack，Michael Ramos 维护镜像 backnotprop/pstack\"\u003e\n      \u003cdefs\u003e\u003cmarker id=\"ah\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto\"\u003e\u003cpath d=\"M0,0 L10,5 L0,10 z\" fill=\"var(--muted)\"/\u003e\u003c/marker\u003e\u003c/defs\u003e\n      \u003crect x=\"20\" y=\"20\" width=\"200\" height=\"64\" rx=\"12\" fill=\"var(--accent)\"/\u003e\n      \u003ctext x=\"120\" y=\"48\" text-anchor=\"middle\" font-size=\"16\" font-weight=\"700\" fill=\"#fff\"\u003eLauren Tan\u003c/text\u003e\n      \u003ctext x=\"120\" y=\"68\" text-anchor=\"middle\" font-size=\"12\" fill=\"#fff\" opacity=\".85\"\u003e@poteto · 作者\u003c/text\u003e\n      \u003cpath d=\"M220 52 H290\" stroke=\"var(--muted)\" stroke-width=\"2\" marker-end=\"url(#ah)\"/\u003e\n      \u003crect x=\"296\" y=\"20\" width=\"250\" height=\"64\" rx=\"12\" fill=\"var(--card)\" stroke=\"var(--accent)\" stroke-width=\"2\"/\u003e\n      \u003ctext x=\"421\" y=\"47\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"700\" fill=\"var(--ink)\" font-family=\"var(--mono)\"\u003ecursor/plugins/pstack\u003c/text\u003e\n      \u003ctext x=\"421\" y=\"68\" text-anchor=\"middle\" font-size=\"12\" fill=\"var(--muted)\"\u003e原始版本 · Cursor 插件 · 0.15.30\u003c/text\u003e\n      \u003cpath d=\"M421 84 V140\" stroke=\"var(--muted)\" stroke-width=\"2\" stroke-dasharray=\"5 4\" marker-end=\"url(#ah)\" class=\"ants\"/\u003e\n      \u003ctext x=\"432\" y=\"118\" font-size=\"11\" fill=\"var(--warn)\"\u003e手动同步，有延迟\u003c/text\u003e\n      \u003crect x=\"296\" y=\"146\" width=\"250\" height=\"64\" rx=\"12\" fill=\"var(--card)\" stroke=\"var(--teal)\" stroke-width=\"2\"/\u003e\n      \u003ctext x=\"421\" y=\"173\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"700\" fill=\"var(--ink)\" font-family=\"var(--mono)\"\u003ebacknotprop/pstack\u003c/text\u003e\n      \u003ctext x=\"421\" y=\"194\" text-anchor=\"middle\" font-size=\"12\" fill=\"var(--muted)\"\u003eMichael Ramos 的镜像 · 0.15.28\u003c/text\u003e\n      \u003cpath d=\"M546 178 H590\" stroke=\"var(--muted)\" stroke-width=\"2\"/\u003e\n      \u003cpath d=\"M590 140 V230\" stroke=\"var(--muted)\" stroke-width=\"2\"/\u003e\n      \u003cpath d=\"M590 140 H604\" stroke=\"var(--muted)\" stroke-width=\"2\"/\u003e\u003cpath d=\"M590 185 H604\" stroke=\"var(--muted)\" stroke-width=\"2\"/\u003e\u003cpath d=\"M590 230 H604\" stroke=\"var(--muted)\" stroke-width=\"2\"/\u003e\n      \u003ctext x=\"612\" y=\"144\" font-size=\"12\" fill=\"var(--ink2)\"\u003e\u003ctspan font-family=\"var(--mono)\" font-weight=\"600\"\u003eupstream\u003c/tspan\u003e 上游原样\u003c/text\u003e\n      \u003ctext x=\"612\" y=\"189\" font-size=\"12\" fill=\"var(--ink2)\"\u003e\u003ctspan font-family=\"var(--mono)\" font-weight=\"600\"\u003emain\u003c/tspan\u003e + 通用化改写\u003c/text\u003e\n      \u003ctext x=\"612\" y=\"234\" font-size=\"11\" fill=\"var(--teal)\" font-family=\"var(--mono)\"\u003enpx skills add …\u003c/text\u003e\n      \u003ctext x=\"40\" y=\"160\" font-size=\"12\" fill=\"var(--muted)\"\u003e经 Grok Bot / Cursor 安装\u003c/text\u003e\n      \u003ctext x=\"40\" y=\"178\" font-size=\"12\" fill=\"var(--muted)\"\u003e→ 自动更新\u003c/text\u003e\n      \u003ctext x=\"40\" y=\"210\" font-size=\"12\" fill=\"var(--muted)\"\u003e经镜像安装（Claude Code、\u003c/text\u003e\n      \u003ctext x=\"40\" y=\"228\" font-size=\"12\" fill=\"var(--muted)\"\u003eCodex、Pi 等）→ 等维护者同步\u003c/text\u003e\n    \u003c/svg\u003e\n  \u003c/figure\u003e\n\n  \u003cdiv class=\"grid2\"\u003e\n    \u003cdiv class=\"card\"\u003e\n      \u003cspan class=\"tag o\"\u003e为什么默认是 Grok\u003c/span\u003e\n      \u003csvg viewBox=\"0 0 380 92\" style=\"margin:14px 0 4px\" role=\"img\" aria-label=\"履历：React 团队，Cursor Agents Window 性能，SpaceX AI Grok Bot\"\u003e\n        \u003cline x1=\"24\" y1=\"30\" x2=\"356\" y2=\"30\" stroke=\"var(--line)\" stroke-width=\"3\"/\u003e\n        \u003ccircle cx=\"24\" cy=\"30\" r=\"7\" fill=\"var(--bar2)\"/\u003e\u003ccircle cx=\"190\" cy=\"30\" r=\"7\" fill=\"var(--bar2)\"/\u003e\u003ccircle cx=\"356\" cy=\"30\" r=\"9\" fill=\"var(--accent)\"/\u003e\n        \u003ctext x=\"24\" y=\"62\" text-anchor=\"start\" font-size=\"13\" font-weight=\"600\" fill=\"var(--ink)\"\u003eReact 团队\u003c/text\u003e\n        \u003ctext x=\"190\" y=\"62\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"600\" fill=\"var(--ink)\"\u003eCursor\u003c/text\u003e\n        \u003ctext x=\"190\" y=\"80\" text-anchor=\"middle\" font-size=\"11\" fill=\"var(--muted)\"\u003eAgents Window 性能\u003c/text\u003e\n        \u003ctext x=\"356\" y=\"62\" text-anchor=\"end\" font-size=\"13\" font-weight=\"600\" fill=\"var(--accent)\"\u003eSpaceX AI\u003c/text\u003e\n        \u003ctext x=\"356\" y=\"80\" text-anchor=\"end\" font-size=\"11\" fill=\"var(--muted)\"\u003eGrok Bot\u003c/text\u003e\n      \u003c/svg\u003e\n      \u003cp class=\"note\" style=\"margin:0\"\u003eCursor 现在并入了 SpaceX AI。Grok 是她公司自己的模型，所以默认配置里 Claude 和 Grok 混用。这个组合首先反映她的工作环境，不一定适合其他宿主。\u003c/p\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\n      \u003cspan class=\"tag w\"\u003e更新很快\u003c/span\u003e\n      \u003csvg viewBox=\"0 0 380 92\" style=\"margin:14px 0 4px\" role=\"img\" aria-label=\"10 月 4 日 0.15.9 到 10 月 22 日 0.15.30\"\u003e\n        \u003cg id=\"ticks\"\u003e\u003c/g\u003e\n        \u003ctext x=\"10\" y=\"80\" font-size=\"11\" fill=\"var(--muted)\" font-family=\"var(--mono)\"\u003e10/04 · 0.15.9\u003c/text\u003e\n        \u003ctext x=\"370\" y=\"80\" font-size=\"11\" fill=\"var(--accent)\" text-anchor=\"end\" font-family=\"var(--mono)\" font-weight=\"600\"\u003e10/22 · 0.15.30\u003c/text\u003e\n      \u003c/svg\u003e\n      \u003cp class=\"note\" style=\"margin:0\"\u003e18 天二十来个补丁版本。对试用是好事；对把它固化进团队流程的人是个提醒：技能文本随时在变，评测结果也会跟着变。镜像的 \u003ca href=\"https://github.com/backnotprop/pstack/blob/main/MIRROR.md\"\u003eMIRROR.md\u003c/a\u003e 写明冲突时\"保留 Cursor 的新含义，再套用通用措辞\"，\u003ca href=\"https://x.com/poteto/status/2110047891201114165\"\u003e镜像要等维护者手动同步\u003c/a\u003e。\u003c/p\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/section\u003e\n\n\u003c!-- 3 --\u003e\n\u003csection id=\"s3\"\u003e\n  \u003ch2\u003e\u003cspan class=\"n\"\u003e03\u003c/span\u003e仓库结构\u003c/h2\u003e\n  \u003cp class=\"sub\"\u003e56 个技能、23 个 playbook、两个代理定义（\u003ccode\u003epoteto-agent\u003c/code\u003e、\u003ccode\u003ecomment-sicko\u003c/code\u003e）、一套只适用于 Cursor 的 Benny 自动化、10 章指南，MIT 许可。\u003c/p\u003e\n\n  \u003cfigure class=\"card\"\u003e\n    \u003cdiv style=\"display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;align-items:baseline\"\u003e\n      \u003cstrong\u003e每次进上下文的文本量（英文词）\u003c/strong\u003e\n      \u003cspan class=\"note\"\u003e全部 SKILL.md + playbook 合计约 49,500 词，不会一次全读\u003c/span\u003e\n    \u003c/div\u003e\n    \u003csvg id=\"wordsChart\" viewBox=\"0 0 720 210\" role=\"img\" aria-label=\"词数条形图\"\u003e\u003c/svg\u003e\n    \u003cfigcaption\u003e\u003ccode\u003epoteto-mode\u003c/code\u003e 每个子代理都要再读一遍；原则主文件只放索引，要求\"应用哪个就完整读哪个\"；playbook 按任务类型选中后才读。\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\n  \u003cfigure class=\"card\"\u003e\n    \u003cstrong\u003e固定上下文随子代理数线性增长\u003c/strong\u003e\n    \u003csvg id=\"agentsChart\" viewBox=\"0 0 720 150\" role=\"img\" aria-label=\"子代理数与 poteto-mode 读取量\"\u003e\u003c/svg\u003e\n    \u003cfigcaption\u003e只算 \u003ccode\u003epoteto-mode\u003c/code\u003e 本身：主会话一次，加上每个 \u003ccode\u003epoteto-agent\u003c/code\u003e 子代理一次，每次约 3,600 词。\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\n  \u003ch3\u003e\u003ccode\u003epoteto-mode\u003c/code\u003e 里值得注意的硬规则\u003c/h3\u003e\n  \u003cdiv class=\"grid3\"\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag o\"\u003e先跑后问\u003c/span\u003e\u003cp\u003e要问用户\"选哪个方案\"之前，先判断能不能靠跑一下得到答案；能的话走 Prototype playbook 去试。\u003c/p\u003e\u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag o\"\u003e先说数据结构\u003c/span\u003e\u003cp\u003e任何代码先说出数据结构；跨函数边界的改动先走 \u003ccode\u003e/architect\u003c/code\u003e。\u003c/p\u003e\u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag o\"\u003e关卡\u003c/span\u003e\u003cp\u003e提交前过 \u003ccode\u003edeslop\u003c/code\u003e，review 前过 \u003ccode\u003e/no-comments\u003c/code\u003e。\u003c/p\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"callout\"\u003e\u003cstrong\u003e防糊弄设计：\u003c/strong\u003e答复里要点名哪个原则改变了哪个决定，而且只能点名本会话里真读过的原则。\u003c/div\u003e\n\u003c/section\u003e\n\n\u003c!-- 4 --\u003e\n\u003csection id=\"s4\"\u003e\n  \u003ch2\u003e\u003cspan class=\"n\"\u003e04\u003c/span\u003e两篇长文中的方法\u003c/h2\u003e\n  \u003cp class=\"sub\"\u003e这两篇解释了 README 里\"没有 planning 技能\"的说法：不是不计划，是把计划换成可运行的东西。\u003c/p\u003e\n  \u003cdiv class=\"grid2\"\u003e\n    \u003cdiv class=\"card\"\u003e\n      \u003cspan class=\"tag o\"\u003ePt. 1 · 8 月 31 日\u003c/span\u003e\n      \u003ch3 style=\"margin-top:12px\"\u003e验证是一切的前提\u003c/h3\u003e\n      \u003cp class=\"note\"\u003e她把验证技能当作\"关键基础设施\"，甚至建议给它排 oncall。\u003c/p\u003e\n      \u003cp\u003e\u003cstrong\u003e① 小 CLI 而不是临时脚本。\u003c/strong\u003e对应原则 \u003ca href=\"https://github.com/backnotprop/pstack/blob/main/skills/principle-build-the-lever/SKILL.md\"\u003eBuild the Lever\u003c/a\u003e。应有的特征：\u003c/p\u003e\n      \u003cdiv class=\"chips\" style=\"margin:0 0 10px\"\u003e\n        \u003cspan class=\"chip\"\u003e可组合\u003c/span\u003e\u003cspan class=\"chip\"\u003e破坏性命令带 --dry-run\u003c/span\u003e\u003cspan class=\"chip\"\u003e子命令逐步暴露\u003c/span\u003e\u003cspan class=\"chip\"\u003e错误信息教代理怎么做\u003c/span\u003e\u003cspan class=\"chip\"\u003e详细 --help\u003c/span\u003e\u003cspan class=\"chip\"\u003e输出 JSON\u003c/span\u003e\n      \u003c/div\u003e\n      \u003cp\u003e\u003cstrong\u003e② feature map。\u003c/strong\u003e每个功能写清楚用户从哪进、怎么用、用 CLI 怎么驱动、有哪些坑。她称之为\"物化的记忆\"：代码是团队决策的投影，feature map 是它的压缩版。见\u003ca href=\"https://github.com/poteto/verification-skill-example\"\u003e虚构应用 Atlas 的示例\u003c/a\u003e。\u003c/p\u003e\n      \u003cp\u003e\u003cstrong\u003e③ 技术栈影响代理生产力。\u003c/strong\u003eElectron 和 Web 有 CDP，iOS 有模拟器；运行时越难调试、越难控制，代理越难用。她甚至说值得为此自建调试工具或换技术栈。很激进，但逻辑一致。\u003c/p\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\n      \u003cspan class=\"tag t\"\u003ePt. 2 · 9 月 9 日\u003c/span\u003e\n      \u003ch3 style=\"margin-top:12px\"\u003e用代码做计划\u003c/h3\u003e\n      \u003cp class=\"note\"\u003e主题是\"监督比你聪明的人\"。\u003c/p\u003e\n      \u003cp\u003e\u003cstrong\u003e先对齐意图。\u003c/strong\u003e让代理用自己的话复述问题（\u003ccode\u003e/in-your-own-words\u003c/code\u003e），早发现误解，也避免自己的假设把代理带偏。\u003c/p\u003e\n      \u003cp\u003e\u003cstrong\u003e补上下文。\u003c/strong\u003e\u003ccode\u003e/teach\u003c/code\u003e 调 \u003ccode\u003e/how\u003c/code\u003e（追运行机制）和 \u003ccode\u003e/why\u003c/code\u003e（从 git、PR 评论、Linear、Notion、Slack、Sentry 查动机），\u003ccode\u003e/recall\u003c/code\u003e 从历史会话捞上下文。\u003c/p\u003e\n      \u003cp\u003e\u003cstrong\u003e原型代替长文档。\u003c/strong\u003e她反对对抽象计划做对抗式评审：代理会臆想风险、为不会发生的边界情况设防。替代做法：\u003c/p\u003e\n      \u003csvg viewBox=\"0 0 400 66\" role=\"img\" aria-label=\"原型流程\"\u003e\n        \u003cg font-size=\"11.5\" text-anchor=\"middle\"\u003e\n          \u003crect x=\"0\" y=\"12\" width=\"88\" height=\"40\" rx=\"8\" fill=\"var(--teal-soft)\"/\u003e\u003ctext x=\"44\" y=\"36\" fill=\"var(--teal)\" font-weight=\"600\"\u003e2–3 个变体\u003c/text\u003e\n          \u003crect x=\"104\" y=\"12\" width=\"88\" height=\"40\" rx=\"8\" fill=\"var(--teal-soft)\"/\u003e\u003ctext x=\"148\" y=\"36\" fill=\"var(--teal)\" font-weight=\"600\"\u003e截图测量\u003c/text\u003e\n          \u003crect x=\"208\" y=\"12\" width=\"88\" height=\"40\" rx=\"8\" fill=\"var(--teal-soft)\"/\u003e\u003ctext x=\"252\" y=\"31\" fill=\"var(--teal)\" font-weight=\"600\"\u003e/architect\u003c/text\u003e\u003ctext x=\"252\" y=\"45\" fill=\"var(--teal)\" font-size=\"10\"\u003e多家族出签名\u003c/text\u003e\n          \u003crect x=\"312\" y=\"12\" width=\"88\" height=\"40\" rx=\"8\" fill=\"var(--teal)\"/\u003e\u003ctext x=\"356\" y=\"36\" fill=\"#fff\" font-weight=\"600\"\u003e交叉评判→实现\u003c/text\u003e\n          \u003cg fill=\"var(--muted)\"\u003e\u003cpath d=\"M90 32 l10 0\" stroke=\"var(--muted)\"/\u003e\u003cpath d=\"M194 32 l10 0\" stroke=\"var(--muted)\"/\u003e\u003cpath d=\"M298 32 l10 0\" stroke=\"var(--muted)\"/\u003e\u003c/g\u003e\n        \u003c/g\u003e\n      \u003c/svg\u003e\n      \u003cp\u003e设计错了就推倒。真要计划文档，就用 multi-phase-plan playbook，每项以\"实际运行验证过\"为完成标准，用 \u003ccode\u003echeck-plan.mjs\u003c/code\u003e 查格式；大项目的计划临时提交进仓库，做完就删。\u003c/p\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/section\u003e\n\n\u003c!-- 5 --\u003e\n\u003csection id=\"s5\"\u003e\n  \u003ch2\u003e\u003cspan class=\"n\"\u003e05\u003c/span\u003e在 Claude Code 里实际会发生什么\u003c/h2\u003e\n  \u003cp class=\"sub\"\u003e依据镜像加的映射表 \u003ca href=\"https://github.com/backnotprop/pstack/blob/main/docs/harness/claude-code.md\"\u003e\u003ccode\u003edocs/harness/claude-code.md\u003c/code\u003e\u003c/a\u003e。\u003c/p\u003e\n\n  \u003cdiv class=\"cmpwrap\"\u003e\n  \u003ctable class=\"cmp\"\u003e\n    \u003cthead\u003e\u003ctr\u003e\u003cth\u003e能力\u003c/th\u003e\u003cth\u003eCursor（设计目标）\u003c/th\u003e\u003cth class=\"arrow\"\u003e\u003c/th\u003e\u003cth\u003eClaude Code（映射后）\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\n    \u003ctbody\u003e\n      \u003ctr\u003e\u003ctd\u003e多模型评审\u003c/td\u003e\u003ctd\u003e评审团一个 Claude、一个 Grok：代码类 \u003ccode\u003egrok-4.7-xhigh-fast\u003c/code\u003e，判断和写作 \u003ccode\u003eclaude-opus-5-5-xhigh\u003c/code\u003e\u003c/td\u003e\u003ctd class=\"arrow\"\u003e→\u003c/td\u003e\u003ctd class=\"lose\"\u003e非 Claude 模型\"省略 \u003ccode\u003emodel\u003c/code\u003e，沿用会话模型\"，Grok 写成 \u003ccode\u003einherit-parent\u003c/code\u003e；两个席位同一家族\u003c/td\u003e\u003c/tr\u003e\n      \u003ctr\u003e\u003ctd\u003e并行\u003c/td\u003e\u003ctd\u003e云代理：每个代理一台机器、录屏截图、半夜自己合并\u003c/td\u003e\u003ctd class=\"arrow\"\u003e→\u003c/td\u003e\u003ctd class=\"lose\"\u003e\u003ccode\u003eenvironment: \"cloud\"\u003c/code\u003e 换成 \u003ccode\u003eisolation: \"worktree\"\u003c/code\u003e；她本人劝别用，本地大概十个到头\u003c/td\u003e\u003c/tr\u003e\n      \u003ctr\u003e\u003ctd\u003e技能互调\u003c/td\u003e\u003ctd\u003e原生调用\u003c/td\u003e\u003ctd class=\"arrow\"\u003e→\u003c/td\u003e\u003ctd class=\"lose\"\u003e55 个技能禁止模型自动调用，Skill 工具会拒绝；改为直接 \u003ccode\u003eRead\u003c/code\u003e 对应 \u003ccode\u003eSKILL.md\u003c/code\u003e，多一步、多吃上下文\u003c/td\u003e\u003c/tr\u003e\n      \u003ctr\u003e\u003ctd\u003eCursor 专有\u003c/td\u003e\u003ctd\u003eAutomations、Bugbot、云代理面板；\u003ccode\u003e/maintain-verification-skill\u003c/code\u003e 每日自动跑\u003c/td\u003e\u003ctd class=\"arrow\"\u003e→\u003c/td\u003e\u003ctd class=\"lose\"\u003e一行 \"Skipped in Claude Code\"；每日维护要自己用 cron 等调度补\u003c/td\u003e\u003c/tr\u003e\n      \u003ctr\u003e\u003ctd\u003e外循环\u003c/td\u003e\u003ctd\u003eGrok Bot 接 Slack、Datadog、Sentry、PlanetScale；routines 订阅线程和告警，自动派云代理复现 bug、开 PR\u003c/td\u003e\u003ctd class=\"arrow\"\u003e→\u003c/td\u003e\u003ctd class=\"lose\"\u003epstack 不提供，Claude Code 也没有现成对应物，要自己搭\u003c/td\u003e\u003c/tr\u003e\n    \u003c/tbody\u003e\n  \u003c/table\u003e\n  \u003c/div\u003e\n\n  \u003cfigure class=\"card\"\u003e\n    \u003cstrong\u003e评审团席位：同一提示，换一个模型\u003c/strong\u003e\n    \u003csvg viewBox=\"0 0 720 170\" role=\"img\" aria-label=\"Cursor 里评审团是 Claude 加 Grok，Claude Code 里两个席位都是 Claude\"\u003e\n      \u003ctext x=\"170\" y=\"26\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" fill=\"var(--ink)\"\u003eCursor\u003c/text\u003e\n      \u003ctext x=\"550\" y=\"26\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"700\" fill=\"var(--ink)\"\u003eClaude Code\u003c/text\u003e\n      \u003cg\u003e\u003ccircle cx=\"120\" cy=\"88\" r=\"40\" fill=\"var(--accent-soft)\" stroke=\"var(--accent)\" stroke-width=\"2\"/\u003e\u003ctext x=\"120\" y=\"93\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"700\" fill=\"var(--accent)\"\u003eClaude\u003c/text\u003e\u003c/g\u003e\n      \u003cg\u003e\u003ccircle cx=\"220\" cy=\"88\" r=\"40\" fill=\"var(--teal-soft)\" stroke=\"var(--teal)\" stroke-width=\"2\"/\u003e\u003ctext x=\"220\" y=\"93\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"700\" fill=\"var(--teal)\"\u003eGrok\u003c/text\u003e\u003c/g\u003e\n      \u003ctext x=\"170\" y=\"155\" text-anchor=\"middle\" font-size=\"12\" fill=\"var(--muted)\"\u003e两家一致 → 强信号\u003c/text\u003e\n      \u003cpath d=\"M318 88 H402\" stroke=\"var(--muted)\" stroke-width=\"2\" marker-end=\"url(#ah)\"/\u003e\n      \u003ctext x=\"360\" y=\"78\" text-anchor=\"middle\" font-size=\"11\" fill=\"var(--muted)\"\u003einherit-parent\u003c/text\u003e\n      \u003cg\u003e\u003ccircle cx=\"500\" cy=\"88\" r=\"40\" fill=\"var(--accent-soft)\" stroke=\"var(--accent)\" stroke-width=\"2\"/\u003e\u003ctext x=\"500\" y=\"93\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"700\" fill=\"var(--accent)\"\u003eClaude\u003c/text\u003e\u003c/g\u003e\n      \u003cg\u003e\u003ccircle cx=\"600\" cy=\"88\" r=\"40\" fill=\"var(--accent-soft)\" stroke=\"var(--accent)\" stroke-width=\"2\" stroke-dasharray=\"6 4\"/\u003e\u003ctext x=\"600\" y=\"93\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"700\" fill=\"var(--accent)\"\u003eClaude\u003c/text\u003e\u003c/g\u003e\n      \u003ctext x=\"550\" y=\"155\" text-anchor=\"middle\" font-size=\"12\" fill=\"var(--warn)\"\u003e同一家族自评，信号打折\u003c/text\u003e\n    \u003c/svg\u003e\n    \u003cfigcaption\u003e\u003ccode\u003epoteto-mode\u003c/code\u003e 自己写着\"第二意见是同一提示换一个模型，一致才是强信号\"。要找回多样性，得让子代理调用外部 CLI（Codex、Gemini 等），pstack 本身不提供。\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/section\u003e\n\n\u003c!-- 6 --\u003e\n\u003csection id=\"s6\"\u003e\n  \u003ch2\u003e\u003cspan class=\"n\"\u003e06\u003c/span\u003e成本：已知数字和一个独立样本\u003c/h2\u003e\n  \u003cp class=\"sub\"\u003e两层成本：固定上下文 × 子代理数量。\u003c/p\u003e\n  \u003cdiv class=\"grid2\"\u003e\n    \u003cfigure class=\"card\" style=\"margin:0\"\u003e\n      \u003cstrong\u003e@dwkim601 的对比\u003c/strong\u003e\n      \u003cdiv class=\"note\"\u003eclaude-sonnet-5-5 · 5 个带隐藏测试的小任务\u003c/div\u003e\n      \u003csvg id=\"costChart\" viewBox=\"0 0 400 170\" role=\"img\" aria-label=\"不加 pstack 2.435 美元，加 poteto-mode 3.455 美元\"\u003e\u003c/svg\u003e\n      \u003cfigcaption\u003e两组都是 15/15 通过。他自己也说任务太简单，说明不了难题上的效果。\u003ca href=\"https://x.com/dwkim601/status/2113002041991926194\"\u003e原推\u003c/a\u003e\u003c/figcaption\u003e\n    \u003c/figure\u003e\n    \u003cdiv class=\"card\"\u003e\n      \u003cspan class=\"tag o\"\u003e成本来自哪\u003c/span\u003e\n      \u003cp\u003eLauren 说\u003ca href=\"https://x.com/poteto/status/2110498629307990461\"\u003e成本主要来自大量子代理\u003c/a\u003e，建议跑 \u003ccode\u003e/setup-pstack\u003c/code\u003e 选预算，并在会话开头告诉代理别开大规模 swarm。\u003c/p\u003e\n      \u003cdiv class=\"callout\" style=\"margin:12px 0\"\u003e\u003cstrong\u003e注意：\u003c/strong\u003e预算档位只调推理强度（max / xhigh / high / medium），不减少子代理个数。\u003c/div\u003e\n      \u003cp class=\"note\"\u003e样本很小，但方向和直觉一致：简单任务上 pstack 主要是额外成本，收益要到需要复现、验证、设计取舍的任务上才可能体现。Lauren 说她\u003ca href=\"https://x.com/poteto/status/2109912648116826250\"\u003e对自己的技能做评测\u003c/a\u003e，还说过一次\u003ca href=\"https://x.com/poteto/status/2109116030761230571\"\u003e精简 10% 且行为无损\u003c/a\u003e，但没有公开评测数据。\u003c/p\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"callout t\"\u003e\u003cstrong\u003e外部风险：\u003c/strong\u003eCursor 订阅方案调整后，有用户说\u003ca href=\"https://x.com/antoniolorusso/status/2112973440923693268\"\u003e用不了 Opus 5.5\u003c/a\u003e，也有人问\u003ca href=\"https://x.com/Zeez0321/status/2113065638755541362\"\u003e第三方模型受限后 pstack 是否会调整\u003c/a\u003e。默认配置绑定了具体模型名，宿主的模型政策一变，效果就会变。\u003c/div\u003e\n\u003c/section\u003e\n\n\u003c!-- 7 --\u003e\n\u003csection id=\"s7\"\u003e\n  \u003ch2\u003e\u003cspan class=\"n\"\u003e07\u003c/span\u003e推文里的工程判断\u003c/h2\u003e\n  \u003cp class=\"sub\"\u003e被纠正时，从最硬的一层修起。\u003c/p\u003e\n\n  \u003ch3\u003e把反复纠正变成结构：\u003ca href=\"https://x.com/poteto/status/2089067865098113024\"\u003e四级顺序\u003c/a\u003e\u003c/h3\u003e\n  \u003cdiv class=\"ladder\"\u003e\n    \u003cdiv class=\"rung\"\u003e\u003cspan class=\"lv\"\u003e1\u003c/span\u003e\u003cdiv\u003e\u003cdiv class=\"t\"\u003e架构 / 数据结构根除\u003c/div\u003e\u003cdiv class=\"d\"\u003e让错误在类别上不可能发生\u003c/div\u003e\u003c/div\u003e\u003cdiv class=\"meter\"\u003e\u003ci style=\"width:100%;--d:.1s\"\u003e\u003c/i\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv class=\"rung\"\u003e\u003cspan class=\"lv\"\u003e2\u003c/span\u003e\u003cdiv\u003e\u003cdiv class=\"t\"\u003elint 或测试，CI 拦截\u003c/div\u003e\u003cdiv class=\"d\"\u003e机器强制，不靠记性\u003c/div\u003e\u003c/div\u003e\u003cdiv class=\"meter\"\u003e\u003ci style=\"width:75%;--d:.25s\"\u003e\u003c/i\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv class=\"rung\"\u003e\u003cspan class=\"lv\"\u003e3\u003c/span\u003e\u003cdiv\u003e\u003cdiv class=\"t\"\u003e技能或规则\u003c/div\u003e\u003cdiv class=\"d\"\u003e代理多数时候会遵守，但可能漏读\u003c/div\u003e\u003c/div\u003e\u003cdiv class=\"meter\"\u003e\u003ci style=\"width:45%;--d:.4s\"\u003e\u003c/i\u003e\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv class=\"rung ngmi\"\u003e\u003cspan class=\"lv\"\u003e4\u003c/span\u003e\u003cdiv\u003e\u003cdiv class=\"t\"\u003e人工 review\u003c/div\u003e\u003cdiv class=\"d\"\u003e她标成 \"ngmi\"\u003c/div\u003e\u003c/div\u003e\u003cdiv class=\"meter\"\u003e\u003ci style=\"width:15%;background:var(--muted);--d:.55s\"\u003e\u003c/i\u003e\u003c/div\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  \u003cp\u003e\u003ccode\u003e/correct\u003c/code\u003e 回看代理反复犯的错，用架构、类型和检查去修。她给过一段\u003ca href=\"https://x.com/poteto/status/2106542593656111276\"\u003e可以直接用的提示词\u003c/a\u003e：让代理翻历史提交找常见陷阱，用原型回答自己的开放问题，带着数据回来给人审。\u003c/p\u003e\n\n  \u003ch3\u003eDune：让捷径就是正确的路\u003c/h3\u003e\n  \u003cp\u003eGrok Bot 的客户端框架，演讲里最具体的例子。代价是人写起来很难受；好处是上下文很少的代理，或者设计师、PM 驾驶的代理，默认也能写对。\u003c/p\u003e\n  \u003cdiv class=\"grid3\"\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag o\"\u003e原则 1\u003c/span\u003e\u003cp\u003e\u003cstrong\u003e删掉已有技术债。\u003c/strong\u003e\u003c/p\u003e\u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag o\"\u003e原则 2\u003c/span\u003e\u003cp\u003e\u003cstrong\u003e每件事只留一种写法\u003c/strong\u003e，用 CI 和 lint 引着代理走，不让它猜。\u003c/p\u003e\u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag o\"\u003e原则 3\u003c/span\u003e\u003cp\u003e\u003cstrong\u003e看到坏模式先写 lint 止血\u003c/strong\u003e，之后再让代理清理，代码库始终处在\"代理照抄也没问题\"的状态。\u003c/p\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  \u003cfigure class=\"card\"\u003e\n    \u003cstrong\u003e落地例子：用导入依赖图隔开 Electron 主进程和渲染进程\u003c/strong\u003e\n    \u003csvg viewBox=\"0 0 720 210\" role=\"img\" aria-label=\"主进程模块不能被导入到渲染进程，渲染线程每帧预算 16ms 或 8ms\"\u003e\n      \u003crect x=\"20\" y=\"30\" width=\"250\" height=\"150\" rx=\"14\" fill=\"var(--teal-soft)\"/\u003e\n      \u003ctext x=\"40\" y=\"56\" font-size=\"13\" font-weight=\"700\" fill=\"var(--teal)\"\u003e主进程 main\u003c/text\u003e\n      \u003crect x=\"40\" y=\"72\" width=\"100\" height=\"34\" rx=\"8\" fill=\"var(--card)\" stroke=\"var(--teal)\"/\u003e\u003ctext x=\"90\" y=\"94\" text-anchor=\"middle\" font-size=\"12\" fill=\"var(--ink2)\"\u003e慢代码\u003c/text\u003e\n      \u003crect x=\"150\" y=\"72\" width=\"100\" height=\"34\" rx=\"8\" fill=\"var(--card)\" stroke=\"var(--teal)\"/\u003e\u003ctext x=\"200\" y=\"94\" text-anchor=\"middle\" font-size=\"12\" fill=\"var(--ink2)\"\u003eIO / 重计算\u003c/text\u003e\n      \u003crect x=\"450\" y=\"30\" width=\"250\" height=\"150\" rx=\"14\" fill=\"var(--accent-soft)\"/\u003e\n      \u003ctext x=\"470\" y=\"56\" font-size=\"13\" font-weight=\"700\" fill=\"var(--accent)\"\u003e渲染进程 renderer\u003c/text\u003e\n      \u003ctext x=\"470\" y=\"84\" font-size=\"12\" fill=\"var(--ink2)\"\u003e每帧预算\u003c/text\u003e\n      \u003crect x=\"470\" y=\"96\" width=\"210\" height=\"16\" rx=\"4\" fill=\"var(--bar2)\"/\u003e\u003crect x=\"470\" y=\"96\" width=\"210\" height=\"16\" rx=\"4\" fill=\"var(--accent)\"/\u003e\u003ctext x=\"676\" y=\"108\" text-anchor=\"end\" font-size=\"11\" fill=\"#fff\" font-weight=\"600\"\u003e16ms · 60fps\u003c/text\u003e\n      \u003crect x=\"470\" y=\"122\" width=\"105\" height=\"16\" rx=\"4\" fill=\"var(--accent)\" opacity=\".7\"/\u003e\u003ctext x=\"583\" y=\"134\" font-size=\"11\" fill=\"var(--ink2)\" font-weight=\"600\"\u003e8ms · 120fps\u003c/text\u003e\n      \u003ctext x=\"470\" y=\"164\" font-size=\"11\" fill=\"var(--muted)\"\u003e不能有长任务\u003c/text\u003e\n      \u003cline x1=\"360\" y1=\"20\" x2=\"360\" y2=\"190\" stroke=\"var(--ink)\" stroke-width=\"3\" stroke-dasharray=\"2 6\" stroke-linecap=\"round\"/\u003e\n      \u003cpath d=\"M90 106 C 120 160, 330 150, 440 120\" fill=\"none\" stroke=\"var(--warn)\" stroke-width=\"2\" stroke-dasharray=\"6 4\" class=\"ants\"/\u003e\n      \u003ccircle class=\"pulse\" cx=\"360\" cy=\"136\" r=\"14\" fill=\"var(--paper)\" stroke=\"var(--warn)\" stroke-width=\"2\"/\u003e\n      \u003cpath d=\"M353 129 L367 143 M367 129 L353 143\" stroke=\"var(--warn)\" stroke-width=\"2.5\" stroke-linecap=\"round\"/\u003e\n      \u003ctext x=\"360\" y=\"204\" text-anchor=\"middle\" font-size=\"11\" fill=\"var(--ink2)\"\u003e依赖图检查：禁止跨界导入\u003c/text\u003e\n    \u003c/svg\u003e\n    \u003cfigcaption\u003eCursor Agents Window 出过慢代码被误引入渲染线程的问题。她强调重点不在 Dune 本身，而在于把原本散在 code review 评论里的经验写进框架。\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\n  \u003cdiv class=\"grid2\"\u003e\n    \u003cdiv class=\"card\"\u003e\n      \u003cspan class=\"tag w\"\u003e删注释\u003c/span\u003e\n      \u003cp\u003e她主张\u003ca href=\"https://x.com/poteto/status/2110149626133438732\"\u003e禁止并删除大部分代码注释\u003c/a\u003e：代理爱模仿现有代码，一条解释临时绕过方案的注释会被当成模板扩散。演讲里给了起因：在 Cursor 代码库里，代理拿周围的注释当理由，不去解决根本问题，贴个补丁了事。所以 Dune 直接禁止写注释。\u003c/p\u003e\n      \u003cp class=\"note\"\u003e\u003ccode\u003e/no-comments\u003c/code\u003e 会保留解释浏览器怪癖这类必要注释。立场有争议，她在回复里承认\u003ca href=\"https://x.com/poteto/status/2110165682302447699\"\u003e不是非黑即白\u003c/a\u003e。\u003c/p\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\n      \u003cspan class=\"tag t\"\u003e验证是近似\u003c/span\u003e\n      \u003cp\u003e\u003ca href=\"https://x.com/poteto/status/2109436202554372476\"\u003e验证推文\u003c/a\u003e说得很克制：验证产物要证明工作正确、符合意图、比读整个 PR 更好审；同时承认不是所有领域都容易验证，验证也会错，\"和相信人类真的跑过自己写的代码没什么区别\"。\u003c/p\u003e\n      \u003cspan class=\"tag w\" style=\"margin-top:8px\"\u003e形式化验证 · beta\u003c/span\u003e\n      \u003cp class=\"note\"\u003e\u003ca href=\"https://github.com/backnotprop/pstack/blob/main/skills/create-formal-verification-skill/SKILL.md\"\u003e\u003ccode\u003e/create-formal-verification-skill\u003c/code\u003e\u003c/a\u003e 只有 41 行：先挑单元测试够不着、出错代价高的性质；事件顺序默认 TLA+；没有验证器就明说，改用生成输入测真实代码；每个性质都要在故意改坏的版本上失败过。上游 10 月 19 日补了 TLA+ 默认值和回退，又加了 \u003ccode\u003emaintain-formal-verification-skill\u003c/code\u003e。\u003c/p\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\n  \u003cfigure class=\"card\"\u003e\n    \u003cdiv style=\"display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;align-items:baseline\"\u003e\n      \u003cstrong\u003e产能数字一直在涨，口径不统一（每月 PR 数，自述）\u003c/strong\u003e\n    \u003c/div\u003e\n    \u003csvg id=\"prChart\" viewBox=\"0 0 720 220\" role=\"img\" aria-label=\"8 月 19 日 1000，8 月 31 日 2000，9 月 21 日 2500\"\u003e\u003c/svg\u003e\n    \u003cfigcaption\u003e她在 Pt. 1 里也说过 PR 数曾是她眼里的虚荣指标。这些数字依赖 Grok Bot 团队的代码库、Cursor 云代理、接着 Slack 和 Sentry 自动派活的外循环，以及她本人的判断力，\u003cstrong\u003e不能当作安装 pstack 的预期收益\u003c/strong\u003e。\u003c/figcaption\u003e\n  \u003c/figure\u003e\n\u003c/section\u003e\n\n\u003c!-- 8 --\u003e\n\u003csection id=\"s8\"\u003e\n  \u003ch2\u003e\u003cspan class=\"n\"\u003e08\u003c/span\u003e社区反应\u003c/h2\u003e\n  \u003cp class=\"sub\"\u003e最近两周以称赞为主，批评集中在细节。\u003c/p\u003e\n  \u003cdiv class=\"grid2\"\u003e\n    \u003cdiv class=\"card\"\u003e\u003cdiv class=\"quote\"\u003e\"pstack is the new solid\"\u003c/div\u003e\u003cdiv class=\"who\"\u003eTaylor Otwell\u003c/div\u003e\u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\u003cdiv class=\"quote\"\u003e原则里有\"非常重要的智慧\"\u003c/div\u003e\u003cdiv class=\"who\"\u003eUncle Bob\u003c/div\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"grid3\" style=\"margin-top:16px\"\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag t\"\u003e移植\u003c/span\u003e\u003cp\u003e有人移植到 \u003ca href=\"https://x.com/monkeyin_92/status/2113105674557411541\"\u003eDeepSeek Harness\u003c/a\u003e 和 Codex。\u003c/p\u003e\u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag w\"\u003e细节批评\u003c/span\u003e\u003cp\u003e有设计师\u003ca href=\"https://x.com/dvsch/status/2113130048668463260\"\u003e不满 \u003ccode\u003e/unslop\u003c/code\u003e 要求把弯引号换成直引号\u003c/a\u003e。\u003c/p\u003e\u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\u003cspan class=\"tag w\"\u003e速度\u003c/span\u003e\u003cp\u003e有用户说 Grok Bot 加云代理\u003ca href=\"https://x.com/chrisdrit/status/2113060804018974833\"\u003e多数时候很慢\u003c/a\u003e，需要人在环路里时宁可开 CLI 自己引导。\u003c/p\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  \u003cp class=\"note\"\u003e最后这条和 Lauren 自己说的\"\u003ca href=\"https://x.com/poteto/status/2107567417316831523\"\u003e开头给足方向，之后放手\u003c/a\u003e\"其实是一回事。\u003c/p\u003e\n\u003c/section\u003e\n\n\u003c!-- 9 --\u003e\n\u003csection id=\"s9\"\u003e\n  \u003ch2\u003e\u003cspan class=\"n\"\u003e09\u003c/span\u003e怎么用\u003c/h2\u003e\n  \u003cp class=\"sub\"\u003e挑着装，先打地基。\u003c/p\u003e\n  \u003col class=\"howto\"\u003e\n    \u003cli\u003e\u003cdiv\u003e\u003ch4\u003e先不装全套\u003c/h4\u003e\u003cp\u003eLauren 自己建议\u003ca href=\"https://x.com/poteto/status/2098637947021205856\"\u003e从零技能开始观察失败模式\u003c/a\u003e。镜像 README 列了 16 个可以单独装的技能，比如 \u003ccode\u003ecorrect\u003c/code\u003e、\u003ccode\u003ein-your-own-words\u003c/code\u003e、\u003ccode\u003earena\u003c/code\u003e、\u003ccode\u003eunslop\u003c/code\u003e。\u003c/p\u003e\u003c/div\u003e\u003c/li\u003e\n    \u003cli\u003e\u003cdiv\u003e\u003ch4\u003e第一件正事是验证技能\u003c/h4\u003e\u003cp\u003e跑 \u003ccode\u003e/create-verification-skill\u003c/code\u003e，重点打磨它生成的 CLI，再让 feature map 覆盖核心路径。在 Claude Code 里，每日维护要自己排程。\u003c/p\u003e\u003c/div\u003e\u003c/li\u003e\n    \u003cli\u003e\u003cdiv\u003e\u003ch4\u003e\u003ccode\u003e/poteto-mode\u003c/code\u003e 只给难任务\u003c/h4\u003e\u003cp\u003e复现型 bug、跨模块设计、性能问题值得用；改文案、小修小补不值得。开头加一句\"不要开大规模子代理\"。\u003c/p\u003e\u003c/div\u003e\u003c/li\u003e\n    \u003cli\u003e\u003cdiv\u003e\u003ch4\u003e在 Claude Code 里补模型多样性\u003c/h4\u003e\u003cp\u003e如果在意 arena、architect、interrogate 的评审质量，让其中一个席位调用外部模型 CLI，否则要接受它们是同一家族的自评。\u003c/p\u003e\u003c/div\u003e\u003c/li\u003e\n    \u003cli\u003e\u003cdiv\u003e\u003ch4\u003e固定版本\u003c/h4\u003e\u003cp\u003e镜像和上游都改得快。团队使用时记下提交号，升级前用自己的几个代表任务对比一下。\u003c/p\u003e\u003c/div\u003e\u003c/li\u003e\n  \u003c/ol\u003e\n\u003c/section\u003e\n\n\u003c!-- 10 --\u003e\n\u003csection id=\"s10\"\u003e\n  \u003ch2\u003e\u003cspan class=\"n\"\u003e10\u003c/span\u003e我的判断\u003c/h2\u003e\n  \u003cp class=\"sub\"\u003e最能直接带走的三样东西，都不依赖 Cursor，也不需要装全套技能。\u003c/p\u003e\n  \u003cdiv class=\"take\"\u003e\n    \u003cdiv class=\"card\"\u003e\u003cb\u003e1\u003c/b\u003e\u003cp\u003e\u003cstrong\u003e验证 CLI + feature map\u003c/strong\u003e这套做法。\u003c/p\u003e\u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\u003cb\u003e2\u003c/b\u003e\u003cp\u003e\u003cstrong\u003e\"能跑出答案的问题不要问人\"\u003c/strong\u003e这条路由规则。\u003c/p\u003e\u003c/div\u003e\n    \u003cdiv class=\"card\"\u003e\u003cb\u003e3\u003c/b\u003e\u003cp\u003e把反复纠正\u003cstrong\u003e沉淀成架构和 lint\u003c/strong\u003e的习惯。\u003c/p\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  \u003cp\u003e它的多代理、多模型部分是为 Cursor 云代理加 Claude/Grok 混合模型设计的。离开这个环境，尤其在纯 Claude Code 本地跑时，并行能力和评审多样性都会缩水，成本却不会等比例下降。唯一的公开第三方对比显示简单任务上贵 40% 且没有收益，难任务上的效果目前只有作者自述。\u003c/p\u003e\n  \u003cdiv class=\"verdict\"\u003e\n    \u003cdiv class=\"k\"\u003e下一步\u003c/div\u003e\n    \u003cp\u003e先花一两天把一个核心功能做成代理能自己跑通、能截图取证的路径，再挑一个反复出现的代理错误用 \u003ccode style=\"background:rgba(255,255,255,.12)\"\u003e/correct\u003c/code\u003e 试一次。这两步做完，就能看出整套 pstack 在自己的代码库里值不值。\u003c/p\u003e\n  \u003c/div\u003e\n\u003c/section\u003e\n\n\u003cfooter\u003e分析日期 2026-10-22 · 产能、质量数字均为作者自述 · 演讲转写由 Whisper 自动生成\u003c/footer\u003e\n\u003c/main\u003e\n\u003c/div\u003e\n\n\u003cscript\u003e\nconst NS=\"http://www.w3.org/2000/svg\";\nconst css=v=\u003egetComputedStyle(document.documentElement).getPropertyValue(v).trim();\nconst tip=document.getElementById('tip');\nfunction el(tag,attrs,parent,text){const e=document.createElementNS(NS,tag);for(const k in attrs)e.setAttribute(k,attrs[k]);if(text!=null)e.textContent=text;parent\u0026\u0026parent.appendChild(e);return e}\nfunction hover(g,html){g.classList.add('hov');g.addEventListener('mousemove',e=\u003e{tip.innerHTML=html;tip.style.opacity=1;tip.style.left=Math.min(e.clientX+14,innerWidth-270)+'px';tip.style.top=(e.clientY+14)+'px'});g.addEventListener('mouseleave',()=\u003etip.style.opacity=0)}\nconst fmt=n=\u003en.toLocaleString('en-US');\n\nfunction hbar(svg,rows,max,opt={}){\n  const W=720,L=opt.left||210,R=70,top=14,h=opt.h||30,gap=opt.gap||14,plot=W-L-R;\n  svg.innerHTML='';\n  [0,.25,.5,.75,1].forEach(t=\u003e{const x=L+plot*t;el('line',{x1:x,x2:x,y1:top-4,y2:top+rows.length*(h+gap)-gap+4,stroke:'var(--grid)'},svg)});\n  rows.forEach((r,i)=\u003e{\n    const y=top+i*(h+gap),w=Math.max(4,plot*r.v/max);\n    const g=el('g',{},svg);\n    el('rect',{x:0,y:y-gap/2,width:W,height:h+gap,fill:'transparent'},g);\n    el('text',{x:L-12,y:y+h/2-2,'text-anchor':'end','font-size':13,'font-weight':600,fill:'var(--ink)'},g,r.label);\n    if(r.sub)el('text',{x:L-12,y:y+h/2+14,'text-anchor':'end','font-size':11,fill:'var(--muted)'},g,r.sub);\n    el('rect',{class:'m gx',style:`--d:${i*.12}s`,x:L,y:y+4,width:w,height:h-8,rx:4,fill:r.hi?'var(--bar)':'var(--bar2)'},g);\n    el('text',{class:'lbl-fade',style:`--d:${.6+i*.12}s`,x:L+w+8,y:y+h/2+4,'font-size':12.5,'font-weight':600,fill:'var(--ink)','font-family':'var(--mono)'},g,r.text||fmt(r.v));\n    hover(g,r.tip);\n  });\n}\n\nhbar(document.getElementById('wordsChart'),[\n  {label:'单个 playbook（最小）',sub:'bug-fix',v:368,tip:'\u003cb\u003ebug-fix playbook\u003c/b\u003e\u003cbr\u003e368 词 · 按任务类型选中后读'},\n  {label:'单个 playbook（最大）',sub:'orchestrate',v:2692,tip:'\u003cb\u003eorchestrate playbook\u003c/b\u003e\u003cbr\u003e2,692 词 · 按任务类型选中后读'},\n  {label:'poteto-mode/SKILL.md',sub:'每次 + 每个子代理',v:3600,hi:true,text:'~3,600',tip:'\u003cb\u003epoteto-mode/SKILL.md\u003c/b\u003e\u003cbr\u003e约 3,600 词 · 每次 /poteto-mode，每个 poteto-agent 子代理也要读'},\n  {label:'24 个原则合计',sub:'应用哪个读哪个',v:5100,text:'~5,100',tip:'\u003cb\u003e24 个 principle-*\u003c/b\u003e\u003cbr\u003e合计约 5,100 词 · 主文件只放索引'},\n],5100,{h:36,gap:14});\n\n(function(){\n  const svg=document.getElementById('agentsChart');const W=720,L=40,base=118,bw=68,gap=12,max=11*3600,H=96;\n  el('line',{x1:L,x2:W-10,y1:base,y2:base,stroke:'var(--line)'},svg);\n  [0,1,2,4,6,8,10].forEach((n,i)=\u003e{\n    const v=(n+1)*3600,x=L+i*(bw+gap+18),h=Math.max(4,H*v/max);\n    const g=el('g',{},svg);\n    el('rect',{x:x-6,y:0,width:bw+12,height:150,fill:'transparent'},g);\n    el('rect',{class:'m gy',style:`--d:${i*.09}s`,x,y:base-h,width:bw,height:h,rx:4,fill:n===0?'var(--bar2)':'var(--bar)'},g);\n    el('text',{class:'lbl-fade',style:`--d:${.5+i*.09}s`,x:x+bw/2,y:base-h-6,'text-anchor':'middle','font-size':11.5,'font-weight':600,fill:'var(--ink)','font-family':'var(--mono)'},g,(v/1000).toFixed(1)+'k');\n    el('text',{x:x+bw/2,y:base+18,'text-anchor':'middle','font-size':11.5,fill:'var(--muted)'},g,n===0?'仅主会话':n+' 个子代理');\n    hover(g,`\u003cb\u003e${n===0?'仅主会话':'主会话 + '+n+' 个子代理'}\u003c/b\u003e\u003cbr\u003epoteto-mode 读取约 ${fmt(v)} 词`);\n  });\n})();\n\n(function(){\n  const svg=document.getElementById('costChart');const L=20,base=128,bw=110,H=96,max=3.455;\n  el('line',{x1:10,x2:390,y1:base,y2:base,stroke:'var(--line)'},svg);\n  [{x:60,v:2.435,l:'不加 pstack',hi:false},{x:230,v:3.455,l:'加 poteto-mode',hi:true}].forEach((d,i)=\u003e{\n    const h=H*d.v/max,g=el('g',{},svg);\n    el('rect',{x:d.x-10,y:0,width:bw+20,height:170,fill:'transparent'},g);\n    el('rect',{class:'m gy',style:`--d:${i*.2}s`,x:d.x,y:base-h,width:bw,height:h,rx:4,fill:d.hi?'var(--bar)':'var(--bar2)'},g);\n    el('text',{class:'lbl-fade',style:`--d:${.7+i*.2}s`,x:d.x+bw/2,y:base-h-8,'text-anchor':'middle','font-size':15,'font-weight':700,fill:'var(--ink)','font-family':'var(--mono)'},g,'$'+d.v.toFixed(3));\n    el('text',{x:d.x+bw/2,y:base+20,'text-anchor':'middle','font-size':12,fill:'var(--ink2)'},g,d.l);\n    el('text',{x:d.x+bw/2,y:base+36,'text-anchor':'middle','font-size':11,fill:'var(--muted)','font-family':'var(--mono)'},g,'15/15 通过');\n    hover(g,`\u003cb\u003e${d.l}\u003c/b\u003e\u003cbr\u003e$${d.v.toFixed(3)} · 15/15 通过`);\n  });\n  el('text',{class:'lbl-fade',style:'--d:1.2s',x:372,y:22,'text-anchor':'end','font-size':13,'font-weight':700,fill:'var(--accent)'},svg,'≈ 1.4×');\n})();\n\n(function(){\n  const svg=document.getElementById('prChart');const W=720,L=60,R=40,top=24,base=170,plot=W-L-R;\n  const d0=new Date('2026-08-10'),d1=new Date('2026-09-30'),sx=d=\u003eL+plot*(new Date(d)-d0)/(d1-d0),sy=v=\u003ebase-(base-top)*v/3000;\n  [0,1000,2000,3000].forEach(v=\u003e{el('line',{x1:L,x2:W-R,y1:sy(v),y2:sy(v),stroke:'var(--grid)'},svg);el('text',{x:L-10,y:sy(v)+4,'text-anchor':'end','font-size':11,fill:'var(--muted)','font-family':'var(--mono)'},svg,fmt(v))});\n  const pts=[{d:'2026-08-19',v:1000,l:'8/19 推文',u:'上个月 1,000 个'},{d:'2026-08-31',v:2000,l:'8/31 Pt. 1',u:'每月 2,000 个'},{d:'2026-09-21',v:2500,l:'9/21 推文',u:'上个月 2,500 个'}];\n  el('path',{d:pts.map((p,i)=\u003e(i?'L':'M')+sx(p.d)+' '+sy(p.v)).join(' '),fill:'none',stroke:'var(--bar)','stroke-width':2,class:'draw',pathLength:1},svg);\n  pts.forEach((p,i)=\u003e{\n    const g=el('g',{class:'lbl-fade',style:`--d:${.3+i*.5}s`},svg),x=sx(p.d),y=sy(p.v);\n    el('rect',{x:x-30,y:top-10,width:60,height:base-top+30,fill:'transparent'},g);\n    el('circle',{class:'m',cx:x,cy:y,r:6,fill:'var(--bar)',stroke:'var(--card)','stroke-width':2},g);\n    el('text',{x,y:y-14,'text-anchor':'middle','font-size':13,'font-weight':700,fill:'var(--ink)','font-family':'var(--mono)'},g,fmt(p.v));\n    el('text',{x,y:base+20,'text-anchor':'middle','font-size':11.5,fill:'var(--muted)'},g,p.l);\n    hover(g,`\u003cb\u003e${p.l}\u003c/b\u003e\u003cbr\u003e${p.u}`);\n  });\n})();\n\n(function(){\n  const g=document.getElementById('ticks');const n=21;\n  for(let i=0;i\u003c=n;i++){const x=10+i*(360/n);const r=document.createElementNS(NS,'rect');r.setAttribute('x',x);r.setAttribute('y',i===n?14:24);r.setAttribute('width',6);r.setAttribute('height',i===n?40:30);r.setAttribute('rx',2);r.setAttribute('class','gy');r.setAttribute('style','--d:'+(i*.04).toFixed(2)+'s');r.setAttribute('fill',i===0?'var(--bar2)':'var(--accent)');r.setAttribute('opacity',i===0?1:(.35+.65*i/n).toFixed(2));g.appendChild(r)}\n})();\n\n// toc + progress\nconst links=[...document.querySelectorAll('nav.toc a')],secs=links.map(a=\u003edocument.querySelector(a.getAttribute('href')));\nconst bar=document.getElementById('progress');\nfunction onScroll(){const h=document.documentElement;bar.style.width=(h.scrollTop/(h.scrollHeight-h.clientHeight)*100)+'%';let i=0;secs.forEach((s,k)=\u003e{if(s.getBoundingClientRect().top\u003c140)i=k});links.forEach((a,k)=\u003ea.classList.toggle('on',k===i))}\naddEventListener('scroll',onScroll,{passive:true});onScroll();\n// reveal on scroll\n(function(){\n  const sel='main section \u003e h2, main section \u003e .sub, main section \u003e p, main section \u003e h3, .card, .flow .step, .rung, ol.howto li, .callout, .cmpwrap, .verdict, .take .card';\n  const items=[...document.querySelectorAll(sel)];\n  items.forEach(e=\u003e{e.classList.add('reveal');const sib=[...e.parentElement.children].filter(c=\u003ec.matches(sel));const k=sib.indexOf(e);if(k\u003e0\u0026\u0026k\u003c8\u0026\u0026!e.style.getPropertyValue('--d'))e.style.setProperty('--d',(k*.07)+'s')});\n  document.querySelectorAll('.ladder,.stats').forEach(e=\u003ee.classList.add('reveal'));\n  if(!('IntersectionObserver' in window)){document.querySelectorAll('.reveal').forEach(e=\u003ee.classList.add('in'));return}\n  const io=new IntersectionObserver(es=\u003ees.forEach(en=\u003e{if(en.isIntersecting){const t=en.target;t.classList.add('in');io.unobserve(t);setTimeout(()=\u003et.classList.remove('reveal'),1600)}}),{threshold:.15,rootMargin:'0px 0px -40px 0px'});\n  document.querySelectorAll('.reveal').forEach(e=\u003eio.observe(e));\n})();\n// count-up hero stats\n(function(){\n  if(matchMedia('(prefers-reduced-motion: reduce)').matches)return;\n  document.querySelectorAll('.stat b').forEach((b,i)=\u003e{\n    const node=[...b.childNodes].find(n=\u003en.nodeType===3\u0026\u0026/\\d/.test(n.textContent));if(!node)return;\n    const raw=node.textContent,m=raw.match(/[\\d,.]+/);if(!m)return;\n    const target=parseFloat(m[0].replace(/,/g,'')),dec=(m[0].split('.')[1]||'').length,comma=m[0].includes(',');\n    const t0=performance.now()+300+i*90,dur=1100;\n    function f(t){const k=Math.min(1,Math.max(0,(t-t0)/dur)),e=1-Math.pow(1-k,3),v=target*e;\n      let s=dec?v.toFixed(dec):Math.round(v).toString();if(comma)s=Number(s).toLocaleString('en-US');\n      node.textContent=raw.replace(m[0],s);if(k\u003c1)requestAnimationFrame(f)}\n    requestAnimationFrame(f);\n  });\n})();\n\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n","default_view":"markdown","version":1,"updated_by":"4e3fvwoonbfzbvqtdwehr2fzdp","updated_at":"2026-10-22T10:34:02Z","assets":[],"base_url":"/pub/pl3gagh2wsbh/p/"},"sources":[],"topic":{"id":"pl3gagh2wsbh","title":"pstack","question":"","visibility":"public","slug":"pstack","hue":243,"emoji":"🧠","owner_id":"4e3fvwoonbfzbvqtdwehr2fzdp","created_at":"2026-10-22T08:09:35Z","updated_at":"2026-10-22T10:34:03Z","published_at":"2026-10-22T10:34:03Z","item_count":0,"report_words":3853,"formats":["markdown","html"],"url":"https://research.sorrycc.dev/@sorrycc/pstack"}}
