
Ponytail 的「平台原生方案」对照手册在安装任何依赖之前先查这里【免费下载链接】ponytailMakes your AI agent think like the laziest senior dev in the room. The best code is the code you never wrote.项目地址: https://gitcode.com/GitHub_Trending/po/ponytail在 AI Agent 编程的语境下为了一个功能顺手装一个包是最常见的过度工程来源。Ponytail 把团队里最懒的那位资深开发装进了你的 Agent让它写代码前先走一遍七级决策阶梯而 docs/platform-native.md 正是回答阶梯第四级平台是不是已经内置了这个功能的速查手册。读完本文你将掌握如何按 HTML、CSS、JavaScript/浏览器 API、Swift/SwiftUI、Node.js、Python、数据库七个层面把你以为需要某个库的需求映射回平台自带的原生能力以及这套判断标准背后的模式与边界——什么时候库才真正挣得了一席之地。它在 Ponytail 决策阶梯中的位置Ponytail 的核心规则定义在 AGENTS.md 中写任何代码之前停在第一级成立的阶梯上1. Does this need to be built at all? → 不需要就直接跳过YAGNI 2. Already in this codebase? → 复用已有工具/模式 3. Stdlib does it? → 用标准库 4. Native platform feature? → 用平台原生能力 5. Installed dependency? → 用已安装的依赖 6. One line? → 能一行就一行 7. Only then: the minimum that works → 最后才写能工作的最少量代码skills/ponytail/SKILL.md 中第 4 级的示例就是 platform-native.md 的缩影input type\date\优于一个日期选择器库CSS 优于 JS数据库约束优于应用层代码。docs/platform-native.md就是把这条阶梯查表化的产物文档开篇的定位是在伸手去装包之前先扫一遍这里。平台自带的能力是免费的、不会在升级时坏掉而且编写者的工作就是解决这类问题。README 里给出的标志性例子也出自这份清单让你做一个日期选择器没有 Ponytail 的 Agent 会安装 flatpickr、写一个包装组件、加一份样式表然后开始讨论时区装上 Ponytail 之后产出只有一行!-- ponytail: browser has one -- input typedate下面是 platform-native.md 的完整内容继承与扩充。HTML 元素浏览器早已内置的表单控件文档给出的第一张对照表——你以为需要的东西 vs 平台实际已经提供的东西你以为你需要平台已经有什么日期选择器库input typedate时间选择器库input typetime颜色选择器库input typecolor范围滑块库input typerange进度条组件progress value70 max100仪表/量规组件meter value0.7模态框/对话框库dialogdialog.showModal()手风琴/FAQ 组件detailssummary标题/summary…/detailsTooltip 库title属性 CSS::before/::after可搜索下拉框input listiddatalist idid自动增高 textareafield-sizing: contentCSS吸顶标题栏position: sticky; top: 0CSS值得展开的两行details/summary是免费的折叠面板自带展开/收起状态与可访问性语义不需要任何状态管理代码dialog配合showModal()提供焦点陷阱与模态行为替代掉一个对话框库要手工维护的逻辑。仓库的示例目录里有一组由真实基准测试模型输出Claude Haiku 4.5无技能 vs 有技能整理的对照案例见 examples/其中 modal-dialog.md 正是对话框库 vsdialog的逐行对照。CSS 能力那些你本来想写 JavaScript 干的事文档第二张表方向反过来了很多需求你以为需要 JS其实 CSS 就能做你以为需要 JS 的事CSS 有什么响应式字号font-size: clamp(1rem, 2.5vw, 2rem)流式间距padding: clamp(1rem, 5vw, 3rem)深色模式media (prefers-color-scheme: dark)减弱动效media (prefers-reduced-motion: reduce)无断点响应式布局grid-template-columns: repeat(auto-fill, minmax(250px, 1fr))组件级响应式设计container查询全局设计令牌/主题CSS 自定义属性--color-primary: #7c3aed平滑滚动scroll-behavior: smooth滚动吸附轮播scroll-snap-type: x mandatoryscroll-snap-align: start宽高比强制aspect-ratio: 16 / 9省略号截断文本overflow: hidden; text-overflow: ellipsis; white-space: nowrap多行文本截断-webkit-line-clamp: 3CSS 级联层样式隔离layer base, components, utilities嵌套 CSS 选择器原生 CSS 嵌套无需预处理器has()父选择器:has(input:checked)这张表的价值在于它直接回答了该不该写一段 JS 监听/计算逻辑clamp()让字号与间距随视口线性变化而不用resize监听器auto-fill minmax让网格卡片数量随容器宽度自动增减省掉断点判断container把响应式从视口下沉到组件容器级别prefers-reduced-motion是可访问性需求用一行媒体查询就覆盖了。JavaScript / 浏览器 API运行时已随附的库文档第三张表针对的是人们会安装、但运行时早已内置的库你以为你需要平台已经有什么query-string/qsnew URLSearchParams(location.search)lodash.clonedeepstructuredClone(obj)lodash.groupbyObject.groupBy(arr, fn)lodash.debounce见下方防抖一行流numeral/accountingnew Intl.NumberFormat(en-US, { style: currency, currency: USD })date-fns格式化new Intl.DateTimeFormat(en-US, { dateStyle: long }).format(date)date-fns相对时间new Intl.RelativeTimeFormat(en, { numeric: auto }).format(-3, day)plural/ i18n 复数规则new Intl.PluralRules(en-US).select(count)clipboard.jsnavigator.clipboard.writeText(text)uuidv4crypto.randomUUID()无限滚动库new IntersectionObserver(cb).observe(sentinel)Resize 监听库new ResizeObserver(cb).observe(element)DOM 变更监视器new MutationObserver(cb).observe(el, options)uuid-validate/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id)is-online/ 网络检测navigator.onLineonline/offline事件分享面板库navigator.share({ title, text, url })store.js/localForage简单场景localStorage.setItem(key, JSON.stringify(val))fetch 超时中止传给fetch的AbortSignal.timeout(5000)自定义事件总线new EventTarget()/dispatchEvent(new CustomEvent(x, { detail }))文档同时给出了不带任何库的防抖一行流// ponytail: 3 行代码胜过一个依赖 let t; const debounce (fn, ms) (...args) { clearTimeout(t); t setTimeout(() fn(...args), ms); };仓库的 examples/ 目录为其中几个条目提供了可复现的实证真实模型输出非手写可用npx promptfoo eval -c benchmarks/promptfooconfig.yaml复现URL 参数examples/url-params.md无技能一臂npm install query-string后用它解析/构造查询串有技能一臂直接用URLSearchParams读取用params.get(page)、params.getAll(tags)构造用out.append()后toString()。结论是1 个依赖 → 0 个依赖URLSearchParams处理了编码、重复键与迭代。深拷贝examples/deep-clone.mdstructuredClone(original)替代lodash的cloneDeep或JSON.parse(JSON.stringify())这种会丢失Date、Map、Set、循环引用的脆弱写法。示例注明structuredClone覆盖Date、Map、Set、ArrayBuffer、RegExp、循环引用浏览器自 2022 年起、Node.js 自 v17 起可用——等真正需要 lodash 其余能力时再引入而不是为了一个函数。分组examples/group-by.mdObject.groupBy(orders, order order.status)一行替代lodash或手写reduce。示例特别提醒了运行时基线Object.groupBy需 Chrome 117 / Firefox 119 / Safari 17.4 / Node.js 21目标是 IE11 或旧 Node 时reduce一行流仍是正确选择——而不是 lodash。无限滚动examples/infinite-scroll.mdIntersectionObserver观察一个哨兵元素进入视口才触发加载无 scroll 事件、无需节流库包装的恰好就是这个 API。防抖examples/debounce.md同一模型、同一提示词无技能一臂输出 116 行基础版 加载态增强版 带 cancel/immediate 的高级版 HTML/CSS有技能一臂 10 行setTimeoutclearTimeout就是防抖本身等到需要在 3 个以上输入框复用时再抽工具函数。Swift / SwiftUIUI 组件与标准库包装文档的第四、五张表面向 iOS/macOS。UI 层面你以为你需要平台已经有什么日期/时间选择器库DatePicker颜色选择器库ColorPicker搜索栏 过滤.searchable(text:)下拉刷新库.refreshable { }滑动删除/行操作.swipeActions { }异步图片加载 缓存AsyncImage图表库Swift Chartsimport ChartsMarkdown 渲染Text(...)markdown /AttributedString(markdown:)分享面板包装ShareLink加载转圈ProgressView()照片选择器PhotosPicker地图 SDK基础MapSwiftUI 的 MapKit网格布局库Grid/LazyVGrid框架与标准库层面——包装器们在包装的东西你以为你需要平台已经有什么JSON 库SwiftyJSONCodableJSONDecoder/JSONEncoderHTTP 客户端Alamofire简单用法URLSessionasync/await复杂重试/多部分上传的规模下 Alamofire 才挣得位置日期/数字/货币格式化.formatted()/FormatStyle正则库Swift 正则字面量 Regex加密库CryptoSwiftCryptoKitKeychain 包装SecuritySecItem几行代码不是一个依赖持久化/ORMSwiftData小量键值对用AppStorage日志库Loggeros.logUUID / Base64 工具UUID()、Data(...).base64EncodedString()图片降采样ImageIOCGImageSourceCreateThumbnailAtIndexCombine 异步包装async/await AsyncSequence注意第二张表里对 Alamofire 的措辞Alamofire earns it for complex retry/multipart at scale在复杂重试/多部分上传的规模下它才挣得位置——这与文档结尾库何时合格的判据完全一致不是不许用库而是到挣得位置的那一刻再用。Node.js 标准库包装内置模块的包文档第六张表你以为你需要Node 已经有什么mkdirpfs.mkdirSync(path, { recursive: true })rimraffs.rmSync(path, { recursive: true, force: true })make-dirfs.mkdirSync(path, { recursive: true })slashWindows 路径path.posix或path.normalize()uuidv4crypto.randomUUID()ms解析时长字符串保留ms它确实有用且体积极小is-streamval instanceof stream.Readableobject-assignObject.assign()/ 展开语法array-uniq[...new Set(arr)]array-flattenarr.flat(Infinity)flatarr.flat(depth)path-existsfs.existsSync(path)load-json-fileJSON.parse(fs.readFileSync(path, utf8))write-json-filefs.writeFileSync(path, JSON.stringify(obj, null, 2))pkg-dirpath.resolve(__dirname, ..)/import.meta.dirname这张表里最值得玩味的一行是ms保留ms它确实有用且体积极小。Ponytail 的规则不是教条式零依赖而是按这个包是否只是对内置能力的一层薄包装、是否引入了你会替它调试的代码来判断——纯薄包装mkdirp、path-exists、array-uniq被拒绝小而真正补位的工具被保留。skills/ponytail/SKILL.md 中的对应规则是两种标准库写法体量相同时选边界情况正确的那个——懒意味着写更少代码不是选更脆弱的算法。Python 标准库Python 早已随附的东西文档第七张表你以为你需要Python 已经有什么python-dateutil基础解析datetime.fromisoformat()Python 3.7pytzzoneinfo.ZoneInfo(America/New_York)Python 3.9attrs简单数据类dataclasssix删掉它Python 2 已经消失pathlib2pathlib.Path3.4 起内置enum34enum.Enum3.4 起内置typing_extensions常见类型from __future__ import annotations 内置泛型simplejson基础用法json标准库requests简单 GETurllib.request.urlopen(url)真实场景用requestsclick单命令argparse标准库mergedeepdict \| other_dictPython 3.9more-itertools基础itertools标准库chain、islice、groupby、producttoolz基础functoolslru_cache、partial、reducetabulate仅开发/调试pprint.pprint()快速检查这张表同时给出了版本前提3.7/3.9和例外任何真实场景用requests、删掉six与 Node 表对ms的处理同一风格按运行时版本和需求复杂度分情况而不是无差别拒绝第三方包。数据库应用层实现的数据库早就做了文档第八张表把判断标准延伸到数据层——你以为需要应用代码做的事数据库本身就会你以为需要应用代码数据库已经有什么offset/limit 分页LIMIT 20 OFFSET 40累计值SUM(...) OVER (ORDER BY date)窗口函数组内排名RANK() OVER (PARTITION BY category ORDER BY score DESC)透视/交叉表FILTER (WHERE ...) 条件聚合去重SELECT DISTINCT/ON CONFLICT DO NOTHING软删除过滤生成列 部分索引树遍历递归 CTEWITH RECURSIVE全文搜索基础tsvector/MATCH AGAINST/FTS5JSON 存储 查询jsonbPostgres /JSON_EXTRACTSQLite/MySQLUUID 生成gen_random_uuid()Postgres /UUID()MySQL插入/更新时间戳DEFAULT now() 触发器或ON UPDATE CURRENT_TIMESTAMP强制唯一性UNIQUE约束而不是应用层检查强制引用完整性FOREIGN KEY而不是应用层检查强制取值范围CHECK (price 0)而不是应用层校验最后一行的取舍标准值得注意Ponytail 从不砍掉校验本身只主张把唯一性/外键/范围这类不变量放在数据库约束里而不是散落在应用代码中——约束天然覆盖所有写入路径而应用层检查会随调用方增加而漏。这与 AGENTS.md 中信任边界处的输入校验、防数据丢失的错误处理、安全性、可访问性永远不在砍掉之列的底线一致懒在方案体量不懒在正确性。The Pattern为什么包装器终会抛下你文档收尾给出贯穿所有层的同一个模式平台团队花数年解决这个问题。 包作者把它包了一层。 你装下这个包装。 包装不再被维护。 你在调试这个包装。跳过包装平台能力随你的应用免费提供。文档最后给出了库的合格线当原生方案确实不够用时需要兼容旧浏览器、存在它处理不了的边界情况、规模上来后人体工学真正重要这个库就挣得了它的位置——到那时再装而不是之前。放回 Ponytail 的规则体系看这正是决策阶梯第 4 级与第 5 级之间的分界线原生能力不够才轮到已安装的依赖再不够才考虑新增依赖——而新增的门槛是几行代码能解决的事绝不为此新增一个。配套的落地手段还包括AGENTS.md 要求对刻意的、带已知天花板的简化打上ponytail:注释写明上限与升级路径/ponytail-audit命令则可以对整个仓库反向审计过度工程见 commands/ponytail-audit.toml。如何把这份手册用起来作为人工查表在npm install/pip install/pod install之前按本文七张表先扫一遍对应技术栈表中你以为你需要一列就是最常见的过度工程入口。作为 Agent 规则Ponytail 通过各宿主Claude Code、Codex、OpenCode、Gemini CLI 等安装方式见 README.md 的 Install 一节把决策阶梯注入每个会话Agent 会在第 3、4 级停住并优先选择原生方案examples/ 目录保留了同一模型、同一提示词在无技能/有技能两臂下的逐字输出可作为该行为的实证样本。适用前提表中 API 均有运行时基线如Object.groupBy需 Node 21/较新浏览器、field-sizing依赖新版浏览器、zoneinfo需 Python 3.9。目标运行时更老时文档给出的替代是一行标准库写法如reduce手写分组而不是旧版第三方包——库挣得位置的前提永远是原生方案在该运行时下确实不够用。输出文章结束/输出文章 /输出文章 /输出文章【免费下载链接】ponytailMakes your AI agent think like the laziest senior dev in the room. The best code is the code you never wrote.项目地址: https://gitcode.com/GitHub_Trending/po/ponytail创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考