ast_grep_search was mentioned exactly once in the librarian prompt
(bundled as 'grep/ast_grep_search for function/class') with no syntax
guidance. When the librarian cloned a repo and tried to match code
shape, it fell into the same regex-in-AST trap as the main agent.
Two targeted edits, no rewrite of the surrounding request-classification
flow:
- Phase 1 TYPE B 'Find the implementation' now separates ast_grep_search
(code shape) from grep (text/literals) and reminds the LLM that AST
patterns use $VAR and $$$ and are not regex.
- TOOL REFERENCE adds a dedicated ast_grep_search row with valid
examples and the explicit regex anti-pattern list, alongside tightened
guidance for grep_app and grep so the LLM picks the right tool for
cross-repo vs single-repo, text vs shape.
The previous Tool Strategy was a neutral 5-bullet list that treated
ast_grep_search and grep as equals. LLMs read 'structural patterns
(function shapes, class structures)' and reach for ast_grep_search
first, then call it with regex ('foo|bar', '.*', '\\w') and silently
get zero results.
Rewrite so the default is clear - grep first, ast_grep_search only for
true AST shape matching - and enumerate the regex anti-patterns with
their corrective switches. Add an explicit rule: if ast_grep_search
returns zero matches and the printed hint says the pattern is regex-
shaped, switch to grep instead of retrying with another regex variant.
Preserves the existing absolute-path requirement, <results> block
format, and read-only / no-emoji constraints.
The previous description (41 words) told the LLM to write 'complete AST
nodes' but did not explain that regex syntax is the #1 failure mode. It
also shipped a bug: the Python example 'def $FUNC($$$):' had a trailing
colon that the hint system actively flags as wrong.
Extract descriptions into tool-descriptions.ts and rewrite:
- Open with 'This is NOT regex' so the constraint is unmissable
- List the four regex patterns that do not work (|, .*, \\w, [a-z])
with the corrective action for each
- Tell the LLM to switch to grep when the pattern is text-shaped
- Fix the Python example (no trailing colon) and add Go and Rust rows
since the failing reports came from Go codebases
- Shorten the pattern-param description with the same anti-regex list
Also harden the LSP reference for the new test files using the
bun-types triple-slash directive already used elsewhere.
LLMs frequently call ast_grep_search with regex-style patterns like
'func.*build|BuildMode|projectReferences' instead of AST patterns. The
search silently returns zero matches with no useful feedback, so the
model retries with a different regex-shaped pattern and loops.
Extract hint generation into pattern-hints.ts and add detectors for the
four dominant misuse modes:
- regex escapes (\\w, \\d, \\s, \\b)
- character-class ranges ([a-z], [0-9])
- regex wildcards (.* .+) with no meta-vars
- pure alternation (foo|bar|baz with no structural syntax)
Heuristics are designed to be safe on valid AST patterns: bitwise OR
'$A | $B' and Rust closures '|x| x + 1' are not flagged. Language-
specific shape hints (trailing-colon Python, body-less JS/TS/Go/Rust
functions) are preserved and extended to Go and Rust.
OPENAI_ONLY_AGENT_OVERRIDES was rewriting explore and librarian back to
gpt-5.4 medium for OpenAI-only installs. Match the runtime primary so the
install default stays on gpt-5.4-mini-fast.
Document the new primary chain and install-time fallback behavior for explorer and librarian.\nKeep the user-facing guidance aligned with the runtime and CLI model selection.
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Default the install-time fallback chain to gpt-5.4-mini-fast for librarian and explore when OpenAI is available.\nKeep the snapshot and catalog tests aligned with the new resolution path.
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Use gpt-5.4-mini-fast as the primary runtime model for librarian and explore.\nKeep the fallback chain intact so older providers still resolve.
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Keep the supplemental OpenAI model available when the bundled snapshot omits it.\nMerge its capabilities at runtime so downstream model resolution can use it.
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Tighten resolve-metadata-model runtime guards, tidy tool-argument-preparation
subagent-type override logging, and trim a redundant literal in the
metadata-model-unification test. Behavior preserved (328 tests pass).
Strip obvious comments, over-defensive guards, and dead branches across
the five delegate-task executor files while preserving all metadata
propagation behavior added in prior commits. Regression tests remain
green (328 pass / 0 fail).
The execute field with { task_id, task_dir } was defined but never referenced anywhere in the codebase. Removing dead code simplifies the type surface and prevents accidental future misuse.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Oracle flagged that the previous test file monkey-patched process.kill
and relied on mock.module for 5 modules. Running it after manager.test.ts
in the same Bun process reproduced 2 failures - the test resolution of
`./session-kill` specifier interacted badly with manager.test.ts's
`../../shared/tmux` barrel mock.
Solution: refactor stale-session-sweep.ts to expose
`sweepStaleOmoAgentSessionsWith(deps)` that accepts a SweepDeps record
(isInsideTmux, getTmuxPath, listCandidateSessions, killSession,
processAlive, currentPid, log). The public `sweepStaleOmoAgentSessions()`
still uses runtime-built deps so call sites are unchanged.
The test file now imports the pure function directly and constructs a
fixture with fake deps. Zero mock.module calls, zero process.kill
patching, zero cache-bust dynamic imports. 8 tests (up from 6) run
deterministically in any order with any neighbor.
Before: combined run with manager.test.ts = 2 fail, 50 pass.
After: combined run with manager.test.ts = 0 fail, 54 pass.
Oracle noted that loadSweeper() monkey-patches process.kill without
ever restoring it. Added afterEach hook to set process.kill back to the
captured original. Individual file runs already passed, and
script/run-ci-tests.ts confirms the full CI suite - 4781 pass, 0 fail
across 491 files - but this makes the test file safe under non-isolated
local runs as well.