# Agent Note: 跨目录树采样超出上限的 glob 结果

Status: implemented

[English](2026-07-27-glob-sampling.md) | 中文

## 问题

用户询问工作区包含什么内容时，一个 agent（智能体）把某个子文件夹描述成了整个项目。该工作区有 22 个顶层条目和 11,485 个文件。`glob {"pattern":"*"}` 匹配到 10,030 条路径，但内联显示的 100 条路径全部位于一棵近期解压的子树中，因此模型完全没有看到其余 21 个条目。

三个单独看都合理的行为叠加后造成了错误印象。不含 `/` 的 glob 会匹配任意深度的文件名，因此 `*` 表示目录树中的每个文件，而不是 shell 对当前目录执行的展开。Ripgrep 的 `--sort=modified` 按升序排列，因此归档包还原出的旧时间戳会让该子树排在最前。随后，内联页面直接截取这一顺序的前部，却没有说明它只代表集中于一处的切片。

## 决策

未超过 `globMaxResults` 的结果仍保持完整，且按修改时间排序的内容逐字节不变。必填的 `sampleOverCapGlobResults` 配置没有回退值：`false` 会为超过上限的结果保留按修改时间排序的前部，`true` 则会在完整结果的顶层条目之间按轮转方式采样。采样模式下，每个条目都先获得一个位置，之后才有条目获得第二个位置；已经用尽的分组会退出轮转；各组内部的相对顺序保持稳定；分组以实际搜索根为基准，显式指定 `path` 时也如此。

采样模式下，footer 会说明当前页面是跨条目的样本，而不是按修改时间排序的前部；当触达的顶层条目数能提供额外信息时，还会报告该数量。若顶层条目数量超过内联位置数，footer 会要求模型缩小 `path`。保留前部的模式沿用达到上限时的普通 footer。spill 成功时，两种模式都会在该产物中保留完整排序列表。

提示词与 schema 会说明配置所指定的超限结果排序方式、不含 `/` 的模式会匹配任意深度，以及 glob 只返回文件而绝不返回目录条目。随产品交付的 CLI（命令行界面）组合显式选择保留前部的模式；希望达到上限的页面具有代表性的部署则选择采样模式。在向模型暴露 bash 工具的部署中，目录定位仍由普通 shell 操作完成：查看一个目录使用 `ls`，跨目录树按指定文件路径模式查找则使用 glob。skill（技能）发现流程仍将 `ctx.fs.listDir` 作为内部提供方原语使用；本决策不会新增面向模型的 `list` 工具。

## 考虑过的替代方案

**只保留按修改时间排序的前部。** 测量实际故障形态后否决。某些部署需要这种稳定排序；但重视工作区定位的部署可以显式选择具有代表性的数据，而不必要求模型怀疑自己拿到的唯一一批路径。

**为采样选项提供默认值。** 否决。没有全产品范围的证据支持把任一排序作为隐式契约，因此每个组合都必须选择一种，配置错误则在加载时失败。

**对所有结果采样。** 否决。完整结果没有因截断损失任何信息，因此按修改时间排序仍有助于回答关注新旧时间的问题。只有当截取前部已经无法描述整体时，才开始采样。

**改为最新优先排序。** 否决。这只会改变哪一棵结果集中的子树可能占据主导；既取消了现有的最旧优先契约，也没有让受限页面更具代表性。

**仅在偏斜超过阈值时采样。** 否决。目前没有证据支持适用于所有部署的统一阈值，模型也无法判断当前采用的是哪一种排序契约。现有上限是可以清楚解释的切换点。

**在顶层以下递归平衡。** 暂缓。按第一路径段做平衡已经修复观测到的故障；更深层的平衡需要一套尚无依据的深度与广度取舍策略。

**新增面向模型的 `list` 工具。** 实现评审后否决。默认编程组合已经提供通用 bash，模型也理解 `ls`；重复工具会永久增加 schema 与提示词所占的 token，并引入排序、分页、符号链接、转义、UI 与快照契约，却没有独立的安全或策略收益。不向模型提供 bash 工具的精简部署也不会因本次改动获得目录定位能力。

**拒绝 `*`，或在不含分隔符的模式前静默加上根目录锚点。** 否决。同样的「在任意深度匹配文件名」行为使 `*.ts` 可以有效地跨目录树搜索。记录这条规则能够保留正常工作的 Ripgrep 语义。

## 影响

采样模式下，超过上限的 glob 页面无法再根据内联路径回答按时间判断新旧的问题；footer 会明确说明这一点，spill 产物仍保留完整的排序视图。采样只平衡搜索根下的第一路径段，因此某个顶层条目内部较深处、结果密集的子树仍可能占据主导。保留前部的模式则把集中风险作为显式部署取舍保留下来。

工具接口不会扩大。每个组合都必须设置 `sampleOverCapGlobResults`；更改该值会改变 glob 的提示词、schema 描述以及超过上限时的 Native 渲染。规范输出保留 `root`，以便采样模式恢复其分组基准；未超过上限的结果保持不变。

## 测试

包测试锁定了必填配置、两种超过上限模式及其提示词和 schema 描述、结果集中与扁平两种情况、显式根目录、分组数超过 JavaScript 参数个数上限、分组耗尽、位置数少于分组数，以及工作目录以外的路径。`fs-glob-sampling` ACP（Agent Client Protocol）场景会显式启用采样，启动最小化的真实 Loader/app/local-bash 组合，并让真实搜索插件对接确定性的 `rg` 进程 fixture（测试前置数据）；其结果覆盖 4 个顶层条目，而不是只返回某棵子树的前部。
