fix(github-research): disclose truncated trees (#7815)

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
周龙杰 2026-11-04 10:40:59 +08:00 committed by GitHub
parent 5371343f69
commit 900a5173b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 1 deletions

View File

@ -1913,6 +1913,7 @@ File reads accept raw repository-relative paths and preserve spaces, Unicode,
`#`, `?`, and literal percent signs with either HTTP client.
Directory listings ask for the repository's own default branch, so a repository that
uses neither `main` nor `master` reports its current tree instead of a stale branch.
They indicate when GitHub or the local output limit truncates the listing.
The `issues` command excludes pull requests and follows additional pages to fill
its requested issue limit; the `prs` command remains available for pull requests.

View File

@ -57,6 +57,7 @@ python /path/to/skill/scripts/github_api.py <owner> <repo> tree
- releases
The `issues` command returns repository issues only, excluding pull requests. It follows additional pages when needed to fill the requested issue limit; use `prs` to research pull requests separately.
The `tree` command marks results truncated by GitHub or by its own output limit; inspect subdirectories separately before drawing conclusions from an incomplete tree.
**Round 2 - Discovery (3-5 web_search)**
- Get overview and identify key terms

View File

@ -252,7 +252,12 @@ class GitHubAPI:
else:
lines.append(f"{indent}{name}")
return "\n".join(lines[:100]) # Limit output
output = lines[:100]
if len(lines) > 100:
output.append("[Tree output limit: additional entries omitted]")
if tree_data.get("truncated"):
output.append("[GitHub truncated the tree; additional entries may be missing]")
return "\n".join(output)
def summarize_repo(self, owner: str, repo: str) -> Dict:
"""

View File

@ -173,6 +173,35 @@ def test_tree_does_not_guess_another_branch(monkeypatch, fallback_client):
assert asked == ["/repos/owner/repo/git/trees/HEAD"]
@pytest.mark.parametrize("truncated", [False, True])
def test_tree_reports_upstream_truncation(fallback_client, truncated):
client, _ = fallback_client
result = client.format_tree({"tree": [{"path": "README.md", "type": "blob"}], "truncated": truncated})
assert result.startswith("README.md")
assert ("GitHub" in result and "truncated" in result) is truncated
@pytest.mark.parametrize("count", [99, 100, 101])
def test_tree_reports_local_entry_limit(fallback_client, count):
client, _ = fallback_client
tree = [{"path": f"file-{i}", "type": "blob"} for i in range(count)]
result = client.format_tree({"tree": tree, "truncated": False})
assert ("output limit" in result) is (count > 100)
assert "file-98" in result
if count > 100:
assert "file-100" not in result
def test_tree_reports_both_limits_and_ignores_entries_below_max_depth(fallback_client):
client, _ = fallback_client
hidden = [{"path": f"folder/file-{i}", "type": "blob"} for i in range(101)]
assert client.format_tree({"tree": hidden}, max_depth=1) == ""
visible = [{"path": f"file-{i}", "type": "blob"} for i in range(101)]
result = client.format_tree({"tree": visible, "truncated": True})
assert "output limit" in result
assert "GitHub truncated" in result
def _client_returning_status(monkeypatch, transport, status, body=b'{"ok": true}'):
"""One client whose transport answers ``status`` for every request, plus its module.