diff --git a/AGENTS.md b/AGENTS.md index 3a2abca..1ec57bf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,7 +20,7 @@ | `pi-notify/` | Kitty OSC 99 完成与权限确认通知,精确聚焦来源窗口 | | `pi-compaction/` | 压力触发的观察遮蔽(Pi context_edit)、阈值整段摘要、effective token、native compaction | | `pi-overflow/` | 新工具结果统一截断:超阈值原文落盘 + 有界视图 + `overflow_query` | -| `extensions/fff-override.ts` | FFF `override` 模式接管 `find`/`grep`/`multi_grep` 与 `@` 补全 | +| `extensions/fff-override.ts` | FFF `override` 模式接管 `find`/`grep` 与 `@` 补全,`multi_grep` 按上游保持关闭 | | `extensions/codegraph.ts` | 原生 `codegraph_explore`,自有 stdio JSON-RPC 直连 `codegraph serve`(`codegraph-client.ts`) | | `extensions/hashline.ts` | 部署 `config/pi-hashline-edit.json` 后加载 pi-hashline-edit 覆盖 `read`/`edit`(`hashline-config.ts`) | | `extensions/permission-system.ts` | 直接加载仓库内 `pi-permission-system/src/index.ts` | diff --git a/README.md b/README.md index b0768e3..5691605 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ 个人维护的 Pi 扩展组合包。安装一次即可加载并配置: -- `@ff-labs/pi-fff@0.10.5`:使用官方 `override` 模式接管 `find`、`grep` 和 `multi_grep`。 +- `@ff-labs/pi-fff@0.10.5`:使用官方 `override` 模式接管 `find` 和 `grep`;上游默认关闭的 `multi_grep` 保持关闭。 - 本仓库维护的 `pi-rtk-optimizer`:只处理 Bash/read 等输出压缩,默认不改写命令,也不处理搜索工具结果。 - 本仓库自维护的 `pi-web-search`:对模型只暴露 `web_search` / `web_fetch` 两个工具;`web_search` 由当前主模型在 Tavily / Exa / Keenable 间路由,`web_fetch` 固定走 Exa,三家均以纯 `fetch` 直连(Exa 为 `mcp.exa.ai` 的 JSON-RPC,不经 MCP adapter)。 - `extensions/codegraph.ts`:注册原生 `codegraph_explore` 工具,按索引根惰性启动常驻 `codegraph serve --mcp` 子进程,由组合包自有 stdio JSON-RPC 客户端直连(无 MCP adapter/SDK);serve 的文件监听自动同步索引,无结果缓存;未初始化项目经确认后才 `codegraph init`,拒绝记入会话不再重复询问。 @@ -138,7 +138,7 @@ CodeGraph 的更新或遥测设置。 ### 工具与搜索路由 -`config/prompt/routing.jsonc` 定义跨工具路由规则,由 `extensions/system-prompt.ts` 在每轮开始前按当前激活工具渲染为 `` 分区。代码结构、调用关系和待修改 symbol 优先使用 CodeGraph,定义、引用、类型和修改后诊断优先使用 LSP;仓库字面搜索先用 FFF `find` 缩小文件或目录范围,再在已收敛的路径中用 `grep`/`multi_grep` 获取行号。宽泛搜索命中大量结果、发生截断或达到上限时,应继续缩小路径、glob 或 pattern,而不是提高 limit 或输出全部结果。 +`config/prompt/routing.jsonc` 定义跨工具路由规则,由 `extensions/system-prompt.ts` 在每轮开始前按当前激活工具渲染为 `` 分区。代码结构、调用关系和待修改 symbol 优先使用 CodeGraph,定义、引用、类型和修改后诊断优先使用 LSP;本地字面搜索按已知信息直接选工具:确切标识符或文本用 `grep` 字面模式并限定 path/exclude,多个命名变体合并为一次 `grep` 正则 alternation,文件名、路径片段或功能概念用 FFF `find` 模糊全路径匹配,然后只 `read` 命中区域。对搜索结果做提取、去重、计数或聚合时,在 codemode 脚本中调用 `tools.grep` / `tools.find` 并用 JavaScript 后处理;bash 中不得运行 `grep`/`rg`/`find`/`fd`/`git grep`(策略 deny 的 reason 指明替代工具),程序需要文件清单时传 `$(git ls-files '')`。宽泛搜索命中大量结果、发生截断或达到上限时,应继续缩小路径、glob 或 pattern,而不是提高 limit 或输出全部结果。 在线搜索默认按任务只选一个服务:关键词不确定、新闻/近期话题或需要较多候选来源时优先 Tavily;官方/API 文档、版本信息、论文和高确定性事实确认优先 Exa;中文政策、政府公告、中文网页、站点限定和日期筛选优先 Keenable。只有来源质量或不确定性确实需要时才跨服务复核,避免默认把三套结果全部塞进上下文。 @@ -211,7 +211,8 @@ Hashline 不负责压缩大文件;每行锚点本身还会增加少量 token `extensions/fff-override.ts` 强制设置 FFF 官方的 `PI_FFF_MODE=override`(显式传入 `--fff-mode` 仍按 FFF 官方优先级覆盖它)。FFF 替换 -Pi 的 `find` 和 `grep`,并提供 `multi_grep`;RTK 对所有 `grep` 工具结果直接跳过, +Pi 的 `find` 和 `grep`;`multi_grep` 上游标注为有害、默认关闭,wrapper 在加载前 +删除 `PI_FFF_MULTIGREP` 环境变量,使其永远无法注册。RTK 对所有 `grep` 工具结果直接跳过, 也默认关闭 Bash 命令改写,因此不会把 `rg`、`grep`、`find` 或 `fd` 改写到 RTK。 ### 输出压缩归 RTK diff --git a/config/pi-permission-policy.jsonc b/config/pi-permission-policy.jsonc index 107aa7d..2603179 100644 --- a/config/pi-permission-policy.jsonc +++ b/config/pi-permission-policy.jsonc @@ -37,7 +37,6 @@ "edit": "allow", "grep": "allow", "find": "allow", - "multi_grep": "allow", "ls": "allow", "codegraph_explore": "allow", "lsp_diagnostics": "allow", @@ -103,10 +102,10 @@ }, "bash": { "*": "allow", - "rg*": "deny", - "grep*": "deny", - "find*": "deny", - "fd*": "deny", + "rg*": { "action": "deny", "reason": "Bash content search is disabled. Locally use the grep tool (pattern + path/exclude; regex alternation for several names); to extract/dedupe/count matches, call tools.grep in codemode and process in JS; to filter command output, use overflow_query on the stored result. Over SSH use ssh_grep." }, + "grep*": { "action": "deny", "reason": "Bash content search is disabled. Locally use the grep tool (pattern + path/exclude; regex alternation for several names); to extract/dedupe/count matches, call tools.grep in codemode and process in JS; to filter command output, use overflow_query on the stored result. Over SSH use ssh_grep." }, + "find*": { "action": "deny", "reason": "Bash file search is disabled. Locally use the find tool (fuzzy path, or a glob in path such as 'src/**/*.ts'); to pass a file list to a program use $(git ls-files ''). Over SSH use ssh_find." }, + "fd*": { "action": "deny", "reason": "Bash file search is disabled. Locally use the find tool (fuzzy path, or a glob in path such as 'src/**/*.ts'); to pass a file list to a program use $(git ls-files ''). Over SSH use ssh_find." }, "git *": "ask", "git status*": "allow", "git diff*": "allow", @@ -114,7 +113,7 @@ "git show*": "allow", "git rev-parse*": "allow", "git ls-files*": "allow", - "git grep*": "deny", + "git grep*": { "action": "deny", "reason": "Bash content search is disabled. Locally use the grep tool (pattern + path/exclude; regex alternation for several names); to extract/dedupe/count matches, call tools.grep in codemode and process in JS; to filter command output, use overflow_query on the stored result. Over SSH use ssh_grep." }, "git branch": "allow", "git branch --show-current*": "allow", "git remote -v": "allow", diff --git a/config/prompt/routing.jsonc b/config/prompt/routing.jsonc index 684732d..f66fe60 100644 --- a/config/prompt/routing.jsonc +++ b/config/prompt/routing.jsonc @@ -16,16 +16,25 @@ "text": "Use LSP for symbol definitions, references, hover/type information, and post-edit diagnostics when the language server supports the file." }, { - "whenAny": ["find", "grep", "multi_grep"], - "text": "For literal search, narrow in stages instead of requesting a repository-wide dump:\n 1. Use find to identify likely files or directories. Constrain path/glob and keep the result limit small.\n 2. Use grep or multi_grep only inside the narrowed path or file to obtain matching line numbers. Start with a specific or literal pattern, a small context window, and a bounded limit.\n 3. Use read with offset/limit only for the exact matching region when full source is still needed." + "whenAny": ["find", "grep"], + "text": "Pick the local search tool by what you already know:\n - Exact identifier or text: grep with a literal pattern, constrained by path/exclude. Do not run find first just to locate it.\n - Several identifiers or naming variants: one grep with a regex alternation (e.g. user_id|userId|UserId) instead of several greps.\n - A filename, path fragment, or feature concept: find (fuzzy whole-path match; use a glob in path for exact names).\n - Then read only the matching region with offset/limit." }, { - "whenAny": ["find", "grep", "multi_grep"], + "whenAny": ["find", "grep"], "text": "Do not run a broad search expected to return hundreds or thousands of files or matches. If results truncate or hit a limit, narrow the path, glob, or pattern instead of increasing the limit or dumping all results." }, + { + "whenAll": ["codemode"], + "whenAny": ["find", "grep"], + "text": "To extract, deduplicate, count, or aggregate across search matches (what grep -o | sort -u | wc would do), call tools.grep / tools.find inside one codemode script and post-process the results in JavaScript." + }, { "whenAny": ["bash"], - "text": "Use bash for builds, tests, git, package scripts, and other programs. Never search files by running grep, find, rg, or fd through bash; use the find/grep tools." + "text": "Use bash for builds, tests, git, package scripts, and other programs. Never run grep, rg, find, fd, or git grep in bash — standalone, piped, inside a loop, or in $(…). Search files with the grep/find tools; when a program needs a file list (wc, node, tsc), pass $(git ls-files '')." + }, + { + "whenAll": ["bash", "overflow_query"], + "text": "To filter a command's output, run it without | grep; if the result carries a [pi-overflow id=…] marker, search it with overflow_query instead of re-running." }, { "whenAny": ["ssh_connect"], @@ -59,12 +68,15 @@ }, { "whenAny": ["read"], - "text": "Use read only when exact source is needed or the file is small. Before editing, request the smallest useful offset/limit range; do not read a complete large file merely to copy, compare, hash, count, explore, or summarize it." + "text": "Use read only when exact source is needed or the file is small. Before editing, request the smallest useful offset/limit range; do not read a complete large source file merely to copy, compare, hash, count, or explore it. Reading project overview docs such as a README in full is fine." }, { "whenAll": ["read", "edit"], "text": "For existing-file changes, obtain fresh LINE#HASH anchors with a small read (find/grep output has no anchors), then use anchored edit operations. Reuse fresh anchors returned by successful edits for chained changes; re-read only when anchors are stale or the next target region was not shown." }, + { + "text": "When a tool call is denied by policy, use the alternative named in the denial and continue the subtask; do not drop it or present unverified facts as checked." + }, { "text": "Stop searching once the current evidence is sufficient. Avoid repeating the same lookup through CodeGraph, find, grep, and read without a concrete information gap." } diff --git a/config/prompt/subagent/agents/Explore.md b/config/prompt/subagent/agents/Explore.md index 4d6461f..40e719a 100644 --- a/config/prompt/subagent/agents/Explore.md +++ b/config/prompt/subagent/agents/Explore.md @@ -14,7 +14,7 @@ You locate code and answer "where is X / what references Y" questions for the de ## Hard limits - Do not create, modify, move, copy, or delete files, including temporary files anywhere (also /tmp). - Use bash only for read-only commands such as git status, git log, git diff, git show, and ls. Never use output redirection, heredocs, or any command that changes system state. -- Never search through bash (grep, rg, find, fd); use the find and grep tools. +- Never search through bash (grep, rg, find, fd); use the find and grep tools. For several names use one grep with a regex alternation (a|b); when a program needs a file list, pass $(git ls-files ''). ## Approach - Match the requested breadth: "quick" is one targeted lookup, "medium" covers a few related locations, "very thorough" searches multiple locations and naming conventions. diff --git a/config/prompt/subagent/agents/Plan.md b/config/prompt/subagent/agents/Plan.md index fa463bd..ead39bf 100644 --- a/config/prompt/subagent/agents/Plan.md +++ b/config/prompt/subagent/agents/Plan.md @@ -14,7 +14,7 @@ You explore the codebase and return an implementation plan to the delegating age ## Hard limits - Do not create, modify, move, copy, or delete files, including temporary files anywhere (also /tmp). - Use bash only for read-only commands such as git status, git log, git diff, git show, and ls. Never use output redirection, heredocs, or any command that changes system state. -- Never search through bash (grep, rg, find, fd); use the find and grep tools. +- Never search through bash (grep, rg, find, fd); use the find and grep tools. For several names use one grep with a regex alternation (a|b); when a program needs a file list, pass $(git ls-files ''). ## Process 1. Restate the goal and the constraints you were given. Record anything ambiguous as an open question instead of guessing. diff --git a/config/prompt/tools.jsonc b/config/prompt/tools.jsonc index 295af96..165ea1a 100644 --- a/config/prompt/tools.jsonc +++ b/config/prompt/tools.jsonc @@ -18,7 +18,7 @@ "edit": { "guidelines": [ "Use edit with LINE#HASH anchors from the latest read or edit result for all file changes; batch every change to one file into a single edit call.", - "find/grep/multi_grep results carry plain line numbers, not LINE#HASH anchors; read the exact target range before editing.", + "find/grep results carry plain line numbers, not LINE#HASH anchors; read the exact target range before editing.", "Never reuse anchors from an earlier read or edit response once a newer one exists for the same file; treat only the most recent response as carrying valid anchors.", "After a successful edit, the returned --- Anchors --- block replaces a re-read for nearby follow-up edits.", "On [E_STALE_ANCHOR], the error lists the stale refs and any content-matched candidate anchors; re-read the file to get current anchors before retrying." @@ -28,19 +28,18 @@ "write": { "inherit": true }, "ls": { "inherit": true }, "powershell": { "inherit": true }, - "grep": { "inherit": true }, - "find": { "inherit": true }, - "multi_grep": { "inherit": true }, + "grep": { "snippet": "Search file contents via the FFF index (git-aware, smart-case, frecency-ranked, regex or literal); replaces bash grep/rg" }, + "find": { "snippet": "Find files by fuzzy path or glob via the FFF index; replaces bash find/fd" }, "tool_search": { "inherit": true }, "codemode": { "guidelines": [ "Use codemode to batch two or more independent tool calls (Promise.allSettled), chain dependent lookups, or filter large output down to what you need; call a single tool directly instead of wrapping it in a script.", "Call edit, write, ssh_connect, ssh_cd, ask_user_question, and Agent directly, never from a codemode script.", - "Inside scripts, search with tools.grep, tools.find, or tools.multi_grep; never run grep, find, rg, or fd through tools.bash." + "Inside scripts, search with tools.grep or tools.find and do extraction, dedup, and counting in JavaScript; never run grep, find, rg, or fd through tools.bash." ] }, - "codegraph_explore": { "inherit": true }, + "codegraph_explore": { "snippet": "Explore code structure from the CodeGraph index: symbols, relationships, call flows, and their source" }, "lsp_diagnostics": { "inherit": true }, "lsp_definition": { "inherit": true }, "lsp_references": { "inherit": true }, diff --git a/extensions/AGENTS.md b/extensions/AGENTS.md index 5511f2a..7eff582 100644 --- a/extensions/AGENTS.md +++ b/extensions/AGENTS.md @@ -24,7 +24,7 @@ ## 各 wrapper 约定 -- `fff-override.ts`:强制 FFF 官方 `override` 模式,统一接管 `find`、`grep`、`multi_grep` 和 `@` 补全;FFF 独占本地字面搜索,远端服务器搜索由 `ssh_find` / `ssh_grep` 负责,RTK 不得接管搜索工具(见 `pi-rtk-optimizer/AGENTS.md`)。显式 CLI flag 仍遵循 FFF 官方优先级。 +- `fff-override.ts`:强制 FFF 官方 `override` 模式,统一接管 `find`、`grep` 和 `@` 补全;`multi_grep` 按上游保持关闭(加载前删除 `PI_FFF_MULTIGREP` 环境变量)。FFF 独占本地字面搜索,远端服务器搜索由 `ssh_find` / `ssh_grep` 负责,RTK 不得接管搜索工具(见 `pi-rtk-optimizer/AGENTS.md`)。显式 CLI flag 仍遵循 FFF 官方优先级。 - `codegraph.ts` + `codegraph-client.ts`:注册原生 `codegraph_explore` 工具,按索引根惰性常驻 `codegraph serve --mcp -p ` 子进程,经组合包自有 stdio 逐行 JSON-RPC 客户端直连(不经 shell、不带 pi-mcp-adapter 或 MCP SDK);serve 进程内置文件监听自动同步索引,无结果缓存。子进程 10 分钟无调用自动关闭、会话结束统一关闭;调用中死亡换新客户端透明重试一次;其启动的上游 daemon(`.codegraph/daemon.sock`)退出后可多驻留 ≤5 分钟,属上游行为,组合包不管理。 - CodeGraph 是机器级依赖,`install.sh`/`update.sh` 经官方安装器管理 `codegraph` CLI,组合包不内置其运行时。安装、升级和普通启动流程不得执行 `codegraph init`;只有 `codegraph_explore` 在未初始化项目上被调用、且用户在 `ctx.ui.confirm` 中明确确认后才可 `codegraph init` 当前目录,拒绝记入会话级 declined 不再重复询问;init 失败必须如实报告并让模型回退内置工具;不得改动 CodeGraph 更新或遥测设置。CLI 缺失、init 被拒或服务调用失败都不得抛出,必须以文本结果打回并引导模型改用 `find`/`grep`/`read`/LSP。已移除的 `plugin-init.ts`(原 `/plugin_init`)职责已并入本文件的惰性确认,不得恢复。 - `hashline.ts` + `hashline-config.ts`:部署组合包权威 `config/pi-hashline-edit.json` 后加载 `pi-hashline-edit`;默认以 2 字符行哈希覆盖内置 `read` / `edit`,`grep` 与 `replaceText` 均关闭。它保证锚定编辑而不负责压缩,大文件上下文节省必须来自先定位/隔离分析、再做最小范围 `offset/limit` 读取。 diff --git a/extensions/fff-override.ts b/extensions/fff-override.ts index 64e9d07..770054b 100644 --- a/extensions/fff-override.ts +++ b/extensions/fff-override.ts @@ -5,5 +5,6 @@ import { guardExtensionApi } from "./prompt-guard.ts"; /** Load FFF as the bundle's canonical `find` and `grep` implementation. */ export default function fffOverrideExtension(pi: ExtensionAPI): void { process.env.PI_FFF_MODE = "override"; + delete process.env.PI_FFF_MULTIGREP; fffExtension(guardExtensionApi(pi)); } diff --git a/pi-permission-system/test/seed-config.test.ts b/pi-permission-system/test/seed-config.test.ts index 9d586cc..a447f88 100644 --- a/pi-permission-system/test/seed-config.test.ts +++ b/pi-permission-system/test/seed-config.test.ts @@ -7,6 +7,7 @@ import { autoReviewConfigFileSchema, normalizeAutoReviewConfig, } from "#src/auto-review/config"; +import { stripJsonComments } from "#src/config-loader"; import { unifiedConfigSchema } from "#src/config-schema"; /** The bundle's authoritative policy seed, as shipped. */ @@ -16,10 +17,10 @@ const SEED_PATH = fileURLToPath( function readSeed(): Record { const raw = readFileSync(SEED_PATH, "utf8"); - const stripped = raw - .replace(/^\s*\/\/.*$/gm, "") - .replace(/\/\*[\s\S]*?\*\//g, ""); - return JSON.parse(stripped) as Record; + // Parse with the same string-aware stripper the loader uses: a naive regex + // strips `/*`-looking runs inside string values (e.g. a `'src/**/*.ts'` + // glob in a deny reason) and corrupts the JSON. + return JSON.parse(stripJsonComments(raw)) as Record; } describe("bundled policy seed", () => { diff --git a/pi-tool-search/CHANGELOG.md b/pi-tool-search/CHANGELOG.md index 23119c7..2585db6 100644 --- a/pi-tool-search/CHANGELOG.md +++ b/pi-tool-search/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased — my-pi maintained source ### Changed +- Removed `multi_grep` from the `filesystem-navigation` group: the bundle wrapper keeps FFF's upstream `PI_FFF_MULTIGREP` opt-in disabled, so the tool is never registered and the group now covers only `ls`. - Pinned Pi's built-in `codemode` (exposure `model-only`) in `alwaysEnabled` so batching several tool calls through one script never depends on a `tool_search` activation; `platformToolPolicy` now also drops tools with `hidden` or `codemode` (script-only) exposure so they can never enter the catalog or the unknown-tools path. - Removed the `PI_TOOL_SEARCH_CONFIG_PATH` environment override; the extension reads the bundle `config/tool-search.json`, and tests inject a path through the `createToolSearchExtension({ configPath })` factory. - Removed the retired context-mode integration: the `ctx_execute` / `ctx_execute_file` / `ctx_batch_execute` pins left `alwaysEnabled` and the four `context-*` bundle groups were dropped. Large tool results are now bounded by pi-overflow and recoverable through the pinned `overflow_query`. diff --git a/pi-tool-search/README.md b/pi-tool-search/README.md index 972cb48..af80d78 100644 --- a/pi-tool-search/README.md +++ b/pi-tool-search/README.md @@ -26,7 +26,7 @@ Run `/tool-search-status` to inspect the current catalog source, pinned count, d | Group | Bundle tools | |---|---| -| `filesystem-navigation` | `ls`, `multi_grep` | +| `filesystem-navigation` | `ls` | | `ssh-connection` | `ssh_connect` | | `ssh-remote-files` | `ssh_read`, `ssh_write`, `ssh_edit` | | `ssh-remote-search` | `ssh_find`, `ssh_grep` | diff --git a/pi-tool-search/extensions/bundle-groups.ts b/pi-tool-search/extensions/bundle-groups.ts index c1f6186..72d3c57 100644 --- a/pi-tool-search/extensions/bundle-groups.ts +++ b/pi-tool-search/extensions/bundle-groups.ts @@ -25,11 +25,11 @@ export const BUNDLE_GROUP_DEFINITIONS: BundleGroupDefinition[] = [ { id: "filesystem-navigation", title: "Filesystem navigation", - summary: "Inspect directory layouts and run bounded multi-pattern literal searches.", - useWhen: ["You need directory entries or several literal searches after narrowing a path"], + summary: "Inspect directory layouts.", + useWhen: ["You need the alphabetical directory entries of an unknown path"], avoidWhen: ["Code relationships or types are the real question"], - keywords: ["files", "directory", "list", "multi grep", "目录", "文件", "多模式搜索"], - tools: ["ls", "multi_grep"], + keywords: ["files", "directory", "list", "目录", "文件"], + tools: ["ls"], }, { id: "ssh-connection", diff --git a/tests/bundle-config.test.ts b/tests/bundle-config.test.ts index eeb5443..4de93e1 100644 --- a/tests/bundle-config.test.ts +++ b/tests/bundle-config.test.ts @@ -16,7 +16,10 @@ import { import { CONFIG_PATH as RTK_CONFIG_PATH } from "../pi-rtk-optimizer/src/constants.ts"; import { CONFIG_PATH as COMPACTION_CONFIG_PATH } from "../pi-compaction/src/config.ts"; import { WORKTREE_CONFIG_PATH } from "../pi-worktree/src/settings.ts"; -import { resolvePreamblePath } from "../extensions/system-prompt-config.ts"; +import { + resolvePreamblePath, + stripJsoncComments, +} from "../extensions/system-prompt-config.ts"; const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const bundleConfigDir = join(repositoryRoot, "config"); @@ -48,9 +51,9 @@ const BUNDLE_CONFIG_FILES = [ "p10k.zsh", ]; -/** Strip JSONC comments (line and block) — same approach as the seed test. */ +/** Strip JSONC comments (line and block) without touching string literals. */ function stripJsonc(raw: string): string { - return raw.replace(/^\s*\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, ""); + return stripJsoncComments(raw); } test("every bundle config file exists and is non-empty", async () => { diff --git a/tests/extension-load.test.ts b/tests/extension-load.test.ts index 4472abe..5518f01 100644 --- a/tests/extension-load.test.ts +++ b/tests/extension-load.test.ts @@ -343,4 +343,12 @@ test("all package extensions load together without global registration conflicts const codemode = probe.all.find((tool) => tool.name === "codemode"); assert.equal(codemode?.exposure, "model-only", "Pi's built-in codemode must load with model-only exposure"); assert.ok(probe.active.includes("codemode"), "Tool Search must pin codemode into the active set"); + assert.ok( + probe.all.every((tool) => tool.name !== "multi_grep"), + "FFF's upstream-flagged multi_grep must stay unregistered (fff-override deletes PI_FFF_MULTIGREP)", + ); + assert.ok( + !probe.active.includes("multi_grep"), + "multi_grep must not appear in the active tool set", + ); }); diff --git a/tests/system-prompt.test.ts b/tests/system-prompt.test.ts index 5991fb9..a6474f7 100644 --- a/tests/system-prompt.test.ts +++ b/tests/system-prompt.test.ts @@ -255,7 +255,7 @@ test("bundled routing rules select the same guidance the retired tool-routing ex const routing = loadRoutingRules(); const literal = renderRouting(routing.rules, ["find", "grep", "read"]); - assert.match(literal, /Use find to identify likely files or directories/); + assert.match(literal, /Pick the local search tool by what you already know/); assert.match(literal, /narrow the path, glob, or pattern instead of increasing the limit/); const ssh = renderRouting(routing.rules, ["ssh_connect", "ssh_cd", "ssh_bash"]); @@ -267,7 +267,7 @@ test("bundled routing rules select the same guidance the retired tool-routing ex const minimal = renderRouting(routing.rules, ["read"]); assert.doesNotMatch(minimal, /codegraph_explore first/); - assert.doesNotMatch(minimal, /For literal search/); + assert.doesNotMatch(minimal, /Pick the local search tool/); assert.doesNotMatch(minimal, /ssh_connect only when/); assert.match(minimal, /Stop searching once the current evidence is sufficient/); }); @@ -397,7 +397,6 @@ test("composer splices the preamble, applies the catalog, and orders sections", read: "reads files", bash: "runs commands", edit: "edits", - codegraph_explore: "explores", tool_search: "searches", }, toolGuidelines: { edit: ["upstream edit rule"] }, @@ -414,6 +413,11 @@ test("composer splices the preamble, applies the catalog, and orders sections", "the bundle preamble replaces Pi's default preamble", ); assert.match(output, /\n- Use codegraph_explore first/); + assert.match( + output, + /[\s\S]*?- codegraph_explore: Explore code structure from the CodeGraph index/, + "tools.jsonc must add a snippet for codegraph_explore, which has no upstream entry", + ); assert.match(output, /search files with the find\/grep tools, not bash/); assert.match(output, /LINE#HASH anchors/); assert.ok(