polyglot-ast-slicer 1.0.0__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 (169) hide show
  1. polyglot_ast_slicer-1.0.0/.githooks/pre-commit +3 -0
  2. polyglot_ast_slicer-1.0.0/.github/ISSUE_TEMPLATE/bug_report.yml +28 -0
  3. polyglot_ast_slicer-1.0.0/.github/ISSUE_TEMPLATE/feature_request.yml +22 -0
  4. polyglot_ast_slicer-1.0.0/.github/workflows/ci.yml +41 -0
  5. polyglot_ast_slicer-1.0.0/.gitignore +24 -0
  6. polyglot_ast_slicer-1.0.0/AGENTS.md +1 -0
  7. polyglot_ast_slicer-1.0.0/CHANGELOG.md +109 -0
  8. polyglot_ast_slicer-1.0.0/CLAUDE.md +8 -0
  9. polyglot_ast_slicer-1.0.0/CONTRIBUTING.md +43 -0
  10. polyglot_ast_slicer-1.0.0/LICENSE +21 -0
  11. polyglot_ast_slicer-1.0.0/METRICS.md +150 -0
  12. polyglot_ast_slicer-1.0.0/Makefile +27 -0
  13. polyglot_ast_slicer-1.0.0/PKG-INFO +261 -0
  14. polyglot_ast_slicer-1.0.0/PROGRESS.md +272 -0
  15. polyglot_ast_slicer-1.0.0/README.md +228 -0
  16. polyglot_ast_slicer-1.0.0/README.template.md +159 -0
  17. polyglot_ast_slicer-1.0.0/STATE.md +309 -0
  18. polyglot_ast_slicer-1.0.0/benchmarks/agent_eval/README.md +13 -0
  19. polyglot_ast_slicer-1.0.0/benchmarks/agent_eval/run.py +88 -0
  20. polyglot_ast_slicer-1.0.0/benchmarks/agent_eval/tasks.example.json +9 -0
  21. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/README.md +27 -0
  22. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/audit_canary_plausibility.py +84 -0
  23. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/audit_v1.py +59 -0
  24. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/build_bundle.py +79 -0
  25. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/build_canary.py +134 -0
  26. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/build_hard.py +175 -0
  27. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/build_recall.py +184 -0
  28. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/build_recall_raw.py +241 -0
  29. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/build_v2.py +229 -0
  30. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/export_gold.py +51 -0
  31. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/precision.py +162 -0
  32. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/recall.py +126 -0
  33. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/sample_edges.py +137 -0
  34. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/score_canary.py +84 -0
  35. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/score_labels.py +170 -0
  36. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/stats.py +28 -0
  37. polyglot_ast_slicer-1.0.0/benchmarks/edge_eval/test_score_labels.py +58 -0
  38. polyglot_ast_slicer-1.0.0/benchmarks/fault/analysis.json +619 -0
  39. polyglot_ast_slicer-1.0.0/benchmarks/fault/analyze.py +143 -0
  40. polyglot_ast_slicer-1.0.0/benchmarks/fault/rescore.json +211 -0
  41. polyglot_ast_slicer-1.0.0/benchmarks/fault/rescore.py +79 -0
  42. polyglot_ast_slicer-1.0.0/benchmarks/fault/results.json +1766 -0
  43. polyglot_ast_slicer-1.0.0/benchmarks/ground_truth/heldout_eval.py +148 -0
  44. polyglot_ast_slicer-1.0.0/benchmarks/ground_truth/python_eval.py +557 -0
  45. polyglot_ast_slicer-1.0.0/benchmarks/ground_truth/ts_engine.py +67 -0
  46. polyglot_ast_slicer-1.0.0/benchmarks/ground_truth/ts_eval.mjs +744 -0
  47. polyglot_ast_slicer-1.0.0/benchmarks/readme_examples.py +46 -0
  48. polyglot_ast_slicer-1.0.0/benchmarks/scale/scale_bench.py +99 -0
  49. polyglot_ast_slicer-1.0.0/benchmarks/size_compare.py +188 -0
  50. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/RESULTS.md +18 -0
  51. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/baselines.json +249 -0
  52. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/baselines.py +98 -0
  53. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/commits.json +253 -0
  54. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/diagnose.py +99 -0
  55. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/diagnosis.json +98 -0
  56. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/mine.py +52 -0
  57. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/results.json +413 -0
  58. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/results_v2.json +411 -0
  59. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/run_v2.py +185 -0
  60. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/summary.json +60 -0
  61. polyglot_ast_slicer-1.0.0/benchmarks/stage_b/summary_v2.json +20 -0
  62. polyglot_ast_slicer-1.0.0/benchmarks/token_bench.py +327 -0
  63. polyglot_ast_slicer-1.0.0/labels/README.md +21 -0
  64. polyglot_ast_slicer-1.0.0/labels/canary_plausibility.json +74 -0
  65. polyglot_ast_slicer-1.0.0/labels/click/answers.json +702 -0
  66. polyglot_ast_slicer-1.0.0/labels/click/blind_packets.json +802 -0
  67. polyglot_ast_slicer-1.0.0/labels/click/canary_answer_key.json +507 -0
  68. polyglot_ast_slicer-1.0.0/labels/click/canary_labels.csv +116 -0
  69. polyglot_ast_slicer-1.0.0/labels/click/canary_packets.json +922 -0
  70. polyglot_ast_slicer-1.0.0/labels/click/canary_result.json +20 -0
  71. polyglot_ast_slicer-1.0.0/labels/click/labels.csv +101 -0
  72. polyglot_ast_slicer-1.0.0/labels/click_hard/labeler_bundle/LABELING.md +16 -0
  73. polyglot_ast_slicer-1.0.0/labels/click_hard/labeler_bundle/packets_v2.json +1451 -0
  74. polyglot_ast_slicer-1.0.0/labels/click_hard/labeler_bundle/repo_sha.txt +1 -0
  75. polyglot_ast_slicer-1.0.0/labels/click_hard/v2_answer_key.json +425 -0
  76. polyglot_ast_slicer-1.0.0/labels/click_hard/v2_packets.json +1451 -0
  77. polyglot_ast_slicer-1.0.0/labels/express/answers.json +9 -0
  78. polyglot_ast_slicer-1.0.0/labels/express/blind_packets.json +10 -0
  79. polyglot_ast_slicer-1.0.0/labels/express/labels.csv +2 -0
  80. polyglot_ast_slicer-1.0.0/labels/gold_for_human.csv +908 -0
  81. polyglot_ast_slicer-1.0.0/labels/gold_v2_for_human.csv +407 -0
  82. polyglot_ast_slicer-1.0.0/labels/recall_click/labeler_bundle/LABELING.md +9 -0
  83. polyglot_ast_slicer-1.0.0/labels/recall_click/labeler_bundle/packets.json +752 -0
  84. polyglot_ast_slicer-1.0.0/labels/recall_click/labeler_bundle/repo_sha.txt +1 -0
  85. polyglot_ast_slicer-1.0.0/labels/recall_click/recall_answer_key.json +374 -0
  86. polyglot_ast_slicer-1.0.0/labels/recall_click/recall_labels.csv +51 -0
  87. polyglot_ast_slicer-1.0.0/labels/recall_click/recall_packets.json +752 -0
  88. polyglot_ast_slicer-1.0.0/labels/recall_requests/labeler_bundle/LABELING.md +9 -0
  89. polyglot_ast_slicer-1.0.0/labels/recall_requests/labeler_bundle/packets.json +752 -0
  90. polyglot_ast_slicer-1.0.0/labels/recall_requests/labeler_bundle/repo_sha.txt +1 -0
  91. polyglot_ast_slicer-1.0.0/labels/recall_requests/recall_answer_key.json +345 -0
  92. polyglot_ast_slicer-1.0.0/labels/recall_requests/recall_labels.csv +51 -0
  93. polyglot_ast_slicer-1.0.0/labels/recall_requests/recall_packets.json +752 -0
  94. polyglot_ast_slicer-1.0.0/labels/requests/answers.json +702 -0
  95. polyglot_ast_slicer-1.0.0/labels/requests/blind_packets.json +802 -0
  96. polyglot_ast_slicer-1.0.0/labels/requests/canary_answer_key.json +542 -0
  97. polyglot_ast_slicer-1.0.0/labels/requests/canary_labels.csv +121 -0
  98. polyglot_ast_slicer-1.0.0/labels/requests/canary_packets.json +962 -0
  99. polyglot_ast_slicer-1.0.0/labels/requests/canary_result.json +20 -0
  100. polyglot_ast_slicer-1.0.0/labels/requests/labels.csv +101 -0
  101. polyglot_ast_slicer-1.0.0/labels/requests_hard/labeler_bundle/LABELING.md +16 -0
  102. polyglot_ast_slicer-1.0.0/labels/requests_hard/labeler_bundle/packets_v2.json +1451 -0
  103. polyglot_ast_slicer-1.0.0/labels/requests_hard/labeler_bundle/repo_sha.txt +1 -0
  104. polyglot_ast_slicer-1.0.0/labels/requests_hard/v2_answer_key.json +425 -0
  105. polyglot_ast_slicer-1.0.0/labels/requests_hard/v2_packets.json +1451 -0
  106. polyglot_ast_slicer-1.0.0/labels/v1_audit.json +14 -0
  107. polyglot_ast_slicer-1.0.0/labels/zod/answers.json +702 -0
  108. polyglot_ast_slicer-1.0.0/labels/zod/blind_packets.json +802 -0
  109. polyglot_ast_slicer-1.0.0/labels/zod/labeler_bundle/LABELING.md +16 -0
  110. polyglot_ast_slicer-1.0.0/labels/zod/labeler_bundle/packets_v2.json +1451 -0
  111. polyglot_ast_slicer-1.0.0/labels/zod/labeler_bundle/repo_sha.txt +1 -0
  112. polyglot_ast_slicer-1.0.0/labels/zod/labels.csv +101 -0
  113. polyglot_ast_slicer-1.0.0/labels/zod/v2_answer_key.json +425 -0
  114. polyglot_ast_slicer-1.0.0/labels/zod/v2_packets.json +1451 -0
  115. polyglot_ast_slicer-1.0.0/metrics/click_precision.json +33 -0
  116. polyglot_ast_slicer-1.0.0/metrics/click_recall.json +29 -0
  117. polyglot_ast_slicer-1.0.0/metrics/examples.json +30 -0
  118. polyglot_ast_slicer-1.0.0/metrics/heldout_ground_truth.json +116 -0
  119. polyglot_ast_slicer-1.0.0/metrics/python_ground_truth.json +965 -0
  120. polyglot_ast_slicer-1.0.0/metrics/requests_precision.json +28 -0
  121. polyglot_ast_slicer-1.0.0/metrics/requests_recall.json +45 -0
  122. polyglot_ast_slicer-1.0.0/metrics/scale_5000.json +5 -0
  123. polyglot_ast_slicer-1.0.0/metrics/size_comparison.json +685 -0
  124. polyglot_ast_slicer-1.0.0/metrics/synthetic_benchmark.json +28 -0
  125. polyglot_ast_slicer-1.0.0/metrics/tests.json +1 -0
  126. polyglot_ast_slicer-1.0.0/metrics/ts_ground_truth.json +2992 -0
  127. polyglot_ast_slicer-1.0.0/polyglot_ast_slicer/__init__.py +38 -0
  128. polyglot_ast_slicer-1.0.0/polyglot_ast_slicer/__main__.py +8 -0
  129. polyglot_ast_slicer-1.0.0/polyglot_ast_slicer/cache.py +332 -0
  130. polyglot_ast_slicer-1.0.0/polyglot_ast_slicer/graph_engine.py +2090 -0
  131. polyglot_ast_slicer-1.0.0/polyglot_ast_slicer/parser.py +1421 -0
  132. polyglot_ast_slicer-1.0.0/polyglot_ast_slicer/py.typed +0 -0
  133. polyglot_ast_slicer-1.0.0/polyglot_ast_slicer/server.py +451 -0
  134. polyglot_ast_slicer-1.0.0/pyproject.toml +61 -0
  135. polyglot_ast_slicer-1.0.0/scripts/generate_metrics.py +1097 -0
  136. polyglot_ast_slicer-1.0.0/tests/conftest.py +88 -0
  137. polyglot_ast_slicer-1.0.0/tests/test_cache.py +162 -0
  138. polyglot_ast_slicer-1.0.0/tests/test_graph_engine.py +334 -0
  139. polyglot_ast_slicer-1.0.0/tests/test_parser.py +253 -0
  140. polyglot_ast_slicer-1.0.0/tests/test_phase1.py +1259 -0
  141. polyglot_ast_slicer-1.0.0/tests/test_server.py +195 -0
  142. polyglot_ast_slicer-1.0.0/tests/test_slicer.py +111 -0
  143. polyglot_ast_slicer-1.0.0/uv.lock +2199 -0
  144. polyglot_ast_slicer-1.0.0/verify/check_known_cases.py +772 -0
  145. polyglot_ast_slicer-1.0.0/verify/ci_smoke.py +45 -0
  146. polyglot_ast_slicer-1.0.0/verify/dogfood_probe.py +61 -0
  147. polyglot_ast_slicer-1.0.0/verify/fixtures/readme/python/backend/service.py +36 -0
  148. polyglot_ast_slicer-1.0.0/verify/fixtures/readme/typescript/src/service.ts +37 -0
  149. polyglot_ast_slicer-1.0.0/verify/fixtures/smoke/python/app.py +6 -0
  150. polyglot_ast_slicer-1.0.0/verify/fixtures/smoke/typescript/app.ts +7 -0
  151. polyglot_ast_slicer-1.0.0/verify/incremental_probe.py +135 -0
  152. polyglot_ast_slicer-1.0.0/verify/known_cases_output.txt +63 -0
  153. polyglot_ast_slicer-1.0.0/verify/mcp_e2e.py +197 -0
  154. polyglot_ast_slicer-1.0.0/verify/mcp_probe.py +105 -0
  155. polyglot_ast_slicer-1.0.0/verify/measurements.txt +9 -0
  156. polyglot_ast_slicer-1.0.0/verify/network_probe.py +83 -0
  157. polyglot_ast_slicer-1.0.0/verify/perf_probe.py +72 -0
  158. polyglot_ast_slicer-1.0.0/verify/release_artifacts.txt +16 -0
  159. polyglot_ast_slicer-1.0.0/verify/release_gate.txt +12 -0
  160. polyglot_ast_slicer-1.0.0/verify/results/dogfood.json +48 -0
  161. polyglot_ast_slicer-1.0.0/verify/results/incremental.json +58 -0
  162. polyglot_ast_slicer-1.0.0/verify/results/mcp.json +933 -0
  163. polyglot_ast_slicer-1.0.0/verify/results/network.json +13 -0
  164. polyglot_ast_slicer-1.0.0/verify/results/robustness.json +10 -0
  165. polyglot_ast_slicer-1.0.0/verify/results/scale.json +754 -0
  166. polyglot_ast_slicer-1.0.0/verify/results/watcher.json +9 -0
  167. polyglot_ast_slicer-1.0.0/verify/robustness_probe.py +93 -0
  168. polyglot_ast_slicer-1.0.0/verify/scale_probe.py +134 -0
  169. polyglot_ast_slicer-1.0.0/verify/watcher_probe.py +106 -0
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ set -e
3
+ exec make gate
@@ -0,0 +1,28 @@
1
+ name: Bug report
2
+ description: Wrong edge, missed edge, crash, or bad slice
3
+ labels: [bug]
4
+ body:
5
+ - type: textarea
6
+ id: what
7
+ attributes:
8
+ label: What happened
9
+ description: Include the exact command and the raw output.
10
+ validations: { required: true }
11
+ - type: input
12
+ id: version
13
+ attributes:
14
+ label: Version
15
+ description: Output of `polyglot-ast-slicer --version`
16
+ validations: { required: true }
17
+ - type: input
18
+ id: repo
19
+ attributes:
20
+ label: Repository
21
+ description: Public URL and commit SHA, or a minimal reproduction.
22
+ validations: { required: true }
23
+ - type: textarea
24
+ id: expected
25
+ attributes:
26
+ label: Expected vs actual edge
27
+ description: For graph bugs, include source line, target line and `explain_edge` output.
28
+ validations: { required: true }
@@ -0,0 +1,22 @@
1
+ name: Feature request
2
+ description: Propose a capability
3
+ labels: [enhancement]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes:
8
+ label: Problem
9
+ description: What can you not do today? Include a concrete repository example.
10
+ validations: { required: true }
11
+ - type: textarea
12
+ id: proposal
13
+ attributes:
14
+ label: Proposal
15
+ description: What should the tool return, and how would we measure success?
16
+ validations: { required: true }
17
+ - type: dropdown
18
+ id: scope
19
+ attributes:
20
+ label: Scope
21
+ options: [resolution, slice payload, MCP UX, packaging, language support]
22
+ validations: { required: true }
@@ -0,0 +1,41 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ${{ matrix.os }}
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest, windows-latest]
15
+ python-version: ["3.12", "3.13"]
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: astral-sh/setup-uv@v5
19
+ with:
20
+ python-version: ${{ matrix.python-version }}
21
+ - name: Install
22
+ run: uv sync --all-extras
23
+ - name: Lint
24
+ run: uv run ruff check .
25
+ - name: Type check
26
+ run: uv run mypy polyglot_ast_slicer
27
+ - name: Test
28
+ run: uv run pytest
29
+ - name: Metrics drift check (offline)
30
+ run: uv run python scripts/generate_metrics.py --check
31
+ - name: Build wheel
32
+ run: uv build --wheel
33
+ - name: Install wheel in a clean venv and smoke test
34
+ shell: bash
35
+ run: |
36
+ uv venv .smoke-venv
37
+ PYTHON=.smoke-venv/bin/python
38
+ if [ -f .smoke-venv/Scripts/python.exe ]; then PYTHON=.smoke-venv/Scripts/python.exe; fi
39
+ uv pip install --python "$PYTHON" dist/*.whl
40
+ "$PYTHON" -m polyglot_ast_slicer --version
41
+ "$PYTHON" verify/ci_smoke.py
@@ -0,0 +1,24 @@
1
+ # Virtual environment & Python cache
2
+ .venv/
3
+ venv/
4
+ __pycache__/
5
+ *.py[cod]
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ .mypy_cache/
9
+ dist/
10
+ build/
11
+ *.egg-info/
12
+ *.whl
13
+ .coverage
14
+ htmlcov/
15
+
16
+ # Local SQLite AST cache files
17
+ .ast_slicer_cache.db
18
+ .ast_slicer_cache.db-shm
19
+ .ast_slicer_cache.db-wal
20
+
21
+ # OS & Editor files
22
+ .DS_Store
23
+ .idea/
24
+ .vscode/
@@ -0,0 +1 @@
1
+ Follow CLAUDE.md
@@ -0,0 +1,109 @@
1
+ # Changelog
2
+
3
+ Measured numbers are not stored here. They live in `METRICS.md`, which is generated by
4
+ `python scripts/generate_metrics.py` from the committed evaluation scripts, and CI fails if it
5
+ drifts. Parameters such as the 6,000-token payload cap are code constants, not measurements.
6
+
7
+ ## 1.0.0 — 2026-11-06
8
+
9
+ ### Added
10
+
11
+ - Exhaustive call-site ground truth: Jedi for Python (requests, click, flask; held-out
12
+ werkzeug) and the TypeScript compiler API for TS/JS (zod, nest, bulletproof-react,
13
+ node-fetch, express; held-out zustand, moment). Per-repo, per-group and per-form
14
+ precision/recall with 95% Wilson intervals, wired into `METRICS.md`.
15
+ - `verify/` evidence suite: 5k/20k/50k scale, incremental differential after random edits,
16
+ watcher end-to-end, network-blocked queries, MCP through the built wheel, robustness
17
+ inputs, dogfood slices.
18
+ - Slice size comparison (`benchmarks/size_compare.py`) and README worked examples generated
19
+ from real engine output.
20
+ - CI matrix: ubuntu/macos/windows with Python 3.12 and 3.13, offline metrics/README drift
21
+ check, wheel build and clean-venv Python/TS smoke test.
22
+ - Windows `LOCALAPPDATA` cache path and simulated Windows/macOS/Linux path tests, plus
23
+ case-insensitive path and CRLF coverage.
24
+
25
+ ### Fixed
26
+
27
+ - TypeScript/JavaScript: default imports; emitted specifier mapping (`.js` to `.ts`/`.tsx`,
28
+ `.mjs`/`.cjs`/`.jsx`); specifiers whose basename contains a dot; `super.m()` against base
29
+ classes; property-assigned function bodies; bare calls binding to property methods.
30
+ - Python: incremental module reconciliation, call+type relations on one pair, nested
31
+ `TYPE_CHECKING`/try imports, module-scope symbols, getter/setter and overload spans,
32
+ `super()` and constructed receivers.
33
+ - Removed stale test-selection references from README, CHANGELOG, CLI help and benchmarks.
34
+
35
+ ### Changed
36
+
37
+ - `impact_of_diff` returns changed and impacted symbols only; no test selection.
38
+ - `METRICS.md` and `README.md` are generated; `scripts/generate_metrics.py --check` verifies
39
+ both offline.
40
+
41
+ ### Removed
42
+
43
+ - `benchmarks/stage_b/run.py`, `benchmarks/fault/run_click.py` and the Stage B METRICS
44
+ section.
45
+
46
+ ### Notes
47
+
48
+ - The first run downloads the tree-sitter grammars, so it needs internet once; after that
49
+ indexing and queries run offline. No code leaves the machine.
50
+
51
+ ### Measured
52
+
53
+ See `METRICS.md`.
54
+
55
+ ## 0.4.0 — 2026-10-31
56
+
57
+ ### Added
58
+
59
+ - `impact_of_diff(base, head | diff)`: parses a unified diff, maps changed lines to symbols,
60
+ walks upstream call edges, and returns changed and impacted symbols by hop.
61
+ Verified on real git commits.
62
+ - Slice context: each region carries `# class X:` and the referenced `# import:` lines
63
+ without repeating the sliced code.
64
+ - TypeScript: `tsconfig` `baseUrl`/`paths`, `export *` barrel re-exports, and verified
65
+ `.tsx`/`.js` grammar loading.
66
+ - `benchmarks/agent_eval/`: dry-run harness that measures tool payload tokens per task and
67
+ marks resolve rate UNMEASURED. No model adapter is shipped.
68
+
69
+ ### Measured
70
+
71
+ See `METRICS.md`.
72
+
73
+ ## 0.3.0 — 2026-10-31
74
+
75
+ ### Changed (breaking)
76
+
77
+ - Removed the 0.50 name-only edge tier; unresolved and ambiguous calls now produce no edge and
78
+ are tracked in a reverse index for incremental relinking.
79
+ - `get_ast_call_slice` caps the exact JSON payload at 6,000 tokens by default, applies per-hop
80
+ fan-out caps (10) and a total cap (40), and treats symbols with degree >= 150 as hubs.
81
+ - Metadata requires `include_metadata=True`; the default payload is `compiled_context` plus
82
+ token metrics and diagnostics.
83
+ - Ambiguous queries return `code: "ambiguous_symbol"` with all candidates.
84
+ - The SQLite index moved from the repository into the OS cache directory.
85
+ - `explain_edge` exposes per-edge provenance (`resolution`, `line`, `receiver`, `name`).
86
+
87
+ ### Added
88
+
89
+ - Self-recursion is kept as a self-edge and reported separately.
90
+ - `POLYGLOT_AST_ALLOWED_ROOTS` allowlist; escaping symlinks, binary files and oversized files
91
+ are skipped and reported.
92
+ - Differential test: incremental graph must equal a from-scratch rebuild after random edits.
93
+
94
+ ### Fixed
95
+
96
+ - Symlinked source files outside the repository crashed indexing.
97
+ - Read-only checkouts failed to open the cache database.
98
+ - Class-level TS static factories made the class look self-recursive.
99
+ - Bare calls such as `open(...)` inside a class bound to a same-named method.
100
+ - Nested/local classes and functions now resolve within their lexical scope.
101
+
102
+ ### Measured
103
+
104
+ See `METRICS.md`.
105
+
106
+ ## 0.2.0 and earlier
107
+
108
+ Initial parser, cache, graph engine, MCP server and CLI. Historical numbers are superseded by
109
+ `METRICS.md`.
@@ -0,0 +1,8 @@
1
+ # Guidelines for AI agents on polyglot-ast-slicer
2
+ Bias: caution over speed. For trivial tasks, use judgment.
3
+ 1. Think before coding: state assumptions; ask only if blocked, otherwise state the assumption and proceed; list interpretations instead of picking silently; say so if a simpler approach exists.
4
+ 2. Simplicity first: minimum code for the request; no speculative features, single-use abstractions or unrequested configurability; no error handling for impossible cases.
5
+ 3. Surgical changes: every changed line traces to the request; do not restyle or refactor adjacent code; mention unrelated dead code instead of deleting it; remove only what your change orphaned.
6
+ 4. Goal-driven: bug -> failing test first, then fix; refactor -> tests green before and after; for multi-step work write a plan "step -> verify: check".
7
+ Project rules: never invent numbers, APIs or results (unmeasured = UNMEASURED); every figure in README/METRICS comes from a committed script; prefer a missing edge to a wrong edge; never relabel data or lower a gate to pass; engine changes need a regression test plus a re-run of the labeled precision samples.
8
+ Token discipline: don't re-read known files; don't print full test logs; keep reports short.
@@ -0,0 +1,43 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ uv sync --all-extras
7
+ make gate # offline: ruff, mypy, pytest, lock, metrics-check
8
+ make install-hooks # routes git commit through .githooks/pre-commit
9
+ make metrics # network: clones pinned repos and rewrites artifacts + METRICS.md
10
+ ```
11
+
12
+ ## Gates (must pass before a PR is reviewed)
13
+
14
+ 1. `uv run pytest` — no failures. Skips are only allowed for a grammar that cannot be
15
+ downloaded; the skip must name the grammar.
16
+ 2. `uv run ruff check .`
17
+ 3. `uv run mypy polyglot_ast_slicer`
18
+ 4. `uv lock --check`
19
+ 5. `uv run python scripts/generate_metrics.py --check` — offline; renders `METRICS.md` from
20
+ the committed `metrics/*.json` artifacts, never clones. `make metrics` is the networked
21
+ path: it clones the pinned repos (verifying their SHAs), reruns the harnesses, and rewrites
22
+ both the artifacts and `METRICS.md`. Never hand-edit either.
23
+ 6. A wheel install smoke test: `uv build --wheel`, install into a fresh venv, run
24
+ `polyglot-ast-slicer --version`.
25
+
26
+ ## Resolution changes
27
+
28
+ - Prefer a missing edge to a wrong edge. Every edge must carry `relation`, `confidence`,
29
+ `resolution` and `line`; do not add a name-only fallback.
30
+ - Run `benchmarks/edge_eval/precision.py` on `requests` and `click` before and after. Precision
31
+ must not drop below 98%; if it does, revert the rule.
32
+ - New inference rules need a regression fixture plus the precision delta in the PR description.
33
+
34
+ ## Languages
35
+
36
+ Do not add a language without a manifest (tier, grammar source, limitations), golden fixtures,
37
+ two pinned repositories and a labelled 100-edge sample. Anything below its tier's precision
38
+ gate ships as experimental and hidden by default.
39
+
40
+ ## Commits
41
+
42
+ Conventional commits (`feat:`, `fix:`, `docs:`, `test:`). One logical change per commit; gates
43
+ must pass in every commit you push.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Polyglot AST Slicer contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,150 @@
1
+ # Generated metrics
2
+
3
+ <!-- Generated by `make metrics`. Do not edit by hand. -->
4
+
5
+ Pinned inputs: requests `3c7baaa`, click `2247b35`. Intervals are 95% Wilson score intervals.
6
+ Test suite (generated): 107 tests collected.
7
+
8
+ ## Definitions
9
+
10
+ - **Confirmed by Jedi (strict)** — Jedi's definition lands inside the claimed target's
11
+ file and line span.
12
+ - **Not contradicted by Jedi (canonical)** — strict, or Jedi lands on a file that
13
+ re-exports the claimed symbol. This is not precision and is not the headline.
14
+ - **Hand-labeled precision (headline)** — human verdict on the blind 100-edge packet.
15
+ requests and click are labeled; zod is still unlabeled.
16
+ - **Conditional recall** — found edges divided by call sites Jedi resolves to a project
17
+ symbol. **Unconditional recall is UNMEASURED.**
18
+ ## Hand-labeled precision (headline)
19
+
20
+ | Repo | Labeled | Correct | Unsure | Precision (unsure=incorrect) | Precision (unsure excluded) |
21
+ |---|---:|---:|---:|---|---|
22
+ | `requests` | 100 | 100 | 0 | 100.0% (95% CI 96.3%–100.0%) | 100.0% (95% CI 96.3%–100.0%) |
23
+ | `click` | 100 | 100 | 0 | 100.0% (95% CI 96.3%–100.0%) | 100.0% (95% CI 96.3%–100.0%) |
24
+ | `zod` | 0 | — | — | UNMEASURED | UNMEASURED |
25
+
26
+ ## Canary check (seeded wrong edges mixed into the blind set)
27
+
28
+ | Repo | Seeded | Labeled correct | False-accept rate | False rejects | Unsure | Agreement with prior pass | Cohen's kappa |
29
+ |---|---:|---:|---|---:|---:|---|---|
30
+ | `requests` | 20 | 0 | 0.0% (95% CI 0.0%–16.1%) | 0/100 | 0 | 100/100 | n/a |
31
+ | `click` | 15 | 0 | 0.0% (95% CI 0.0%–20.4%) | 0/100 | 0 | n/a (no prior pass) | n/a |
32
+ | `zod` | — | — | UNMEASURED | — | — | — | — |
33
+
34
+ ## Hard-kind precision (v2 packets)
35
+
36
+ | Repo | Kind | n | Correct | Unsure | Precision (unsure=incorrect) |
37
+ |---|---|---:|---:|---:|---|
38
+ | `requests` | all | — | — | — | UNMEASURED |
39
+ | `click` | all | — | — | — | UNMEASURED |
40
+ | `zod` | all | — | — | — | UNMEASURED |
41
+ ## Edge agreement with Jedi (100 random call edges, seed 42)
42
+
43
+ | Repo | Sampled | Confirmed (strict) | Not contradicted (canonical) |
44
+ |---|---:|---:|---:|
45
+ | `requests` | 100 | 39/100 | 100/100 (100.0%; 95% CI 96.3%–100.0%) |
46
+ | `click` | 100 | 33/100 | 100/100 (100.0%; 95% CI 96.3%–100.0%) |
47
+
48
+ The canonical column also accepts re-export hops; it is not hand-labeled precision.
49
+
50
+ ## Conditional recall (150 call sites, seed 7; Jedi-resolvable only)
51
+
52
+ | Repo | Found / resolvable | Recall | Unresolved by Jedi |
53
+ |---|---:|---:|---:|
54
+ | `requests` | 45/58 | 77.6% (95% CI 65.3%–86.4%) | 92 |
55
+ | `click` | 73/77 | 94.8% (95% CI 87.4%–98.0%) | 73 |
56
+
57
+ Unconditional recall (hand-labelled true targets) is UNMEASURED.
58
+
59
+ ## Python call-site ground truth (Jedi, `src/` only)
60
+
61
+ Pinned: requests `3c7baaa`, click `2247b35`, flask `49943b5`. Every raw tree-sitter call site is resolved with Jedi (`follow_imports=True`).
62
+ Precision = correct/(correct+wrong); recall = correct/project sites. High-confidence
63
+ means the tool's reported edge confidence is at least 0.95.
64
+
65
+ | Repo | Sites | Correct | Wrong | Missed | Ambiguous (reported) | Precision | High-conf precision | Recall |
66
+ |---|---:|---:|---:|---:|---:|---|---|---|
67
+ | `requests` | 307 | 276 | 0 | 31 | 0 (0) | 100.0% (95% CI 98.6%–100.0%) | 100.0% (257/257) | 89.9% (95% CI 86.0%–92.8%) |
68
+ | `click` | 740 | 552 | 1 | 187 | 8 (4) | 99.8% (95% CI 99.0%–100.0%) | 99.8% (460/461) | 74.6% (95% CI 71.3%–77.6%) |
69
+ | `flask` | 348 | 210 | 0 | 138 | 2 (0) | 100.0% (95% CI 98.2%–100.0%) | 100.0% (193/193) | 60.3% (95% CI 55.1%–65.3%) |
70
+
71
+ Combined: 1038 correct, 1 wrong, 356 missed of 1395 project sites; precision 99.9%, recall 74.4%, high-confidence precision 99.9% (910/911).
72
+
73
+ | Form | Sites | Correct | Wrong | Missed | Ambiguous reported | Precision | Recall |
74
+ |---|---:|---:|---:|---:|---:|---|---|
75
+ | `bare` | 517 | 398 | 1 | 118 | 4 | 99.7% | 77.0% |
76
+ | `module_attr` | 6 | 6 | 0 | 0 | 0 | 100.0% | 100.0% |
77
+ | `self_cls` | 442 | 366 | 0 | 76 | 0 | 100.0% | 82.8% |
78
+ | `super` | 43 | 34 | 0 | 9 | 0 | 100.0% | 79.1% |
79
+ | `constructor` | 175 | 158 | 0 | 17 | 0 | 100.0% | 90.3% |
80
+ | `aliased_import` | 13 | 13 | 0 | 0 | 0 | 100.0% | 100.0% |
81
+ | `chained` | 1 | 0 | 0 | 1 | 0 | 0.0% | 0.0% |
82
+ | `callback` | 13 | 0 | 0 | 13 | 0 | 0.0% | 0.0% |
83
+ | `other` | 185 | 63 | 0 | 122 | 0 | 100.0% | 34.1% |
84
+
85
+ Independent hand audit: 30/30 sampled unjudged edges correct, with file:line citations in `metrics/python_ground_truth.json`.
86
+
87
+ ## TypeScript/JavaScript call-site ground truth (TypeScript compiler)
88
+
89
+ Pinned: zod `ca42965` (src; excludes __tests__,benchmarks), nest `416830c` (packages; excludes test,.spec.ts,.e2e-spec.ts), bulletproof-react `9506629` (src; excludes __tests__,test,testing,.test.ts,.test.tsx,.stories.ts,.stories.tsx), node-fetch `8b3320d` (src), express `1faf228` (lib).
90
+ Every call, `new`, and JSX tag in production source is resolved with `checker.getSymbolAtLocation` (aliases followed); test and story files are excluded per repo.
91
+ Precision = correct/(correct+wrong); recall = correct/project sites. High-confidence means the tool's reported confidence is at least 0.95.
92
+
93
+ | Repo | Group | Sites | Correct | Wrong | Missed | Ambiguous (reported) | Precision | High-conf precision | Recall |
94
+ |---|---|---:|---:|---:|---:|---:|---|---|---|
95
+ | `zod` | TS+TSX | 557 | 452 | 0 | 105 | 0 (0) | 100.0% (95% CI 99.2%–100.0%) | 100.0% (417/417) | 81.1% (95% CI 77.7%–84.2%) |
96
+ | `nest` | TS+TSX | 1998 | 1783 | 0 | 215 | 0 (0) | 100.0% (95% CI 99.8%–100.0%) | 100.0% (1442/1442) | 89.2% (95% CI 87.8%–90.5%) |
97
+ | `bulletproof-react` | TS+TSX | 213 | 159 | 0 | 54 | 0 (0) | 100.0% (95% CI 97.6%–100.0%) | 100.0% (159/159) | 74.6% (95% CI 68.4%–80.0%) |
98
+ | `node-fetch` | JS+JSX | 89 | 84 | 0 | 5 | 0 (0) | 100.0% (95% CI 95.6%–100.0%) | 100.0% (84/84) | 94.4% (95% CI 87.5%–97.6%) |
99
+ | `express` | JS+JSX | 67 | 21 | 0 | 46 | 0 (0) | 100.0% (95% CI 84.5%–100.0%) | 100.0% (20/20) | 31.3% (95% CI 21.5%–43.2%) |
100
+
101
+ | Group | Sites | Correct | Wrong | Missed | Ambiguous (reported) | Precision | High-conf precision | Recall |
102
+ |---|---:|---:|---:|---:|---:|---|---|---|
103
+ | **TS+TSX** | 2768 | 2394 | 0 | 374 | 0 (0) | 100.0% (95% CI 99.8%–100.0%) | 100.0% (2018/2018) | 86.5% (95% CI 85.2%–87.7%) |
104
+ | **JS+JSX** | 156 | 105 | 0 | 51 | 0 (0) | 100.0% (95% CI 96.5%–100.0%) | 100.0% (104/104) | 67.3% (95% CI 59.6%–74.2%) |
105
+
106
+ | Group | Form | Sites | Correct | Wrong | Missed | Ambiguous reported | Precision | Recall |
107
+ |---|---|---:|---:|---:|---:|---:|---|---|
108
+ | TS+TSX | `bare` | 581 | 480 | 0 | 101 | 0 | 100.0% | 82.6% |
109
+ | TS+TSX | `self_cls` | 1431 | 1321 | 0 | 110 | 0 | 100.0% | 92.3% |
110
+ | TS+TSX | `constructor` | 333 | 326 | 0 | 7 | 0 | 100.0% | 97.9% |
111
+ | TS+TSX | `chained` | 7 | 0 | 0 | 7 | 0 | 0.0% | 0.0% |
112
+ | TS+TSX | `other` | 313 | 171 | 0 | 142 | 0 | 100.0% | 54.6% |
113
+ | TS+TSX | `super` | 7 | 7 | 0 | 0 | 0 | 100.0% | 100.0% |
114
+ | TS+TSX | `jsx` | 96 | 89 | 0 | 7 | 0 | 100.0% | 92.7% |
115
+ | JS+JSX | `bare` | 86 | 61 | 0 | 25 | 0 | 100.0% | 70.9% |
116
+ | JS+JSX | `self_cls` | 25 | 7 | 0 | 18 | 0 | 100.0% | 28.0% |
117
+ | JS+JSX | `constructor` | 36 | 36 | 0 | 0 | 0 | 100.0% | 100.0% |
118
+ | JS+JSX | `other` | 8 | 0 | 0 | 8 | 0 | 0.0% | 0.0% |
119
+ | JS+JSX | `module_attr` | 1 | 1 | 0 | 0 | 0 | 100.0% | 100.0% |
120
+
121
+ Gate (high-confidence precision >= 95%, overall precision >= 90%, recall >= 50%): TS+TSX PASS; JS+JSX PASS.
122
+
123
+ Independent hand audit: 30/30 sampled edges the compiler cannot judge were correct, with file:line citations in `metrics/ts_ground_truth.json`.
124
+
125
+ ## Slice size comparison (30 random symbols per language, seed 42)
126
+
127
+ Default slice payload tokens vs the entry symbol's whole file vs every unique file containing its callers and callees. Sizes only; no sufficiency claim.
128
+
129
+ | Language | Symbols | Payload tokens p10 / median / p90 | Entry file p10 / median / p90 | Caller+callee files p10 / median / p90 |
130
+ |---|---:|---|---|---|
131
+ | python | 30 | 259 / 522 / 5422 | 1254 / 4906 / 14296 | 1254 / 5430 / 31961 |
132
+ | typescript | 30 | 256 / 2323 / 5506 | 182 / 1032 / 39169 | 539 / 2404 / 39169 |
133
+
134
+ ## Synthetic token benchmark (hops=2)
135
+
136
+ | Target | Touched files | Repo | Slice | Saved vs files |
137
+ |---|---:|---:|---:|---:|
138
+ | `process_payment` | 10540 | 12214 | 539 | 94.89% |
139
+ | `handle_checkout_webhook` | 10540 | 12214 | 539 | 94.89% |
140
+ | `submitOrderCheckout` | 1674 | 12214 | 168 | 89.96% |
141
+
142
+ Corpus: 4 files, 252 symbols, 16 edges. Latency is machine-dependent and omitted here; run `benchmarks/scale/scale_bench.py` for timings.
143
+
144
+ ## Scale (5000 generated files, seed 42)
145
+
146
+ | Files | Symbols | Edges |
147
+ |---:|---:|---:|
148
+ | 5000 | 5000 | 5000 |
149
+
150
+ Larger runs: `python benchmarks/scale/scale_bench.py --files 50000 --json`.
@@ -0,0 +1,27 @@
1
+ PY ?= uv run --extra dev
2
+
3
+ .PHONY: gate lint types test lock metrics metrics-check install-hooks
4
+
5
+ gate: lint types test lock metrics-check
6
+
7
+ lint:
8
+ $(PY) ruff check .
9
+
10
+ types:
11
+ $(PY) mypy polyglot_ast_slicer
12
+
13
+ test:
14
+ $(PY) pytest
15
+
16
+ lock:
17
+ uv lock --check
18
+
19
+ metrics:
20
+ $(PY) python scripts/generate_metrics.py
21
+
22
+ metrics-check:
23
+ $(PY) python scripts/generate_metrics.py --check
24
+
25
+ install-hooks:
26
+ git config core.hooksPath .githooks
27
+ @echo "pre-commit hook installed"