Skip to content

feat(bun): lockfile-only analysis from bun.lock + fix reader defects - #680

Open
a-oren wants to merge 8 commits into
guacsec:mainfrom
a-oren:TC-7014
Open

a-oren wants to merge 8 commits into
guacsec:mainfrom
a-oren:TC-7014

Conversation

@a-oren

@a-oren a-oren commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Makes Bun dependency analysis lockfile-only: it reads bun.lock directly with no bun --version or bun install invocation and requires a pre-existing text lockfile. The tree-builder is rewritten onto the shared {rootId, nodes} graph contract (readBunGraph/parseBunEntry/readBunLock), fixing the prior reader's correctness defects:

  • Aliases report their npm-target identity (pkg:npm/is-number@…), not the alias name.

  • Nested resolutions are keyed by their parent/child install path, so conflicting versions stay distinct instead of collapsing onto the root.

  • Workspace members report their real manifest identity and dependencies (no more workspace: pseudo-version).

  • Optional branches are preserved; missing required resolutions and unsupported lockfileVersion now fail closed with actionable errors instead of being silently dropped.

  • A binary bun.lockb without a text bun.lock is rejected with a migrate diagnostic.

  • TC-7199 The bun.lockb migrate diagnostic is now reachable through match()/stackAnalysis/componentAnalysis (not only direct provider calls): the base validateLockFile matches a provider-declared binary lockfile so Bun is selected and raises the diagnostic instead of the generic "requires a lock file" error. _findLockFileDir is generalized to accept lockfile names (replacing Bun's duplicated walk) so the diagnostic honors TRUSTIFY_DA_WORKSPACE_DIR, and the suggested command matches the README.

  • TC-7069 A malformed/unreachable bun.lock packages entry (an id without @) is now skipped per-entry in _parseLockFileHashes instead of throwing and clearing the entire hash map, so provideComponent keeps valid direct-dependency integrity hashes and agrees with provideStack.

  • [TC-7200] The bun golden-SBOM and lockfile-only test suites moved into test/javascript_lockfile.test.js to reuse that file's shared SBOM_CASES, canonical() and snapshot() helpers instead of duplicating them in test/providers/javascript.test.js; the bun golden reference suite now iterates SBOM_CASES rather than an inline {method,type} list, matching CONVENTIONS.md Testing Conventions.

  • [TC-7201] Wrapped the ~23 lines added under src/ that exceeded the documented 100-column limit (CONVENTIONS.md Code Style; ESLint does not enforce it) and added DCO Signed-off-by: trailers to every commit on the branch. Formatting/compliance only, no behavior change.

Supports lockfileVersion 0/1/2, hosted/git 3-tuples, empty-registry entries, and SHA-1/SHA-512 integrity.

Reuse / design notes

  • Reuses the {rootId, nodes} contract + addGraphToSbom/graphRootDependencies and the npm/yarn-era helpers (projectManifests, validateSnapshot, validateRange, descriptor, stale, unsupported, hashes) already in javascript_lockfile.js.
  • bun.lock tuple shapes were grounded against real Bun 1.4.0 output (npm, alias, nested conflict, optional, git) before implementing.
  • Transitive peerDependencies are intentionally omitted (as the prior reader did); direct peers are still supplemented by the SBOM builder.

Tests

  • Golden-SBOM deep.equal fixtures for alias / nested / workspace / optional / lockfileVersion 0/1/2.
  • Programmatic regression tests for each fixed defect, a no-subprocess + unchanged-tree reproducer, version support, hosted/empty-registry/SHA-1 handling, malformed/absent lock, and the bun.lockb migrate diagnostic.
  • Regression test for TC-7069: a lockfile with a valid leaf@1.0.0 plus an unreachable malformed entry keeps leaf's SHA-512 hash in the component SBOM and agrees with the stack SBOM.
  • npm run lint (0 errors) and npm test (full suite + coverage) pass.

Implements TC-7014

Also implements TC-7069

🤖 Generated with Claude Code

Summary by Sourcery

Make Bun dependency analysis lockfile-only and produce validated, accurate dependency graphs from text bun.lock files.

New Features:

  • Support lockfile-only Bun dependency analysis from pre-existing text bun.lock files across lockfile versions 0, 1, and 2.
  • Add Bun workspace, alias, nested-resolution, optional-dependency, hosted/git, and integrity handling.

Bug Fixes:

  • Correct Bun package identities for aliases and workspace members, preserve conflicting nested resolutions, and fail on stale or missing required metadata instead of silently dropping dependencies.
  • Reject unsupported or malformed lockfiles, including binary bun.lockb files without a text-lockfile migration path.

Enhancements:

  • Reuse the shared JavaScript lockfile graph and validation contract so Bun analysis does not invoke Bun, install dependencies, or modify project files.

Documentation:

  • Document Bun as a supported lockfile-only ecosystem, including workspace lockfile discovery and bun.lockb migration guidance.

Tests:

  • Add regression, fixture, and complete-SBOM comparisons covering Bun graph correctness, validation failures, lockfile formats, hashes, workspaces, and no-subprocess behavior.

Chores:

  • Exclude Bun test fixtures from automated dependency updates.

@sourcery-ai

sourcery-ai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Reworks Bun dependency analysis into a lockfile-only implementation backed by the shared graph contract, with robust tuple/version/workspace resolution and actionable failure behavior, while adding broad regression and golden-SBOM coverage for the corrected reader defects.

Sequence diagram for lockfile-only Bun dependency analysis

sequenceDiagram
    participant Caller
    participant Javascript_bun
    participant Filesystem
    participant BunLockGraph
    participant SBOM

    Caller->>Javascript_bun: _buildDependencyTree(includeTransitive, opts)
    Javascript_bun->>Filesystem: _findLockFileDir(manifestDir, opts)
    alt text bun.lock found
        Javascript_bun->>BunLockGraph: readBunLock(bun.lock)
        BunLockGraph-->>Javascript_bun: parsed lock
        Javascript_bun->>BunLockGraph: readBunGraph(lockDir, manifestPath, manifest, lock)
        BunLockGraph-->>Javascript_bun: {rootId, nodes}
        Javascript_bun->>Javascript_bun: _loadHashes(lockDir)
        Javascript_bun-->>SBOM: dependency graph
    else only bun.lockb found
        Javascript_bun->>Filesystem: #binaryLockFileDir(manifestDir)
        Filesystem-->>Javascript_bun: bun.lockb directory
        Javascript_bun-->>Caller: migrate diagnostic
    else no lockfile
        Javascript_bun-->>Caller: requires bun.lock error
    end
Loading

Flow diagram for Bun lockfile graph resolution

flowchart TD
    A[Read bun.lock as JSONC] --> B{lockfileVersion 0, 1, or 2?}
    B -- No --> E[Fail with unsupported-version error]
    B -- Yes --> C[Validate workspace manifests]
    C --> D[Resolve dependency edge]
    D --> F{Workspace pointer?}
    F -- Yes --> G[Redirect to ws member node]
    F -- No --> H[Resolve parent/child package key]
    H --> I{Required resolution missing?}
    I -- Yes --> J[Fail with stale-resolution error]
    I -- No --> K[Create package node with identity and hashes]
    G --> L[Visit dependencies]
    K --> L
    L --> M{Optional resolution missing?}
    M -- Yes --> N[Preserve graph without optional edge]
    M -- No --> D
Loading

File-Level Changes

Change Details Files
Converted Bun analysis to consume only a pre-existing text lockfile and never invoke Bun or mutate the project.
  • Bypassed executable/version setup and lockfile generation.
  • Added explicit missing-lockfile and binary bun.lockb migration diagnostics.
  • Loaded hashes from the existing lockfile without altering project files.
src/providers/javascript_bun.js
test/providers/javascript.test.js
Implemented a shared graph-based Bun lockfile reader supporting Bun lockfile versions and tuple formats.
  • Added JSONC parsing with validation for lockfile versions 0, 1, and 2.
  • Parsed npm, alias, hosted/git, empty-registry, workspace, and integrity tuple shapes.
  • Built the shared {rootId, nodes} graph using existing manifest, snapshot, range, and hash helpers.
src/providers/javascript_lockfile.js
Corrected dependency graph identity and resolution behavior for Bun-specific edge cases.
  • Reported aliases using their resolved npm target identity.
  • Resolved nested dependencies by install path to preserve conflicting versions.
  • Mapped workspace members to on-disk manifest identity and dependencies.
  • Preserved available optional branches while failing closed for missing required resolutions and unsupported lockfile versions.
src/providers/javascript_lockfile.js
src/providers/javascript_bun.js
Added comprehensive Bun regression, golden-SBOM, and fixture coverage.
  • Added deep-equality stack/component fixtures for aliases, nested conflicts, workspaces, optional dependencies, and lockfile versions 0–2.
  • Added tests for no subprocesses, unchanged trees, malformed or absent locks, binary lock migration, hosted entries, empty registries, and SHA-1/SHA-512 hashes.
  • Excluded Bun fixture directories from Dependabot updates.
test/providers/javascript.test.js
test/providers/tst_manifests/bun/alias/bun.lock
test/providers/tst_manifests/bun/alias/package.json
test/providers/tst_manifests/bun/alias/expected_component_sbom.json
test/providers/tst_manifests/bun/alias/expected_stack_sbom.json
test/providers/tst_manifests/bun/lockfile_v0/bun.lock
test/providers/tst_manifests/bun/lockfile_v0/package.json
test/providers/tst_manifests/bun/lockfile_v0/expected_component_sbom.json
test/providers/tst_manifests/bun/lockfile_v0/expected_stack_sbom.json
test/providers/tst_manifests/bun/lockfile_v1/bun.lock
test/providers/tst_manifests/bun/lockfile_v1/package.json
test/providers/tst_manifests/bun/lockfile_v1/expected_component_sbom.json
test/providers/tst_manifests/bun/lockfile_v1/expected_stack_sbom.json
test/providers/tst_manifests/bun/lockfile_v2/bun.lock
test/providers/tst_manifests/bun/lockfile_v2/package.json
test/providers/tst_manifests/bun/lockfile_v2/expected_component_sbom.json
test/providers/tst_manifests/bun/lockfile_v2/expected_stack_sbom.json
test/providers/tst_manifests/bun/nested/bun.lock
test/providers/tst_manifests/bun/nested/package.json
test/providers/tst_manifests/bun/nested/expected_component_sbom.json
test/providers/tst_manifests/bun/nested/expected_stack_sbom.json
test/providers/tst_manifests/bun/optional/bun.lock
test/providers/tst_manifests/bun/optional/package.json
test/providers/tst_manifests/bun/optional/expected_component_sbom.json
test/providers/tst_manifests/bun/optional/expected_stack_sbom.json
test/providers/tst_manifests/bun/workspace/bun.lock
test/providers/tst_manifests/bun/workspace/package.json
test/providers/tst_manifests/bun/workspace/expected_component_sbom.json
test/providers/tst_manifests/bun/workspace/expected_stack_sbom.json
test/providers/tst_manifests/bun/workspace/packages/member/package.json
.github/dependabot.yml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@codecov-commenter

codecov-commenter commented Oct 21, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.99700% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.38%. Comparing base (235595c) to head (4bd7416).

Files with missing lines Patch % Lines
src/providers/javascript_lockfile.js 96.86% 8 Missing ⚠️
src/providers/javascript_bun.js 96.42% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #680      +/-   ##
==========================================
- Coverage   92.02%   91.38%   -0.64%     
==========================================
  Files          43       43              
  Lines       11284    11494     +210     
  Branches     2258     2313      +55     
==========================================
+ Hits        10384    10504     +120     
- Misses        900      990      +90     
Flag Coverage Δ
unit-tests 91.38% <96.99%> (-0.64%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/providers/base_javascript.js 76.34% <100.00%> (-14.58%) ⬇️
src/providers/javascript_bun.js 94.00% <96.42%> (+5.04%) ⬆️
src/providers/javascript_lockfile.js 97.12% <96.86%> (+0.57%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/providers/javascript_bun.js" line_range="48" />
<code_context>
-			const name = id.slice(0, at);
-			const version = id.slice(at + 1);
-			const hash = sriToHash(entry[3]);
+			const { name, version, integrity } = parseBunEntry(entry);
+			const hash = integrity ? sriToHash(integrity) : null;
 			if (name && version && hash) {
</code_context>
<issue_to_address>
**Valid dependency hashes disappear**

When a lockfile contains a package entry with a string descriptor that makes `parseBunEntry` throw, even though that package is not reachable from the analyzed manifest, `parseBunEntry` throws while `_parseLockFileHashes` scans a malformed, otherwise-unreachable package entry. `Base_javascript._loadHashes` catches the error and replaces the entire hash map with an empty one, so `provideComponent` omits hashes even for valid direct dependencies.

Handle malformed hash entries individually, or validate the entire lockfile explicitly before hash extraction instead of silently clearing all hashes.
</issue_to_address>

Sourcery assessment

Approval pending. 1 finding to address first.

Blocking findings: src/providers/javascript_bun.js:48


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread src/providers/javascript_bun.js Outdated
@a-oren

a-oren commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

[sdlc-workflow/verify-pr] Re: @sourcery-ai review — Classified as code change request — sub-task TC-7069 created to address this feedback. This is the same "valid dependency hashes disappear" finding as the inline comment at src/providers/javascript_bun.js:48; one sub-task covers both.

@a-oren

a-oren commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Verification Report for TC-7014 (commit c53efa0)

Check Result Details
Review Feedback WARN 1 code change request (Sourcery "valid dependency hashes disappear", inline javascript_bun.js:48 + review body). Sub-task TC-7069 created and linked (Blocks).
Root-Cause Investigation DONE Skill gap in implement-task phase. Root-cause task TC-7070 created (catch-all blast-radius / per-item isolation analysis step).
Scope Containment WARN All modify-files + all fixture scenarios present. Spec-listed bun.lockb-only fixture dir realized as an inline temp-dir fixture instead of a committed dir — behavior + regression test fully present, no coverage gap.
Diff Size PASS 1320/-117 across 33 files, proportionate (most additions are golden-SBOM JSON fixtures for 7 scenarios).
Commit Traceability PASS Single commit references Implements TC-7014.
Sensitive Patterns PASS No secrets/credentials in added lines; only dependency integrity hashes (exempt).
CI Status PASS All 6 checks green (lint/test Node 22 & 24, Sourcery, PR title, commit messages, dependabot config).
Acceptance Criteria WARN 6 of 6 named criteria met and 130 bun tests pass, but the confirmed silent-omission defect (component SBOM drops all hashes on one malformed/unreachable entry) undercuts AC #4's "no silent omission" intent. Tracked in TC-7069.
Test Quality WARN Repetitive Test Detection PASS; Test Documentation WARN (new tests use /// line comments vs the project's /** */ JSDoc form; parameterized reference-comparison test lacks a doc comment — minor/informational); Eval Quality N/A (no eval reviews).
Test Change Classification ADDITIVE Two new bun suites (~90 parameterized tests, 100+ assertions); no tests/assertions removed or relaxed; subprocess mock swapped for the real lockfile-only provider.
Verification Commands PASS npm run lint 0 errors (18 pre-existing warnings); bun/lockfile suite 130 passing.

Overall: WARN

The PR is functionally solid — CI green, all acceptance criteria implemented, lint clean, 130 bun tests passing, additive test coverage, no secrets. One confirmed defect needs a follow-up before merge: a single malformed or unreachable bun.lock packages entry makes the component SBOM drop integrity hashes for all valid direct dependencies (the stack SBOM is unaffected, so the two disagree). This is tracked in sub-task TC-7069, with systemic prevention in root-cause task TC-7070. Scope and test-documentation items are informational. No code was modified and the PR was not merged — a human reviewer decides whether to merge now or after TC-7069.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.10.

@Strum355 Strum355 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some statements mainly on the test manifests:

  1. Can you double check whether the lockfile_v0 is actually a v0 lockfile? From what I saw, its actually a v1/v2 but just with the version set to 0. Im wondering whether Claude generated these manifests by hand instead of using bun
  2. Im not sure we should really be adding the v0, v1 & v2 test fixtures. The formats are, for the most part, pretty identical, and these 3 tests themselves dont really add anything of use to our test suite. Id rather avoid adding a mountain of tautological tests when we can be re-using existing test manifests where its reasonable enough to do so (or not adding extra tests for something at all)

@a-oren
a-oren requested a review from Strum355 October 25, 2026 08:43
@a-oren
a-oren force-pushed the TC-7014 branch 2 times, most recently from 417b537 to 3e48976 Compare October 25, 2026 08:58
@a-oren
a-oren requested a review from ruromero October 26, 2026 07:03

@ruromero ruromero left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lockfile-only rewrite looks solid overall. I checked the stale-lockfile detection against scratch projects: a changed range, a dependency added only to package.json, and a locked version outside the declared range all fail with "Lockfile is out of date", and an in-sync project produces the SBOM. Findings below, most important first; details are in the inline comments.

1. The bun.lockb migrate error is not reachable through the public API

match() (src/provider.js:74) picks the provider through validateLockFile → _findLockFileDir, which only looks for bun.lock. For a project with only bun.lockb, no provider is selected and the user gets the generic package.json requires a lock file. Use your preferred package manager to generate the lock file. The new diagnostic only fires when the Bun provider is called directly, which is what the test does. All public entry points go through match() (src/index.js:185, :200, :306).

Reproduced on this branch with a directory containing only package.json + bun.lockb:

match(path.join(dir, 'package.json'), availableProviders)
// -> package.json requires a lock file. Use your preferred package manager to generate the lock file.
new Javascript_bun().provideStack(path.join(dir, 'package.json'))
// -> Bun analysis found a binary 'bun.lockb' but no text 'bun.lock'. Migrate it with ...

So TC-7014's "Binary bun.lockb is detected and rejected with an actionable 'migrate to bun.lock' error" isn't met for real callers.

2. CONTRIBUTING.md / CONVENTIONS.md gaps

  • DCO sign-off missing. None of the 5 commits has a Signed-off-by: trailer. CONTRIBUTING.md: "Commits must be signed-off"; CONVENTIONS.md: "DCO (Developer Certificate of Origin) required". git rebase --signoff upstream/main fixes it.
  • Max line length 100. 24 added lines under src/ exceed it (tabs counted as 4), e.g. javascript_lockfile.js:826, :919 and the error string at javascript_bun.js:82. ESLint doesn't enforce this, so it's easy to miss.
  • SBOM_CASES pattern. CONVENTIONS.md: "Tests must use the SBOM_CASES pattern". The Bun golden-file suite builds its own inline list instead.

3. Other implementation issues

  • The bun.lockb error suggests bun install --save-text-lockfile, but the README says bun install --save-text-lockfile --frozen-lockfile --lockfile-only. The error's version installs node_modules and can change resolved versions; the two should match, ideally on the README command.
  • #binaryLockFileDir ignores TRUSTIFY_DA_WORKSPACE_DIR, unlike _findLockFileDir. With that option pointing at a directory that has only bun.lockb, even a direct provider call returns the generic "Bun analysis requires a lockfile".

4. Duplication

  • canonical() / snapshot() in test/providers/javascript.test.js are verbatim copies of the helpers in test/javascript_lockfile.test.js.
  • The Bun lockfile tests live in test/providers/javascript.test.js, while npm/pnpm/yarn lockfile coverage runs through MANAGERS in test/javascript_lockfile.test.js. Adding Bun to that suite would also cover SBOM_CASES and remove the copied helpers.
  • readBunGraph repeats the "resolve child, skip if absent, record, push" block three times (and mirrors readPnpmGraph); the path.relative(...).split(path.sep).join('/') || '.' expression now appears five times in the file.
  • #binaryLockFileDir re-implements the directory walk in _findLockFileDir.

Comment thread src/providers/javascript_bun.js Outdated
const lockDir = this._findLockFileDir(manifestDir, opts);
if (!lockDir) {
if (this.#binaryLockFileDir(manifestDir)) {
throw new Error("Bun analysis found a binary 'bun.lockb' but no text 'bun.lock'. Migrate it with 'bun install --save-text-lockfile' (Bun >= 1.2) before scanning.");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This branch is only reachable when the Bun provider is called directly. Through match() (used by every public entry point in src/index.js), a bun.lockb-only project never selects the Bun provider, because validateLockFile → _findLockFileDir only looks for bun.lock. The user gets the generic "package.json requires a lock file" message instead of this one.

One option is to detect bun.lockb in the match/validateLockFile path and raise this diagnostic there.

Also, the suggested command differs from the README (bun install --save-text-lockfile --frozen-lockfile --lockfile-only). Without --frozen-lockfile --lockfile-only this installs node_modules and may re-resolve versions. This line is also over the 100-char limit from CONVENTIONS.md.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[sdlc-workflow/verify-pr] Classified as code change request — sub-task TC-7199 created to address this feedback (bun.lockb diagnostic reachable via match(), honor TRUSTIFY_DA_WORKSPACE_DIR, align the migrate command with the README, wrap the >100-char line).

Comment thread src/providers/javascript_bun.js Outdated
* @returns {string|null} The directory containing bun.lockb, or null
* @private
*/
#binaryLockFileDir(manifestDir) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplicates the walk in Base_javascript._findLockFileDir but skips its TRUSTIFY_DA_WORKSPACE_DIR branch. With that option pointing at a directory that only has bun.lockb, the user gets "Bun analysis requires a lockfile" rather than the migrate diagnostic. Could _findLockFileDir take the file name(s) to look for, so both lookups share one walk and honour the option the same way?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[sdlc-workflow/verify-pr] Classified as code change request — sub-task TC-7199 created. The #binaryLockFileDir walk and its missing TRUSTIFY_DA_WORKSPACE_DIR handling are covered there (sharing one walk with _findLockFileDir is the suggested approach).

Comment thread src/providers/javascript_lockfile.js Outdated
const devSpec = local.devDependencies[name];
// Bun may lock either range when it retains both declarations for the same name.
const effective = typeof devSpec === 'string' && semver.validRange(spec) && semver.validRange(devSpec) ? `${spec} || ${devSpec}` : spec;
const cid = childId(local.packageKey, name, effective, local.file, Object.hasOwn(optionalDeps, name));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "resolve child → skip if absent → node.dependencies.set → children.push" block appears three times in readBunGraph (here, :940, :947) and mirrors readPnpmGraph (:731-734). A small addEdge(node, children, name, cid) helper would remove the repetition. The line is also over 100 chars.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[sdlc-workflow/verify-pr] Classified as code change request (upgraded from suggestion) — the >100-char portion matches project convention: CONVENTIONS.md §Code Style "Max line length: 100" (confirmed >100 with tabs=4 on :912/:918/:919/:926). Sub-task TC-7201 created for the line-wrapping. The optional addEdge() DRY refactor remains a non-blocking suggestion.

}
const required = dependencyMap(parsed.info, 'dependencies', `${file} for ${id}`);
const optionalDeps = dependencyMap(parsed.info, 'optionalDependencies', `${file} for ${id}`);
// ponytail: transitive peerDependencies are omitted (as the prior

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ponytail: isn't a tag used anywhere else in the repo. Please use plain wording or a TODO. Since TC-7014 is about avoiding silent omissions, it may also be worth tracking transitive peer resolution in an issue rather than only in this comment.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[sdlc-workflow/verify-pr] Classified as nit — minor wording of an in-code comment; does not affect correctness. The suggestion to track transitive peer resolution in an issue is noted. No sub-task created.

Comment thread test/providers/javascript.test.js Outdated
const BUN_SRI_HEX = Buffer.from(BUN_SRI.slice('sha512-'.length), 'base64').toString('hex');

/** Sorts components and dependency edges so two SBOMs compare order-independently. */
function canonical(sbom) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

canonical() and snapshot() are verbatim copies of the helpers in test/javascript_lockfile.test.js (:21, :29). If the Bun lockfile cases moved into that suite (alongside MANAGERS), these copies could go.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[sdlc-workflow/verify-pr] Classified as suggestion — helper duplication is not covered by a documented convention, so no standalone sub-task. It is noted as related cleanup in TC-7200 (removing the copies naturally follows if the Bun cases move into the SBOM_CASES/MANAGERS suite). No sub-task created.

Comment thread test/providers/javascript.test.js Outdated
});

/// Verifies a binary bun.lockb (without a text bun.lock) yields an actionable migrate diagnostic.
test('rejects a binary bun.lockb with a migrate-to-bun.lock diagnostic', () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This passes because it calls the Bun provider directly. Going through match() / stackAnalysis with the same fixture returns the generic "package.json requires a lock file" error, so the test doesn't cover the path users hit. Please exercise it through match() once the diagnostic is raised there.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[sdlc-workflow/verify-pr] Classified as code change request — sub-task TC-7199 created. It requires the bun.lockb diagnostic to be exercised through match()/stackAnalysis (the path real users hit), not only a direct provider call.

Comment thread test/providers/javascript.test.js Outdated
const base = 'test/providers/tst_manifests/bun';
const fixtures = ['alias', 'nested', 'optional', 'workspace'];
for (const fixture of fixtures) {
for (const { method, type } of [{ method: 'provideStack', type: 'stack' }, { method: 'provideComponent', type: 'component' }]) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONVENTIONS.md asks golden-file tests to use the SBOM_CASES pattern. This re-declares the stack/component list inline. Reusing SBOM_CASES (or adding Bun to the existing reference-comparison suite in test/javascript_lockfile.test.js) would keep it consistent.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[sdlc-workflow/verify-pr] Classified as code change request (upgraded from suggestion) — this matches project convention: CONVENTIONS.md §Testing Conventions requires "Tests must use the SBOM_CASES pattern to do a full deep.equal comparison", and SBOM_CASES is used in 10+ places across the suite. Sub-task TC-7200 created to address this feedback.

@a-oren

a-oren commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

[sdlc-workflow/verify-pr] Re: @Strum355 review — two points, classified separately:

  • Question — "is lockfile_v0 actually a v0 lockfile?": this asks for verification rather than a code change. The versioned v0/v1/v2 fixtures were since removed in commit 3e489769 as tautological, so the concern is resolved; lockfileVersion 0/1/2 support remains in code and is covered by the parameterized supports lockfileVersion 0/1/2 / rejects unsupported version unit tests.
  • Suggestion — "avoid adding tautological v0/v1/v2 fixtures": addressed — those fixtures were dropped in commit 3e489769.
    No sub-task created.

@a-oren

a-oren commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor Author

[sdlc-workflow/verify-pr] Re: @ruromero review — thanks for the thorough reproduction. Classified as code change request (multiple items), tracked across sub-tasks:

  • §1 bun.lockb migrate error not reachable through match() (+ TRUSTIFY_DA_WORKSPACE_DIR, README command mismatch) → TC-7199. Confirmed during verification: a bun.lockb-only project returns the generic "requires a lock file" error via match(), so AC chore: added component analysis #6 is not met for real callers.
  • §2 DCO sign-off missing on all commits + 24 added src/ lines exceed the 100-char limit → TC-7201.
  • §2/§4 Bun golden suite should use the SBOM_CASES pattern; duplicated canonical()/snapshot() helpers → TC-7200.
  • §4 remaining DRY items (addEdge() helper, repeated path.relative(...) expression) are non-blocking suggestions; no separate sub-task.
    Your confirmation that stale-lockfile detection works as intended is noted — no action needed there.

@a-oren

a-oren commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor Author

Verification Report for TC-7014 (commit 72a7cf7)

Check Result Details
Review Feedback WARN 9 new review items since the last run (commit c53efa0) classified. 5 code change requests (incl. 2 convention upgrades) → sub-tasks TC-7199 (AC#6 reachability), TC-7200 (SBOM_CASES), TC-7201 (line-length + DCO). Prior TC-7069 fix (commit 72a7cf7) verified correct.
Root-Cause Investigation DONE 2 implement-task skill gaps → TC-7202 (verify AC reachability via public entry point + test that path) and TC-7203 (read/enforce CONVENTIONS.md before completion). Neither overlaps TC-7070.
Scope Containment WARN All task source/config/test files + the alias/nested/workspace/optional fixtures present. README.md out-of-scope but a reasonable companion doc change; planned lockfileVersion 0/1/2 fixtures removed in 3e489769 as tautological (reviewer-driven, version support still code-tested); bun.lockb-only fixture realized inline. No coverage gap.
Diff Size PASS +1543/-146 across 22 files; bulk is golden-SBOM JSON fixtures + the test file. Proportionate to a provider rewrite.
Commit Traceability WARN Only 1 of 5 commits references TC-7014; others carry no reference (one references the spun-off TC-7069). DCO Signed-off-by missing on all commits (tracked in TC-7201).
Sensitive Patterns PASS No secrets/credentials in added lines; only dependency integrity hashes (exempt).
CI Status PASS All 5 required checks green (lint/test Node 22 & 24, PR title, commit messages, dependabot config). Sourcery skipped (not a failure).
Acceptance Criteria FAIL 5 of 6 met. AC #6 FAIL: the binary bun.lockb migrate diagnostic is only reachable on a direct provider call — every public entry point routes through match(), which selects providers via _findLockFileDir/_lockFileNames() = ['bun.lock'], so a bun.lockb-only project gets the generic "requires a lock file" error. Tracked in TC-7199.
Test Quality WARN Repetitive Test Detection PASS (new tests heavily parameterized); Test Documentation WARN (many new test() functions lack a doc comment; some use /// vs the project's /** */); Eval Quality N/A (no eval reviews).
Test Change Classification ADDITIVE +36 test functions, +61 assertions, 2 new suites; no tests/assertions removed or relaxed; the one pre-existing edit narrows (not broadens) the bun mock to prove no subprocess runs.
Verification Commands PASS npm run lint 0 errors (18 pre-existing warnings in unrelated files); npx mocha test/providers/javascript.test.js 170 passing, 0 failing.

Overall: FAIL

AC #6 is not satisfied for real callers: the actionable bun.lockb → bun.lock migrate diagnostic never fires through the public match()/stackAnalysis/componentAnalysis path — a bun.lockb-only project instead gets the generic "requires a lock file" message, and the PR's own test passed only by calling the provider directly and bypassing match(). Tracked in TC-7199, with systemic prevention in root-cause task TC-7202. Convention gaps (SBOM_CASES, >100-char lines, DCO sign-off) are tracked in TC-7200/TC-7201 with prevention in TC-7203. The prior TC-7069 hash-dropping defect fix (commit 72a7cf7) is verified correct, and AC #1–#5 all hold. No code was modified and the PR was not merged — a human reviewer decides whether to merge after the AC #6 fix lands.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.10.

a-oren and others added 8 commits October 26, 2026 15:46
Make Bun dependency analysis read bun.lock directly, with no `bun --version`
or `bun install` invocation, and require a pre-existing text lockfile. Rewrite
the tree-builder into the shared `{rootId, nodes}` graph contract
(`readBunGraph`/`parseBunEntry`/`readBunLock` in javascript_lockfile.js) and
fix the prior reader's correctness defects:

- aliases report their npm-target identity instead of the alias name
- nested resolutions are keyed by their `parent/child` install path, so
  conflicting versions stay distinct instead of collapsing onto the root
- workspace members report their real manifest identity and dependencies
- optional branches are preserved; missing required resolutions and
  unsupported lockfileVersions now fail closed instead of being dropped

Reject a binary `bun.lockb` without a text `bun.lock` with an actionable
migrate diagnostic. Supports lockfileVersion 0, 1 and 2, hosted/git 3-tuples,
empty-registry entries, and SHA-1/SHA-512 integrity. Adds golden-SBOM and
regression fixtures plus their dependabot suppression entries.

Implements TC-7014

Assisted-by: Claude Code
Signed-off-by: Adva Oren <aoren@redhat.com>
Signed-off-by: Adva Oren <aoren@redhat.com>
Signed-off-by: Adva Oren <aoren@redhat.com>
The lockfile_v0/v1/v2 fixtures were byte-identical except the
lockfileVersion field (and the v0 one was not a genuine v0 lockfile,
just the v1/v2 shape with the number set to 0). The version gate is
already covered by the inline supports/rejects lockfileVersion unit
tests, so these full-SBOM comparisons added no coverage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Adva Oren <aoren@redhat.com>
_parseLockFileHashes iterated every bun.lock packages entry and let
parseBunEntry throw on an id without '@'. Base_javascript._loadHashes
caught that single throw and cleared the whole hash map, so
provideComponent omitted integrity hashes even for valid direct
dependencies while provideStack (which only parses reachable entries)
kept them. Skip the malformed/unreachable entry per-entry so valid
hashes survive and both SBOMs agree.

Implements TC-7069

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Assisted-by: Claude Code
Signed-off-by: Adva Oren <aoren@redhat.com>
A bun.lockb-only project failed match() with the generic "requires a
lock file" error because Bun only advertised bun.lock, so the migrate
diagnostic was reachable only on direct provider calls. Let the base
validateLockFile also match a provider-declared binary lockfile and have
Bun declare bun.lockb, so match()/stackAnalysis/componentAnalysis select
Bun and raise the actionable diagnostic.

Generalize _findLockFileDir to accept lockfile names, replacing Bun's
duplicated #binaryLockFileDir walk so the diagnostic honors
TRUSTIFY_DA_WORKSPACE_DIR. Align the suggested command with the README.

Implements TC-7199

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Assisted-by: Claude Code
Signed-off-by: Adva Oren <aoren@redhat.com>
Move the bun lockfile-only and golden-SBOM suites into
test/javascript_lockfile.test.js so they reuse that file's shared
SBOM_CASES, canonical() and snapshot() helpers instead of duplicating
them in test/providers/javascript.test.js. The bun golden reference suite
now iterates SBOM_CASES rather than an inline {method,type} list, matching
CONVENTIONS.md Testing Conventions and the other provider suites.

Implements TC-7200

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Assisted-by: Claude Code
Signed-off-by: Adva Oren <aoren@redhat.com>
Wrap lines added under src/ that exceeded the documented 100-column limit
(CONVENTIONS.md Code Style). Pure formatting plus semantics-preserving
helper extractions; no behavior change.

Implements TC-7201

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Assisted-by: Claude Code
Signed-off-by: Adva Oren <aoren@redhat.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants