callers, reverse-deps, and digest --json cut their output at a default cap without saying so, so a truncated result is indistinguishable from a complete one. For an agent consuming sb, that becomes a confidently wrong answer: it reports "3 callers", sizes a refactor from that number, and moves on.
impact already handles the analogous ambiguity case well, and its note is a good template for the rest: # note: 'decodeBinary' matched 70 symbols; showing all. Use a more specific suffix (e.g. 'Type.method') to narrow.
Version: ast-bro 3.0.0 (Homebrew aeroxy/tap, bottle 64), macOS 15.5 arm64. Repro below is from pgjdbc, but nothing about it is repo-specific.
Repro
callers reports the post-cap count as if it were the total
$ sb callers decodeBinary | head -1
# 113 caller(s) for 'decodeBinary':
$ sb callers decodeBinary --limit 3 | head -1
# 3 caller(s) for 'decodeBinary':
The second header is exactly what a symbol with three callers prints. Since --limit defaults to 200, the same thing happens with no flags at all on any symbol above that count.
reverse-deps cuts the list with no note
$ sb reverse-deps pgjdbc/src/main/java/org/postgresql/api/codec/CodecContext.java | wc -l
201
That is the default --limit 200 plus one header line. Nothing in the output says the list was cut.
digest is honest in text but not in JSON
Text mode prints ... +13 more, and the per-file header carries the true member count, so a human sees the truncation. ast-bro.map.v1 carries neither a truncation flag nor a total:
$ sb digest <dir> --max-members 2 --json | python3 -c "import json,sys; print(sorted(json.load(sys.stdin)['files'][0].keys()))"
['declarations', 'error_count', 'language', 'line_count', 'path']
Proposal
- Text. When a cap is hit, report the total and name the flag that lifts it —
# 113 caller(s) for 'decodeBinary' (showing 3; raise --limit to see the rest): — following the note impact already prints. Same shape for reverse-deps and for each impact section.
- JSON. Add
total and truncated beside every capped collection: callers.matches[], reverse-deps, impact.sections[].entries[], and the declarations[] that digest --max-members cuts. ast-bro.context.v1 already exposes truncated, so reusing that field name everywhere would let a consumer check one thing.
- Depth-bounded walks.
deps, reverse-deps, callers, callees, impact, and trace stop at --depth rather than truncating a list, but from the caller's side the effect is the same. A flag saying the frontier was still non-empty at the cutoff would separate "the graph ends here" from "the walk stopped here".
Minor, related
--limit exists on callers, impact, and reverse-deps but not on callees, which returned 68 rows unbounded in my repo. Whichever way that inconsistency is meant to resolve, the per-command defaults are currently discoverable only through --help: --max-members 50 (digest), --limit 200 (callers, impact, reverse-deps), --budget 8000 (context), -k 10 (search), and the --depth defaults of 1, 2, 3, and 12. sb prompt mentions none of them, so an agent working from the generated prompt cannot know a cap exists, let alone that it was hit.
callers,reverse-deps, anddigest --jsoncut their output at a default cap without saying so, so a truncated result is indistinguishable from a complete one. For an agent consumingsb, that becomes a confidently wrong answer: it reports "3 callers", sizes a refactor from that number, and moves on.impactalready handles the analogous ambiguity case well, and its note is a good template for the rest:# note: 'decodeBinary' matched 70 symbols; showing all. Use a more specific suffix (e.g. 'Type.method') to narrow.Version:
ast-bro 3.0.0(Homebrewaeroxy/tap, bottle 64), macOS 15.5 arm64. Repro below is from pgjdbc, but nothing about it is repo-specific.Repro
callersreports the post-cap count as if it were the totalThe second header is exactly what a symbol with three callers prints. Since
--limitdefaults to 200, the same thing happens with no flags at all on any symbol above that count.reverse-depscuts the list with no noteThat is the default
--limit 200plus one header line. Nothing in the output says the list was cut.digestis honest in text but not in JSONText mode prints
... +13 more, and the per-file header carries the true member count, so a human sees the truncation.ast-bro.map.v1carries neither a truncation flag nor a total:Proposal
# 113 caller(s) for 'decodeBinary' (showing 3; raise --limit to see the rest):— following the noteimpactalready prints. Same shape forreverse-depsand for eachimpactsection.totalandtruncatedbeside every capped collection:callers.matches[],reverse-deps,impact.sections[].entries[], and thedeclarations[]thatdigest --max-memberscuts.ast-bro.context.v1already exposestruncated, so reusing that field name everywhere would let a consumer check one thing.deps,reverse-deps,callers,callees,impact, andtracestop at--depthrather than truncating a list, but from the caller's side the effect is the same. A flag saying the frontier was still non-empty at the cutoff would separate "the graph ends here" from "the walk stopped here".Minor, related
--limitexists oncallers,impact, andreverse-depsbut not oncallees, which returned 68 rows unbounded in my repo. Whichever way that inconsistency is meant to resolve, the per-command defaults are currently discoverable only through--help:--max-members 50(digest),--limit 200(callers,impact,reverse-deps),--budget 8000(context),-k 10(search), and the--depthdefaults of 1, 2, 3, and 12.sb promptmentions none of them, so an agent working from the generated prompt cannot know a cap exists, let alone that it was hit.