Skip to content

feat: flip search-tool / search-tool-bash defaults to on (#738) - #742

Merged
robotrocketscience merged 4 commits into
mainfrom
feat/738-search-tool-default-on
May 13, 2026
Merged

feat: flip search-tool / search-tool-bash defaults to on (#738)#742
robotrocketscience merged 4 commits into
mainfrom
feat/738-search-tool-default-on

Conversation

@robotrocketscience

@robotrocketscience robotrocketscience commented May 13, 2026

Copy link
Copy Markdown
Owner

Closes #738.

What

aelf setup (no flags) now installs both PreToolUse:Grep|Glob and PreToolUse:Bash retrieval hooks. The flags follow the --X / --no-X BooleanOptionalAction convention used by every other default-on hook (transcript-ingest, commit-ingest, session-start, stop-hook). The old --search-tool / --search-tool-bash opt-in flags and the asymmetric --no-search-tool-bash setup-time uninstall are gone — use aelf setup --no-search-tool[-bash] to skip + persist an opt-out, or aelf unsetup (default-on for both flags) for explicit removal.

Why

Per the #738 audit: README §"How it works" advertises four parallel retrieval lanes (L0/L1/L2/L2.5), but the agent's own Grep/Glob/Bash-search calls skipped the retrieval pipeline unless the operator explicitly opted in via aelf setup --search-tool. The product as documented and the product as installed were not the same product. This PR closes that gap.

The bfs_enabled (L2 graph walk) flip is tracked separately under #739 and is bench-gated. Cross-fire dedup is tracked under #740.

Latency budget (per issue body)

Surface Cost per fire Cap Worst-case turn
search-tool (Grep / Glob) ~4.5ms p99 none 5 fires × 4.5ms ≈ 22ms
search-tool-bash (grep/rg/find/fd/ack) ~2–4ms 3/turn (BASH_FIRE_CAP_PER_TURN) 3 fires × 4ms ≈ 12ms
Combined ~34ms / turn

No new retrieval code paths enabled — the retrieve() call site reused is already validated for UserPromptSubmit fires.

Changes (4 atomic commits)

  1. feat(cli) — flag rename + setup/unsetup body defaults flip + opt-out mapping.
  2. feat(auto-install)hook_manifest.json + _DISPATCH so first aelf <cmd> after upgrade auto-installs the two new entries.
  3. test — rewrite 3 broken tests (old --no-search-tool-bash → uninstall semantic), add coverage for the new defaults + opt-out persistence.
  4. docsCHANGELOG.md [Unreleased] §Changed, docs/INSTALL.md hooks table + opt-out block, docs/search_tool_hook.md top-of-doc status flip.

Verification

  • aelf setup --help shows both --X / --no-X forms for both flags.
  • aelf setup (no flags) installs both hooks (new test).
  • aelf setup --no-search-tool --no-search-tool-bash reproduces the pre-3.0.1 no-PreToolUse default (new test).
  • aelf setup --no-search-tool[-bash] writes the opt-out to ~/.aelfrice/opt-out-hooks.json (new tests in test_cli_setup_opt_out_sync.py).
  • Bare aelf unsetup removes both (new test).
  • Manifest reconcile picks up both rows on upgrade (existing test_first_run_creates_stamp_and_writes_all_hooks set-inclusion assertion covers it; new search_tool / search_tool_bash names appear in result.installed).

Full test suite: 3820 passed, 59 skipped, 75 xfailed in 76s — no regressions.

Out of scope

Summary by CodeRabbit

  • New Features

    • Search-tool hooks now shipped and enabled by default (v3.0.1+), with finer-grained control via --no-search-tool and --no-search-tool-bash opt-out flags.
  • Documentation

    • Updated installation and hook setup documentation to reflect default-on behavior for search-tool features.
  • Tests

    • Added comprehensive test coverage for search-tool hook setup and opt-out persistence scenarios.

Review Change Stack

`aelf setup` (no flags) now installs both PreToolUse hooks. The flags
follow the `--X / --no-X` BooleanOptionalAction convention used by every
other default-on hook (transcript-ingest, commit-ingest, session-start,
stop-hook). The old `--search-tool` / `--search-tool-bash` opt-in flags
and the asymmetric `--no-search-tool-bash` setup-time uninstall are gone.

`aelf unsetup` (no flags) now removes both for symmetry. Use
`--no-search-tool[-bash]` on setup to skip + record an opt-out (persisted
across upgrades via `~/.aelfrice/opt-out-hooks.json`), or on unsetup to
leave the entries in place.

Per #738 audit: README §"How it works" advertises four parallel retrieval
lanes, but the agent's own Grep/Glob/Bash-search calls skipped them
unless the user explicitly opted in. The product as documented and the
product as installed are now the same product.

Worst-case latency cost: ~22ms / turn for 5 Grep fires (4.5ms p99 each,
README:47) + ~12ms / turn for 3 Bash-search fires (capped at 3 per turn
via BASH_FIRE_CAP_PER_TURN in hook_search_tool.py:75). No new retrieval
code paths; the `retrieve()` call site reused is already validated for
UserPromptSubmit fires.

Manifest reconcile + tests + docs land in follow-up commits.
)

Add `search_tool` and `search_tool_bash` rows to `hook_manifest.json`
with `default_on: true` and `since: "3.0.1"`, and register the
corresponding install/resolve functions in `auto_install._DISPATCH`.

Without this, the cli.py default-on flip in the prior commit only
reaches users who explicitly re-run `aelf setup` after upgrading.
With it, the first `aelf <cmd>` invocation after `uv tool upgrade
aelfrice` reconciles the bumped manifest version against
`~/.aelfrice/installed-manifest-version` and merges both new entries
into `~/.claude/settings.json` automatically — closing the upgrade-path
loop for the new defaults.

Opt-outs continue to live in `~/.aelfrice/opt-out-hooks.json`. Users
who run `aelf setup --no-search-tool[-bash]` get the opt-out persisted
via `_SETUP_FLAG_TO_HOOK_NAME` (added in the prior commit), and the
reconciler skips those names on every subsequent run.

Both hooks share the `aelf-search-tool-hook` script basename — fine for
`owned_basenames()` (frozenset dedup) and reflects the on-disk reality
(setup.py:659,665 both point at the same script; the matcher differs).
Three existing tests in `test_aelf_setup_search_tool_bash.py` asserted
the old `aelf setup --no-search-tool-bash → removes existing entry`
semantic. Under the new BooleanOptionalAction convention (matching
transcript-ingest / commit-ingest / session-start / stop-hook),
setup-time --no-X skips install + records the opt-out but does NOT
actively uninstall. Use `aelf unsetup` for explicit removal.

Rewrites:
- `*_no_search_tool_bash_removes` → `*_does_not_remove_existing` + new
  assertion that the bash entry remains.
- `*_idempotent_when_absent` → `*_skips_install` (no "no search-tool-bash"
  removal message on the setup path anymore).
- `*_leaves_grep_glob_intact` → `*_installs_grep_glob_only` (single setup
  call, asserts the asymmetric default).

New coverage:
- Bare `aelf setup` wires both PreToolUse hooks.
- `aelf setup --no-search-tool --no-search-tool-bash` reproduces the
  pre-3.0.1 no-PreToolUse default.
- `aelf setup --no-search-tool` wires search-tool-bash only.
- Bare `aelf unsetup` removes both.
- `aelf unsetup --no-search-tool` leaves the Grep|Glob hook in place.

Opt-out persistence (test_cli_setup_opt_out_sync.py):
- `aelf setup --no-search-tool` records `search_tool` in
  opt-out-hooks.json so manifest reconcile skips it on upgrade.
- Same for `search_tool_bash`.
- Bare `aelf setup` after a prior --no-X rescinds both opt-outs.

Full suite: 3820 passed, 59 skipped, 75 xfailed (76s).
CHANGELOG.md [Unreleased] §Changed: new entry covering the flag flip,
the convention shift, the opt-out surface, the auto-install reconcile
hook, and the latency budget.

docs/INSTALL.md: hooks-installed table now lists search-tool and
search-tool-bash as default-on (with the "(v3.0.1+)" annotation),
adds the missing stop-lock-prompt row, and the opt-out / opt-in code
blocks reflect the new shape. The rebuilder is the only off-by-default
hook left.

docs/search_tool_hook.md: top-of-doc Status flips from "spec / default-on
candidate at v1.3.0" to "shipped; default-on as of v3.0.1." Hook
registration section drops the `--search-tool` opt-in language.
Historical design-discussion sections (lines 200+) are not retroactively
edited — the top-of-doc note tells readers that "default-OFF" framing
below pre-dates the flip.

README: no changes. The product copy describes the four-lane retrieval
stack at the user-perception level and does not mention the `--search-tool`
flag.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @robotrocketscience, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented May 13, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 730a8ed5-f0ff-48aa-84ca-1e79ff553375

📥 Commits

Reviewing files that changed from the base of the PR and between 13a57ac and 8ea9ab5.

⛔ Files ignored due to path filters (1)
  • CHANGELOG.md is excluded by !**/CHANGELOG.md
📒 Files selected for processing (7)
  • docs/INSTALL.md
  • docs/search_tool_hook.md
  • src/aelfrice/auto_install.py
  • src/aelfrice/cli.py
  • src/aelfrice/data/hook_manifest.json
  • tests/test_aelf_setup_search_tool_bash.py
  • tests/test_cli_setup_opt_out_sync.py

📝 Walkthrough

Walkthrough

This PR implements issue #738, flipping the install-time default for search-tool and search-tool-bash hooks from OFF to ON as of v3.0.1+. The hooks now wire automatically via aelf setup unless explicitly disabled with --no-search-tool or --no-search-tool-bash, with opt-out choices persisted in ~/.aelfrice/opt-out-hooks.json. Manifest entries enable auto-install during upgrade; CLI parsing and command logic implement the new defaults; documentation and tests describe and validate the full opt-out matrix.

Changes

Search-tool hooks default-on flip (v3.0.1+)

Layer / File(s) Summary
Hook manifest and auto-install dispatch
src/aelfrice/data/hook_manifest.json, src/aelfrice/auto_install.py
Hook manifest registers search_tool and search_tool_bash as default-on hooks (since v3.0.1); auto_install imports installers and wires dispatch entries so hooks auto-install during post-upgrade reconciliation.
CLI argument parsing with BooleanOptionalAction
src/aelfrice/cli.py
Both aelf setup and aelf unsetup define --search-tool/--no-search-tool and --search-tool-bash/--no-search-tool-bash using argparse.BooleanOptionalAction with default=True, enabling bidirectional flags that default to installing (or removing) both hooks unless explicitly disabled.
Setup and unsetup command execution with opt-out persistence
src/aelfrice/cli.py
_cmd_setup installs both hooks by default (getattr with default True) and _cmd_unsetup removes both by default. Opt-out flags are persisted via _SETUP_FLAG_TO_HOOK_NAME so --no-* choices are reflected in the opt-out file.
Documentation updates for default-on behavior
docs/INSTALL.md, docs/search_tool_hook.md
INSTALL.md and search_tool_hook.md updated to reflect hooks are shipped and default-on as of v3.0.1+, with new rows in the hooks table, explicit --no-search-tool/--no-search-tool-bash opt-out commands, and clarification that opt-outs persist.
Test coverage for default-on matrix and opt-out persistence
tests/test_aelf_setup_search_tool_bash.py, tests/test_cli_setup_opt_out_sync.py
Comprehensive tests cover new defaults: bare setup installs both hooks, --no-* flags skip/remove selectively, bare unsetup removes both, and opt-out flags are persisted and rescinded by bare setup.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • robotrocketscience/aelfrice#627: Both PRs modify the shared auto-install and hook-manifest pipeline (src/aelfrice/auto_install.py and src/aelfrice/data/hook_manifest.json) to add/merge default-on hook definitions, so this PR's search_tool/search_tool_bash wiring is directly built on the framework introduced in #627.

Suggested labels

author-Setr, docs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: flip search-tool / search-tool-bash defaults to on (#738)' clearly and concisely describes the main change: flipping the default behavior of search-tool hooks from off to on, with the issue number for context.
Description check ✅ Passed The PR description comprehensively covers the linked issue, changes, rationale, verification steps, and scope. It includes a summary section, linked issues reference (#738), a detailed 'What' and 'Why' explanation, latency budget analysis, changes breakdown, verification checklist, and out-of-scope items.
Linked Issues check ✅ Passed The PR successfully implements all major coding objectives from #738: flips search-tool/search-tool-bash defaults to on, converts CLI flags to BooleanOptionalAction (--X/--no-X), adds manifest entries with default_on:true, updates tests for new defaults and opt-out persistence, and provides latency budget analysis within acceptable bounds.
Out of Scope Changes check ✅ Passed All changes are directly aligned with #738 objectives: CLI flag refactoring, manifest entries, auto-install wiring, test updates, and documentation changes. No unrelated changes to other systems or features are present; out-of-scope items (bfs_enabled flip, cross-fire dedup) are explicitly noted.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/738-search-tool-default-on

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown

PR-size soft cap

This PR is over the advisory size threshold:

  • 301 changed lines (limit: 200)
  • 8 changed files (limit: 3)

Bigger PRs collide with more open work, which under the parallel-session workflow tends to produce repeated attn:merge-conflict cycles (see #602). When practical, split into smaller PRs that each touch a focused surface.

This is advisory only — nothing is blocked. If the size is intentional (large refactor, module removal, generated code), apply the size:override label and this comment will be removed on the next push.

@robotrocketscience
robotrocketscience merged commit 8ea9ab5 into main May 13, 2026
28 checks passed
@robotrocketscience
robotrocketscience deleted the feat/738-search-tool-default-on branch May 13, 2026 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flip default: search-tool + search-tool-bash hooks on by default

1 participant