Since #136 brief emits both the manifest row and the lockfile row for a direct dependency. For lockfile formats that record which packages are direct (Gemfile.lock DEPENDENCIES, package-lock.json top-level dependencies) both rows have direct: true. For formats that do not (Cargo.lock, Pipfile.lock), the lockfile row has direct: false:
$ brief --json https://github.com/ijl/orjson | jq -c '.dependencies[]|select(.name=="pyo3-ffi")'
{"name":"pyo3-ffi","version":"0.28","purl":"pkg:cargo/pyo3-ffi","scope":"runtime","direct":true}
{"name":"pyo3-ffi","version":"0.28.1","purl":"pkg:cargo/pyo3-ffi@0.28.1","scope":"runtime","direct":false}
manifests/internal/cargo/cargo.go sets Direct: false on every [[package]]; manifests/internal/pypi/pypi.go:224 does the same for Pipfile.lock. Neither manifests nor detect.go merges the two.
git-pkgs/git-pkgs/cmd/licenses.go resolvedLicenseVersions already does this inline: group by manifest directory, prefer dep.Direct && !existing.Direct, pair the manifest constraint with the lockfile's resolved version. git-pkgs/resolve/parsers/cargo.go avoids it by parsing cargo metadata, which distinguishes.
Doing the same merge in detect.go where it assembles dependencies[] (or as a manifests helper both callers use) would give one row per (name, ecosystem, scope, manifest-dir) with direct = any(direct) and version = resolved. Emitting both rows is still useful when a caller wants the constraint string, so the merged row could carry both ("constraint": "0.28", "version": "0.28.1") rather than dropping one.
Since #136 brief emits both the manifest row and the lockfile row for a direct dependency. For lockfile formats that record which packages are direct (Gemfile.lock
DEPENDENCIES, package-lock.json top-leveldependencies) both rows havedirect: true. For formats that do not (Cargo.lock, Pipfile.lock), the lockfile row hasdirect: false:manifests/internal/cargo/cargo.gosetsDirect: falseon every[[package]];manifests/internal/pypi/pypi.go:224does the same for Pipfile.lock. Neither manifests nordetect.gomerges the two.git-pkgs/git-pkgs/cmd/licenses.goresolvedLicenseVersionsalready does this inline: group by manifest directory, preferdep.Direct && !existing.Direct, pair the manifest constraint with the lockfile's resolved version.git-pkgs/resolve/parsers/cargo.goavoids it by parsingcargo metadata, which distinguishes.Doing the same merge in
detect.gowhere it assemblesdependencies[](or as a manifests helper both callers use) would give one row per (name, ecosystem, scope, manifest-dir) withdirect = any(direct)andversion = resolved. Emitting both rows is still useful when a caller wants the constraint string, so the merged row could carry both ("constraint": "0.28", "version": "0.28.1") rather than dropping one.