graph-indexer 1.0.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/PROMPT.md CHANGED
@@ -1,143 +1,182 @@
1
- <agent_instructions name="graph-indexer-system-prompt">
2
- <context>
3
- You have access to a graph-indexer MCP server that has pre-indexed this entire codebase into a searchable AST graph. It is always faster, cheaper, and more accurate than reading files directly.
4
- </context>
5
-
6
- <absolute_rules>
7
- <rule id="1" name="Search before you read">NEVER use readFile, listDir, grep, find, or any native file tool as your first step. Every code discovery task starts with a graph-indexer tool. Violating this wastes 10-100x more tokens and is strictly forbidden.</rule>
8
- <rule id="2" name="Never read a full file to find one function">If you know a chunk ID from search results, call get_chunk(id) directly. If you need one function from a file, search for it; do not read the whole file.</rule>
9
- <rule id="3" name="Never modify an exported function without checking its callers">Before changing any function or class signature, call get_call_graph(functionName) to find all callers repo-wide. This takes 1 tool call. Skipping it risks breaking code you cannot see.</rule>
10
- <rule id="4" name="Use resolve_symbol for exact names, not search">If you know the exact function or class name (e.g., validateToken, UserService), call resolve_symbol(validateToken). It is O(1) and returns the definition instantly. Do not use search_code for names you already know.</rule>
11
- </absolute_rules>
12
-
13
- <decision_tree>
14
- <task name="Unfamiliar codebase, need overview" tool="get_repo_map()" />
15
- <task name="Focus on a subsystem" tool="get_repo_map(path_filter='auth')" />
16
- <task name="Know exact symbol name" tool="resolve_symbol('ExactName')" />
17
- <task name="Find concept or behavior" tool="search_code(query, detail='signatures')" />
18
- <task name="Need interface only (no body)" tool="get_chunk_summary(chunk_id)" />
19
- <task name="Need full implementation" tool="get_chunk(chunk_id)" />
20
- <task name="See all exports in one file" tool="get_file_skeleton('src/file.ts')" />
21
- <task name="Find who calls a function" tool="get_call_graph('functionName')" />
22
- <task name="Check index health or search mode" tool="list_index_stats()" />
23
- <task name="Browse file dependencies" tool="resource graph://dependencies/{file_path}" />
24
- </decision_tree>
25
-
26
- <token_management>
27
- <costs>
28
- <action tool="get_repo_map()" tokens="1500" context="Orienting in an unknown codebase" />
29
- <action tool="resolve_symbol('Name')" tokens="50" context="You know the exact name" />
30
- <action tool="search_code(detail='signatures', top_k=5)" tokens="100" context="Finding candidates to inspect" />
31
- <action tool="get_chunk_summary(id)" tokens="50" context="You need the interface, not the body" />
32
- <action tool="search_code(detail='smart', top_k=5)" tokens="750" context="You need to understand the logic" />
33
- <action tool="get_chunk(id)" tokens="300" context="You need the complete implementation" />
34
- <action tool="get_file_skeleton('file.ts')" tokens="80" context="You need all exports in one file" />
35
- <action tool="search_code(detail='full', top_k=5)" tokens="1500" context="Rarely; full bodies for all results" />
36
- <action tool="Direct file read" tokens="5000" context="Never - use the tools above" />
37
- </costs>
38
- <escalation_ladder>
39
- <step level="1" tool="search_code(detail='signatures')">Start here: names and types only</step>
40
- <step level="2" tool="get_chunk_summary(id)">Escalate: add docstring and calls</step>
41
- <step level="3" tool="search_code(detail='smart')">Escalate: add query-relevant snippets</step>
42
- <step level="4" tool="get_chunk(id)">Last resort: full body when you must</step>
43
- </escalation_ladder>
44
- </token_management>
45
-
46
- <workflows>
47
- <workflow name="Orienting in a new codebase">
48
- <step>get_repo_map() -> files sorted by importance (PageRank)</step>
49
- <step>identify key files, pick relevant ones</step>
50
- <step>resolve_symbol or search_code to drill in</step>
51
- </workflow>
52
- <workflow name="Finding where a concept is implemented">
53
- <step>search_code(query='semantic description', detail='signatures', top_k=5) -> read signature cards and topology</step>
54
- <step>if a result looks right: get_chunk_summary(id) to check interface</step>
55
- <step>if confirmed: get_chunk(id) for the full body</step>
56
- </workflow>
57
- <workflow name="Looking up a specific function or class">
58
- <step>resolve_symbol('ExactName') -> definition, type signature, cross-file topology</step>
59
- <step>get_chunk(id) if you need the body</step>
60
- </workflow>
61
- <workflow name="Understanding a file structure">
62
- <step>get_file_skeleton('src/module.ts') -> all exported symbols with line numbers (no bodies)</step>
63
- <step>resolve_symbol or get_chunk for specific items</step>
64
- </workflow>
65
- <workflow name="Safe refactoring">
66
- <step>get_call_graph('targetFunction') -> all callers repo-wide</step>
67
- <step>review impact before changing signature</step>
68
- <step>get_chunk for each caller if you need to update call sites</step>
69
- </workflow>
70
- </workflows>
71
-
72
- <query_guidelines>
73
- <description>search_code uses BM25 hybrid search. Query quality determines result quality.</description>
74
- <examples type="good">
75
- <example>JWT token validation and expiry check middleware</example>
76
- <example>HTTP adapter XMLHttpRequest browser send request</example>
77
- <example>dependency injection container resolve provider</example>
78
- <example>route registration path method handler</example>
79
- </examples>
80
- <examples type="bad">
81
- <example reason="matches everything with the word auth">auth</example>
82
- <example reason="thousands of results, meaningless ranking">request</example>
83
- <example reason="too broad">handler</example>
84
- </examples>
85
- <rules>
86
- <rule>Describe the behavior, not just the noun: 'parse and validate request body schema' not 'validation'</rule>
87
- <rule>Include language context: 'TypeScript interface generic constraint' not 'interface'</rule>
88
- <rule>If you know the name, use exact_tokens: search_code(query='token validation', exact_tokens='validateToken')</rule>
89
- <rule>For files: include path segments in query: 'middleware auth route' will boost auth/middleware.ts</rule>
90
- </rules>
91
- </query_guidelines>
92
-
93
- <detail_parameter tool="search_code">
94
- <option value="signatures" tokens="20">Name, type, params, return, topology (no body). Use for first pass finding candidates.</option>
95
- <option value="smart" default="true" tokens="150">Signature + query-matching lines only, boilerplate removed. Use for understanding logic without full body.</option>
96
- <option value="full" tokens="300">Complete source body. Use when you must see the full implementation.</option>
97
- <instruction>Always start with signatures, escalate only when you need more.</instruction>
98
- </detail_parameter>
99
-
100
- <anti_patterns>
101
- <anti_pattern action="readFile('src/auth/jwt.ts')">WRONG: Reading files to discover code. Never use as a first step.</anti_pattern>
102
- <anti_pattern action="search_code('validateToken')">WRONG: Searching for what you already have. You already have the chunk ID from search results.</anti_pattern>
103
- <anti_pattern action="search_code(query='...', detail='full')">WRONG: Using full detail by default. Only use when you need all bodies.</anti_pattern>
104
- <anti_pattern action="Edit function -> push -> find 12 other files break">WRONG: Modifying exported functions without impact check. Correct: get_call_graph('functionName') first.</anti_pattern>
105
- <anti_pattern action="search_code(query='error')">WRONG: Generic one-word queries. Use semantic descriptions like 'HTTP error response handler middleware'.</anti_pattern>
106
- <anti_pattern action="Ignoring topology in search results">WRONG: If results show 'Used by: auth.ts, routes.ts', read that, do not re-search.</anti_pattern>
107
- <anti_pattern action="Re-searching for the same concept">WRONG: search_code returns chunk ID -> call get_chunk(id), not another search_code.</anti_pattern>
108
- </anti_patterns>
109
-
110
- <topology_info>
111
- <description>Every search_code and resolve_symbol result includes topology for free. Use this topology to navigate without additional tool calls.</description>
112
- <fields>
113
- <field name="Deps">What this file imports (and which symbols it uses from each)</field>
114
- <field name="Used by">Which other files import this file</field>
115
- <field name="Calls">Functions this chunk calls directly</field>
116
- </fields>
117
- </topology_info>
118
-
119
- <index_health>
120
- <troubleshooting>
121
- <step>Call list_index_stats() to check chunk count, vector status, daemon status, index age.</step>
122
- <step>If index age > 1h with no activity, ask the user to run npm run mcp:index.</step>
123
- <step>If a symbol is missing from resolve_symbol, fall back to search_code.</step>
124
- </troubleshooting>
125
- <search_modes>
126
- <mode name="Hybrid">semantic + lexical RRF, full quality, Ollama running</mode>
127
- <mode name="Lexical only">BM25 only, Ollama unavailable; still high quality (R@5=1.00)</mode>
128
- </search_modes>
129
- </index_health>
130
-
131
- <quick_reference>
132
- <command name="get_repo_map()" returns="full codebase overview (~1500 tok)" />
133
- <command name="get_repo_map(path_filter='auth')" returns="subsystem overview (~300 tok)" />
134
- <command name="resolve_symbol('ExactName')" returns="instant definition + topology" />
135
- <command name="search_code('concept', 'signatures')" returns="find candidates (~100 tok)" />
136
- <command name="get_chunk_summary(id)" returns="interface view (~50 tok)" />
137
- <command name="get_chunk(id)" returns="full body (~300 tok)" />
138
- <command name="get_file_skeleton('path/file.ts')" returns="all exports in file (~80 tok)" />
139
- <command name="get_call_graph('name')" returns="all callers, pre-refactor check" />
140
- <command name="list_index_stats()" returns="index health" />
141
- <command name="graph://dependencies/{file_path}" returns="bidirectional dep graph" />
142
- </quick_reference>
143
- </agent_instructions>
1
+ # graph-indexer — Agent Instructions
2
+
3
+ ---
4
+
5
+ ## Prime directive
6
+
7
+ This codebase is **pre-indexed**. The `graph-indexer` MCP server answers code
8
+ questions from an AST-precise search index in tens of tokens, with cross-file
9
+ topology your file tools cannot see.
10
+
11
+ **Every code discovery task starts with a graph-indexer tool. Never start with
12
+ a native file tool** — no `read file`, `list directory`, `grep`, `codebase
13
+ search`, `find`, or equivalent — regardless of what your IDE calls them.
14
+ Reading a file to "look around" costs 5,000–15,000 tokens; the same answer via
15
+ the index costs 50–700. The difference compounds over every step of your
16
+ session.
17
+
18
+ Native tools are a **last resort**, permitted only under the fallback rules at
19
+ the end of this document. Editing files is unaffected — write code with your
20
+ normal tools; *discovery* belongs to the index.
21
+
22
+ ---
23
+
24
+ ## The five rules
25
+
26
+ 1. **Search before you read.** First step of any discovery task is
27
+ `search_code`, `resolve_symbol`, or `get_repo_map` — never a file read.
28
+ 2. **Know the name? Don't search it.** `resolve_symbol("validateToken")` is an
29
+ O(1) exact lookup with topology included. Use it whenever you know the
30
+ symbol's exact name. Use `search_code` only for concepts and behaviour.
31
+ 3. **Never read a whole file to get one function.** Search results give you a
32
+ chunk ID → `get_chunk(id)` returns exactly that function's body.
33
+ 4. **Never change a signature blind.** Before modifying any exported
34
+ function/class, `get_call_graph("name")` lists every caller repo-wide in
35
+ one call. Skipping this breaks code you cannot see.
36
+ 5. **Escalate token spend stepwise.** signatures → summary → smart → full
37
+ body. Start cheap; pay for bodies only when you must (ladder below).
38
+
39
+ ---
40
+
41
+ ## Tool selection — decision table
42
+
43
+ | You need… | Call | ~Tokens |
44
+ | :--- | :--- | ---: |
45
+ | Orientation in an unfamiliar repo | `get_repo_map()` | 1,500 |
46
+ | Orientation in one subsystem | `get_repo_map(path_filter: "auth")` | 300 |
47
+ | A symbol you can name exactly | `resolve_symbol("UserService")` | 50 |
48
+ | Code for a concept/behaviour | `search_code(query, detail: "signatures")` | 100 |
49
+ | The interface of a found chunk | `get_chunk_summary(id)` | 50 |
50
+ | Interfaces of everything a chunk calls | `get_chunk_summary(id, expand_calls: true)` | 150 |
51
+ | The full implementation | `get_chunk(id)` | 300 |
52
+ | All exports of one known file | `get_file_skeleton("src/file.ts")` | 80 |
53
+ | Who calls a function (pre-refactor) | `get_call_graph("name")` | 100 |
54
+ | What a file imports / who imports it | resource `graph://dependencies/{path}` | 100 |
55
+ | Index health / why results look off | `list_index_stats()` | 100 |
56
+ | *(comparison)* reading one file directly | — | 5,000+ |
57
+
58
+ ### Escalation ladder (token budget)
59
+
60
+ ```
61
+ 1. search_code(query, detail: "signatures", top_k: 5) ~100 tok — find candidates
62
+ 2. get_chunk_summary(id) ~50 tok — confirm the interface
63
+ 3. search_code(query, detail: "smart") ~750 tok — see query-relevant lines
64
+ 4. get_chunk(id) ~300 tok — full body, last resort
65
+ ```
66
+
67
+ Stop climbing as soon as you can answer. Most questions die at step 1–2.
68
+
69
+ ---
70
+
71
+ ## Writing queries that hit
72
+
73
+ `search_code` is hybrid (BM25 keywords + semantic vectors) and **detects your
74
+ query style automatically**. Both styles are first-class:
75
+
76
+ **Keyword style** — when you know domain words or partial names:
77
+ - `JWT token validation expiry middleware`
78
+ - `route registration path method handler`
79
+ - Partial name known? Pin it: `search_code(query: "token validation", exact_tokens: "validateToken")` → guaranteed rank-1.
80
+ - Use resolve_symbol("Name") when you ONLY need the definition of that specific symbol. Use search_code(query: "...", exact_tokens: "Name") when you want to explore a concept but want to guarantee a specific symbol appears at the very top of the results.
81
+
82
+ **Natural-language style** — when you only know the behaviour:
83
+ - `How does the application parse incoming JSON payloads from the client?`
84
+ - `the logic that decides whether a requested URL matches a registered route`
85
+ - `stopping an HTTP call that takes too long or is no longer needed`
86
+
87
+ Rules of thumb:
88
+ - Describe **behaviour, not nouns**: `parse and validate request body schema`, not `validation`.
89
+ - One-word queries (`auth`, `request`, `handler`) are useless — thousands of matches.
90
+ - Include path hints when you have them: `middleware auth route` boosts `auth/middleware.ts`.
91
+ - **A keyword miss is not a dead end**: rephrase the same need as a full
92
+ behavioural sentence — the semantic channel finds code that shares none of
93
+ your words. This rephrase is *mandatory* before any native-tool fallback.
94
+ - Slow-but-smarter option: `search_code(..., rerank: true)` has a local LLM
95
+ judge reorder the top results (~1–2 s). Use it when a natural-language query
96
+ returns plausible-but-not-quite results.
97
+
98
+ ### Reading results
99
+
100
+ Every result card includes **free topology** — use it instead of new searches:
101
+ - `Deps:` what this file imports (with key symbols per import)
102
+ - `Used by:` which files import this one
103
+ - `Calls:` functions this chunk invokes
104
+ - `ID:` pass to `get_chunk` / `get_chunk_summary` — never re-search what you already found.
105
+
106
+ A result with node type `re_export` means the symbol is re-exported from a
107
+ dependency (e.g. `fastapi` re-exporting Starlette's `BackgroundTasks`): the
108
+ implementation lives outside this repo — do not hunt for it in the codebase.
109
+
110
+ ---
111
+
112
+ ## Standard workflows
113
+
114
+ **Unfamiliar codebase** → `get_repo_map()` → pick files → `resolve_symbol` /
115
+ `search_code` to drill in.
116
+
117
+ **"Where is X implemented?"** → `search_code(behavioural query, detail:
118
+ "signatures")` → `get_chunk_summary(best id)` → `get_chunk(id)` only if you
119
+ must see the body.
120
+
121
+ **Safe refactor** → `get_call_graph("target")` → review callers →
122
+ `get_chunk(callerId)` for each call site you need to update → edit with your
123
+ normal tools.
124
+
125
+ **Understanding one file** → `get_file_skeleton(path)` (all exports + line
126
+ numbers, no bodies) → drill into specific symbols.
127
+
128
+ **Debugging a behaviour** → natural-language `search_code` describing the
129
+ symptom's mechanism → follow `Calls:` topology instead of re-searching.
130
+
131
+ ---
132
+
133
+ ## Anti-patterns (each of these is a bug in your behaviour)
134
+
135
+ - ❌ Reading a file as your *first* move on any question.
136
+ - ❌ `search_code("validateToken")` — you know the name; that's `resolve_symbol`.
137
+ - ❌ Re-searching a concept you already have a chunk ID for.
138
+ - ❌ `detail: "full"` by default — signatures first, always.
139
+ - ❌ Editing an exported signature without `get_call_graph` first.
140
+ - ❌ Giving up after one keyword query without trying a behavioural rephrase.
141
+ - ❌ Ignoring `Used by:` / `Calls:` topology and issuing new searches for it.
142
+ - ❌ Re-indexing after edits: Do not tell the user to re-index or attempt to re-index after you modify a file. Graph Indexer has a live daemon (watch-daemon.mjs) that instantly updates the index in the background using SQLite WAL. Your next search will automatically see your changes.
143
+
144
+ ---
145
+
146
+ ## Fallback to native tools — the ONLY permitted cases
147
+
148
+ You may use native file/search tools **only** when one of these is true:
149
+
150
+ 1. **The index says no.** You tried BOTH query styles (keyword + behavioural
151
+ sentence) and `resolve_symbol`, and the target genuinely isn't returned.
152
+ 2. **The index is unhealthy.** `list_index_stats()` shows 0 chunks, a missing
153
+ index, or a clearly stale index that the daemon isn't updating — tell the
154
+ user to run `npm run mcp:index`, then fall back for now.
155
+ 3. **Non-code files.** Configs, lockfiles, markdown, data files, generated
156
+ artifacts — the index covers source code chunks; plain files are fair game.
157
+ 4. **You need exact current file state for an edit** you are about to make
158
+ (e.g. precise surrounding lines to produce a diff) — *after* the index
159
+ located the file and line range for you.
160
+
161
+ When you do fall back, scope it: read the one file the index pointed you to —
162
+ never directory-walk or repo-grep what the index already answered.
163
+
164
+ ---
165
+
166
+ ## Quick reference
167
+
168
+ ```
169
+ search_code(query, exact_tokens?, detail?, top_k?, rerank?) hybrid search, topology included
170
+ resolve_symbol(symbol) O(1) exact definition lookup
171
+ get_chunk(chunk_id, view?) full body of one chunk
172
+ get_chunk_summary(chunk_id, expand_calls?) interface only, ~50 tok
173
+ get_file_skeleton(file_path) all exports of a file, no bodies
174
+ get_call_graph(target_function) every caller repo-wide
175
+ get_repo_map(path_filter?, max_files?) PageRank-ordered codebase map
176
+ list_index_stats() index health + search mode
177
+ graph://dependencies/{file_path} bidirectional import topology
178
+ ```
179
+
180
+ **Detail levels:** `signatures` ~20 tok/result · `smart` (default) ~150 ·
181
+ `full` ~300. **Search modes:** hybrid (semantic + lexical) when Ollama runs;
182
+ lexical-only otherwise — in lexical-only mode prefer keyword-style queries.