From e07349a9879d2c2239062dc2cf07cb469c039707 Mon Sep 17 00:00:00 2001 From: Rodion Mostovoi <36400912+rodion-m@users.noreply.github.com> Date: Wed, 8 Apr 2026 08:35:41 +0500 Subject: [PATCH 1/2] Add canonical semantic and grep skill flows --- README.md | 2 + skills/codealive-context-engine/SKILL.md | 37 ++++-- .../codealive-context-engine/scripts/fetch.py | 2 +- .../codealive-context-engine/scripts/grep.py | 115 ++++++++++++++++ .../scripts/lib/api_client.py | 125 ++++++++++++++++++ .../scripts/search.py | 115 +++++++--------- tests/test_cli_smoke.py | 6 +- tests/test_setup_and_client.py | 49 +++++++ 8 files changed, 368 insertions(+), 83 deletions(-) create mode 100755 skills/codealive-context-engine/scripts/grep.py diff --git a/README.md b/README.md index 82eca03..3f6ed05 100644 --- a/README.md +++ b/README.md @@ -81,8 +81,10 @@ The key is stored once and shared across all agents on the same machine. Start your agent and ask naturally: - *"How is authentication implemented?"* +- *"Find the exact regex or string match for this token parser"* - *"Show me error handling patterns across services"* - *"Find similar features to guide my implementation"* +- *"Show me who calls this handler and what it depends on"* No special commands needed — the agent picks up the skill automatically. diff --git a/skills/codealive-context-engine/SKILL.md b/skills/codealive-context-engine/SKILL.md index 5d48256..17ef8d7 100644 --- a/skills/codealive-context-engine/SKILL.md +++ b/skills/codealive-context-engine/SKILL.md @@ -38,7 +38,8 @@ Do NOT retry the failed script until setup completes successfully. | Tool | Script | Speed | Cost | Best For | |------|--------|-------|------|----------| | **List Data Sources** | `datasources.py` | Instant | Free | Discovering indexed repos and workspaces | -| **Search** | `search.py` | Fast | Low | Finding code locations, descriptions, identifiers | +| **Semantic Search** | `search.py` | Fast | Low | Finding relevant artifacts by meaning | +| **Grep Search** | `grep.py` | Fast | Low | Exact text and regex matches with line previews | | **Fetch Artifacts** | `fetch.py` | Fast | Low | Retrieving full content for search results | | **Artifact Relationships** | `relationships.py` | Fast | Low | Drilling into call graph, inheritance, references for one artifact | | **Chat with Codebase** | `chat.py` | Slow | High | Synthesized answers, architectural explanations | @@ -85,8 +86,9 @@ python scripts/datasources.py ```bash python scripts/search.py "JWT token validation" my-backend -python scripts/search.py "error handling patterns" workspace:platform-team --mode deep -python scripts/search.py "authentication flow" my-repo --description-detail full +python scripts/search.py "authentication flow" my-repo --path src/auth --ext .py +python scripts/grep.py "AuthService" my-repo +python scripts/grep.py "auth\\(" my-repo --regex ``` ### 3. Fetch full content (for external repos) @@ -135,11 +137,9 @@ python scripts/search.py [options] | Option | Description | |--------|-------------| -| `--mode auto` | Default. Intelligent semantic search — use 80% of the time | -| `--mode fast` | Quick lexical search for known terms | -| `--mode deep` | Exhaustive search for complex cross-cutting queries. Resource-intensive | -| `--description-detail short` | Default. Brief description of each result | -| `--description-detail full` | More detailed description of each result | +| `--max-results N` | Optional cap for the number of returned artifacts | +| `--path PATH` | Repo-relative path or directory scope (repeatable) | +| `--ext EXT` | File extension scope such as `.py` or `.ts` (repeatable) | **`description` is a triage pointer ONLY** — it tells you which artifacts are worth a closer look. It is NOT the source of truth and you must NOT draw @@ -148,6 +148,25 @@ source: use `fetch.py ` for external repos, or your editor's file-read tool on the path for repos in the current working directory. Treat only that real `content` as ground truth. +### `grep.py` — Exact / Regex Search + +Returns artifact-level matches with line previews. Use this when the pattern +itself matters more than semantic similarity. + +```bash +python scripts/grep.py [--regex] [--max-results N] [--path PATH] [--ext EXT] +``` + +| Option | Description | +|--------|-------------| +| `--regex` | Interpret the query as a regex pattern | +| `--max-results N` | Optional cap for the number of returned artifacts | +| `--path PATH` | Repo-relative path or directory scope (repeatable) | +| `--ext EXT` | File extension scope such as `.py` or `.ts` (repeatable) | + +Line previews are still search evidence, not source of truth. Use `fetch.py` +or your local file-read tool before drawing conclusions about behavior. + ### `fetch.py` — Fetch Artifact Content Retrieves the full source code content for artifacts found via search. Use this for external repositories you cannot access locally. @@ -270,7 +289,7 @@ This skill works standalone, but delivers the best experience when combined with | Component | What it provides | |-----------|-----------------| | **This skill** | Query patterns, workflow guidance, cost-aware tool selection | -| **MCP server** | Direct `codebase_search`, `fetch_artifacts`, `get_artifact_relationships`, `codebase_consultant`, `get_data_sources` tools | +| **MCP server** | Direct `semantic_search`, `grep_search`, `fetch_artifacts`, `get_artifact_relationships`, `codebase_consultant`, `get_data_sources` tools | When both are installed, prefer the MCP server's tools for direct operations and this skill's scripts for guided workflows. diff --git a/skills/codealive-context-engine/scripts/fetch.py b/skills/codealive-context-engine/scripts/fetch.py index 15e2606..6986178 100644 --- a/skills/codealive-context-engine/scripts/fetch.py +++ b/skills/codealive-context-engine/scripts/fetch.py @@ -15,7 +15,7 @@ # Fetch multiple artifacts python fetch.py "my-org/backend::src/auth.py::login" "my-org/backend::src/utils.py::helper" -Identifiers come from codebase_search results (the `identifier` field). +Identifiers come from semantic/grep search results (the `identifier` field). The format is: {owner/repo}::{path}::{symbol} (for symbols/chunks) {owner/repo}::{path} (for files) diff --git a/skills/codealive-context-engine/scripts/grep.py b/skills/codealive-context-engine/scripts/grep.py new file mode 100755 index 0000000..72bf733 --- /dev/null +++ b/skills/codealive-context-engine/scripts/grep.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +""" +CodeAlive Grep Search - exact text or regex search across indexed repositories. + +Usage: + python grep.py "AuthService" my-repo + python grep.py "auth\\(" my-repo --regex --max-results 25 + python grep.py "TODO" workspace:backend-team --path src --ext .py +""" + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent / "lib")) + +from api_client import CodeAliveClient + + +def format_grep_results(results: dict) -> str: + items = results.get("results", []) if isinstance(results, dict) else [] + if not items: + return "No results found." + + output = [] + for idx, result in enumerate(items, 1): + location = result.get("location", {}) + file_path = location.get("path") or result.get("path") + matches = result.get("matches", []) + + output.append(f"\n--- Result #{idx} [{result.get('kind', 'Artifact')}] ---") + if file_path: + output.append(f" File: {file_path}") + if result.get("identifier"): + output.append(f" Identifier: {result['identifier']}") + if result.get("matchCount") is not None: + output.append(f" Match count: {result['matchCount']}") + + for match in matches: + output.append( + " " + f"{match.get('lineNumber', '?')}:{match.get('startColumn', '?')}-" + f"{match.get('endColumn', '?')} {match.get('lineText', '')}" + ) + + output.append( + "\nHint: match previews are search evidence only. Fetch the full source " + "with `python fetch.py ` or read the local file before reasoning about behavior." + ) + return "\n".join(output) + + +def main(): + if len(sys.argv) < 3: + print("Error: Missing required arguments.", file=sys.stderr) + print( + "Usage: python grep.py [data_source2...] " + "[--regex] [--max-results N] [--path PATH] [--ext EXT]", + file=sys.stderr, + ) + sys.exit(1) + + query = sys.argv[1] + data_sources = [] + paths = [] + extensions = [] + max_results = None + regex = False + + i = 2 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--regex": + regex = True + i += 1 + elif arg == "--max-results" and i + 1 < len(sys.argv): + max_results = int(sys.argv[i + 1]) + i += 2 + elif arg == "--path" and i + 1 < len(sys.argv): + paths.append(sys.argv[i + 1]) + i += 2 + elif arg == "--ext" and i + 1 < len(sys.argv): + extensions.append(sys.argv[i + 1]) + i += 2 + elif arg == "--help": + print(__doc__) + sys.exit(0) + else: + data_sources.append(arg) + i += 1 + + if not data_sources: + print( + "Error: At least one data source is required. Run datasources.py to see available sources.", + file=sys.stderr, + ) + sys.exit(1) + + try: + client = CodeAliveClient() + results = client.grep_search( + query=query, + data_sources=data_sources, + paths=paths or None, + extensions=extensions or None, + max_results=max_results, + regex=regex, + ) + print(format_grep_results(results)) + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/skills/codealive-context-engine/scripts/lib/api_client.py b/skills/codealive-context-engine/scripts/lib/api_client.py index bd78603..5014bfe 100644 --- a/skills/codealive-context-engine/scripts/lib/api_client.py +++ b/skills/codealive-context-engine/scripts/lib/api_client.py @@ -268,6 +268,52 @@ def search( } return self._make_request("GET", "/api/search", params=params) + def semantic_search( + self, + query: str, + data_sources: List[str], + paths: Optional[List[str]] = None, + extensions: Optional[List[str]] = None, + max_results: Optional[int] = None, + ) -> Dict[str, Any]: + """Search indexed artifacts semantically using the canonical API.""" + params: Dict[str, Any] = { + "Query": query, + "Names": data_sources, + } + if paths: + params["Paths"] = paths + if extensions: + params["Extensions"] = extensions + if max_results is not None: + params["MaxResults"] = max_results + + return self._make_request("GET", "/api/search/semantic", params=params) + + def grep_search( + self, + query: str, + data_sources: List[str], + paths: Optional[List[str]] = None, + extensions: Optional[List[str]] = None, + max_results: Optional[int] = None, + regex: bool = False, + ) -> Dict[str, Any]: + """Search indexed artifacts by exact text or regex using the canonical API.""" + params: Dict[str, Any] = { + "Query": query, + "Names": data_sources, + "Regex": str(regex).lower(), + } + if paths: + params["Paths"] = paths + if extensions: + params["Extensions"] = extensions + if max_results is not None: + params["MaxResults"] = max_results + + return self._make_request("GET", "/api/search/grep", params=params) + def fetch_artifacts( self, identifiers: List[str], @@ -393,6 +439,8 @@ def main(): print("Commands:") print(" datasources [--all]") print(" search [data_source2...] [--mode auto|fast|deep] [--description-detail short|full]") + print(" semantic-search [data_source2...] [--path PATH] [--ext EXT] [--max-results N]") + print(" grep-search [data_source2...] [--regex] [--path PATH] [--ext EXT] [--max-results N]") print(" fetch [identifier2...]") print(" relationships [--profile callsOnly|inheritanceOnly|allRelevant|referencesOnly] [--max-count N]") print(" chat [data_source2...] [--conversation-id ID]") @@ -433,6 +481,83 @@ def main(): result = client.search(query, data_sources, mode, description_detail) print(json.dumps(result, indent=2)) + elif command == "semantic-search": + if len(sys.argv) < 4: + print("Usage: semantic-search [data_source2...] [--path PATH] [--ext EXT] [--max-results N]") + sys.exit(1) + + query = sys.argv[2] + data_sources = [] + paths = [] + extensions = [] + max_results = None + + i = 3 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--path" and i + 1 < len(sys.argv): + paths.append(sys.argv[i + 1]) + i += 2 + elif arg == "--ext" and i + 1 < len(sys.argv): + extensions.append(sys.argv[i + 1]) + i += 2 + elif arg == "--max-results" and i + 1 < len(sys.argv): + max_results = int(sys.argv[i + 1]) + i += 2 + else: + data_sources.append(arg) + i += 1 + + result = client.semantic_search( + query, + data_sources, + paths=paths or None, + extensions=extensions or None, + max_results=max_results, + ) + print(json.dumps(result, indent=2)) + + elif command == "grep-search": + if len(sys.argv) < 4: + print("Usage: grep-search [data_source2...] [--regex] [--path PATH] [--ext EXT] [--max-results N]") + sys.exit(1) + + query = sys.argv[2] + data_sources = [] + paths = [] + extensions = [] + max_results = None + regex = False + + i = 3 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--regex": + regex = True + i += 1 + elif arg == "--path" and i + 1 < len(sys.argv): + paths.append(sys.argv[i + 1]) + i += 2 + elif arg == "--ext" and i + 1 < len(sys.argv): + extensions.append(sys.argv[i + 1]) + i += 2 + elif arg == "--max-results" and i + 1 < len(sys.argv): + max_results = int(sys.argv[i + 1]) + i += 2 + else: + data_sources.append(arg) + i += 1 + + result = client.grep_search( + query, + data_sources, + paths=paths or None, + extensions=extensions or None, + max_results=max_results, + regex=regex, + ) + print(json.dumps(result, indent=2)) + elif command == "fetch": if len(sys.argv) < 3: print("Usage: fetch [identifier2...]") diff --git a/skills/codealive-context-engine/scripts/search.py b/skills/codealive-context-engine/scripts/search.py index 9a51d14..081cf44 100755 --- a/skills/codealive-context-engine/scripts/search.py +++ b/skills/codealive-context-engine/scripts/search.py @@ -1,61 +1,33 @@ #!/usr/bin/env python3 """ -CodeAlive Search - Semantic code search across indexed repositories +CodeAlive Semantic Search - semantic retrieval across indexed repositories. Usage: - python search.py "How is authentication handled?" my-repo --mode auto - python search.py "JWT token validation" workspace:backend-team - python search.py "React hooks patterns" react lodash --mode deep - python search.py "user registration" my-repo --description-detail full - -Examples: - # Search current project - python search.py "user registration logic" my-backend-repo - - # Search across workspace (multiple repos) - python search.py "error handling patterns" workspace:platform-team - - # Deep search for complex queries - python search.py "How do services communicate?" workspace:microservices --mode deep - - # Get full descriptions for more context - python search.py "authentication flow" my-repo --description-detail full - -IMPORTANT: `description` is a triage pointer ONLY. It tells you which results are -worth a closer look — it is NOT the source of truth. For every artifact you decide -is relevant you MUST load the real source via `fetch.py ` (external -repos) or your editor's file-read tool on the path (current working repo). Treat -only that real `content` as ground truth. + python search.py "How is authentication handled?" my-repo + python search.py "JWT token validation" workspace:backend-team --max-results 15 + python search.py "user registration" my-repo --path src/auth --ext .py """ import sys -import json from pathlib import Path -# Add lib directory to path sys.path.insert(0, str(Path(__file__).parent / "lib")) from api_client import CodeAliveClient def _format_byte_size(size_bytes: int) -> str: - """Format byte size to human-readable string.""" if size_bytes < 1024: return f"{size_bytes} B" - elif size_bytes < 1024 * 1024: + if size_bytes < 1024 * 1024: return f"{size_bytes / 1024:.1f} KB" - else: - return f"{size_bytes / (1024 * 1024):.1f} MB" + return f"{size_bytes / (1024 * 1024):.1f} MB" def format_search_results(results: dict) -> str: - """Format search results for display.""" if not results: return "No results found." - output = [] - - # Handle different response structures if isinstance(results, list): items = results elif "results" in results: @@ -66,15 +38,14 @@ def format_search_results(results: dict) -> str: if not items: return "No results found." + output = [] for idx, result in enumerate(items, 1): - # Extract location (API returns nested structure) location = result.get("location", {}) - file_path = location.get("path") or result.get("filePath") or result.get("file") or result.get("path") + file_path = location.get("path") or result.get("filePath") or result.get("path") range_info = location.get("range", {}) - start_line = range_info.get("start", {}).get("line") or result.get("startLine") or result.get("lineNumber") + start_line = range_info.get("start", {}).get("line") or result.get("startLine") end_line = range_info.get("end", {}).get("line") or result.get("endLine") - # Extract data source name ds = result.get("dataSource", {}) source_name = ds.get("name") if isinstance(ds, dict) else ds @@ -84,13 +55,11 @@ def format_search_results(results: dict) -> str: snippet = result.get("snippet", "") content_byte_size = result.get("contentByteSize") - # Extract file path from identifier (format: "{owner/repo}::{path}::{symbol_or_chunk}") if not file_path and "::" in identifier: parts = identifier.split("::") if len(parts) >= 2: file_path = parts[1] - # Format file:line reference loc_str = file_path or "" if loc_str and start_line and start_line > 0: if end_line and end_line != start_line and end_line > 0: @@ -98,7 +67,6 @@ def format_search_results(results: dict) -> str: else: loc_str = f"{file_path}:{start_line}" - # Compact output: one block per result output.append(f"\n--- Result #{idx} [{kind}] ---") if loc_str: output.append(f" File: {loc_str}") @@ -113,43 +81,44 @@ def format_search_results(results: dict) -> str: if description: output.append(f" Description: {description}") elif snippet: - output.append(f" Content (truncated): {snippet}") + output.append(f" Snippet: {snippet}") output.append(f"\n({len(items)} results)") output.append( - "\n💡 Hint: `Description` is only a pointer for triage — DO NOT base your " - "understanding on it.\n" - " For every result that looks relevant, load the real source:\n" - " • External repos: `python fetch.py `\n" - " • Current working repo: read the file at the shown path\n" - " Treat only the real `content` as ground truth.\n" - " To explore an artifact's call graph or inheritance, run " - "`python relationships.py `." + "\nHint: descriptions are triage pointers only. Fetch the full source " + "for relevant identifiers with `python fetch.py ` or read " + "the local file before drawing conclusions." ) return "\n".join(output) def main(): - """CLI interface for code search.""" if len(sys.argv) < 3: print("Error: Missing required arguments.", file=sys.stderr) - print("Usage: python search.py [data_source2...] [--mode auto|fast|deep] [--description-detail short|full]", file=sys.stderr) + print( + "Usage: python search.py [data_source2...] " + "[--max-results N] [--path PATH] [--ext EXT]", + file=sys.stderr, + ) sys.exit(1) query = sys.argv[1] - mode = "auto" - description_detail = "short" data_sources = [] + paths = [] + extensions = [] + max_results = None - # Parse arguments i = 2 while i < len(sys.argv): arg = sys.argv[i] - if arg == "--mode" and i + 1 < len(sys.argv): - mode = sys.argv[i + 1] + if arg == "--max-results" and i + 1 < len(sys.argv): + max_results = int(sys.argv[i + 1]) i += 2 - elif arg == "--description-detail" and i + 1 < len(sys.argv): - description_detail = sys.argv[i + 1] + elif arg == "--path" and i + 1 < len(sys.argv): + paths.append(sys.argv[i + 1]) + i += 2 + elif arg == "--ext" and i + 1 < len(sys.argv): + extensions.append(sys.argv[i + 1]) i += 2 elif arg == "--help": print(__doc__) @@ -159,30 +128,36 @@ def main(): i += 1 if not data_sources: - print("Error: At least one data source is required. Run datasources.py to see available sources.", file=sys.stderr) + print( + "Error: At least one data source is required. Run datasources.py to see available sources.", + file=sys.stderr, + ) sys.exit(1) try: client = CodeAliveClient() - print(f"🔍 Searching for: '{query}'", file=sys.stderr) - print(f"📚 Data sources: {', '.join(data_sources)}", file=sys.stderr) - print(f"⚙️ Mode: {mode}", file=sys.stderr) - if description_detail != "short": - print(f"📝 Description detail: {description_detail}", file=sys.stderr) + print(f"Semantic search: '{query}'", file=sys.stderr) + print(f"Data sources: {', '.join(data_sources)}", file=sys.stderr) + if max_results is not None: + print(f"Max results: {max_results}", file=sys.stderr) + if paths: + print(f"Paths: {', '.join(paths)}", file=sys.stderr) + if extensions: + print(f"Extensions: {', '.join(extensions)}", file=sys.stderr) print(file=sys.stderr) - results = client.search( + results = client.semantic_search( query=query, data_sources=data_sources, - mode=mode, - description_detail=description_detail + paths=paths or None, + extensions=extensions or None, + max_results=max_results, ) print(format_search_results(results)) - except Exception as e: - print(f"❌ Error: {e}", file=sys.stderr) + print(f"Error: {e}", file=sys.stderr) sys.exit(1) diff --git a/tests/test_cli_smoke.py b/tests/test_cli_smoke.py index 65cb507..bf38eeb 100644 --- a/tests/test_cli_smoke.py +++ b/tests/test_cli_smoke.py @@ -72,7 +72,7 @@ def chat_handler(_request): 200, [{"id": "repo-1", "name": "backend", "type": "Repository", "description": "Main backend"}], ), - ("GET", "/api/search?Query=auth&Mode=auto&IncludeContent=false&DescriptionDetail=Short&Names=backend"): search_handler, + ("GET", "/api/search/semantic?Query=auth&Names=backend"): search_handler, ("POST", "/api/search/artifacts"): fetch_handler, ("POST", "/api/chat/completions"): chat_handler, } @@ -97,7 +97,7 @@ def chat_handler(_request): # search must surface the "description is only a triage pointer" hint assert "triage" in search.stdout assert "fetch.py" in search.stdout - assert "ground truth" in search.stdout + assert "before drawing conclusions" in search.stdout assert fetch.returncode == 0, fetch.stderr assert "AuthService.login" in fetch.stdout @@ -114,7 +114,7 @@ def chat_handler(_request): assert [request["path"] for request in requests] == [ "/api/datasources/ready", - "/api/search?Query=auth&Mode=auto&IncludeContent=false&DescriptionDetail=Short&Names=backend", + "/api/search/semantic?Query=auth&Names=backend", "/api/search/artifacts", "/api/chat/completions", ] diff --git a/tests/test_setup_and_client.py b/tests/test_setup_and_client.py index 32267e3..fb3dfda 100644 --- a/tests/test_setup_and_client.py +++ b/tests/test_setup_and_client.py @@ -116,6 +116,55 @@ def chat_handler(request): assert chat_result["conversation_id"] == "conv_123" +def test_api_client_canonical_search_endpoints_use_scope_params(): + def semantic_handler(request): + assert "Query=auth" in request["path"] + assert "Names=backend" in request["path"] + assert "Paths=src%2Fauth.py" in request["path"] + assert "Extensions=.py" in request["path"] + assert "MaxResults=7" in request["path"] + return 200, { + "results": [ + { + "identifier": "org/repo::src/auth.py::AuthService", + "location": {"path": "src/auth.py"}, + } + ] + }, {} + + def grep_handler(request): + assert "Query=AuthService" in request["path"] + assert "Regex=true" in request["path"] + return 200, { + "results": [ + { + "identifier": "org/repo::src/auth.py", + "matchCount": 1, + "matches": [{"lineNumber": 12, "lineText": "class AuthService:"}], + } + ] + }, {} + + with mock_codealive_server( + { + ("GET", "/api/search/semantic?Query=auth&Names=backend&Paths=src%2Fauth.py&Extensions=.py&MaxResults=7"): semantic_handler, + ("GET", "/api/search/grep?Query=AuthService&Names=backend&Regex=true"): grep_handler, + } + ) as (base_url, _requests): + client = CodeAliveClient(api_key="skill-test-key", base_url=base_url) + semantic_result = client.semantic_search( + "auth", + ["backend"], + paths=["src/auth.py"], + extensions=[".py"], + max_results=7, + ) + grep_result = client.grep_search("AuthService", ["backend"], regex=True) + + assert semantic_result["results"][0]["identifier"] == "org/repo::src/auth.py::AuthService" + assert grep_result["results"][0]["matchCount"] == 1 + + def test_api_client_get_artifact_relationships_posts_expected_body(): received_bodies: list = [] From 7b21d869c7b37e33b69d218c76a7a7c0a3937e03 Mon Sep 17 00:00:00 2001 From: Rodion Mostovoi <36400912+rodion-m@users.noreply.github.com> Date: Thu, 9 Apr 2026 01:10:31 +0500 Subject: [PATCH 2/2] Update skill guidance for search-first workflow --- skills/codealive-context-engine/SKILL.md | 12 +++++---- .../references/query-patterns.md | 2 +- .../references/workflows.md | 27 ++++++++++--------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/skills/codealive-context-engine/SKILL.md b/skills/codealive-context-engine/SKILL.md index 17ef8d7..1904799 100644 --- a/skills/codealive-context-engine/SKILL.md +++ b/skills/codealive-context-engine/SKILL.md @@ -1,6 +1,6 @@ --- name: codealive-context-engine -description: Semantic code search and AI-powered codebase Q&A across indexed repositories. Use when understanding code beyond local files, exploring dependencies, discovering cross-project patterns, planning features, debugging, or onboarding. Queries like "How does X work?", "Show me Y patterns", "How is library Z used?". Provides search (fast, returns file locations and descriptions) and chat-with-codebase (slower, costs more, but returns synthesized answers). +description: Semantic code search and AI-powered codebase Q&A across indexed repositories. Use when understanding code beyond local files, exploring dependencies, discovering cross-project patterns, planning features, debugging, or onboarding. Queries like "How does X work?", "Show me Y patterns", "How is library Z used?". The default path is semantic search plus grep search; chat-with-codebase is slower, more expensive, and usually secondary. --- # CodeAlive Context Engine @@ -44,7 +44,9 @@ Do NOT retry the failed script until setup completes successfully. | **Artifact Relationships** | `relationships.py` | Fast | Low | Drilling into call graph, inheritance, references for one artifact | | **Chat with Codebase** | `chat.py` | Slow | High | Synthesized answers, architectural explanations | -**Cost guidance:** Search is lightweight and should be the default starting point. Chat with Codebase invokes an LLM on the server side, making it significantly more expensive per call — use it when you need a synthesized, ready-to-use answer rather than raw search results. +**Cost guidance:** `semantic_search` and `grep_search` are the default starting point. Chat with Codebase invokes an LLM on the server side, can take up to 30 seconds, and is significantly more expensive per call — use it only when you need a synthesized, ready-to-use answer rather than raw search results. + +**Highest-confidence guidance:** If your agent supports subagents and the task needs maximum reliability or depth, prefer a subagent-driven workflow that combines `search.py`, `grep.py`, `fetch.py`, `relationships.py`, and local file reads. `chat.py` is optional synthesis, not the default path. **Three-step workflow (search → triage → load real content):** 1. **Search** — find relevant code locations with descriptions and identifiers @@ -110,7 +112,7 @@ python scripts/relationships.py "my-org/backend::src/models.py::User" --profile python scripts/relationships.py "my-org/backend::src/svc.py::Service" --profile allRelevant --max-count 200 ``` -### 5. Chat with codebase (slower, richer answers) +### 5. Chat with codebase (slower, optional synthesis) ```bash python scripts/chat.py "Explain the authentication flow" my-backend @@ -211,7 +213,7 @@ python scripts/relationships.py [--profile PROFILE] [--max-count N] Sends your question to an AI consultant that has full context of the indexed codebase. Returns synthesized, ready-to-use answers. Supports conversation continuity for follow-ups. -**This is more expensive than search** because it runs an LLM inference on the server side. Prefer search when you just need to locate code. Use chat when you need explanations, comparisons, or architectural analysis. +**This is more expensive than search** because it runs an LLM inference on the server side. Prefer search when you just need to locate code. Use chat when you need explanations, comparisons, or architectural analysis after search. It can take up to 30 seconds. ```bash python scripts/chat.py [options] @@ -289,7 +291,7 @@ This skill works standalone, but delivers the best experience when combined with | Component | What it provides | |-----------|-----------------| | **This skill** | Query patterns, workflow guidance, cost-aware tool selection | -| **MCP server** | Direct `semantic_search`, `grep_search`, `fetch_artifacts`, `get_artifact_relationships`, `codebase_consultant`, `get_data_sources` tools | +| **MCP server** | Direct `semantic_search`, `grep_search`, `fetch_artifacts`, `get_artifact_relationships`, `chat`, `get_data_sources` tools plus deprecated aliases | When both are installed, prefer the MCP server's tools for direct operations and this skill's scripts for guided workflows. diff --git a/skills/codealive-context-engine/references/query-patterns.md b/skills/codealive-context-engine/references/query-patterns.md index a4c38fa..88eb326 100644 --- a/skills/codealive-context-engine/references/query-patterns.md +++ b/skills/codealive-context-engine/references/query-patterns.md @@ -298,7 +298,7 @@ Use when: 1. **Use natural language** - CodeAlive understands intent, not just keywords 2. **Be specific about context** - Include domain/layer info (API, database, frontend) 3. **Leverage workspaces** - Search across multiple repos for patterns -4. **Start with chat** - Ask "How does X work?" before searching +4. **Start with search** - Use semantic search first, then grep when the literal pattern matters; only use chat after you have evidence and still need synthesis 5. **Iterate** - Use follow-up questions to drill deeper 6. **Combine with local tools** - CodeAlive for discovery, Read for details 7. **Think like a librarian** - Focus on "what" and "why", not "where" diff --git a/skills/codealive-context-engine/references/workflows.md b/skills/codealive-context-engine/references/workflows.md index 49b6a30..a48b89f 100644 --- a/skills/codealive-context-engine/references/workflows.md +++ b/skills/codealive-context-engine/references/workflows.md @@ -28,24 +28,24 @@ Review output to understand: - What workspaces group related repos - Which data sources to use for exploration -### Step 2: Get Architectural Overview +### Step 2: Understand Entry Points ```bash -python chat.py "Provide an architectural overview of this codebase. What are the main components, how do they interact, and what's the tech stack?" my-backend-repo +python search.py "main application entry point, startup initialization" my-backend-repo ``` -### Step 3: Understand Entry Points +### Step 3: Explore Key Features ```bash -python search.py "main application entry point, startup initialization" my-backend-repo +python search.py "main features, core capabilities, major services" my-backend-repo ``` -### Step 4: Explore Key Features +### Step 4: Get Architectural Overview Only If Needed ```bash -python chat.py "What are the main features/capabilities of this system?" my-backend-repo +python chat.py "Provide an architectural overview of this codebase. What are the main components, how do they interact, and what's the tech stack?" my-backend-repo ``` ### Step 5: Understand Data Models ```bash -python search.py "database models, schemas, entity definitions" my-backend-repo --mode auto +python search.py "database models, schemas, entity definitions" my-backend-repo ``` **Progressive Discovery:** @@ -61,18 +61,19 @@ python search.py "database models, schemas, entity definitions" my-backend-repo ### Example: Understanding User Authentication -#### Step 1: Start with High-Level Question +#### Step 1: Start with Search ```bash -python chat.py "How is user authentication implemented? Describe the flow from login to session management" my-backend +python search.py "user authentication, login flow, session management" my-backend +python grep.py "refresh token" my-backend ``` -Save conversation_id for follow-up questions. - -#### Step 2: Find Entry Points +#### Step 2: Use Chat Only If You Still Need Synthesis ```bash -python search.py "user login endpoint, authentication API" my-backend +python chat.py "How is user authentication implemented? Describe the flow from login to session management" my-backend ``` +Save conversation_id for follow-up questions. + #### Step 3: Trace Through Layers ```bash # API Layer