@westbayberry/dg 1.2.1 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2568,9 +2568,9 @@ function loadDgrc() {
2568
2568
  `);
2569
2569
  }
2570
2570
  }
2571
- if (cwdPath !== homePath && existsSync2(cwdPath) && process.env.DG_QUIET !== "1") {
2571
+ if (cwdPath !== homePath && existsSync2(cwdPath)) {
2572
2572
  process.stderr.write(
2573
- `dg: note: ./.dgrc.json is ignored (repo-controlled config is no longer honored). Use ~/.dg/.dgrc.json, env vars (DG_MODE, DG_API_URL), or CLI flags.
2573
+ `dg: note: ./.dgrc.json is ignored (repo-controlled config is no longer honored). Use ~/.dg/.dgrc.json or CLI flags.
2574
2574
  `
2575
2575
  );
2576
2576
  }
@@ -2668,7 +2668,7 @@ function parseConfig(argv, strictFlags = true) {
2668
2668
  const apiKey = dgrc.apiKey && typeof dgrc.apiKey === "string" && (dgrc.apiKey.startsWith("dg_live_") || dgrc.apiKey.startsWith("dg_test_")) ? dgrc.apiKey : null;
2669
2669
  const isProtectiveWrapper = command === "npm" || command === "pip";
2670
2670
  const defaultMode = isProtectiveWrapper ? "block" : "warn";
2671
- const modeRaw = values.mode ?? process.env.DG_MODE ?? dgrc.mode ?? defaultMode;
2671
+ const modeRaw = values.mode ?? dgrc.mode ?? defaultMode;
2672
2672
  if (!["block", "warn", "off"].includes(modeRaw)) {
2673
2673
  process.stderr.write(
2674
2674
  `Error: Invalid mode "${modeRaw}". Must be block, warn, or off.
@@ -2696,7 +2696,7 @@ function parseConfig(argv, strictFlags = true) {
2696
2696
  sarif: values.sarif || false,
2697
2697
  scanAll: !values["changed-only"],
2698
2698
  baseLockfile: values["base-lockfile"] ?? null,
2699
- workspace: values.workspace ?? process.env.DG_WORKSPACE ?? null,
2699
+ workspace: values.workspace ?? null,
2700
2700
  outputFile: values.output ?? null,
2701
2701
  command,
2702
2702
  debug,
@@ -2705,7 +2705,6 @@ function parseConfig(argv, strictFlags = true) {
2705
2705
  quiet: (() => {
2706
2706
  if (values["no-quiet"]) return false;
2707
2707
  if (values.quiet) return true;
2708
- if (process.env.DG_QUIET === "1") return true;
2709
2708
  if (process.env.CI === "1" || process.env.CI === "true") return true;
2710
2709
  return false;
2711
2710
  })(),
@@ -2814,8 +2813,7 @@ var init_config = __esm({
2814
2813
  --api-url <url> API base URL (default: https://api.westbayberry.com)
2815
2814
 
2816
2815
  Install-wrapper flags (work on \`npm install\`, \`pip install\`, etc.):
2817
- --dg-force Bypass a block (audit-visible \u2014 record it)
2818
- --dg-force-reason "..." Reason recorded with the override
2816
+ --dg-force Bypass a block (audit-visible)
2819
2817
  --dg-no-scripts Add \`--ignore-scripts\` to the real install
2820
2818
  --strict Strongest protection: implies --dg-no-scripts and
2821
2819
  refuses any partial-coverage scan
@@ -2824,16 +2822,11 @@ var init_config = __esm({
2824
2822
  DG_API_KEY CI auth token (dg_live_* or dg_test_*).
2825
2823
  Used when ~/.dg/config.json is absent.
2826
2824
  File beats env if both are present.
2827
- DG_API_URL API base URL
2828
- DG_MODE Mode (block | warn | off)
2829
- DG_DEBUG=1 Enable debug output
2830
- DG_QUIET=1 Same as passing --quiet
2831
- DG_WORKSPACE Workspace subdirectory to scan
2832
- DG_TELEMETRY=0 Opt out of anonymous crash reports (on by default; DO_NOT_TRACK=1 also opts out)
2833
- DG_FORCE_POSTINSTALL=1 Force postinstall to run even outside a TTY
2834
- (useful for re-running setup manually)
2825
+ DG_TELEMETRY=0 Opt out of anonymous crash reports (on by default;
2826
+ DO_NOT_TRACK=1 also opts out)
2835
2827
  DG_NO_RC_EDIT=1 Postinstall installs shims but does not edit
2836
2828
  shell rc files; you set PATH yourself
2829
+ NO_COLOR=1 Disable colored output
2837
2830
  CI=1 Auto-enables --ci output mode + --quiet
2838
2831
 
2839
2832
  Exit Codes:
@@ -2850,8 +2843,8 @@ var init_config = __esm({
2850
2843
  if the verdict permits. Top-level versions are pinned to the
2851
2844
  exact version we scanned (TOCTOU defense).
2852
2845
  - Warn verdict in a TTY: shows findings and prompts \`Proceed? (Y/n)\`.
2853
- - Block verdict: refuses install, prints the override command.
2854
- Override always requires \`--dg-force-reason\`.
2846
+ - Block verdict: refuses install, prints the override command
2847
+ (re-run with \`--dg-force\` to install anyway).
2855
2848
  - Read-only subcommands (npm view, pip show, pnpm list, etc.) skip
2856
2849
  the wrapper entirely \u2014 fast pass-through to the real binary.
2857
2850
  - \`dg scan\` is read-only and never blocks. It does not consume
@@ -2864,7 +2857,7 @@ var init_config = __esm({
2864
2857
  bun add some-pkg
2865
2858
  uv pip install numpy
2866
2859
  pipx install black
2867
- npm install risky-pkg --dg-force --dg-force-reason="emergency hotfix"
2860
+ npm install risky-pkg --dg-force
2868
2861
  dg scan --json | jq # CI-friendly
2869
2862
  dg status # see what's protected
2870
2863
  `.trimStart();
@@ -4006,7 +3999,6 @@ dg publish-check \u2014 scan a package about to be published
4006
3999
 
4007
4000
  Usage:
4008
4001
  dg publish-check [--ecosystem npm|pypi] [--json] [--dg-force]
4009
- [--dg-force-reason <text>]
4010
4002
 
4011
4003
  What it does:
4012
4004
  Scans the package artifact you're about to publish for bundled secrets,
@@ -4018,7 +4010,6 @@ Flags:
4018
4010
  --ecosystem <npm|pypi> Force ecosystem detection
4019
4011
  --json JSON output to stdout
4020
4012
  --dg-force Bypass block verdict (audited)
4021
- --dg-force-reason <text> Reason string stored with override
4022
4013
 
4023
4014
  Exit codes:
4024
4015
  0 pass No risks detected
@@ -14039,7 +14030,7 @@ var require_react_reconciler_development = __commonJS({
14039
14030
  var HostPortal = 4;
14040
14031
  var HostComponent = 5;
14041
14032
  var HostText = 6;
14042
- var Fragment6 = 7;
14033
+ var Fragment7 = 7;
14043
14034
  var Mode = 8;
14044
14035
  var ContextConsumer = 9;
14045
14036
  var ContextProvider = 10;
@@ -14179,7 +14170,7 @@ var require_react_reconciler_development = __commonJS({
14179
14170
  return "DehydratedFragment";
14180
14171
  case ForwardRef:
14181
14172
  return getWrappedName$1(type, type.render, "ForwardRef");
14182
- case Fragment6:
14173
+ case Fragment7:
14183
14174
  return "Fragment";
14184
14175
  case HostComponent:
14185
14176
  return type;
@@ -17313,7 +17304,7 @@ var require_react_reconciler_development = __commonJS({
17313
17304
  }
17314
17305
  }
17315
17306
  function updateFragment2(returnFiber, current2, fragment, lanes, key) {
17316
- if (current2 === null || current2.tag !== Fragment6) {
17307
+ if (current2 === null || current2.tag !== Fragment7) {
17317
17308
  var created = createFiberFromFragment(fragment, returnFiber.mode, lanes, key);
17318
17309
  created.return = returnFiber;
17319
17310
  return created;
@@ -17716,7 +17707,7 @@ var require_react_reconciler_development = __commonJS({
17716
17707
  if (child.key === key) {
17717
17708
  var elementType = element.type;
17718
17709
  if (elementType === REACT_FRAGMENT_TYPE) {
17719
- if (child.tag === Fragment6) {
17710
+ if (child.tag === Fragment7) {
17720
17711
  deleteRemainingChildren(returnFiber, child.sibling);
17721
17712
  var existing = useFiber(child, element.props.children);
17722
17713
  existing.return = returnFiber;
@@ -23207,7 +23198,7 @@ var require_react_reconciler_development = __commonJS({
23207
23198
  var _resolvedProps2 = workInProgress2.elementType === type ? _unresolvedProps2 : resolveDefaultProps(type, _unresolvedProps2);
23208
23199
  return updateForwardRef(current2, workInProgress2, type, _resolvedProps2, renderLanes2);
23209
23200
  }
23210
- case Fragment6:
23201
+ case Fragment7:
23211
23202
  return updateFragment(current2, workInProgress2, renderLanes2);
23212
23203
  case Mode:
23213
23204
  return updateMode(current2, workInProgress2, renderLanes2);
@@ -23644,7 +23635,7 @@ var require_react_reconciler_development = __commonJS({
23644
23635
  case SimpleMemoComponent:
23645
23636
  case FunctionComponent:
23646
23637
  case ForwardRef:
23647
- case Fragment6:
23638
+ case Fragment7:
23648
23639
  case Mode:
23649
23640
  case Profiler:
23650
23641
  case ContextConsumer:
@@ -28412,7 +28403,7 @@ var require_react_reconciler_development = __commonJS({
28412
28403
  return fiber;
28413
28404
  }
28414
28405
  function createFiberFromFragment(elements, mode, lanes, key) {
28415
- var fiber = createFiber(Fragment6, elements, key, mode);
28406
+ var fiber = createFiber(Fragment7, elements, key, mode);
28416
28407
  fiber.lanes = lanes;
28417
28408
  return fiber;
28418
28409
  }
@@ -42587,6 +42578,24 @@ var init_lockfile = __esm({
42587
42578
  });
42588
42579
 
42589
42580
  // src/commands/wrapper-shared.ts
42581
+ import { spawn as spawn2 } from "node:child_process";
42582
+ function spawnTrimmed(bin, args, env3) {
42583
+ return new Promise((resolve3) => {
42584
+ const child = spawn2(bin, args, { stdio: ["inherit", "pipe", "pipe"], shell: false, env: { ...env3, FORCE_COLOR: "1" } });
42585
+ let buf = "";
42586
+ const onData = (c) => {
42587
+ buf += c.toString();
42588
+ };
42589
+ child.stdout?.on("data", onData);
42590
+ child.stderr?.on("data", onData);
42591
+ child.on("error", () => resolve3(1));
42592
+ child.on("close", (code) => {
42593
+ const lines = buf.split("\n").filter((l) => l.replace(ANSI_RE, "").trim() !== "");
42594
+ if (lines.length) process.stdout.write(lines.join("\n") + "\n");
42595
+ resolve3(code ?? 1);
42596
+ });
42597
+ });
42598
+ }
42590
42599
  function injectIgnoreScripts(args, opts) {
42591
42600
  if (!opts.isNpmFamily) return args;
42592
42601
  if (!(opts.strict || opts.dgNoScripts)) return args;
@@ -42595,7 +42604,6 @@ function injectIgnoreScripts(args, opts) {
42595
42604
  }
42596
42605
  function stripDgFlags(args) {
42597
42606
  let dgForce = false;
42598
- let dgForceReason;
42599
42607
  let dgNoScripts = false;
42600
42608
  const filtered = [];
42601
42609
  for (let i = 0; i < args.length; i++) {
@@ -42604,15 +42612,6 @@ function stripDgFlags(args) {
42604
42612
  dgForce = true;
42605
42613
  continue;
42606
42614
  }
42607
- if (arg === "--dg-force-reason") {
42608
- dgForceReason = (args[i + 1] ?? "").slice(0, 500);
42609
- i++;
42610
- continue;
42611
- }
42612
- if (arg.startsWith("--dg-force-reason=")) {
42613
- dgForceReason = arg.slice("--dg-force-reason=".length).slice(0, 500);
42614
- continue;
42615
- }
42616
42615
  if (arg === "--dg-no-scripts") {
42617
42616
  dgNoScripts = true;
42618
42617
  continue;
@@ -42632,12 +42631,13 @@ function stripDgFlags(args) {
42632
42631
  if (consumed) continue;
42633
42632
  filtered.push(arg);
42634
42633
  }
42635
- return { filtered, dgForce, dgForceReason, dgNoScripts };
42634
+ return { filtered, dgForce, dgNoScripts };
42636
42635
  }
42637
- var DG_VALUE_FLAGS, DG_BOOLEAN_FLAGS;
42636
+ var ANSI_RE, DG_VALUE_FLAGS, DG_BOOLEAN_FLAGS;
42638
42637
  var init_wrapper_shared = __esm({
42639
42638
  "src/commands/wrapper-shared.ts"() {
42640
42639
  "use strict";
42640
+ ANSI_RE = /\x1b\[[0-9;]*m/g;
42641
42641
  DG_VALUE_FLAGS = /* @__PURE__ */ new Set([
42642
42642
  "--mode",
42643
42643
  "--api-url",
@@ -42646,6 +42646,8 @@ var init_wrapper_shared = __esm({
42646
42646
  "--workspace",
42647
42647
  "--output",
42648
42648
  "-o",
42649
+ // Removed flag: still consumed (with its value) so a legacy invocation is
42650
+ // silently stripped rather than leaking to the real installer as a package.
42649
42651
  "--dg-force-reason"
42650
42652
  ]);
42651
42653
  DG_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
@@ -42663,7 +42665,7 @@ var init_wrapper_shared = __esm({
42663
42665
  });
42664
42666
 
42665
42667
  // src/commands/npm-wrapper.ts
42666
- import { spawn as spawn2 } from "node:child_process";
42668
+ import { spawn as spawn3 } from "node:child_process";
42667
42669
  import { readFileSync as readFileSync9, existsSync as existsSync12, mkdtempSync, writeFileSync as writeFileSync8, rmSync } from "node:fs";
42668
42670
  import { join as join7 } from "node:path";
42669
42671
  import { tmpdir } from "node:os";
@@ -42678,7 +42680,7 @@ function shimSentinelEnv() {
42678
42680
  return childInstallEnv();
42679
42681
  }
42680
42682
  function parseNpmArgs(args) {
42681
- const { filtered, dgForce, dgForceReason, dgNoScripts } = stripDgFlags(args);
42683
+ const { filtered, dgForce, dgNoScripts } = stripDgFlags(args);
42682
42684
  const command = filtered[0] ?? "";
42683
42685
  const shouldScan = INSTALL_COMMANDS.has(command);
42684
42686
  const packages = [];
@@ -42699,7 +42701,6 @@ function parseNpmArgs(args) {
42699
42701
  packages,
42700
42702
  rawArgs: filtered,
42701
42703
  dgForce,
42702
- dgForceReason,
42703
42704
  dgNoScripts,
42704
42705
  shouldScan
42705
42706
  };
@@ -42755,7 +42756,7 @@ async function resolveVersion(spec) {
42755
42756
  return null;
42756
42757
  }
42757
42758
  return new Promise((resolve3) => {
42758
- const child = spawn2(realNpmBinary(), ["view", spec, "version", "--json"], {
42759
+ const child = spawn3(realNpmBinary(), ["view", spec, "version", "--json"], {
42759
42760
  stdio: ["pipe", "pipe", "pipe"],
42760
42761
  env: shimSentinelEnv()
42761
42762
  });
@@ -42831,9 +42832,12 @@ async function resolvePackages(specs) {
42831
42832
  return { resolved, failed };
42832
42833
  }
42833
42834
  function runNpm(args, opts) {
42835
+ if (opts?.trim) {
42836
+ return spawnTrimmed(realNpmBinary(), args, shimSentinelEnv());
42837
+ }
42834
42838
  return new Promise((resolve3) => {
42835
42839
  const stdio = opts?.stdoutToStderr ? ["inherit", "pipe", "inherit"] : ["inherit", "inherit", "inherit"];
42836
- const child = spawn2(realNpmBinary(), args, { stdio, shell: false, env: shimSentinelEnv() });
42840
+ const child = spawn3(realNpmBinary(), args, { stdio, shell: false, env: shimSentinelEnv() });
42837
42841
  if (opts?.stdoutToStderr && child.stdout) {
42838
42842
  child.stdout.on("data", (chunk) => {
42839
42843
  process.stderr.write(chunk);
@@ -42853,7 +42857,7 @@ async function resolveTreeNpm(specs) {
42853
42857
  try {
42854
42858
  writeFileSync8(join7(dir, "package.json"), '{"name":"_dg_resolve","version":"1.0.0","private":true}');
42855
42859
  const stdout = await new Promise((resolve3) => {
42856
- const child = spawn2(
42860
+ const child = spawn3(
42857
42861
  realNpmBinary(),
42858
42862
  [
42859
42863
  "install",
@@ -43013,10 +43017,10 @@ var init_npm_wrapper = __esm({
43013
43017
  });
43014
43018
 
43015
43019
  // src/commands/pip-wrapper.ts
43016
- import { spawn as spawn3 } from "node:child_process";
43020
+ import { spawn as spawn4 } from "node:child_process";
43017
43021
  import { existsSync as existsSync13 } from "node:fs";
43018
43022
  function parsePipArgs(args) {
43019
- const { filtered, dgForce, dgForceReason, dgNoScripts } = stripDgFlags(args);
43023
+ const { filtered, dgForce, dgNoScripts } = stripDgFlags(args);
43020
43024
  const command = filtered[0] ?? "";
43021
43025
  const shouldScan = INSTALL_COMMANDS2.has(command);
43022
43026
  const packages = [];
@@ -43043,7 +43047,6 @@ function parsePipArgs(args) {
43043
43047
  packages,
43044
43048
  rawArgs: filtered,
43045
43049
  dgForce,
43046
- dgForceReason,
43047
43050
  dgNoScripts,
43048
43051
  shouldScan,
43049
43052
  requirementsFile
@@ -43215,7 +43218,7 @@ async function detectPipBinary() {
43215
43218
  try {
43216
43219
  const parts = cmd.split(" ");
43217
43220
  const code = await new Promise((resolve3) => {
43218
- const child = spawn3(parts[0], [...parts.slice(1), "--version"], {
43221
+ const child = spawn4(parts[0], [...parts.slice(1), "--version"], {
43219
43222
  stdio: ["pipe", "pipe", "pipe"],
43220
43223
  timeout: 5e3,
43221
43224
  env: shimSentinelEnv2()
@@ -43234,9 +43237,12 @@ async function detectPipBinary() {
43234
43237
  async function runPip(args, opts) {
43235
43238
  const pipCmd = await detectPipBinary();
43236
43239
  const parts = pipCmd.split(" ");
43240
+ if (opts?.trim) {
43241
+ return spawnTrimmed(parts[0], [...parts.slice(1), ...args], shimSentinelEnv2());
43242
+ }
43237
43243
  return new Promise((resolve3) => {
43238
43244
  const stdio = opts?.stdoutToStderr ? ["inherit", "pipe", "inherit"] : ["inherit", "inherit", "inherit"];
43239
- const child = spawn3(parts[0], [...parts.slice(1), ...args], { stdio, shell: false, env: shimSentinelEnv2() });
43245
+ const child = spawn4(parts[0], [...parts.slice(1), ...args], { stdio, shell: false, env: shimSentinelEnv2() });
43240
43246
  if (opts?.stdoutToStderr && child.stdout) {
43241
43247
  child.stdout.on("data", (chunk) => {
43242
43248
  process.stderr.write(chunk);
@@ -43251,7 +43257,7 @@ async function pipVersion() {
43251
43257
  const pipCmd = await detectPipBinary();
43252
43258
  const parts = pipCmd.split(" ");
43253
43259
  return await new Promise((resolve3) => {
43254
- const child = spawn3(parts[0], [...parts.slice(1), "--version"], {
43260
+ const child = spawn4(parts[0], [...parts.slice(1), "--version"], {
43255
43261
  stdio: ["pipe", "pipe", "pipe"],
43256
43262
  timeout: 5e3,
43257
43263
  env: shimSentinelEnv2()
@@ -43309,7 +43315,7 @@ async function resolveTreePip(specs) {
43309
43315
  const pipCmd = await detectPipBinary();
43310
43316
  const parts = pipCmd.split(" ");
43311
43317
  const runDryRun = (extraFlags) => new Promise((resolve3) => {
43312
- const child = spawn3(
43318
+ const child = spawn4(
43313
43319
  parts[0],
43314
43320
  [
43315
43321
  ...parts.slice(1),
@@ -44955,7 +44961,6 @@ async function dispatchPublishCheckAudit(opts) {
44955
44961
  score: opts.score,
44956
44962
  action: opts.decisionAction,
44957
44963
  bypassed: opts.bypassed,
44958
- bypass_reason: opts.bypassReason,
44959
44964
  event_kind: "publish_check"
44960
44965
  },
44961
44966
  { apiUrl: opts.apiUrl }
@@ -44977,7 +44982,6 @@ function recordBypassLocally(record) {
44977
44982
  ecosystem: record.ecosystem,
44978
44983
  verdict: record.verdict,
44979
44984
  trigger: record.trigger,
44980
- reason: record.reason,
44981
44985
  packages: record.packages
44982
44986
  };
44983
44987
  appendFileSync3(path, JSON.stringify(full) + "\n", { mode: 384 });
@@ -45000,7 +45004,6 @@ async function dispatchInstallAudit(opts) {
45000
45004
  score: p.score,
45001
45005
  action: opts.decisionAction,
45002
45006
  bypassed: opts.bypassed,
45003
- bypass_reason: opts.bypassReason,
45004
45007
  project_hash: opts.projectHash
45005
45008
  },
45006
45009
  { apiUrl: opts.apiUrl }
@@ -45815,21 +45818,19 @@ ${installLine}
45815
45818
  const blockedSpecArg = topLevelSpecs.length > 0 ? topLevelSpecs.join(" ") : topLevel.split(", ").map((s) => s.replace(/ /g, "@")).join(" ");
45816
45819
  process.stderr.write(
45817
45820
  ` ${import_chalk5.default.red("\u2717")} ${import_chalk5.default.bold("DG blocked")} ${topLevel}.
45818
- Real install was NOT run. To override:
45819
- ` + import_chalk5.default.dim(` npm install ${blockedSpecArg} --dg-force --dg-force-reason="<reason>"
45821
+ ${import_chalk5.default.dim(`install anyway: npm install ${blockedSpecArg} --dg-force`)}
45820
45822
 
45821
- `)
45823
+ `
45822
45824
  );
45823
45825
  }
45824
45826
  } else if (d.verdict === "analysis_incomplete") {
45825
45827
  if (d.outcome === "refuse") {
45826
45828
  const specArg = topLevelSpecs.length > 0 ? topLevelSpecs.join(" ") : resolved.map((p) => `${p.name}@${p.version}`).join(" ");
45827
45829
  process.stderr.write(
45828
- ` ${import_chalk5.default.cyan("?")} ${import_chalk5.default.bold("DG could not verify")} ${topLevel} \u2014 treating as unverified, not safe.
45829
- Real install was NOT run (--mode block). To override:
45830
- ` + import_chalk5.default.dim(` npm install ${specArg} --dg-force --dg-force-reason="<reason>"
45830
+ ` ${import_chalk5.default.cyan("?")} ${import_chalk5.default.bold("DG couldn't verify")} ${topLevel} \u2014 unverified, not safe.
45831
+ ${import_chalk5.default.dim(`install anyway: npm install ${specArg} --dg-force`)}
45831
45832
 
45832
- `)
45833
+ `
45833
45834
  );
45834
45835
  } else {
45835
45836
  process.stderr.write(import_chalk5.default.dim(` DG could not fully verify ${topLevel}; proceeding (mode is not block).
@@ -45851,8 +45852,7 @@ ${installLine}
45851
45852
  ecosystem: "npm",
45852
45853
  packages: result.packages,
45853
45854
  decisionAction: kind,
45854
- bypassed: kind === "override",
45855
- bypassReason: kind === "override" ? parsed.dgForceReason : void 0
45855
+ bypassed: kind === "override"
45856
45856
  });
45857
45857
  },
45858
45858
  emit(record) {
@@ -45873,8 +45873,7 @@ ${installLine}
45873
45873
  passthroughArgs: parsed.rawArgs,
45874
45874
  result,
45875
45875
  resolved,
45876
- suppressedCount: 0,
45877
- dgForceReason: parsed.dgForceReason
45876
+ suppressedCount: 0
45878
45877
  };
45879
45878
  process.exit(await executeDecision(npmDecision, npmCtx, npmPresenter));
45880
45879
  }
@@ -46072,21 +46071,19 @@ ${installLine}
46072
46071
  const pipBlockedSpecArg = resolved.map((p) => `${p.name}==${p.version}`).join(" ");
46073
46072
  process.stderr.write(
46074
46073
  ` ${import_chalk5.default.red("\u2717")} ${import_chalk5.default.bold("DG blocked")} ${topLevel}.
46075
- Real install was NOT run. To override:
46076
- ` + import_chalk5.default.dim(` pip install ${pipBlockedSpecArg} --dg-force --dg-force-reason="<reason>"
46074
+ ${import_chalk5.default.dim(`install anyway: pip install ${pipBlockedSpecArg} --dg-force`)}
46077
46075
 
46078
- `)
46076
+ `
46079
46077
  );
46080
46078
  }
46081
46079
  } else if (d.verdict === "analysis_incomplete") {
46082
46080
  if (d.outcome === "refuse") {
46083
46081
  const pipSpecArg = resolved.map((p) => `${p.name}==${p.version}`).join(" ");
46084
46082
  process.stderr.write(
46085
- ` ${import_chalk5.default.cyan("?")} ${import_chalk5.default.bold("DG could not verify")} ${topLevel} \u2014 treating as unverified, not safe.
46086
- Real install was NOT run (--mode block). To override:
46087
- ` + import_chalk5.default.dim(` pip install ${pipSpecArg} --dg-force --dg-force-reason="<reason>"
46083
+ ` ${import_chalk5.default.cyan("?")} ${import_chalk5.default.bold("DG couldn't verify")} ${topLevel} \u2014 unverified, not safe.
46084
+ ${import_chalk5.default.dim(`install anyway: pip install ${pipSpecArg} --dg-force`)}
46088
46085
 
46089
- `)
46086
+ `
46090
46087
  );
46091
46088
  } else {
46092
46089
  process.stderr.write(import_chalk5.default.dim(` DG could not fully verify ${topLevel}; proceeding (mode is not block).
@@ -46108,8 +46105,7 @@ ${installLine}
46108
46105
  ecosystem: "pypi",
46109
46106
  packages: result.packages,
46110
46107
  decisionAction: kind,
46111
- bypassed: kind === "override",
46112
- bypassReason: kind === "override" ? parsed.dgForceReason : void 0
46108
+ bypassed: kind === "override"
46113
46109
  });
46114
46110
  },
46115
46111
  emit(record) {
@@ -46130,8 +46126,7 @@ ${installLine}
46130
46126
  passthroughArgs: parsed.rawArgs,
46131
46127
  result,
46132
46128
  resolved,
46133
- suppressedCount: 0,
46134
- dgForceReason: parsed.dgForceReason
46129
+ suppressedCount: 0
46135
46130
  };
46136
46131
  process.exit(await executeDecision(pipDecision, pipCtx, pipPresenter));
46137
46132
  }
@@ -46262,7 +46257,8 @@ var init_static_output = __esm({
46262
46257
  var status_exports = {};
46263
46258
  __export(status_exports, {
46264
46259
  collectStatusSnapshot: () => collectStatusSnapshot,
46265
- handleStatusCommand: () => handleStatusCommand
46260
+ handleStatusCommand: () => handleStatusCommand,
46261
+ renderStatusHuman: () => renderStatusHuman
46266
46262
  });
46267
46263
  import { existsSync as existsSync18, readFileSync as readFileSync12 } from "node:fs";
46268
46264
  import { join as join11 } from "node:path";
@@ -46322,6 +46318,7 @@ async function collectStatusSnapshot(cliVersion2) {
46322
46318
  };
46323
46319
  });
46324
46320
  const engineResolvable = isEngineResolvable();
46321
+ const dirOnPath = (process.env.PATH ?? "").split(":").includes(shimDir2);
46325
46322
  const pythonHooks = readPythonReceipt();
46326
46323
  const cwd2 = process.cwd();
46327
46324
  const hookPart = { installed: false };
@@ -46353,7 +46350,7 @@ async function collectStatusSnapshot(cliVersion2) {
46353
46350
  }
46354
46351
  return {
46355
46352
  auth: authPart,
46356
- shims: { rows: shimRows, engineResolvable },
46353
+ shims: { rows: shimRows, engineResolvable, dirOnPath },
46357
46354
  pythonHooks,
46358
46355
  hook: hookPart,
46359
46356
  update: updatePart
@@ -46403,6 +46400,11 @@ async function renderStatusHuman(s) {
46403
46400
  if (protectedRows.length > 0 && !s.shims.engineResolvable) {
46404
46401
  protectedGlyph = chalk18.yellow("!");
46405
46402
  protectedLine = `${protectedRows.join(", ")} \u2014 engine unresolved, installs pass through unscanned (run \`dg status\` to repair)`;
46403
+ } else if (protectedRows.length > 0 && !s.shims.dirOnPath) {
46404
+ const shell = process.env.SHELL ?? "";
46405
+ const rcHint = shell.includes("zsh") ? "~/.zshrc" : shell.includes("bash") ? "~/.bashrc" : "your shell rc";
46406
+ protectedGlyph = chalk18.yellow("!");
46407
+ protectedLine = `wired but not active in this shell \u2014 run \`source ${rcHint}\` or open a new terminal (installs here run unscanned until you do)`;
46406
46408
  } else if (missingRows.length === 0) {
46407
46409
  protectedGlyph = chalk18.green("\u2713");
46408
46410
  protectedLine = protectedRows.join(", ");
@@ -48749,7 +48751,7 @@ __export(publish_check_exports, {
48749
48751
  scanPayload: () => scanPayload,
48750
48752
  summarize: () => summarize
48751
48753
  });
48752
- import { spawn as spawn4 } from "node:child_process";
48754
+ import { spawn as spawn5 } from "node:child_process";
48753
48755
  import { readFileSync as readFileSync13, existsSync as existsSync19, readdirSync as readdirSync3 } from "node:fs";
48754
48756
  import { join as join12, basename as basename2 } from "node:path";
48755
48757
  import { createGunzip } from "node:zlib";
@@ -48761,7 +48763,7 @@ function sanitizeSnippet(s, max = 40) {
48761
48763
  }
48762
48764
  async function npmPackDryRun(cwd2 = process.cwd()) {
48763
48765
  return new Promise((resolve3) => {
48764
- const child = spawn4("npm", ["pack", "--dry-run", "--json"], {
48766
+ const child = spawn5("npm", ["pack", "--dry-run", "--json"], {
48765
48767
  cwd: cwd2,
48766
48768
  stdio: ["ignore", "pipe", "pipe"]
48767
48769
  });
@@ -51805,24 +51807,18 @@ var init_readonly = __esm({
51805
51807
  // src/ui/hooks/useWrapperBase.ts
51806
51808
  function reducer4(_state, action) {
51807
51809
  switch (action.type) {
51808
- case "PASSTHROUGH":
51809
- return { phase: "passthrough" };
51810
51810
  case "RESOLVING":
51811
51811
  return { phase: "resolving", count: action.count };
51812
51812
  case "SCANNING":
51813
51813
  return { phase: "scanning", count: action.count };
51814
- case "PASS":
51815
- return { phase: "pass", count: action.count, result: action.result };
51816
51814
  case "WARN":
51817
- return { phase: "warn", result: action.result, dgForce: action.dgForce };
51818
- case "BLOCKED":
51819
- return { phase: "blocked", result: action.result, dgForce: action.dgForce };
51820
- case "INCOMPLETE":
51821
- return { phase: "incomplete", result: action.result, message: action.message, proceed: action.proceed };
51815
+ return { phase: "warn", result: action.result };
51822
51816
  case "REFUSED":
51823
- return { phase: "refused", result: action.result, message: action.message };
51817
+ return { phase: "refused", result: action.result, verdict: action.verdict, cmd: action.cmd, exitCode: action.exitCode };
51818
+ case "DECLINED":
51819
+ return { phase: "declined", line: action.line, exitCode: action.exitCode };
51824
51820
  case "INSTALLING":
51825
- return { phase: "installing" };
51821
+ return { phase: "installing", line: action.line };
51826
51822
  case "DONE":
51827
51823
  return { phase: "done", exitCode: action.exitCode };
51828
51824
  case "ERROR":
@@ -51831,12 +51827,17 @@ function reducer4(_state, action) {
51831
51827
  return { phase: "free_cap_reached" };
51832
51828
  }
51833
51829
  }
51834
- function useInstallWrapper(rawArgs, config, opts, exit) {
51830
+ function useInstallWrapper(rawArgs, config, opts, handoff) {
51835
51831
  const [state, dispatch] = (0, import_react37.useReducer)(reducer4, { phase: "resolving", count: 0 });
51836
51832
  const started = (0, import_react37.useRef)(false);
51837
51833
  const parsedRef = (0, import_react37.useRef)(opts.parseArgs(rawArgs));
51838
51834
  const pendingInstall = (0, import_react37.useRef)(null);
51839
51835
  const rejectRef = (0, import_react37.useRef)(null);
51836
+ const ho = handoff ?? { install: null };
51837
+ const requestInstall = (args, line) => {
51838
+ ho.install = { run: opts.runInstall, args };
51839
+ dispatch({ type: "INSTALLING", line });
51840
+ };
51840
51841
  const confirmInstall = () => {
51841
51842
  if (pendingInstall.current) {
51842
51843
  pendingInstall.current();
@@ -51859,18 +51860,14 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
51859
51860
  (async () => {
51860
51861
  try {
51861
51862
  if (!parsed.shouldScan) {
51862
- dispatch({ type: "PASSTHROUGH" });
51863
- const code2 = await opts.runInstall(parsed.rawArgs);
51864
- dispatch({ type: "DONE", exitCode: code2 });
51863
+ requestInstall(parsed.rawArgs, null);
51865
51864
  return;
51866
51865
  }
51867
51866
  let specs;
51868
51867
  if (parsed.packages.length === 0) {
51869
51868
  specs = opts.inferSpecsFromContext(parsed);
51870
51869
  if (specs.length === 0) {
51871
- dispatch({ type: "PASSTHROUGH" });
51872
- const code2 = await opts.runInstall(parsed.rawArgs);
51873
- dispatch({ type: "DONE", exitCode: code2 });
51870
+ requestInstall(parsed.rawArgs, null);
51874
51871
  return;
51875
51872
  }
51876
51873
  } else {
@@ -51879,9 +51876,7 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
51879
51876
  dispatch({ type: "RESOLVING", count: specs.length });
51880
51877
  const { resolved } = await opts.resolvePackages(specs);
51881
51878
  if (resolved.length === 0) {
51882
- dispatch({ type: "PASSTHROUGH" });
51883
- const code2 = await opts.runInstall(parsed.rawArgs);
51884
- dispatch({ type: "DONE", exitCode: code2 });
51879
+ requestInstall(parsed.rawArgs, null);
51885
51880
  return;
51886
51881
  }
51887
51882
  const isRequirementsInstall = opts.ecosystem === "pypi" && (parsed.rawArgs.includes("-r") || parsed.rawArgs.includes("--requirement"));
@@ -51891,7 +51886,6 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
51891
51886
  message: `A -r requirements install cannot be pinned to the exact scanned versions; refusing in ${config.strict ? "--strict" : "--mode block"} (resolve\u2192install mismatch risk). Use --mode warn or --dg-force to bypass.`,
51892
51887
  proceed: false
51893
51888
  });
51894
- dispatch({ type: "DONE", exitCode: 2 });
51895
51889
  return;
51896
51890
  }
51897
51891
  const pinnedArgs = isRequirementsInstall ? parsed.rawArgs : opts.ecosystem === "npm" ? pinTopLevelArgs(parsed.rawArgs, parsed.packages, resolved) : pinPipArgs(parsed.rawArgs, parsed.packages, resolved);
@@ -51911,98 +51905,60 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
51911
51905
  message: `Could not enumerate the dependency tree (${tree.errorMessage ?? "dry-run produced no tree"}); transitive deps would install unscanned. Install aborted in ${config.strict ? "--strict" : "--mode block"}. Use --dg-force to bypass.`,
51912
51906
  proceed: false
51913
51907
  });
51914
- dispatch({ type: "DONE", exitCode: 2 });
51915
51908
  return;
51916
51909
  }
51917
51910
  }
51918
51911
  dispatch({ type: "SCANNING", count: scanSet.length });
51919
51912
  const result = await opts.callAnalyze(scanSet, config);
51920
- if (result.action === "pass") {
51921
- if (exit) exit();
51922
- const chalk18 = (await Promise.resolve().then(() => __toESM(require_source(), 1))).default;
51923
- const line = formatPassLine(result, chalk18);
51924
- process.stderr.write(" " + line + "\n\n");
51925
- const code2 = await opts.runInstall(installArgs);
51926
- process.exit(code2);
51927
- return;
51928
- }
51929
- const verdict = verdictFromResult(result);
51930
51913
  const decision = routeVerdict({
51931
- verdict,
51914
+ verdict: verdictFromResult(result),
51932
51915
  mode: config.mode,
51933
51916
  strict: config.strict,
51934
51917
  dgForce: parsed.dgForce
51935
51918
  });
51936
- const bypassVerdict = decision.verdict === "block" ? "block" : "warn";
51919
+ if (decision.outcome === "refuse") {
51920
+ const cmd = `${opts.ecosystem === "npm" ? "npm" : "pip"} ${parsed.rawArgs.join(" ")} --dg-force`;
51921
+ const v = decision.verdict === "analysis_incomplete" ? "incomplete" : decision.verdict === "block" ? "block" : "warn";
51922
+ dispatch({ type: "REFUSED", result, verdict: v, cmd, exitCode: decision.refuseExitCode });
51923
+ return;
51924
+ }
51937
51925
  const recordBypass = async (trigger) => {
51938
51926
  const { recordBypassLocally: recordBypassLocally2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
51939
51927
  recordBypassLocally2({
51940
51928
  ecosystem: opts.ecosystem,
51941
- verdict: bypassVerdict,
51929
+ verdict: decision.verdict === "block" ? "block" : "warn",
51942
51930
  trigger,
51943
- reason: trigger === "dg-force" ? parsed.dgForceReason : void 0,
51944
51931
  packages: result.packages.map((p) => ({ name: p.name, version: p.version, score: p.score }))
51945
51932
  });
51946
51933
  };
51947
- const refusedMessage = () => {
51948
- const list = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
51949
- if (decision.verdict === "block") {
51950
- return `DG blocked ${list}. Real install was NOT run. Re-run with --dg-force --dg-force-reason="<reason>" to override.`;
51951
- }
51952
- if (decision.verdict === "analysis_incomplete") {
51953
- return `DG could not fully analyze ${list} (analysis incomplete). Refusing in ${config.strict ? "--strict" : "--mode block"} \u2014 unverified is not safe. Use --mode warn or --dg-force to bypass.`;
51954
- }
51955
- return `DG flagged ${list}. Refusing in --strict. Use --mode warn or --dg-force to proceed.`;
51956
- };
51957
- const presenter = {
51958
- announce(d) {
51959
- if (d.outcome === "refuse") {
51960
- dispatch({ type: "REFUSED", result, message: refusedMessage() });
51961
- return;
51962
- }
51963
- switch (d.verdict) {
51964
- case "warn":
51965
- dispatch({ type: "WARN", result, dgForce: d.bypassed });
51966
- return;
51967
- case "block":
51968
- dispatch({ type: "BLOCKED", result, dgForce: d.bypassed });
51969
- return;
51970
- case "analysis_incomplete":
51971
- dispatch({ type: "INCOMPLETE", result, proceed: true, message: "DG could not fully analyze the install set (analysis incomplete)." });
51972
- return;
51973
- default:
51974
- return;
51975
- }
51976
- },
51977
- confirmProceed() {
51978
- return new Promise((resolve3) => {
51979
- pendingInstall.current = () => resolve3(true);
51980
- rejectRef.current = () => resolve3(false);
51981
- });
51982
- },
51983
- async runInstall(args) {
51984
- dispatch({ type: "INSTALLING" });
51985
- return opts.runInstall(args);
51986
- },
51987
- async audit(kind) {
51988
- if (kind === "override") await recordBypass("dg-force");
51989
- },
51990
- onPromptAccepted: () => recordBypass("interactive-confirm"),
51991
- emit() {
51934
+ const chalk18 = (await Promise.resolve().then(() => __toESM(require_source(), 1))).default;
51935
+ const top = result.packages.length === 1 ? result.packages[0] : null;
51936
+ const name = top ? `${top.name}@${top.version}` : `${result.packages.length} packages`;
51937
+ const pinnedLine = (() => {
51938
+ if (decision.bypassed) {
51939
+ const sig = decision.verdict === "block" ? chalk18.red("\u2718") : chalk18.yellow("\u26A0");
51940
+ return ` ${sig} ${name} ${chalk18.dim(`(${decision.verdict}) \u2014 --dg-force override, installing`)}`;
51941
+ }
51942
+ if (decision.verdict === "analysis_incomplete") return ` ${chalk18.cyan("?")} ${name} ${chalk18.dim("\u2014 could not verify; proceeding")}`;
51943
+ if (decision.verdict === "pass") return ` ${chalk18.green("\u2713")} ${name} ${chalk18.dim("\u2014 clean")}`;
51944
+ return null;
51945
+ })();
51946
+ if (decision.outcome === "prompt") {
51947
+ dispatch({ type: "WARN", result });
51948
+ const accepted = await new Promise((resolve3) => {
51949
+ pendingInstall.current = () => resolve3(true);
51950
+ rejectRef.current = () => resolve3(false);
51951
+ });
51952
+ if (!accepted) {
51953
+ dispatch({ type: "DECLINED", line: ` ${chalk18.yellow("\u2717")} ${name} ${chalk18.dim("\u2014 not installed")}`, exitCode: decision.refuseExitCode });
51954
+ return;
51992
51955
  }
51993
- };
51994
- const ctx = {
51995
- ecosystem: opts.ecosystem,
51996
- apiKind: opts.ecosystem,
51997
- installArgs,
51998
- passthroughArgs: parsed.rawArgs,
51999
- result,
52000
- resolved,
52001
- suppressedCount: 0,
52002
- dgForceReason: parsed.dgForceReason
52003
- };
52004
- const code = await executeDecision(decision, ctx, presenter);
52005
- dispatch({ type: "DONE", exitCode: code });
51956
+ await recordBypass("interactive-confirm");
51957
+ requestInstall(installArgs, null);
51958
+ return;
51959
+ }
51960
+ if (decision.bypassed) await recordBypass("dg-force");
51961
+ requestInstall(decision.outcome === "passthrough" ? parsed.rawArgs : installArgs, pinnedLine);
52006
51962
  return;
52007
51963
  } catch (error) {
52008
51964
  if (error instanceof FreeCapReachedError) {
@@ -52016,27 +51972,17 @@ function useInstallWrapper(rawArgs, config, opts, exit) {
52016
51972
  message: `Scan failed (${message}) and --mode is block. Install aborted. Use --dg-force to bypass.`,
52017
51973
  proceed: false
52018
51974
  });
52019
- dispatch({ type: "DONE", exitCode: 2 });
52020
51975
  return;
52021
51976
  }
52022
- dispatch({ type: "ERROR", message, proceed: true });
52023
- dispatch({ type: "INSTALLING" });
52024
- const code = await opts.runInstall(installArgs);
52025
- dispatch({ type: "DONE", exitCode: code });
51977
+ const chalk18 = (await Promise.resolve().then(() => __toESM(require_source(), 1))).default;
51978
+ requestInstall(installArgs, ` ${chalk18.yellow("\u26A0")} ${chalk18.dim(`scan failed (${message}); proceeding`)}`);
52026
51979
  }
52027
51980
  })();
52028
51981
  }, [rawArgs, config]);
52029
51982
  return { state, confirmInstall, rejectInstall };
52030
51983
  }
52031
- function formatPassLine(result, chalk18) {
52032
- if (result.packages.length === 1) {
52033
- const p = result.packages[0];
52034
- return chalk18.green("\u2713 ") + `${p.name}@${p.version}` + chalk18.dim(" \u2014 clean. Installing.");
52035
- }
52036
- return chalk18.green("\u2713 ") + `${result.packages.length} packages` + chalk18.dim(" \u2014 all clean. Installing.");
52037
- }
52038
- function useWrapper(args, config, ecosystem, exit) {
52039
- return useInstallWrapper(args, config, ecosystem === "npm" ? NPM_OPTIONS : PIP_OPTIONS, exit);
51984
+ function useWrapper(args, config, ecosystem, handoff) {
51985
+ return useInstallWrapper(args, config, ecosystem === "npm" ? NPM_OPTIONS : PIP_OPTIONS, handoff);
52040
51986
  }
52041
51987
  var import_react37, NPM_OPTIONS, PIP_OPTIONS;
52042
51988
  var init_useWrapperBase = __esm({
@@ -52054,7 +52000,7 @@ var init_useWrapperBase = __esm({
52054
52000
  resolvePackages,
52055
52001
  resolveTree: resolveTreeNpm,
52056
52002
  callAnalyze: callAnalyzeAPI,
52057
- runInstall: runNpm,
52003
+ runInstall: (args) => runNpm(args, { trim: true }),
52058
52004
  inferSpecsFromContext: () => readBareInstallPackages(process.cwd()),
52059
52005
  ecosystem: "npm"
52060
52006
  };
@@ -52063,7 +52009,7 @@ var init_useWrapperBase = __esm({
52063
52009
  resolvePackages: resolvePackages2,
52064
52010
  resolveTree: resolveTreePip,
52065
52011
  callAnalyze: callPyPIAnalyzeAPI,
52066
- runInstall: runPip,
52012
+ runInstall: (args) => runPip(args, { trim: true }),
52067
52013
  inferSpecsFromContext: (parsed) => {
52068
52014
  const file = parsed.requirementsFile;
52069
52015
  return file ? parseRequirementsFile(file) : [];
@@ -52245,6 +52191,7 @@ var init_ConfirmPrompt = __esm({
52245
52191
  onReject();
52246
52192
  }
52247
52193
  });
52194
+ if (!message) return null;
52248
52195
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { flexDirection: "column", children: [
52249
52196
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Text, { children: [
52250
52197
  import_chalk17.default.red.bold("\u26A0"),
@@ -52300,7 +52247,8 @@ var init_WrapperVerdictLine = __esm({
52300
52247
  WrapperVerdictLine = ({
52301
52248
  result,
52302
52249
  verdict,
52303
- dgForce
52250
+ dgForce,
52251
+ refusal
52304
52252
  }) => {
52305
52253
  const total = result.packages.length;
52306
52254
  const counts = countSummary(result);
@@ -52326,12 +52274,13 @@ var init_WrapperVerdictLine = __esm({
52326
52274
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { dimColor: true, children: " \u2014 all clean. Installing." })
52327
52275
  ] });
52328
52276
  }
52329
- const sigil = verdict === "block" ? "\u2718" : "\u26A0";
52330
- const color = verdict === "block" ? "red" : "yellow";
52277
+ const sigil = verdict === "block" ? "\u2718" : verdict === "incomplete" ? "?" : "\u26A0";
52278
+ const color = verdict === "block" ? "red" : verdict === "incomplete" ? "cyan" : "yellow";
52331
52279
  const prompt = verdict === "block" ? "install anyway?" : "install?";
52332
52280
  if (total === 1) {
52333
52281
  const p = topPackage(result);
52334
52282
  const score = p ? p.score : result.score;
52283
+ const meta = verdict === "incomplete" ? `(could not verify)${reasonTag(p)}` : `(${verdict}, score ${score})${reasonTag(p)}`;
52335
52284
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { flexDirection: "row", children: [
52336
52285
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { color, children: [
52337
52286
  sigil,
@@ -52342,18 +52291,23 @@ var init_WrapperVerdictLine = __esm({
52342
52291
  "@",
52343
52292
  p?.version
52344
52293
  ] }),
52345
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { dimColor: true, children: [
52346
- " (",
52347
- verdict,
52348
- ", score ",
52349
- score,
52350
- ")",
52351
- reasonTag(p),
52352
- " \u2014 "
52353
- ] }),
52354
- dgForce ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color, bold: true, children: "--dg-force: bypassing. Installing." }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { bold: true, children: [
52355
- prompt,
52356
- " [y/N]"
52294
+ refusal ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { dimColor: true, children: [
52295
+ " ",
52296
+ meta
52297
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
52298
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { dimColor: true, children: [
52299
+ " ",
52300
+ meta,
52301
+ " \u2014 "
52302
+ ] }),
52303
+ dgForce ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color, bold: true, children: "--dg-force: bypassing. Installing." }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { bold: true, children: [
52304
+ prompt,
52305
+ " [",
52306
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color: "green", children: "y" }),
52307
+ "/",
52308
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color: "red", children: "N" }),
52309
+ "]"
52310
+ ] })
52357
52311
  ] })
52358
52312
  ] });
52359
52313
  }
@@ -52371,14 +52325,23 @@ var init_WrapperVerdictLine = __esm({
52371
52325
  total,
52372
52326
  " packages"
52373
52327
  ] }),
52374
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { dimColor: true, children: [
52328
+ refusal ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { dimColor: true, children: [
52375
52329
  ": ",
52376
- parts.join(", "),
52377
- " \u2014 "
52378
- ] }),
52379
- dgForce ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color, bold: true, children: "--dg-force: bypassing. Installing." }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { bold: true, children: [
52380
- prompt,
52381
- " [y/N] [d] details"
52330
+ parts.join(", ")
52331
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
52332
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { dimColor: true, children: [
52333
+ ": ",
52334
+ parts.join(", "),
52335
+ " \u2014 "
52336
+ ] }),
52337
+ dgForce ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color, bold: true, children: "--dg-force: bypassing. Installing." }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text, { bold: true, children: [
52338
+ prompt,
52339
+ " [",
52340
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color: "green", children: "y" }),
52341
+ "/",
52342
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color: "red", children: "N" }),
52343
+ "] [d] details"
52344
+ ] })
52382
52345
  ] })
52383
52346
  ] });
52384
52347
  };
@@ -52416,21 +52379,30 @@ var init_WrapperApp = __esm({
52416
52379
  installing: "Installing with pip..."
52417
52380
  }
52418
52381
  };
52419
- WrapperApp = ({ args, config, ecosystem }) => {
52382
+ WrapperApp = ({ args, config, ecosystem, handoff }) => {
52420
52383
  const { exit } = use_app_default();
52421
- const { state, confirmInstall, rejectInstall } = useWrapper(args, config, ecosystem, exit);
52384
+ const { state, confirmInstall, rejectInstall } = useWrapper(args, config, ecosystem, handoff);
52422
52385
  const [showDetails, setShowDetails] = (0, import_react38.useState)(false);
52423
52386
  use_input_default((input) => {
52424
- if (input === "d" && (state.phase === "warn" || state.phase === "blocked")) {
52387
+ if (input === "d" && state.phase === "warn") {
52425
52388
  setShowDetails((v) => !v);
52426
52389
  }
52427
52390
  });
52428
52391
  (0, import_react38.useEffect)(() => {
52429
- if (state.phase === "done") {
52392
+ if (state.phase === "done" || state.phase === "refused" || state.phase === "declined") {
52430
52393
  process.exitCode = state.exitCode;
52431
52394
  const timer = setTimeout(() => exit(), 0);
52432
52395
  return () => clearTimeout(timer);
52433
52396
  }
52397
+ if (state.phase === "installing") {
52398
+ const timer = setTimeout(() => exit(), 0);
52399
+ return () => clearTimeout(timer);
52400
+ }
52401
+ if (state.phase === "error") {
52402
+ process.exitCode = 2;
52403
+ const timer = setTimeout(() => exit(), 0);
52404
+ return () => clearTimeout(timer);
52405
+ }
52434
52406
  if (state.phase === "free_cap_reached") {
52435
52407
  process.exitCode = 1;
52436
52408
  const timer = setTimeout(() => exit(), 0);
@@ -52445,44 +52417,30 @@ var init_WrapperApp = __esm({
52445
52417
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Spinner2, { label: labels.resolving(state.count, state.count !== 1 ? "s" : "") });
52446
52418
  case "scanning":
52447
52419
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Spinner2, { label: labels.scanning(state.count, state.count !== 1 ? "s" : "") });
52448
- case "pass":
52449
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(WrapperVerdictLine, { result: state.result, verdict: "pass" });
52450
52420
  case "warn":
52451
52421
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Box_default, { flexDirection: "column", children: [
52452
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(WrapperVerdictLine, { result: state.result, verdict: "warn", dgForce: state.dgForce }),
52422
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(WrapperVerdictLine, { result: state.result, verdict: "warn" }),
52453
52423
  showDetails && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ResultsView, { result: state.result, config, durationMs: state.result.durationMs }) }),
52454
- !state.dgForce && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ConfirmPrompt, { message: "", onConfirm: handleConfirm, onReject: handleReject })
52424
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ConfirmPrompt, { message: "", onConfirm: handleConfirm, onReject: handleReject })
52455
52425
  ] });
52456
- case "blocked":
52426
+ case "refused":
52457
52427
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Box_default, { flexDirection: "column", children: [
52458
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(WrapperVerdictLine, { result: state.result, verdict: "block", dgForce: state.dgForce }),
52459
- showDetails && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ResultsView, { result: state.result, config, durationMs: state.result.durationMs }) })
52428
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(WrapperVerdictLine, { result: state.result, verdict: state.verdict, refusal: true }),
52429
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Text, { dimColor: true, children: [
52430
+ " install anyway: ",
52431
+ state.cmd
52432
+ ] })
52460
52433
  ] });
52461
- case "refused":
52462
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ErrorView, { error: new Error(state.message) });
52463
- case "incomplete":
52464
- if (state.proceed) {
52465
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Text, { color: "yellow", children: [
52466
- state.message,
52467
- " Proceeding with install."
52468
- ] });
52469
- }
52470
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ErrorView, { error: new Error(state.message) });
52434
+ case "declined":
52435
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text, { children: state.line });
52436
+ // The verdict line is Ink's final frame; it stays on screen after unmount and
52437
+ // the installer's (trimmed) output is printed under it by bin.ts.
52471
52438
  case "installing":
52472
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Spinner2, { label: labels.installing });
52439
+ return state.line ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text, { children: state.line }) : null;
52473
52440
  case "done":
52474
52441
  return null;
52475
52442
  case "error":
52476
- if (state.proceed) {
52477
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Text, { color: "yellow", children: [
52478
- "Warning: Scan failed (",
52479
- state.message,
52480
- "). Proceeding with install."
52481
- ] });
52482
- }
52483
52443
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ErrorView, { error: new Error(state.message) });
52484
- case "passthrough":
52485
- return null;
52486
52444
  case "free_cap_reached": {
52487
52445
  let hasKey = false;
52488
52446
  try {
@@ -52518,9 +52476,9 @@ __export(conda_wrapper_exports, {
52518
52476
  adapter: () => adapter,
52519
52477
  runStaticConda: () => runStaticConda
52520
52478
  });
52521
- import { spawn as spawn5 } from "node:child_process";
52479
+ import { spawn as spawn6 } from "node:child_process";
52522
52480
  function parseCondaArgs(args) {
52523
- const { filtered, dgForce, dgForceReason, dgNoScripts } = stripDgFlags(args);
52481
+ const { filtered, dgForce, dgNoScripts } = stripDgFlags(args);
52524
52482
  const command = filtered[0] ?? "";
52525
52483
  const shouldScan = INSTALL_COMMANDS3.has(command);
52526
52484
  const packages = [];
@@ -52539,7 +52497,6 @@ function parseCondaArgs(args) {
52539
52497
  packages,
52540
52498
  rawArgs: filtered,
52541
52499
  dgForce,
52542
- dgForceReason,
52543
52500
  dgNoScripts,
52544
52501
  shouldScan
52545
52502
  };
@@ -52573,7 +52530,7 @@ async function runStaticConda(args, ecosystem, config) {
52573
52530
  return 127;
52574
52531
  }
52575
52532
  return await new Promise((resolve3) => {
52576
- const child = spawn5(real, parsed.rawArgs, { stdio: "inherit", env: childInstallEnv() });
52533
+ const child = spawn6(real, parsed.rawArgs, { stdio: "inherit", env: childInstallEnv() });
52577
52534
  child.on("close", (code) => resolve3(code ?? 1));
52578
52535
  child.on("error", () => resolve3(1));
52579
52536
  });
@@ -52620,7 +52577,7 @@ function pnpmFlagTakesValue(flag) {
52620
52577
  return valueFlagPrefixes.includes(flag);
52621
52578
  }
52622
52579
  function parsePnpmArgs(args) {
52623
- const { filtered, dgForce, dgForceReason, dgNoScripts } = stripDgFlags(args);
52580
+ const { filtered, dgForce, dgNoScripts } = stripDgFlags(args);
52624
52581
  const command = filtered[0] ?? "";
52625
52582
  const shouldScan = INSTALL_COMMANDS4.has(command);
52626
52583
  const packages = [];
@@ -52639,7 +52596,6 @@ function parsePnpmArgs(args) {
52639
52596
  packages,
52640
52597
  rawArgs: filtered,
52641
52598
  dgForce,
52642
- dgForceReason,
52643
52599
  dgNoScripts,
52644
52600
  shouldScan
52645
52601
  };
@@ -52718,7 +52674,7 @@ function yarnFlagTakesValue(flag) {
52718
52674
  return valueFlagPrefixes.includes(flag);
52719
52675
  }
52720
52676
  function parseYarnArgs(args) {
52721
- const { filtered, dgForce, dgForceReason, dgNoScripts } = stripDgFlags(args);
52677
+ const { filtered, dgForce, dgNoScripts } = stripDgFlags(args);
52722
52678
  const command = filtered[0] ?? "";
52723
52679
  const shouldScan = INSTALL_COMMANDS5.has(command);
52724
52680
  const packages = [];
@@ -52737,7 +52693,6 @@ function parseYarnArgs(args) {
52737
52693
  packages,
52738
52694
  rawArgs: filtered,
52739
52695
  dgForce,
52740
- dgForceReason,
52741
52696
  dgNoScripts,
52742
52697
  shouldScan
52743
52698
  };
@@ -52817,7 +52772,7 @@ function bunFlagTakesValue(flag) {
52817
52772
  return valueFlagPrefixes.includes(flag);
52818
52773
  }
52819
52774
  function parseBunArgs(args) {
52820
- const { filtered, dgForce, dgForceReason, dgNoScripts } = stripDgFlags(args);
52775
+ const { filtered, dgForce, dgNoScripts } = stripDgFlags(args);
52821
52776
  const command = filtered[0] ?? "";
52822
52777
  const shouldScan = INSTALL_COMMANDS6.has(command);
52823
52778
  const packages = [];
@@ -52836,7 +52791,6 @@ function parseBunArgs(args) {
52836
52791
  packages,
52837
52792
  rawArgs: filtered,
52838
52793
  dgForce,
52839
- dgForceReason,
52840
52794
  dgNoScripts,
52841
52795
  shouldScan
52842
52796
  };
@@ -52923,7 +52877,7 @@ function uvFlagTakesValue(flag) {
52923
52877
  return valueFlagPrefixes.includes(flag);
52924
52878
  }
52925
52879
  function parseUvArgs(args) {
52926
- const { filtered, dgForce, dgForceReason, dgNoScripts } = stripDgFlags(args);
52880
+ const { filtered, dgForce, dgNoScripts } = stripDgFlags(args);
52927
52881
  const first = filtered[0] ?? "";
52928
52882
  let command = "";
52929
52883
  let argStart = 1;
@@ -52972,7 +52926,6 @@ function parseUvArgs(args) {
52972
52926
  packages,
52973
52927
  rawArgs: filtered,
52974
52928
  dgForce,
52975
- dgForceReason,
52976
52929
  dgNoScripts,
52977
52930
  shouldScan
52978
52931
  };
@@ -53034,7 +52987,7 @@ function pipxFlagTakesValue(flag) {
53034
52987
  return valueFlagPrefixes.includes(flag);
53035
52988
  }
53036
52989
  function parsePipxArgs(args) {
53037
- const { filtered, dgForce, dgForceReason, dgNoScripts } = stripDgFlags(args);
52990
+ const { filtered, dgForce, dgNoScripts } = stripDgFlags(args);
53038
52991
  const command = filtered[0] ?? "";
53039
52992
  const shouldScan = INSTALL_COMMANDS7.has(command) && command !== "upgrade-all";
53040
52993
  const packages = [];
@@ -53057,7 +53010,6 @@ function parsePipxArgs(args) {
53057
53010
  packages,
53058
53011
  rawArgs: filtered,
53059
53012
  dgForce,
53060
- dgForceReason,
53061
53013
  dgNoScripts,
53062
53014
  shouldScan
53063
53015
  };
@@ -53111,7 +53063,7 @@ var wrapper_factory_exports = {};
53111
53063
  __export(wrapper_factory_exports, {
53112
53064
  runEcosystemWrapper: () => runEcosystemWrapper
53113
53065
  });
53114
- import { spawn as spawn6 } from "node:child_process";
53066
+ import { spawn as spawn7 } from "node:child_process";
53115
53067
  function shimSentinelEnv3() {
53116
53068
  return childInstallEnv();
53117
53069
  }
@@ -53123,7 +53075,7 @@ async function spawnRealBinary(adapter7, args) {
53123
53075
  return 127;
53124
53076
  }
53125
53077
  return await new Promise((resolve3) => {
53126
- const child = spawn6(real, args, { stdio: "inherit", env: shimSentinelEnv3() });
53078
+ const child = spawn7(real, args, { stdio: "inherit", env: shimSentinelEnv3() });
53127
53079
  child.on("close", (code) => resolve3(code ?? 1));
53128
53080
  child.on("error", () => resolve3(1));
53129
53081
  });
@@ -53325,7 +53277,6 @@ async function runEcosystemWrapper(adapter7, args, config) {
53325
53277
  result,
53326
53278
  resolved,
53327
53279
  suppressedCount,
53328
- dgForceReason: parsed.dgForceReason,
53329
53280
  error: verdict === "analysis_incomplete" && decision.outcome === "refuse" ? { code: "analysis_incomplete", message: "scanner could not fully analyze the install set" } : void 0
53330
53281
  };
53331
53282
  const presenter = {
@@ -53377,10 +53328,9 @@ ${installLine}
53377
53328
  const blockedList = resolved.map((p) => `${p.name} ${p.version}`).join(", ");
53378
53329
  process.stderr.write(
53379
53330
  ` ${import_chalk19.default.red("\u2717")} ${import_chalk19.default.bold("DG blocked")} ${blockedList}.
53380
- Real install was NOT run. To override:
53381
- ` + import_chalk19.default.dim(` ${adapter7.realBinaryName} ${parsed.rawArgs.join(" ")} --dg-force --dg-force-reason="<reason>"
53331
+ ${import_chalk19.default.dim(`install anyway: ${adapter7.realBinaryName} ${parsed.rawArgs.join(" ")} --dg-force`)}
53382
53332
 
53383
- `)
53333
+ `
53384
53334
  );
53385
53335
  }
53386
53336
  return;
@@ -53390,10 +53340,10 @@ ${installLine}
53390
53340
  if (d.outcome === "refuse") {
53391
53341
  if (!config.json) {
53392
53342
  process.stderr.write(
53393
- ` ${import_chalk19.default.red("\u2717")} ${import_chalk19.default.bold("DG could not verify")} ${list} \u2014 analysis incomplete.
53394
- ` + import_chalk19.default.dim(` --mode ${config.strict ? "strict" : "block"} \u21D2 refusing install (unverified is not safe). Use --mode warn or --dg-force to bypass.
53343
+ ` ${import_chalk19.default.cyan("?")} ${import_chalk19.default.bold("DG couldn't verify")} ${list} \u2014 unverified, not safe.
53344
+ ${import_chalk19.default.dim(`install anyway: ${adapter7.realBinaryName} ${parsed.rawArgs.join(" ")} --dg-force`)}
53395
53345
 
53396
- `)
53346
+ `
53397
53347
  );
53398
53348
  }
53399
53349
  } else if (!config.json && !config.quiet) {
@@ -53425,8 +53375,7 @@ ${installLine}
53425
53375
  ecosystem: adapter7.apiKind,
53426
53376
  packages: result.packages,
53427
53377
  decisionAction: kind,
53428
- bypassed: kind === "override",
53429
- bypassReason: kind === "override" ? parsed.dgForceReason : void 0
53378
+ bypassed: kind === "override"
53430
53379
  });
53431
53380
  } catch {
53432
53381
  }
@@ -53713,8 +53662,6 @@ async function main() {
53713
53662
  }
53714
53663
  if (result.action === "block") {
53715
53664
  try {
53716
- const reasonIdx = args.indexOf("--dg-force-reason");
53717
- const bypassReason = reasonIdx >= 0 ? args[reasonIdx + 1] : void 0;
53718
53665
  const { dispatchPublishCheckAudit: dispatchPublishCheckAudit2 } = await Promise.resolve().then(() => (init_audit_dispatcher(), audit_dispatcher_exports));
53719
53666
  const at = result.artifact.lastIndexOf("@");
53720
53667
  const pkgName = at > 0 ? result.artifact.slice(0, at) : result.artifact;
@@ -53725,8 +53672,7 @@ async function main() {
53725
53672
  packageVersion: pkgVersion,
53726
53673
  score: result.score,
53727
53674
  decisionAction: force ? "override" : "block",
53728
- bypassed: !!force,
53729
- bypassReason
53675
+ bypassed: !!force
53730
53676
  });
53731
53677
  } catch {
53732
53678
  }
@@ -53898,6 +53844,12 @@ async function main() {
53898
53844
  return;
53899
53845
  }
53900
53846
  }
53847
+ async function runHandoff(handoff) {
53848
+ if (!handoff.install) {
53849
+ return typeof process.exitCode === "number" ? process.exitCode : 0;
53850
+ }
53851
+ return handoff.install.run(handoff.install.args);
53852
+ }
53901
53853
  async function handleWrapInternal(argv) {
53902
53854
  let ecosystem = argv[0];
53903
53855
  if (!ecosystem) {
@@ -53934,9 +53886,9 @@ async function handleWrapInternal(argv) {
53934
53886
  const { isReadonlySubcommand: isReadonlySubcommand2 } = await Promise.resolve().then(() => (init_readonly(), readonly_exports));
53935
53887
  const ecoTyped = ecosystem;
53936
53888
  const spawnReal = async (real, args) => {
53937
- const { spawn: spawn7 } = await import("node:child_process");
53889
+ const { spawn: spawn8 } = await import("node:child_process");
53938
53890
  const { childInstallEnv: childInstallEnv2 } = await Promise.resolve().then(() => (init_install(), install_exports));
53939
- const child = spawn7(real, args, { stdio: "inherit", env: childInstallEnv2() });
53891
+ const child = spawn8(real, args, { stdio: "inherit", env: childInstallEnv2() });
53940
53892
  return await new Promise((resolve3) => {
53941
53893
  child.on("close", (code) => resolve3(code ?? 1));
53942
53894
  child.on("error", () => resolve3(1));
@@ -53963,11 +53915,12 @@ async function handleWrapInternal(argv) {
53963
53915
  const { render: render2 } = await init_build2().then(() => build_exports);
53964
53916
  const React22 = await Promise.resolve().then(() => __toESM(require_react(), 1));
53965
53917
  const { WrapperApp: WrapperApp2 } = await init_WrapperApp().then(() => WrapperApp_exports);
53918
+ const handoff = { install: null };
53966
53919
  const { waitUntilExit } = render2(
53967
- React22.createElement(WrapperApp2, { config, args: wrapperArgs, ecosystem: "npm" })
53920
+ React22.createElement(WrapperApp2, { config, args: wrapperArgs, ecosystem: "npm", handoff })
53968
53921
  );
53969
53922
  await waitUntilExit();
53970
- return 0;
53923
+ return runHandoff(handoff);
53971
53924
  }
53972
53925
  if (ecosystem === "pip" || ecosystem === "pip3") {
53973
53926
  if (config.json || !process.stdout.isTTY) {
@@ -53978,11 +53931,12 @@ async function handleWrapInternal(argv) {
53978
53931
  const { render: render2 } = await init_build2().then(() => build_exports);
53979
53932
  const React22 = await Promise.resolve().then(() => __toESM(require_react(), 1));
53980
53933
  const { WrapperApp: WrapperApp2 } = await init_WrapperApp().then(() => WrapperApp_exports);
53934
+ const handoff = { install: null };
53981
53935
  const { waitUntilExit } = render2(
53982
- React22.createElement(WrapperApp2, { config, args: wrapperArgs, ecosystem: "pypi" })
53936
+ React22.createElement(WrapperApp2, { config, args: wrapperArgs, ecosystem: "pypi", handoff })
53983
53937
  );
53984
53938
  await waitUntilExit();
53985
- return 0;
53939
+ return runHandoff(handoff);
53986
53940
  }
53987
53941
  if (ecosystem === "conda" || ecosystem === "mamba") {
53988
53942
  const { runStaticConda: runStaticConda2 } = await Promise.resolve().then(() => (init_conda_wrapper(), conda_wrapper_exports));
@@ -703,22 +703,26 @@ async function main() {
703
703
  } catch {
704
704
  }
705
705
  void ecosystemsWired;
706
+ const rcPath = rcAppended[0] ?? result.rcOutcomes.find((o) => o.status === "already-present")?.path ?? null;
707
+ const shimDir2 = `${targetHome}/.dg/shims`;
708
+ const activeNow = (process.env.PATH ?? "").split(":").includes(shimDir2);
706
709
  emit("\u2713 Dependency Guardian installed.");
707
- emit("\u2713 Protected: npm, pnpm, yarn, bun, pip, pip3, uv, pipx, conda, mamba.");
710
+ emit("\u2713 Wired: npm, pnpm, yarn, bun, pip, pip3, uv, pipx, conda, mamba.");
708
711
  if (pythonVersions.length > 0) {
709
- emit(`\u2713 python -m pip \u2014 protected on ${pythonVersions.join(", ")}.`);
710
- }
711
- if (rcAppended.length > 0) {
712
- for (const p of rcAppended) emit(`\u2713 Updated: ${p}`);
713
- } else {
714
- emit("\u2139\uFE0F Shell rc not modified (already wired or not detected).");
712
+ emit(`\u2713 python -m pip \u2014 wired on ${pythonVersions.join(", ")}.`);
715
713
  }
714
+ if (rcPath) emit(`\u2713 Added ${shimDir2} to PATH in ${rcPath}.`);
716
715
  emit("");
717
- emit("\u2728 Dependency Guardian is active. Happy scanning.");
718
- emit("");
719
- emit(" Run `dg login` to authenticate your account.");
720
- emit(" Run `dg status` to see what's protected.");
721
- emit(" Run `dg uninstall` to remove everything.");
716
+ if (!activeNow) {
717
+ emit(" \u26A0 One more step \u2014 activate it in your shell:");
718
+ emit(rcPath ? ` source ${rcPath} (or just open a new terminal)` : " open a new terminal");
719
+ emit(" Until you do, installs in THIS shell still run unscanned.");
720
+ emit("");
721
+ }
722
+ emit(" Then:");
723
+ emit(" dg login authenticate your account");
724
+ emit(" dg status see what's protected (and if this shell is active)");
725
+ emit(" dg uninstall remove everything");
722
726
  } catch (err) {
723
727
  emit("\u2139\uFE0F Dependency Guardian installed.");
724
728
  emit(` Setup did not complete: ${err.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@westbayberry/dg",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "type": "module",
5
5
  "description": "Supply chain security scanner for npm and Python dependencies",
6
6
  "bin": {