pi-mono/packages/durable/test
Petr Houška c7372af420
fix(durable): rank tool search like the coding agent (#11631)
Ports the coding agent's tool ranking fixes for #11331 (#11440, #11625)
to durable, which keeps its own copy of the ranker in `src/search.ts`.

Problem: durable's `rankDocuments()` was still the coding agent's ranker
from before both fixes. `thread_read` with `limit: 1` returned
`queue_read`, and a tool name among other words (`peekaboo app`) lost to
tools that only mention the words in their descriptions.

Change:
- `src/search.ts`: same scoring as the coding agent's `Bm25Ranker`, plus
coverage first: a tool matching more of the query's terms (in any field)
ranks above one matching fewer, whatever the scores. Without it, name
weighting regressed `screenshot window` (1 to 2, `window` beat `image`)
and `describe app` (1 to 2, `app` beat `see`). The name is a separate
field (3x IDF per term, above any number of description mentions), a
tool whose whole local name is in the query gets a bonus worth one more
match of every query term, a query that is exactly a tool's name ranks
it first, and namespace text is a separate 0.5x field that is not
length-normalized.
- `tool_search`: the search text no longer repeats the name; the ranker
reads it from `name`.
- `searchTools()`: same, and the namespace text now includes the
namespace instructions, as in the coding agent.
- `test/search.test.ts`: the coding agent's ranker cases.

Remaining difference from the coding agent: durable's `tool_search` has
no namespaces (they are a code mode option), and `searchTools()` ranks
on the tool sample from the start data (description plus TypeScript
declaration) rather than description plus schema text.

`searchTools()` results are journaled, so replaying a script started
before this change returns the old results; no `CODEMODE_MODULE_VERSION`
bump.


## Before/after

`searchTools()` ranking on a made-up set of 16 MCP tools from 5 servers.
Each tool is searched with its description; each server is a code mode
namespace (prefix `mcp__<server>__`) with the description and
instructions below. Rank of the wanted tool among all matches, with the
top result when it is another tool.

| Server | Description | Instructions | Tools: description |
|---|---|---|---|
| `github` | GitHub repositories, issues, and pull requests | Use
owner/repo for repositories. Issues and pull requests share numbers. |
`list_issues`: List issues in a repository, filtered by state, labels,
or assignee.<br>`get_issue`: Get an issue with its comments by
number.<br>`create_issue`: Open a new issue in a
repository.<br>`search_code`: Search code across
repositories.<br>`create_pull_request`: Open a pull request from a
branch. |
| `linear` | Linear issue tracker | Search issues before creating new
ones. Issues belong to teams. | `search_issues`: Search Linear issues by
text.<br>`create_issue`: Create a Linear issue in a team. |
| `peekaboo` | macOS automation | Peekaboo controls macOS apps. Use app
names or bundle IDs. Peekaboo can capture any app window. | `app`:
Launch, quit, relaunch, focus, hide, or switch applications. Targets an
application by name, bundle identifier, or process ID, and can wait
until it is ready.<br>`see`: Capture the app window and describe the UI
elements of the app.<br>`window`: Move, resize, or close a window of an
app.<br>`menu`: Click a menu item in an app.<br>`image`: Take a
screenshot of the screen, an app, or a window. |
| `app` | Thread and queue state of the app | Threads hold messages; the
queue holds pending messages of a thread. | `queue_read`: Read a queued
message of this thread.<br>`thread_read`: Read durable state and a
paginated timeline from any thread. The default view returns user
messages, assistant messages and plans. Continue with afterPosition
until hasMore is false. |
| `docs` | Project documentation | Search the docs before answering
questions about the API. | `search`: Search the
documentation.<br>`read_page`: Read a documentation page by path. |

Before, a tool's search text was its name, the name with `_` as spaces,
its description, and the namespace name and description (no
instructions). After, the name and the namespace (with instructions) are
separate fields.

| Query | Wanted | Before: rank | After: rank | Change |
|---|---|---|---|---|
| `thread_read` | `app__thread_read` | 2 (top: `app__queue_read`) | 1 |
$\color{green}{\textsf{better}}$ |
| `mcp__app__thread_read` | `app__thread_read` | 2 (top:
`app__queue_read`) | 1 | $\color{green}{\textsf{better}}$ |
| `peekaboo app` | `peekaboo__app` | 5 (top: `peekaboo__see`) | 1 |
$\color{green}{\textsf{better}}$ |
| `app` | `peekaboo__app` | 4 (top: `app__queue_read`) | 1 |
$\color{green}{\textsf{better}}$ |
| `read thread messages` | `app__thread_read` | 2 (top:
`app__queue_read`) | 1 | $\color{green}{\textsf{better}}$ |
| `open the peekaboo app tool` | `peekaboo__app` | 5 (top:
`peekaboo__see`) | 1 | $\color{green}{\textsf{better}}$ |
| `launch app` | `peekaboo__app` | 1 | 1 | $\color{gray}{\textsf{same}}$
|
| `create linear issue` | `linear__create_issue` | 1 | 1 |
$\color{gray}{\textsf{same}}$ |
| `search documentation` | `docs__search` | 1 | 1 |
$\color{gray}{\textsf{same}}$ |
| `read docs` | `docs__read_page` | 1 | 1 |
$\color{gray}{\textsf{same}}$ |
| `pull request` | `github__create_pull_request` | 1 | 1 |
$\color{gray}{\textsf{same}}$ |
| `get issue comments` | `github__get_issue` | 1 | 1 |
$\color{gray}{\textsf{same}}$ |
| `screenshot window` | `peekaboo__image` | 1 | 1 |
$\color{gray}{\textsf{same}}$ |
| `describe app` | `peekaboo__see` | 1 | 1 |
$\color{gray}{\textsf{same}}$ |
| `create issue` | `github__create_issue` | 2 (top:
`linear__create_issue`) | 2 (top: `linear__create_issue`) |
$\color{gray}{\textsf{same}}$ |
| `search github issues` | `github__list_issues` | 5 (top:
`github__search_code`) | 5 (top: `github__search_code`) |
$\color{gray}{\textsf{same}}$ |

No regressions on this set. `search github issues` stays at 5:
`list_issues` does not contain "search", so it ties on coverage (2 of 3
terms) with `search_code` and `linear__search_issues`, and their scores
win.
2026-10-30 23:08:57 +01:00
..
examples feat(chord): Chord v2 slice 8, registries and host.root 2026-10-28 21:34:56 +00:00
fixtures feat(durable): first coding-agent tool turn (Package 16) 2026-09-29 21:24:32 +02:00
chat-support.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
codemode-bench.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
codemode-checkpoints.test.ts feat: checkpointWhen is required on Durable document definitions 2026-10-19 18:17:42 +00:00
codemode-describe.test.ts feat(durable): deferred tools and the tool_search extension 2026-10-12 08:05:26 +00:00
codemode-imports.test.ts fix(durable): import toCodemodeIdentifier from pi-codemode/declarations 2026-10-27 21:31:47 +00:00
codemode-models.test.ts feat(durable): code mode listing, tool search, output, models.*, grammar; tool error rule 2026-10-12 00:06:09 +00:00
codemode.test.ts fix(durable): return image blocks from read in Code Mode scripts (#11606) 2026-10-30 12:23:48 +01:00
conversation-transcript.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
conversation-view-bench.ts feat(chord,durable): Chord v2 slice 6b, Durable and jobs on the store 2026-10-28 19:18:30 +00:00
document-append-bench.ts feat: checkpointWhen is required on Durable document definitions 2026-10-19 18:17:42 +00:00
env-line-scan.test.ts feat(durable): bounded read tool via BinaryReader.scanLines 2026-10-04 23:15:37 +02:00
env-node-conformance.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
env-node-spill.test.ts feat(durable): first coding-agent tool turn (Package 16) 2026-09-29 21:24:32 +02:00
env-node.test.ts fix(coding-agent): resolve Windows shells from installation directories 2026-10-19 21:55:12 +02:00
env-truncate.test.ts feat(chord,durable): move OutputBuffer and Progress to @earendil-works/chord/output 2026-10-15 09:59:46 +00:00
harness-after-run.test.ts feat(durable): run-end tasks with the afterRun hook 2026-10-28 14:03:25 +00:00
harness-blocked.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-callers.test.ts feat(durable): nested tool calls, structured output, callers; storage errors end the Session 2026-10-09 17:13:34 +00:00
harness-cancellation-barrier.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-compaction.test.ts fix(durable): pi.live version 3 gives a stored run without turns a count of 0 2026-10-28 14:28:41 +00:00
harness-context-range.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-context.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-continue.test.ts feat(durable): continue submissions 2026-10-28 11:45:59 +00:00
harness-conversations.test.ts feat: Durable storage adopt callback inside the commit, watch types in Chord, explicit watch retirement 2026-10-22 10:52:59 +00:00
harness-deferred-progress.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-failed-run-inbox.test.ts fix(durable): review fixes for the crash-loop guard, reports, and blocked tasks 2026-10-18 00:53:14 +00:00
harness-generation-recovery.test.ts feat(durable): run-end tasks with the afterRun hook 2026-10-28 14:03:25 +00:00
harness-generation.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-group-commit.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-hook-reads.test.ts feat(durable): entry reads for hooks and tasks 2026-10-28 14:03:00 +00:00
harness-host-inputs.test.ts feat(ai,agent,coding-agent): move client identity and provider attribution into pi-ai 2026-10-21 11:17:02 +00:00
harness-inbox.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-input-entries.test.ts feat(durable): run-end tasks with the afterRun hook 2026-10-28 14:03:25 +00:00
harness-inspect.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
harness-json.test.ts fix: harden handling of untrusted URLs, terminal text, and streamed data 2026-10-26 20:46:31 +01:00
harness-lifecycle.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-live-deltas.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-nested-tools-restart.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
harness-nested-tools.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-observers.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-ownership.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-partial-changes.test.ts feat(durable): deferred storage of throttled commits 2026-10-24 17:49:30 +00:00
harness-prompt.test.ts feat(durable): deferred tools and the tool_search extension 2026-10-12 08:05:26 +00:00
harness-read-only.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
harness-registry-reader.test.ts feat(chord): Chord v2 slice 8, registries and host.root 2026-10-28 21:34:56 +00:00
harness-registry.test.ts feat(durable): deferred storage of throttled commits 2026-10-24 17:49:30 +00:00
harness-reports.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
harness-restart-failure.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-run-failure.test.ts feat(durable): run-end tasks with the afterRun hook 2026-10-28 14:03:25 +00:00
harness-scheduler-indexes.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-scheduler-retention.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-sleep.test.ts feat: Durable storage adopt callback inside the commit, watch types in Chord, explicit watch retirement 2026-10-22 10:52:59 +00:00
harness-storage-failure.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-structured-output.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
harness-structured.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-submissions.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-submit-in-commit.test.ts feat(durable): admit submissions inside the caller's commit with submit(tx, draft) 2026-10-28 13:09:00 +00:00
harness-support.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
harness-task-graph.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-tasks-recovery.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
harness-tasks.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-telemetry-options.test.ts feat: Durable and pi-ai telemetry; Context.telemetry is always a span 2026-10-19 06:26:02 +00:00
harness-telemetry.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
harness-tool-hooks.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-tools-recovery.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
harness-tools.test.ts feat(durable): beforeProviderRequest generation hook (#11619) 2026-10-30 18:15:05 +01:00
harness-turn-limit.test.ts feat(durable): per-conversation turn limit 2026-10-28 11:45:59 +00:00
harness-view-run.test.ts feat(durable): run-end tasks with the afterRun hook 2026-10-28 14:03:25 +00:00
harness-view.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
heap-retained.ts feat(durable): bound the Session's document cache by use (documentRetentionMs) 2026-10-11 08:03:35 +00:00
images-wasm-module.test.ts feat(durable): read returns images, optional Photon image processor 2026-10-09 19:38:02 +00:00
indexeddb-storage.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
jsonl-storage.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
live-support.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
memory-storage.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
nested-images-bench.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
nested-tools-bench.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
provider-session-cache-e2e.test.ts fix(durable): run the Codex prompt-cache e2e test on gpt-6.1-sol 2026-10-16 19:42:02 +00:00
scheduler-fanout-bench.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
scheduler-memory-bench.ts feat(durable): bound the Session's document cache by use (documentRetentionMs) 2026-10-11 08:03:35 +00:00
search.test.ts fix(durable): rank tool search like the coding agent (#11631) 2026-10-30 23:08:57 +01:00
session-adoption.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
session-cached-storage.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
session-checkpoints-migrations.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
session-conversation-tails.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
session-deferred-commits.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
session-definitions.test.ts feat: Durable storage adopt callback inside the commit, watch types in Chord, explicit watch retirement 2026-10-22 10:52:59 +00:00
session-document-cache-bench.ts feat(durable): bound the Session's document cache by use (documentRetentionMs) 2026-10-11 08:03:35 +00:00
session-document-retention.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
session-documents.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
session-forks.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
session-group-commit.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
session-observers.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
session-support.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
session-tables.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
session-watches.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
setup-document-retention.ts feat(durable): bound the Session's document cache by use (documentRetentionMs) 2026-10-11 08:03:35 +00:00
spec-usage.test.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
sqlite-cloudflare.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
sqlite-facade.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
sqlite-migrations.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
sqlite-storage.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
storage-memory.ts feat(chord,durable): Chord v2 slice 6b, Durable and jobs on the store 2026-10-28 19:18:30 +00:00
storage-runtime-boundary.test.ts feat(durable): first coding-agent tool turn (Package 16) 2026-09-29 21:24:32 +02:00
storage.bench.ts feat(chord,durable): Chord v2 slice 6b, Durable and jobs on the store 2026-10-28 19:18:30 +00:00
store-storage-commit.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
store-storage-node.ts feat(chord,durable): Chord v2 slice 6b, Durable and jobs on the store 2026-10-28 19:18:30 +00:00
store-storage-support.ts feat(chord,durable): Chord v2 slice 6b, Durable and jobs on the store 2026-10-28 19:18:30 +00:00
store-storage.test.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
system-order-cache-e2e.test.ts feat(durable): nested tool calls, structured output, callers; storage errors end the Session 2026-10-09 17:13:34 +00:00
task-support.ts feat(chord,durable): failures are watch calls; one vocabulary for watches, observers and reports 2026-10-27 20:38:08 +00:00
tool-output-bench.ts feat(durable): group commit and batch Storage.commit 2026-10-30 10:41:11 +00:00
tool-search.test.ts feat(durable): deferred tools and the tool_search extension 2026-10-12 08:05:26 +00:00
tools-images.test.ts fix(durable): encode base64 with btoa, without retaining concatenation trees 2026-10-14 09:41:45 +00:00
tools-read-differential.test.ts fix(durable): return image blocks from read in Code Mode scripts (#11606) 2026-10-30 12:23:48 +01:00
tools.test.ts feat(durable): read returns images, optional Photon image processor 2026-10-09 19:38:02 +00:00
types.test.ts feat(durable): inputs placed as application entries, display-only writes appended at once 2026-10-11 13:12:44 +00:00