@graphpilot-oss/graphpilot 0.0.1 → 1.0.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/CHANGELOG.md +72 -126
- package/README.md +290 -102
- package/dist/cli.js +41 -1
- package/dist/cli.js.map +1 -1
- package/dist/edges.js +22 -11
- package/dist/edges.js.map +1 -1
- package/dist/indexer.js +3 -3
- package/dist/indexer.js.map +1 -1
- package/dist/init.d.ts +28 -0
- package/dist/init.js +112 -0
- package/dist/init.js.map +1 -0
- package/dist/interactions.d.ts +5 -4
- package/dist/interactions.js +0 -0
- package/dist/interactions.js.map +1 -1
- package/dist/mcp.js +119 -90
- package/dist/mcp.js.map +1 -1
- package/dist/repo-resolve.d.ts +47 -0
- package/dist/repo-resolve.js +195 -0
- package/dist/repo-resolve.js.map +1 -0
- package/dist/storage.js +10 -1
- package/dist/storage.js.map +1 -1
- package/dist/symbols.js +26 -2
- package/dist/symbols.js.map +1 -1
- package/dist/validation.js +30 -4
- package/dist/validation.js.map +1 -1
- package/dist/validators.d.ts +1 -5
- package/dist/validators.js +0 -11
- package/dist/validators.js.map +1 -1
- package/dist/watcher.d.ts +10 -0
- package/dist/watcher.js +70 -7
- package/dist/watcher.js.map +1 -1
- package/examples/README.md +105 -0
- package/examples/claude-code/README.md +125 -0
- package/examples/claude-code/claude-routing.md +102 -0
- package/examples/claude-code/claude_config.json +8 -0
- package/examples/cline/.clinerules +39 -0
- package/examples/cline/README.md +104 -0
- package/examples/cline/cline_mcp_settings.json +10 -0
- package/examples/continue/.continuerules +39 -0
- package/examples/continue/README.md +98 -0
- package/examples/continue/config.json +13 -0
- package/examples/cursor/.cursorrules +39 -0
- package/examples/cursor/README.md +98 -0
- package/examples/cursor/mcp.json +11 -0
- package/examples/windsurf/.windsurfrules +39 -0
- package/examples/windsurf/README.md +85 -0
- package/examples/windsurf/mcp_config.json +8 -0
- package/package.json +14 -4
- package/.editorconfig +0 -15
- package/.github/CODEOWNERS +0 -22
- package/.github/FUNDING.yml +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -33
- package/.github/ISSUE_TEMPLATE/config.yml +0 -5
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -23
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -19
- package/.github/dependabot.yml +0 -15
- package/.github/workflows/ci.yml +0 -62
- package/.github/workflows/release.yml +0 -50
- package/.prettierignore +0 -19
- package/.prettierrc.json +0 -20
- package/CODE_OF_CONDUCT.md +0 -83
- package/CONTRIBUTING.md +0 -111
- package/bench/README.md +0 -544
- package/bench/results/agent-tier-2026-05-22.md +0 -28
- package/bench/results/agent-tier-summary.md +0 -44
- package/bench/results/baseline-tier-2026-05-22.md +0 -23
- package/bench/results/baseline.json +0 -810
- package/bench/results/baseline.md +0 -28
- package/bench/run-agent-tier-automated.ts +0 -234
- package/bench/run-agent-tier.md +0 -125
- package/bench/run-baseline-tier.ts +0 -200
- package/bench/run.ts +0 -210
- package/bench/runner-baseline.ts +0 -177
- package/bench/runner-graphpilot.ts +0 -131
- package/bench/score-agent-tier.ts +0 -191
- package/bench/score.ts +0 -59
- package/bench/tasks.ts +0 -236
- package/dist/provenance.d.ts +0 -74
- package/dist/provenance.js +0 -95
- package/dist/provenance.js.map +0 -1
- package/docs/architecture.md +0 -311
- package/docs/limitations.md +0 -156
- package/docs/mcp-setup.md +0 -231
- package/docs/quickstart.md +0 -202
- package/eslint.config.js +0 -148
- package/lefthook.yml +0 -81
- package/pnpm-workspace.yaml +0 -6
- package/scripts/smoke-stdio.mjs +0 -97
- package/src/cli.ts +0 -171
- package/src/edges.ts +0 -202
- package/src/git.ts +0 -255
- package/src/graph-schema.ts +0 -229
- package/src/impact.ts +0 -218
- package/src/indexer.ts +0 -152
- package/src/interactions.ts +0 -0
- package/src/mcp.ts +0 -652
- package/src/parser.ts +0 -138
- package/src/provenance.ts +0 -115
- package/src/query.ts +0 -148
- package/src/redact.ts +0 -122
- package/src/storage.ts +0 -115
- package/src/symbols.ts +0 -173
- package/src/validation.ts +0 -69
- package/src/validators.ts +0 -253
- package/src/watcher.ts +0 -383
- package/tests/edges.test.ts +0 -175
- package/tests/fixtures/sample.ts +0 -32
- package/tests/git.test.ts +0 -303
- package/tests/graph-schema.test.ts +0 -321
- package/tests/impact.test.ts +0 -454
- package/tests/interactions.test.ts +0 -180
- package/tests/lint-policy.test.ts +0 -106
- package/tests/mcp-stdio.test.ts +0 -171
- package/tests/mcp.test.ts +0 -335
- package/tests/parser.test.ts +0 -31
- package/tests/provenance.test.ts +0 -132
- package/tests/query.test.ts +0 -160
- package/tests/redact.test.ts +0 -167
- package/tests/security.test.ts +0 -144
- package/tests/symbols.test.ts +0 -78
- package/tests/validators.test.ts +0 -193
- package/tests/watcher.test.ts +0 -250
- package/tsconfig.json +0 -18
package/bench/score.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Scoring: precision/recall/F1 of a returned set against ground truth.
|
|
3
|
-
*
|
|
4
|
-
* We score whether the set of names returned MATCHES the expected set,
|
|
5
|
-
* not whether it's identical — partial credit is honest. F1 is the
|
|
6
|
-
* primary metric. Per-task results show all three.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export interface Scored {
|
|
10
|
-
precision: number;
|
|
11
|
-
recall: number;
|
|
12
|
-
f1: number;
|
|
13
|
-
intersectionSize: number;
|
|
14
|
-
truePositives: string[];
|
|
15
|
-
falsePositives: string[];
|
|
16
|
-
falseNegatives: string[];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function score(returned: string[], groundTruth: string[]): Scored {
|
|
20
|
-
const ret = new Set(returned);
|
|
21
|
-
const gt = new Set(groundTruth);
|
|
22
|
-
|
|
23
|
-
const tp: string[] = [];
|
|
24
|
-
for (const r of ret) if (gt.has(r)) tp.push(r);
|
|
25
|
-
|
|
26
|
-
const fp: string[] = [];
|
|
27
|
-
for (const r of ret) if (!gt.has(r)) fp.push(r);
|
|
28
|
-
|
|
29
|
-
const fn: string[] = [];
|
|
30
|
-
for (const g of gt) if (!ret.has(g)) fn.push(g);
|
|
31
|
-
|
|
32
|
-
// Edge case: empty ground truth + empty return = perfect.
|
|
33
|
-
// (The recall-miss task hits this.)
|
|
34
|
-
if (gt.size === 0 && ret.size === 0) {
|
|
35
|
-
return {
|
|
36
|
-
precision: 1,
|
|
37
|
-
recall: 1,
|
|
38
|
-
f1: 1,
|
|
39
|
-
intersectionSize: 0,
|
|
40
|
-
truePositives: [],
|
|
41
|
-
falsePositives: [],
|
|
42
|
-
falseNegatives: [],
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const precision = ret.size === 0 ? 0 : tp.length / ret.size;
|
|
47
|
-
const recall = gt.size === 0 ? 0 : tp.length / gt.size;
|
|
48
|
-
const f1 = precision + recall === 0 ? 0 : (2 * precision * recall) / (precision + recall);
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
precision,
|
|
52
|
-
recall,
|
|
53
|
-
f1,
|
|
54
|
-
intersectionSize: tp.length,
|
|
55
|
-
truePositives: tp.sort(),
|
|
56
|
-
falsePositives: fp.sort(),
|
|
57
|
-
falseNegatives: fn.sort(),
|
|
58
|
-
};
|
|
59
|
-
}
|
package/bench/tasks.ts
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The 10-task benchmark corpus. Hand-curated against graphpilot indexing
|
|
3
|
-
* itself, so anyone can `git clone` + `pnpm install` + `pnpm bench` and
|
|
4
|
-
* see the same numbers.
|
|
5
|
-
*
|
|
6
|
-
* Each task carries its OWN ground truth so this file is the single
|
|
7
|
-
* source of truth for what "correct" means. Ground truth was computed
|
|
8
|
-
* by probing the live index at the time this file was authored; if the
|
|
9
|
-
* corpus repo (graphpilot itself) is materially edited, ground truth
|
|
10
|
-
* needs to be refreshed (see bench/README.md §Refreshing).
|
|
11
|
-
*
|
|
12
|
-
* Mix of task types is deliberate:
|
|
13
|
-
* - 7 tasks where GraphPilot's structural index should win
|
|
14
|
-
* - 1 task that's roughly a tie (negative result)
|
|
15
|
-
* - 1 task where grep should outperform GraphPilot (string-literal
|
|
16
|
-
* search). Keeping this in the corpus is what makes the benchmark
|
|
17
|
-
* honest.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
export type TaskKind =
|
|
21
|
-
| 'callers' // who calls X?
|
|
22
|
-
| 'recall' // find symbol by exact name
|
|
23
|
-
| 'recall-substring' // find symbols whose name contains a fragment
|
|
24
|
-
| 'kind-filter' // find all symbols of kind=...
|
|
25
|
-
| 'impact' // blast-radius analysis
|
|
26
|
-
| 'impact-since' // differential impact: callers in changed files since a ref
|
|
27
|
-
| 'tests-affected' // which tests depend on this symbol
|
|
28
|
-
| 'recall-miss' // symbol that doesn't exist
|
|
29
|
-
| 'string-literal'; // text-only search — grep should win
|
|
30
|
-
|
|
31
|
-
export interface Task {
|
|
32
|
-
id: string;
|
|
33
|
-
description: string;
|
|
34
|
-
/** What a developer / agent would naturally ask. */
|
|
35
|
-
prompt: string;
|
|
36
|
-
kind: TaskKind;
|
|
37
|
-
/** Argument to the task's natural tool (graphpilot side). */
|
|
38
|
-
query: string;
|
|
39
|
-
/**
|
|
40
|
-
* Set of expected symbol names (sorted) that the correct answer must
|
|
41
|
-
* contain. For tests-affected tasks, this is the set of test file paths.
|
|
42
|
-
*/
|
|
43
|
-
groundTruth: string[];
|
|
44
|
-
/** Which side we expect to win on F1 score. */
|
|
45
|
-
expectedWinner: 'graphpilot' | 'grep' | 'tie';
|
|
46
|
-
/** Helpful for the README/results: structural vs text-only. */
|
|
47
|
-
difficulty: 'low' | 'medium' | 'high';
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export const TASKS: Task[] = [
|
|
51
|
-
{
|
|
52
|
-
id: 't01-callers-analyzeImpact',
|
|
53
|
-
description: 'Find every function that calls analyzeImpact',
|
|
54
|
-
prompt: 'In this repo, what functions call analyzeImpact?',
|
|
55
|
-
kind: 'callers',
|
|
56
|
-
query: 'analyzeImpact',
|
|
57
|
-
groundTruth: ['handleGpImpact'],
|
|
58
|
-
expectedWinner: 'graphpilot',
|
|
59
|
-
difficulty: 'low',
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
id: 't02-callers-extractSymbols',
|
|
63
|
-
description: 'Find every direct caller of extractSymbols',
|
|
64
|
-
prompt: 'Who calls extractSymbols in this codebase?',
|
|
65
|
-
kind: 'callers',
|
|
66
|
-
query: 'extractSymbols',
|
|
67
|
-
groundTruth: ['indexDirectory', 'applyUpdate', 'symbolsOf'],
|
|
68
|
-
expectedWinner: 'graphpilot',
|
|
69
|
-
difficulty: 'low',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
id: 't03-callers-validateRootPath',
|
|
73
|
-
description: 'Find every direct caller of validateRootPath',
|
|
74
|
-
prompt: 'Where is validateRootPath used in the codebase? List every callsite.',
|
|
75
|
-
kind: 'callers',
|
|
76
|
-
query: 'validateRootPath',
|
|
77
|
-
// Note: GraphWatcher constructor calls validateRootPath; the SymbolRecord
|
|
78
|
-
// for that constructor has name="constructor" (not "GraphWatcher").
|
|
79
|
-
groundTruth: ['cmdIndex', 'main', 'handleGpIndex', 'constructor'],
|
|
80
|
-
expectedWinner: 'graphpilot',
|
|
81
|
-
difficulty: 'medium',
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
id: 't04-recall-substring-parse',
|
|
85
|
-
description: 'Find every symbol whose name contains "parse"',
|
|
86
|
-
prompt: 'List every function, class, or interface whose name contains "parse".',
|
|
87
|
-
kind: 'recall-substring',
|
|
88
|
-
query: 'parse',
|
|
89
|
-
groundTruth: ['ParsedFile', 'getParser', 'parseFile', 'parseSource', 'parseToken'],
|
|
90
|
-
expectedWinner: 'graphpilot',
|
|
91
|
-
difficulty: 'low',
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
id: 't05-kind-filter-interfaces',
|
|
95
|
-
description: 'Enumerate all TypeScript interfaces under src/',
|
|
96
|
-
prompt: 'List every TypeScript interface defined under src/.',
|
|
97
|
-
kind: 'kind-filter',
|
|
98
|
-
query: 'interface', // means: kind === "interface"
|
|
99
|
-
groundTruth: [
|
|
100
|
-
'CallEdge',
|
|
101
|
-
'EdgeQueryOptions',
|
|
102
|
-
'Graph',
|
|
103
|
-
'GpCallersArgs',
|
|
104
|
-
'GpImpactArgs',
|
|
105
|
-
'GpIndexArgs',
|
|
106
|
-
'GpRecallArgs',
|
|
107
|
-
'GpStatsArgs',
|
|
108
|
-
'ImpactCaller',
|
|
109
|
-
'ImpactOptions',
|
|
110
|
-
'ImpactResult',
|
|
111
|
-
'IndexOptions',
|
|
112
|
-
'IndexResult',
|
|
113
|
-
'InteractionEntry',
|
|
114
|
-
'ParsedFile',
|
|
115
|
-
'RawCall',
|
|
116
|
-
'RecallOptions',
|
|
117
|
-
'SecretPattern',
|
|
118
|
-
'SymbolRecord',
|
|
119
|
-
'ToolResult',
|
|
120
|
-
'UpdateResult',
|
|
121
|
-
'ValidationContext',
|
|
122
|
-
'WatcherOptions',
|
|
123
|
-
],
|
|
124
|
-
expectedWinner: 'graphpilot',
|
|
125
|
-
difficulty: 'medium',
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
id: 't06-impact-extractSymbols-depth2',
|
|
129
|
-
description: 'Compute blast radius of changing extractSymbols (depth 2)',
|
|
130
|
-
prompt:
|
|
131
|
-
"If I change extractSymbols's signature, what functions will I need to update? Include indirect callers up to two hops.",
|
|
132
|
-
kind: 'impact',
|
|
133
|
-
query: 'extractSymbols',
|
|
134
|
-
// Direct callers + their direct callers
|
|
135
|
-
groundTruth: [
|
|
136
|
-
// d=1
|
|
137
|
-
'indexDirectory',
|
|
138
|
-
'applyUpdate',
|
|
139
|
-
'symbolsOf',
|
|
140
|
-
// d=2 — callers of the above
|
|
141
|
-
'cmdIndex',
|
|
142
|
-
'handleGpIndex',
|
|
143
|
-
'handleEvent',
|
|
144
|
-
// symbolsOf has no callers in production code; it's only in tests
|
|
145
|
-
],
|
|
146
|
-
expectedWinner: 'graphpilot',
|
|
147
|
-
difficulty: 'high',
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
id: 't07-tests-affected-parseFile',
|
|
151
|
-
description: 'Identify test files that exercise parseFile (directly)',
|
|
152
|
-
prompt: 'If I change the behavior of parseFile, which test files are most likely to break?',
|
|
153
|
-
kind: 'tests-affected',
|
|
154
|
-
query: 'parseFile',
|
|
155
|
-
// The test file containing symbolsOf which calls parseFile
|
|
156
|
-
groundTruth: ['tests/symbols.test.ts'],
|
|
157
|
-
expectedWinner: 'graphpilot',
|
|
158
|
-
difficulty: 'medium',
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
id: 't08-recall-substring-args',
|
|
162
|
-
description: 'Find every MCP-tool input-args interface',
|
|
163
|
-
prompt: 'List every TypeScript type whose name ends with "Args".',
|
|
164
|
-
kind: 'recall-substring',
|
|
165
|
-
query: 'Args',
|
|
166
|
-
groundTruth: ['GpCallersArgs', 'GpImpactArgs', 'GpIndexArgs', 'GpRecallArgs', 'GpStatsArgs'],
|
|
167
|
-
expectedWinner: 'graphpilot',
|
|
168
|
-
difficulty: 'low',
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
id: 't09-recall-miss',
|
|
172
|
-
description: 'Look up a symbol that does not exist (negative test)',
|
|
173
|
-
prompt: 'Find the function definitelyNotARealSymbol in this codebase.',
|
|
174
|
-
kind: 'recall-miss',
|
|
175
|
-
query: 'definitelyNotARealSymbol',
|
|
176
|
-
groundTruth: [], // empty set
|
|
177
|
-
expectedWinner: 'tie',
|
|
178
|
-
difficulty: 'low',
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
id: 't10-string-literal-MAX_FILE_BYTES',
|
|
182
|
-
description: 'Find every literal occurrence of the constant name "MAX_FILE_BYTES"',
|
|
183
|
-
prompt: 'Find every place the string "MAX_FILE_BYTES" appears in the source.',
|
|
184
|
-
kind: 'string-literal',
|
|
185
|
-
query: 'MAX_FILE_BYTES',
|
|
186
|
-
// We don't index string literals or identifier usages outside structural
|
|
187
|
-
// contexts — but for THIS specific constant the structural index has the
|
|
188
|
-
// declaration. Both should find the declaration; only grep finds every
|
|
189
|
-
// usage. We expect grep to win on recall here.
|
|
190
|
-
groundTruth: [
|
|
191
|
-
'src/validation.ts', // declared here
|
|
192
|
-
'src/parser.ts', // imported and used
|
|
193
|
-
'tests/security.test.ts', // referenced in a test
|
|
194
|
-
],
|
|
195
|
-
expectedWinner: 'grep',
|
|
196
|
-
difficulty: 'medium',
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
id: 't11-impact-since-indexDirectory',
|
|
200
|
-
description: 'Differential impact: callers of indexDirectory changed since HEAD~1',
|
|
201
|
-
prompt:
|
|
202
|
-
'Show me callers of indexDirectory, but only those in files that have changed since HEAD~1. This is for PR review — I want to know which of my changes will be affected.',
|
|
203
|
-
kind: 'impact-since',
|
|
204
|
-
query: 'indexDirectory',
|
|
205
|
-
// Ground truth: callers of indexDirectory at all depths are
|
|
206
|
-
// [cmdIndex, handleGpIndex, applyUpdate]. On a clean repo HEAD~1
|
|
207
|
-
// should be empty or shallow-history, so we expect ~0 to all three
|
|
208
|
-
// depending on the branch state. Scorer will filter by changed files.
|
|
209
|
-
groundTruth: [], // Filled in during scoring based on actual git state
|
|
210
|
-
expectedWinner: 'graphpilot', // GraphPilot filters noise; baseline can't
|
|
211
|
-
difficulty: 'high',
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
id: 't12-evidence-anchor-resolution',
|
|
215
|
-
description: 'Evidence anchors: every tool response carries file:line @ sha citations',
|
|
216
|
-
prompt:
|
|
217
|
-
'Find every function that calls analyzeImpact. For each result, I need the exact file and line number I can jump to. Include the git SHA from when the index was built.',
|
|
218
|
-
kind: 'callers', // same tool as t01, different validation
|
|
219
|
-
query: 'analyzeImpact',
|
|
220
|
-
groundTruth: ['handleGpImpact'],
|
|
221
|
-
expectedWinner: 'graphpilot', // Only GP returns structured evidence anchors
|
|
222
|
-
difficulty: 'medium',
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
id: 't13-recall-nonexistent-with-anchor',
|
|
226
|
-
description:
|
|
227
|
-
'Anti-hallucination: looking up a symbol that does not exist returns citation proof',
|
|
228
|
-
prompt:
|
|
229
|
-
'Find the function fakeSymbolXYZ123. If it does not exist, show me the evidence — what query returned no results and why?',
|
|
230
|
-
kind: 'recall-miss',
|
|
231
|
-
query: 'fakeSymbolXYZ123',
|
|
232
|
-
groundTruth: [], // Does not exist
|
|
233
|
-
expectedWinner: 'graphpilot', // GP can cite "not in index" with proof; baseline may hallucinate
|
|
234
|
-
difficulty: 'high',
|
|
235
|
-
},
|
|
236
|
-
];
|
package/dist/provenance.d.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provenance / evidence anchors for tool responses.
|
|
3
|
-
*
|
|
4
|
-
* Why this exists: agents hallucinate. The most common Cursor / Claude
|
|
5
|
-
* Code failure pattern is "the model called a function that doesn't
|
|
6
|
-
* exist" — and the user has no quick way to verify a tool's claim
|
|
7
|
-
* before acting on it.
|
|
8
|
-
*
|
|
9
|
-
* Solution: every result we return carries an evidence anchor — a
|
|
10
|
-
* structured `{file, line, sha, excerpt}` reference that the agent
|
|
11
|
-
* can include verbatim in its reply. The user (or the agent itself)
|
|
12
|
-
* can then jump to the file/line and confirm the cited code matches
|
|
13
|
-
* the claim. If we ever fabricate, the anchor exposes us instantly.
|
|
14
|
-
*
|
|
15
|
-
* Format design:
|
|
16
|
-
* - Path is relative to the indexed root (portable).
|
|
17
|
-
* - Line is 1-indexed (matches editor convention).
|
|
18
|
-
* - SHA is optional — null when the indexed repo isn't a git repo.
|
|
19
|
-
* When present, it's the 7-char short SHA of the index time.
|
|
20
|
-
* - Excerpt is optional and short (~200 chars) — for symbol records
|
|
21
|
-
* it's the signature line. For edges it's the call expression.
|
|
22
|
-
*
|
|
23
|
-
* Per the differentiation research, this is the SINGLE feature no
|
|
24
|
-
* competitor in the 15+ landscape has shipped. See
|
|
25
|
-
* .notes/differentiation-research-2026-05-21.md §1.3.
|
|
26
|
-
*/
|
|
27
|
-
import type { SymbolRecord } from './symbols.js';
|
|
28
|
-
import type { CallEdge } from './edges.js';
|
|
29
|
-
/** A single evidence anchor pointing at a specific location in the repo. */
|
|
30
|
-
export interface Provenance {
|
|
31
|
-
/** Relative path from the indexed repo root, e.g. "src/auth.ts". */
|
|
32
|
-
file: string;
|
|
33
|
-
/** 1-indexed line number. */
|
|
34
|
-
line: number;
|
|
35
|
-
/** Optional 1-indexed column. */
|
|
36
|
-
column?: number;
|
|
37
|
-
/** End line, when the entity spans multiple lines. */
|
|
38
|
-
endLine?: number;
|
|
39
|
-
/** Short git SHA (7 chars) at index time. Null if not a git repo. */
|
|
40
|
-
sha?: string | null;
|
|
41
|
-
/** Short text excerpt — symbol signature, call expression, etc. */
|
|
42
|
-
excerpt?: string;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Make provenance for a symbol. Excerpt is the symbol's stored
|
|
46
|
-
* signature (already secret-redacted by T3).
|
|
47
|
-
*/
|
|
48
|
-
export declare function symbolProvenance(s: SymbolRecord, sha: string | null): Provenance;
|
|
49
|
-
/**
|
|
50
|
-
* Make provenance for a call edge. Points at the CALL SITE (where the
|
|
51
|
-
* call happens), not the callee's definition. The callee's own
|
|
52
|
-
* provenance is available via `symbolProvenance(idx.findById(edge.toId))`
|
|
53
|
-
* when toId is non-null.
|
|
54
|
-
*/
|
|
55
|
-
export declare function edgeProvenance(e: CallEdge, sha: string | null): Provenance;
|
|
56
|
-
/**
|
|
57
|
-
* Format a Provenance as a single-line human/agent-readable string.
|
|
58
|
-
* Used inline in tool text responses.
|
|
59
|
-
*
|
|
60
|
-
* Examples:
|
|
61
|
-
* src/auth.ts:42 (no sha — not a git repo)
|
|
62
|
-
* src/auth.ts:42 @ ab12cd3 (with sha)
|
|
63
|
-
* src/auth.ts:42:5 @ ab12cd3 (with column)
|
|
64
|
-
*/
|
|
65
|
-
export declare function formatProvenance(p: Provenance): string;
|
|
66
|
-
/**
|
|
67
|
-
* Format a Provenance as a verifiable evidence tag the agent can
|
|
68
|
-
* include in its reply. The agent's user (or a downstream tool) can
|
|
69
|
-
* paste this directly into a search.
|
|
70
|
-
*
|
|
71
|
-
* Example:
|
|
72
|
-
* [evidence: src/auth.ts:42 @ ab12cd3]
|
|
73
|
-
*/
|
|
74
|
-
export declare function formatEvidenceTag(p: Provenance): string;
|
package/dist/provenance.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provenance / evidence anchors for tool responses.
|
|
3
|
-
*
|
|
4
|
-
* Why this exists: agents hallucinate. The most common Cursor / Claude
|
|
5
|
-
* Code failure pattern is "the model called a function that doesn't
|
|
6
|
-
* exist" — and the user has no quick way to verify a tool's claim
|
|
7
|
-
* before acting on it.
|
|
8
|
-
*
|
|
9
|
-
* Solution: every result we return carries an evidence anchor — a
|
|
10
|
-
* structured `{file, line, sha, excerpt}` reference that the agent
|
|
11
|
-
* can include verbatim in its reply. The user (or the agent itself)
|
|
12
|
-
* can then jump to the file/line and confirm the cited code matches
|
|
13
|
-
* the claim. If we ever fabricate, the anchor exposes us instantly.
|
|
14
|
-
*
|
|
15
|
-
* Format design:
|
|
16
|
-
* - Path is relative to the indexed root (portable).
|
|
17
|
-
* - Line is 1-indexed (matches editor convention).
|
|
18
|
-
* - SHA is optional — null when the indexed repo isn't a git repo.
|
|
19
|
-
* When present, it's the 7-char short SHA of the index time.
|
|
20
|
-
* - Excerpt is optional and short (~200 chars) — for symbol records
|
|
21
|
-
* it's the signature line. For edges it's the call expression.
|
|
22
|
-
*
|
|
23
|
-
* Per the differentiation research, this is the SINGLE feature no
|
|
24
|
-
* competitor in the 15+ landscape has shipped. See
|
|
25
|
-
* .notes/differentiation-research-2026-05-21.md §1.3.
|
|
26
|
-
*/
|
|
27
|
-
const MAX_EXCERPT_LEN = 200;
|
|
28
|
-
function clipExcerpt(s) {
|
|
29
|
-
if (!s)
|
|
30
|
-
return undefined;
|
|
31
|
-
const trimmed = s.trim();
|
|
32
|
-
if (trimmed.length === 0)
|
|
33
|
-
return undefined;
|
|
34
|
-
return trimmed.length > MAX_EXCERPT_LEN ? trimmed.slice(0, MAX_EXCERPT_LEN - 1) + '…' : trimmed;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Make provenance for a symbol. Excerpt is the symbol's stored
|
|
38
|
-
* signature (already secret-redacted by T3).
|
|
39
|
-
*/
|
|
40
|
-
export function symbolProvenance(s, sha) {
|
|
41
|
-
return {
|
|
42
|
-
file: s.file,
|
|
43
|
-
line: s.line,
|
|
44
|
-
column: s.column,
|
|
45
|
-
endLine: s.endLine,
|
|
46
|
-
sha: sha ?? null,
|
|
47
|
-
excerpt: clipExcerpt(s.signature),
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Make provenance for a call edge. Points at the CALL SITE (where the
|
|
52
|
-
* call happens), not the callee's definition. The callee's own
|
|
53
|
-
* provenance is available via `symbolProvenance(idx.findById(edge.toId))`
|
|
54
|
-
* when toId is non-null.
|
|
55
|
-
*/
|
|
56
|
-
export function edgeProvenance(e, sha) {
|
|
57
|
-
return {
|
|
58
|
-
file: e.file,
|
|
59
|
-
line: e.line,
|
|
60
|
-
column: e.column,
|
|
61
|
-
sha: sha ?? null,
|
|
62
|
-
// No excerpt for edges — we don't store the call line text.
|
|
63
|
-
// (Future v0.2: capture the call line at index time so the agent
|
|
64
|
-
// sees the actual call expression.)
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Format a Provenance as a single-line human/agent-readable string.
|
|
69
|
-
* Used inline in tool text responses.
|
|
70
|
-
*
|
|
71
|
-
* Examples:
|
|
72
|
-
* src/auth.ts:42 (no sha — not a git repo)
|
|
73
|
-
* src/auth.ts:42 @ ab12cd3 (with sha)
|
|
74
|
-
* src/auth.ts:42:5 @ ab12cd3 (with column)
|
|
75
|
-
*/
|
|
76
|
-
export function formatProvenance(p) {
|
|
77
|
-
let out = p.file + ':' + p.line;
|
|
78
|
-
if (p.column !== undefined)
|
|
79
|
-
out += ':' + p.column;
|
|
80
|
-
if (p.sha)
|
|
81
|
-
out += ' @ ' + p.sha;
|
|
82
|
-
return out;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Format a Provenance as a verifiable evidence tag the agent can
|
|
86
|
-
* include in its reply. The agent's user (or a downstream tool) can
|
|
87
|
-
* paste this directly into a search.
|
|
88
|
-
*
|
|
89
|
-
* Example:
|
|
90
|
-
* [evidence: src/auth.ts:42 @ ab12cd3]
|
|
91
|
-
*/
|
|
92
|
-
export function formatEvidenceTag(p) {
|
|
93
|
-
return `[evidence: ${formatProvenance(p)}]`;
|
|
94
|
-
}
|
|
95
|
-
//# sourceMappingURL=provenance.js.map
|
package/dist/provenance.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"provenance.js","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAqBH,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B,SAAS,WAAW,CAAC,CAAqB;IACxC,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3C,OAAO,OAAO,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;AAClG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAe,EAAE,GAAkB;IAClE,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,GAAG,EAAE,GAAG,IAAI,IAAI;QAChB,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;KAClC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,CAAW,EAAE,GAAkB;IAC5D,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,GAAG,EAAE,GAAG,IAAI,IAAI;QAChB,4DAA4D;QAC5D,iEAAiE;QACjE,oCAAoC;KACrC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAa;IAC5C,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC;IAChC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;QAAE,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,IAAI,CAAC,CAAC,GAAG;QAAE,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC;IAChC,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,CAAa;IAC7C,OAAO,cAAc,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC;AAC9C,CAAC"}
|