purecontext-mcp 1.1.1 → 1.1.2
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/package.json +1 -1
- package/docs/dev/API_STABILITY.md +0 -319
- package/docs/dev/DECISIONS.md +0 -22
- package/docs/dev/DOCUMENTATION_PLAN.md +0 -113
- package/docs/dev/PHASE10_TASKS.md +0 -476
- package/docs/dev/PHASE11_TASKS.md +0 -385
- package/docs/dev/PHASE12_TASKS.md +0 -335
- package/docs/dev/PHASE13_TASKS.md +0 -381
- package/docs/dev/PHASE14_TASKS.md +0 -371
- package/docs/dev/PHASE15_TASKS.md +0 -256
- package/docs/dev/PHASE16_TASKS.md +0 -314
- package/docs/dev/PHASE17_TASKS.md +0 -321
- package/docs/dev/PHASE18_TASKS.md +0 -345
- package/docs/dev/PHASE19_TASKS.md +0 -261
- package/docs/dev/PHASE1_TASKS.md +0 -443
- package/docs/dev/PHASE20_TASKS.md +0 -280
- package/docs/dev/PHASE21_TASKS.md +0 -355
- package/docs/dev/PHASE22_TASKS.md +0 -371
- package/docs/dev/PHASE23_TASKS.md +0 -274
- package/docs/dev/PHASE24_TASKS.md +0 -326
- package/docs/dev/PHASE25_TASKS.md +0 -452
- package/docs/dev/PHASE26_TASKS.md +0 -253
- package/docs/dev/PHASE27_TASKS.md +0 -410
- package/docs/dev/PHASE2_TASKS.md +0 -328
- package/docs/dev/PHASE3_TASKS.md +0 -571
- package/docs/dev/PHASE4_TASKS.md +0 -531
- package/docs/dev/PHASE5_TASKS.md +0 -835
- package/docs/dev/PHASE6_TASKS.md +0 -347
- package/docs/dev/PHASE7_TASKS.md +0 -257
- package/docs/dev/PHASE8_TASKS.md +0 -299
- package/docs/dev/PHASE9_TASKS.md +0 -320
- package/docs/dev/PureContext_MCP_PRD_v1.0.docx +0 -0
- package/docs/dev/SELF_HOSTING.md +0 -142
- package/docs/dev/TEAM_SETUP.md +0 -316
- package/docs/dev/TELEMETRY.md +0 -99
- package/docs/dev/feature-analysis.md +0 -305
- package/docs/dev/phase-1-notes.md +0 -3
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
# Phase 24 — Git & History Integration
|
|
2
|
-
|
|
3
|
-
**Goal**: Make code history navigable at the symbol level. Show when a symbol was introduced, who last changed it, how frequently it churns, and which symbols a PR touches — turning PureContext from a static index into a living history of the codebase.
|
|
4
|
-
|
|
5
|
-
**Scope rationale**: jCodeMunch has no git integration whatsoever. This phase is pure differentiation. Developers and AI agents routinely need to know "when was this added?", "who owns this?", and "what does this PR break?" — today they must leave their tool and run git commands manually. PureContext can answer all of this inline.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Task 154: Git Metadata Indexing
|
|
10
|
-
|
|
11
|
-
Extend the indexing pipeline to capture commit-level metadata (SHA, author, date, message) for each file and persist it in the database.
|
|
12
|
-
|
|
13
|
-
**Current state**: The `files` table stores file paths, content hashes, and byte sizes. No git metadata is captured. The `index_repo` tool uses `git clone --depth=1` — a shallow clone that loses history.
|
|
14
|
-
|
|
15
|
-
**Deliverables**:
|
|
16
|
-
|
|
17
|
-
- `src/core/db/schema.ts` — extend `files` table:
|
|
18
|
-
```sql
|
|
19
|
-
ALTER TABLE files ADD COLUMN last_commit_sha TEXT;
|
|
20
|
-
ALTER TABLE files ADD COLUMN last_commit_author TEXT;
|
|
21
|
-
ALTER TABLE files ADD COLUMN last_commit_date INTEGER; -- Unix timestamp
|
|
22
|
-
ALTER TABLE files ADD COLUMN last_commit_message TEXT;
|
|
23
|
-
ALTER TABLE files ADD COLUMN commit_count INTEGER; -- Total commits touching this file
|
|
24
|
-
```
|
|
25
|
-
Add `git_metadata` table for full per-file commit history (limited):
|
|
26
|
-
```sql
|
|
27
|
-
CREATE TABLE IF NOT EXISTS git_metadata (
|
|
28
|
-
repo_id TEXT NOT NULL,
|
|
29
|
-
file_path TEXT NOT NULL,
|
|
30
|
-
commit_sha TEXT NOT NULL,
|
|
31
|
-
author_name TEXT NOT NULL,
|
|
32
|
-
author_email TEXT NOT NULL,
|
|
33
|
-
commit_date INTEGER NOT NULL,
|
|
34
|
-
message TEXT NOT NULL,
|
|
35
|
-
PRIMARY KEY (repo_id, file_path, commit_sha)
|
|
36
|
-
);
|
|
37
|
-
```
|
|
38
|
-
- `src/core/git-log-reader.ts` — new module:
|
|
39
|
-
```typescript
|
|
40
|
-
interface CommitRecord {
|
|
41
|
-
sha: string;
|
|
42
|
-
authorName: string;
|
|
43
|
-
authorEmail: string;
|
|
44
|
-
date: number; // Unix timestamp
|
|
45
|
-
message: string;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
interface FileGitMeta {
|
|
49
|
-
lastCommit: CommitRecord;
|
|
50
|
-
commitCount: number;
|
|
51
|
-
history: CommitRecord[]; // Last N commits (default: 10)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function readFileHistory(
|
|
55
|
-
repoRoot: string,
|
|
56
|
-
filePath: string,
|
|
57
|
-
limit?: number
|
|
58
|
-
): Promise<FileGitMeta>
|
|
59
|
-
|
|
60
|
-
async function readRepoMeta(repoRoot: string): Promise<{
|
|
61
|
-
defaultBranch: string;
|
|
62
|
-
headSha: string;
|
|
63
|
-
remoteUrl?: string;
|
|
64
|
-
}>
|
|
65
|
-
```
|
|
66
|
-
- Use `git log --follow --format="%H|%an|%ae|%at|%s" -n {limit} -- {filePath}` parsed line-by-line
|
|
67
|
-
- `src/core/index-manager.ts` — after indexing, run `git-log-reader` for each processed file and store in `files` + `git_metadata` tables
|
|
68
|
-
- Make git metadata capture optional: skip gracefully if not a git repo (e.g. local folder without git)
|
|
69
|
-
- For GitHub API-indexed repos (Task 137): populate from the GitHub commits API instead of local git
|
|
70
|
-
|
|
71
|
-
**Key technical notes**:
|
|
72
|
-
- Shallow clones lack history — switch `index_repo` from `--depth=1` to `--depth=50` (configurable via `GIT_HISTORY_DEPTH` env var) to capture recent commits
|
|
73
|
-
- For local folder indexing, git metadata is available at no extra cost — just parse `git log` output
|
|
74
|
-
- `commit_count` is expensive for large repos (requires `git log --follow -- file | wc -l`) — use `git log --oneline -n 501 -- file | wc -l` to count up to 500, then cap display at "500+"
|
|
75
|
-
- Schema migration: add `SCHEMA_VERSION` bump and migration path for existing indexes
|
|
76
|
-
|
|
77
|
-
**Tests**: `test/core/git-log-reader.test.ts`
|
|
78
|
-
- Parse `git log` output correctly (all fields)
|
|
79
|
-
- Handle files with no git history (non-git folder)
|
|
80
|
-
- `commitCount` accurate for files with < 10 commits
|
|
81
|
-
- GitHub API fallback (mocked)
|
|
82
|
-
|
|
83
|
-
**Verify**:
|
|
84
|
-
```bash
|
|
85
|
-
# After indexing a git repo, query the files table:
|
|
86
|
-
# SELECT file_path, last_commit_author, last_commit_date FROM files LIMIT 5
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## Task 155: Symbol-Level Change Tracking Tool
|
|
92
|
-
|
|
93
|
-
New `get_symbol_history` tool — show the git history of the file containing a symbol, filtered to commits that actually touched the symbol's line range.
|
|
94
|
-
|
|
95
|
-
**Current state**: Git metadata is stored at the file level (Task 154). There is no way to ask "when was *this specific function* last changed?" — file history includes unrelated changes.
|
|
96
|
-
|
|
97
|
-
**Deliverables**:
|
|
98
|
-
|
|
99
|
-
- `src/server/tools/get-symbol-history.ts` — new MCP tool:
|
|
100
|
-
```typescript
|
|
101
|
-
interface GetSymbolHistoryInput {
|
|
102
|
-
repoId: string;
|
|
103
|
-
symbolId: string;
|
|
104
|
-
limit?: number; // Default 10, max 50
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
interface SymbolCommit {
|
|
108
|
-
sha: string;
|
|
109
|
-
shortSha: string; // First 8 chars
|
|
110
|
-
author: string;
|
|
111
|
-
date: string; // ISO 8601
|
|
112
|
-
daysAgo: number;
|
|
113
|
-
message: string;
|
|
114
|
-
linesAdded?: number;
|
|
115
|
-
linesRemoved?: number;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
interface GetSymbolHistoryOutput {
|
|
119
|
-
symbol: {
|
|
120
|
-
name: string;
|
|
121
|
-
kind: SymbolKind;
|
|
122
|
-
filePath: string;
|
|
123
|
-
};
|
|
124
|
-
history: SymbolCommit[];
|
|
125
|
-
totalCommits: number;
|
|
126
|
-
firstSeen?: SymbolCommit; // Oldest commit in history (commit that introduced it)
|
|
127
|
-
lastChanged: SymbolCommit; // Most recent commit
|
|
128
|
-
churnScore: number; // Commits per 90 days — higher = more volatile
|
|
129
|
-
_meta: ResponseMeta;
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
- Implementation:
|
|
133
|
-
1. Look up symbol → get `filePath`, `startByte`, `endByte`
|
|
134
|
-
2. Convert byte offsets to line range (start line, end line)
|
|
135
|
-
3. Run `git log -L {startLine},{endLine}:{filePath}` (line-range log) — captures only commits touching those lines
|
|
136
|
-
4. Parse output into `SymbolCommit[]`
|
|
137
|
-
5. Calculate `churnScore`: `(commitCount / daysSinceFirstCommit) * 90`
|
|
138
|
-
- `src/core/git-log-reader.ts` — add `readSymbolHistory(repoRoot, filePath, startLine, endLine, limit)`
|
|
139
|
-
- For GitHub API repos: fall back to file-level history from `git_metadata` table (line-range tracking not available without local clone)
|
|
140
|
-
|
|
141
|
-
**Key technical notes**:
|
|
142
|
-
- `git log -L` is slow on large files with long histories — apply the `limit` early via `-n {limit}` flag
|
|
143
|
-
- Line-range tracking: `git log -L` follows the code even if it moves within the file (renamed lines) — this is more accurate than date-filtering the file history
|
|
144
|
-
- `churnScore` is a useful proxy for "how risky is this symbol?" — high churn = frequently changing = more likely to have bugs, more risky to modify
|
|
145
|
-
- `firstSeen` may not be in the `limit` window — use a separate `git log -L ... --diff-filter=A` call to find the introducing commit
|
|
146
|
-
|
|
147
|
-
**Tests**: `test/server/get-symbol-history.test.ts`
|
|
148
|
-
- Returns commits touching the symbol's line range
|
|
149
|
-
- `churnScore` calculated correctly
|
|
150
|
-
- `firstSeen` populated
|
|
151
|
-
- Symbol not found → error
|
|
152
|
-
- No git history (non-git folder) → graceful empty response
|
|
153
|
-
|
|
154
|
-
**Verify**:
|
|
155
|
-
```bash
|
|
156
|
-
# get_symbol_history { repoId: "...", symbolId: "abc123", limit: 10 }
|
|
157
|
-
# Should show commits that touched the function's line range, with churn score
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## Task 156: PR / Diff Impact Analysis Tool
|
|
163
|
-
|
|
164
|
-
New `analyze_diff` tool — given a git diff (unified format), identify all symbols that are added, modified, or deleted, and calculate the downstream blast radius.
|
|
165
|
-
|
|
166
|
-
**Current state**: Agents reviewing PRs must manually call `get_blast_radius` for each changed file. There is no tool that accepts a diff and produces a consolidated impact summary.
|
|
167
|
-
|
|
168
|
-
**Deliverables**:
|
|
169
|
-
|
|
170
|
-
- `src/server/tools/analyze-diff.ts` — new MCP tool:
|
|
171
|
-
```typescript
|
|
172
|
-
interface AnalyzeDiffInput {
|
|
173
|
-
repoId: string;
|
|
174
|
-
diff: string; // Unified diff format (git diff output)
|
|
175
|
-
includeBlastRadius?: boolean; // Default true — compute downstream impact
|
|
176
|
-
blastRadiusDepth?: number; // Default 2
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
interface ChangedSymbol {
|
|
180
|
-
symbolId: string;
|
|
181
|
-
name: string;
|
|
182
|
-
kind: SymbolKind;
|
|
183
|
-
filePath: string;
|
|
184
|
-
changeType: 'added' | 'modified' | 'deleted' | 'signature_changed';
|
|
185
|
-
signatureBefore?: string; // For modified symbols
|
|
186
|
-
signatureAfter?: string;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
interface AnalyzeDiffOutput {
|
|
190
|
-
summary: {
|
|
191
|
-
filesChanged: number;
|
|
192
|
-
symbolsAdded: number;
|
|
193
|
-
symbolsModified: number;
|
|
194
|
-
symbolsDeleted: number;
|
|
195
|
-
signatureBreaks: number; // Public API surface changes
|
|
196
|
-
};
|
|
197
|
-
changedSymbols: ChangedSymbol[];
|
|
198
|
-
blastRadius?: {
|
|
199
|
-
filesImpacted: number;
|
|
200
|
-
symbolsImpacted: number;
|
|
201
|
-
impactedFiles: string[];
|
|
202
|
-
};
|
|
203
|
-
reviewPriority: 'low' | 'medium' | 'high' | 'critical'; // Derived from blast radius + signature breaks
|
|
204
|
-
_meta: ResponseMeta;
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
- Diff parsing (`src/core/diff-parser.ts`):
|
|
208
|
-
- Parse unified diff into per-file changed line ranges
|
|
209
|
-
- Map changed line ranges to symbols using byte-offset lookup from the DB
|
|
210
|
-
- Detect signature changes: compare old symbol signature (from git history) vs new (from current index)
|
|
211
|
-
- `reviewPriority` heuristic:
|
|
212
|
-
- `critical`: any public API signature changed + blast radius > 10 files
|
|
213
|
-
- `high`: signature changed or blast radius > 5 files
|
|
214
|
-
- `medium`: implementation changes with blast radius 1–5
|
|
215
|
-
- `low`: changes to files with no importers
|
|
216
|
-
- Optionally call `get_blast_radius` logic for each modified symbol and aggregate
|
|
217
|
-
|
|
218
|
-
**Key technical notes**:
|
|
219
|
-
- The diff must be in unified format (`git diff` output with `---`/`+++`/`@@` headers)
|
|
220
|
-
- Line-to-symbol mapping: for each changed line range, query symbols where `startByte <= lineEnd` and `endByte >= lineStart` (using the file's content to convert lines to bytes)
|
|
221
|
-
- "Signature changed": compare `symbols.signature` in DB (current index) vs parsing the old content from the diff's `-` lines
|
|
222
|
-
- This tool is most valuable in CI pipelines (GitHub Actions) and code review workflows
|
|
223
|
-
|
|
224
|
-
**Tests**: `test/server/analyze-diff.test.ts`
|
|
225
|
-
- Simple diff with added function → `changeType: 'added'`
|
|
226
|
-
- Modified function body → `changeType: 'modified'`
|
|
227
|
-
- Changed function signature → `changeType: 'signature_changed'`
|
|
228
|
-
- Deleted function → `changeType: 'deleted'`
|
|
229
|
-
- `blastRadius` aggregated correctly
|
|
230
|
-
- `reviewPriority` heuristic validated
|
|
231
|
-
|
|
232
|
-
**Verify**:
|
|
233
|
-
```bash
|
|
234
|
-
# git diff HEAD~1 | npx purecontext-mcp # pipe diff to the tool via CLI
|
|
235
|
-
# analyze_diff { repoId: "...", diff: "<unified diff content>" }
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
---
|
|
239
|
-
|
|
240
|
-
## Task 157: Change Velocity Metrics Tool
|
|
241
|
-
|
|
242
|
-
New `get_churn_metrics` tool — report code churn (change frequency) across the entire repo or a specific directory, identifying the most volatile files and symbols.
|
|
243
|
-
|
|
244
|
-
**Current state**: Git metadata is stored per-file (Task 154) but not surfaced as a tool. There is no way to ask "which parts of this codebase change most often?" — critical for risk assessment and architecture decisions.
|
|
245
|
-
|
|
246
|
-
**Deliverables**:
|
|
247
|
-
|
|
248
|
-
- `src/server/tools/get-churn-metrics.ts` — new MCP tool:
|
|
249
|
-
```typescript
|
|
250
|
-
interface GetChurnMetricsInput {
|
|
251
|
-
repoId: string;
|
|
252
|
-
scope?: string; // Directory prefix filter (e.g. "src/core/")
|
|
253
|
-
dayWindow?: number; // Look back N days, default 90
|
|
254
|
-
topN?: number; // Return top N files/symbols by churn, default 20
|
|
255
|
-
granularity: 'file' | 'symbol';
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
interface ChurnRecord {
|
|
259
|
-
filePath: string;
|
|
260
|
-
symbolName?: string; // Only when granularity: 'symbol'
|
|
261
|
-
symbolKind?: SymbolKind;
|
|
262
|
-
commitCount: number;
|
|
263
|
-
uniqueAuthors: number;
|
|
264
|
-
lastChanged: string; // ISO date
|
|
265
|
-
churnScore: number; // Commits per 90 days
|
|
266
|
-
riskLevel: 'stable' | 'active' | 'volatile' | 'hotspot';
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
interface GetChurnMetricsOutput {
|
|
270
|
-
repoId: string;
|
|
271
|
-
dayWindow: number;
|
|
272
|
-
topChurn: ChurnRecord[];
|
|
273
|
-
summary: {
|
|
274
|
-
totalFilesAnalyzed: number;
|
|
275
|
-
hotspots: number; // Files with churnScore > 10
|
|
276
|
-
stableFiles: number; // Files with churnScore < 1
|
|
277
|
-
mostActiveAuthor: string;
|
|
278
|
-
};
|
|
279
|
-
_meta: ResponseMeta;
|
|
280
|
-
}
|
|
281
|
-
```
|
|
282
|
-
- Data source: `git_metadata` table (populated by Task 154)
|
|
283
|
-
- `churnScore`: commits in the `dayWindow` ÷ (dayWindow / 90)
|
|
284
|
-
- `riskLevel` thresholds: `stable` < 1, `active` 1–5, `volatile` 5–10, `hotspot` > 10
|
|
285
|
-
- For `granularity: 'symbol'`, join against `symbols` table — use line-range overlap to assign commits to symbols (same approach as Task 155)
|
|
286
|
-
- `scope` filter: `WHERE file_path LIKE 'src/core/%'`
|
|
287
|
-
|
|
288
|
-
**Key technical notes**:
|
|
289
|
-
- This tool requires `git_metadata` to be populated — skip gracefully if git metadata wasn't captured (non-git project)
|
|
290
|
-
- `granularity: 'symbol'` is expensive for large repos — apply `topN` limit and use indexed queries
|
|
291
|
-
- Hotspot identification is actionable: files with high churn and high blast radius are the most dangerous areas to modify
|
|
292
|
-
- Consider adding a combined metric: `churnScore × blastRadius` as a "refactoring priority" score
|
|
293
|
-
|
|
294
|
-
**Tests**: `test/server/get-churn-metrics.test.ts`
|
|
295
|
-
- `granularity: 'file'` — top N files by commit count
|
|
296
|
-
- `granularity: 'symbol'` — top N symbols
|
|
297
|
-
- `scope` filter narrows to directory
|
|
298
|
-
- `dayWindow` correctly scopes to date range
|
|
299
|
-
- `riskLevel` assigned correctly
|
|
300
|
-
- No git metadata → clear error with hint
|
|
301
|
-
|
|
302
|
-
**Verify**:
|
|
303
|
-
```bash
|
|
304
|
-
# get_churn_metrics { repoId: "...", granularity: "file", topN: 10 }
|
|
305
|
-
# Should show the 10 most frequently changed files with risk levels
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
---
|
|
309
|
-
|
|
310
|
-
## Order of Execution
|
|
311
|
-
|
|
312
|
-
```
|
|
313
|
-
154 (git metadata indexing) ──▶ 155 (symbol history)
|
|
314
|
-
──▶ 156 (diff analysis — needs symbol-to-line mapping)
|
|
315
|
-
──▶ 157 (churn metrics — needs git_metadata table)
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
Task 154 is the prerequisite for all others. 155, 156, and 157 can be parallelized after 154.
|
|
319
|
-
|
|
320
|
-
---
|
|
321
|
-
|
|
322
|
-
## Phase 24 Completion
|
|
323
|
-
|
|
324
|
-
**Before**: PureContext is a snapshot tool — it sees code as it is now, with no sense of time. Agents must leave PureContext to run git commands for history, authorship, and PR review.
|
|
325
|
-
|
|
326
|
-
**After**: Code history is queryable at the symbol level. Agents can see when a function was introduced, who last changed it, how volatile it is, and what a PR touches — all inline, without leaving the MCP session. No competing code navigation tool offers this. jCodeMunch has zero git integration.
|