feat: adopt bomly-sdk v0.7.0 and emit per-project-root evidence - #1
Merged
Conversation
Migration and phase 2.8 in one pass, so this repo is touched once. Migration: sdk.Dependency becomes sdk.DependencyNode, Graph.Nodes() becomes DependencyNodes() since an analyzer walks dependency nodes, a node's ID is its canonical package URL so .ID becomes .NodeID(), and PURL is a method on the node now. Fixtures route through the testkit constructors, because identity is minted there and the fields holding it are unexported -- a hand-built literal has no node ID at all. Go-ecosystem fixtures gained a namespace: the golang purl type requires one, which purlkit's type profiles enforce. Phase 2.8: reachability is per-project-root evidence. The analyzer already loops per project root; what it did with the second one was skip it, which is wrong in the unsafe direction -- one project can leave a package unimported while another imports it, and the first answer stood. Each root now contributes a ReachabilityEvidence carrying its root and the occurrence node it is attributable to, and the annotation is DeriveReachability over all of them: reachable anywhere wins, unreachable requires every root to agree, and a root that could not be analyzed contributes unknown evidence so the pair does not read as unreachable. The summary rule lives in one helper rather than at each call site, which is how the first-root-wins behaviour got there. Depends on bomly-sdk#31; verified locally through a go.work overlay. One mutation verified: restoring the skip reproduces the discarded root.
The migration was developed against the release candidate through a go.work overlay; this pins the published tag. v0.8.0 rather than v0.7.1 because the SDK fixes added exported API, which is a minor bump under semver -- gorelease named the version. Full suite green under -race against the real tag, with no overlay.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Migration and phase 2.8 in one pass, so this repo is touched once rather than twice.
Migration
sdk.Dependency→sdk.DependencyNode;Graph.Nodes()→DependencyNodes()(an analyzer walks dependency nodes, not every kind);.ID→.NodeID(), since a node's ID is its canonical package URL under ADR-0041;PURLis a method on the node now.Fixtures route through the
testkitconstructors — identity is minted there and the fields holding it are unexported, so a hand-built literal has no node ID at all. Go-ecosystem fixtures gained a namespace: thegolangpurl type requires one, which purlkit's type profiles now enforce.Phase 2.8: per-project-root evidence
The analyzer already loops per project root. What it did with the second one was skip it — wrong in the unsafe direction, since one project can leave a package unimported while another imports it, and the first answer stood.
Each root now contributes a
ReachabilityEvidencecarrying its root and the occurrence node it's attributable to. The annotation isDeriveReachabilityover all of them: reachable anywhere wins; unreachable requires every root to agree; and a root that couldn't be analyzed contributes unknown evidence, so the pair doesn't read as unreachable.The summary rule lives in one helper rather than at each call site — writing it per site is how the first-root-wins behaviour got there.
Verification
One mutation: restoring the skip reproduces the discarded root. Two regression tests pin the multi-root case and the unanalyzed-root safety case.
go vet,gofmt, full suite — clean.🤖 Generated with Claude Code