diffcontext 0.5.6__tar.gz → 0.5.7__tar.gz

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.
Files changed (73) hide show
  1. {diffcontext-0.5.6 → diffcontext-0.5.7}/PKG-INFO +1 -1
  2. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/__init__.py +1 -1
  3. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/mcp_server.py +41 -11
  4. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext.egg-info/PKG-INFO +1 -1
  5. {diffcontext-0.5.6 → diffcontext-0.5.7}/LICENSE +0 -0
  6. {diffcontext-0.5.6 → diffcontext-0.5.7}/README.md +0 -0
  7. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/_warn_once.py +0 -0
  8. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/cache.py +0 -0
  9. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/cli/__init__.py +0 -0
  10. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/context/__init__.py +0 -0
  11. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/context/compiler.py +0 -0
  12. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/context/selector.py +0 -0
  13. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/diff/__init__.py +0 -0
  14. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/diff/git_diff.py +0 -0
  15. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/diff/state_manager.py +0 -0
  16. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/graph_builder.py +0 -0
  17. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/history.py +0 -0
  18. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/impact/__init__.py +0 -0
  19. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/impact/blast_radius.py +0 -0
  20. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/impact/scoring.py +0 -0
  21. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/impact/traversal.py +0 -0
  22. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/impact/visualizer.py +0 -0
  23. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/languages/__init__.py +0 -0
  24. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/languages/typescript.py +0 -0
  25. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/lexical.py +0 -0
  26. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/models.py +0 -0
  27. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/parser.py +0 -0
  28. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/pipeline.py +0 -0
  29. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/py.typed +0 -0
  30. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/rerank/__init__.py +0 -0
  31. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/rerank/features.py +0 -0
  32. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/rerank/model.py +0 -0
  33. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/resolver.py +0 -0
  34. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/scanner.py +0 -0
  35. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/symbols.py +0 -0
  36. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/verify/__init__.py +0 -0
  37. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/verify/cases.py +0 -0
  38. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/verify/history.py +0 -0
  39. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext/verify/sufficiency.py +0 -0
  40. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext.egg-info/SOURCES.txt +0 -0
  41. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext.egg-info/dependency_links.txt +0 -0
  42. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext.egg-info/entry_points.txt +0 -0
  43. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext.egg-info/requires.txt +0 -0
  44. {diffcontext-0.5.6 → diffcontext-0.5.7}/diffcontext.egg-info/top_level.txt +0 -0
  45. {diffcontext-0.5.6 → diffcontext-0.5.7}/pyproject.toml +0 -0
  46. {diffcontext-0.5.6 → diffcontext-0.5.7}/setup.cfg +0 -0
  47. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_cache.py +0 -0
  48. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_cache_fallback.py +0 -0
  49. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_compiler_meta.py +0 -0
  50. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_core.py +0 -0
  51. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_cutoff.py +0 -0
  52. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_determinism.py +0 -0
  53. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_downstream_eval.py +0 -0
  54. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_git_diff.py +0 -0
  55. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_harness_api.py +0 -0
  56. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_history.py +0 -0
  57. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_incremental.py +0 -0
  58. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_index_scoping.py +0 -0
  59. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_lexical.py +0 -0
  60. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_mcp_server.py +0 -0
  61. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_rerank.py +0 -0
  62. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_semantic_ablation.py +0 -0
  63. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_semantic_audit.py +0 -0
  64. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_semantic_gap.py +0 -0
  65. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_semantic_metrics.py +0 -0
  66. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_semantic_mine.py +0 -0
  67. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_service_clone.py +0 -0
  68. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_src_layout.py +0 -0
  69. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_stats.py +0 -0
  70. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_token_budget.py +0 -0
  71. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_typescript_adapter.py +0 -0
  72. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_verify.py +0 -0
  73. {diffcontext-0.5.6 → diffcontext-0.5.7}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diffcontext
3
- Version: 0.5.6
3
+ Version: 0.5.7
4
4
  Summary: Static-analysis-powered repository context compiler for LLMs
5
5
  Author-email: Trakshan Mishra <trakshanmishra477@gmail.com>
6
6
  License: MIT
@@ -32,7 +32,7 @@ Usage as a library:
32
32
  print(ctx.reduction_pct) # how much code was filtered out
33
33
  """
34
34
 
35
- __version__ = "0.5.6"
35
+ __version__ = "0.5.7"
36
36
 
37
37
  # Public, semver-covered API. Everything not listed here (graph_builder,
38
38
  # resolver, symbols, scanner, parser internals) is importable but carries no
@@ -96,6 +96,11 @@ def main():
96
96
  related functions the model needs to make the change safely — packed
97
97
  into max_tokens with a disclosure header showing what was dropped.
98
98
 
99
+ Uses the gap cutoff by default (~6-9 symbols at ~4x precision vs
100
+ top-20, costing ~30% recall) — MCP consumers are budget-sensitive,
101
+ so the default is precise, not exhaustive. The total count of
102
+ dropped symbols is always shown in the meta header.
103
+
99
104
  Optionally pass task_description (the bug report or issue text) to
100
105
  bias retrieval toward symbols relevant to the described problem —
101
106
  the one signal the graph alone can't provide.
@@ -139,23 +144,34 @@ def main():
139
144
  impact = analyze_impact(
140
145
  idx, changed, query_text=task_description, query_weight=query_weight,
141
146
  )
142
- ctx = compile(idx, impact, max_tokens=max_tokens, meta=meta)
147
+ # Gap cutoff by default: ~6-9 symbols at ~4x precision vs top-20,
148
+ # costing ~30% recall. MCP consumers are budget-sensitive — the
149
+ # default should be precise, not exhaustive.
150
+ ctx = compile(idx, impact, max_tokens=max_tokens, meta=meta, cutoff="gap")
143
151
  return ctx.text
144
152
 
145
153
  @server.tool()
146
154
  def find_impact(
147
155
  repo_path: str = "",
148
156
  symbol: str = "",
157
+ limit: int = 0,
149
158
  ) -> str:
150
159
  """Find what breaks if you change a symbol.
151
160
 
152
161
  Returns the blast radius: direct callers, direct callees, and
153
- transitive impact. The "what breaks if I change this" query.
162
+ transitive impact, ranked by impact score. Default cap is 10
163
+ symbols — a reviewer brief must be short enough to read. Pass
164
+ limit > 0 to override with a different cap, or limit=0 for all.
165
+
166
+ The total count is always shown ("339 impacted, showing top 9")
167
+ so nothing is hidden — the cap is a display choice, not
168
+ information loss.
154
169
 
155
170
  Args:
156
171
  repo_path: Absolute path to the repository. If omitted, uses
157
172
  the --repo from server startup.
158
173
  symbol: Symbol ID (e.g. ./src/auth.py:validate_jwt).
174
+ limit: Max symbols to show. 0 = all (default 10).
159
175
  """
160
176
  from diffcontext.pipeline import analyze_impact, warn_unknown_symbols
161
177
 
@@ -164,12 +180,22 @@ def main():
164
180
  warn_unknown_symbols(idx, [symbol])
165
181
  impact = analyze_impact(idx, [symbol], hybrid=False)
166
182
 
183
+ # Rank all impacted symbols by score (excluding the changed symbol).
184
+ ranked = sorted(
185
+ ((sid, sc) for sid, sc in impact.scores.items() if sid != symbol),
186
+ key=lambda x: x[1], reverse=True,
187
+ )
188
+ total = len(ranked)
189
+
190
+ cap = limit if limit > 0 else 10
191
+ show = min(cap, total)
192
+
167
193
  lines = [f"Changed: {symbol}"]
168
- lines.append(f"\nBlast radius ({len(impact.blast_radius)}):")
169
- for sym in impact.blast_radius[:20]:
170
- score = impact.scores.get(sym, 0)
171
- lines.append(f" {sym} (score: {score:.0f})")
172
- lines.append(f"\nTotal impacted: {len(impact.all_relevant)}")
194
+ lines.append(f"\n{total} impacted, showing top {show}:")
195
+ for sid, sc in ranked[:show]:
196
+ lines.append(f" {sid} (score: {sc:.0f})")
197
+ if total > show:
198
+ lines.append(f"\n... and {total - show} more (pass limit={total} to see all)")
173
199
  return "\n".join(lines)
174
200
 
175
201
  @server.tool()
@@ -180,9 +206,11 @@ def main():
180
206
  ) -> str:
181
207
  """Explain why symbols were included or dropped from context.
182
208
 
183
- Returns the included symbols (with scores and token costs) and
184
- the dropped symbols (scored but cut by the token budget), so an
185
- agent can inspect or filter the selection.
209
+ Returns the included symbols (with scores and token costs) and the
210
+ top dropped symbols (scored but cut by the token budget), so an agent
211
+ can inspect or filter the selection. Dropped symbols are capped at
212
+ 10 by default (gap cutoff) — the total count is always shown so
213
+ nothing is hidden.
186
214
 
187
215
  Args:
188
216
  repo_path: Absolute path to the repository. If omitted, uses
@@ -203,13 +231,15 @@ def main():
203
231
  "score": round(item.score, 1), "tokens": item.token_estimate}
204
232
  for item in ctx.items
205
233
  ]
234
+ total_dropped = len(ctx.dropped_symbols)
206
235
  dropped = [
207
236
  {"id": sid, "score": round(impact.scores.get(sid, 0.0), 1)}
208
- for sid in ctx.dropped_symbols
237
+ for sid in ctx.dropped_symbols[:10]
209
238
  ]
210
239
  result = {
211
240
  "included_symbols": included,
212
241
  "dropped_symbols": dropped,
242
+ "dropped_symbols_total": total_dropped,
213
243
  "total_tokens": ctx.token_estimate,
214
244
  "symbol_count": ctx.symbol_count,
215
245
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diffcontext
3
- Version: 0.5.6
3
+ Version: 0.5.7
4
4
  Summary: Static-analysis-powered repository context compiler for LLMs
5
5
  Author-email: Trakshan Mishra <trakshanmishra477@gmail.com>
6
6
  License: MIT
File without changes
File without changes
File without changes
File without changes