☰
读懂 jevgrep 的实现决策清单:从基准计时、请求顺序到发布流水线的 16 项工程取舍
2026/9/30 6:45:08 网站建设 项目流程

【免费下载链接】jevgrep

Find code by asking what it does. A CLI for coding agents that uses Jev to discover relevant files and source context.

项目地址:https://gitcode.com/gh_mirrors/je/jevgrep
点击查看免费下载

choices.md(即 specs/done/jevgrep/choices.md)是 jevgrep 项目中一份特殊的工程文档:它不记录"功能是否验证通过",而是逐条记录实现中已固化的设计决策与其代价——从基准评测的计时口径、跨文件证据的请求顺序,到缓存淘汰策略、发布流水线。本文以该清单为骨架,结合仓库源码逐条展开每个决策的来龙去脉、规则与实现佐证,帮助读者理解 jevgrep 的检索内核(packages/core)为何以当前形态运作,以及未来改动时哪些边界必须被尊重。

这份清单是什么:实现决策台账的定位与用法

清单开篇就划清了边界:它描述的是实现中体现的决策,而非验证状态。jg是安装后的 CLI,Jev 是它调用的相关性分类器(relevance classifier),"Reference" 指被接受的实验性检索实现。三个文档各司其职:

  • 实现记录:拥有闭包决策与测量结论;
  • 修正后的确认:拥有实测结果;
  • 本清单(choices):拥有实现决策本身。

清单按置信度分为两档,并建议优先审阅中置信度的 5 项:基准工作时钟(benchmark work clock)、跨文件证据内部的排序、共享 Python 解释器。它们"保留了预期行为,但制造了未来改动必须尊重的边界"。每一条决策统一用When(何时决策)/ Gap(规范未覆盖的空白)/ Reach(波及范围)/ Verdict(结论)/ Confidence(置信度)/ Owner(责任人文件)六要素记录,阅读时可快速定位"这个坑在哪个文件里"。

中置信度决策:基准计时、请求顺序与解释器边界

基准工作时钟:把"等待检索"与"编码工作"分开计量

When:前瞻性的基准计时的修正。

问题场景:一个编码 Agent 花 12 分钟等待独立的jg搜索,然后花 5 分钟编辑和测试。监控器把这 5 分钟计入其 15 分钟的工作配额。如果搜索期间有其他命令在运行,重叠时间也计为工作;两个搜索并行运行不能获得双倍的等待信用;所有编码 Agent 请求仍计入其账单。若改用墙钟截止时间(wall-clock deadline),Agent 可能为了保住编码时间而取消掉有用的检索。

决策规则:时钟观察的是原生命令启动与结束事件,而非 CPU 使用或 provider 执行时间;模糊的 shell 程序不计入信用;瞬态错误消息不会结束活动命令,命令完成/取消、Agent 报告回合结束或失败、进程退出才会。规则为:

if a recognized search is active and no other command is active: count elapsed time once as retrieval waiting else: charge elapsed time as work

Gap / Reach / Verdict / Confidence:规范要求计时用于诊断但仍需一个失控上限——因此保留独立的 24 小时墙钟守卫;任务容器贯穿 setup 与证据采集,之后 cleanup 删除;宿主机崩溃仍可能遗留一个自有容器。每个新研究冻结自己的计时指令与策略,旧研究保留其原始时钟。结论:对成本/质量目标成立;置信度中,因为观察事件是近似值且指令变更本身是对比的一部分。Owner:installed.py。

源码佐证:该决策与评测实测分离:修正后的十任务队列解决了 6 题、保留 8 个基线解决中的 6 个、取得 4 次成本胜,全 Sol 成本含失败下降 27.30%,但其确认记录仍标记accepted: false;后续同运行时重复(见 variance-repeat.md)以 7 个解决、40.70% 更低成本结束,原始门禁依旧未通过。两份队列都保留全部尝试,禁止 best-cell 池化与基线重跑——这正是时钟规则要保证的"每个尝试独立计量"。

保留请求内部顺序,同时公平比较独立请求

When:参照 harness 与 source-selection 集成。

问题场景:文件 A、B 都产出被选中的源码。如果 B 先完成,它的源码先进入下一个跨文件请求。缓存命中可能改变哪个文件先完成,因此合法地产生顺序不同的后续请求。若按文件名对源码排序,即使每个源码字节都被保留,也会向 Jev(相关性分类器)引入不同的输入。

决策规则:参照 fixture 通过控制"哪个源码被选中"来保证比较稳定;它可以对独立的完整 HTTP 请求排序后再比较,但绝不对请求内部的有序问题或证据排序:

record each request exactly as constructed compare the collection of independent requests preserve every request's internal array and question order

Gap / Reach / Verdict / Confidence:规范未规定 fixture 中如何控制并发参照调用;fixture 相等不等于在线仓库中到达/完成顺序相同。生产环境保留跨文件证据的完成顺序。结论:成立,因为它避免隐藏语义输入的变化;置信度中。Owner:retrieve.ts(文档还指向外部参照测试,本文以仓库内 retrieval.test.ts 作为检索行为测试入口)。

源码佐证:retrieve.ts 中selectEvidence遍历declarations.keys()收集证据,注释明确写着 "Donors follow selection completion order; concurrent completion can affect request context"——完成顺序是有意保留的语义,而非实现巧合;而缓存键也特意"保留请求/问题顺序"(见下文的缓存决策)。

单一 Python 子进程:取消即弃、重放纯检查

When:捆绑 CPython 集成。

问题场景:两个调用方都有待处理的 Python 解析工作。调用方 A 在解释器繁忙时取消。父进程终止该解释器、拒绝 A 的工作,并把 B 仍待处理的请求提交给替代进程。helper 只把源码当作数据来检查,不执行仓库源码、不改文件,因此重放 B 不会重复任何用户动作。每个调用方各一个解释器会消耗更多资源;把解析留在父进程则会让繁忙的同步 helper 更难取消。

决策规则:

on caller cancellation: discard the interpreter process reject requests whose callers cancelled replay other pending, side-effect-free helper requests

Gap / Reach / Verdict / Confidence:要求 Node-only 运行与取消;解释器归属与恢复未规定。包拥有运行时资产与一个子进程,无系统 Python 依赖、无解释器池。结论:成立,因为取消只有一个归属方、重放局限于纯检查;置信度中。Owner:python.ts;python-runtime.md 拥有版本边界。

源码佐证:python.ts 用一个模块级单例runtime持有唯一 worker,stop()在取消时对未取消的 pending 请求调用runPython重放(注释 "Helpers have no side effects; unrelated requests can survive a cancelled interpreter");空闲 worker 通过worker.unref()/channel.unref()不拖住 CLI 生命周期;同一个 Node 子进程宿主同时服务 Node CLI 与 Bun 开发宿主(execPath: process.versions.bun ? "node" : process.execPath)。解析失败走调用方的参照回退(如声明无法解析时用纯文本块),缺资源或子进程失败保持致命;子进程诊断流不能绕过 CLI 的 stdout 策略。

目录枚举顺序与预览顺序分离:只对样本排序

When:文件系统与 discovery 集成。

问题场景:目录名超过一页容量。reader 保持一个打开的游标(cursor,标记枚举继续的位置),按文件系统返回顺序分页返回。空页不等于目录结束——被排除的名字可能占满了那一页。完整展开(full expansion)收集并排序所有条目后再构造请求;预览(preview)则取一个有界的原生顺序前缀、只排序这个样本。若在采样前排序整个目录,Jev 会看到不同的子项集合。

Gap / Reach / Verdict / Confidence:要求有界分页,但 reader 排序未规定;调用方必须区分"游标耗尽"与"刻意的预览截断或分支剪枝",并关闭未用的游标;流式 reader 并不限制收集整个目录的调用方内存。结论:成立,因为它保留了参照的采样区分;置信度中。Owners:filesystem.ts 与 retrieve.ts。

源码佐证:filesystem.ts 的listPage以pageSize: 128为默认分页粒度,游标(Cursor)持有opendir句柄,nextCursor用于续页,closeCursor释放被剪枝的目录;retrieve.ts 的previewDirectory只在收集到预览条目后做entries.sort((a, b) => a.name.localeCompare(b.name)),且受 64 条 / 4096 字节上限截断(preview.truncated = true);而discover的完整展开则对全部条目排序后逐个处理。

保留重叠声明的提问:性能优化不改变分类语义

When:参照恢复(reference restoration)。

问题场景:压缩(minified)文件把多个具名声明放在同一行。参照可以对同一行按每个声明名分别提问。合并这些问题能省工作量,但会改变分类器判断的对象。移植保留问题与可见的请求守卫,而不是假设这些名字冗余。

Gap / Reach / Verdict / Confidence:实现需调和性能顾虑与"保留获胜策略未知贡献"的要求;保留此行为不承诺高效的整机搜索或 minified 源码的最优处理,改变问题分组是独立的检索策略实验。结论:在保留约束下成立;置信度中。Owner:selection.ts。

源码佐证:selection.ts 把源码单元按 "8 个或 14000 字节" 分组为groups,每组作为独立的evidenceRequest提问,每个单元的判定结果以{start}:{end}字节区间为键写入sourceDecisions——同一行上多个声明各自独立评分、互不合并,且value > 0.5才选入selected。

缓存边界:原子发布后扫描淘汰,而非 LRU

When:缓存集成与性能评审。

问题场景:新答案准备保存时缓存接近磁盘上限。缓存先原子发布完整答案,然后按文件系统枚举顺序扫描存储条目,删除超出保留字节预算的条目。这不是 oldest-first 淘汰,也不维护持久化索引或后台清理服务。条目很多时,为大量新答案重复扫描会带来开销;索引式淘汰则是用另一个有状态组件换取这部分工作。

Gap / Reach / Verdict / Confidence:缓存大小上限已定但维护机制开放;存储是尽力而为(best effort),大缓存的写吞吐受重复扫描限制,本机制不做吞吐承诺。结论:作为有披露成本的简单有界存储所有者成立;置信度中。Owner:cache.ts。

源码佐证:cache.ts 中put先写.pending-<uuid>临时文件再rename到entries/<sha256>.json(原子发布),随后trim()用opendir流式扫描,按maxBytes(默认 256 MiB)截断;get校验 schema(schema = 1)、createdAt年龄(默认 TTL 7 天)与全部为有限数字的答案;键是sha256(JSON.stringify([schema, namespace, request]))摘要——只有摘要文件名落盘,源码包与凭据永不为缓存载荷。这正是前文"请求内部顺序"决策的延续:key()注释写明 "Preserve request/question ordering. Only this digest, never the serialized request, reaches disk."。clear()先把当前 entries 目录rename为.cleared-<uuid>原子分离,再清理,因此并发写者可创建新目录,clear 不会暂停其他搜索。

高置信度决策:新鲜度、故障边界与发布流水线

通过同一文件系统策略再验证缓冲源码

When:文件系统集成、跨文件证据处理与新鲜度修正(commit92ca7f9)。

问题场景:请求携带 A、B 的源码排队。等待期间用户编辑了 A 或新增了排除它的 ignore 规则。请求保留 A 的原始内容哈希(content hash,所使用字节的指纹),放在发给 Jev 的数据之外。评估缓冲请求之前、以及每次等待后的 provider 尝试之前,同一个 reader 检查资格并把当前字节与该哈希比对。已变更的源码不能被明知地再次提交。若导航组同时有失效与健康成员,有限分裂(finite splitting)让健康兄弟继续,而不是丢弃整组。

同一规则适用于"一个文件为另一个文件提供上下文":每个不同的源码捐赠者(donor)都被检查,陈旧摘录被移除、结果标记为 incomplete 而已准入的位置仍可用;最终通过还会在角色分类后、对每种语言检查候选。成功缓存复用仍遵循调用方最初的源码校验。规则为:

bind buffered content to its snapshot queue validation in arrival order if a required source changed or became excluded: remove its stale evidence; report incomplete retain independently valid work where possible else: evaluate with the unchanged semantic request before returning, recheck candidate snapshots

Gap / Reach / Verdict / Confidence:新鲜源码要求未定下所有延迟校验点;一个 reader 的策略在其生命周期内固定,改策略需另一个 reader;校验就绪按序排队而 provider 工作保持并发,这不是网络到达/完成顺序的保证;检查是观测而非锁,检查后的变更与已传输的字节无法撤回。结论:对已检测到的变更成立,不声称原子文件系统一致性;置信度高。Owners:filesystem.ts、retrieve.ts、evaluator.ts。

源码佐证:retrieve.ts 的freshEvaluation用validationQueue.then(validate)把unchanged(source)(内容哈希比对)串行排队,beforeAttempt钩子传给 evaluator,使每次 provider 尝试前都重新校验;evaluator.ts 在缓存命中与每次尝试前都调用policy?.beforeAttempt?.();unchanged()发现哈希不符时把该文件证据清空(sourceOmitted: true)并上报changed问题。score中的scoreGroup在source-invalid或可分裂 provider 失败且组多于一项时,把组对半分裂重新入队,让健康兄弟继续评分。

把缓存故障与缺失检索证据分离

When:缓存集成。

问题场景:缓存条目损坏或目录不可读。查询改问 provider 并报告缓存警告;若 provider 提供了所需答案,检索仍可完整。把缓存失败本身当作缺失源码,会把健康结果错误标记为 incomplete。

存储条目包含经校验的数值答案、标识格式的 schema 号与创建时间;精确请求与命名空间(模型、provider、parser/prompt/policy 身份)仅由摘要文件名表示,源码包与凭据不是缓存载荷。清缓存先把当前 entries 目录改名移走再删除;并发写者可建新目录,因此 clear 不暂停其他搜索、也不承诺移除其稍后的写入。

Gap / Reach / Verdict / Confidence:结果 schema 需区分持久化故障与检索失败;并发 clear 需归属规则。调用方必须把警告与 incomplete 证据问题分开保存;缓存答案保持可弃,不兼容格式直接丢弃而非迁移。结论:成立,因为缓存加速检索而不成为其事实源(source of truth);置信度高。Owner:cache.ts。

源码佐证:cache.ts 的get对超限文件、解析失败、schema 不符、答案非法分别warn("cache_corrupt"),对读失败warn("cache_unavailable"),全部按 miss 处理;evaluator.ts 把cacheIssues暴露为options.cache?.stats().issues,而 retrieve.ts 的返回对象把warnings: evaluator.cacheIssues与issues(incomplete 依据)分开存放——两个集合在输出上不混淆。

认证失败时取消查询的兄弟请求

When:provider 故障集成。

问题场景:一个请求收到拒绝密钥的响应,另一个兄弟请求正在重试前休眠。evaluator 拥有一个共享的认证失败取消信号,于是休眠的兄弟与其他在途工作停止使用该密钥。调用方自身的取消仍是独立原因。没有共享信号,兄弟请求会在查询已知密钥不可用后继续等待或发更多请求。

Gap / Reach / Verdict / Confidence:需要整查询的认证失败语义,取消归属未规定;每个请求与重试等待必须同时监听调用方取消与共享认证信号。结论:成立,因为一次认证失败不能让兄弟请求独立消耗工作;置信度高。Owner:evaluator.ts。

源码佐证:evaluator.ts 持有模块级const authenticationFailure = new AbortController(),evaluate捕获 401/403 时authenticationFailure.abort()并抛EvaluationFailure("authentication");stopped = AbortSignal.any([options.signal, authenticationFailure.signal])同时驱动等待队列拒绝与 rate-limit 冷却等待的中断;每次实际网络请求前的assertActive()都检查两个信号。

中断保留已获取证据,失效才移除

When:部分结果与取消集成。

问题场景:用户在第一组声明返回有用源码后、第二组完成前中断。结果保留已获取证据并标记 interrupted。取消本身不是文件已变更的证据;只有新鲜度检查发现不同或新排除的源码时,该文件的陈旧证据才被移除。混淆两种情况会在用户停止搜索时丢弃有用的部分结果。

Gap / Reach / Verdict / Confidence:取消与快照变更在同一个准备边界相遇,但要求对存储证据产生不同效果;后续准备路径必须保留该区分,部分输出不能声称完整发现或原子文件系统快照。结论:成立,因为停止原因决定哪些证据仍可用;置信度高。Owners:selection.ts 与 retrieve.ts。

源码佐证:retrieve.ts 在取消时issue("cancelled")并最终以input.signal.aborted ? "interrupted" : issues.size ? "incomplete" : "complete"决定状态;已在filesmap 中形成的证据不会被清空;而unchanged()发现哈希不符才把文件证据重置为sourceOmitted: true。selection.ts 的selectFile接收previous?: FileEvidence,仅当previous.path !== snapshot.path || previous.contentHash !== snapshot.contentHash才warn("changed")并丢弃 previous——否则在上一轮已选区间(selected)、leads 与sourceDecisions上继续增量推进。

从 workspace 发现中排除废弃评估包

When:workspace 切换(cutover)。

问题场景:开发者运行普通 workspace 安装或测试命令。根 manifest 显式包含 core 与 TypeScript 配置,因此一个旧的个人仓库 eval 包不会只因"摆在旁边"就被发现。历史本地文件仍可用,受支持根命令指向官方工作流;保留宽泛的 package glob 会让废弃工具重新加入日常构建。

Gap / Reach / Verdict / Confidence:移除废弃入口未规定 workspace 发现;新包必须被刻意添加。结论:成立,因为本地历史证据不应因邻近而成为活跃依赖;置信度高。Owner:package.json。

源码佐证:根 package.json 的workspaces.packages显式列出apps/*、packages/core、packages/typescript-config,而非packages/*——这正是"新包必须显式加入"的机制体现。

每次请求构建都强制重建捆绑代码与 skill

When:打包集成。

问题场景:开发者改了规范 skill 或 core 模块后构建 CLI。可执行文件嵌入了两者,即使它们位于 CLI 包之外。构建缓存被禁用,因此构建不能复用"其受跟踪输入遗漏了该变更"的可执行文件;缓存的构建需要完整的跨包输入跟踪才能做出同样的保证。

Gap / Reach / Verdict / Confidence:规范未选择开发构建缓存;构建做更多工作,但输出反映当前源码与 skill 内容,这不替代对产物的检查。结论:成立,因为陈旧的嵌入 skill 会改变已安装行为;置信度高。Owners:turbo.json 与 scripts/build-cli.ts。

源码佐证:规范 skill 唯一权威源是 skills/jevgrep/SKILL.md(contracts.md 要求"随 npm 包携带同一文件,不维护第二份手写副本"),构建脚本把它与 core 一并嵌入 CLI。

从捆绑输入派生许可证通知,固定外部运行时出处

When:发布打包。

问题场景:JavaScript bundle 新增一个依赖。Bun 的 emitted-input 元数据告诉通知生成器哪些已安装包贡献了代码,其许可证文本进入包。若贡献包无许可证文本,构建失败,除非保留精确版本的上游覆盖。手抄静态清单可能漏掉新捆绑的依赖。

单独安装的 Pyodide 运行时含编译组件,无法从 JS bundle 元数据发现;其组件通知与源码链接被单独固定,区分 npm 元数据与上游许可证。运行时升级不得静默继承未经检查的通知集。Jevgrep 自身的 MIT 许可证与这些依赖保持分离。

Gap / Reach / Verdict / Confidence:要求许可证,但收集方式与缺失上游文件处理未规定;依赖变更可能需要通知评审,普通构建读取保留文本而非下载许可证。结论:成立,因为通知归属跟随"实际分发什么";置信度高。Owners:scripts/package-notices.mjs 与 scripts/licenses/README.md(后者目录下保留 Apache-2.0、bzip2、CPython、emscripten、pyodide、zlib 等完整文本与来源记录)。

发布一个归档,再单独验证注册表上的精确版本

When:发布工作流集成。

问题场景:发布标签命名一个版本。工作流校验标签/版本一致、打包一个归档、测试它、试运行发布并发布同一字节。另一个独立 job 从 npm 取回该精确版本,比较其完整性(标识归档的哈希)并再次运行已安装旅程。注册表验证失败时可重试该 job,无需重新发布不可变版本。稳定版本用latest,预发布用next。

Gap / Reach / Verdict / Confidence:用户选择了标签触发的发布与密钥,而产物身份、渠道选择与发布后 job 布局需要实现决策;发布检查跟随一个归档走完发布流程,本工作流自身不授权标签或发布。结论:成立,因为构建时与注册表安装时的声明保持分别可查;置信度高。Owner:.github/workflows/publish.yml。

将基准队列绑定到单一安装包

When:受维护的基准 runner 集成。

问题场景:准备阶段安装一个包,并为队列中的每个 cell(一次任务尝试)冻结其字节、skill、安全任务输入、数据集与 runner 源码。runner 停止时保留现有尝试;终态尝试不被静默替换。新研究获得不同身份,不能借用旧候选的廉价结果。保存的基线 Agent 在此 runner 中没有执行路径。

Gap / Reach / Verdict / Confidence:要求不可变比较,但尝试存储与生命周期机制未规定;所有结果与未完成账单保持可见,小型诊断研究不能代替完整队列;schema 变更保留旧研究与归档 runner,而非重新解释。结论:成立,因为产物与尝试身份阻止结果池化;置信度高。Owner:installed.py。

复用已安装旅程做原生 macOS 检查

When:受支持平台集成。

问题场景:Mac 可能已装 Python 与开发工具。native harness 在临时 npm prefix 安装 tarball,再用仅含 Node 的运行时 PATH 运行已安装 CLI。它复用 Docker 测试中的本地命令与 Python HTTP 搜索旅程,使用临时凭据与缓存。这样系统 Python 无法悄悄满足缺失的产品依赖。

Gap / Reach / Verdict / Confidence:规范要求原生 Mac 证据但未规定 harness;共享可移植旅程避免各自的平台预期。Docker 的文件系统与故障覆盖不声明用于更窄的原生冒烟测试;结果标识实际运行时与归档。结论:成立,因为安装边界被真实演练而不借用检出工具;置信度高。Owner:scripts/test-native.mjs。

阅读清单的三种姿势与三条主线

如何阅读:若你关注评测可信度,先读基准工作时钟与基准队列绑定两条;若你关注检索正确性,读请求顺序、目录枚举与预览分离、缓冲源码再验证、中断与失效区分四条;若你关注发布与运维,读构建重建、许可证派生、发布验证、原生检查四条。

三条贯穿主线:

  1. 保真高于优化:请求顺序、声明提问、预览排序都坚持"不给 Jev 引入不同的输入",性能优化让位于参照策略的语义保真;
  2. 边界归属单一:文件系统 reader、evaluator、cache、selection 各有一个 owner,取消、认证、失效各有唯一归属方,避免共享可变状态;
  3. 诚实的结果标记:incomplete 与 interrupted 被严格区分,缓存故障不等于缺失证据,健康空结果与失败评估截然不同——这些语义全部在 contracts.md 中固化为公开契约。

想继续深入,可顺藤摸瓜:实现记录(闭包决策)、决策地图(用户约束与访谈依据)、研究记录(冻结获胜者与相邻实验的区分),以及 runtime 依据 与 release 证据 两份实测文档。

【免费下载链接】jevgrep

Find code by asking what it does. A CLI for coding agents that uses Jev to discover relevant files and source context.

项目地址:https://gitcode.com/gh_mirrors/je/jevgrep
点击查看免费下载

相关推荐

上一篇:为什么选择selecsls42b.in1k?ImageNet-1k训练的4.6M激活值模型优势解析
下一篇:如何用WoWmapper彻底改变你的《魔兽世界》游戏体验:从键鼠到控制器的完美转换

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询