You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(resolver): resolve Python builtins through the formal tier (DEBT-005)
Root cause was investigated during earlier work: tree-sitter-stack-graphs-
python 0.3.0's bundled src/builtins.py ships empty, so FormalResolver's
merged builtins graph had nothing in it — any reference to len/print/range/
etc. fell through to the resolved/textual tier instead of formal, despite
stack-graphs.tsg wiring up a "<builtins>" push-symbol fallback edge for
exactly this case.
Fix required no TSG grammar patch. build_python_builtins_graph() builds a
StackGraph from a synthetic PYTHON_BUILTINS_STUB (~70 common builtins as
plain def/class stubs) through the same compiled `sgl` rules the upstream
crate already provides, using FILE_PATH="<builtins>.py". That exact path
satisfies stack-graphs.tsg's own per-file module-path rule (the regex branch
that turns a file's relative path into a pop_symbol chain anchored at
ROOT_NODE), producing a pop_symbol="<builtins>" node — the missing
counterpart to every file's push_symbol="<builtins>" fallback edge. Verified
by two new tests (len()/print() resolve; a genuinely undefined name still
doesn't) and a real `ci index` smoke test showing call_sites.confidence =
'formal' for len/print/enumerate/isinstance/sorted calls.
Known scope limit, documented in pattern-debt-registry.yaml and the README:
this is correct at the call_sites storage layer, but rebuild_graph filters
call_sites -> call_edges by name-match against indexed project symbols,
independent of confidence — builtins never match (they aren't project
symbols) so they still don't produce call_edges rows or show up in
callers/path/caller_count_by_confidence. Making that visible would need
builtins to become pseudo-symbols, which risks skewing hub_count/coreness
project-wide (len/print called everywhere) — deliberately left as a
separate, explicitly-tracked follow-up rather than folded in here.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WTXEBnJdVd1o2egp1bTBaX
Copy file name to clipboardExpand all lines: README.md
+5-6Lines changed: 5 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,12 +20,11 @@ tính graph metrics (coreness/hubs), và phục vụ qua SQLite FTS5 + semantic
20
20
2.**Call graph phân cấp** — mỗi edge mang một mức tin cậy:
21
21
-`resolved` — khớp file symbol / import / alias (tier-1, conservative resolver).
22
22
-`inferred` — method call phân giải theo kiểu của receiver (tier-2: `self`/`this` → class bao quanh; biến typed → `type_map`).
23
-
-`formal` — phân giải phạm vi tĩnh qua `stack-graphs` (tier-3, hiện hỗ trợ Python). Được bảo vệ bởi **hai deadline độc lập**: một cho bước build stack-graph (TSG) và một cho bước path-stitching, cộng thêm cap `MAX_WORK_PER_PHASE = 4096` để chống DoS.
> `src/builtins.py` bundled trong `tree-sitter-stack-graphs-python` 0.3.0 rỗng, và rule TSG upstream
26
-
> push symbol `"<builtins>"` nhưng không có rule nào pop lại — dead-end ở tầng grammar, không phải bug
27
-
> phía `ci`. Repo upstream (`github/stack-graphs`) đã bị archive từ 9/2025, không còn nhận fix. Các
28
-
> reference gọi builtin sẽ fall back về `resolved`/`textual` tier như bình thường.
23
+
-`formal` — phân giải phạm vi tĩnh qua `stack-graphs` (tier-3, hiện hỗ trợ Python). Được bảo vệ bởi **hai deadline độc lập**: một cho bước build stack-graph (TSG) và một cho bước path-stitching, cộng thêm cap `MAX_WORK_PER_PHASE = 4096` để chống DoS. Python builtins (`len`, `print`, `range`...) resolve qua tier này nhờ `build_python_builtins_graph` tự build (bundled `src/builtins.py` của `tree-sitter-stack-graphs-python` 0.3.0 rỗng, không dùng được trực tiếp).
24
+
> **Lưu ý**: builtin call hiện được gắn đúng `edge_confidence: formal` ở tầng lưu trữ nội bộ
25
+
> (`call_sites`), nhưng **chưa hiển thị qua `callers`/`path`/`caller_count_by_confidence`** —
26
+
> các tool đó chỉ đọc `call_edges`, vốn chỉ chứa cạnh giữa 2 symbol đã index trong project;
27
+
> builtin không phải project symbol nên không tạo `call_edges` dù ở tier nào.
29
28
-`textual` — chỉ khớp tên (fallback).
30
29
3.**Import graph** — `import_edges` (file→module/file) cho tool `dependencies`.
31
30
4.**Graph metrics** — `coreness` (k-core, O(V+E)) và `is_hub` để AI biết đâu là lõi hệ thống.
Copy file name to clipboardExpand all lines: docs/pattern-debt-registry.yaml
+17-14Lines changed: 17 additions & 14 deletions
Original file line number
Diff line number
Diff line change
@@ -54,24 +54,27 @@ items:
54
54
owner_hint: testing
55
55
56
56
DEBT-005-formal-python-builtins-unresolved:
57
-
status: open
58
-
urgency: low
57
+
status: resolved
58
+
urgency: done
59
+
resolved_at: "2026-07-01"
59
60
description: >
60
61
FormalResolver (formal.rs) không resolve được Python builtins (len, print,
61
-
range...). Root cause đã điều tra trong test_resolve_file_merges_builtins_
62
-
without_error (formal.rs): src/builtins.py bundled trong
62
+
range...). Root cause: src/builtins.py bundled trong
63
63
tree-sitter-stack-graphs-python 0.3.0 rỗng, và stack-graphs.tsg push symbol
64
-
"<builtins>" nhưng không rule nào pop lại — dead-end ở tầng grammar upstream,
65
-
không sửa được từ phía merge builtins graph. Verified 2026-07-01: 0.3.0 vẫn
66
-
là bản mới nhất (12/2024), repo github/stack-graphs đã bị archive 9/2025 nên
67
-
sẽ không có upstream fix. Không ảnh hưởng correctness — reference gọi
68
-
builtin fall back về resolved/textual tier bình thường, chỉ mất confidence
69
-
tier cao nhất.
70
-
current_control: "README caveat dưới bullet formal tier; fallback resolver vẫn hoạt động"
64
+
"<builtins>" mà không có source builtins nào tận dụng đúng cơ chế per-file
65
+
module-path để pop lại nó. Fix: build_python_builtins_graph() tự build
66
+
StackGraph cho một PYTHON_BUILTINS_STUB (~70 builtin phổ biến) bằng đúng
67
+
`sgl` upstream, với FILE_PATH="<builtins>.py" — path này khớp regex
68
+
"([^/]+)\.py$" của chính stack-graphs.tsg, tự nhiên tạo ra node
69
+
pop_symbol="<builtins>" gắn thẳng vào ROOT_NODE. KHÔNG cần vá/fork TSG rule
70
+
nào — chỉ cần gọi đúng API public (build_stack_graph_into) với nội dung và
71
+
FILE_PATH phù hợp. Verified bằng test thật (test_resolve_file_resolves_
72
+
python_builtins) + smoke test CLI thật (index file dùng len/print/enumerate/
73
+
isinstance/sorted → call_sites.confidence='formal' cho cả 5).
74
+
current_control: "build_python_builtins_graph() trong formal.rs; 2 regression test (resolves builtins + vẫn từ chối tên thật sự undefined)"
71
75
remaining:
72
-
- "Xác nhận tree_sitter_stack_graphs::StackGraphLanguage::from_str + tsg_source() đủ để tự vá TSG rule (pop \"<builtins>\") mà không cần fork toàn crate"
73
-
- "Tự viết builtins.py (định nghĩa len/print/range/...) + override rule TSG bù chỗ thiếu pop \"<builtins>\""
74
-
- "Regression test: len()/print() resolve tới definition_symbol qua formal tier, không chỉ textual"
76
+
- "GIỚI HẠN ĐÃ BIẾT: call_sites.confidence='formal' cho builtin KHÔNG tạo ra call_edges row — rebuild_graph() (pipeline.rs) lọc theo tên khớp symbols đã index trong project, độc lập với confidence, nên builtin (không phải project symbol) không bao giờ có call_edges dù tier nào. Nghĩa là callers/path/CallerCountByConfidence chưa thấy được thay đổi này — chỉ đúng ở tầng lưu trữ call_sites, sẵn sàng cho consumer tương lai."
77
+
- "Nếu muốn builtin hiển thị qua tool: cần thiết kế riêng (builtin thành pseudo-symbol?) — rủi ro thật: len/print sẽ có caller_count khổng lồ khắp mọi codebase Python, có thể làm lệch hub_count/coreness. Cố ý chưa làm, cần bàn kỹ trước khi động vào."
0 commit comments