Skip to content

feat: add dependency-walked discovery and source-aware package reporting#112

Merged
LadyBluenotes merged 18 commits intomainfrom
discovery-engine
Apr 13, 2026
Merged

feat: add dependency-walked discovery and source-aware package reporting#112
LadyBluenotes merged 18 commits intomainfrom
discovery-engine

Conversation

@LadyBluenotes
Copy link
Copy Markdown
Member

@LadyBluenotes LadyBluenotes commented Apr 6, 2026

Summary

  • refactor intent package discovery into dedicated registrar and dependency-walker helpers so project, workspace, and transitive dependencies are scanned more consistently
  • track local vs global package sources, surface that in intent list, and keep intent stale scoped to local/workspace packages with correct empty JSON output
  • add CLI and scanner coverage for global-package inclusion, local-over-global precedence, conflict reporting, and updated stale behavior

Notes

  • intent list now intentionally includes accessible global packages and shows a SOURCE column
  • intent stale does not include global packages by default; from a package it checks that package, and from a monorepo root it checks workspace packages with skills

Summary by CodeRabbit

  • New Features

    • intent list adds SOURCE info and can include accessible global packages while preferring local installs; global inclusion is opt-in.
    • intent stale and related commands now operate on the current project/workspace by default (globals excluded).
  • Documentation

    • CLI docs clarified for list, stale, and install about project/workspace scope and optional global scanning.
  • Tests

    • Tests added/updated for local vs global discovery and JSON output including package source.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a26c01a8-9916-47ad-975c-b00932a97b3e

📥 Commits

Reviewing files that changed from the base of the PR and between 4aa03c0 and ea07beb.

📒 Files selected for processing (4)
  • .changeset/discovery-engine.md
  • packages/intent/src/discovery/register.ts
  • packages/intent/src/discovery/walk.ts
  • packages/intent/tests/cli.test.ts

📝 Walkthrough

Walkthrough

Refactors intent discovery by extracting a package registrar and dependency walker, adds ScanOptions.includeGlobal and package source ('local'|'global'), updates CLI to opt-in global scans for list, narrows stale to project/workspace, and updates docs and tests accordingly.

Changes

Cohort / File(s) Summary
Documentation
docs/cli/intent-install.md, docs/cli/intent-list.md, docs/cli/intent-stale.md, docs/getting-started/quick-start-maintainers.md, docs/overview.md
Clarified discovery scope (project/workspace default; list can include global when explicitly scanned), documented SOURCE column and source JSON field, and clarified monorepo/context behavior.
Types & Public API
packages/intent/src/types.ts, packages/intent/src/index.ts
Added ScanOptions (includeGlobal?: boolean) and added `source: 'local'
Scanner Core
packages/intent/src/scanner.ts, packages/intent/src/cli-support.ts
Changed scanForIntents/scanIntentsOrFail signatures to accept ScanOptions, replaced inline traversal with registrar/walker factories, and made global scanning opt-in via includeGlobal.
Discovery: Registrar & Walker
packages/intent/src/discovery/register.ts, packages/intent/src/discovery/walk.ts, packages/intent/src/discovery/index.ts
Added createPackageRegistrar (registration, depth/version selection, path rewriting) and createDependencyWalker (walkProjectDeps, walkWorkspacePackages, walkKnownPackages) plus re-exports.
CLI & Commands
packages/intent/src/cli.ts, packages/intent/src/commands/list.ts, packages/intent/src/commands/stale.ts
list now invokes scan with { includeGlobal: true }; table output adds SOURCE column; dynamic import moved out of JSON path; stale JSON/empty-result control flow adjusted; help text/docs updated.
Tests
packages/intent/tests/cli.test.ts, packages/intent/tests/scanner.test.ts
Added/restored env handling for INTENT_GLOBAL_NODE_MODULES, expanded tests asserting source values, tested global inclusion when { includeGlobal: true } and exclusion otherwise, and precedence of local over global.
Changeset
.changeset/discovery-engine.md
Describes release, behavioral changes to discovery, and new includeGlobal control.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI
    participant Scanner as scanForIntents()
    participant Registrar as PackageRegistrar
    participant Walker as DependencyWalker
    participant FS as FileSystem

    CLI->>Scanner: scanForIntents(root, { includeGlobal: true })
    Scanner->>Registrar: createPackageRegistrar(...)
    Scanner->>Walker: createDependencyWalker(...)

    alt includeGlobal true
        Scanner->>Registrar: scanTarget(nodeModules.global, 'global')
        Registrar->>FS: readdir global/node_modules
        FS-->>Registrar: package dirs
        Registrar->>FS: read package.json / skills/
        Registrar-->>Scanner: register IntentPackage(source='global')
    end

    Scanner->>Walker: walkProjectDeps()
    Walker->>FS: read project package.json
    FS-->>Walker: package.json
    Walker->>Walker: resolve deps -> dep dirs
    Walker->>Registrar: tryRegister(depDir, depName)
    Registrar->>FS: read package.json / skills/
    Registrar-->>Scanner: register IntentPackage(source='local')

    alt workspace present
        Scanner->>Walker: walkWorkspacePackages()
        Walker->>FS: discover workspace package dirs
        Walker->>Registrar: tryRegister per workspace package
        Registrar-->>Scanner: register/replace by depth & version
    end

    Scanner-->>CLI: return ScanResult { packages: [...] }
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 I hopped through node_modules, sniffed each trail,
Brought walkers and registrars to follow the tale.
Local wins the race, globals show on call,
Now skills are found tidy — big or small. 🌱

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description covers the key changes and motivation, but lacks explicit completion of the provided template structure with checklist items. Consider using the full template structure including the checklist items (Contributing guide compliance, local testing with pnpm run test:pr, changeset verification) for consistency with repository standards.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: refactoring discovery with dependency walking and adding source-aware package reporting with a SOURCE column.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch discovery-engine

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link
Copy Markdown

nx-cloud bot commented Apr 6, 2026

View your CI Pipeline Execution ↗ for commit ea07beb

Command Status Duration Result
nx run-many --targets=build --exclude=examples/** ✅ Succeeded 2s View ↗

☁️ Nx Cloud last updated this comment at 2026-04-13 14:46:02 UTC

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 6, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@tanstack/intent@112

commit: ea07beb

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/cli/intent-stale.md (1)

18-23: ⚠️ Potential issue | 🟡 Minor

Clarify no-package behavior for JSON mode.

The current bullets imply the “No intent-enabled packages found.” message always prints, but --json now returns [] instead.

Suggested doc tweak
-- If no packages are found, prints `No intent-enabled packages found.`
+- In text mode, if no packages are found, prints `No intent-enabled packages found.`
+- In `--json` mode, outputs `[]` when no packages are found.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/cli/intent-stale.md` around lines 18 - 23, The doc text is ambiguous
about what happens when no packages are found; update the bullet list in
intent-stale.md so it clearly states the behavior for JSON mode by replacing or
augmenting the line that says "If no packages are found, prints `No
intent-enabled packages found.`" with an explicit note that the CLI prints that
message in text mode but returns an empty JSON array (`[]`) when invoked with
the `--json` flag; mention both outputs and reference the `--json` option and
the exact text message "No intent-enabled packages found." so readers know the
difference.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/cli/intent-list.md`:
- Around line 18-23: The documentation's "discovery scope" wording is too
narrow; update the intent-list docs to reflect that scanForIntents() examines
workspace packages as well as project and workspace dependencies and that intent
list can also include accessible global packages and discovery warnings—adjust
the bulleted scope lines and the sentence that states what is scanned so it
explicitly mentions "workspace packages (not just dependencies),
workspace/project dependencies, and accessible global packages" and retain the
notes about warnings, summary line, and table columns.

In `@docs/overview.md`:
- Line 8: Update the casing of the term "markdown" to the proper noun "Markdown"
in the sentence that defines Skills (the sentence containing "Skills are
markdown documents..."); replace the lowercase instance with "Markdown" to
ensure consistent technical documentation convention across docs/overview.md.

In `@packages/intent/src/discovery/register.ts`:
- Around line 108-123: The replacement logic for package candidates ignores the
package source and can let a global package replace a local one; update the
decision in the register logic to enforce local-over-global first: before
applying the depth/version tie-break, check candidate.source and existing.source
(e.g., if candidate.source === 'local' and existing.source !== 'local' then set
shouldReplace = true, and if existing.source === 'local' and candidate.source
!== 'local' then set shouldReplace = false), otherwise fall back to the
existingDepth/candidateDepth and opts.comparePackageVersions(existing.version,
candidate.version) logic and then assign into opts.packages[existingIndex] when
shouldReplace is true. Ensure you reference and use existing.packageRoot,
candidate.packageRoot, existingIndex, opts.getPackageDepth and
opts.comparePackageVersions as currently used.

In `@packages/intent/src/discovery/walk.ts`:
- Line 3: The named imports on the import line are not alphabetized; reorder the
members in the import from '../utils.js' into alphabetical order (getDeps,
listNodeModulesPackageDirs, resolveDepDir) so the import becomes { getDeps,
listNodeModulesPackageDirs, resolveDepDir }, then save and re-run the linter/CI
to confirm the sort-imports rule is satisfied.

In `@packages/intent/src/scanner.ts`:
- Around line 419-437: The dependency walker is dropping source info by calling
tryRegister(...) with only two args so transitive deps inherit the default
'local'; update the walker (created by createDependencyWalker) to track the
source of the package currently being walked and forward it into tryRegister as
the third argument (i.e., call tryRegister(depPath, depName, currentSource)).
Specifically, modify the walk logic invoked by walkWorkspacePackages,
walkKnownPackages and walkProjectDeps so when scanning dependencies of a package
discovered with a non-local source (e.g., after scanTarget(nodeModules.global,
'global')) the propagated source is passed into tryRegister; adjust
createDependencyWalker and any internal helpers to accept/propagate a source
parameter for recursive walks and ensure existing tryRegister call sites (the
ones referenced in the review) are updated to include that source.

---

Outside diff comments:
In `@docs/cli/intent-stale.md`:
- Around line 18-23: The doc text is ambiguous about what happens when no
packages are found; update the bullet list in intent-stale.md so it clearly
states the behavior for JSON mode by replacing or augmenting the line that says
"If no packages are found, prints `No intent-enabled packages found.`" with an
explicit note that the CLI prints that message in text mode but returns an empty
JSON array (`[]`) when invoked with the `--json` flag; mention both outputs and
reference the `--json` option and the exact text message "No intent-enabled
packages found." so readers know the difference.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 452eb54f-c0f3-494a-ae6e-5b0cf84d0542

📥 Commits

Reviewing files that changed from the base of the PR and between 79519ab and 016ffde.

📒 Files selected for processing (17)
  • docs/cli/intent-install.md
  • docs/cli/intent-list.md
  • docs/cli/intent-stale.md
  • docs/getting-started/quick-start-maintainers.md
  • docs/overview.md
  • packages/intent/src/cli-support.ts
  • packages/intent/src/cli.ts
  • packages/intent/src/commands/list.ts
  • packages/intent/src/commands/stale.ts
  • packages/intent/src/discovery/index.ts
  • packages/intent/src/discovery/register.ts
  • packages/intent/src/discovery/walk.ts
  • packages/intent/src/index.ts
  • packages/intent/src/scanner.ts
  • packages/intent/src/types.ts
  • packages/intent/tests/cli.test.ts
  • packages/intent/tests/scanner.test.ts

Comment on lines +18 to +23
- Scans project and workspace dependencies for intent-enabled packages and skills
- Intentionally includes accessible global packages when listing installed skills
- Includes warnings from discovery
- If no packages are discovered, prints `No intent-enabled packages found.`
- Summary line with package count, skill count, and detected package manager
- Package table columns: `PACKAGE`, `VERSION`, `SKILLS`, `REQUIRES`
- Package table columns: `PACKAGE`, `SOURCE`, `VERSION`, `SKILLS`, `REQUIRES`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

The discovery scope text is still narrower than the implementation.

scanForIntents() walks workspace packages directly, not just dependencies, so this wording undersells what intent list can return.

📝 Suggested wording
-- Scans project and workspace dependencies for intent-enabled packages and skills
+- Scans the project, workspace packages, and their dependencies for intent-enabled packages and skills
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/cli/intent-list.md` around lines 18 - 23, The documentation's "discovery
scope" wording is too narrow; update the intent-list docs to reflect that
scanForIntents() examines workspace packages as well as project and workspace
dependencies and that intent list can also include accessible global packages
and discovery warnings—adjust the bulleted scope lines and the sentence that
states what is scanned so it explicitly mentions "workspace packages (not just
dependencies), workspace/project dependencies, and accessible global packages"
and retain the notes about warnings, summary line, and table columns.

`@tanstack/intent` is a CLI for shipping and consuming Agent Skills as package artifacts.

Skills are markdown documents that teach AI coding agents how to use your library correctly. Intent versions them with your releases, ships them inside npm packages, discovers them from local and accessible global `node_modules`, and helps agents load them automatically when working on matching tasks.
Skills are markdown documents that teach AI coding agents how to use your library correctly. Intent versions them with your releases, ships them inside npm packages, discovers them from your project and workspace by default, and helps agents load them automatically when working on matching tasks.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use proper casing for “Markdown”.

Use Markdown (proper noun) for consistency with technical documentation conventions.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~8-~8: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ...lls as package artifacts.

Skills are markdown documents that teach AI coding agents h...

(MARKDOWN_NNP)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/overview.md` at line 8, Update the casing of the term "markdown" to the
proper noun "Markdown" in the sentence that defines Skills (the sentence
containing "Skills are markdown documents..."); replace the lowercase instance
with "Markdown" to ensure consistent technical documentation convention across
docs/overview.md.

Comment on lines +108 to +123
const existingDepth = opts.getPackageDepth(
existing.packageRoot,
opts.projectRoot,
)
const candidateDepth = opts.getPackageDepth(
candidate.packageRoot,
opts.projectRoot,
)
const shouldReplace =
candidateDepth < existingDepth ||
(candidateDepth === existingDepth &&
opts.comparePackageVersions(candidate.version, existing.version) > 0)

if (shouldReplace) {
opts.packages[existingIndex] = candidate
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Enforce local-over-global precedence before depth/version tie-breaking.

The replacement rule ignores candidate.source, so the new “prefer local over global” behavior currently depends on filesystem layout. A hoisted local package scanned from a workspace subdir can tie a nearby explicit global root on getPackageDepth(), and a newer global version will replace the local candidate.

💡 Suggested fix
     const shouldReplace =
-      candidateDepth < existingDepth ||
-      (candidateDepth === existingDepth &&
-        opts.comparePackageVersions(candidate.version, existing.version) > 0)
+      existing.source === 'global' && candidate.source === 'local'
+        ? true
+        : existing.source === 'local' && candidate.source === 'global'
+          ? false
+          : candidateDepth < existingDepth ||
+            (candidateDepth === existingDepth &&
+              opts.comparePackageVersions(
+                candidate.version,
+                existing.version,
+              ) > 0)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/intent/src/discovery/register.ts` around lines 108 - 123, The
replacement logic for package candidates ignores the package source and can let
a global package replace a local one; update the decision in the register logic
to enforce local-over-global first: before applying the depth/version tie-break,
check candidate.source and existing.source (e.g., if candidate.source ===
'local' and existing.source !== 'local' then set shouldReplace = true, and if
existing.source === 'local' and candidate.source !== 'local' then set
shouldReplace = false), otherwise fall back to the existingDepth/candidateDepth
and opts.comparePackageVersions(existing.version, candidate.version) logic and
then assign into opts.packages[existingIndex] when shouldReplace is true. Ensure
you reference and use existing.packageRoot, candidate.packageRoot,
existingIndex, opts.getPackageDepth and opts.comparePackageVersions as currently
used.

@@ -0,0 +1,113 @@
import { existsSync, readFileSync } from 'node:fs'
import { join } from 'node:path'
import { listNodeModulesPackageDirs, resolveDepDir, getDeps } from '../utils.js'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix import member ordering to satisfy ESLint.

Line 3 has non-alphabetized named imports (sort-imports error), which can fail lint in CI.

🔧 Proposed fix
-import { listNodeModulesPackageDirs, resolveDepDir, getDeps } from '../utils.js'
+import { getDeps, listNodeModulesPackageDirs, resolveDepDir } from '../utils.js'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { listNodeModulesPackageDirs, resolveDepDir, getDeps } from '../utils.js'
import { getDeps, listNodeModulesPackageDirs, resolveDepDir } from '../utils.js'
🧰 Tools
🪛 ESLint

[error] 3-3: Member 'getDeps' of the import declaration should be sorted alphabetically.

(sort-imports)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/intent/src/discovery/walk.ts` at line 3, The named imports on the
import line are not alphabetized; reorder the members in the import from
'../utils.js' into alphabetical order (getDeps, listNodeModulesPackageDirs,
resolveDepDir) so the import becomes { getDeps, listNodeModulesPackageDirs,
resolveDepDir }, then save and re-run the linter/CI to confirm the sort-imports
rule is satisfied.

Comment on lines +419 to 437
const { walkKnownPackages, walkProjectDeps, walkWorkspacePackages } =
createDependencyWalker({
packages,
projectRoot,
workspacePatterns,
)) {
const wsNodeModules = join(wsDir, 'node_modules')
if (existsSync(wsNodeModules)) {
for (const dirPath of listNodeModulesPackageDirs(wsNodeModules)) {
tryRegister(dirPath, 'unknown')
}
}

const wsPkg = readPkgJson(wsDir)
if (wsPkg) {
walkDepsFromPkgJson(wsPkg, wsDir)
}
}
}
readPkgJson,
tryRegister,
warnings,
})

walkWorkspacePackages()
walkKnownPackages()
walkProjectDeps()

if (
explicitGlobalNodeModules ||
packages.length === 0 ||
!nodeModules.local.exists
) {
if (includeGlobal) {
ensureGlobalNodeModules()
scanTarget(nodeModules.global)
scanTarget(nodeModules.global, 'global')
walkKnownPackages()
walkProjectDeps()
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -p 'walk.ts' packages/intent/src/discovery -x sed -n '1,260p' {}
echo '--- tryRegister call sites in walk.ts ---'
rg -n -C3 '\btryRegister\s*\(' packages/intent/src/discovery/walk.ts
echo '--- global/source coverage in scanner tests ---'
rg -n -C2 'includeGlobal|source' packages/intent/tests/scanner.test.ts

Repository: TanStack/intent

Length of output: 4845


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== tryRegister function definition in scanner.ts ==="
rg -n -B2 -A8 'tryRegister\s*[:=]|function tryRegister' packages/intent/src/scanner.ts | head -50

echo -e "\n=== How scanTarget handles source parameter ==="
rg -n -B3 -A10 'scanTarget' packages/intent/src/scanner.ts | head -80

echo -e "\n=== Source field assignments in scanner.ts ==="
rg -n "source\s*[:=]" packages/intent/src/scanner.ts

Repository: TanStack/intent

Length of output: 112


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== createDependencyWalker call site in scanner.ts ==="
rg -n -B5 -A15 'createDependencyWalker' packages/intent/src/scanner.ts

echo -e "\n=== Look for tryRegister callback definition in scanner.ts ==="
rg -n 'tryRegister.*=' packages/intent/src/scanner.ts | head -20

Repository: TanStack/intent

Length of output: 1336


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== createPackageRegistrar implementation ==="
rg -n -B2 -A30 'export function createPackageRegistrar|export const createPackageRegistrar' packages/intent/src/discovery/

echo -e "\n=== Full context around line 402 in scanner.ts ==="
sed -n '395,440p' packages/intent/src/scanner.ts

Repository: TanStack/intent

Length of output: 3675


Transitive global packages are misclassified as local sources.

When scanTarget(nodeModules.global, 'global') finds intent packages directly in the global node_modules, they are correctly labeled with source: 'global'. However, walkKnownPackages() and walkProjectDeps() discover dependencies of those packages via the dependency walker in packages/intent/src/discovery/walk.ts.

The walker's tryRegister calls (lines 38, 80, 97) pass only two arguments and omit the third source parameter. Since tryRegister defaults source to 'local', any intent-enabled transitive dependency discovered through a global package will be incorrectly labeled as source: 'local' instead of inheriting source: 'global'.

The walker needs to track and forward source information when registering transitive packages discovered during the dependency walk.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/intent/src/scanner.ts` around lines 419 - 437, The dependency walker
is dropping source info by calling tryRegister(...) with only two args so
transitive deps inherit the default 'local'; update the walker (created by
createDependencyWalker) to track the source of the package currently being
walked and forward it into tryRegister as the third argument (i.e., call
tryRegister(depPath, depName, currentSource)). Specifically, modify the walk
logic invoked by walkWorkspacePackages, walkKnownPackages and walkProjectDeps so
when scanning dependencies of a package discovered with a non-local source
(e.g., after scanTarget(nodeModules.global, 'global')) the propagated source is
passed into tryRegister; adjust createDependencyWalker and any internal helpers
to accept/propagate a source parameter for recursive walks and ensure existing
tryRegister call sites (the ones referenced in the review) are updated to
include that source.

KyleAMathews and others added 2 commits April 13, 2026 08:44
- Simplify walk.ts/register.ts (extract helpers, unify walkDeps variants)
- Restore ENOENT-discriminated warnings for malformed root/workspace
  package.json (prevents silent failures when config is corrupt)
- Tighten CreateDependencyWalkerOptions.packages to IntentPackage[] to
  make shared mutable state between registrar and walker explicit
- Add coverage for local-over-global precedence in list --json and for
  stale scoping to local packages when globals are configured

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@LadyBluenotes LadyBluenotes merged commit 36e696b into main Apr 13, 2026
5 checks passed
@LadyBluenotes LadyBluenotes deleted the discovery-engine branch April 13, 2026 16:30
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.

2 participants