Conversation
Implementation PlanThree bundled changes: Key ScenarioIn Telegram sessions (
Deliverables
Files to Modify
Change Details
Testing ApproachSchema tests:
Execute tests (using existing fixture project pattern):
Multi-project scenario:
formatSearchCall rendering:
Acceptance Criteria
Risks
Plan created by mach6 |
- Add projectDir parameter to search tool — lets the model index/search arbitrary directories instead of cwd (critical for Telegram sessions) - Add rebuild parameter — force clean index rebuild for stale/corrupt recovery - Add resetIndex() to SearchEngine — closes DB, deletes index, preserves embedder - Update system prompt to position search as default exploration tool - Add 13 new tests covering schema, projectDir, rebuild, isolation, guidelines
Progress UpdateAll three deliverables implemented and tested: Issue 119 — projectDir parameter:
Issue 120 — rebuild parameter:
Prompt nudge — search-first exploration:
Tests: 13 new tests — schema (2), projectDir (2), rebuild (2), multi-project isolation (2), system prompt guidelines (2), plus existing tests all passing (2276 passed, 0 failed). Commit: Progress tracked by mach6 |
QA Report — Manual Testing via
|
| Test | Feature | Status |
|---|---|---|
| Basic search | All params visible | ✅ |
| projectDir | Index scoped to target dir | ✅ |
| rebuild | Forces fresh index build | ✅ |
| System prompt | Search-first guidance | ✅ |
All features working as designed in the built binary.
QA tested by mach6 via dreb -p
Code ReviewCriticalNo critical findings. ImportantFinding 1 — Duplicate search-first guideline in real sessions (code-reviewer, confidence 95) Finding 2 — Non-existent projectDir silently creates directory tree and returns empty results (error-auditor, confidence 85) Finding 3 — resetIndex() failure leaves engine in inconsistent state (error-auditor, confidence 80) SuggestionsFinding 4 — formatSearchCall() rendering branches completely untested (test-reviewer, confidence 92) Finding 5 — isSearchAvailable() === false execution path untested (test-reviewer, confidence 87) Finding 6 — limit parameter is schema-tested but never behavior-tested (test-reviewer, confidence 82) Finding 7 — rebuild: true as the very first call (no prior index) untested (test-reviewer, confidence 83) Finding 8 — Relative projectDir path not tested (test-reviewer, confidence 80) Finding 9 — System-prompt tests do not cover the duplication path (code-reviewer, confidence 85) Strengths
Agents run: code-reviewer, error-auditor, test-reviewer, completeness-checker Reviewed by mach6 |
Review AssessmentClassifications
Action Plan
Assessment by mach6 |
Progress UpdateFixed 3 review findings and a gitignore gap: Finding 2 — projectDir validation: Added Finding 4 — formatSearchCall tests: Exported Finding 7 — Cold-start rebuild test: Added test for Gitignore fix: Changed Commit: Progress tracked by mach6 |
Code Review (Re-review)CriticalNo critical findings. ImportantNo important findings. SuggestionsFinding 1 — Duplicate assertion in formatSearchCall projectDir test (code-reviewer + test-reviewer, confidence 90/92) expect(result).toContain("project");
expect(result).toContain("project"); // shortenPath outputThe second was meant to verify the shortened path, but checks the same substring. Both match the label prefix Finding 2 — TOCTOU window on existsSync/statSync (error-auditor, confidence 82) if (projectDir) {
let isDir = false;
try { isDir = statSync(resolvedProjectDir).isDirectory(); } catch {}
if (!isDir) { return { ... }; }
}This is also simpler: one syscall instead of two. Finding 3 — formatSearchResult / renderResult path untested (test-reviewer, confidence 85) Strengths
Agents run: code-reviewer, error-auditor, test-reviewer, completeness-checker Reviewed by mach6 (re-review) |
Review Assessment (Re-review)Classifications
Action Plan
Assessment by mach6 |
Addendum: .dreb/ gitignore + tool visibility (Option E)ProblemAdding Solution: Explicit Path Include (Option E)When rg/fd receive an explicit path argument, they bypass Tool-visible vs tool-hidden
|
| Visible (include) | Hidden (skip) |
|---|---|
memory/ — project knowledge files |
index/ — SQLite search DB |
agents/ — custom agent definitions |
agent/ — sessions, models, auth, bins |
extensions/ — user extension code |
secrets/ — API keys |
Shared constant
Create a shared list of tool-visible .dreb/ subdirectories that all tools reference:
// packages/coding-agent/src/core/tools/dreb-paths.ts (new file)
export const DREB_TOOL_VISIBLE_DIRS = ["memory", "agents", "extensions"] as const;
export const DREB_DIR = ".dreb";Deliverables
1. .gitignore — change to blanket **/.dreb/
Replace the current specific patterns:
-**/.dreb/index/
-**/.dreb/agent/
+**/.dreb/Also untrack the .dreb/memory/ files that are currently committed:
git rm --cached -r .dreb/memory/2. Scanner (packages/coding-agent/src/core/search/scanner.ts)
After the main walkDirectory call in scanProject(), explicitly scan tool-visible .dreb/ subdirectories. Follow the existing scanMemoryDir() pattern (which already bypasses gitignore for ~/.dreb/memory/):
// After the main walk (line ~124), add:
for (const subdir of DREB_TOOL_VISIBLE_DIRS) {
const dir = join(projectRoot, DREB_DIR, subdir);
if (existsSync(dir)) {
scanMemoryDir(dir, projectRoot, results);
}
}scanMemoryDir already handles recursive scanning of .md files with no gitignore filtering. It works for agents/ and extensions/ too since they contain .md and code files. The key point: this runs AFTER the main walk, so gitignore rules don't apply.
Note: .dreb/index is already in SKIP_DIRS (defense-in-depth). With **/.dreb/ in gitignore, the main walk never enters .dreb/ at all, so SKIP_DIRS is redundant but harmless.
3. grep tool (packages/coding-agent/src/core/tools/grep.ts)
When building rg arguments, append tool-visible .dreb/ subdirectories as additional search paths. rg bypasses gitignore for explicit path arguments.
Only when the user hasn't restricted the search to a specific subdirectory (i.e., no path parameter, or path is the project root). If the user passes path: "src/", don't inject .dreb/ results.
In the rg arg construction (around line ~214):
args.push(pattern, searchPath);
// Include tool-visible .dreb/ subdirs when searching from project root
if (!pathParam || searchPath === cwd) {
for (const subdir of DREB_TOOL_VISIBLE_DIRS) {
const drebSubdir = path.join(cwd, DREB_DIR, subdir);
if (existsSync(drebSubdir)) {
args.push(drebSubdir);
}
}
}rg accepts multiple paths after the pattern: rg pattern path1 path2 path3. Results merge into the same JSON stream. The existing match limit applies across all paths combined.
4. find tool (packages/coding-agent/src/core/tools/find.ts)
Same approach as grep. fd also supports multiple search paths and bypasses gitignore for explicit paths.
In the fd arg construction (around line ~200):
args.push(pattern, searchPath);
// Include tool-visible .dreb/ subdirs when searching from project root
if (!patternParam?.includes(".dreb") && (!pathParam || searchPath === cwd)) {
for (const subdir of DREB_TOOL_VISIBLE_DIRS) {
const drebSubdir = path.join(cwd, DREB_DIR, subdir);
if (existsSync(drebSubdir)) {
args.push(drebSubdir);
}
}
}The existing result limit applies across combined results.
5. Tests
Scanner test (test/search/search-tool.test.ts or new test/search/scanner.test.ts):
- Create a fixture with
.gitignorecontaining.dreb/and a.dreb/memory/test.mdfile - Verify
scanProject()includes the memory file despite gitignore - Verify
.dreb/index/content is NOT included
Grep test (test/tools/grep.test.ts or existing):
- Create a fixture with
.gitignorecontaining.dreb/and a.dreb/memory/test.mdfile - Verify grep finds content inside
.dreb/memory/when no path restriction - Verify grep does NOT find
.dreb/content when path is restricted to a subdirectory
Find test (similar):
- Verify find discovers files inside
.dreb/memory/despite gitignore - Verify find does NOT include
.dreb/files when path is restricted
6. README update
Update the .gitignore guidance in README Semantic Search section to say **/.dreb/ (already done in this PR).
Key implementation notes
scanMemoryDirhandles.mdfiles and recurses into subdirectories. Foragents/(which contain.mdagent definitions) andextensions/(which may contain.ts/.jscode), it should work sincescanMemoryDiralready handles various text file types via the extension map. Verify this handles non-.mdfiles in extensions — if not, consider usingwalkDirectorywith an empty ignore matcher instead.- Match limits: rg and fd apply their limits across all paths combined. No special handling needed — the existing limit logic works.
- Path deduplication: If the user explicitly passes
path: ".dreb/memory", don't add.dreb/memoryagain as an extra path. Check for overlap. - Relative paths in results: rg and fd will emit paths relative to each search root. When
.dreb/memory/is passed as a separate absolute path, rg emits results with the absolute path. The grep tool's result formatting may need to handle this — convert absolute.dreb/paths back to relative-to-cwd.
Acceptance criteria
-
.gitignoreuses**/.dreb/(blanket ignore) -
.dreb/memory/files no longer tracked by git -
searchtool indexes.dreb/memory/,.dreb/agents/,.dreb/extensions/content -
greptool finds matches inside tool-visible.dreb/subdirs -
findtool discovers files inside tool-visible.dreb/subdirs - None of the tools expose
.dreb/index/,.dreb/agent/, or.dreb/secrets/ - Tool-visible dirs only included when searching project root (not narrowed subdirectory)
- All new behavior has test coverage
-
npm testpasses
Plan addendum by mach6
Addendum v2: .dreb/ gitignore + tool visibility (blocklist approach)
ProblemAdding Key InsightWhen rg/fd receive an explicit path argument, they bypass # .gitignore has: .dreb/
rg --hidden pattern . ./.dreb/memory/ # finds matches — gitignore bypassed for explicit path
fd --hidden . . ./.dreb/agents/ # finds files — same behaviorThe search scanner already does this for global memory via Approach: Dynamic Discovery + BlocklistInstead of hardcoding which // Shared constant — the only dirs we HIDE from tools
const DREB_HIDDEN_SUBDIRS = new Set(["index", "agent", "secrets"]);Three items covers it:
Everything else is automatically tool-visible: At runtime, for each tool: const drebDir = path.join(root, ".dreb");
if (existsSync(drebDir)) {
const entries = readdirSync(drebDir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory() && !DREB_HIDDEN_SUBDIRS.has(entry.name)) {
additionalPaths.push(path.join(drebDir, entry.name));
}
}
// Also include top-level .dreb/ files (CONTEXT.md etc) — see per-tool notes
}Current tool behavior (read these files for full context)
Only grep, find, and search need changes. Deliverables1. Shared constant — new file
|
Progress UpdateImplemented .dreb/ gitignore + tool visibility (Option E, blocklist approach): New shared utility (
Scanner ( Grep ( Find ( Tests: 13 new tests across 2 files:
All 2299 tests pass. Build clean. Commit: Progress tracked by mach6 |
Code ReviewCriticalNo critical findings. ImportantFinding 1 — grep and find .dreb/ injection has no integration tests (test-reviewer + completeness-checker, confidence 97) Finding 2 — formatSearchResult still unexported and untested (code-reviewer + test-reviewer, confidence 100) Finding 3 — Symlinked subdirectories inside .dreb/ silently excluded from tool visibility (error-auditor, confidence 92) SuggestionsFinding 4 — Duplicate assertion in formatSearchCall projectDir test still present (code-reviewer + test-reviewer, confidence 100) expect(result).toContain("project");
expect(result).toContain("project"); // shortenPath outputThe second was meant to verify shortenPath output but checks the same substring. Provides zero incremental coverage. Finding 5 — Explicit Finding 6 — readdirSync failure in getDrebToolVisibleDirs silently hides all .dreb/ content (error-auditor, confidence 82) Strengths
Agents run: code-reviewer, error-auditor, test-reviewer, completeness-checker Reviewed by mach6 |
Review AssessmentClassifications
Action Plan
Assessment by mach6 |
…tests, duplicate assertion
Progress UpdateFixed 3 review findings from round 3: Finding 1 — grep/find .dreb/ integration tests: Added 6 integration tests to Finding 2 — formatSearchResult exported and tested: Exported Finding 3 — duplicate assertion fixed: Changed the duplicate All 2312 tests pass. Build and lint clean. Commit: Progress tracked by mach6 |
Closes #119
Closes #120
Three bundled improvements to the search tool:
Implementation plan posted as a comment below.