Skip to content

Add e18e replacement suggestions, supply-chain combination flags, and maintenance drift tiers - #95

Merged
JosephMaynard merged 8 commits into
masterfrom
feature/port-saas-analysis
Jul 23, 2026
Merged

JosephMaynard merged 8 commits into
masterfrom
feature/port-saas-analysis

Conversation

@JosephMaynard

@JosephMaynard JosephMaynard commented Jul 23, 2026 •

Copy link
Copy Markdown
Owner

Ports the worthwhile analysis from the retired Dependency Radar SaaS into the CLI as one PR. The SaaS composite risk score is deliberately not ported — the individual signals below are surfaced as explainable findings instead of a 0–100 number.

Replacement suggestions (e18e)

  • Every scanned package is matched offline against the vendored module-replacements catalogue, part of the e18e ecosystem performance initiative (MIT, pinned to v3.0.0, 792 entries).
  • Vendored at build time via scripts/build-replacements.ts → src/generated/replacements.ts (same pattern as the SPDX data; refresh with npm run update:replacements). Zero runtime dependencies, works with --offline.
  • Surfaced in dependencies[id].replacement, the report's Upgrade & Change Impact detail panel (with credit and links to e18e / module-replacements), explain <pkg> output, and info-level modernization findings for direct dependencies only.
  • The header Replacements stat, the Has replacement suggestion filter, and the detail section are all hidden unless the scan actually matched something.
  • Sample data now includes a recommendation on the chalk stand-in (util.styleText, picocolors, ansis) so npm run dev:report shows the feature.

Supply-chain combination flags

Install lifecycle scripts paired with a mutable or unverifiable source now produce dedicated findings that explain why the pairing matters:

Combination Severity
Install scripts + git dependency error
Install scripts + non-registry tarball error
Install scripts + unexpected registry host error
Install scripts + missing lockfile integrity warning

Shared logic in src/supplyChainCombos.ts feeds findings, report key points, overall dependency risk (error combos escalate to red), and a new opt-in supply-chain-combo --fail-on rule.

Maintenance drift tiers + upgrade risk

  • New slowing status: 12+ months without any registry write.
  • Dual-signal escalation using the repository pushed_at timestamp already returned by the existing bounded ecosyste.ms lookups (no new hosts): registry and repo must both be quiet before a package is called stale (12mo/6mo) or unmaintained (24mo/12mo). An actively developed package that just stopped publishing stays slowing.
  • Single-signal fallback keeps the existing 18/36-month behaviour, so --offline and degraded scans are unchanged.
  • Derived upgrade.risk band (high/medium/low/unknown) from outdated status and blockers, recomputed after registry enrichment.

Housekeeping

  • Report schema bumped to 1.7 (purely additive; 1.6 baselines remain valid for compare).
  • README documents all three features, the new status tiers, and the new CI rule.
  • Committed dist/ includes a catch-up rebuild: Harden Dependency Radar for v1.0.0 #86 changed src/ but shipped without rebuilding dist/, so part of this diff is that drift.
  • No release/tag — more PRs to come before the next version.

Testing

  • 186 unit tests pass (new suites for combos and upgrade risk; extended maintenance, findings, and failOn tests).
  • tsc clean; report-ui typecheck shows only the 3 errors that pre-exist on master.
  • End-to-end offline scan of test-repos/cal.diy: 301 replacement matches, 16 modernization findings, upgrade-risk bands populated, output validates against schema 1.7, and the generated HTML contains the new UI elements.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added fully offline replacement suggestions with a Replacements stat chip, Has replacement suggestion filtering, and explain output (direct dependencies only).
    • Added per-dependency Upgrade risk banding (high/medium/low/unknown).
    • Expanded maintenance signals with a new slowing state based on repo push timing.
    • Added supply-chain combo reporting, including optional enforcement via --fail-on supply-chain-combo.
  • Documentation
    • Updated README for maintenance signals, replacements, upgrade risk, and --fail-on (including supply-chain-combo).
  • Changes
    • Report schema bumped to 1.7 and added the modernization finding category.
  • Tests
    • Updated/added coverage for schema, replacements, upgrade risk, maintenance “slowing,” and supply-chain combo detection.

…e drift tiers

Ports the useful analysis from the retired SaaS into the CLI as three
features, deliberately excluding the composite risk score:

- Replacement suggestions: dependencies are matched offline against the
  vendored e18e module-replacements catalogue (es-tooling/module-replacements
  v3.0.0, MIT). Matches appear in the JSON model, the report detail panel,
  explain output, and as info-level modernization findings for direct deps.
  The report header stat, filter toggle, and detail section only appear when
  a scan actually has matches. Refresh with `npm run update:replacements`.

- Supply-chain combination flags: install lifecycle scripts paired with a
  mutable or unverifiable source (git dependency, non-registry tarball,
  unexpected registry host, missing lockfile integrity) now produce
  dedicated error/warning findings, escalate overall dependency risk in the
  report, and back a new opt-in `supply-chain-combo` --fail-on rule.

- Maintenance drift tiers: a new `slowing` status (12+ months without a
  registry write), plus dual-signal escalation using the repository push
  timestamp already returned by the bounded ecosyste.ms lookups - both the
  registry and the repo must be quiet before a package is called stale or
  unmaintained. Also derives a coarse `upgrade.risk` band per dependency.

Schema bumps to 1.7 (additive; 1.6 baselines remain valid for compare).
Committed dist/ also catches up with PR #86, which shipped without a rebuild.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds dual-surface maintenance statuses, offline replacement suggestions, upgrade-risk bands, supply-chain combination findings and policy rules, schema 1.7 updates, and report UI support for displaying and filtering the new dependency data.

Changes

Report enrichment and risk signals

Layer / File(s) Summary
Maintenance contracts and dual-surface status
src/types.ts, src/runners/maintenanceSignals.ts, src/maintenanceCache.ts, src/schema.ts
Maintenance records include repository push timing and the slowing status, with updated cache persistence and schema metadata.
Replacement catalogue and upgrade risk
scripts/build-replacements.ts, src/aggregator.ts, src/upgradeRisk.ts, src/findings.ts, src/explain.ts
Pinned manifests generate an offline catalogue; aggregation attaches replacements and computes upgrade-risk bands, findings, and explain output.
Supply-chain combinations and policy evaluation
src/supplyChainCombos.ts, src/findings.ts, src/failOn.ts, src/reportDetailRules.ts, src/cli.ts
Install hooks are matched with source signals to produce findings, risk/key-point output, and the supply-chain-combo policy rule.
Report rendering and replacement filtering
report-ui/*, src/report.ts, src/report-assets.ts, report-ui/sample-data.json, README.md
Reports display replacement suggestions, upgrade risk, repository push timing, slowing maintenance, and replacement filters and statistics.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Aggregator
  participant Findings
  participant ReportUI
  CLI->>Aggregator: Aggregate dependencies and enrich records
  Aggregator->>Findings: Build findings from enriched records and signals
  Findings-->>CLI: Return findings and policy inputs
  CLI->>ReportUI: Render schema 1.7 report data
  ReportUI-->>CLI: Display replacement, maintenance, risk, and supply-chain details
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main additions: e18e replacement suggestions, supply-chain combo flags, and new maintenance drift tiers.
✨ 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 feature/port-saas-analysis

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

Comment thread scripts/build-replacements.ts Fixed

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@report-ui/index.html`:
- Around line 239-247: Update the report stat-chip grid styling used by the
stat-replacements chip so all six desktop chips fit on one row, either by
changing the fixed layout to six columns or by using an adaptive grid. Preserve
the existing responsive behavior for narrower viewports.

In `@report-ui/types.ts`:
- Line 103: Update the schemaVersion type in report-ui/types.ts to include '1.7'
alongside the existing supported versions, keeping the report UI contract
aligned with CLI-generated payloads.

In `@src/cli.ts`:
- Around line 2335-2336: Update the aggregation flow around
applyUpgradeRisk(aggregated) so upgrade-risk derivation always runs immediately
after aggregation, regardless of enrichmentTouchedData. Keep only any
enrichment-dependent findings recomputation conditional, and add a CLI
regression test covering scans without registry or maintenance enrichment that
still produce dep.upgrade.risk from local outdated or blocker data.

In `@src/report-assets.ts`:
- Line 16: Update the source-signal indexing logic in function s so packageId is
used as the primary key, preserving its version-qualified identity when deriving
install-script combinations; fall back to packageName only when packageId is
absent. Ensure combination lookup in function i uses the same packageId-first
keying, then regenerate the JS_CONTENT bundle asset.

In `@src/supplyChainCombos.ts`:
- Around line 67-80: The supply-chain signal index currently collapses different
package instances by name, causing false combinations. In
src/supplyChainCombos.ts:67-80, key the map by packageId or the canonical
packageName@packageVersion identity; in src/failOn.ts:543-548, query it using
the matching dependency instance key such as dep.package.id. Add coverage
proving a source signal on one version and an install hook on another does not
trigger supply-chain-combo.
🪄 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: c357148c-f42d-4d65-b82a-f81c4032aa10

📥 Commits

Reviewing files that changed from the base of the PR and between 76774dd and c42ffc6.

⛔ Files ignored due to path filters (20)
  • dist/aggregator.js is excluded by !**/dist/**
  • dist/cli.js is excluded by !**/dist/**
  • dist/explain.js is excluded by !**/dist/**
  • dist/failOn.js is excluded by !**/dist/**
  • dist/findings.js is excluded by !**/dist/**
  • dist/generated/replacements.js is excluded by !**/dist/**, !**/generated/**
  • dist/license.js is excluded by !**/dist/**
  • dist/maintenanceCache.js is excluded by !**/dist/**
  • dist/outputFormats.js is excluded by !**/dist/**
  • dist/report-assets.js is excluded by !**/dist/**
  • dist/report.js is excluded by !**/dist/**
  • dist/reportDetailRules.js is excluded by !**/dist/**
  • dist/runners/maintenanceSignals.js is excluded by !**/dist/**
  • dist/runners/npmAudit.js is excluded by !**/dist/**
  • dist/schema.js is excluded by !**/dist/**
  • dist/supplyChainCombos.js is excluded by !**/dist/**
  • dist/upgradeRisk.js is excluded by !**/dist/**
  • report-ui/dist/report.css is excluded by !**/dist/**
  • report-ui/dist/report.iife.js is excluded by !**/dist/**
  • src/generated/replacements.ts is excluded by !**/generated/**
📒 Files selected for processing (27)
  • README.md
  • package.json
  • report-ui/index.html
  • report-ui/main.ts
  • report-ui/sample-data.json
  • report-ui/types.ts
  • scripts/build-replacements.ts
  • src/aggregator.ts
  • src/cli.test.ts
  • src/cli.ts
  • src/explain.ts
  • src/failOn.test.ts
  • src/failOn.ts
  • src/findings.test.ts
  • src/findings.ts
  • src/maintenanceCache.ts
  • src/report-assets.ts
  • src/report.ts
  • src/reportDetailRules.ts
  • src/runners/maintenanceSignals.test.ts
  • src/runners/maintenanceSignals.ts
  • src/schema.ts
  • src/supplyChainCombos.test.ts
  • src/supplyChainCombos.ts
  • src/types.ts
  • src/upgradeRisk.test.ts
  • src/upgradeRisk.ts

Comment thread report-ui/index.html
Comment on lines +239 to +247
<button
type="button"
class="stat-chip"
id="stat-replacements"
data-stat-filter="has-replacement"
hidden
>
<span class="meta-label">Replacements</span> <strong>–</strong>
</button>

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Prevent the replacement stat from wrapping into its own desktop row.

This adds a sixth chip, but the shipped report CSS uses grid-template-columns: repeat(5, 1fr). Reports with replacements will show a lone second-row stat. Use six columns or an adaptive grid.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@report-ui/index.html` around lines 239 - 247, Update the report stat-chip
grid styling used by the stat-replacements chip so all six desktop chips fit on
one row, either by changing the fixed layout to six columns or by using an
adaptive grid. Preserve the existing responsive behavior for narrower viewports.

Comment thread report-ui/types.ts
Comment thread src/cli.ts
Comment on lines 2335 to +2336
if (enrichmentTouchedData) {
applyUpgradeRisk(aggregated);

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Apply upgrade-risk derivation even when no enrichment ran.

applyUpgradeRisk() is gated by enrichmentTouchedData, which remains false for scans without registry/maintenance enrichment (including offline-oriented runs). Those reports omit the new dep.upgrade.risk field despite having local outdated/blocker data. Invoke it immediately after aggregation; keep only findings recomputation conditional if needed. Add a no-enrichment CLI regression test.

Proposed fix
-    if (enrichmentTouchedData) {
-      applyUpgradeRisk(aggregated);
+    applyUpgradeRisk(aggregated);
+    if (enrichmentTouchedData) {
       const findings = buildDependencyFindings(aggregated, { targetNodeMajor: opts.targetNodeMajor });
📝 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
if (enrichmentTouchedData) {
applyUpgradeRisk(aggregated);
applyUpgradeRisk(aggregated);
if (enrichmentTouchedData) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli.ts` around lines 2335 - 2336, Update the aggregation flow around
applyUpgradeRisk(aggregated) so upgrade-risk derivation always runs immediately
after aggregation, regardless of enrichmentTouchedData. Keep only any
enrichment-dependent findings recomputation conditional, and add a CLI
regression test covering scans without registry or maintenance enrichment that
still produce dep.upgrade.risk from local outdated or blocker data.

Comment thread src/report-assets.ts Outdated
@@ -13,4 +13,4 @@ export const CSS_CONTENT = `*,:before,:after{box-sizing:border-box}:root{--bg-pr
* JavaScript content for the dependency radar HTML report
* Built from report-ui/main.ts
*/
export const JS_CONTENT = `!function(){var e={"network-access":"Accesses network during install","dynamic-exec":"Uses dynamic execution","child-process":"Spawns child processes",encoding:"Uses encoding/decoding logic",obfuscated:"Contains obfuscated/minified install logic","reads-env":"Reads environment variables","reads-home":"Reads user home directory","uses-ssh":"Uses SSH configuration/keys"};function t(e){return e.critical+e.high+e.moderate+e.low}function n(e){return"runtime"===e?"Runtime":"dev"===e?"Dev":"optional"===e?"Optional":"peer"===e?"Peer":e.split(/[-_\\s]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}function a(a,s){const r=[],i=t(s),o=a.security.advisories?.some(e=>e.fixAvailable);if(s.critical||s.high){const e=s.critical+s.high;r.push(\`\${e} critical/high \${1===e?"vulnerability":"vulnerabilities"}\${o?", fix available":""}\`)}if(s.moderate||s.low){const e=s.moderate+s.low;r.push(\`\${function(e){const t=[];return e.moderate&&t.push(\`\${e.moderate} moderate\`),e.low&&t.push(\`\${e.low} low\`),t.join(", ")}(s)} \${1===e?"vulnerability":"vulnerabilities"}\${o?", fix available":""}\`)}"deprecated"===a.maintenance?.status?r.push(a.maintenance.deprecated&&!a.maintenance.deprecated.installedVersion?"Latest version deprecated by the author":"Deprecated by the author"):"archived"===a.maintenance?.status?r.push("Source repository is archived"):"unmaintained"===a.maintenance?.status?r.push("No registry activity for 3+ years"):"stale"===a.maintenance?.status&&r.push("No registry activity for 18+ months"),"green"!==a.compliance.licenseRisk&&r.push("Licence status: "+function(e){switch(e){case"declared-only":return"Declared";case"inferred-only":return"Inferred";case"match":return"Declared + Inferred (match)";case"mismatch":return"Declared + Inferred (mismatch)";case"invalid-spdx":return"Invalid SPDX";default:return"Unknown"}}(a.compliance.license.status)),a.upgrade.blocksNodeMajor&&r.push("Blocks Node major upgrade"),a.upgrade.blockers?.length&&r.push(\`\${a.upgrade.blockers.length} upgrade \${1===a.upgrade.blockers.length?"blocker":"blockers"} detected\`);const c=a.execution?.risk||"green";var l;if("green"!==c&&r.push(("red"===(l=c)?"High":"amber"===l?"Medium":"Low")+" install-time execution risk"),a.execution?.scripts?.hooks?.length&&r.push("Runs "+a.execution.scripts.hooks.slice(0,2).join(", ")+" lifecycle script"+(1===a.execution.scripts.hooks.length?"":"s")),function(e){return Array.from(new Set([...e.execution?.scripts?.signals||[],...e.execution?.signals||[]]))}(a).slice(0,3).forEach(t=>r.push(e[t])),a.packaging?.signals?.length&&r.push(\`\${a.packaging.signals.length} package content \${1===a.packaging.signals.length?"signal":"signals"}\`),a.supplyChain?.registry?.signals?.length&&r.push(\`\${a.supplyChain.registry.signals.length} registry metadata \${1===a.supplyChain.registry.signals.length?"signal":"signals"}\`),a.usage.direct)r.push(\`Direct \${n(a.usage.scope).toLowerCase()} dependency\`);else{const e=a.usage.origins.topParentPackages?.[0]?\` introduced by \${a.usage.origins.topParentPackages[0]}\`:"";r.push(\`Transitive \${n(a.usage.scope).toLowerCase()} dependency\${e}\`)}return a.usage.depth>1&&r.push(\`Dependency depth \${a.usage.depth}\`),(0===r.length||0===i&&"green"===c&&"green"===a.compliance.licenseRisk&&r.length<3)&&["No known vulnerabilities","No install-time execution signals detected","Licence status appears consistent",a.usage.direct?\`Direct \${n(a.usage.scope).toLowerCase()} dependency\`:\`Transitive \${n(a.usage.scope).toLowerCase()} dependency\`].forEach(e=>{r.includes(e)||r.push(e)}),Array.from(new Set(r)).slice(0,8)}function s(e){if(!e.workspaces.enabled)return[];const t=new Set;return(e.workspaces.workspacePackages||[]).forEach(e=>{e.name&&t.add(e.name)}),Object.values(e.dependencies||{}).forEach(e=>{(e.usage.origins.workspaces||[]).forEach(e=>{e&&t.add(e)})}),Array.from(t).sort((e,t)=>"root"===e?-1:"root"===t?1:e.localeCompare(t))}var r=2.8,i='500 11.5px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';function o(e,t,n){return Math.min(n,Math.max(t,e))}function c(e,t=!1){return t?e.length:Math.min(e.length,34)}function l(e){const t=c(e);return e.length<=34?t:Math.max(1,t-6)}function d(e){const{labelGraphemes:t}=e;if(t.length<=34)return e.ref.name;const n=o(Math.round(e.renderLabelChars),1,t.length);return n>=t.length?e.ref.name:\`\${t.slice(0,n-1).join("")}…\`}function u(e,t,n){const a=function(e){const t=e.trim(),n=t.match(/^#([0-9a-f]{3}|[0-9a-f]{6})\$/i);if(n){const e=n[1];return 3===e.length?{r:parseInt(e[0]+e[0],16),g:parseInt(e[1]+e[1],16),b:parseInt(e[2]+e[2],16)}:{r:parseInt(e.slice(0,2),16),g:parseInt(e.slice(2,4),16),b:parseInt(e.slice(4,6),16)}}const a=t.match(/^rgba?\\(([^)]+)\\)\$/i);if(!a)return null;const s=a[1].replace(/\\//g," ").split(/[\\s,]+/).filter(Boolean).slice(0,3);if(3!==s.length)return null;const r=e=>{if(e.endsWith("%")){const t=Number(e.slice(0,-1));return Number.isFinite(t)?o(Math.round(t/100*255),0,255):null}const t=Number(e);return Number.isFinite(t)?o(Math.round(t),0,255):null},i=r(s[0]),c=r(s[1]),l=r(s[2]);return null===i||null===c||null===l?null:{r:i,g:c,b:l}}(e);if(!a)return n;const s=o(t,0,1);return\`rgb(\${Math.round(a.r+(255-a.r)*s)}, \${Math.round(a.g+(255-a.g)*s)}, \${Math.round(a.b+(255-a.b)*s)})\`}function p(e){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()}function h(e,t,n){if(0===t.length)return;if(e.moveTo(t[0].x,t[0].y),1===t.length)return;if(2===t.length)return void e.lineTo(t[1].x,t[1].y);for(let s=1;s<t.length-1;s+=1){const a=t[s-1],r=t[s],i=t[s+1],o=r.x-a.x,c=r.y-a.y,l=i.x-r.x,d=i.y-r.y,u=Math.hypot(o,c),p=Math.hypot(l,d);if(u<.001||p<.001){e.lineTo(r.x,r.y);continue}const h=Math.min(n,.45*u,.45*p),g=r.x-o/u*h,m=r.y-c/u*h,v=r.x+l/p*h,f=r.y+d/p*h;e.lineTo(g,m),e.quadraticCurveTo(r.x,r.y,v,f)}const a=t[t.length-1];e.lineTo(a.x,a.y)}function g(e){const t=new Map;return e.nodes.forEach(e=>{const n=t.get(e.depth);n?n.push(e):t.set(e.depth,[e])}),t.forEach(e=>{e.sort((e,t)=>e.renderY-t.renderY)}),t}function m(e,t,n,a){const s=t.renderX,r=t.renderY,i=n.renderX,c=n.renderY,l=n.depth-t.depth,d=Math.abs(l);if(0===d){const n=Math.abs(s-i)<a.sameColumnXThreshold,l=Math.abs(r-c),d=t.depth<a.maxDepth;if(n&&l>a.minDetourVerticalSpan&&d){const n=a.paddingX+t.depth*a.layerGap,d=a.paddingX+(t.depth+1)*a.layerGap,u=.5*(n+d);let p=u+a.detourInset;const g=Math.min(r,c)-12,m=Math.max(r,c)+12;(function(e,t,n,a,s){const r=e.depthNodeIndex.get(t);if(!r||0===r.length)return!1;const i=function(e,t){let n=0,a=e.length;for(;n<a;){const s=n+(a-n>>1);e[s].renderY<t?n=s+1:a=s}return n}(r,n);for(let o=i;o<r.length&&r[o].renderY<=a;o+=1)if(Math.abs(r[o].renderX-s)<e.detourNodeClearance)return!0;return!1})(a,t.depth+1,g,m,p)&&(p+=12);p=o(p,u+8,d-24);const v=Math.max(1,p-s);return void h(e,[{x:s,y:r},{x:p,y:r},{x:p,y:c},{x:i,y:c}],o(.42*Math.min(v,l),16,52))}e.moveTo(s,r);const u=s+.5*(i-s),p=r+(c-r)*a.edgeCurve;return void e.quadraticCurveTo(u,p,i,c)}if(1===d){const o=Math.min(t.depth,n.depth),l=a.paddingX+o*a.layerGap+.5*a.layerGap;return e.moveTo(s,r),void e.bezierCurveTo(l,r,l,c,i,c)}const u=Math.sign(l),p=c-r,g=[{x:s,y:r}],m=a.paddingX+t.depth*a.layerGap+u*(.5*a.layerGap);g.push({x:m,y:r});for(let o=1;o<d;o+=1){const e=t.depth+u*o,n=a.paddingX+e*a.layerGap+u*(.5*a.layerGap),s=o/d;g.push({x:n,y:r+p*s})}const v=a.paddingX+n.depth*a.layerGap-u*(.5*a.layerGap);g.push({x:v,y:c}),g.push({x:i,y:c}),h(e,g,14)}function v(e,t,n,a){a&&t.highlighted?function(e,t,n){const a=t.renderX,s=t.renderY,r=n.renderX,i=n.renderY,c=r-a,l=i-s;if(e.moveTo(a,s),Math.abs(c)<18){const t=a+(s<=i?26:-26);return void e.bezierCurveTo(t,s,t,i,r,i)}const d=o(.44*Math.abs(c),42,150),u=Math.sign(c),p=o(.12*Math.abs(l),0,24);e.bezierCurveTo(a+u*d,s+p*Math.sign(l),r-u*d,i-p*Math.sign(l),r,i)}(e,t.from,t.to):m(e,t.from,t.to,n)}function f(e,t){return\`\${e}@\${t}\`}function y(e,t){return\`\${e}->\${t}\`}function k(e){if(!e||"object"!=typeof e)return!1;const t=e;if(!Array.isArray(t.workspaces))return!1;if(!t.dependencies||"object"!=typeof t.dependencies)return!1;const n=e=>Array.isArray(e)&&e.every(e=>"string"==typeof e);return!!t.workspaces.every(e=>(e=>{if(!e||"object"!=typeof e)return!1;const t=e;return"string"==typeof t.name&&!!Array.isArray(t.directDependencies)&&!!Array.isArray(t.directDevDependencies)})(e))&&(!!t.workspaces.every(e=>n(e.directDependencies)&&n(e.directDevDependencies))&&!!Object.entries(t.dependencies).every(([,e])=>{if(!e||"object"!=typeof e)return!1;const t=e;return!(void 0!==t.dependencies&&!Array.isArray(t.dependencies))&&!(void 0!==t.workspaceOrigins&&!Array.isArray(t.workspaceOrigins))}))}function b(e){const t=e.compliance.license.declared?.valid?e.compliance.license.declared.spdxId:void 0;return t||(e.compliance.license.inferred?.spdxId||"Unknown")}function w(e){const t=e.security?.summary;return t?Number(t.critical||0)+Number(t.high||0)+Number(t.moderate||0)+Number(t.low||0):0}function C(e){const t=e.security?.summary?.highest;return"critical"===t||"high"===t?"high":"moderate"===t?"moderate":"none"}function E(e,t){const n=new Set,a=[t];for(;a.length>0;){const t=a.pop();if(!t)continue;const s=e.nodes.get(t);s&&s.parents.forEach(e=>{n.has(e)||(n.add(e),a.push(e))})}return n}function x(e,t){const n=new Set,a=[t];for(;a.length>0;){const t=a.pop();if(!t)continue;const s=e.nodes.get(t);s&&s.children.forEach(e=>{n.has(e)||(n.add(e),a.push(e))})}return n}function S(e,t,n){const a=new Map,s=[{slug:t,distance:0}];let r=0;for(;r<s.length;){const t=s[r++],i=e.nodes.get(t.slug);i&&i[n].forEach(e=>{a.has(e)||(a.set(e,t.distance+1),s.push({slug:e,distance:t.distance+1}))})}return a}function L(e){const t=function(e,t,n){const a=window.__DEPENDENCY_DATA__;if(k(a)){const e={};return Object.entries(a.dependencies).forEach(([t,n])=>{const a=n,s=a.vulnerabilitySeverity||a.vulnerabilityHighest||a.highestSeverity||"none",r=String(s).trim().toLowerCase();let i="none";"critical"===r||"high"===r?i="high":"moderate"!==r&&"medium"!==r||(i="moderate"),e[t]={slug:String(a.slug||t),name:String(a.name||t),version:String(a.version||""),dependencies:Array.isArray(a.dependencies)?a.dependencies.map(e=>String(e)):[],license:String(a.license||"Unknown"),vulnerabilityCount:Number(a.vulnerabilityCount||0),vulnerabilitySeverity:i,isDevOnly:Boolean(a.isDevOnly),workspaceOrigins:Array.isArray(a.workspaceOrigins)?a.workspaceOrigins.map(e=>String(e)):[]}}),{workspaces:a.workspaces,dependencies:e}}const s={},r=Object.values(e.dependencies||{});r.forEach(e=>{const t=f(e.package.name,e.package.version);s[t]={slug:t,name:e.package.name,version:e.package.version,dependencies:[],license:b(e),vulnerabilityCount:w(e),vulnerabilitySeverity:C(e),isDevOnly:"dev"===e.usage.scope,workspaceOrigins:e.usage.origins.workspaces||[]}}),r.forEach(e=>{const a=f(e.package.name,e.package.version),r=e.graph.subDeps;if(!r)return;const i=new Set;["dep","dev","opt","peer"].forEach(e=>{const o=r[e];o&&Object.values(o).forEach(e=>{const r=e[1];if(!r)return;const o=n(r);o&&t.has(o)&&s[o]&&o!==a&&i.add(o)})}),s[a].dependencies=[...i]});const i=new Map,o=e=>{const t=i.get(e);if(t)return t;const n={directDependencies:new Set,directDevDependencies:new Set};return i.set(e,n),n};return o("root"),(e.workspaces.workspacePackages||[]).forEach(e=>{o(e.name)}),r.forEach(e=>{if(!e.usage.direct)return;const t=f(e.package.name,e.package.version);(e.usage.origins.workspaces?.length?e.usage.origins.workspaces:["root"]).forEach(n=>{const a=o(n);"dev"===e.usage.scope?a.directDevDependencies.add(t):a.directDependencies.add(t)})}),{workspaces:[...i.entries()].map(([e,t])=>({name:e,directDependencies:[...t.directDependencies],directDevDependencies:[...t.directDevDependencies]})).sort((e,t)=>e.name.localeCompare(t.name)),dependencies:s}}(e.report,e.knownDepKeys,e.resolveDepKey),n=new Map(t.workspaces.map(e=>[e.name,e])),a=new Map,s=new Map;Object.values(t.dependencies).forEach(e=>{const n=(e.dependencies||[]).filter(n=>n!==e.slug&&Boolean(t.dependencies[n]));s.set(e.slug,n),n.forEach(t=>{const n=a.get(t)||[];n.push(e.slug),a.set(t,n)})});let h=null,m="",L=null,I=null,M=new Set,P=new Set,B=new Set,D=new Map,A=null,Y=null,X=new Set,N=new Set,T=null,j=1,R=0,V=0,\$=1,H=.1,O=0,F=0,W=null,U=null,G=!1,_=!0,q=0,z=Math.max(1,Math.floor(window.devicePixelRatio||1)),K=1,J=1,Z=50;const Q={down:!1,moved:!1,startX:0,startY:0,startPanX:0,startPanY:0},ee={active:!1,startX1:0,startY1:0,startX2:0,startY2:0,startPanX:0,startPanY:0,startDist:0,startZoom:0,anchorX:null,anchorY:null},te={active:!1,velocityX:0,velocityY:0,lastSampleX:0,lastSampleY:0,lastSampleTime:0,lastFrameTime:0},ne=e.canvas.getContext("2d"),ae=Boolean(ne);let se=!1,re=!1,ie=!1,oe=null,ce=null,le=null,de=!1;const ue="function"==typeof window.matchMedia?window.matchMedia("(prefers-reduced-motion: reduce)"):null;let pe={runtime:"#10b981",runtimeHighlight:"#34d399",dev:"#f59e0b",devHighlight:"#fcd34d",transitive:"#06b6d4",transitiveHighlight:"#67e8f9",edge:"#64748b",highlight:"#22d3ee",muted:"#64748b",ringHigh:"#ef4444",ringModerate:"#f59e0b",label:"#e8edf5",backgroundPrimary:"#0c1222"};function he(){const e=p("--graph-direct-runtime")||"#10b981",t=p("--graph-direct-dev")||"#f59e0b",n=p("--graph-transitive")||"#06b6d4";pe={runtime:e,runtimeHighlight:u(e,.2,"#34d399"),dev:t,devHighlight:u(t,.28,"#fcd34d"),transitive:n,transitiveHighlight:u(n,.38,"#67e8f9"),edge:p("--graph-edge")||"#64748b",highlight:p("--graph-highlight")||"#22d3ee",muted:p("--graph-muted")||"#64748b",ringHigh:p("--graph-vuln-high")||"#ef4444",ringModerate:p("--graph-vuln-medium")||"#f59e0b",label:p("--text-primary")||"#e8edf5",backgroundPrimary:p("--bg-primary")||"#0c1222"}}function ge(){if(de)return;de=!0,console.warn("Dependency Radar: unable to initialize 2D canvas; graph rendering disabled."),e.controlsRoot.classList.add("hidden"),e.workspaceWrap.classList.add("hidden"),e.canvas.style.display="none";const t=document.createElement("div");t.className="empty-state";const n=document.createElement("div");n.className="empty-state-text",n.textContent="Graph view is unavailable in this browser context.",t.appendChild(n),e.canvasHost.appendChild(t)}function me(e){return(e-R)/j}function ve(e){return(e-V)/j}function fe(e,t){if(!h)return{x:e,y:t};const n=h.bounds.minX-120,a=h.bounds.maxX+120,s=h.bounds.minY-90,r=h.bounds.maxY+90,i=Math.min(.22*K,220),c=Math.min(.22*J,180),l=i-a*j,d=K-i-n*j,u=c-r*j,p=J-c-s*j;return{x:l>d? .5*(l+d):o(e,l,d),y:u>p? .5*(u+p):o(t,u,p)}}function ye(e,t){const n=fe(e,t);R=n.x,V=n.y}function ke(){W=null,U=null}function be(e,t,n){Ee(),ke();const a=o(e,H,r),s=me(t),i=ve(n);j=a,ye(t-s*j,n-i*j),_=!0,ze()}function we(e,t){Ee(),ke(),ye(R+e,V+t),_=!0,ze()}function Ce(){return!ue?.matches}function Ee(){te.active=!1,te.velocityX=0,te.velocityY=0,te.lastFrameTime=0}function xe(e,t,n){te.lastSampleX=e,te.lastSampleY=t,te.lastSampleTime=n}function Se(e,t,n){const a=n-te.lastSampleTime;if(a<=0)return void xe(e,t,n);const s=(e-te.lastSampleX)/a,r=(t-te.lastSampleY)/a;te.velocityX+=.22*(s-te.velocityX),te.velocityY+=.22*(r-te.velocityY),xe(e,t,n)}function Le(){Ce()?Math.hypot(te.velocityX,te.velocityY)<.08?Ee():(te.active=!0,te.lastFrameTime=performance.now(),Ve(!1),ze()):Ee()}function Ie(){const t=e.canvasHost.getBoundingClientRect();K=Math.max(1,Math.floor(t.width)),J=Math.max(1,Math.floor(t.height)),z=Math.max(1,Math.floor(window.devicePixelRatio||1)),e.canvas.width=K*z,e.canvas.height=J*z,e.canvas.style.width=\`\${K}px\`,e.canvas.style.height=\`\${J}px\`;const n=e.canvasHost.querySelector(".graph-overlay-top");Z=n?Math.ceil(n.getBoundingClientRect().height):50,e.canvasHost.style.setProperty("--graph-toolbar-height",\`\${Z}px\`),_=!0,ze()}function Me(){if(!h)return;const e=h.bounds;let t=e.maxX;ne&&(ne.save(),ne.font=i,h.nodes.forEach(e=>{const n=d(e);if(!n)return;const a=ne.measureText(n).width;t=Math.max(t,e.baseX+e.radius+6+a)}),ne.restore());const n=Math.max(1,e.maxY-e.minY),a=Math.max(1,K-32),s=Math.max(1,J-Z-24),c=a/Math.max(1,t-e.minX),l=s/n;\$=o(Math.min(c,l),.05,r),H=o(.64*\$,.05,r),O=16+.5*(a-Math.max(1,t-e.minX)*\$)-e.minX*\$,F=Z+12+.5*(s-n*\$)-e.minY*\$}function Pe(t,n){if(!h)return null;const a=e.canvas.getBoundingClientRect();if(t<a.left||t>a.right||n<a.top||n>a.bottom)return null;const s=me(t-a.left),r=ve(n-a.top);let i=null,o=1/0;return h.nodes.forEach(e=>{const t=s-e.renderX,n=r-e.renderY,a=Math.sqrt(t*t+n*n);a<=e.renderRadius+5&&a<o&&(o=a,i=e)}),i}function Be(t){e.canvas.classList.toggle("is-clickable",t&&!Q.down&&!ee.active)}function De(t=!1){Be(!1),t&&e.canvas.classList.remove("is-panning")}function Ae(e,t){const n=Pe(e,t);return He(n?n.slug:null),Be(Boolean(n)),n}function Ye(e){const r=n.get(e);if(!r)return null;const i=new Set(r.directDependencies.filter(e=>Boolean(t.dependencies[e]))),o=new Set(r.directDevDependencies.filter(e=>Boolean(t.dependencies[e]))),d=new Set([...i,...o]);0===d.size&&Object.keys(t.dependencies).filter(e=>0===(a.get(e)||[]).length).slice(0,40).forEach(e=>{d.add(e)});const u=new Set,p=[...d];let h=0;for(;h<p.length;){const e=p[h++];e&&(u.has(e)||t.dependencies[e]&&(u.add(e),(s.get(e)||[]).forEach(e=>{u.has(e)||p.push(e)})))}if(0===u.size)return null;const g=new Map;u.forEach(e=>{const n=i.has(e)?"direct-runtime":o.has(e)?"direct-dev":"transitive",a=Array.from(t.dependencies[e].name);g.set(e,{slug:e,ref:t.dependencies[e],labelGraphemes:a,parents:new Set,children:new Set,depth:Number.POSITIVE_INFINITY,order:0,amplification:0,kind:n,baseX:0,baseY:0,targetX:0,targetY:0,renderX:0,renderY:0,radius:8,targetRadius:8,renderRadius:8,targetLabelChars:c(a),renderLabelChars:l(a)})}),g.forEach(e=>{(a.get(e.slug)||[]).forEach(t=>{g.has(t)&&e.parents.add(t)}),(s.get(e.slug)||[]).forEach(t=>{g.has(t)&&e.children.add(t)})});const m=[];for(d.forEach(e=>{const t=g.get(e);t&&(t.depth=0,m.push(e))});m.length>0;){const e=m.shift();if(!e)continue;const t=g.get(e);t&&t.children.forEach(e=>{const n=g.get(e);if(!n)return;const a=t.depth+1;a>=n.depth||(n.depth=a,m.push(e))})}g.forEach(e=>{if(Number.isFinite(e.depth))return;let t=Number.POSITIVE_INFINITY;e.parents.forEach(e=>{const n=g.get(e);n&&Number.isFinite(n.depth)&&(t=Math.min(t,n.depth+1))}),e.depth=Number.isFinite(t)?t:0});const v=[...g.values()].reduce((e,t)=>Math.max(e,t.depth),0),f=Array.from({length:v+1},()=>[]);g.forEach(e=>{f[e.depth].push(e.slug)});const y=[];g.forEach(e=>{e.children.forEach(t=>{y.push({from:e.slug,to:t,direct:0===e.depth})})});const k={workspaceName:e,nodes:g,edges:y,layers:f,directRuntime:i,directDev:o,directAll:new Set([...i,...o]),bounds:{minX:0,maxX:1,minY:0,maxY:1}};return Xe(k),Ne(k),k}function Xe(e){e.nodes.forEach(e=>{e.amplification=0}),e.nodes.forEach(t=>{if(0!==t.depth)return;if(!e.directAll.has(t.slug))return;const n=new Set,a=[...t.children];for(;a.length>0;){const s=a.pop();if(!s)continue;if(s===t.slug)continue;if(n.has(s))continue;n.add(s);const r=e.nodes.get(s);r&&r.children.forEach(e=>{n.has(e)||a.push(e)})}t.amplification=n.size})}function Ne(e){const t=new Map;e.layers.forEach((n,a)=>{0===a?n.sort((t,n)=>{const a=e.nodes.get(t),s=e.nodes.get(n);if(!a&&!s)return 0;if(!a)return 1;if(!s)return-1;if(a.amplification!==s.amplification)return s.amplification-a.amplification;if(a.kind!==s.kind){if("direct-runtime"===a.kind)return-1;if("direct-runtime"===s.kind)return 1}return a.ref.name.localeCompare(s.ref.name)}):n.sort((n,a)=>{const s=e.nodes.get(n),r=e.nodes.get(a);if(!s&&!r)return 0;if(!s)return 1;if(!r)return-1;const i=(()=>{let e=0,n=0;return s.parents.forEach(a=>{const s=t.get(a);"number"==typeof s&&(e+=1,n+=s)}),e>0?n/e:Number.MAX_SAFE_INTEGER})(),o=(()=>{let e=0,n=0;return r.parents.forEach(a=>{const s=t.get(a);"number"==typeof s&&(e+=1,n+=s)}),e>0?n/e:Number.MAX_SAFE_INTEGER})();return i!==o?i-o:s.ref.name.localeCompare(r.ref.name)}),n.forEach((e,n)=>{t.set(e,n)})});const n=e.layers.reduce((e,t)=>Math.max(e,t.length),1);e.bounds={minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY},e.layers.forEach((t,a)=>{const s=Math.max(0,43*(t.length-1)),r=64+.5*(43*n-s);t.forEach((t,n)=>{const s=e.nodes.get(t);if(!s)return;s.order=n,s.baseX=96+240*a,s.baseY=r+43*n,s.targetX=s.baseX,s.targetY=s.baseY,s.renderX=s.baseX,s.renderY=s.baseY;const i=.55*Math.log(s.children.size+s.parents.size+1),o=0===s.depth&&e.directAll.has(s.slug)?1.05*Math.log(s.amplification+1):0;s.radius=6.7+i+o,s.targetRadius=s.radius,s.renderRadius=s.radius,s.targetLabelChars=c(s.labelGraphemes),s.renderLabelChars=l(s.labelGraphemes),e.bounds.minX=Math.min(e.bounds.minX,s.baseX),e.bounds.maxX=Math.max(e.bounds.maxX,s.baseX),e.bounds.minY=Math.min(e.bounds.minY,s.baseY),e.bounds.maxY=Math.max(e.bounds.maxY,s.baseY)})}),Number.isFinite(e.bounds.minX)||(e.bounds={minX:0,maxX:1,minY:0,maxY:1})}function Te(e,t){if(!h)return;const n=o(Math.max(j,1.35*\$),H,r);j+=(n-j)*(ue?.matches?1:.35),function(e,t){const n=fe(e,t);W=n.x,U=n.y}(.46*K-e*j,.5*J-t*j)}function je(e){if(!h||!h.nodes.has(e))return;Ee(),L=e;const t=E(h,e),n=x(h,e);M=new Set([e]),t.forEach(e=>{M.add(e)}),n.forEach(e=>{M.add(e)}),P=new Set;const a=[e],s=new Set([e]);for(;a.length>0;){const e=a.pop();if(!e)continue;const t=h.nodes.get(e);t&&t.parents.forEach(t=>{P.add(y(t,e)),s.has(t)||(s.add(t),a.push(t))})}const r=[e],i=new Set([e]);for(;r.length>0;){const e=r.pop();if(!e)continue;const t=h.nodes.get(e);t&&t.children.forEach(t=>{P.add(y(e,t)),i.has(t)||(i.add(t),r.push(t))})}B=new Set(M);const c=h.nodes.get(e);c.parents.forEach(e=>{B.add(e)}),c.children.forEach(e=>{B.add(e)});const l=null===A||null===Y,d=!l&&Boolean(T)&&M.has(T);!l&&d||(A=c.renderX,Y=c.renderY),D=function(e,t,n,a){const s=new Map,r=S(e,t,"parents"),i=S(e,t,"children"),c=new Map;return s.set(t,{x:n,y:a}),M.forEach(a=>{if(a===t)return;const s=e.nodes.get(a);if(!s)return;const o=r.get(a),l=i.get(a);let d=0;"number"==typeof o&&("number"!=typeof l||o<=l)?d=-o:"number"==typeof l&&(d=l),0===d&&(d=s.baseX<n?-1:1);const u=c.get(d)||[];u.push(s),c.set(d,u)}),c.forEach((e,t)=>{e.sort((e,n)=>{const a=t<0?r.get(e.slug)||0:i.get(e.slug)||0,s=t<0?r.get(n.slug)||0:i.get(n.slug)||0;return a!==s?a-s:e.baseY!==n.baseY?e.baseY-n.baseY:e.ref.name.localeCompare(n.ref.name)});const c=o(760/Math.max(1,e.length-1),34,54),l=a-(e.length-1)*c*.5;e.forEach((e,a)=>{const r=170*(1+.78*Math.max(0,Math.abs(t)-1));s.set(e.slug,{x:n+Math.sign(t)*r,y:l+a*c})})}),s}(h,e,A??c.renderX,Y??c.renderY),Te(A??c.renderX,Y??c.renderY),_=!0,ze()}function Re(){L=null,M=new Set,P=new Set,B=new Set,D=new Map,A=null,Y=null,ke(),_=!0,ze()}function Ve(e=!0){I=null,X=new Set,N=new Set,e&&(_=!0,ze())}function \$e(){if(!h)return;const e=L&&h.nodes.get(L)||null;h.nodes.forEach(t=>{t.targetRadius=function(e){const t=L===e.slug,n=M.has(e.slug);let a=e.radius;t?a*=1.85:L&&n?a*=1.22:L&&!n?a*=.84:I&&X.has(e.slug)?a*=1.1:I&&(a*=.9);return a}(t),t.targetLabelChars=c(t.labelGraphemes,Boolean(L)&&M.has(t.slug)||!L&&Boolean(I)&&X.has(t.slug));const n=D.get(t.slug);if(e&&n)return t.targetX=n.x,void(t.targetY=n.y);if(!e||!B.has(t.slug))return t.targetX=t.baseX,void(t.targetY=t.baseY);const a=t.baseX-e.baseX,s=t.baseY-e.baseY,r=1+120/(Math.sqrt(a*a+s*s)+1);t.targetX=e.baseX+a*r,t.targetY=e.baseY+s*r})}function He(e){if(L)return;if(I=e,X=new Set,N=new Set,!h||!e||!h.nodes.has(e))return _=!0,void ze();const t=E(h,e),n=x(h,e);X=new Set([e]),t.forEach(e=>{X.add(e)}),n.forEach(e=>{X.add(e)});const a=h.nodes.get(e);a&&(a.parents.forEach(e=>{X.add(e)}),a.children.forEach(e=>{X.add(e)})),h.edges.forEach(e=>{X.has(e.from)&&X.has(e.to)&&N.add(y(e.from,e.to))}),_=!0,ze()}function Oe(t){if(!h)return;const n=h.nodes.get(t);if(!n)return;const a=0===n.depth&&h.directAll.has(n.slug);T=t,e.popoverName.textContent=n.ref.name,e.popoverVersion.textContent=\`Version: \${n.ref.version}\`,e.popoverLicense.textContent=\`License: \${n.ref.license||"Unknown"}\`,e.popoverVulns.textContent=\`Vulnerabilities: \${n.ref.vulnerabilityCount||0}\`,e.popoverAmplification.textContent=a?\`Amplification: \${n.amplification}\`:\`Dependencies: \${n.children.size} • Dependents: \${n.parents.size}\`,e.popover.hidden=!1,We()}function Fe(){T=null,e.popover.hidden=!0}function We(){if(!h||!T||e.popover.hidden)return;const t=h.nodes.get(T);if(!t)return void Fe();const n=t.renderX*j+R,a=t.renderY*j+V,s=e.canvasHost.getBoundingClientRect(),r=e.popover.getBoundingClientRect(),i=Math.max(8,s.width-r.width-8),c=Math.max(8,s.height-r.height-8),l=o(n+14,8,i),d=o(a+14,8,c);e.popover.style.left=\`\${l}px\`,e.popover.style.top=\`\${d}px\`}function Ue(e){return L?M.has(e)?1:.14:I?X.has(e)?1:.16:.95}function Ge(){if(!ne)return;if(ne.setTransform(z,0,0,z,0,0),ne.clearRect(0,0,K,J),!h)return;const e=h,t=me(0)-80,n=me(K)+80,a=ve(0)-80,s=ve(J)+80;ne.setTransform(z*j,0,0,z*j,z*R,z*V);const r=pe.runtime,c=pe.dev,l=pe.transitive,u=pe.edge,p=pe.highlight,m=pe.muted,f=pe.ringHigh,k=pe.ringModerate,b=pe.label,w=pe.backgroundPrimary,C=new Set;e.nodes.forEach(e=>{const r=Math.max(e.radius,e.renderRadius);e.renderX+r>=t&&e.renderX-r<=n&&e.renderY+r>=a&&e.renderY-r<=s&&C.add(e.slug)});const E=[];let x=0;e.nodes.forEach(e=>{if(!C.has(e.slug))return;let t=0;L===e.slug?t=2:(M.has(e.slug)||X.has(e.slug))&&(t=1),E.push({node:e,priority:t,order:x++})}),E.sort((e,t)=>e.priority-t.priority||e.order-t.order);const S=Math.max(0,e.layers.length-1),B={depthNodeIndex:g(e),maxDepth:S,sameColumnXThreshold:6,minDetourVerticalSpan:80,detourInset:14,detourNodeClearance:26,paddingX:96,layerGap:240,edgeCurve:.2},D=[];e.edges.forEach(t=>{const n=e.nodes.get(t.from),a=e.nodes.get(t.to);if(!n||!a)return;if(!C.has(n.slug)&&!C.has(a.slug))return;const s=y(t.from,t.to);D.push({from:n,to:a,highlighted:P.has(s)||!L&&N.has(s),span:Math.abs(a.depth-n.depth)})}),D.sort((e,t)=>t.span-e.span),ne.globalCompositeOperation="source-over",ne.strokeStyle=L||I?m:u,ne.lineWidth=1.05,ne.globalAlpha=L||I? .04*o((j-.35)/.9,.75,1):.25*o((j-.35)/.9,.2,1),ne.beginPath(),D.forEach(e=>{e.highlighted||v(ne,e,B,Boolean(L))}),ne.stroke(),ne.globalCompositeOperation="lighter",ne.strokeStyle=p,ne.lineWidth=1.2,ne.globalAlpha=.36*o((j-.35)/.9,.2,1),ne.beginPath(),D.forEach(e=>{e.highlighted&&v(ne,e,B,Boolean(L))}),ne.stroke(),ne.globalCompositeOperation="source-over";const A=e=>{const t=L===e.slug,n=e.renderRadius;ne.globalAlpha=1,ne.fillStyle=w,ne.beginPath(),ne.arc(e.renderX,e.renderY,n,0,2*Math.PI),ne.fill(),ne.globalAlpha=Ue(e.slug);const a=ne.createRadialGradient(e.renderX-.3*n,e.renderY-.3*n,0,e.renderX,e.renderY,1.2*n);"direct-runtime"===e.kind?(a.addColorStop(0,pe.runtimeHighlight),a.addColorStop(1,r)):"direct-dev"===e.kind?(a.addColorStop(0,pe.devHighlight),a.addColorStop(1,c)):(a.addColorStop(0,pe.transitiveHighlight),a.addColorStop(1,l)),ne.fillStyle=a,ne.beginPath(),ne.arc(e.renderX,e.renderY,n,0,2*Math.PI),ne.fill(),t&&(ne.globalAlpha=.95,ne.strokeStyle=p,ne.lineWidth=1.5,ne.beginPath(),ne.arc(e.renderX,e.renderY,n+4,0,2*Math.PI),ne.stroke())},Y=e=>{if(!e.ref.vulnerabilityCount||e.ref.vulnerabilityCount<=0)return;if("none"===e.ref.vulnerabilitySeverity)return;const t=e.renderRadius,n="high"===e.ref.vulnerabilitySeverity?f:k;var a;ne.save(),ne.translate(e.renderX,e.renderY),ne.globalAlpha=(a=e.slug,L?M.has(a)? .78:.11:I?X.has(a)? .76:.12:.8),ne.strokeStyle=n;const s=t/e.radius,r=t/3*1.2/12,i=1.2*r+3*(s-1),o=Math.max(.5*r,.15),c=Math.max(1*r,.3),l=Math.max(3*r,.8),d=Math.max(1*r,.3),u=Math.max(.5*r,.15),p=t+(2+6*(s-1))+o/2,h=p+o/2+i+c/2,g=h+c/2+i+l/2,m=g+l/2+i+d/2,v=m+d/2+i+u/2;ne.setLineDash([]),ne.lineWidth=u,ne.beginPath(),ne.arc(0,0,v,0,2*Math.PI),ne.stroke(),ne.lineWidth=d,ne.beginPath(),ne.arc(0,0,m,0,2*Math.PI),ne.stroke(),ne.lineWidth=l,ne.beginPath(),ne.arc(0,0,g,0,2*Math.PI),ne.stroke(),ne.lineWidth=c,ne.beginPath(),ne.arc(0,0,h,0,2*Math.PI),ne.stroke(),ne.lineWidth=o,ne.beginPath(),ne.arc(0,0,p,0,2*Math.PI),ne.stroke(),ne.restore()};for(const i of[0,1,2])E.forEach(({node:e,priority:t})=>{t===i&&A(e)}),E.forEach(({node:e,priority:t})=>{t===i&&Y(e)});ne.textBaseline="middle",ne.font=i,ne.fillStyle=b,E.forEach(({node:e})=>{(e=>{const t=d(e);t&&(ne.globalAlpha=Ue(e.slug),ne.fillText(t,e.renderX+e.renderRadius+6,e.renderY))})(e)}),ne.globalAlpha=1,We()}function _e(){if(!G)return void(q=0);\$e();const e=function(){if(!h)return!1;let e=!1;const t=ue?.matches;return h.nodes.forEach(n=>{if(t)return n.renderX=n.targetX,n.renderY=n.targetY,n.renderRadius=n.targetRadius,void(n.renderLabelChars=n.targetLabelChars);const a=L? .18:.15;n.renderX+=(n.targetX-n.renderX)*a,n.renderY+=(n.targetY-n.renderY)*a,n.renderRadius+=.18*(n.targetRadius-n.renderRadius),n.renderLabelChars+=.32*(n.targetLabelChars-n.renderLabelChars),Math.abs(n.targetX-n.renderX)<.06&&Math.abs(n.targetY-n.renderY)<.06&&Math.abs(n.targetRadius-n.renderRadius)<.04&&Math.abs(n.targetLabelChars-n.renderLabelChars)<.12||(e=!0)}),e}(),t=function(e){if(!te.active)return!1;if(!Ce())return Ee(),!1;const t=o(e-te.lastFrameTime||16,1,32);te.lastFrameTime=e,ye(R+te.velocityX*t,V+te.velocityY*t);const n=Math.exp(-.0042*t);return te.velocityX*=n,te.velocityY*=n,_=!0,!(Math.hypot(te.velocityX,te.velocityY)<.02&&(Ee(),1))}(performance.now()),n=null!==W&&null!==U&&(ue?.matches?(ye(W,U),ke(),_=!0,!1):(R+=.12*(W-R),V+=.12*(U-V),ye(R,V),Math.abs((W??R)-R)<.35&&Math.abs((U??V)-V)<.35?(ye(W,U),ke(),_=!0,!1):(_=!0,!0)));if(_||e||t||n)return Ge(),_=!1,void(q=G&&(_||e||t||n)?window.requestAnimationFrame(_e):0);q=0}function qe(){G&&!q&&_&&(q=window.requestAnimationFrame(_e))}function ze(){_=!0,G&&qe()}function Ke(e){const t=Ye(e);t&&(Ee(),m=e,h=t,Re(),Fe(),I=null,X=new Set,N=new Set,De(!0),h&&(Ee(),ke(),Me(),j=\$,ye(O,F)),_=!0,ze())}function Je(t){0===t.button&&(Ee(),ke(),Q.down=!0,Q.moved=!1,Q.startX=t.clientX,Q.startY=t.clientY,Q.startPanX=R,Q.startPanY=V,xe(t.clientX,t.clientY,t.timeStamp),De(),e.canvas.classList.add("is-panning"))}function Ze(e){if(!Q.down)return void Ae(e.clientX,e.clientY);const t=e.clientX-Q.startX,n=e.clientY-Q.startY;(Math.abs(t)>2||Math.abs(n)>2)&&(Q.moved=!0),ye(Q.startPanX+t,Q.startPanY+n),Se(e.clientX,e.clientY,e.timeStamp),ze()}function Qe(t){if(!Q.down)return;e.canvas.classList.remove("is-panning");const n=Q.moved;if(Q.down=!1,Q.moved=!1,n)return Le(),te.active?void Be(!1):void Ae(t.clientX,t.clientY);const a=Ae(t.clientX,t.clientY);if(!a)return Ve(!1),Re(),void Fe();je(a.slug),Oe(a.slug)}function et(t){if(!e.canvasHost.contains(t.target))return;t.preventDefault(),Ee();const n=e.canvas.getBoundingClientRect(),a=t.clientX-n.left,s=t.clientY-n.top,r=t.ctrlKey||t.metaKey? .015*t.deltaY:.002*t.deltaY,i=Math.exp(-r);be(j*i,a,s)}function tt(t){if(0===t.touches.length)return;t.preventDefault(),Ee(),ke(),De();const n=e.canvas.getBoundingClientRect();if(1===t.touches.length)ee.active=!0,Q.moved=!1,ee.startX1=t.touches[0].clientX,ee.startY1=t.touches[0].clientY,ee.startPanX=R,ee.startPanY=V,xe(t.touches[0].clientX,t.touches[0].clientY,t.timeStamp),e.canvas.classList.add("is-panning");else if(2===t.touches.length){ee.active=!0,Q.moved=!1,ee.startX1=t.touches[0].clientX,ee.startY1=t.touches[0].clientY,ee.startX2=t.touches[1].clientX,ee.startY2=t.touches[1].clientY;const e=ee.startX2-ee.startX1,a=ee.startY2-ee.startY1;ee.startDist=Math.sqrt(e*e+a*a),ee.startZoom=j;const s=(ee.startX1+ee.startX2)/2,r=(ee.startY1+ee.startY2)/2,i=s-n.left,o=r-n.top;ee.anchorX=i,ee.anchorY=o}}function nt(e){if(ee.active)if(e.preventDefault(),1===e.touches.length){const t=e.touches[0].clientX-ee.startX1,n=e.touches[0].clientY-ee.startY1;(Math.abs(t)>2||Math.abs(n)>2)&&(Q.moved=!0),ye(ee.startPanX+t,ee.startPanY+n),Se(e.touches[0].clientX,e.touches[0].clientY,e.timeStamp),ze()}else if(2===e.touches.length){Ee(),Q.moved=!0;const t=e.touches[0].clientX,n=e.touches[0].clientY,a=e.touches[1].clientX-t,s=e.touches[1].clientY-n,r=Math.sqrt(a*a+s*s);if(ee.startDist>0){const e=r/ee.startDist;be(ee.startZoom*e,ee.anchorX??K/2,ee.anchorY??J/2)}}}function at(e){if(ee.active){if(e.preventDefault(),"touchcancel"===e.type)return Ee(),De(!0),ee.active=!1,ee.anchorX=null,ee.anchorY=null,void(Q.moved=!1);if(0===e.touches.length){if(De(!0),ee.active=!1,ee.anchorX=null,ee.anchorY=null,Q.moved||1!==e.changedTouches.length)Q.moved&&Le();else{const t=Pe(e.changedTouches[0].clientX,e.changedTouches[0].clientY);t?(je(t.slug),Oe(t.slug)):(Ve(!1),Re(),Fe())}Q.moved=!1}else 1===e.touches.length&&(ee.startX1=e.touches[0].clientX,ee.startY1=e.touches[0].clientY,ee.startPanX=R,ee.startPanY=V,xe(e.touches[0].clientX,e.touches[0].clientY,e.timeStamp))}}function st(){He(null),De()}function rt(t){if(!G)return;const n=t.target;e.popover.hidden||e.popover.contains(n)||e.canvasHost.contains(n)||Fe()}function it(e){const t=e.target.closest("button[data-action]");if(!t)return;const n=t.dataset.action;n&&("zoom-in"!==n?"zoom-out"!==n?"pan-left"!==n?"pan-right"!==n?"pan-up"!==n?"pan-down"!==n?"reset"===n&&(Ee(),j=\$,ye(O,F),Re(),Fe(),ze()):we(0,52):we(0,-52):we(52,0):we(-52,0):be(j/1.18,.5*K,.5*J):be(1.18*j,.5*K,.5*J))}function ot(){T&&e.onOpenList(T)}function ct(){Ke(e.workspaceSelect.value)}function lt(){G&&(Ie(),K<=1||J<=1||(Me(),j=o(j,H,r),ye(R,V),ze()))}function dt(){ie||(e.workspaceSelect.addEventListener("change",ct),ie=!0),re||(e.controlsRoot.addEventListener("click",it),e.popoverOpenButton.addEventListener("click",ot),re=!0)}return{initGraphView:function(){const a=t.workspaces.length?t.workspaces:[{name:"root",directDependencies:[],directDevDependencies:[]}],s=a.find(e=>"root"===e.name),r=s?[s,...a.filter(e=>"root"!==e.name)]:a;e.workspaceSelect.textContent="",r.forEach((t,n)=>{const a=document.createElement("option");if(a.value=t.name,a.textContent="root"===t.name?"Workspace root":t.name,e.workspaceSelect.appendChild(a),"root"===t.name&&r.length>1&&0===n){const t=document.createElement("option");t.disabled=!0,t.textContent="──────────────",e.workspaceSelect.appendChild(t)}}),e.workspaceWrap.classList.toggle("hidden",a.length<=1),n.has("root")||1!==a.length||n.set("root",a[0]),m=r[0].name,e.workspaceSelect.value=m,he(),function(){if(oe&&oe.disconnect(),oe=new MutationObserver(()=>{he(),ze()}),oe.observe(document.documentElement,{attributes:!0,attributeFilter:["class","data-theme"]}),ce&&(ce.disconnect(),ce=null),le&&(window.removeEventListener("resize",le),le=null),"undefined"!=typeof ResizeObserver)return ce=new ResizeObserver(lt),void ce.observe(e.canvasHost);le=lt,window.addEventListener("resize",le)}(),dt(),ae?(Ie(),Ke(m)):ge()},buildWorkspaceGraph:Ye,computeAmplification:Xe,layoutGraph:Ne,renderLoop:qe,applyFocus:je,clearFocus:Re,showPopover:Oe,hidePopover:Fe,switchWorkspace:Ke,setActive:function(t){if(G=t,G)return ae?(!se&&ae&&(e.canvas.addEventListener("mousedown",Je),window.addEventListener("mousemove",Ze),window.addEventListener("mouseup",Qe),e.canvas.addEventListener("wheel",et,{passive:!1}),e.canvas.addEventListener("touchstart",tt,{passive:!1}),window.addEventListener("touchmove",nt,{passive:!1}),window.addEventListener("touchend",at,{passive:!1}),window.addEventListener("touchcancel",at,{passive:!1}),e.canvas.addEventListener("mouseleave",st),document.addEventListener("mousedown",rt),se=!0),Ie(),K>1&&J>1&&(Me(),j=o(j,H,r),ye(R,V)),qe(),void ze()):void ge();se&&(e.canvas.removeEventListener("mousedown",Je),window.removeEventListener("mousemove",Ze),window.removeEventListener("mouseup",Qe),e.canvas.removeEventListener("wheel",et),e.canvas.removeEventListener("touchstart",tt),window.removeEventListener("touchmove",nt),window.removeEventListener("touchend",at),window.removeEventListener("touchcancel",at),e.canvas.removeEventListener("mouseleave",st),document.removeEventListener("mousedown",rt),De(!0),Q.down=!1,Q.moved=!1,ee.active=!1,ee.anchorX=null,ee.anchorY=null,Ee(),se=!1),Ee(),q&&(window.cancelAnimationFrame(q),q=0)},requestRender:ze}}var I={permissive:["MIT","ISC","BSD-2-Clause","BSD-3-Clause","Apache-2.0","Unlicense","0BSD","CC0-1.0","BSD","Apache","Apache 2.0","Apache License 2.0","MIT License","ISC License"],weakCopyleft:["LGPL-2.1","LGPL-3.0","LGPL-2.0","LGPL","MPL-2.0","MPL-1.1","MPL","EPL-1.0","EPL-2.0","EPL"],strongCopyleft:["GPL-2.0","GPL-3.0","GPL","AGPL-3.0","AGPL","GPL-2.0-only","GPL-3.0-only","GPL-2.0-or-later","GPL-3.0-or-later"]},M={"network-access":"Accesses the network during install","dynamic-exec":"Uses dynamic execution","child-process":"Spawns child processes",encoding:"Uses encoding/decoding logic",obfuscated:"Contains obfuscated/minified install logic","reads-env":"Reads environment variables","reads-home":"Reads user home directory","uses-ssh":"Uses SSH configuration/keys"},P={"bundled-dependencies":"Declares bundled dependencies","embedded-shrinkwrap":"Contains embedded npm-shrinkwrap.json"},B={"recent-package":"Recently created package","recent-version":"Recently published installed version","low-release-history":"Low release history","reactivated-package":"Reactivated after dormancy","old-major-new-patch":"Recent patch on older major line"};function D(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}function A(e){const t=e.compliance.license,n=t.declared?.valid?t.declared.spdxId:void 0,a=t.inferred?.spdxId;return n?{value:n,isInferred:!1}:a?{value:a,isInferred:!0}:{value:"Unknown",isInferred:!1}}function Y(e){const t=e.security;if(t?.summary)return{summary:t.summary,advisories:t.advisories};if(t?.vulnerabilities){const e=t.vulnerabilities;return{summary:{critical:Number(e.critical||0),high:Number(e.high||0),moderate:Number(e.moderate||0),low:Number(e.low||0),highest:e.highest||"none",risk:t.vulnRisk||t.risk||"green"},advisories:t.advisories}}return{summary:{critical:0,high:0,moderate:0,low:0,highest:"none",risk:"green"},advisories:t?.advisories}}function X(e){return e?.highest||"none"}function N(e){return e&&e.risk||"green"}var T={permissive:"green",weakCopyleft:"amber",strongCopyleft:"red",unknown:"gray"},j={none:0,low:1,moderate:2,high:3,critical:4},R=[{id:"type",label:"Type",sortKey:"type",getValue:e=>e.usage.direct?"Dependency":"Sub-Dependency",getTone:e=>e.usage.direct?"green":"amber",sortFn:(e,t)=>e.usage.direct===t.usage.direct?0:e.usage.direct?-1:1},{id:"scope",label:"Scope",sortKey:"scope",getValue:e=>{return"runtime"===(t=e.usage.scope)?"Runtime":"dev"===t?"Dev":"optional"===t?"Optional":"peer"===t?"Peer":t;var t},getTone:e=>"runtime"===e.usage.scope?"green":"dev"===e.usage.scope||"optional"===e.usage.scope?"amber":"gray",sortFn:(e,t)=>e.usage.scope.localeCompare(t.usage.scope)},{id:"license",label:"License",sortKey:"license",getValue:e=>{const t=A(e),n=t.isInferred?\`\${t.value} (inferred)\`:t.value;return"mismatch"===e.compliance.license.status?\`\${n} *\`:n},getTone:e=>{const t=function(e){if(!e)return"unknown";const t=e.toUpperCase();for(const[n,a]of Object.entries(I))if(a.some(e=>t.includes(e.toUpperCase())))return n;return"unknown"}(A(e).value);return T[t]},sortFn:(e,t)=>{const n=A(e).value,a=A(t).value;return n.localeCompare(a)}},{id:"vulns",label:"Vulnerabilities",sortKey:"severity",getValue:e=>D(X(Y(e).summary)),getTone:e=>Y(e).summary.risk,sortFn:(e,t)=>j[X(Y(t).summary)]-j[X(Y(e).summary)]},{id:"install",label:"Install",sortKey:"install",getValue:e=>{return(t=e.execution)?D(t.risk||"low"):"Low";var t},getTone:e=>N(e.execution),sortFn:(e,t)=>{const n={green:0,amber:1,red:2},a=N(e.execution),s=N(t.execution);return n[a]-n[s]}},{id:"maintenance",label:"Maintenance",sortKey:"maintenance",getValue:e=>\$(e.maintenance?.status),getTone:e=>{return t=e.maintenance?.status,"deprecated"===t||"archived"===t?"red":"unmaintained"===t||"stale"===t?"amber":"active"===t?"green":"gray";var t},sortFn:(e,t)=>H(t.maintenance?.status)-H(e.maintenance?.status)}],V={deprecated:"Deprecated",archived:"Archived",unmaintained:"Unmaintained",stale:"Stale",active:"Active",unknown:"—"};function \$(e){return e&&V[e]||"—"}function H(e){return e&&{deprecated:5,archived:4,unmaintained:3,stale:2,active:1}[e]||0}function O(e){const t=e.maintenance?.status;return"deprecated"===t||"archived"===t||"unmaintained"===t||"stale"===t}function F(e){return"green"!==e.compliance.licenseRisk}function W(e){return Boolean(e.upgrade.blocksNodeMajor||e.upgrade.blockers?.length)}var U=R.length;function G(e){if(!e)return"unknown";const t=e.toUpperCase();for(const[n,a]of Object.entries(I))if(a.some(e=>t.includes(e.toUpperCase())))return n;return"unknown"}function _(e){const t=e.compliance.license,n=t.declared?.valid?t.declared.spdxId:void 0,a=t.inferred?.spdxId;return n?{value:n,isInferred:!1}:a?{value:a,isInferred:!0}:{value:"Unknown",isInferred:!1}}function q(e){switch(e){case"declared-only":return"Declared";case"inferred-only":return"Inferred";case"match":return"Declared + Inferred (match)";case"mismatch":return"Declared + Inferred (mismatch)";case"invalid-spdx":return"Invalid SPDX";default:return"Unknown"}}var z={none:0,low:1,moderate:2,high:3,critical:4};function K(e){const t=e.security;if(t?.summary)return{summary:t.summary,advisories:t.advisories};if(t?.vulnerabilities){const e=t.vulnerabilities;return{summary:{critical:Number(e.critical||0),high:Number(e.high||0),moderate:Number(e.moderate||0),low:Number(e.low||0),highest:e.highest||"none",risk:t.vulnRisk||t.risk||"green"},advisories:t.advisories}}return{summary:{critical:0,high:0,moderate:0,low:0,highest:"none",risk:"green"},advisories:t?.advisories}}function J(e){return e?"Yes":"No"}function Z(e){return e?String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):""}function Q(e){return null!=e&&("string"==typeof e?e.trim().length>0:Array.isArray(e)?e.length>0:"object"!=typeof e||Object.keys(e).length>0)}function ee(e){return Array.isArray(e)?e.map(e=>ee(e)).join(", "):"boolean"==typeof e?e?"Yes":"No":"object"==typeof e&&null!==e?Object.entries(e).filter(([,e])=>Q(e)).map(([e,t])=>Z(e)+": "+ee(t)).join("<br>"):Z(String(e))}function te(e,t){return Q(t)?'<div class="metadata-row"><div class="metadata-row-label">'+Z(e)+'</div><div class="metadata-row-value">'+ee(t)+"</div></div>":""}function ne(e,t){const n=t.filter(Boolean);return 0===n.length?"":'<section class="metadata-section"><div class="metadata-section-title">'+Z(e)+'</div><div class="metadata-grid">'+n.join("")+"</div></section>"}function ae(e){const t=e.workspaces;if(!t||!t.enabled)return ne("Workspaces",[te("Enabled",!1),te("Type",t?.type)]);const n=t.workspacePackages||[],a=n.length?'<div class="metadata-list">'+n.map(e=>'<div class="metadata-list-item"><div class="metadata-row-value">'+Z(e.name)+'</div><div class="metadata-muted">'+Z(e.relativePath)+" · runtime "+Z(String(e.directExternal.runtime))+" · dev "+Z(String(e.directExternal.dev))+"</div></div>").join("")+"</div>":"";return ne("Workspaces",[te("Enabled",t.enabled),te("Type",t.type),te("Package count",t.packageCount),a?'<div class="metadata-row"><div class="metadata-row-label">Packages</div><div>'+a+"</div></div>":""])}function se(e){const t=e.supplyChain;if(!t)return"";const n=t.signatureAudit;return ne("Supply Chain",[te("Signals",t.signals?.length),n?te("Signature audit",{attempted:n.attempted,ok:n.ok,status:n.status,error:n.error}):""])}function re(e){return"runtime"===e?"Runtime":"dev"===e?"Dev":"optional"===e?"Optional":"peer"===e?"Peer":e}function ie(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}function oe(e){return e.split(/[\\s-_]+/).map(e=>e?ie(e):e).join(" ")}function ce(e){return R.map(t=>{return n=t.label,a=t.getValue(e),'<div class="badge-card '+t.getTone(e)+'"><span class="badge-label">'+Z(n)+'</span><span class="badge-value">'+Z(a)+"</span></div>";var n,a}).join("")}function le(e,t){const n=R.map(n=>function(e,t,n,a){const s=n===e,r=s?a?" ▲":" ▼":"",i=s?a?" sorted-asc":" sorted-desc":"";return'<button type="button" class="column-header'+(s?" sorted":"")+i+'" data-sort="'+Z(e)+'"><span class="column-header-label">'+Z(t)+'</span><span class="sort-indicator">'+r+"</span></button>"}(n.sortKey,n.label,e,t)).join("");return'<div class="column-headers" style="--column-count: '+U+'">'+n+"</div>"}function de(e,t,n){let a='<div class="kv-item">';return a+='<span class="kv-label">'+Z(e)+"</span>",a+='<span class="kv-value">'+Z(String(t))+"</span>",n&&(a+='<span class="kv-hint">'+Z(n)+"</span>"),a+="</div>",a}function ue(e,t){return'<span class="kv-value risk-value"><span class="risk-dot '+t+'"></span>'+Z(String(e))+"</span>"}function pe(e,t="neutral"){return'<span class="status-chip '+t+'">'+Z(e)+"</span>"}function he(e,n,a){const s=t(n),r=e.execution?.risk||"green",i=e.upgrade.blocksNodeMajor||!!e.upgrade.blockers?.length;return'<div class="status-chip-strip">'+[pe(e.usage.direct?"Direct dependency":"Transitive dependency"),pe(re(e.usage.scope)),pe(s>0?"Vulnerability: "+oe(n.highest):"Vulnerability: None","green"===n.risk?"neutral":n.risk),pe("Licence: "+a,"green"===e.compliance.licenseRisk?"neutral":e.compliance.licenseRisk),pe("Install risk: "+Pe(r),"green"===r?"neutral":r),pe(i?"Upgrade blocker":"No upgrade blocker",i?"amber":"neutral")].join("")+"</div>"}function ge(e,t,n){let a='<div class="kv-item">';return a+='<span class="kv-label">'+Z(e)+"</span>",a+=t,n&&(a+='<span class="kv-hint">'+Z(n)+"</span>"),a+="</div>",a}function me(e,t){if(!e||0===e.length)return'<span class="kv-value">None</span>';const n=e.slice(0,t),a=e.length-t;let s='<div class="package-list">';return n.forEach(e=>{s+='<span class="package-tag">'+Z(e)+"</span>"}),a>0&&(s+='<span class="package-tag">+'+a+" more</span>"),s+="</div>",s}function ve(e,t,n,a){if(!e||0===e.length)return'<span class="kv-value">None</span>';const s=e.slice(0,t),r=e.length-t;let i='<div class="package-list">';return s.forEach(e=>{const t=Ee(e,n,a);i+=t?'<a class="package-tag package-tag-link root-package-link" href="#'+Z(be(t))+'" data-dep-key="'+Z(t)+'" aria-label="Jump to dependency '+Z(t)+'">'+Z(e)+"</a>":'<span class="package-tag">'+Z(e)+"</span>"}),r>0&&(i+='<span class="package-tag">+'+r+" more</span>"),i+="</div>",i}function fe(e,t){return e+"@"+t}var ye=new WeakMap;function ke(e){const t=e.lastIndexOf("@npm:");if(t>0)return{name:e.slice(0,t),version:e.slice(t+1)};const n=e.lastIndexOf("@");return n<=0?null:{name:e.slice(0,n),version:e.slice(n+1)}}function be(e){return\`dep-\${e}\`}function we(e){const t=ye.get(e);if(t)return t;const n=new Map;return e.forEach(e=>{const t=ke(e);if(!t)return;const a=n.get(t.name)||[];a.push(e),n.set(t.name,a)}),ye.set(e,n),n}function Ce(e,t,n){const a=((n||we(t)).get(e)||[]).filter(e=>t.has(e));return 1===a.length?a[0]:null}function Ee(e,t,n){if(t.has(e))return e;const a=ke(e);if(!a)return Ce(e,t,n);if(a.version.startsWith("npm:")){const e=a.version.slice(4),n=a.name+(e.startsWith("@")?e:"@"+e);if(t.has(n))return n}return Ce(a.name,t,n)}function xe(e,t){if(t.has(e))return e;const n=ke(e);if(!n)return null;if(n.version.startsWith("npm:")){const e=n.version.slice(4),a=n.name+(e.startsWith("@")?e:"@"+e);if(t.has(a))return a}return null}function Se(e,t,n,a){if(!e||0===e.length)return'<span class="kv-value">None</span>';const s=e.slice(0,t),r=e.length-t;let i='<div class="package-list">';return s.forEach(e=>{if("string"==typeof e){const t=Ee(e,n,a);return t?void(i+='<a class="package-tag package-tag-link root-package-link" href="#'+Z(be(t))+'" data-dep-key="'+Z(t)+'" aria-label="Jump to dependency '+Z(t)+'">'+Z(e)+"</a>"):void(i+='<span class="package-tag">'+Z(e)+"</span>")}const t=fe(e.name,e.version),s=e.name+"@"+e.version,r=Ee(t,n,a);i+=r?'<a class="package-tag package-tag-link root-package-link" href="#'+Z(be(r))+'" data-dep-key="'+Z(r)+'" aria-label="Jump to dependency '+Z(r)+'">'+Z(s)+"</a>":'<span class="package-tag">'+Z(s)+"</span>"}),r>0&&(i+='<span class="package-tag">+'+r+" more</span>"),i+="</div>",i}function Le(e,t,n){const a=e.graph.subDeps;if(!a)return"";const s=[{title:"Dependencies",key:"dep"},{title:"Optional",key:"opt"},{title:"Peer",key:"peer"},{title:"Dev Dependencies",key:"dev"}];let r=0,i=0;for(const l of s){const e=a[l.key];if(e)for(const t of Object.values(e))r+=1,t[1]&&(i+=1)}if(0===r)return"";const o='<div class="declared-summary">Total: '+r+" • Installed: "+i+" • Not installed: "+(r-i)+"</div>",c=s.map(e=>{const s=a[e.key];if(!s||0===Object.keys(s).length)return"";let r=0,i=0;const o=Object.entries(s).sort(([e],[t])=>e.localeCompare(t)).map(([e,[a,s]])=>{r+=1,s&&(i+=1);const o='<div class="declared-name">'+Z(e)+"</div>",c='<div class="declared-range">'+Z(a)+"</div>",l=s?function(e,t,n){const a=Ee(e,t,n);return a?'<a class="status-pill installed root-package-link" href="#'+Z(be(a))+'" data-dep-key="'+Z(a)+'" aria-label="Jump to dependency '+Z(a)+'">Installed</a>':'<span class="status-pill installed">Installed</span>'}(s,t,n):'<span class="status-pill missing">Not installed</span>';return'<div class="declared-row">'+o+c+l+"</div>"}),c=i+" of "+r+" installed";return['<details class="declared-group">','<summary class="declared-group-summary"><span class="expand-icon" aria-hidden="true"></span><span class="declared-group-title">'+Z(e.title)+' <span class="declared-count">('+c+")</span></span></summary>",'<div class="declared-table">'+o.join("")+"</div>","</details>"].join("")}).filter(Boolean);return Ie("Declared Dependencies","Dependencies declared by this package",o+'<div class="declared-deps">'+c.join("")+"</div>")}function Ie(e,t,n){let a='<div class="section">';return a+='<div class="section-header">',a+='<span class="section-title">'+Z(e)+"</span>",t&&(a+='<span class="section-desc">'+Z(t)+"</span>"),a+="</div>",a+=n,a+="</div>",a}function Me(e,t,n,a){let s='<div class="subsection'+(a?" "+a:"")+'">';return s+='<div class="subsection-header">',s+='<span class="subsection-title">'+Z(e)+"</span>",n&&(s+='<span class="subsection-desc">'+Z(n)+"</span>"),s+="</div>",s+=t,s+="</div>",s}function Pe(e){return"red"===e?"High":"amber"===e?"Medium":"Low"}function Be(e){return e&&0!==e.length?Me("Supply chain source",'<div class="section-note">Shown only when lockfile source metadata is unusual or incomplete.</div><div class="kv-grid">'+e.map(e=>{return de({"git-dependency":"Git dependency source","file-dependency":"Local dependency source","non-registry-tarball":"Non-registry tarball","missing-integrity":"Missing lockfile integrity","unexpected-registry-host":"Unexpected registry host"}[t=e.type]||oe(t),e.source,e.detail);var t}).join("")+"</div>","Lockfile source signals","warning"):""}function De(e){if(!e)return;const t=e.trim();if(!t)return;const n=e=>e.replace(/\\.git\$/i,"");if(/^https?:\\/\\//i.test(t))return n(t);if(/^git\\+https?:\\/\\//i.test(t))return n(t.replace(/^git\\+/,""));if(/^git:\\/\\/github\\.com\\//i.test(t))return n(t.replace(/^git:\\/\\//i,"https://"));if(/^github:/i.test(t)){const e=t.slice(7).replace(/^\\/+/,"");return e?\`https://github.com/\${n(e)}\`:void 0}if(/^git@github\\.com:/i.test(t)){const e=t.slice(15);return e?\`https://github.com/\${n(e)}\`:void 0}return/^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+\$/.test(t)?\`https://github.com/\${n(t)}\`:void 0}function Ae(e,t){const n=De(e);if(!n)return;let a;try{a=new URL(n)}catch{return}if("github.com"!==a.hostname.toLowerCase())return;const s=a.pathname.split("/").filter(Boolean);if(s.length<2)return;const r=s[0],i=s[1].replace(/\\.git\$/i,"");return r&&i?\`https://github.com/\${r}/\${i}/blob/HEAD/\${t}\`:void 0}function Ye(e,t){return t?Z(e)+' <a class="kv-inline-link" href="'+Z(t)+'" target="_blank" rel="noopener noreferrer">GitHub<svg class="kv-inline-link-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M7 17 17 7"/><path d="M9 7h8v8"/></svg></a>':Z(e)}function Xe(e){if(e)try{const t=new URL(e);if("https:"!==t.protocol&&"http:"!==t.protocol)return;return t.username="",t.password="",t.toString()}catch{return}}function Ne(e){const t='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.332h-2.669v-.001zm12.001 0h-1.33v-4h-1.336v4h-1.335v-4h-1.33v4h-2.671V8.667h8.002v5.331zM10.665 10H12v2.667h-1.335V10z"/></svg>',n='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg>',a='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',s='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>';if(!(e.npm||e.repository||e.homepage||e.issues))return"";let r='<div class="package-links">';const i=Xe(e.npm),o=Xe(e.repository),c=Xe(e.homepage),l=Xe(e.issues);return i||o||c||l?(i&&(r+='<a href="'+Z(i)+'" target="_blank" rel="noopener" class="package-link">'+t+"npm</a>"),o&&(r+='<a href="'+Z(o)+'" target="_blank" rel="noopener" class="package-link">'+n+"Repository</a>"),c&&(r+='<a href="'+Z(c)+'" target="_blank" rel="noopener" class="package-link">'+s+"Homepage</a>"),l&&(r+='<a href="'+Z(l)+'" target="_blank" rel="noopener" class="package-link">'+a+"Issues</a>"),r+="</div>",r):""}function Te(e,n,s,r){const i=K(e),o=i.summary,c=_(e),l=c.isInferred?\`\${c.value} (inferred)\`:c.value,d=function(e){const t=e.package?.links||{},n=e.links||{},a=De(t.repository||n.repository||n.repo);return{npm:t.npm||n.npm,repository:a||t.repository||n.repository||n.repo,homepage:t.homepage||n.homepage,issues:t.bugs||t.issues||n.bugs||n.issues}}(e),u=JSON.stringify(e,null,2),p=e.usage.origins.workspaces?.length?'<div class="micro-sublist"><div class="micro-subtitle">Workspaces</div>'+me(e.usage.origins.workspaces,8)+"</div>":"",h=e.package.description?'<p class="dep-description"><span>Description: </span>'+Z(e.package.description)+"</p>":"";var g,m;const v=Ie("Overview",void 0,'<div class="definition-grid">'+[de("Dependency status",e.usage.direct?"Direct dependency":"Transitive dependency"),de("Scope",re(e.usage.scope)),e.usage.introduction?de("Introduced by",oe(e.usage.introduction)):"",e.usage.runtimeImpact?de("Runtime impact",(m=e.usage.runtimeImpact,m?oe(m):"")):"",de("Dependency depth",e.usage.depth),e.usage.direct?"":ge("Introduced via root packages",Se(e.usage.origins.topRootPackages,8,n,s)),e.usage.direct?"":de("Direct roots",e.usage.origins.rootPackageCount),e.usage.direct?"":ge("Direct parents",ve(e.usage.origins.topParentPackages,8,n,s)),e.usage.direct?"":de("Direct parents count",e.usage.origins.parentPackageCount??0),de("TypeScript types",(g=e.usage.tsTypes,"bundled"===g?"Bundled":"definitelyTyped"===g?"DefinitelyTyped":"none"===g?"None":"Unknown"))].filter(Boolean).join("")+"</div>"+p+function(e,t,n,a){if(!t||0===t.length)return"";const s=t.slice(0,n),r=t.length-n;let i='<div class="detail-list">';return i+='<div class="detail-title">'+Z(e)+"</div>",i+='<ul class="detail-items'+(a?" "+a:"")+'">',s.forEach(e=>{i+='<li class="detail-item">'+Z(e)+"</li>"}),r>0&&(i+='<li class="detail-item muted">+'+r+" more</li>"),i+="</ul></div>",i}("Top import locations",e.usage.importUsage?.topFiles,5,"mono")),f=e.compliance.license,y=Ae(d.repository,"package.json"),k=Ae(d.repository,"LICENSE"),b=[ge("Primary license",ue(l,e.compliance.licenseRisk)),de("Status",q(f.status))];if(f.declared){const e=[f.declared.valid?"valid":"invalid",f.declared.expression?"expression":void 0,f.declared.deprecated?"deprecated":void 0].filter(Boolean).join(", "),t=f.exception?.id?\` WITH \${f.exception.id}\`:"";b.push(ge("Declared SPDX in package.json",'<span class="kv-value">'+Ye(\`\${f.declared.spdxId}\${t}\${e?\` (\${e})\`:""}\`,y)+"</span>"))}f.inferred&&b.push(ge("Inferred from LICENSE file",'<span class="kv-value">'+Ye(\`\${f.inferred.spdxId} (\${f.inferred.confidence})\`,k)+"</span>")),"mismatch"===f.status&&b.push(de("Mismatch","Declared SPDX and LICENSE text do not match")),"invalid-spdx"===f.status&&b.push(de("Invalid SPDX","Package.json license is not a valid SPDX identifier or expression"));const w=Me("License",'<div class="kv-grid">'+b.join("")+"</div>"),C=t(o),E=[ge("Vulnerability status",ue(0===C?"No known vulnerabilities":String(C),o.risk)),de("Highest severity","none"===o.highest?"None":oe(o.highest))],x=C>0?'<div class="kv-grid kv-grid-tight">'+[de("Critical",o.critical),de("High",o.high),de("Moderate",o.moderate),de("Low",o.low)].join("")+"</div>":"",S=function(e){if(!e||0===e.length)return"";let t='<table class="vuln-table"><thead><tr>';return t+="<th>Title</th><th>Severity</th><th>Affected range</th><th>Fix available</th><th>Reference</th>",t+="</tr></thead><tbody>",e.forEach(e=>{const n=Z(e.title),a=Xe(e.url),s=a?'<a href="'+Z(a)+'" target="_blank" rel="noopener">Link</a>':"";t+='<tr data-severity="'+Z(e.severity)+'">',t+='<td data-label="Title">'+n+"</td>",t+='<td data-label="Severity">'+Z(ie(e.severity))+"</td>",t+='<td data-label="Affected range">'+Z(e.vulnerableRange)+"</td>",t+='<td data-label="Fix available">'+Z(e.fixAvailable?"Yes":"No")+"</td>",t+='<td data-label="Reference">'+s+"</td>",t+="</tr>"}),t+="</tbody></table>",t}(i.advisories),L=Me("Vulnerabilities",['<div class="kv-grid">'+E.join("")+"</div>",x||"",S||""].join(""),"Known security issues from npm audit","vuln-block"),I=e.execution?function(e){const t=[ge("Execution risk",ue(Pe(e.risk),e.risk))];if(e.native&&t.push(de("Native build tooling detected (native)","Yes")),e.scripts?.hooks?.length&&t.push(ge("Lifecycle hooks",me(e.scripts.hooks,6))),"number"==typeof e.scripts?.complexity&&t.push(de("Heuristic complexity","Script complexity: "+e.scripts.complexity+" (complexity)")),e.scripts?.signals?.length){const n=e.scripts.signals.map(e=>\`\${M[e]} (\${e})\`);t.push(ge("Install-time signals",me(n,6)))}const n=(e.signals||[]).filter(t=>!(e.scripts?.signals||[]).includes(t));if(n.length){const e=n.map(e=>\`\${M[e]} (\${e})\`);t.push(ge("Local execution signals",me(e,6)))}return Me("Install-time execution behaviour",'<div class="section-note">Execution behaviour signals are local static review cues from lifecycle scripts, entry files, package bins, or a small bounded set of package files. They do not imply compromise.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.execution):"",D=function(e){if(!e?.signals?.length)return"";const t=[ge("Packaging signals",me(e.signals.map(e=>\`\${P[e]} (\${e})\`),6))];return e.bundledDependencies?.length&&t.push(ge("Bundled dependencies",me(e.bundledDependencies,8))),Me("Package contents",'<div class="section-note">Packaging signals describe local package structure that may warrant review; they are not malware verdicts.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.packaging),A=function(e){if(!e?.attempted)return"";const t=[de("Lookup",e.ok?"Available":"Unavailable"),ge("Candidate reasons",me(e.candidateReasons||[],6))];if(e.error&&t.push(de("Error",e.error)),e.signals?.length){const n=e.signals.map(e=>\`\${B[e]} (\${e})\`);t.push(ge("Registry signals",me(n,6)))}return e.installedVersionPublishedAt&&t.push(de("Installed version published",e.installedVersionPublishedAt)),e.packageCreatedAt&&t.push(de("Package created",e.packageCreatedAt)),"number"==typeof e.versionCount&&t.push(de("Published versions",e.versionCount)),e.latestVersion&&t.push(de("Latest dist-tag",e.latestVersion)),Me("Registry metadata",'<div class="section-note">Targeted npm registry metadata is collected only for packages that already show local review signals, and is skipped in offline scans.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.supplyChain?.registry),Y=Ie("Risk & Compliance",void 0,w+L+function(e){if(!e?.attempted)return"";const t=[de("Status",\$(e.status))];if(e.deprecated){const n=e.deprecated.installedVersion?"Installed version":"Latest version";t.push(de("Deprecated",n,e.deprecated.message))}void 0!==e.repoArchived&&t.push(de("Repository archived",J(e.repoArchived),e.repoCheckedAt?\`Checked \${e.repoCheckedAt}\`:void 0)),e.packageModifiedAt&&t.push(de("Last registry activity",e.packageModifiedAt,"number"==typeof e.monthsSinceModified?\`~\${e.monthsSinceModified} months ago\`:void 0)),e.latestVersion&&t.push(de("Latest version",e.latestVersion)),e.fetchedAt&&t.push(de("Data fetched",e.fetchedAt+(e.fromCache?" (cached)":""))),e.error&&t.push(de("Error",e.error));const n="deprecated"===e.status||"archived"===e.status?"warning":void 0;return Me("Maintenance",'<div class="section-note">Conservative registry heuristics: "last registry activity" updates on any packument write, so age-based statuses under-flag rather than over-flag. Review cues, not verdicts.</div><div class="kv-grid">'+t.join("")+"</div>",void 0,n)}(e.maintenance)+I+D+A+Be(r)),X=[de("Outdated status",(N=e.upgrade.outdatedStatus,N?"unknown"===N?"Unknown":oe(N):"Not reported"))];var N;e.upgrade.latestVersion&&X.push(de("Latest version",e.upgrade.latestVersion));const T=Me("Version",'<div class="section-note">Based on npm outdated findings and registry metadata.</div><div class="kv-grid">'+X.join("")+"</div>"),j=e.package.deprecated&&!e.maintenance?.deprecated?Me("Deprecated",'<div class="kv-grid">'+de("Deprecated","Yes","Declared by the package author.")+"</div>",void 0,"warning"):"",R=[de("Node engine constraint",e.upgrade.nodeEngine||"Any")];void 0!==e.upgrade.blocksNodeMajor&&R.push(de("Blocks Node major upgrade",J(e.upgrade.blocksNodeMajor)));const V=Me("Constraints",'<div class="kv-grid">'+R.join("")+"</div>"),H=Me("Blast radius",'<div class="kv-grid">'+[de("Used by other packages (fanIn)",e.graph.fanIn),de("Depends on packages (fanOut)",e.graph.fanOut)].join("")+"</div>"),O={nodeEngine:"Node engine constraint",peerDependency:"Peer dependency constraints",nativeBindings:"Native bindings/build tooling",installScripts:"Install lifecycle scripts",deprecated:"Deprecated by author"},F=Ie("Upgrade & Change Impact","Currency, constraints, and blast radius",T+j+V+H+('<div class="subsection"><div class="subsection-header"><span class="subsection-title">Upgrade blockers</span></div>'+(e.upgrade.blockers?.length?'<ul class="bullet-list">'+e.upgrade.blockers.map(e=>"<li>"+Z(O[e]||e)+"</li>").join("")+"</ul>":'<div class="status-row">No upgrade blockers detected</div>')+"</div>")),W=Le(e,n,s);return[Ne(d),h,he(e,o,l),(U=a(e,o),['<div class="key-points">','<div class="section-header compact"><span class="section-title">Key points</span></div>','<ul class="key-points-list">',U.map(e=>"<li>"+Z(e)+"</li>").join(""),"</ul>","</div>"].join("")),v,Y,F,W,'<details class="raw-data-toggle"><summary><span class="expand-icon" aria-hidden="true"></span>View raw data</summary><div class="raw-data-pane"><pre>'+Z(u)+'</pre><button type="button" class="copy-json-btn" aria-label="Copy raw JSON">Copy JSON</button></div></details>'].join("");var U}async function je(){const e=await async function(){const e=document.getElementById("radar-data");return e&&e.textContent&&"{}"!==e.textContent.trim()?JSON.parse(e.textContent):(await fetch("./sample-data.json")).json()}();void 0===window.__DEPENDENCY_DATA__&&(window.__DEPENDENCY_DATA__=e);const t=document.getElementById("dependency-list"),n=document.getElementById("results-summary"),a=document.getElementById("scan-status-banner");if(a&&e.scanStatus?.warnings.length){a.hidden=!1;const t=document.createElement("strong");t.textContent=e.scanStatus.complete?"Some analysis was intentionally skipped":"Scan evidence is incomplete",a.appendChild(t);const n=document.createElement("ul");e.scanStatus.warnings.slice(0,8).forEach(e=>{const t=document.createElement("li");t.textContent=e.length>300?\`\${e.slice(0,297)}…\`:e,n.appendChild(t)}),a.appendChild(n)}const r=document.getElementById("project-path");r&&(r.textContent=e.project.name||e.project.projectDir,r.title=e.project.projectDir);const i=document.getElementById("metadata-toggle"),o=document.getElementById("metadata-panel"),c=document.getElementById("formatted-date");let l=e.generatedAt||"";if(c&&e.generatedAt)try{const t=new Date(e.generatedAt);Number.isNaN(t.getTime())?(l=e.generatedAt,c.textContent=e.generatedAt):(l=new Intl.DateTimeFormat(void 0,{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"}).format(t),c.textContent=l)}catch{l=e.generatedAt,c.textContent=e.generatedAt}o&&(o.innerHTML=function(e,t){const n=e.environment||{},a=n.minRequiredMajor,s=a&&a>0?"Node requirement derived from dependency engine ranges.":"";return[ne("Report",[te("Dependency Radar",e.dependencyRadarVersion),te("Schema",e.schemaVersion),te("Generated",t||e.generatedAt),te("Generated raw",e.generatedAt)]),ne("Project",[te("Name",e.project.name),te("Version",e.project.version),te("Path",e.project.projectDir),te("Description",e.project.description),te("License",e.project.license),te("Homepage",e.project.homepage),te("Repository",e.project.repository),te("Constraints",e.project.constraints),te("Dependency policy",e.project.dependencyPolicySummary)]),ne("Git",[te("Branch",e.git?.branch)]),ne("Environment",[te("Node",n.nodeVersion),te("Runtime",n.runtimeVersion),te("Minimum required Node major",n.minRequiredMajor),te("Target Node major",n.targetNodeMajor),te("Platform",n.platform),te("Architecture",n.arch),te("CI",n.ci),te("packageManager field",n.packageManagerField),te("Package manager",n.packageManager),te("Package manager version",n.packageManagerVersion),te("Tool versions",n.toolVersions),te("Node note",s)]),ae(e),ne("Summary",[te("Dependencies",e.summary?.dependencyCount),te("Direct",e.summary?.directCount),te("Transitive",e.summary?.transitiveCount),te("Findings",e.summary?.findingCount)]),ne("Scan evidence",[te("Complete",e.scanStatus?.complete),te("Collectors",e.scanStatus?.collectors),te("Warnings",e.scanStatus?.warnings)]),se(e)].filter(Boolean).join("")}(e,l),o.hidden=!1,o.inert=!0,o.setAttribute("aria-hidden","true"));const d=e=>{i&&o&&(o.classList.toggle("open",e),o.inert=!e,o.setAttribute("aria-hidden",String(!e)),i.classList.toggle("open",e),i.setAttribute("aria-expanded",String(e)))};i?.addEventListener("click",()=>{const e=!o?.classList.contains("open");d(e)}),document.addEventListener("click",e=>{if(!i||!o)return;if(!o.classList.contains("open"))return;const t=e.target;i.contains(t)||o.contains(t)||d(!1)}),document.addEventListener("keydown",e=>{"Escape"===e.key&&d(!1)});const u={search:document.getElementById("search"),direct:document.getElementById("direct-filter"),runtime:document.getElementById("runtime-filter"),workspace:document.getElementById("workspace-filter"),workspaceWrap:document.getElementById("workspace-filter-wrap"),sort:document.getElementById("sort-by"),sortDirection:document.getElementById("sort-direction"),hasVulns:document.getElementById("has-vulns"),maintenanceConcerns:document.getElementById("maintenance-concerns"),licenseIssues:document.getElementById("license-issues"),upgradeBlockers:document.getElementById("upgrade-blockers"),themeSwitch:document.getElementById("theme-switch"),licenseToggle:document.getElementById("license-toggle"),licensePanel:document.getElementById("license-panel"),licensePermissive:document.getElementById("license-permissive"),licenseWeakCopyleft:document.getElementById("license-weak-copyleft"),licenseStrongCopyleft:document.getElementById("license-strong-copyleft"),licenseUnknown:document.getElementById("license-unknown"),licenseAll:document.getElementById("license-all"),licenseFriendly:document.getElementById("license-friendly"),filtersToggle:document.getElementById("filters-toggle"),filterCountBadge:document.getElementById("filter-count-badge"),filterControls:document.getElementById("filter-controls"),activeFiltersRow:document.getElementById("active-filters-row"),activeFilterChips:document.getElementById("active-filter-chips"),activeFilterClear:document.getElementById("active-filter-clear"),clearAllFilters:document.getElementById("clear-all-filters"),licensePermissiveLabel:document.getElementById("license-permissive-label"),licenseWeakCopyleftLabel:document.getElementById("license-weak-copyleft-label"),licenseStrongCopyleftLabel:document.getElementById("license-strong-copyleft-label"),licenseUnknownLabel:document.getElementById("license-unknown-label"),hasVulnsLabel:document.getElementById("has-vulns-label"),maintenanceConcernsLabel:document.getElementById("maintenance-concerns-label"),licenseIssuesLabel:document.getElementById("license-issues-label"),upgradeBlockersLabel:document.getElementById("upgrade-blockers-label"),columnHeadersContainer:document.getElementById("column-headers-container"),packageHeader:document.getElementById("package-header"),viewGraphButton:document.getElementById("view-graph-btn"),graphBackButton:document.getElementById("graph-back-btn"),listViewPanel:document.getElementById("list-view"),graphViewPanel:document.getElementById("graph-view"),graphWorkspaceSelect:document.getElementById("graph-workspace"),graphWorkspaceWrap:document.getElementById("graph-workspace-wrap"),graphControls:document.getElementById("graph-controls"),graphCanvas:document.getElementById("graph-canvas"),graphCanvasShell:document.getElementById("graph-canvas-shell"),graphPopover:document.getElementById("graph-popover"),graphPopoverName:document.getElementById("graph-popover-name"),graphPopoverVersion:document.getElementById("graph-popover-version"),graphPopoverLicense:document.getElementById("graph-popover-license"),graphPopoverVulns:document.getElementById("graph-popover-vulns"),graphPopoverAmplification:document.getElementById("graph-popover-amplification"),graphOpenList:document.getElementById("graph-open-list"),reportFooter:document.querySelector(".report-footer")};let p="name",h=!0,g=null,m=!1;document.documentElement.setAttribute("data-theme","dark"),"light"===localStorage.getItem("dependency-radar-theme")?(document.documentElement.classList.add("light"),u.themeSwitch.classList.add("light"),u.themeSwitch.setAttribute("aria-pressed","true"),document.documentElement.setAttribute("data-theme","light")):(document.documentElement.classList.remove("light"),u.themeSwitch.classList.remove("light"),u.themeSwitch.setAttribute("aria-pressed","false"),document.documentElement.setAttribute("data-theme","dark")),u.themeSwitch.addEventListener("click",()=>{document.documentElement.classList.toggle("light"),u.themeSwitch.classList.toggle("light");const e=document.documentElement.classList.contains("light");document.documentElement.setAttribute("data-theme",e?"light":"dark"),u.themeSwitch.setAttribute("aria-pressed",String(e)),localStorage.setItem("dependency-radar-theme",e?"light":"dark"),g?.requestRender()});const v=window.matchMedia("(max-width: 768px)");let f=v.matches;const y=e=>{u.filterControls&&u.filtersToggle&&(u.filterControls.classList.toggle("open",e),u.filterControls.inert=!e,u.filterControls.setAttribute("aria-hidden",String(!e)),u.filtersToggle.classList.toggle("open",e),u.filtersToggle.setAttribute("aria-expanded",String(e)),e&&d(!1))},k=()=>{if(v.matches)return y(!1),void(f=!0);f&&y(!1),f=!1};function b(){if(u.columnHeadersContainer&&(u.columnHeadersContainer.innerHTML=le(p,h)),u.packageHeader){const e=u.packageHeader.querySelector(".sort-indicator");e&&("name"===p?(e.textContent=h?" ▲":" ▼",u.packageHeader.classList.add("sorted")):(e.textContent="",u.packageHeader.classList.remove("sorted")))}}function w(e){const t=e.target.closest(".column-header");if(!t)return;const n=t.dataset.sort;n&&(p===n?h=!h:(p=n,h=!0),u.sort&&(u.sort.value=p,u.sortDirection.textContent=h?"↑":"↓"),b(),q())}u.filtersToggle&&u.filterControls&&u.filtersToggle.addEventListener("click",()=>{const e=!u.filterControls.classList.contains("open");y(e)}),document.addEventListener("click",e=>{if(!u.filterControls||!u.filtersToggle)return;const t=e.target;u.filterControls.contains(t)||u.filtersToggle.contains(t)||y(!1)}),document.addEventListener("keydown",e=>{"Escape"===e.key&&y(!1)}),y(!1),window.addEventListener("resize",k),k(),u.sortDirection.addEventListener("click",()=>{h=!h,u.sortDirection.textContent=h?"↑":"↓",b(),q()}),u.sort.addEventListener("change",()=>{p=u.sort.value,b(),q()}),u.columnHeadersContainer&&u.columnHeadersContainer.addEventListener("click",w),u.packageHeader&&u.packageHeader.addEventListener("click",w),b(),u.licenseAll.addEventListener("click",()=>{u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!0,u.licenseStrongCopyleft.checked=!0,u.licenseUnknown.checked=!0,X.clear(),q()}),u.licenseFriendly.addEventListener("click",()=>{u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!1,u.licenseStrongCopyleft.checked=!1,u.licenseUnknown.checked=!1,X.clear(),q()});const C=Object.values(e.dependencies||{}),E=e=>{const t=e.usage.origins.workspaces||[];return t.length>0?t:["root"]},x=Array.from(new Set([...s(e),...C.flatMap(E)])).sort((e,t)=>"root"===e?-1:"root"===t?1:e.localeCompare(t)),S=(e,t)=>e+" ("+t+")",I=e=>{return z[t=K(e).summary,t?.highest||"none"]>0;var t},M=e=>C.reduce((t,n)=>t+(e(n)?1:0),0);if(u.workspace&&u.workspaceWrap&&x.length>1){u.workspace.textContent="";const e=document.createElement("option");e.value="all",e.textContent=S("All workspaces",C.length),u.workspace.appendChild(e),x.forEach(e=>{const t=document.createElement("option");t.value=e,t.textContent=S("root"===e?"Workspace root":e,M(t=>E(t).includes(e))),u.workspace.appendChild(t)}),u.workspaceWrap.classList.remove("hidden")}!function(){const e=C.length;u.direct.options[0].textContent=S("All",e),u.direct.options[1].textContent=S("Direct",M(e=>e.usage.direct)),u.direct.options[2].textContent=S("Transitive",M(e=>!e.usage.direct));const t={all:"All",runtime:"Production",dev:"Development",optional:"Optional",peer:"Peer"};Array.from(u.runtime.options).forEach(n=>{n.textContent=S(t[n.value]||n.textContent||n.value,"all"===n.value?e:M(e=>e.usage.scope===n.value))});const n={permissive:0,weakCopyleft:0,strongCopyleft:0,unknown:0};C.forEach(e=>{n[G(_(e).value)]+=1}),u.licensePermissiveLabel&&(u.licensePermissiveLabel.textContent=S("Permissive",n.permissive)),u.licenseWeakCopyleftLabel&&(u.licenseWeakCopyleftLabel.textContent=S("Weak Copyleft",n.weakCopyleft)),u.licenseStrongCopyleftLabel&&(u.licenseStrongCopyleftLabel.textContent=S("Strong Copyleft",n.strongCopyleft)),u.licenseUnknownLabel&&(u.licenseUnknownLabel.textContent=S("Other / Unknown",n.unknown)),u.hasVulnsLabel&&(u.hasVulnsLabel.textContent=S("Has vulnerabilities",M(I))),u.maintenanceConcernsLabel&&(u.maintenanceConcernsLabel.textContent=S("Maintenance concerns",M(O))),u.licenseIssuesLabel&&(u.licenseIssuesLabel.textContent=S("Licence issues",M(F))),u.upgradeBlockersLabel&&(u.upgradeBlockersLabel.textContent=S("Upgrade blockers",M(W)))}(),function(){const t=document.getElementById("header-stats");if(!t)return;let n=0,a=0,s=0,r=!1,i=0,o=0;C.forEach(e=>{if(I(e)&&(n+=1),e.maintenance?.attempted&&(r=!0),O(e)){a+=1;const t=e.maintenance?.status;"deprecated"!==t&&"archived"!==t||(s+=1)}F(e)&&(i+=1),W(e)&&(o+=1)});const c=(e,t,n,a)=>{const s=document.getElementById(e);if(!s)return;const r=s.querySelector("strong");r&&(r.textContent=String(t)),s.classList.remove("red","amber"),n&&t>0&&s.classList.add(n),a&&(s.title=a)};c("stat-total",e.summary.dependencyCount,void 0,\`\${e.summary.directCount} direct, \${e.summary.transitiveCount} transitive\`),c("stat-vulnerable",n,"red","Dependencies with known vulnerabilities — click to filter");const l=(e,t,n)=>{const a=document.getElementById(e);if(!a)return;a.hidden=!1,a.disabled=!0,a.classList.remove("red","amber");const s=a.querySelector("strong");s&&(s.textContent="?"),a.title=\`\${n} is unknown because its collector is \${t}\`},d=e.scanStatus?.collectors.audit;d&&"available"!==d&&l("stat-vulnerable",d,"Vulnerability status"),c("stat-license",i,"amber","Dependencies with licence review flags — click to filter"),c("stat-blockers",o,"amber","Dependencies with upgrade blockers — click to filter");const p=document.getElementById("stat-maintenance");if(p){const t=e.scanStatus?.collectors.maintenance;t&&"available"!==t?l("stat-maintenance",t,"Maintenance status"):r?c("stat-maintenance",a,s>0?"red":"amber","Deprecated, archived, unmaintained, or stale dependencies — click to filter"):p.hidden=!0}t.addEventListener("click",e=>{const t=e.target.closest("[data-stat-filter]");if(!t)return;if(t.disabled)return;const n={"has-vulns":u.hasVulns,"maintenance-concerns":u.maintenanceConcerns,"license-issues":u.licenseIssues,"upgrade-blockers":u.upgradeBlockers}[t.dataset.statFilter||""];if(!n)return;const a=n.checked;u.search.value="",\$(),n.checked=!a,n.dispatchEvent(new Event("change"))})}();const P=new Map;C.forEach(e=>{P.set(fe(e.package.name,e.package.version),e)});const B=new Set(P.keys()),D=we(B),A=function(e,t,n){const a=new Map,s=(e,t)=>{const n=a.get(e)||[];n.push(t),a.set(e,n)};for(const r of e.supplyChain?.signals||[]){const e=[r.packageId,r.packageName&&r.packageVersion?fe(r.packageName,r.packageVersion):void 0].filter(Boolean);let a=!1;for(const n of e){const e=xe(n,t);if(e){s(e,r),a=!0;break}}if(!a&&r.packageName&&!r.packageVersion){const e=Ce(r.packageName,t,n);e&&s(e,r)}}return a}(e,B,D),Y=new Set,X=new Set,N=new Map,T=(()=>{const e=document.getElementById("copy-announcer");if(e)return e;const t=document.createElement("div");return t.id="copy-announcer",t.className="sr-only",t.setAttribute("aria-live","polite"),document.body.appendChild(t),t})();function j(e){const t=e.dataset.depKey;if(!t)return;const n=e.querySelector(".dep-details");if(!n||"true"===n.dataset.rendered)return;const a=P.get(t);a&&(n.setAttribute("aria-busy","true"),n.innerHTML=['<div class="dep-loading" role="presentation">','<div class="dep-loading-bar"></div>',"</div>"].join(""),requestAnimationFrame(()=>{n.innerHTML=Te(a,B,D,A.get(t)),n.dataset.rendered="true",n.removeAttribute("aria-busy")}))}function V(e){return(e.selectedOptions[0]?.textContent||"").replace(/\\s+\\(\\d+\\)\$/,"")}function \$(){u.direct.value="all",u.runtime.value="all",u.workspace&&(u.workspace.value="all"),u.hasVulns.checked=!1,u.maintenanceConcerns&&(u.maintenanceConcerns.checked=!1),u.licenseIssues&&(u.licenseIssues.checked=!1),u.upgradeBlockers&&(u.upgradeBlockers.checked=!1),u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!0,u.licenseStrongCopyleft.checked=!0,u.licenseUnknown.checked=!0}function H(){const e=[],t=u.search.value.trim();return t&&e.push({id:"search",label:"Search: "+t,remove:()=>{u.search.value=""}}),"all"!==u.direct.value&&e.push({id:"type",label:"Type: "+V(u.direct),remove:()=>{u.direct.value="all"}}),"all"!==u.runtime.value&&e.push({id:"scope",label:"Scope: "+V(u.runtime),remove:()=>{u.runtime.value="all"}}),u.workspace&&"all"!==u.workspace.value&&e.push({id:"workspace",label:"Workspace: "+V(u.workspace),remove:()=>{u.workspace.value="all"}}),[{id:"license-permissive",checked:u.licensePermissive.checked,label:"License: Permissive",reset:()=>{u.licensePermissive.checked=!0}},{id:"license-weak-copyleft",checked:u.licenseWeakCopyleft.checked,label:"License: Weak Copyleft",reset:()=>{u.licenseWeakCopyleft.checked=!0}},{id:"license-strong-copyleft",checked:u.licenseStrongCopyleft.checked,label:"License: Strong Copyleft",reset:()=>{u.licenseStrongCopyleft.checked=!0}},{id:"license-unknown",checked:u.licenseUnknown.checked,label:"License: Other / Unknown",reset:()=>{u.licenseUnknown.checked=!0}}].forEach(t=>{t.checked||e.push({id:t.id,label:t.label,remove:t.reset})}),u.hasVulns.checked&&e.push({id:"has-vulns",label:"Has vulnerabilities",remove:()=>{u.hasVulns.checked=!1}}),u.maintenanceConcerns?.checked&&e.push({id:"maintenance-concerns",label:"Maintenance concerns",remove:()=>{u.maintenanceConcerns&&(u.maintenanceConcerns.checked=!1)}}),u.licenseIssues?.checked&&e.push({id:"license-issues",label:"Licence issues",remove:()=>{u.licenseIssues&&(u.licenseIssues.checked=!1)}}),u.upgradeBlockers?.checked&&e.push({id:"upgrade-blockers",label:"Upgrade blockers",remove:()=>{u.upgradeBlockers&&(u.upgradeBlockers.checked=!1)}}),e}function q(){!function(){const e=H(),t=e.length;u.filtersToggle.classList.toggle("has-active-filters",t>0),u.filterCountBadge&&(u.filterCountBadge.hidden=0===t,u.filterCountBadge.textContent=String(t)),u.activeFiltersRow&&u.activeFilterChips&&(u.activeFiltersRow.hidden=0===t,u.activeFilterChips.innerHTML=e.map(e=>'<span class="active-filter-chip">'+Z(e.label)+'<button type="button" class="active-filter-remove" data-filter-chip="'+Z(e.id)+'" aria-label="Remove '+Z(e.label)+'">×</button></span>').join(""))}();const a=function(e){const t=[...e];if("name"===p)t.sort((e,t)=>e.package.name.localeCompare(t.package.name));else if("depth"===p)t.sort((e,t)=>e.usage.depth-t.usage.depth);else{const e=R.find(e=>e.sortKey===p||e.id===p);e?.sortFn?t.sort(e.sortFn):e&&t.sort((t,n)=>e.getValue(t).localeCompare(e.getValue(n)))}return h||t.reverse(),t}(function(){const e=(u.search.value||"").toLowerCase(),t=u.direct.value,n=u.runtime.value,a=u.workspace?.value||"all",s=u.hasVulns.checked,r=u.maintenanceConcerns?.checked??!1,i=u.licenseIssues?.checked??!1,o=u.upgradeBlockers?.checked??!1,c=u.licensePermissive.checked,l=u.licenseWeakCopyleft.checked,d=u.licenseStrongCopyleft.checked,p=u.licenseUnknown.checked;return C.filter(u=>{const h=fe(u.package.name,u.package.version);if(X.has(h))return!0;const g=_(u),m=[g.value,u.compliance.license.declared?.spdxId,u.compliance.license.inferred?.spdxId].filter(Boolean).join(" ").toLowerCase();if(e&&!u.package.name.toLowerCase().includes(e)&&!m.includes(e))return!1;if("direct"===t&&!u.usage.direct)return!1;if("transitive"===t&&u.usage.direct)return!1;if("all"!==n&&u.usage.scope!==n)return!1;if("all"!==a&&!E(u).includes(a))return!1;if(s&&!I(u))return!1;if(r&&!O(u))return!1;if(i&&!F(u))return!1;if(o&&!W(u))return!1;const v=G(g.value);return!("permissive"===v&&!c||"weakCopyleft"===v&&!l||"strongCopyleft"===v&&!d||"unknown"===v&&!p)})}()),s=e.summary?.dependencyCount||C.length;n.innerHTML="Showing <strong>"+a.length+"</strong> of <strong>"+s+"</strong> dependencies","all"!==(u.workspace?.value||"all")&&(n.innerHTML+=" in <strong>"+Z(u.workspace.value)+"</strong>"),0!==a.length?(t.innerHTML=a.map(e=>function(e,t){const n=function(e,t,n=0){const a=e.execution?.risk||"green",s=n>0||(e.packaging?.signals?.length||0)>0?"amber":"green",r=(e.supplyChain?.registry?.signals?.length||0)>0?"amber":"green",i=e.maintenance?.status,o="deprecated"===i||"archived"===i?"red":"unmaintained"===i?"amber":"green";return(c=[t.risk,e.compliance.licenseRisk,a,s,r,o]).includes("red")?"red":c.includes("amber")?"amber":"green";var c}(e,K(e).summary,t?.length||0),a=fe(e.package.name,e.package.version),s=be(a),r=ce(e),i=['<summary class="dep-summary">','<span class="expand-icon" aria-hidden="true"></span>','<span class="dep-name">'+Z(e.package.name)+'<span class="dep-version">@'+Z(e.package.version)+"</span></span>",'<div class="dep-indicators" style="--column-count: '+U+'">',r,"</div>","</summary>"].join("");return['<details class="dep-card" data-risk="'+n+'" data-dep-key="'+Z(a)+'" id="'+Z(s)+'">',i,'<div class="dep-details" data-rendered="false"></div>',"</details>"].join("")}(e,A.get(fe(e.package.name,e.package.version)))).join(""),N.clear(),t.querySelectorAll("details.dep-card").forEach(e=>{const t=e.dataset.depKey;t&&N.set(t,e)}),Y.forEach(e=>{const t=N.get(e);t&&(t.open||(t.open=!0),j(t))})):t.innerHTML='<div class="empty-state"><div class="empty-state-icon">📦</div><div class="empty-state-text">No dependencies match your filters</div></div>'}function J(e){const t=D.get(e)||[];return 1===t.length?t[0]:null}function Q(e){if(P.has(e))return e;const t=ke(e);if(!t)return J(e);if(t.version.startsWith("npm:")){const e=t.version.slice(4),n=t.name+(e.startsWith("@")?e:"@"+e);if(P.has(n))return n}return J(t.name)}function ee(t){if(!u.listViewPanel||!u.graphViewPanel)return void console.warn("Dependency Radar: view panels are missing from the report DOM.");const n="list"===t;n||Boolean(u.graphWorkspaceSelect&&u.graphWorkspaceWrap&&u.graphControls&&u.graphCanvas&&u.graphCanvasShell&&u.graphPopover&&u.graphPopoverName&&u.graphPopoverVersion&&u.graphPopoverLicense&&u.graphPopoverVulns&&u.graphPopoverAmplification&&u.graphOpenList)?(u.listViewPanel.classList.toggle("active",n),u.graphViewPanel.classList.toggle("active",!n),u.listViewPanel.setAttribute("aria-hidden",String(!n)),u.graphViewPanel.setAttribute("aria-hidden",String(n)),u.viewGraphButton&&(u.viewGraphButton.style.display=n?"":"none"),u.graphBackButton&&(u.graphBackButton.style.display=n?"none":""),u.reportFooter?.classList.toggle("hidden",!n),document.body.classList.toggle("graph-mode",!n),n?g?.setActive(!1):(m||(g=L({report:e,knownDepKeys:B,resolveDepKey:Q,workspaceSelect:u.graphWorkspaceSelect,workspaceWrap:u.graphWorkspaceWrap,controlsRoot:u.graphControls,canvas:u.graphCanvas,canvasHost:u.graphCanvasShell,popover:u.graphPopover,popoverName:u.graphPopoverName,popoverVersion:u.graphPopoverVersion,popoverLicense:u.graphPopoverLicense,popoverVulns:u.graphPopoverVulns,popoverAmplification:u.graphPopoverAmplification,popoverOpenButton:u.graphOpenList,onOpenList:e=>{!function(e){ee("list");let t=document.getElementById(be(e));!t&&P.has(e)&&(X.add(e),q(),t=document.getElementById(be(e)));if(!t)return;if(t instanceof HTMLDetailsElement){const e=t.dataset.depKey;e&&Y.add(e),t.open||(t.open=!0),j(t)}t.classList.add("dep-list-highlight"),re(t,!0),window.setTimeout(()=>{t?.classList.remove("dep-list-highlight")},2e3)}(e)}}),g.initGraphView(),m=!0),g?.setActive(!0),g?.requestRender())):console.warn("Dependency Radar: graph view DOM nodes are missing; graph view disabled.")}function re(e,t=!1){const n=()=>{const n=window.scrollY+e.getBoundingClientRect().top-function(){const e=document.querySelector(".filter-bar");return!e||document.body.classList.contains("graph-mode")?0:Math.ceil(e.getBoundingClientRect().height+8)}();if(window.scrollTo({top:Math.max(0,n),behavior:"smooth"}),t){const t=e.querySelector("summary");t&&t.focus({preventScroll:!0})}};requestAnimationFrame(()=>{n(),window.setTimeout(n,60)})}const ie=[u.search,u.direct,u.runtime,u.sort,u.hasVulns,u.maintenanceConcerns,u.licenseIssues,u.upgradeBlockers,u.workspace,u.licensePermissive,u.licenseWeakCopyleft,u.licenseStrongCopyleft,u.licenseUnknown],oe=()=>{X.clear(),q()};ie.forEach(e=>{e&&(e.addEventListener("input",oe),e.addEventListener("change",oe))}),u.activeFilterChips?.addEventListener("click",e=>{const t=e.target.closest("[data-filter-chip]");if(!t)return;const n=H().find(e=>e.id===t.dataset.filterChip);n&&(n.remove(),oe())});const de=()=>{u.search.value="",\$(),oe()};function ue(e){const t=e.getAttribute("data-dep-key");if(!t)return;const n=Q(t);if(!n)return;let a=N.get(n);a||(X.add(n),q(),a=N.get(n)),a&&(Y.add(n),a.open||(a.open=!0),j(a),re(a,!0))}u.activeFilterClear?.addEventListener("click",de),u.clearAllFilters?.addEventListener("click",de),u.viewGraphButton?.addEventListener("click",()=>{ee("graph")}),u.graphBackButton?.addEventListener("click",()=>{ee("list")}),t.addEventListener("toggle",e=>{const t=e.target;if(!(t instanceof HTMLDetailsElement))return;if(!t.classList.contains("dep-card"))return;const n=t.dataset.depKey;n&&(t.open?(Y.add(n),j(t)):Y.delete(n))},!0),t.addEventListener("click",e=>{const t=e.target,n=t.closest(".root-package-link");if(n)return e.preventDefault(),void ue(n);const a=t.closest(".copy-json-btn");a&&(e.preventDefault(),async function(e){const t=(e.closest(".raw-data-toggle")?.querySelector("pre"))?.textContent??"";if(t)try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(t);else{const e=document.createElement("textarea");e.value=t,e.setAttribute("readonly","true"),e.style.position="absolute",e.style.left="-9999px",document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e)}const n=e.dataset.label||e.textContent||"Copy JSON";e.dataset.label=n,e.textContent="Copied",e.classList.add("copied"),T.textContent="Copied JSON to clipboard.",window.setTimeout(()=>{e.textContent=n,e.classList.remove("copied")},1500)}catch{T.textContent="Copy failed."}}(a))}),t.addEventListener("keydown",e=>{const t=e.target.closest(".root-package-link");t&&(" "!==e.key&&"Spacebar"!==e.key||(e.preventDefault(),ue(t)))}),b(),q(),ee("list")}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",je):je()}();`;
export const JS_CONTENT = `!function(){var e=[{signalType:"git-dependency",type:"install-scripts-git-source",severity:"error",title:"Install scripts from a git-sourced package",detail:"This package runs code at install time AND is installed from a git source, so its content can change without a version bump or registry publish."},{signalType:"non-registry-tarball",type:"install-scripts-non-registry-tarball",severity:"error",title:"Install scripts from a non-registry tarball",detail:"This package runs code at install time AND is fetched from a tarball outside the configured registry, bypassing registry review surfaces."},{signalType:"unexpected-registry-host",type:"install-scripts-unexpected-registry-host",severity:"error",title:"Install scripts from an unexpected registry host",detail:"This package runs code at install time AND resolves from a registry host that does not match the expected hosts for this project."},{signalType:"missing-integrity",type:"install-scripts-missing-integrity",severity:"warning",title:"Install scripts without lockfile integrity",detail:"This package runs code at install time AND has no lockfile integrity hash, so a substituted artifact would not be detected at install."}];function t(t,n){const a=t.execution?.scripts?.hooks||[];if(0===a.length||!n||0===n.size)return[];const s=[];for(const r of e)n.has(r.signalType)&&s.push({type:r.type,severity:r.severity,signalType:r.signalType,hooks:[...a].sort(),title:r.title,detail:r.detail});return s}var n={"network-access":"Accesses network during install","dynamic-exec":"Uses dynamic execution","child-process":"Spawns child processes",encoding:"Uses encoding/decoding logic",obfuscated:"Contains obfuscated/minified install logic","reads-env":"Reads environment variables","reads-home":"Reads user home directory","uses-ssh":"Uses SSH configuration/keys"};function a(e){return e.critical+e.high+e.moderate+e.low}function s(e,t){if(t&&0!==t.length)return function(e){const t=new Map;for(const n of e||[]){let e=n.packageName;if(!e&&n.packageId){const t=n.packageId.lastIndexOf("@");t>0&&(e=n.packageId.slice(0,t))}if(!e)continue;const a=t.get(e)||new Set;a.add(n.type),t.set(e,a)}return t}(t).get(e)}function r(e){return"runtime"===e?"Runtime":"dev"===e?"Dev":"optional"===e?"Optional":"peer"===e?"Peer":e.split(/[-_\\s]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}function i(e,i,o){const c=[],l=a(i),d=e.security.advisories?.some(e=>e.fixAvailable);if(i.critical||i.high){const e=i.critical+i.high;c.push(\`\${e} critical/high \${1===e?"vulnerability":"vulnerabilities"}\${d?", fix available":""}\`)}if(i.moderate||i.low){const e=i.moderate+i.low;c.push(\`\${function(e){const t=[];return e.moderate&&t.push(\`\${e.moderate} moderate\`),e.low&&t.push(\`\${e.low} low\`),t.join(", ")}(i)} \${1===e?"vulnerability":"vulnerabilities"}\${d?", fix available":""}\`)}"deprecated"===e.maintenance?.status?c.push(e.maintenance.deprecated&&!e.maintenance.deprecated.installedVersion?"Latest version deprecated by the author":"Deprecated by the author"):"archived"===e.maintenance?.status?c.push("Source repository is archived"):"unmaintained"===e.maintenance?.status?c.push(void 0!==e.maintenance.monthsSinceRepoPush?"Registry and source repository have both gone quiet":"No registry activity for 3+ years"):"stale"===e.maintenance?.status?c.push(void 0!==e.maintenance.monthsSinceRepoPush?"Publishing and source activity have slowed to a trickle":"No registry activity for 18+ months"):"slowing"===e.maintenance?.status&&c.push("No registry publishes for 12+ months"),"green"!==e.compliance.licenseRisk&&c.push("Licence status: "+function(e){switch(e){case"declared-only":return"Declared";case"inferred-only":return"Inferred";case"match":return"Declared + Inferred (match)";case"mismatch":return"Declared + Inferred (mismatch)";case"invalid-spdx":return"Invalid SPDX";default:return"Unknown"}}(e.compliance.license.status)),e.upgrade.blocksNodeMajor&&c.push("Blocks Node major upgrade"),e.upgrade.blockers?.length&&c.push(\`\${e.upgrade.blockers.length} upgrade \${1===e.upgrade.blockers.length?"blocker":"blockers"} detected\`),t(e,s(e.package.name,o)).forEach(e=>c.push(e.title)),e.replacement&&c.push("Community-suggested replacement available (e18e)");const u=e.execution?.risk||"green";var p;if("green"!==u&&c.push(("red"===(p=u)?"High":"amber"===p?"Medium":"Low")+" install-time execution risk"),e.execution?.scripts?.hooks?.length&&c.push("Runs "+e.execution.scripts.hooks.slice(0,2).join(", ")+" lifecycle script"+(1===e.execution.scripts.hooks.length?"":"s")),function(e){return Array.from(new Set([...e.execution?.scripts?.signals||[],...e.execution?.signals||[]]))}(e).slice(0,3).forEach(e=>c.push(n[e])),e.packaging?.signals?.length&&c.push(\`\${e.packaging.signals.length} package content \${1===e.packaging.signals.length?"signal":"signals"}\`),e.supplyChain?.registry?.signals?.length&&c.push(\`\${e.supplyChain.registry.signals.length} registry metadata \${1===e.supplyChain.registry.signals.length?"signal":"signals"}\`),e.usage.direct)c.push(\`Direct \${r(e.usage.scope).toLowerCase()} dependency\`);else{const t=e.usage.origins.topParentPackages?.[0]?\` introduced by \${e.usage.origins.topParentPackages[0]}\`:"";c.push(\`Transitive \${r(e.usage.scope).toLowerCase()} dependency\${t}\`)}return e.usage.depth>1&&c.push(\`Dependency depth \${e.usage.depth}\`),(0===c.length||0===l&&"green"===u&&"green"===e.compliance.licenseRisk&&c.length<3)&&["No known vulnerabilities","No install-time execution signals detected","Licence status appears consistent",e.usage.direct?\`Direct \${r(e.usage.scope).toLowerCase()} dependency\`:\`Transitive \${r(e.usage.scope).toLowerCase()} dependency\`].forEach(e=>{c.includes(e)||c.push(e)}),Array.from(new Set(c)).slice(0,8)}function o(e){if(!e.workspaces.enabled)return[];const t=new Set;return(e.workspaces.workspacePackages||[]).forEach(e=>{e.name&&t.add(e.name)}),Object.values(e.dependencies||{}).forEach(e=>{(e.usage.origins.workspaces||[]).forEach(e=>{e&&t.add(e)})}),Array.from(t).sort((e,t)=>"root"===e?-1:"root"===t?1:e.localeCompare(t))}var c=2.8,l='500 11.5px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';function d(e,t,n){return Math.min(n,Math.max(t,e))}function u(e,t=!1){return t?e.length:Math.min(e.length,34)}function p(e){const t=u(e);return e.length<=34?t:Math.max(1,t-6)}function h(e){const{labelGraphemes:t}=e;if(t.length<=34)return e.ref.name;const n=d(Math.round(e.renderLabelChars),1,t.length);return n>=t.length?e.ref.name:\`\${t.slice(0,n-1).join("")}…\`}function g(e,t,n){const a=function(e){const t=e.trim(),n=t.match(/^#([0-9a-f]{3}|[0-9a-f]{6})\$/i);if(n){const e=n[1];return 3===e.length?{r:parseInt(e[0]+e[0],16),g:parseInt(e[1]+e[1],16),b:parseInt(e[2]+e[2],16)}:{r:parseInt(e.slice(0,2),16),g:parseInt(e.slice(2,4),16),b:parseInt(e.slice(4,6),16)}}const a=t.match(/^rgba?\\(([^)]+)\\)\$/i);if(!a)return null;const s=a[1].replace(/\\//g," ").split(/[\\s,]+/).filter(Boolean).slice(0,3);if(3!==s.length)return null;const r=e=>{if(e.endsWith("%")){const t=Number(e.slice(0,-1));return Number.isFinite(t)?d(Math.round(t/100*255),0,255):null}const t=Number(e);return Number.isFinite(t)?d(Math.round(t),0,255):null},i=r(s[0]),o=r(s[1]),c=r(s[2]);return null===i||null===o||null===c?null:{r:i,g:o,b:c}}(e);if(!a)return n;const s=d(t,0,1);return\`rgb(\${Math.round(a.r+(255-a.r)*s)}, \${Math.round(a.g+(255-a.g)*s)}, \${Math.round(a.b+(255-a.b)*s)})\`}function m(e){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()}function v(e,t,n){if(0===t.length)return;if(e.moveTo(t[0].x,t[0].y),1===t.length)return;if(2===t.length)return void e.lineTo(t[1].x,t[1].y);for(let s=1;s<t.length-1;s+=1){const a=t[s-1],r=t[s],i=t[s+1],o=r.x-a.x,c=r.y-a.y,l=i.x-r.x,d=i.y-r.y,u=Math.hypot(o,c),p=Math.hypot(l,d);if(u<.001||p<.001){e.lineTo(r.x,r.y);continue}const h=Math.min(n,.45*u,.45*p),g=r.x-o/u*h,m=r.y-c/u*h,v=r.x+l/p*h,f=r.y+d/p*h;e.lineTo(g,m),e.quadraticCurveTo(r.x,r.y,v,f)}const a=t[t.length-1];e.lineTo(a.x,a.y)}function f(e){const t=new Map;return e.nodes.forEach(e=>{const n=t.get(e.depth);n?n.push(e):t.set(e.depth,[e])}),t.forEach(e=>{e.sort((e,t)=>e.renderY-t.renderY)}),t}function y(e,t,n,a){const s=t.renderX,r=t.renderY,i=n.renderX,o=n.renderY,c=n.depth-t.depth,l=Math.abs(c);if(0===l){const n=Math.abs(s-i)<a.sameColumnXThreshold,c=Math.abs(r-o),l=t.depth<a.maxDepth;if(n&&c>a.minDetourVerticalSpan&&l){const n=a.paddingX+t.depth*a.layerGap,l=a.paddingX+(t.depth+1)*a.layerGap,u=.5*(n+l);let p=u+a.detourInset;const h=Math.min(r,o)-12,g=Math.max(r,o)+12;(function(e,t,n,a,s){const r=e.depthNodeIndex.get(t);if(!r||0===r.length)return!1;const i=function(e,t){let n=0,a=e.length;for(;n<a;){const s=n+(a-n>>1);e[s].renderY<t?n=s+1:a=s}return n}(r,n);for(let o=i;o<r.length&&r[o].renderY<=a;o+=1)if(Math.abs(r[o].renderX-s)<e.detourNodeClearance)return!0;return!1})(a,t.depth+1,h,g,p)&&(p+=12);p=d(p,u+8,l-24);const m=Math.max(1,p-s);return void v(e,[{x:s,y:r},{x:p,y:r},{x:p,y:o},{x:i,y:o}],d(.42*Math.min(m,c),16,52))}e.moveTo(s,r);const u=s+.5*(i-s),p=r+(o-r)*a.edgeCurve;return void e.quadraticCurveTo(u,p,i,o)}if(1===l){const c=Math.min(t.depth,n.depth),l=a.paddingX+c*a.layerGap+.5*a.layerGap;return e.moveTo(s,r),void e.bezierCurveTo(l,r,l,o,i,o)}const u=Math.sign(c),p=o-r,h=[{x:s,y:r}],g=a.paddingX+t.depth*a.layerGap+u*(.5*a.layerGap);h.push({x:g,y:r});for(let d=1;d<l;d+=1){const e=t.depth+u*d,n=a.paddingX+e*a.layerGap+u*(.5*a.layerGap),s=d/l;h.push({x:n,y:r+p*s})}const m=a.paddingX+n.depth*a.layerGap-u*(.5*a.layerGap);h.push({x:m,y:o}),h.push({x:i,y:o}),v(e,h,14)}function k(e,t,n,a){a&&t.highlighted?function(e,t,n){const a=t.renderX,s=t.renderY,r=n.renderX,i=n.renderY,o=r-a,c=i-s;if(e.moveTo(a,s),Math.abs(o)<18){const t=a+(s<=i?26:-26);return void e.bezierCurveTo(t,s,t,i,r,i)}const l=d(.44*Math.abs(o),42,150),u=Math.sign(o),p=d(.12*Math.abs(c),0,24);e.bezierCurveTo(a+u*l,s+p*Math.sign(c),r-u*l,i-p*Math.sign(c),r,i)}(e,t.from,t.to):y(e,t.from,t.to,n)}function b(e,t){return\`\${e}@\${t}\`}function w(e,t){return\`\${e}->\${t}\`}function C(e){if(!e||"object"!=typeof e)return!1;const t=e;if(!Array.isArray(t.workspaces))return!1;if(!t.dependencies||"object"!=typeof t.dependencies)return!1;const n=e=>Array.isArray(e)&&e.every(e=>"string"==typeof e);return!!t.workspaces.every(e=>(e=>{if(!e||"object"!=typeof e)return!1;const t=e;return"string"==typeof t.name&&!!Array.isArray(t.directDependencies)&&!!Array.isArray(t.directDevDependencies)})(e))&&(!!t.workspaces.every(e=>n(e.directDependencies)&&n(e.directDevDependencies))&&!!Object.entries(t.dependencies).every(([,e])=>{if(!e||"object"!=typeof e)return!1;const t=e;return!(void 0!==t.dependencies&&!Array.isArray(t.dependencies))&&!(void 0!==t.workspaceOrigins&&!Array.isArray(t.workspaceOrigins))}))}function E(e){const t=e.compliance.license.declared?.valid?e.compliance.license.declared.spdxId:void 0;return t||(e.compliance.license.inferred?.spdxId||"Unknown")}function x(e){const t=e.security?.summary;return t?Number(t.critical||0)+Number(t.high||0)+Number(t.moderate||0)+Number(t.low||0):0}function S(e){const t=e.security?.summary?.highest;return"critical"===t||"high"===t?"high":"moderate"===t?"moderate":"none"}function L(e,t){const n=new Set,a=[t];for(;a.length>0;){const t=a.pop();if(!t)continue;const s=e.nodes.get(t);s&&s.parents.forEach(e=>{n.has(e)||(n.add(e),a.push(e))})}return n}function I(e,t){const n=new Set,a=[t];for(;a.length>0;){const t=a.pop();if(!t)continue;const s=e.nodes.get(t);s&&s.children.forEach(e=>{n.has(e)||(n.add(e),a.push(e))})}return n}function M(e,t,n){const a=new Map,s=[{slug:t,distance:0}];let r=0;for(;r<s.length;){const t=s[r++],i=e.nodes.get(t.slug);i&&i[n].forEach(e=>{a.has(e)||(a.set(e,t.distance+1),s.push({slug:e,distance:t.distance+1}))})}return a}function P(e){const t=function(e,t,n){const a=window.__DEPENDENCY_DATA__;if(C(a)){const e={};return Object.entries(a.dependencies).forEach(([t,n])=>{const a=n,s=a.vulnerabilitySeverity||a.vulnerabilityHighest||a.highestSeverity||"none",r=String(s).trim().toLowerCase();let i="none";"critical"===r||"high"===r?i="high":"moderate"!==r&&"medium"!==r||(i="moderate"),e[t]={slug:String(a.slug||t),name:String(a.name||t),version:String(a.version||""),dependencies:Array.isArray(a.dependencies)?a.dependencies.map(e=>String(e)):[],license:String(a.license||"Unknown"),vulnerabilityCount:Number(a.vulnerabilityCount||0),vulnerabilitySeverity:i,isDevOnly:Boolean(a.isDevOnly),workspaceOrigins:Array.isArray(a.workspaceOrigins)?a.workspaceOrigins.map(e=>String(e)):[]}}),{workspaces:a.workspaces,dependencies:e}}const s={},r=Object.values(e.dependencies||{});r.forEach(e=>{const t=b(e.package.name,e.package.version);s[t]={slug:t,name:e.package.name,version:e.package.version,dependencies:[],license:E(e),vulnerabilityCount:x(e),vulnerabilitySeverity:S(e),isDevOnly:"dev"===e.usage.scope,workspaceOrigins:e.usage.origins.workspaces||[]}}),r.forEach(e=>{const a=b(e.package.name,e.package.version),r=e.graph.subDeps;if(!r)return;const i=new Set;["dep","dev","opt","peer"].forEach(e=>{const o=r[e];o&&Object.values(o).forEach(e=>{const r=e[1];if(!r)return;const o=n(r);o&&t.has(o)&&s[o]&&o!==a&&i.add(o)})}),s[a].dependencies=[...i]});const i=new Map,o=e=>{const t=i.get(e);if(t)return t;const n={directDependencies:new Set,directDevDependencies:new Set};return i.set(e,n),n};return o("root"),(e.workspaces.workspacePackages||[]).forEach(e=>{o(e.name)}),r.forEach(e=>{if(!e.usage.direct)return;const t=b(e.package.name,e.package.version);(e.usage.origins.workspaces?.length?e.usage.origins.workspaces:["root"]).forEach(n=>{const a=o(n);"dev"===e.usage.scope?a.directDevDependencies.add(t):a.directDependencies.add(t)})}),{workspaces:[...i.entries()].map(([e,t])=>({name:e,directDependencies:[...t.directDependencies],directDevDependencies:[...t.directDevDependencies]})).sort((e,t)=>e.name.localeCompare(t.name)),dependencies:s}}(e.report,e.knownDepKeys,e.resolveDepKey),n=new Map(t.workspaces.map(e=>[e.name,e])),a=new Map,s=new Map;Object.values(t.dependencies).forEach(e=>{const n=(e.dependencies||[]).filter(n=>n!==e.slug&&Boolean(t.dependencies[n]));s.set(e.slug,n),n.forEach(t=>{const n=a.get(t)||[];n.push(e.slug),a.set(t,n)})});let r=null,i="",o=null,v=null,y=new Set,P=new Set,B=new Set,D=new Map,A=null,Y=null,X=new Set,N=new Set,T=null,R=1,j=0,V=0,\$=1,H=.1,O=0,F=0,W=null,U=null,G=!1,_=!0,q=0,z=Math.max(1,Math.floor(window.devicePixelRatio||1)),K=1,J=1,Z=50;const Q={down:!1,moved:!1,startX:0,startY:0,startPanX:0,startPanY:0},ee={active:!1,startX1:0,startY1:0,startX2:0,startY2:0,startPanX:0,startPanY:0,startDist:0,startZoom:0,anchorX:null,anchorY:null},te={active:!1,velocityX:0,velocityY:0,lastSampleX:0,lastSampleY:0,lastSampleTime:0,lastFrameTime:0},ne=e.canvas.getContext("2d"),ae=Boolean(ne);let se=!1,re=!1,ie=!1,oe=null,ce=null,le=null,de=!1;const ue="function"==typeof window.matchMedia?window.matchMedia("(prefers-reduced-motion: reduce)"):null;let pe={runtime:"#10b981",runtimeHighlight:"#34d399",dev:"#f59e0b",devHighlight:"#fcd34d",transitive:"#06b6d4",transitiveHighlight:"#67e8f9",edge:"#64748b",highlight:"#22d3ee",muted:"#64748b",ringHigh:"#ef4444",ringModerate:"#f59e0b",label:"#e8edf5",backgroundPrimary:"#0c1222"};function he(){const e=m("--graph-direct-runtime")||"#10b981",t=m("--graph-direct-dev")||"#f59e0b",n=m("--graph-transitive")||"#06b6d4";pe={runtime:e,runtimeHighlight:g(e,.2,"#34d399"),dev:t,devHighlight:g(t,.28,"#fcd34d"),transitive:n,transitiveHighlight:g(n,.38,"#67e8f9"),edge:m("--graph-edge")||"#64748b",highlight:m("--graph-highlight")||"#22d3ee",muted:m("--graph-muted")||"#64748b",ringHigh:m("--graph-vuln-high")||"#ef4444",ringModerate:m("--graph-vuln-medium")||"#f59e0b",label:m("--text-primary")||"#e8edf5",backgroundPrimary:m("--bg-primary")||"#0c1222"}}function ge(){if(de)return;de=!0,console.warn("Dependency Radar: unable to initialize 2D canvas; graph rendering disabled."),e.controlsRoot.classList.add("hidden"),e.workspaceWrap.classList.add("hidden"),e.canvas.style.display="none";const t=document.createElement("div");t.className="empty-state";const n=document.createElement("div");n.className="empty-state-text",n.textContent="Graph view is unavailable in this browser context.",t.appendChild(n),e.canvasHost.appendChild(t)}function me(e){return(e-j)/R}function ve(e){return(e-V)/R}function fe(e,t){if(!r)return{x:e,y:t};const n=r.bounds.minX-120,a=r.bounds.maxX+120,s=r.bounds.minY-90,i=r.bounds.maxY+90,o=Math.min(.22*K,220),c=Math.min(.22*J,180),l=o-a*R,u=K-o-n*R,p=c-i*R,h=J-c-s*R;return{x:l>u? .5*(l+u):d(e,l,u),y:p>h? .5*(p+h):d(t,p,h)}}function ye(e,t){const n=fe(e,t);j=n.x,V=n.y}function ke(){W=null,U=null}function be(e,t,n){Ee(),ke();const a=d(e,H,c),s=me(t),r=ve(n);R=a,ye(t-s*R,n-r*R),_=!0,ze()}function we(e,t){Ee(),ke(),ye(j+e,V+t),_=!0,ze()}function Ce(){return!ue?.matches}function Ee(){te.active=!1,te.velocityX=0,te.velocityY=0,te.lastFrameTime=0}function xe(e,t,n){te.lastSampleX=e,te.lastSampleY=t,te.lastSampleTime=n}function Se(e,t,n){const a=n-te.lastSampleTime;if(a<=0)return void xe(e,t,n);const s=(e-te.lastSampleX)/a,r=(t-te.lastSampleY)/a;te.velocityX+=.22*(s-te.velocityX),te.velocityY+=.22*(r-te.velocityY),xe(e,t,n)}function Le(){Ce()?Math.hypot(te.velocityX,te.velocityY)<.08?Ee():(te.active=!0,te.lastFrameTime=performance.now(),Ve(!1),ze()):Ee()}function Ie(){const t=e.canvasHost.getBoundingClientRect();K=Math.max(1,Math.floor(t.width)),J=Math.max(1,Math.floor(t.height)),z=Math.max(1,Math.floor(window.devicePixelRatio||1)),e.canvas.width=K*z,e.canvas.height=J*z,e.canvas.style.width=\`\${K}px\`,e.canvas.style.height=\`\${J}px\`;const n=e.canvasHost.querySelector(".graph-overlay-top");Z=n?Math.ceil(n.getBoundingClientRect().height):50,e.canvasHost.style.setProperty("--graph-toolbar-height",\`\${Z}px\`),_=!0,ze()}function Me(){if(!r)return;const e=r.bounds;let t=e.maxX;ne&&(ne.save(),ne.font=l,r.nodes.forEach(e=>{const n=h(e);if(!n)return;const a=ne.measureText(n).width;t=Math.max(t,e.baseX+e.radius+6+a)}),ne.restore());const n=Math.max(1,e.maxY-e.minY),a=Math.max(1,K-32),s=Math.max(1,J-Z-24),i=a/Math.max(1,t-e.minX),o=s/n;\$=d(Math.min(i,o),.05,c),H=d(.64*\$,.05,c),O=16+.5*(a-Math.max(1,t-e.minX)*\$)-e.minX*\$,F=Z+12+.5*(s-n*\$)-e.minY*\$}function Pe(t,n){if(!r)return null;const a=e.canvas.getBoundingClientRect();if(t<a.left||t>a.right||n<a.top||n>a.bottom)return null;const s=me(t-a.left),i=ve(n-a.top);let o=null,c=1/0;return r.nodes.forEach(e=>{const t=s-e.renderX,n=i-e.renderY,a=Math.sqrt(t*t+n*n);a<=e.renderRadius+5&&a<c&&(c=a,o=e)}),o}function Be(t){e.canvas.classList.toggle("is-clickable",t&&!Q.down&&!ee.active)}function De(t=!1){Be(!1),t&&e.canvas.classList.remove("is-panning")}function Ae(e,t){const n=Pe(e,t);return He(n?n.slug:null),Be(Boolean(n)),n}function Ye(e){const r=n.get(e);if(!r)return null;const i=new Set(r.directDependencies.filter(e=>Boolean(t.dependencies[e]))),o=new Set(r.directDevDependencies.filter(e=>Boolean(t.dependencies[e]))),c=new Set([...i,...o]);0===c.size&&Object.keys(t.dependencies).filter(e=>0===(a.get(e)||[]).length).slice(0,40).forEach(e=>{c.add(e)});const l=new Set,d=[...c];let h=0;for(;h<d.length;){const e=d[h++];e&&(l.has(e)||t.dependencies[e]&&(l.add(e),(s.get(e)||[]).forEach(e=>{l.has(e)||d.push(e)})))}if(0===l.size)return null;const g=new Map;l.forEach(e=>{const n=i.has(e)?"direct-runtime":o.has(e)?"direct-dev":"transitive",a=Array.from(t.dependencies[e].name);g.set(e,{slug:e,ref:t.dependencies[e],labelGraphemes:a,parents:new Set,children:new Set,depth:Number.POSITIVE_INFINITY,order:0,amplification:0,kind:n,baseX:0,baseY:0,targetX:0,targetY:0,renderX:0,renderY:0,radius:8,targetRadius:8,renderRadius:8,targetLabelChars:u(a),renderLabelChars:p(a)})}),g.forEach(e=>{(a.get(e.slug)||[]).forEach(t=>{g.has(t)&&e.parents.add(t)}),(s.get(e.slug)||[]).forEach(t=>{g.has(t)&&e.children.add(t)})});const m=[];for(c.forEach(e=>{const t=g.get(e);t&&(t.depth=0,m.push(e))});m.length>0;){const e=m.shift();if(!e)continue;const t=g.get(e);t&&t.children.forEach(e=>{const n=g.get(e);if(!n)return;const a=t.depth+1;a>=n.depth||(n.depth=a,m.push(e))})}g.forEach(e=>{if(Number.isFinite(e.depth))return;let t=Number.POSITIVE_INFINITY;e.parents.forEach(e=>{const n=g.get(e);n&&Number.isFinite(n.depth)&&(t=Math.min(t,n.depth+1))}),e.depth=Number.isFinite(t)?t:0});const v=[...g.values()].reduce((e,t)=>Math.max(e,t.depth),0),f=Array.from({length:v+1},()=>[]);g.forEach(e=>{f[e.depth].push(e.slug)});const y=[];g.forEach(e=>{e.children.forEach(t=>{y.push({from:e.slug,to:t,direct:0===e.depth})})});const k={workspaceName:e,nodes:g,edges:y,layers:f,directRuntime:i,directDev:o,directAll:new Set([...i,...o]),bounds:{minX:0,maxX:1,minY:0,maxY:1}};return Xe(k),Ne(k),k}function Xe(e){e.nodes.forEach(e=>{e.amplification=0}),e.nodes.forEach(t=>{if(0!==t.depth)return;if(!e.directAll.has(t.slug))return;const n=new Set,a=[...t.children];for(;a.length>0;){const s=a.pop();if(!s)continue;if(s===t.slug)continue;if(n.has(s))continue;n.add(s);const r=e.nodes.get(s);r&&r.children.forEach(e=>{n.has(e)||a.push(e)})}t.amplification=n.size})}function Ne(e){const t=new Map;e.layers.forEach((n,a)=>{0===a?n.sort((t,n)=>{const a=e.nodes.get(t),s=e.nodes.get(n);if(!a&&!s)return 0;if(!a)return 1;if(!s)return-1;if(a.amplification!==s.amplification)return s.amplification-a.amplification;if(a.kind!==s.kind){if("direct-runtime"===a.kind)return-1;if("direct-runtime"===s.kind)return 1}return a.ref.name.localeCompare(s.ref.name)}):n.sort((n,a)=>{const s=e.nodes.get(n),r=e.nodes.get(a);if(!s&&!r)return 0;if(!s)return 1;if(!r)return-1;const i=(()=>{let e=0,n=0;return s.parents.forEach(a=>{const s=t.get(a);"number"==typeof s&&(e+=1,n+=s)}),e>0?n/e:Number.MAX_SAFE_INTEGER})(),o=(()=>{let e=0,n=0;return r.parents.forEach(a=>{const s=t.get(a);"number"==typeof s&&(e+=1,n+=s)}),e>0?n/e:Number.MAX_SAFE_INTEGER})();return i!==o?i-o:s.ref.name.localeCompare(r.ref.name)}),n.forEach((e,n)=>{t.set(e,n)})});const n=e.layers.reduce((e,t)=>Math.max(e,t.length),1);e.bounds={minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY},e.layers.forEach((t,a)=>{const s=Math.max(0,43*(t.length-1)),r=64+.5*(43*n-s);t.forEach((t,n)=>{const s=e.nodes.get(t);if(!s)return;s.order=n,s.baseX=96+240*a,s.baseY=r+43*n,s.targetX=s.baseX,s.targetY=s.baseY,s.renderX=s.baseX,s.renderY=s.baseY;const i=.55*Math.log(s.children.size+s.parents.size+1),o=0===s.depth&&e.directAll.has(s.slug)?1.05*Math.log(s.amplification+1):0;s.radius=6.7+i+o,s.targetRadius=s.radius,s.renderRadius=s.radius,s.targetLabelChars=u(s.labelGraphemes),s.renderLabelChars=p(s.labelGraphemes),e.bounds.minX=Math.min(e.bounds.minX,s.baseX),e.bounds.maxX=Math.max(e.bounds.maxX,s.baseX),e.bounds.minY=Math.min(e.bounds.minY,s.baseY),e.bounds.maxY=Math.max(e.bounds.maxY,s.baseY)})}),Number.isFinite(e.bounds.minX)||(e.bounds={minX:0,maxX:1,minY:0,maxY:1})}function Te(e,t){if(!r)return;const n=d(Math.max(R,1.35*\$),H,c);R+=(n-R)*(ue?.matches?1:.35),function(e,t){const n=fe(e,t);W=n.x,U=n.y}(.46*K-e*R,.5*J-t*R)}function Re(e){if(!r||!r.nodes.has(e))return;Ee(),o=e;const t=L(r,e),n=I(r,e);y=new Set([e]),t.forEach(e=>{y.add(e)}),n.forEach(e=>{y.add(e)}),P=new Set;const a=[e],s=new Set([e]);for(;a.length>0;){const e=a.pop();if(!e)continue;const t=r.nodes.get(e);t&&t.parents.forEach(t=>{P.add(w(t,e)),s.has(t)||(s.add(t),a.push(t))})}const i=[e],c=new Set([e]);for(;i.length>0;){const e=i.pop();if(!e)continue;const t=r.nodes.get(e);t&&t.children.forEach(t=>{P.add(w(e,t)),c.has(t)||(c.add(t),i.push(t))})}B=new Set(y);const l=r.nodes.get(e);l.parents.forEach(e=>{B.add(e)}),l.children.forEach(e=>{B.add(e)});const u=null===A||null===Y,p=!u&&Boolean(T)&&y.has(T);!u&&p||(A=l.renderX,Y=l.renderY),D=function(e,t,n,a){const s=new Map,r=M(e,t,"parents"),i=M(e,t,"children"),o=new Map;return s.set(t,{x:n,y:a}),y.forEach(a=>{if(a===t)return;const s=e.nodes.get(a);if(!s)return;const c=r.get(a),l=i.get(a);let d=0;"number"==typeof c&&("number"!=typeof l||c<=l)?d=-c:"number"==typeof l&&(d=l),0===d&&(d=s.baseX<n?-1:1);const u=o.get(d)||[];u.push(s),o.set(d,u)}),o.forEach((e,t)=>{e.sort((e,n)=>{const a=t<0?r.get(e.slug)||0:i.get(e.slug)||0,s=t<0?r.get(n.slug)||0:i.get(n.slug)||0;return a!==s?a-s:e.baseY!==n.baseY?e.baseY-n.baseY:e.ref.name.localeCompare(n.ref.name)});const o=d(760/Math.max(1,e.length-1),34,54),c=a-(e.length-1)*o*.5;e.forEach((e,a)=>{const r=170*(1+.78*Math.max(0,Math.abs(t)-1));s.set(e.slug,{x:n+Math.sign(t)*r,y:c+a*o})})}),s}(r,e,A??l.renderX,Y??l.renderY),Te(A??l.renderX,Y??l.renderY),_=!0,ze()}function je(){o=null,y=new Set,P=new Set,B=new Set,D=new Map,A=null,Y=null,ke(),_=!0,ze()}function Ve(e=!0){v=null,X=new Set,N=new Set,e&&(_=!0,ze())}function \$e(){if(!r)return;const e=o&&r.nodes.get(o)||null;r.nodes.forEach(t=>{t.targetRadius=function(e){const t=o===e.slug,n=y.has(e.slug);let a=e.radius;t?a*=1.85:o&&n?a*=1.22:o&&!n?a*=.84:v&&X.has(e.slug)?a*=1.1:v&&(a*=.9);return a}(t),t.targetLabelChars=u(t.labelGraphemes,Boolean(o)&&y.has(t.slug)||!o&&Boolean(v)&&X.has(t.slug));const n=D.get(t.slug);if(e&&n)return t.targetX=n.x,void(t.targetY=n.y);if(!e||!B.has(t.slug))return t.targetX=t.baseX,void(t.targetY=t.baseY);const a=t.baseX-e.baseX,s=t.baseY-e.baseY,r=1+120/(Math.sqrt(a*a+s*s)+1);t.targetX=e.baseX+a*r,t.targetY=e.baseY+s*r})}function He(e){if(o)return;if(v=e,X=new Set,N=new Set,!r||!e||!r.nodes.has(e))return _=!0,void ze();const t=L(r,e),n=I(r,e);X=new Set([e]),t.forEach(e=>{X.add(e)}),n.forEach(e=>{X.add(e)});const a=r.nodes.get(e);a&&(a.parents.forEach(e=>{X.add(e)}),a.children.forEach(e=>{X.add(e)})),r.edges.forEach(e=>{X.has(e.from)&&X.has(e.to)&&N.add(w(e.from,e.to))}),_=!0,ze()}function Oe(t){if(!r)return;const n=r.nodes.get(t);if(!n)return;const a=0===n.depth&&r.directAll.has(n.slug);T=t,e.popoverName.textContent=n.ref.name,e.popoverVersion.textContent=\`Version: \${n.ref.version}\`,e.popoverLicense.textContent=\`License: \${n.ref.license||"Unknown"}\`,e.popoverVulns.textContent=\`Vulnerabilities: \${n.ref.vulnerabilityCount||0}\`,e.popoverAmplification.textContent=a?\`Amplification: \${n.amplification}\`:\`Dependencies: \${n.children.size} • Dependents: \${n.parents.size}\`,e.popover.hidden=!1,We()}function Fe(){T=null,e.popover.hidden=!0}function We(){if(!r||!T||e.popover.hidden)return;const t=r.nodes.get(T);if(!t)return void Fe();const n=t.renderX*R+j,a=t.renderY*R+V,s=e.canvasHost.getBoundingClientRect(),i=e.popover.getBoundingClientRect(),o=Math.max(8,s.width-i.width-8),c=Math.max(8,s.height-i.height-8),l=d(n+14,8,o),u=d(a+14,8,c);e.popover.style.left=\`\${l}px\`,e.popover.style.top=\`\${u}px\`}function Ue(e){return o?y.has(e)?1:.14:v?X.has(e)?1:.16:.95}function Ge(){if(!ne)return;if(ne.setTransform(z,0,0,z,0,0),ne.clearRect(0,0,K,J),!r)return;const e=r,t=me(0)-80,n=me(K)+80,a=ve(0)-80,s=ve(J)+80;ne.setTransform(z*R,0,0,z*R,z*j,z*V);const i=pe.runtime,c=pe.dev,u=pe.transitive,p=pe.edge,g=pe.highlight,m=pe.muted,b=pe.ringHigh,C=pe.ringModerate,E=pe.label,x=pe.backgroundPrimary,S=new Set;e.nodes.forEach(e=>{const r=Math.max(e.radius,e.renderRadius);e.renderX+r>=t&&e.renderX-r<=n&&e.renderY+r>=a&&e.renderY-r<=s&&S.add(e.slug)});const L=[];let I=0;e.nodes.forEach(e=>{if(!S.has(e.slug))return;let t=0;o===e.slug?t=2:(y.has(e.slug)||X.has(e.slug))&&(t=1),L.push({node:e,priority:t,order:I++})}),L.sort((e,t)=>e.priority-t.priority||e.order-t.order);const M=Math.max(0,e.layers.length-1),B={depthNodeIndex:f(e),maxDepth:M,sameColumnXThreshold:6,minDetourVerticalSpan:80,detourInset:14,detourNodeClearance:26,paddingX:96,layerGap:240,edgeCurve:.2},D=[];e.edges.forEach(t=>{const n=e.nodes.get(t.from),a=e.nodes.get(t.to);if(!n||!a)return;if(!S.has(n.slug)&&!S.has(a.slug))return;const s=w(t.from,t.to);D.push({from:n,to:a,highlighted:P.has(s)||!o&&N.has(s),span:Math.abs(a.depth-n.depth)})}),D.sort((e,t)=>t.span-e.span),ne.globalCompositeOperation="source-over",ne.strokeStyle=o||v?m:p,ne.lineWidth=1.05,ne.globalAlpha=o||v? .04*d((R-.35)/.9,.75,1):.25*d((R-.35)/.9,.2,1),ne.beginPath(),D.forEach(e=>{e.highlighted||k(ne,e,B,Boolean(o))}),ne.stroke(),ne.globalCompositeOperation="lighter",ne.strokeStyle=g,ne.lineWidth=1.2,ne.globalAlpha=.36*d((R-.35)/.9,.2,1),ne.beginPath(),D.forEach(e=>{e.highlighted&&k(ne,e,B,Boolean(o))}),ne.stroke(),ne.globalCompositeOperation="source-over";const A=e=>{const t=o===e.slug,n=e.renderRadius;ne.globalAlpha=1,ne.fillStyle=x,ne.beginPath(),ne.arc(e.renderX,e.renderY,n,0,2*Math.PI),ne.fill(),ne.globalAlpha=Ue(e.slug);const a=ne.createRadialGradient(e.renderX-.3*n,e.renderY-.3*n,0,e.renderX,e.renderY,1.2*n);"direct-runtime"===e.kind?(a.addColorStop(0,pe.runtimeHighlight),a.addColorStop(1,i)):"direct-dev"===e.kind?(a.addColorStop(0,pe.devHighlight),a.addColorStop(1,c)):(a.addColorStop(0,pe.transitiveHighlight),a.addColorStop(1,u)),ne.fillStyle=a,ne.beginPath(),ne.arc(e.renderX,e.renderY,n,0,2*Math.PI),ne.fill(),t&&(ne.globalAlpha=.95,ne.strokeStyle=g,ne.lineWidth=1.5,ne.beginPath(),ne.arc(e.renderX,e.renderY,n+4,0,2*Math.PI),ne.stroke())},Y=e=>{if(!e.ref.vulnerabilityCount||e.ref.vulnerabilityCount<=0)return;if("none"===e.ref.vulnerabilitySeverity)return;const t=e.renderRadius,n="high"===e.ref.vulnerabilitySeverity?b:C;var a;ne.save(),ne.translate(e.renderX,e.renderY),ne.globalAlpha=(a=e.slug,o?y.has(a)? .78:.11:v?X.has(a)? .76:.12:.8),ne.strokeStyle=n;const s=t/e.radius,r=t/3*1.2/12,i=1.2*r+3*(s-1),c=Math.max(.5*r,.15),l=Math.max(1*r,.3),d=Math.max(3*r,.8),u=Math.max(1*r,.3),p=Math.max(.5*r,.15),h=t+(2+6*(s-1))+c/2,g=h+c/2+i+l/2,m=g+l/2+i+d/2,f=m+d/2+i+u/2,k=f+u/2+i+p/2;ne.setLineDash([]),ne.lineWidth=p,ne.beginPath(),ne.arc(0,0,k,0,2*Math.PI),ne.stroke(),ne.lineWidth=u,ne.beginPath(),ne.arc(0,0,f,0,2*Math.PI),ne.stroke(),ne.lineWidth=d,ne.beginPath(),ne.arc(0,0,m,0,2*Math.PI),ne.stroke(),ne.lineWidth=l,ne.beginPath(),ne.arc(0,0,g,0,2*Math.PI),ne.stroke(),ne.lineWidth=c,ne.beginPath(),ne.arc(0,0,h,0,2*Math.PI),ne.stroke(),ne.restore()};for(const r of[0,1,2])L.forEach(({node:e,priority:t})=>{t===r&&A(e)}),L.forEach(({node:e,priority:t})=>{t===r&&Y(e)});ne.textBaseline="middle",ne.font=l,ne.fillStyle=E,L.forEach(({node:e})=>{(e=>{const t=h(e);t&&(ne.globalAlpha=Ue(e.slug),ne.fillText(t,e.renderX+e.renderRadius+6,e.renderY))})(e)}),ne.globalAlpha=1,We()}function _e(){if(!G)return void(q=0);\$e();const e=function(){if(!r)return!1;let e=!1;const t=ue?.matches;return r.nodes.forEach(n=>{if(t)return n.renderX=n.targetX,n.renderY=n.targetY,n.renderRadius=n.targetRadius,void(n.renderLabelChars=n.targetLabelChars);const a=o? .18:.15;n.renderX+=(n.targetX-n.renderX)*a,n.renderY+=(n.targetY-n.renderY)*a,n.renderRadius+=.18*(n.targetRadius-n.renderRadius),n.renderLabelChars+=.32*(n.targetLabelChars-n.renderLabelChars),Math.abs(n.targetX-n.renderX)<.06&&Math.abs(n.targetY-n.renderY)<.06&&Math.abs(n.targetRadius-n.renderRadius)<.04&&Math.abs(n.targetLabelChars-n.renderLabelChars)<.12||(e=!0)}),e}(),t=function(e){if(!te.active)return!1;if(!Ce())return Ee(),!1;const t=d(e-te.lastFrameTime||16,1,32);te.lastFrameTime=e,ye(j+te.velocityX*t,V+te.velocityY*t);const n=Math.exp(-.0042*t);return te.velocityX*=n,te.velocityY*=n,_=!0,!(Math.hypot(te.velocityX,te.velocityY)<.02&&(Ee(),1))}(performance.now()),n=null!==W&&null!==U&&(ue?.matches?(ye(W,U),ke(),_=!0,!1):(j+=.12*(W-j),V+=.12*(U-V),ye(j,V),Math.abs((W??j)-j)<.35&&Math.abs((U??V)-V)<.35?(ye(W,U),ke(),_=!0,!1):(_=!0,!0)));if(_||e||t||n)return Ge(),_=!1,void(q=G&&(_||e||t||n)?window.requestAnimationFrame(_e):0);q=0}function qe(){G&&!q&&_&&(q=window.requestAnimationFrame(_e))}function ze(){_=!0,G&&qe()}function Ke(e){const t=Ye(e);t&&(Ee(),i=e,r=t,je(),Fe(),v=null,X=new Set,N=new Set,De(!0),r&&(Ee(),ke(),Me(),R=\$,ye(O,F)),_=!0,ze())}function Je(t){0===t.button&&(Ee(),ke(),Q.down=!0,Q.moved=!1,Q.startX=t.clientX,Q.startY=t.clientY,Q.startPanX=j,Q.startPanY=V,xe(t.clientX,t.clientY,t.timeStamp),De(),e.canvas.classList.add("is-panning"))}function Ze(e){if(!Q.down)return void Ae(e.clientX,e.clientY);const t=e.clientX-Q.startX,n=e.clientY-Q.startY;(Math.abs(t)>2||Math.abs(n)>2)&&(Q.moved=!0),ye(Q.startPanX+t,Q.startPanY+n),Se(e.clientX,e.clientY,e.timeStamp),ze()}function Qe(t){if(!Q.down)return;e.canvas.classList.remove("is-panning");const n=Q.moved;if(Q.down=!1,Q.moved=!1,n)return Le(),te.active?void Be(!1):void Ae(t.clientX,t.clientY);const a=Ae(t.clientX,t.clientY);if(!a)return Ve(!1),je(),void Fe();Re(a.slug),Oe(a.slug)}function et(t){if(!e.canvasHost.contains(t.target))return;t.preventDefault(),Ee();const n=e.canvas.getBoundingClientRect(),a=t.clientX-n.left,s=t.clientY-n.top,r=t.ctrlKey||t.metaKey? .015*t.deltaY:.002*t.deltaY,i=Math.exp(-r);be(R*i,a,s)}function tt(t){if(0===t.touches.length)return;t.preventDefault(),Ee(),ke(),De();const n=e.canvas.getBoundingClientRect();if(1===t.touches.length)ee.active=!0,Q.moved=!1,ee.startX1=t.touches[0].clientX,ee.startY1=t.touches[0].clientY,ee.startPanX=j,ee.startPanY=V,xe(t.touches[0].clientX,t.touches[0].clientY,t.timeStamp),e.canvas.classList.add("is-panning");else if(2===t.touches.length){ee.active=!0,Q.moved=!1,ee.startX1=t.touches[0].clientX,ee.startY1=t.touches[0].clientY,ee.startX2=t.touches[1].clientX,ee.startY2=t.touches[1].clientY;const e=ee.startX2-ee.startX1,a=ee.startY2-ee.startY1;ee.startDist=Math.sqrt(e*e+a*a),ee.startZoom=R;const s=(ee.startX1+ee.startX2)/2,r=(ee.startY1+ee.startY2)/2,i=s-n.left,o=r-n.top;ee.anchorX=i,ee.anchorY=o}}function nt(e){if(ee.active)if(e.preventDefault(),1===e.touches.length){const t=e.touches[0].clientX-ee.startX1,n=e.touches[0].clientY-ee.startY1;(Math.abs(t)>2||Math.abs(n)>2)&&(Q.moved=!0),ye(ee.startPanX+t,ee.startPanY+n),Se(e.touches[0].clientX,e.touches[0].clientY,e.timeStamp),ze()}else if(2===e.touches.length){Ee(),Q.moved=!0;const t=e.touches[0].clientX,n=e.touches[0].clientY,a=e.touches[1].clientX-t,s=e.touches[1].clientY-n,r=Math.sqrt(a*a+s*s);if(ee.startDist>0){const e=r/ee.startDist;be(ee.startZoom*e,ee.anchorX??K/2,ee.anchorY??J/2)}}}function at(e){if(ee.active){if(e.preventDefault(),"touchcancel"===e.type)return Ee(),De(!0),ee.active=!1,ee.anchorX=null,ee.anchorY=null,void(Q.moved=!1);if(0===e.touches.length){if(De(!0),ee.active=!1,ee.anchorX=null,ee.anchorY=null,Q.moved||1!==e.changedTouches.length)Q.moved&&Le();else{const t=Pe(e.changedTouches[0].clientX,e.changedTouches[0].clientY);t?(Re(t.slug),Oe(t.slug)):(Ve(!1),je(),Fe())}Q.moved=!1}else 1===e.touches.length&&(ee.startX1=e.touches[0].clientX,ee.startY1=e.touches[0].clientY,ee.startPanX=j,ee.startPanY=V,xe(e.touches[0].clientX,e.touches[0].clientY,e.timeStamp))}}function st(){He(null),De()}function rt(t){if(!G)return;const n=t.target;e.popover.hidden||e.popover.contains(n)||e.canvasHost.contains(n)||Fe()}function it(e){const t=e.target.closest("button[data-action]");if(!t)return;const n=t.dataset.action;n&&("zoom-in"!==n?"zoom-out"!==n?"pan-left"!==n?"pan-right"!==n?"pan-up"!==n?"pan-down"!==n?"reset"===n&&(Ee(),R=\$,ye(O,F),je(),Fe(),ze()):we(0,52):we(0,-52):we(52,0):we(-52,0):be(R/1.18,.5*K,.5*J):be(1.18*R,.5*K,.5*J))}function ot(){T&&e.onOpenList(T)}function ct(){Ke(e.workspaceSelect.value)}function lt(){G&&(Ie(),K<=1||J<=1||(Me(),R=d(R,H,c),ye(j,V),ze()))}function dt(){ie||(e.workspaceSelect.addEventListener("change",ct),ie=!0),re||(e.controlsRoot.addEventListener("click",it),e.popoverOpenButton.addEventListener("click",ot),re=!0)}return{initGraphView:function(){const a=t.workspaces.length?t.workspaces:[{name:"root",directDependencies:[],directDevDependencies:[]}],s=a.find(e=>"root"===e.name),r=s?[s,...a.filter(e=>"root"!==e.name)]:a;e.workspaceSelect.textContent="",r.forEach((t,n)=>{const a=document.createElement("option");if(a.value=t.name,a.textContent="root"===t.name?"Workspace root":t.name,e.workspaceSelect.appendChild(a),"root"===t.name&&r.length>1&&0===n){const t=document.createElement("option");t.disabled=!0,t.textContent="──────────────",e.workspaceSelect.appendChild(t)}}),e.workspaceWrap.classList.toggle("hidden",a.length<=1),n.has("root")||1!==a.length||n.set("root",a[0]),i=r[0].name,e.workspaceSelect.value=i,he(),function(){if(oe&&oe.disconnect(),oe=new MutationObserver(()=>{he(),ze()}),oe.observe(document.documentElement,{attributes:!0,attributeFilter:["class","data-theme"]}),ce&&(ce.disconnect(),ce=null),le&&(window.removeEventListener("resize",le),le=null),"undefined"!=typeof ResizeObserver)return ce=new ResizeObserver(lt),void ce.observe(e.canvasHost);le=lt,window.addEventListener("resize",le)}(),dt(),ae?(Ie(),Ke(i)):ge()},buildWorkspaceGraph:Ye,computeAmplification:Xe,layoutGraph:Ne,renderLoop:qe,applyFocus:Re,clearFocus:je,showPopover:Oe,hidePopover:Fe,switchWorkspace:Ke,setActive:function(t){if(G=t,G)return ae?(!se&&ae&&(e.canvas.addEventListener("mousedown",Je),window.addEventListener("mousemove",Ze),window.addEventListener("mouseup",Qe),e.canvas.addEventListener("wheel",et,{passive:!1}),e.canvas.addEventListener("touchstart",tt,{passive:!1}),window.addEventListener("touchmove",nt,{passive:!1}),window.addEventListener("touchend",at,{passive:!1}),window.addEventListener("touchcancel",at,{passive:!1}),e.canvas.addEventListener("mouseleave",st),document.addEventListener("mousedown",rt),se=!0),Ie(),K>1&&J>1&&(Me(),R=d(R,H,c),ye(j,V)),qe(),void ze()):void ge();se&&(e.canvas.removeEventListener("mousedown",Je),window.removeEventListener("mousemove",Ze),window.removeEventListener("mouseup",Qe),e.canvas.removeEventListener("wheel",et),e.canvas.removeEventListener("touchstart",tt),window.removeEventListener("touchmove",nt),window.removeEventListener("touchend",at),window.removeEventListener("touchcancel",at),e.canvas.removeEventListener("mouseleave",st),document.removeEventListener("mousedown",rt),De(!0),Q.down=!1,Q.moved=!1,ee.active=!1,ee.anchorX=null,ee.anchorY=null,Ee(),se=!1),Ee(),q&&(window.cancelAnimationFrame(q),q=0)},requestRender:ze}}var B={permissive:["MIT","ISC","BSD-2-Clause","BSD-3-Clause","Apache-2.0","Unlicense","0BSD","CC0-1.0","BSD","Apache","Apache 2.0","Apache License 2.0","MIT License","ISC License"],weakCopyleft:["LGPL-2.1","LGPL-3.0","LGPL-2.0","LGPL","MPL-2.0","MPL-1.1","MPL","EPL-1.0","EPL-2.0","EPL"],strongCopyleft:["GPL-2.0","GPL-3.0","GPL","AGPL-3.0","AGPL","GPL-2.0-only","GPL-3.0-only","GPL-2.0-or-later","GPL-3.0-or-later"]},D={"network-access":"Accesses the network during install","dynamic-exec":"Uses dynamic execution","child-process":"Spawns child processes",encoding:"Uses encoding/decoding logic",obfuscated:"Contains obfuscated/minified install logic","reads-env":"Reads environment variables","reads-home":"Reads user home directory","uses-ssh":"Uses SSH configuration/keys"},A={"bundled-dependencies":"Declares bundled dependencies","embedded-shrinkwrap":"Contains embedded npm-shrinkwrap.json"},Y={"recent-package":"Recently created package","recent-version":"Recently published installed version","low-release-history":"Low release history","reactivated-package":"Reactivated after dormancy","old-major-new-patch":"Recent patch on older major line"};function X(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}function N(e){const t=e.compliance.license,n=t.declared?.valid?t.declared.spdxId:void 0,a=t.inferred?.spdxId;return n?{value:n,isInferred:!1}:a?{value:a,isInferred:!0}:{value:"Unknown",isInferred:!1}}function T(e){const t=e.security;if(t?.summary)return{summary:t.summary,advisories:t.advisories};if(t?.vulnerabilities){const e=t.vulnerabilities;return{summary:{critical:Number(e.critical||0),high:Number(e.high||0),moderate:Number(e.moderate||0),low:Number(e.low||0),highest:e.highest||"none",risk:t.vulnRisk||t.risk||"green"},advisories:t.advisories}}return{summary:{critical:0,high:0,moderate:0,low:0,highest:"none",risk:"green"},advisories:t?.advisories}}function R(e){return e?.highest||"none"}function j(e){return e&&e.risk||"green"}var V={permissive:"green",weakCopyleft:"amber",strongCopyleft:"red",unknown:"gray"},\$={none:0,low:1,moderate:2,high:3,critical:4},H=[{id:"type",label:"Type",sortKey:"type",getValue:e=>e.usage.direct?"Dependency":"Sub-Dependency",getTone:e=>e.usage.direct?"green":"amber",sortFn:(e,t)=>e.usage.direct===t.usage.direct?0:e.usage.direct?-1:1},{id:"scope",label:"Scope",sortKey:"scope",getValue:e=>{return"runtime"===(t=e.usage.scope)?"Runtime":"dev"===t?"Dev":"optional"===t?"Optional":"peer"===t?"Peer":t;var t},getTone:e=>"runtime"===e.usage.scope?"green":"dev"===e.usage.scope||"optional"===e.usage.scope?"amber":"gray",sortFn:(e,t)=>e.usage.scope.localeCompare(t.usage.scope)},{id:"license",label:"License",sortKey:"license",getValue:e=>{const t=N(e),n=t.isInferred?\`\${t.value} (inferred)\`:t.value;return"mismatch"===e.compliance.license.status?\`\${n} *\`:n},getTone:e=>{const t=function(e){if(!e)return"unknown";const t=e.toUpperCase();for(const[n,a]of Object.entries(B))if(a.some(e=>t.includes(e.toUpperCase())))return n;return"unknown"}(N(e).value);return V[t]},sortFn:(e,t)=>{const n=N(e).value,a=N(t).value;return n.localeCompare(a)}},{id:"vulns",label:"Vulnerabilities",sortKey:"severity",getValue:e=>X(R(T(e).summary)),getTone:e=>T(e).summary.risk,sortFn:(e,t)=>\$[R(T(t).summary)]-\$[R(T(e).summary)]},{id:"install",label:"Install",sortKey:"install",getValue:e=>{return(t=e.execution)?X(t.risk||"low"):"Low";var t},getTone:e=>j(e.execution),sortFn:(e,t)=>{const n={green:0,amber:1,red:2},a=j(e.execution),s=j(t.execution);return n[a]-n[s]}},{id:"maintenance",label:"Maintenance",sortKey:"maintenance",getValue:e=>F(e.maintenance?.status),getTone:e=>{return t=e.maintenance?.status,"deprecated"===t||"archived"===t?"red":"unmaintained"===t||"stale"===t||"slowing"===t?"amber":"active"===t?"green":"gray";var t},sortFn:(e,t)=>W(t.maintenance?.status)-W(e.maintenance?.status)}],O={deprecated:"Deprecated",archived:"Archived",unmaintained:"Unmaintained",stale:"Stale",slowing:"Slowing",active:"Active",unknown:"—"};function F(e){return e&&O[e]||"—"}function W(e){return e&&{deprecated:6,archived:5,unmaintained:4,stale:3,slowing:2,active:1}[e]||0}function U(e){const t=e.maintenance?.status;return"deprecated"===t||"archived"===t||"unmaintained"===t||"stale"===t||"slowing"===t}function G(e){return Boolean(e.replacement?.replacements?.length)}function _(e){return"green"!==e.compliance.licenseRisk}function q(e){return Boolean(e.upgrade.blocksNodeMajor||e.upgrade.blockers?.length)}var z=H.length;function K(e){if(!e)return"unknown";const t=e.toUpperCase();for(const[n,a]of Object.entries(B))if(a.some(e=>t.includes(e.toUpperCase())))return n;return"unknown"}function J(e){const t=e.compliance.license,n=t.declared?.valid?t.declared.spdxId:void 0,a=t.inferred?.spdxId;return n?{value:n,isInferred:!1}:a?{value:a,isInferred:!0}:{value:"Unknown",isInferred:!1}}function Z(e){switch(e){case"declared-only":return"Declared";case"inferred-only":return"Inferred";case"match":return"Declared + Inferred (match)";case"mismatch":return"Declared + Inferred (mismatch)";case"invalid-spdx":return"Invalid SPDX";default:return"Unknown"}}var Q={none:0,low:1,moderate:2,high:3,critical:4};function ee(e){const t=e.security;if(t?.summary)return{summary:t.summary,advisories:t.advisories};if(t?.vulnerabilities){const e=t.vulnerabilities;return{summary:{critical:Number(e.critical||0),high:Number(e.high||0),moderate:Number(e.moderate||0),low:Number(e.low||0),highest:e.highest||"none",risk:t.vulnRisk||t.risk||"green"},advisories:t.advisories}}return{summary:{critical:0,high:0,moderate:0,low:0,highest:"none",risk:"green"},advisories:t?.advisories}}function te(e){return e?"Yes":"No"}function ne(e){return e?String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):""}function ae(e){return null!=e&&("string"==typeof e?e.trim().length>0:Array.isArray(e)?e.length>0:"object"!=typeof e||Object.keys(e).length>0)}function se(e){return Array.isArray(e)?e.map(e=>se(e)).join(", "):"boolean"==typeof e?e?"Yes":"No":"object"==typeof e&&null!==e?Object.entries(e).filter(([,e])=>ae(e)).map(([e,t])=>ne(e)+": "+se(t)).join("<br>"):ne(String(e))}function re(e,t){return ae(t)?'<div class="metadata-row"><div class="metadata-row-label">'+ne(e)+'</div><div class="metadata-row-value">'+se(t)+"</div></div>":""}function ie(e,t){const n=t.filter(Boolean);return 0===n.length?"":'<section class="metadata-section"><div class="metadata-section-title">'+ne(e)+'</div><div class="metadata-grid">'+n.join("")+"</div></section>"}function oe(e){const t=e.workspaces;if(!t||!t.enabled)return ie("Workspaces",[re("Enabled",!1),re("Type",t?.type)]);const n=t.workspacePackages||[],a=n.length?'<div class="metadata-list">'+n.map(e=>'<div class="metadata-list-item"><div class="metadata-row-value">'+ne(e.name)+'</div><div class="metadata-muted">'+ne(e.relativePath)+" · runtime "+ne(String(e.directExternal.runtime))+" · dev "+ne(String(e.directExternal.dev))+"</div></div>").join("")+"</div>":"";return ie("Workspaces",[re("Enabled",t.enabled),re("Type",t.type),re("Package count",t.packageCount),a?'<div class="metadata-row"><div class="metadata-row-label">Packages</div><div>'+a+"</div></div>":""])}function ce(e){const t=e.supplyChain;if(!t)return"";const n=t.signatureAudit;return ie("Supply Chain",[re("Signals",t.signals?.length),n?re("Signature audit",{attempted:n.attempted,ok:n.ok,status:n.status,error:n.error}):""])}function le(e){return"runtime"===e?"Runtime":"dev"===e?"Dev":"optional"===e?"Optional":"peer"===e?"Peer":e}function de(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}function ue(e){return e.split(/[\\s-_]+/).map(e=>e?de(e):e).join(" ")}function pe(e){return H.map(t=>{return n=t.label,a=t.getValue(e),'<div class="badge-card '+t.getTone(e)+'"><span class="badge-label">'+ne(n)+'</span><span class="badge-value">'+ne(a)+"</span></div>";var n,a}).join("")}function he(e,t){const n=H.map(n=>function(e,t,n,a){const s=n===e,r=s?a?" ▲":" ▼":"",i=s?a?" sorted-asc":" sorted-desc":"";return'<button type="button" class="column-header'+(s?" sorted":"")+i+'" data-sort="'+ne(e)+'"><span class="column-header-label">'+ne(t)+'</span><span class="sort-indicator">'+r+"</span></button>"}(n.sortKey,n.label,e,t)).join("");return'<div class="column-headers" style="--column-count: '+z+'">'+n+"</div>"}function ge(e,t,n){let a='<div class="kv-item">';return a+='<span class="kv-label">'+ne(e)+"</span>",a+='<span class="kv-value">'+ne(String(t))+"</span>",n&&(a+='<span class="kv-hint">'+ne(n)+"</span>"),a+="</div>",a}function me(e,t){return'<span class="kv-value risk-value"><span class="risk-dot '+t+'"></span>'+ne(String(e))+"</span>"}function ve(e,t="neutral"){return'<span class="status-chip '+t+'">'+ne(e)+"</span>"}function fe(e,t,n){const s=a(t),r=e.execution?.risk||"green",i=e.upgrade.blocksNodeMajor||!!e.upgrade.blockers?.length;return'<div class="status-chip-strip">'+[ve(e.usage.direct?"Direct dependency":"Transitive dependency"),ve(le(e.usage.scope)),ve(s>0?"Vulnerability: "+ue(t.highest):"Vulnerability: None","green"===t.risk?"neutral":t.risk),ve("Licence: "+n,"green"===e.compliance.licenseRisk?"neutral":e.compliance.licenseRisk),ve("Install risk: "+Ye(r),"green"===r?"neutral":r),ve(i?"Upgrade blocker":"No upgrade blocker",i?"amber":"neutral")].join("")+"</div>"}function ye(e,t,n){let a='<div class="kv-item">';return a+='<span class="kv-label">'+ne(e)+"</span>",a+=t,n&&(a+='<span class="kv-hint">'+ne(n)+"</span>"),a+="</div>",a}function ke(e,t){if(!e||0===e.length)return'<span class="kv-value">None</span>';const n=e.slice(0,t),a=e.length-t;let s='<div class="package-list">';return n.forEach(e=>{s+='<span class="package-tag">'+ne(e)+"</span>"}),a>0&&(s+='<span class="package-tag">+'+a+" more</span>"),s+="</div>",s}function be(e,t,n,a){if(!e||0===e.length)return'<span class="kv-value">None</span>';const s=e.slice(0,t),r=e.length-t;let i='<div class="package-list">';return s.forEach(e=>{const t=Ie(e,n,a);i+=t?'<a class="package-tag package-tag-link root-package-link" href="#'+ne(xe(t))+'" data-dep-key="'+ne(t)+'" aria-label="Jump to dependency '+ne(t)+'">'+ne(e)+"</a>":'<span class="package-tag">'+ne(e)+"</span>"}),r>0&&(i+='<span class="package-tag">+'+r+" more</span>"),i+="</div>",i}function we(e,t){return e+"@"+t}var Ce=new WeakMap;function Ee(e){const t=e.lastIndexOf("@npm:");if(t>0)return{name:e.slice(0,t),version:e.slice(t+1)};const n=e.lastIndexOf("@");return n<=0?null:{name:e.slice(0,n),version:e.slice(n+1)}}function xe(e){return\`dep-\${e}\`}function Se(e){const t=Ce.get(e);if(t)return t;const n=new Map;return e.forEach(e=>{const t=Ee(e);if(!t)return;const a=n.get(t.name)||[];a.push(e),n.set(t.name,a)}),Ce.set(e,n),n}function Le(e,t,n){const a=((n||Se(t)).get(e)||[]).filter(e=>t.has(e));return 1===a.length?a[0]:null}function Ie(e,t,n){if(t.has(e))return e;const a=Ee(e);if(!a)return Le(e,t,n);if(a.version.startsWith("npm:")){const e=a.version.slice(4),n=a.name+(e.startsWith("@")?e:"@"+e);if(t.has(n))return n}return Le(a.name,t,n)}function Me(e,t){if(t.has(e))return e;const n=Ee(e);if(!n)return null;if(n.version.startsWith("npm:")){const e=n.version.slice(4),a=n.name+(e.startsWith("@")?e:"@"+e);if(t.has(a))return a}return null}function Pe(e,t,n,a){if(!e||0===e.length)return'<span class="kv-value">None</span>';const s=e.slice(0,t),r=e.length-t;let i='<div class="package-list">';return s.forEach(e=>{if("string"==typeof e){const t=Ie(e,n,a);return t?void(i+='<a class="package-tag package-tag-link root-package-link" href="#'+ne(xe(t))+'" data-dep-key="'+ne(t)+'" aria-label="Jump to dependency '+ne(t)+'">'+ne(e)+"</a>"):void(i+='<span class="package-tag">'+ne(e)+"</span>")}const t=we(e.name,e.version),s=e.name+"@"+e.version,r=Ie(t,n,a);i+=r?'<a class="package-tag package-tag-link root-package-link" href="#'+ne(xe(r))+'" data-dep-key="'+ne(r)+'" aria-label="Jump to dependency '+ne(r)+'">'+ne(s)+"</a>":'<span class="package-tag">'+ne(s)+"</span>"}),r>0&&(i+='<span class="package-tag">+'+r+" more</span>"),i+="</div>",i}function Be(e,t,n){const a=e.graph.subDeps;if(!a)return"";const s=[{title:"Dependencies",key:"dep"},{title:"Optional",key:"opt"},{title:"Peer",key:"peer"},{title:"Dev Dependencies",key:"dev"}];let r=0,i=0;for(const l of s){const e=a[l.key];if(e)for(const t of Object.values(e))r+=1,t[1]&&(i+=1)}if(0===r)return"";const o='<div class="declared-summary">Total: '+r+" • Installed: "+i+" • Not installed: "+(r-i)+"</div>",c=s.map(e=>{const s=a[e.key];if(!s||0===Object.keys(s).length)return"";let r=0,i=0;const o=Object.entries(s).sort(([e],[t])=>e.localeCompare(t)).map(([e,[a,s]])=>{r+=1,s&&(i+=1);const o='<div class="declared-name">'+ne(e)+"</div>",c='<div class="declared-range">'+ne(a)+"</div>",l=s?function(e,t,n){const a=Ie(e,t,n);return a?'<a class="status-pill installed root-package-link" href="#'+ne(xe(a))+'" data-dep-key="'+ne(a)+'" aria-label="Jump to dependency '+ne(a)+'">Installed</a>':'<span class="status-pill installed">Installed</span>'}(s,t,n):'<span class="status-pill missing">Not installed</span>';return'<div class="declared-row">'+o+c+l+"</div>"}),c=i+" of "+r+" installed";return['<details class="declared-group">','<summary class="declared-group-summary"><span class="expand-icon" aria-hidden="true"></span><span class="declared-group-title">'+ne(e.title)+' <span class="declared-count">('+c+")</span></span></summary>",'<div class="declared-table">'+o.join("")+"</div>","</details>"].join("")}).filter(Boolean);return De("Declared Dependencies","Dependencies declared by this package",o+'<div class="declared-deps">'+c.join("")+"</div>")}function De(e,t,n){let a='<div class="section">';return a+='<div class="section-header">',a+='<span class="section-title">'+ne(e)+"</span>",t&&(a+='<span class="section-desc">'+ne(t)+"</span>"),a+="</div>",a+=n,a+="</div>",a}function Ae(e,t,n,a){let s='<div class="subsection'+(a?" "+a:"")+'">';return s+='<div class="subsection-header">',s+='<span class="subsection-title">'+ne(e)+"</span>",n&&(s+='<span class="subsection-desc">'+ne(n)+"</span>"),s+="</div>",s+=t,s+="</div>",s}function Ye(e){return"red"===e?"High":"amber"===e?"Medium":"Low"}var Xe={native:"Native platform functionality",documented:"Lighter community alternative",simple:"Small inline snippet"};function Ne(e){return e&&0!==e.length?Ae("Supply chain source",'<div class="section-note">Shown only when lockfile source metadata is unusual or incomplete.</div><div class="kv-grid">'+e.map(e=>{return ge({"git-dependency":"Git dependency source","file-dependency":"Local dependency source","non-registry-tarball":"Non-registry tarball","missing-integrity":"Missing lockfile integrity","unexpected-registry-host":"Unexpected registry host"}[t=e.type]||ue(t),e.source,e.detail);var t}).join("")+"</div>","Lockfile source signals","warning"):""}function Te(e){if(!e)return;const t=e.trim();if(!t)return;const n=e=>e.replace(/\\.git\$/i,"");if(/^https?:\\/\\//i.test(t))return n(t);if(/^git\\+https?:\\/\\//i.test(t))return n(t.replace(/^git\\+/,""));if(/^git:\\/\\/github\\.com\\//i.test(t))return n(t.replace(/^git:\\/\\//i,"https://"));if(/^github:/i.test(t)){const e=t.slice(7).replace(/^\\/+/,"");return e?\`https://github.com/\${n(e)}\`:void 0}if(/^git@github\\.com:/i.test(t)){const e=t.slice(15);return e?\`https://github.com/\${n(e)}\`:void 0}return/^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+\$/.test(t)?\`https://github.com/\${n(t)}\`:void 0}function Re(e,t){const n=Te(e);if(!n)return;let a;try{a=new URL(n)}catch{return}if("github.com"!==a.hostname.toLowerCase())return;const s=a.pathname.split("/").filter(Boolean);if(s.length<2)return;const r=s[0],i=s[1].replace(/\\.git\$/i,"");return r&&i?\`https://github.com/\${r}/\${i}/blob/HEAD/\${t}\`:void 0}function je(e,t){return t?ne(e)+' <a class="kv-inline-link" href="'+ne(t)+'" target="_blank" rel="noopener noreferrer">GitHub<svg class="kv-inline-link-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M7 17 17 7"/><path d="M9 7h8v8"/></svg></a>':ne(e)}function Ve(e){if(e)try{const t=new URL(e);if("https:"!==t.protocol&&"http:"!==t.protocol)return;return t.username="",t.password="",t.toString()}catch{return}}function \$e(e){const t='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.332h-2.669v-.001zm12.001 0h-1.33v-4h-1.336v4h-1.335v-4h-1.33v4h-2.671V8.667h8.002v5.331zM10.665 10H12v2.667h-1.335V10z"/></svg>',n='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg>',a='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',s='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>';if(!(e.npm||e.repository||e.homepage||e.issues))return"";let r='<div class="package-links">';const i=Ve(e.npm),o=Ve(e.repository),c=Ve(e.homepage),l=Ve(e.issues);return i||o||c||l?(i&&(r+='<a href="'+ne(i)+'" target="_blank" rel="noopener" class="package-link">'+t+"npm</a>"),o&&(r+='<a href="'+ne(o)+'" target="_blank" rel="noopener" class="package-link">'+n+"Repository</a>"),c&&(r+='<a href="'+ne(c)+'" target="_blank" rel="noopener" class="package-link">'+s+"Homepage</a>"),l&&(r+='<a href="'+ne(l)+'" target="_blank" rel="noopener" class="package-link">'+a+"Issues</a>"),r+="</div>",r):""}function He(e,n){const a=function(e,n,a=0,r){const i=e.execution?.risk||"green",o=t(e,s(e.package.name,r)),c=o.some(e=>"error"===e.severity)?"red":o.length>0?"amber":"green",l=a>0||(e.packaging?.signals?.length||0)>0?"amber":"green",d=(e.supplyChain?.registry?.signals?.length||0)>0?"amber":"green",u=e.maintenance?.status,p="deprecated"===u||"archived"===u?"red":"unmaintained"===u?"amber":"green";return(h=[n.risk,e.compliance.licenseRisk,i,l,c,d,p]).includes("red")?"red":h.includes("amber")?"amber":"green";var h}(e,ee(e).summary,n?.length||0,n),r=we(e.package.name,e.package.version),i=xe(r),o=pe(e),c=['<summary class="dep-summary">','<span class="expand-icon" aria-hidden="true"></span>','<span class="dep-name">'+ne(e.package.name)+'<span class="dep-version">@'+ne(e.package.version)+"</span></span>",'<div class="dep-indicators" style="--column-count: '+z+'">',o,"</div>","</summary>"].join("");return['<details class="dep-card" data-risk="'+a+'" data-dep-key="'+ne(r)+'" id="'+ne(i)+'">',c,'<div class="dep-details" data-rendered="false"></div>',"</details>"].join("")}function Oe(e,t,n,s){const r=ee(e),o=r.summary,c=J(e),l=c.isInferred?\`\${c.value} (inferred)\`:c.value,d=function(e){const t=e.package?.links||{},n=e.links||{},a=Te(t.repository||n.repository||n.repo);return{npm:t.npm||n.npm,repository:a||t.repository||n.repository||n.repo,homepage:t.homepage||n.homepage,issues:t.bugs||t.issues||n.bugs||n.issues}}(e),u=JSON.stringify(e,null,2),p=e.usage.origins.workspaces?.length?'<div class="micro-sublist"><div class="micro-subtitle">Workspaces</div>'+ke(e.usage.origins.workspaces,8)+"</div>":"",h=e.package.description?'<p class="dep-description"><span>Description: </span>'+ne(e.package.description)+"</p>":"";var g,m;const v=De("Overview",void 0,'<div class="definition-grid">'+[ge("Dependency status",e.usage.direct?"Direct dependency":"Transitive dependency"),ge("Scope",le(e.usage.scope)),e.usage.introduction?ge("Introduced by",ue(e.usage.introduction)):"",e.usage.runtimeImpact?ge("Runtime impact",(m=e.usage.runtimeImpact,m?ue(m):"")):"",ge("Dependency depth",e.usage.depth),e.usage.direct?"":ye("Introduced via root packages",Pe(e.usage.origins.topRootPackages,8,t,n)),e.usage.direct?"":ge("Direct roots",e.usage.origins.rootPackageCount),e.usage.direct?"":ye("Direct parents",be(e.usage.origins.topParentPackages,8,t,n)),e.usage.direct?"":ge("Direct parents count",e.usage.origins.parentPackageCount??0),ge("TypeScript types",(g=e.usage.tsTypes,"bundled"===g?"Bundled":"definitelyTyped"===g?"DefinitelyTyped":"none"===g?"None":"Unknown"))].filter(Boolean).join("")+"</div>"+p+function(e,t,n,a){if(!t||0===t.length)return"";const s=t.slice(0,n),r=t.length-n;let i='<div class="detail-list">';return i+='<div class="detail-title">'+ne(e)+"</div>",i+='<ul class="detail-items'+(a?" "+a:"")+'">',s.forEach(e=>{i+='<li class="detail-item">'+ne(e)+"</li>"}),r>0&&(i+='<li class="detail-item muted">+'+r+" more</li>"),i+="</ul></div>",i}("Top import locations",e.usage.importUsage?.topFiles,5,"mono")),f=e.compliance.license,y=Re(d.repository,"package.json"),k=Re(d.repository,"LICENSE"),b=[ye("Primary license",me(l,e.compliance.licenseRisk)),ge("Status",Z(f.status))];if(f.declared){const e=[f.declared.valid?"valid":"invalid",f.declared.expression?"expression":void 0,f.declared.deprecated?"deprecated":void 0].filter(Boolean).join(", "),t=f.exception?.id?\` WITH \${f.exception.id}\`:"";b.push(ye("Declared SPDX in package.json",'<span class="kv-value">'+je(\`\${f.declared.spdxId}\${t}\${e?\` (\${e})\`:""}\`,y)+"</span>"))}f.inferred&&b.push(ye("Inferred from LICENSE file",'<span class="kv-value">'+je(\`\${f.inferred.spdxId} (\${f.inferred.confidence})\`,k)+"</span>")),"mismatch"===f.status&&b.push(ge("Mismatch","Declared SPDX and LICENSE text do not match")),"invalid-spdx"===f.status&&b.push(ge("Invalid SPDX","Package.json license is not a valid SPDX identifier or expression"));const w=Ae("License",'<div class="kv-grid">'+b.join("")+"</div>"),C=a(o),E=[ye("Vulnerability status",me(0===C?"No known vulnerabilities":String(C),o.risk)),ge("Highest severity","none"===o.highest?"None":ue(o.highest))],x=C>0?'<div class="kv-grid kv-grid-tight">'+[ge("Critical",o.critical),ge("High",o.high),ge("Moderate",o.moderate),ge("Low",o.low)].join("")+"</div>":"",S=function(e){if(!e||0===e.length)return"";let t='<table class="vuln-table"><thead><tr>';return t+="<th>Title</th><th>Severity</th><th>Affected range</th><th>Fix available</th><th>Reference</th>",t+="</tr></thead><tbody>",e.forEach(e=>{const n=ne(e.title),a=Ve(e.url),s=a?'<a href="'+ne(a)+'" target="_blank" rel="noopener">Link</a>':"";t+='<tr data-severity="'+ne(e.severity)+'">',t+='<td data-label="Title">'+n+"</td>",t+='<td data-label="Severity">'+ne(de(e.severity))+"</td>",t+='<td data-label="Affected range">'+ne(e.vulnerableRange)+"</td>",t+='<td data-label="Fix available">'+ne(e.fixAvailable?"Yes":"No")+"</td>",t+='<td data-label="Reference">'+s+"</td>",t+="</tr>"}),t+="</tbody></table>",t}(r.advisories),L=Ae("Vulnerabilities",['<div class="kv-grid">'+E.join("")+"</div>",x||"",S||""].join(""),"Known security issues from npm audit","vuln-block"),I=e.execution?function(e){const t=[ye("Execution risk",me(Ye(e.risk),e.risk))];if(e.native&&t.push(ge("Native build tooling detected (native)","Yes")),e.scripts?.hooks?.length&&t.push(ye("Lifecycle hooks",ke(e.scripts.hooks,6))),"number"==typeof e.scripts?.complexity&&t.push(ge("Heuristic complexity","Script complexity: "+e.scripts.complexity+" (complexity)")),e.scripts?.signals?.length){const n=e.scripts.signals.map(e=>\`\${D[e]} (\${e})\`);t.push(ye("Install-time signals",ke(n,6)))}const n=(e.signals||[]).filter(t=>!(e.scripts?.signals||[]).includes(t));if(n.length){const e=n.map(e=>\`\${D[e]} (\${e})\`);t.push(ye("Local execution signals",ke(e,6)))}return Ae("Install-time execution behaviour",'<div class="section-note">Execution behaviour signals are local static review cues from lifecycle scripts, entry files, package bins, or a small bounded set of package files. They do not imply compromise.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.execution):"",M=function(e){if(!e?.signals?.length)return"";const t=[ye("Packaging signals",ke(e.signals.map(e=>\`\${A[e]} (\${e})\`),6))];return e.bundledDependencies?.length&&t.push(ye("Bundled dependencies",ke(e.bundledDependencies,8))),Ae("Package contents",'<div class="section-note">Packaging signals describe local package structure that may warrant review; they are not malware verdicts.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.packaging),P=function(e){if(!e?.attempted)return"";const t=[ge("Lookup",e.ok?"Available":"Unavailable"),ye("Candidate reasons",ke(e.candidateReasons||[],6))];if(e.error&&t.push(ge("Error",e.error)),e.signals?.length){const n=e.signals.map(e=>\`\${Y[e]} (\${e})\`);t.push(ye("Registry signals",ke(n,6)))}return e.installedVersionPublishedAt&&t.push(ge("Installed version published",e.installedVersionPublishedAt)),e.packageCreatedAt&&t.push(ge("Package created",e.packageCreatedAt)),"number"==typeof e.versionCount&&t.push(ge("Published versions",e.versionCount)),e.latestVersion&&t.push(ge("Latest dist-tag",e.latestVersion)),Ae("Registry metadata",'<div class="section-note">Targeted npm registry metadata is collected only for packages that already show local review signals, and is skipped in offline scans.</div><div class="kv-grid">'+t.join("")+"</div>")}(e.supplyChain?.registry),B=De("Risk & Compliance",void 0,w+L+function(e){if(!e?.attempted)return"";const t=[ge("Status",F(e.status))];if(e.deprecated){const n=e.deprecated.installedVersion?"Installed version":"Latest version";t.push(ge("Deprecated",n,e.deprecated.message))}void 0!==e.repoArchived&&t.push(ge("Repository archived",te(e.repoArchived),e.repoCheckedAt?\`Checked \${e.repoCheckedAt}\`:void 0)),e.packageModifiedAt&&t.push(ge("Last registry activity",e.packageModifiedAt,"number"==typeof e.monthsSinceModified?\`~\${e.monthsSinceModified} months ago\`:void 0)),e.repoPushedAt&&t.push(ge("Last repository push",e.repoPushedAt,"number"==typeof e.monthsSinceRepoPush?\`~\${e.monthsSinceRepoPush} months ago\`:void 0)),e.latestVersion&&t.push(ge("Latest version",e.latestVersion)),e.fetchedAt&&t.push(ge("Data fetched",e.fetchedAt+(e.fromCache?" (cached)":""))),e.error&&t.push(ge("Error",e.error));const n="deprecated"===e.status||"archived"===e.status?"warning":void 0;return Ae("Maintenance",'<div class="section-note">Conservative registry heuristics: "last registry activity" updates on any packument write, so age-based statuses under-flag rather than over-flag. When a repository push timestamp is also known, both surfaces must be quiet before a package escalates past "slowing". Review cues, not verdicts.</div><div class="kv-grid">'+t.join("")+"</div>",void 0,n)}(e.maintenance)+I+M+P+Ne(s)),N=[ge("Outdated status",(T=e.upgrade.outdatedStatus,T?"unknown"===T?"Unknown":ue(T):"Not reported"))];var T;e.upgrade.latestVersion&&N.push(ge("Latest version",e.upgrade.latestVersion)),e.upgrade.risk&&N.push(ge("Upgrade risk",X(e.upgrade.risk),"Derived from outdated status and known blockers"));const R=Ae("Version",'<div class="section-note">Based on npm outdated findings and registry metadata.</div><div class="kv-grid">'+N.join("")+"</div>"),j=e.package.deprecated&&!e.maintenance?.deprecated?Ae("Deprecated",'<div class="kv-grid">'+ge("Deprecated","Yes","Declared by the package author.")+"</div>",void 0,"warning"):"",V=[ge("Node engine constraint",e.upgrade.nodeEngine||"Any")];void 0!==e.upgrade.blocksNodeMajor&&V.push(ge("Blocks Node major upgrade",te(e.upgrade.blocksNodeMajor)));const \$=Ae("Constraints",'<div class="kv-grid">'+V.join("")+"</div>"),H=Ae("Blast radius",'<div class="kv-grid">'+[ge("Used by other packages (fanIn)",e.graph.fanIn),ge("Depends on packages (fanOut)",e.graph.fanOut)].join("")+"</div>"),O={nodeEngine:"Node engine constraint",peerDependency:"Peer dependency constraints",nativeBindings:"Native bindings/build tooling",installScripts:"Install lifecycle scripts",deprecated:"Deprecated by author"},W='<div class="subsection"><div class="subsection-header"><span class="subsection-title">Upgrade blockers</span></div>'+(e.upgrade.blockers?.length?'<ul class="bullet-list">'+e.upgrade.blockers.map(e=>"<li>"+ne(O[e]||e)+"</li>").join("")+"</ul>":'<div class="status-row">No upgrade blockers detected</div>')+"</div>",U=De("Upgrade & Change Impact","Currency, constraints, and blast radius",function(e){if(!e?.replacements?.length)return"";const t=[ge("Suggested",e.replacements.join(", ")),ge("Replacement type",Xe[e.type]||e.type)],n=e.docUrl?'<div class="section-note"><a href="'+ne(e.docUrl)+'" target="_blank" rel="noopener noreferrer">Migration guidance for this replacement</a></div>':"";return Ae("Replacement available",'<div class="kv-grid">'+t.join("")+"</div>"+n+'<div class="section-note">Suggestion from the community-maintained <a href="https://github.com/es-tooling/module-replacements" target="_blank" rel="noopener noreferrer">module-replacements</a> catalogue, part of the <a href="https://e18e.dev" target="_blank" rel="noopener noreferrer">e18e</a> ecosystem performance initiative. Guidance to review, not a drop-in instruction.</div>',"Community-suggested lighter or native alternative")}(e.replacement)+R+j+\$+H+W),G=Be(e,t,n);return[\$e(d),h,fe(e,o,l),(_=i(e,o,s),['<div class="key-points">','<div class="section-header compact"><span class="section-title">Key points</span></div>','<ul class="key-points-list">',_.map(e=>"<li>"+ne(e)+"</li>").join(""),"</ul>","</div>"].join("")),v,B,U,G,'<details class="raw-data-toggle"><summary><span class="expand-icon" aria-hidden="true"></span>View raw data</summary><div class="raw-data-pane"><pre>'+ne(u)+'</pre><button type="button" class="copy-json-btn" aria-label="Copy raw JSON">Copy JSON</button></div></details>'].join("");var _}async function Fe(){const e=await async function(){const e=document.getElementById("radar-data");return e&&e.textContent&&"{}"!==e.textContent.trim()?JSON.parse(e.textContent):(await fetch("./sample-data.json")).json()}();void 0===window.__DEPENDENCY_DATA__&&(window.__DEPENDENCY_DATA__=e);const t=document.getElementById("dependency-list"),n=document.getElementById("results-summary"),a=document.getElementById("scan-status-banner");if(a&&e.scanStatus?.warnings.length){a.hidden=!1;const t=document.createElement("strong");t.textContent=e.scanStatus.complete?"Some analysis was intentionally skipped":"Scan evidence is incomplete",a.appendChild(t);const n=document.createElement("ul");e.scanStatus.warnings.slice(0,8).forEach(e=>{const t=document.createElement("li");t.textContent=e.length>300?\`\${e.slice(0,297)}…\`:e,n.appendChild(t)}),a.appendChild(n)}const s=document.getElementById("project-path");s&&(s.textContent=e.project.name||e.project.projectDir,s.title=e.project.projectDir);const r=document.getElementById("metadata-toggle"),i=document.getElementById("metadata-panel"),c=document.getElementById("formatted-date");let l=e.generatedAt||"";if(c&&e.generatedAt)try{const t=new Date(e.generatedAt);Number.isNaN(t.getTime())?(l=e.generatedAt,c.textContent=e.generatedAt):(l=new Intl.DateTimeFormat(void 0,{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"}).format(t),c.textContent=l)}catch{l=e.generatedAt,c.textContent=e.generatedAt}i&&(i.innerHTML=function(e,t){const n=e.environment||{},a=n.minRequiredMajor,s=a&&a>0?"Node requirement derived from dependency engine ranges.":"";return[ie("Report",[re("Dependency Radar",e.dependencyRadarVersion),re("Schema",e.schemaVersion),re("Generated",t||e.generatedAt),re("Generated raw",e.generatedAt)]),ie("Project",[re("Name",e.project.name),re("Version",e.project.version),re("Path",e.project.projectDir),re("Description",e.project.description),re("License",e.project.license),re("Homepage",e.project.homepage),re("Repository",e.project.repository),re("Constraints",e.project.constraints),re("Dependency policy",e.project.dependencyPolicySummary)]),ie("Git",[re("Branch",e.git?.branch)]),ie("Environment",[re("Node",n.nodeVersion),re("Runtime",n.runtimeVersion),re("Minimum required Node major",n.minRequiredMajor),re("Target Node major",n.targetNodeMajor),re("Platform",n.platform),re("Architecture",n.arch),re("CI",n.ci),re("packageManager field",n.packageManagerField),re("Package manager",n.packageManager),re("Package manager version",n.packageManagerVersion),re("Tool versions",n.toolVersions),re("Node note",s)]),oe(e),ie("Summary",[re("Dependencies",e.summary?.dependencyCount),re("Direct",e.summary?.directCount),re("Transitive",e.summary?.transitiveCount),re("Findings",e.summary?.findingCount)]),ie("Scan evidence",[re("Complete",e.scanStatus?.complete),re("Collectors",e.scanStatus?.collectors),re("Warnings",e.scanStatus?.warnings)]),ce(e)].filter(Boolean).join("")}(e,l),i.hidden=!1,i.inert=!0,i.setAttribute("aria-hidden","true"));const d=e=>{r&&i&&(i.classList.toggle("open",e),i.inert=!e,i.setAttribute("aria-hidden",String(!e)),r.classList.toggle("open",e),r.setAttribute("aria-expanded",String(e)))};r?.addEventListener("click",()=>{const e=!i?.classList.contains("open");d(e)}),document.addEventListener("click",e=>{if(!r||!i)return;if(!i.classList.contains("open"))return;const t=e.target;r.contains(t)||i.contains(t)||d(!1)}),document.addEventListener("keydown",e=>{"Escape"===e.key&&d(!1)});const u={search:document.getElementById("search"),direct:document.getElementById("direct-filter"),runtime:document.getElementById("runtime-filter"),workspace:document.getElementById("workspace-filter"),workspaceWrap:document.getElementById("workspace-filter-wrap"),sort:document.getElementById("sort-by"),sortDirection:document.getElementById("sort-direction"),hasVulns:document.getElementById("has-vulns"),maintenanceConcerns:document.getElementById("maintenance-concerns"),licenseIssues:document.getElementById("license-issues"),upgradeBlockers:document.getElementById("upgrade-blockers"),hasReplacement:document.getElementById("has-replacement"),hasReplacementWrap:document.getElementById("has-replacement-wrap"),themeSwitch:document.getElementById("theme-switch"),licenseToggle:document.getElementById("license-toggle"),licensePanel:document.getElementById("license-panel"),licensePermissive:document.getElementById("license-permissive"),licenseWeakCopyleft:document.getElementById("license-weak-copyleft"),licenseStrongCopyleft:document.getElementById("license-strong-copyleft"),licenseUnknown:document.getElementById("license-unknown"),licenseAll:document.getElementById("license-all"),licenseFriendly:document.getElementById("license-friendly"),filtersToggle:document.getElementById("filters-toggle"),filterCountBadge:document.getElementById("filter-count-badge"),filterControls:document.getElementById("filter-controls"),activeFiltersRow:document.getElementById("active-filters-row"),activeFilterChips:document.getElementById("active-filter-chips"),activeFilterClear:document.getElementById("active-filter-clear"),clearAllFilters:document.getElementById("clear-all-filters"),licensePermissiveLabel:document.getElementById("license-permissive-label"),licenseWeakCopyleftLabel:document.getElementById("license-weak-copyleft-label"),licenseStrongCopyleftLabel:document.getElementById("license-strong-copyleft-label"),licenseUnknownLabel:document.getElementById("license-unknown-label"),hasVulnsLabel:document.getElementById("has-vulns-label"),maintenanceConcernsLabel:document.getElementById("maintenance-concerns-label"),licenseIssuesLabel:document.getElementById("license-issues-label"),upgradeBlockersLabel:document.getElementById("upgrade-blockers-label"),hasReplacementLabel:document.getElementById("has-replacement-label"),columnHeadersContainer:document.getElementById("column-headers-container"),packageHeader:document.getElementById("package-header"),viewGraphButton:document.getElementById("view-graph-btn"),graphBackButton:document.getElementById("graph-back-btn"),listViewPanel:document.getElementById("list-view"),graphViewPanel:document.getElementById("graph-view"),graphWorkspaceSelect:document.getElementById("graph-workspace"),graphWorkspaceWrap:document.getElementById("graph-workspace-wrap"),graphControls:document.getElementById("graph-controls"),graphCanvas:document.getElementById("graph-canvas"),graphCanvasShell:document.getElementById("graph-canvas-shell"),graphPopover:document.getElementById("graph-popover"),graphPopoverName:document.getElementById("graph-popover-name"),graphPopoverVersion:document.getElementById("graph-popover-version"),graphPopoverLicense:document.getElementById("graph-popover-license"),graphPopoverVulns:document.getElementById("graph-popover-vulns"),graphPopoverAmplification:document.getElementById("graph-popover-amplification"),graphOpenList:document.getElementById("graph-open-list"),reportFooter:document.querySelector(".report-footer")};let p="name",h=!0,g=null,m=!1;document.documentElement.setAttribute("data-theme","dark"),"light"===localStorage.getItem("dependency-radar-theme")?(document.documentElement.classList.add("light"),u.themeSwitch.classList.add("light"),u.themeSwitch.setAttribute("aria-pressed","true"),document.documentElement.setAttribute("data-theme","light")):(document.documentElement.classList.remove("light"),u.themeSwitch.classList.remove("light"),u.themeSwitch.setAttribute("aria-pressed","false"),document.documentElement.setAttribute("data-theme","dark")),u.themeSwitch.addEventListener("click",()=>{document.documentElement.classList.toggle("light"),u.themeSwitch.classList.toggle("light");const e=document.documentElement.classList.contains("light");document.documentElement.setAttribute("data-theme",e?"light":"dark"),u.themeSwitch.setAttribute("aria-pressed",String(e)),localStorage.setItem("dependency-radar-theme",e?"light":"dark"),g?.requestRender()});const v=window.matchMedia("(max-width: 768px)");let f=v.matches;const y=e=>{u.filterControls&&u.filtersToggle&&(u.filterControls.classList.toggle("open",e),u.filterControls.inert=!e,u.filterControls.setAttribute("aria-hidden",String(!e)),u.filtersToggle.classList.toggle("open",e),u.filtersToggle.setAttribute("aria-expanded",String(e)),e&&d(!1))},k=()=>{if(v.matches)return y(!1),void(f=!0);f&&y(!1),f=!1};function b(){if(u.columnHeadersContainer&&(u.columnHeadersContainer.innerHTML=he(p,h)),u.packageHeader){const e=u.packageHeader.querySelector(".sort-indicator");e&&("name"===p?(e.textContent=h?" ▲":" ▼",u.packageHeader.classList.add("sorted")):(e.textContent="",u.packageHeader.classList.remove("sorted")))}}function w(e){const t=e.target.closest(".column-header");if(!t)return;const n=t.dataset.sort;n&&(p===n?h=!h:(p=n,h=!0),u.sort&&(u.sort.value=p,u.sortDirection.textContent=h?"↑":"↓"),b(),O())}u.filtersToggle&&u.filterControls&&u.filtersToggle.addEventListener("click",()=>{const e=!u.filterControls.classList.contains("open");y(e)}),document.addEventListener("click",e=>{if(!u.filterControls||!u.filtersToggle)return;const t=e.target;u.filterControls.contains(t)||u.filtersToggle.contains(t)||y(!1)}),document.addEventListener("keydown",e=>{"Escape"===e.key&&y(!1)}),y(!1),window.addEventListener("resize",k),k(),u.sortDirection.addEventListener("click",()=>{h=!h,u.sortDirection.textContent=h?"↑":"↓",b(),O()}),u.sort.addEventListener("change",()=>{p=u.sort.value,b(),O()}),u.columnHeadersContainer&&u.columnHeadersContainer.addEventListener("click",w),u.packageHeader&&u.packageHeader.addEventListener("click",w),b(),u.licenseAll.addEventListener("click",()=>{u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!0,u.licenseStrongCopyleft.checked=!0,u.licenseUnknown.checked=!0,X.clear(),O()}),u.licenseFriendly.addEventListener("click",()=>{u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!1,u.licenseStrongCopyleft.checked=!1,u.licenseUnknown.checked=!1,X.clear(),O()});const C=Object.values(e.dependencies||{}),E=e=>{const t=e.usage.origins.workspaces||[];return t.length>0?t:["root"]},x=Array.from(new Set([...o(e),...C.flatMap(E)])).sort((e,t)=>"root"===e?-1:"root"===t?1:e.localeCompare(t)),S=(e,t)=>e+" ("+t+")",L=e=>{return Q[t=ee(e).summary,t?.highest||"none"]>0;var t},I=e=>C.reduce((t,n)=>t+(e(n)?1:0),0);if(u.workspace&&u.workspaceWrap&&x.length>1){u.workspace.textContent="";const e=document.createElement("option");e.value="all",e.textContent=S("All workspaces",C.length),u.workspace.appendChild(e),x.forEach(e=>{const t=document.createElement("option");t.value=e,t.textContent=S("root"===e?"Workspace root":e,I(t=>E(t).includes(e))),u.workspace.appendChild(t)}),u.workspaceWrap.classList.remove("hidden")}!function(){const e=C.length;u.direct.options[0].textContent=S("All",e),u.direct.options[1].textContent=S("Direct",I(e=>e.usage.direct)),u.direct.options[2].textContent=S("Transitive",I(e=>!e.usage.direct));const t={all:"All",runtime:"Production",dev:"Development",optional:"Optional",peer:"Peer"};Array.from(u.runtime.options).forEach(n=>{n.textContent=S(t[n.value]||n.textContent||n.value,"all"===n.value?e:I(e=>e.usage.scope===n.value))});const n={permissive:0,weakCopyleft:0,strongCopyleft:0,unknown:0};C.forEach(e=>{n[K(J(e).value)]+=1}),u.licensePermissiveLabel&&(u.licensePermissiveLabel.textContent=S("Permissive",n.permissive)),u.licenseWeakCopyleftLabel&&(u.licenseWeakCopyleftLabel.textContent=S("Weak Copyleft",n.weakCopyleft)),u.licenseStrongCopyleftLabel&&(u.licenseStrongCopyleftLabel.textContent=S("Strong Copyleft",n.strongCopyleft)),u.licenseUnknownLabel&&(u.licenseUnknownLabel.textContent=S("Other / Unknown",n.unknown)),u.hasVulnsLabel&&(u.hasVulnsLabel.textContent=S("Has vulnerabilities",I(L))),u.maintenanceConcernsLabel&&(u.maintenanceConcernsLabel.textContent=S("Maintenance concerns",I(U))),u.licenseIssuesLabel&&(u.licenseIssuesLabel.textContent=S("Licence issues",I(_))),u.upgradeBlockersLabel&&(u.upgradeBlockersLabel.textContent=S("Upgrade blockers",I(q)));const a=I(G);u.hasReplacementWrap&&(u.hasReplacementWrap.hidden=0===a),u.hasReplacementLabel&&a>0&&(u.hasReplacementLabel.textContent=S("Has replacement suggestion",a))}(),function(){const t=document.getElementById("header-stats");if(!t)return;let n=0,a=0,s=0,r=!1,i=0,o=0,c=0;C.forEach(e=>{if(L(e)&&(n+=1),G(e)&&(c+=1),e.maintenance?.attempted&&(r=!0),U(e)){a+=1;const t=e.maintenance?.status;"deprecated"!==t&&"archived"!==t||(s+=1)}_(e)&&(i+=1),q(e)&&(o+=1)});const l=(e,t,n,a)=>{const s=document.getElementById(e);if(!s)return;const r=s.querySelector("strong");r&&(r.textContent=String(t)),s.classList.remove("red","amber"),n&&t>0&&s.classList.add(n),a&&(s.title=a)};l("stat-total",e.summary.dependencyCount,void 0,\`\${e.summary.directCount} direct, \${e.summary.transitiveCount} transitive\`),l("stat-vulnerable",n,"red","Dependencies with known vulnerabilities — click to filter");const d=(e,t,n)=>{const a=document.getElementById(e);if(!a)return;a.hidden=!1,a.disabled=!0,a.classList.remove("red","amber");const s=a.querySelector("strong");s&&(s.textContent="?"),a.title=\`\${n} is unknown because its collector is \${t}\`},p=e.scanStatus?.collectors.audit;p&&"available"!==p&&d("stat-vulnerable",p,"Vulnerability status"),l("stat-license",i,"amber","Dependencies with licence review flags — click to filter"),l("stat-blockers",o,"amber","Dependencies with upgrade blockers — click to filter");const h=document.getElementById("stat-replacements");h&&(0===c?h.hidden=!0:(h.hidden=!1,l("stat-replacements",c,void 0,"Dependencies with community-suggested replacements (e18e) — click to filter")));const g=document.getElementById("stat-maintenance");if(g){const t=e.scanStatus?.collectors.maintenance;t&&"available"!==t?d("stat-maintenance",t,"Maintenance status"):r?l("stat-maintenance",a,s>0?"red":"amber","Deprecated, archived, unmaintained, or stale dependencies — click to filter"):g.hidden=!0}t.addEventListener("click",e=>{const t=e.target.closest("[data-stat-filter]");if(!t)return;if(t.disabled)return;const n={"has-vulns":u.hasVulns,"maintenance-concerns":u.maintenanceConcerns,"license-issues":u.licenseIssues,"upgrade-blockers":u.upgradeBlockers,"has-replacement":u.hasReplacement}[t.dataset.statFilter||""];if(!n)return;const a=n.checked;u.search.value="",V(),n.checked=!a,n.dispatchEvent(new Event("change"))})}();const M=new Map;C.forEach(e=>{M.set(we(e.package.name,e.package.version),e)});const B=new Set(M.keys()),D=Se(B),A=function(e,t,n){const a=new Map,s=(e,t)=>{const n=a.get(e)||[];n.push(t),a.set(e,n)};for(const r of e.supplyChain?.signals||[]){const e=[r.packageId,r.packageName&&r.packageVersion?we(r.packageName,r.packageVersion):void 0].filter(Boolean);let a=!1;for(const n of e){const e=Me(n,t);if(e){s(e,r),a=!0;break}}if(!a&&r.packageName&&!r.packageVersion){const e=Le(r.packageName,t,n);e&&s(e,r)}}return a}(e,B,D),Y=new Set,X=new Set,N=new Map,T=(()=>{const e=document.getElementById("copy-announcer");if(e)return e;const t=document.createElement("div");return t.id="copy-announcer",t.className="sr-only",t.setAttribute("aria-live","polite"),document.body.appendChild(t),t})();function R(e){const t=e.dataset.depKey;if(!t)return;const n=e.querySelector(".dep-details");if(!n||"true"===n.dataset.rendered)return;const a=M.get(t);a&&(n.setAttribute("aria-busy","true"),n.innerHTML=['<div class="dep-loading" role="presentation">','<div class="dep-loading-bar"></div>',"</div>"].join(""),requestAnimationFrame(()=>{n.innerHTML=Oe(a,B,D,A.get(t)),n.dataset.rendered="true",n.removeAttribute("aria-busy")}))}function j(e){return(e.selectedOptions[0]?.textContent||"").replace(/\\s+\\(\\d+\\)\$/,"")}function V(){u.direct.value="all",u.runtime.value="all",u.workspace&&(u.workspace.value="all"),u.hasVulns.checked=!1,u.maintenanceConcerns&&(u.maintenanceConcerns.checked=!1),u.licenseIssues&&(u.licenseIssues.checked=!1),u.upgradeBlockers&&(u.upgradeBlockers.checked=!1),u.hasReplacement&&(u.hasReplacement.checked=!1),u.licensePermissive.checked=!0,u.licenseWeakCopyleft.checked=!0,u.licenseStrongCopyleft.checked=!0,u.licenseUnknown.checked=!0}function \$(){const e=[],t=u.search.value.trim();return t&&e.push({id:"search",label:"Search: "+t,remove:()=>{u.search.value=""}}),"all"!==u.direct.value&&e.push({id:"type",label:"Type: "+j(u.direct),remove:()=>{u.direct.value="all"}}),"all"!==u.runtime.value&&e.push({id:"scope",label:"Scope: "+j(u.runtime),remove:()=>{u.runtime.value="all"}}),u.workspace&&"all"!==u.workspace.value&&e.push({id:"workspace",label:"Workspace: "+j(u.workspace),remove:()=>{u.workspace.value="all"}}),[{id:"license-permissive",checked:u.licensePermissive.checked,label:"License: Permissive",reset:()=>{u.licensePermissive.checked=!0}},{id:"license-weak-copyleft",checked:u.licenseWeakCopyleft.checked,label:"License: Weak Copyleft",reset:()=>{u.licenseWeakCopyleft.checked=!0}},{id:"license-strong-copyleft",checked:u.licenseStrongCopyleft.checked,label:"License: Strong Copyleft",reset:()=>{u.licenseStrongCopyleft.checked=!0}},{id:"license-unknown",checked:u.licenseUnknown.checked,label:"License: Other / Unknown",reset:()=>{u.licenseUnknown.checked=!0}}].forEach(t=>{t.checked||e.push({id:t.id,label:t.label,remove:t.reset})}),u.hasVulns.checked&&e.push({id:"has-vulns",label:"Has vulnerabilities",remove:()=>{u.hasVulns.checked=!1}}),u.maintenanceConcerns?.checked&&e.push({id:"maintenance-concerns",label:"Maintenance concerns",remove:()=>{u.maintenanceConcerns&&(u.maintenanceConcerns.checked=!1)}}),u.licenseIssues?.checked&&e.push({id:"license-issues",label:"Licence issues",remove:()=>{u.licenseIssues&&(u.licenseIssues.checked=!1)}}),u.upgradeBlockers?.checked&&e.push({id:"upgrade-blockers",label:"Upgrade blockers",remove:()=>{u.upgradeBlockers&&(u.upgradeBlockers.checked=!1)}}),u.hasReplacement?.checked&&e.push({id:"has-replacement",label:"Has replacement suggestion",remove:()=>{u.hasReplacement&&(u.hasReplacement.checked=!1)}}),e}function O(){!function(){const e=\$(),t=e.length;u.filtersToggle.classList.toggle("has-active-filters",t>0),u.filterCountBadge&&(u.filterCountBadge.hidden=0===t,u.filterCountBadge.textContent=String(t)),u.activeFiltersRow&&u.activeFilterChips&&(u.activeFiltersRow.hidden=0===t,u.activeFilterChips.innerHTML=e.map(e=>'<span class="active-filter-chip">'+ne(e.label)+'<button type="button" class="active-filter-remove" data-filter-chip="'+ne(e.id)+'" aria-label="Remove '+ne(e.label)+'">×</button></span>').join(""))}();const a=function(e){const t=[...e];if("name"===p)t.sort((e,t)=>e.package.name.localeCompare(t.package.name));else if("depth"===p)t.sort((e,t)=>e.usage.depth-t.usage.depth);else{const e=H.find(e=>e.sortKey===p||e.id===p);e?.sortFn?t.sort(e.sortFn):e&&t.sort((t,n)=>e.getValue(t).localeCompare(e.getValue(n)))}return h||t.reverse(),t}(function(){const e=(u.search.value||"").toLowerCase(),t=u.direct.value,n=u.runtime.value,a=u.workspace?.value||"all",s=u.hasVulns.checked,r=u.maintenanceConcerns?.checked??!1,i=u.licenseIssues?.checked??!1,o=u.upgradeBlockers?.checked??!1,c=u.hasReplacement?.checked??!1,l=u.licensePermissive.checked,d=u.licenseWeakCopyleft.checked,p=u.licenseStrongCopyleft.checked,h=u.licenseUnknown.checked;return C.filter(u=>{const g=we(u.package.name,u.package.version);if(X.has(g))return!0;const m=J(u),v=[m.value,u.compliance.license.declared?.spdxId,u.compliance.license.inferred?.spdxId].filter(Boolean).join(" ").toLowerCase();if(e&&!u.package.name.toLowerCase().includes(e)&&!v.includes(e))return!1;if("direct"===t&&!u.usage.direct)return!1;if("transitive"===t&&u.usage.direct)return!1;if("all"!==n&&u.usage.scope!==n)return!1;if("all"!==a&&!E(u).includes(a))return!1;if(s&&!L(u))return!1;if(r&&!U(u))return!1;if(i&&!_(u))return!1;if(o&&!q(u))return!1;if(c&&!G(u))return!1;const f=K(m.value);return!("permissive"===f&&!l||"weakCopyleft"===f&&!d||"strongCopyleft"===f&&!p||"unknown"===f&&!h)})}()),s=e.summary?.dependencyCount||C.length;n.innerHTML="Showing <strong>"+a.length+"</strong> of <strong>"+s+"</strong> dependencies","all"!==(u.workspace?.value||"all")&&(n.innerHTML+=" in <strong>"+ne(u.workspace.value)+"</strong>"),0!==a.length?(t.innerHTML=a.map(e=>He(e,A.get(we(e.package.name,e.package.version)))).join(""),N.clear(),t.querySelectorAll("details.dep-card").forEach(e=>{const t=e.dataset.depKey;t&&N.set(t,e)}),Y.forEach(e=>{const t=N.get(e);t&&(t.open||(t.open=!0),R(t))})):t.innerHTML='<div class="empty-state"><div class="empty-state-icon">📦</div><div class="empty-state-text">No dependencies match your filters</div></div>'}function F(e){const t=D.get(e)||[];return 1===t.length?t[0]:null}function W(e){if(M.has(e))return e;const t=Ee(e);if(!t)return F(e);if(t.version.startsWith("npm:")){const e=t.version.slice(4),n=t.name+(e.startsWith("@")?e:"@"+e);if(M.has(n))return n}return F(t.name)}function z(t){if(!u.listViewPanel||!u.graphViewPanel)return void console.warn("Dependency Radar: view panels are missing from the report DOM.");const n="list"===t;n||Boolean(u.graphWorkspaceSelect&&u.graphWorkspaceWrap&&u.graphControls&&u.graphCanvas&&u.graphCanvasShell&&u.graphPopover&&u.graphPopoverName&&u.graphPopoverVersion&&u.graphPopoverLicense&&u.graphPopoverVulns&&u.graphPopoverAmplification&&u.graphOpenList)?(u.listViewPanel.classList.toggle("active",n),u.graphViewPanel.classList.toggle("active",!n),u.listViewPanel.setAttribute("aria-hidden",String(!n)),u.graphViewPanel.setAttribute("aria-hidden",String(n)),u.viewGraphButton&&(u.viewGraphButton.style.display=n?"":"none"),u.graphBackButton&&(u.graphBackButton.style.display=n?"none":""),u.reportFooter?.classList.toggle("hidden",!n),document.body.classList.toggle("graph-mode",!n),n?g?.setActive(!1):(m||(g=P({report:e,knownDepKeys:B,resolveDepKey:W,workspaceSelect:u.graphWorkspaceSelect,workspaceWrap:u.graphWorkspaceWrap,controlsRoot:u.graphControls,canvas:u.graphCanvas,canvasHost:u.graphCanvasShell,popover:u.graphPopover,popoverName:u.graphPopoverName,popoverVersion:u.graphPopoverVersion,popoverLicense:u.graphPopoverLicense,popoverVulns:u.graphPopoverVulns,popoverAmplification:u.graphPopoverAmplification,popoverOpenButton:u.graphOpenList,onOpenList:e=>{!function(e){z("list");let t=document.getElementById(xe(e));!t&&M.has(e)&&(X.add(e),O(),t=document.getElementById(xe(e)));if(!t)return;if(t instanceof HTMLDetailsElement){const e=t.dataset.depKey;e&&Y.add(e),t.open||(t.open=!0),R(t)}t.classList.add("dep-list-highlight"),Z(t,!0),window.setTimeout(()=>{t?.classList.remove("dep-list-highlight")},2e3)}(e)}}),g.initGraphView(),m=!0),g?.setActive(!0),g?.requestRender())):console.warn("Dependency Radar: graph view DOM nodes are missing; graph view disabled.")}function Z(e,t=!1){const n=()=>{const n=window.scrollY+e.getBoundingClientRect().top-function(){const e=document.querySelector(".filter-bar");return!e||document.body.classList.contains("graph-mode")?0:Math.ceil(e.getBoundingClientRect().height+8)}();if(window.scrollTo({top:Math.max(0,n),behavior:"smooth"}),t){const t=e.querySelector("summary");t&&t.focus({preventScroll:!0})}};requestAnimationFrame(()=>{n(),window.setTimeout(n,60)})}const te=[u.search,u.direct,u.runtime,u.sort,u.hasVulns,u.maintenanceConcerns,u.licenseIssues,u.upgradeBlockers,u.hasReplacement,u.workspace,u.licensePermissive,u.licenseWeakCopyleft,u.licenseStrongCopyleft,u.licenseUnknown],ae=()=>{X.clear(),O()};te.forEach(e=>{e&&(e.addEventListener("input",ae),e.addEventListener("change",ae))}),u.activeFilterChips?.addEventListener("click",e=>{const t=e.target.closest("[data-filter-chip]");if(!t)return;const n=\$().find(e=>e.id===t.dataset.filterChip);n&&(n.remove(),ae())});const se=()=>{u.search.value="",V(),ae()};function le(e){const t=e.getAttribute("data-dep-key");if(!t)return;const n=W(t);if(!n)return;let a=N.get(n);a||(X.add(n),O(),a=N.get(n)),a&&(Y.add(n),a.open||(a.open=!0),R(a),Z(a,!0))}u.activeFilterClear?.addEventListener("click",se),u.clearAllFilters?.addEventListener("click",se),u.viewGraphButton?.addEventListener("click",()=>{z("graph")}),u.graphBackButton?.addEventListener("click",()=>{z("list")}),t.addEventListener("toggle",e=>{const t=e.target;if(!(t instanceof HTMLDetailsElement))return;if(!t.classList.contains("dep-card"))return;const n=t.dataset.depKey;n&&(t.open?(Y.add(n),R(t)):Y.delete(n))},!0),t.addEventListener("click",e=>{const t=e.target,n=t.closest(".root-package-link");if(n)return e.preventDefault(),void le(n);const a=t.closest(".copy-json-btn");a&&(e.preventDefault(),async function(e){const t=(e.closest(".raw-data-toggle")?.querySelector("pre"))?.textContent??"";if(t)try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(t);else{const e=document.createElement("textarea");e.value=t,e.setAttribute("readonly","true"),e.style.position="absolute",e.style.left="-9999px",document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e)}const n=e.dataset.label||e.textContent||"Copy JSON";e.dataset.label=n,e.textContent="Copied",e.classList.add("copied"),T.textContent="Copied JSON to clipboard.",window.setTimeout(()=>{e.textContent=n,e.classList.remove("copied")},1500)}catch{T.textContent="Copy failed."}}(a))}),t.addEventListener("keydown",e=>{const t=e.target.closest(".root-package-link");t&&(" "!==e.key&&"Spacebar"!==e.key||(e.preventDefault(),le(t)))}),b(),O(),z("list")}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",Fe):Fe()}();`;

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep supply-chain combinations version-qualified.

The bundle indexes source signals by package name, discarding packageId versions before deriving combinations. If foo@1 is git-sourced and foo@2 is registry-sourced, both can receive the same install-script combination finding. Index by packageId first and only fall back to name when the source signal is genuinely unversioned; then regenerate this asset.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/report-assets.ts` at line 16, Update the source-signal indexing logic in
function s so packageId is used as the primary key, preserving its
version-qualified identity when deriving install-script combinations; fall back
to packageName only when packageId is absent. Ensure combination lookup in
function i uses the same packageId-first keying, then regenerate the JS_CONTENT
bundle asset.

Comment thread src/supplyChainCombos.ts Outdated
JosephMaynard and others added 6 commits July 23, 2026 12:47
…der, 1.7 in UI types

- Supply-chain combo signals are now indexed by version-qualified package
  identity (packageId, falling back to name@version, then bare name only
  for version-less signals), so a source signal on one installed version no
  longer implicates a different version's install hooks. Callers in
  findings, failOn, and reportDetailRules look up via the dependency's own
  id; added cross-version regression coverage at both the combo and
  fail-on level.
- Header stat grid uses column auto-flow so the optional Replacements chip
  renders as a sixth equal column on desktop instead of wrapping; the
  mobile two-column layout is unchanged.
- report-ui schemaVersion type now includes '1.7'.
- Rebuilt dist/ and the embedded report assets.

Not changed: applyUpgradeRisk already runs unconditionally inside
aggregateData, so upgrade.risk is derived from local outdated/blocker data
even when no enrichment runs; the cli.ts call is only the post-enrichment
recompute.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The validate-output-schemas CI fixture hardcoded schemaVersion '1.6' and
failed against the 1.7 const in the report schema. Use the exported
REPORT_SCHEMA_VERSION so the fixture can never drift from the schema again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… ajv)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The final console.log interpolated values CodeQL traces back to fetched
manifest data. Coerce the count to a number and log the static output path
so the new error-level alert stops blocking merges under the code-scanning
ruleset.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The flagged sink was console.error(err) in the catch handler, not the
success log: fetch/parse errors can embed response-derived text. Log the
message with newlines removed, the sanitizer the query recognizes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread scripts/build-replacements.ts Fixed
…itizer

The query's StringReplaceSanitizer only matches a replace of the literal
newline with an empty string; the previous character-class-with-space form
satisfied neither condition, so the alert reappeared on the new line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@JosephMaynard
JosephMaynard merged commit 80b5d20 into master Jul 23, 2026
5 checks passed
@JosephMaynard
JosephMaynard deleted the feature/port-saas-analysis branch July 24, 2026 21:33
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