Found while building engram's codedb bridge, which machine-parses deps output.
Problem
codedb <root> deps <file> is inconsistent between empty and non-empty dependency lists:
- Non-empty lists print one entry per line plus a
(N files) summary.
- Empty lists print a literal
(none) entry line and no summary at all.
$ codedb ~/engram deps src/trace.zig
src/trace.zig is imported by:
src/search.zig
src/memexp.zig
src/lib.zig
src/design.zig
src/mcp.zig
src/seed.zig
(6 files)
$ codedb ~/engram deps src/main.zig
src/main.zig is imported by:
(none)
Any consumer that parses the list body (because the summary is absent in exactly this case) sees (none) as one entry unless it special-cases the sentinel string.
Real-world impact (red)
engram's feature extractor counted (none) as 1, so every zero-importer file got in-degree 1 — and on repos where 1 was the max, every candidate normalized to centrality/reach/blast = 1.0 (degenerate ties). The re-ranker weights it learned on those features were garbage; .swiftlint.yml ranked top-3 for the query gateway on a 19.7k-file repo with "centrality 1.000". Fixed on engram's side by special-casing the string, but the format invited the bug.
- Expected: empty lists are distinguishable from one-entry lists without knowing the
(none) sentinel — e.g. print (0 files) so the summary line is always present.
- Actual: empty lists print a body line
(none) and omit the summary.
Suggested fix
Print the (N files) summary unconditionally ((0 files) when empty). Keeping (none) as the body is fine for humans — the always-present summary gives machines one reliable thing to parse. Applies to all three variants (deps, deps --depends-on, deps --transitive).
Seen on codedb 0.2.5824 (macOS, warm daemon).
Found while building engram's codedb bridge, which machine-parses
depsoutput.Problem
codedb <root> deps <file>is inconsistent between empty and non-empty dependency lists:(N files)summary.(none)entry line and no summary at all.Any consumer that parses the list body (because the summary is absent in exactly this case) sees
(none)as one entry unless it special-cases the sentinel string.Real-world impact (red)
engram's feature extractor counted
(none)as 1, so every zero-importer file got in-degree 1 — and on repos where 1 was the max, every candidate normalized to centrality/reach/blast = 1.0 (degenerate ties). The re-ranker weights it learned on those features were garbage;.swiftlint.ymlranked top-3 for the querygatewayon a 19.7k-file repo with "centrality 1.000". Fixed on engram's side by special-casing the string, but the format invited the bug.(none)sentinel — e.g. print(0 files)so the summary line is always present.(none)and omit the summary.Suggested fix
Print the
(N files)summary unconditionally ((0 files)when empty). Keeping(none)as the body is fine for humans — the always-present summary gives machines one reliable thing to parse. Applies to all three variants (deps,deps --depends-on,deps --transitive).Seen on
codedb 0.2.5824(macOS, warm daemon).