@westbayberry/dg 2.0.11 → 2.2.0

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.
Files changed (143) hide show
  1. package/README.md +216 -226
  2. package/dist/agents/claude-code.js +113 -0
  3. package/dist/agents/codex.js +65 -0
  4. package/dist/agents/copilot-cli.js +115 -0
  5. package/dist/agents/cursor.js +113 -0
  6. package/dist/agents/gemini.js +107 -0
  7. package/dist/agents/persistence.js +285 -0
  8. package/dist/agents/registry.js +127 -0
  9. package/dist/agents/types.js +1 -0
  10. package/dist/agents/windsurf.js +93 -0
  11. package/dist/api/analyze.js +6 -4
  12. package/dist/audit/detectors.js +0 -11
  13. package/dist/audit/events.js +5 -21
  14. package/dist/audit-ui/AuditApp.js +2 -0
  15. package/dist/audit-ui/components/AuditResultsView.js +55 -92
  16. package/dist/audit-ui/export.js +0 -4
  17. package/dist/audit-ui/format.js +0 -3
  18. package/dist/audit-ui/launch.js +10 -1
  19. package/dist/auth/device-login.js +4 -5
  20. package/dist/auth/login-app.js +7 -7
  21. package/dist/auth/store.js +8 -3
  22. package/dist/bin/dg.js +59 -52
  23. package/dist/commands/agents.js +231 -0
  24. package/dist/commands/audit.js +22 -3
  25. package/dist/commands/config.js +26 -10
  26. package/dist/commands/cooldown.js +389 -0
  27. package/dist/commands/decisions.js +169 -0
  28. package/dist/commands/doctor.js +1 -1
  29. package/dist/commands/help.js +1 -1
  30. package/dist/commands/licenses.js +10 -22
  31. package/dist/commands/logout.js +4 -11
  32. package/dist/commands/router.js +8 -4
  33. package/dist/commands/sbom.js +206 -0
  34. package/dist/commands/scan.js +3 -2
  35. package/dist/commands/service.js +32 -13
  36. package/dist/commands/setup.js +197 -27
  37. package/dist/commands/status.js +5 -2
  38. package/dist/commands/types.js +1 -0
  39. package/dist/commands/update.js +17 -8
  40. package/dist/commands/verify.js +8 -5
  41. package/dist/config/settings.js +154 -65
  42. package/dist/decisions/apply.js +128 -0
  43. package/dist/decisions/remember-prompt.js +92 -0
  44. package/dist/export-ui/ExportDialog.js +198 -0
  45. package/dist/install-ui/LiveInstall.js +2 -2
  46. package/dist/install-ui/block-render.js +21 -4
  47. package/dist/install-ui/prep-spinner.js +32 -0
  48. package/dist/install-ui/prompt.js +14 -0
  49. package/dist/launcher/agent-check.js +466 -0
  50. package/dist/launcher/agent-hook-exec.js +70 -0
  51. package/dist/launcher/agent-hook-io.js +31 -0
  52. package/dist/launcher/cargo-cache.js +40 -0
  53. package/dist/launcher/classify.js +17 -6
  54. package/dist/launcher/env.js +71 -24
  55. package/dist/launcher/install-preflight.js +167 -17
  56. package/dist/launcher/live-install.js +25 -5
  57. package/dist/launcher/output-redaction.js +7 -4
  58. package/dist/launcher/preflight-prompt.js +43 -3
  59. package/dist/launcher/run.js +100 -86
  60. package/dist/launcher/spawn-invocation.js +21 -0
  61. package/dist/policy/cooldown.js +117 -0
  62. package/dist/policy/evaluate.js +5 -21
  63. package/dist/policy/pypi-name.js +17 -0
  64. package/dist/presentation/mode.js +3 -2
  65. package/dist/presentation/package-page.js +9 -0
  66. package/dist/presentation/provenance.js +23 -0
  67. package/dist/presentation/theme.js +7 -7
  68. package/dist/project/dgfile.js +446 -0
  69. package/dist/proxy/auth.js +42 -0
  70. package/dist/proxy/ca.js +29 -9
  71. package/dist/proxy/cooldown-exemptions-file.js +33 -0
  72. package/dist/proxy/enforcement.js +57 -17
  73. package/dist/proxy/metadata-map.js +66 -4
  74. package/dist/proxy/preverified.js +55 -0
  75. package/dist/proxy/server.js +473 -45
  76. package/dist/proxy/worker.js +16 -1
  77. package/dist/publish-set/collect.js +1 -4
  78. package/dist/publish-set/npm.js +8 -5
  79. package/dist/publish-set/pack.js +9 -3
  80. package/dist/runtime/cli.js +0 -4
  81. package/dist/runtime/fatal.js +31 -0
  82. package/dist/runtime/first-run.js +12 -11
  83. package/dist/runtime/node-version.js +43 -6
  84. package/dist/runtime/nudges.js +35 -2
  85. package/dist/sbom/cyclonedx.js +211 -0
  86. package/dist/sbom-ui/SbomApp.js +158 -0
  87. package/dist/sbom-ui/components/SbomHeader.js +32 -0
  88. package/dist/sbom-ui/components/SbomList.js +52 -0
  89. package/dist/sbom-ui/inventory.js +128 -0
  90. package/dist/sbom-ui/launch.js +51 -0
  91. package/dist/sbom-ui/run.js +55 -0
  92. package/dist/sbom-ui/store.js +26 -0
  93. package/dist/scan/collect.js +10 -6
  94. package/dist/scan/command.js +51 -17
  95. package/dist/scan/discovery.js +11 -2
  96. package/dist/scan/render.js +63 -8
  97. package/dist/scan/scanner-report.js +42 -9
  98. package/dist/scan/staged.js +71 -11
  99. package/dist/scan-ui/LegacyApp.js +12 -16
  100. package/dist/scan-ui/alt-screen.js +5 -8
  101. package/dist/scan-ui/components/InteractiveResultsView.js +193 -123
  102. package/dist/scan-ui/components/ProgressBar.js +3 -14
  103. package/dist/scan-ui/components/ProjectSelector.js +1 -1
  104. package/dist/scan-ui/components/ScoreHeader.js +2 -3
  105. package/dist/scan-ui/components/SetupBanner.js +0 -6
  106. package/dist/scan-ui/format-helpers.js +61 -5
  107. package/dist/scan-ui/hooks/useResizeRepaint.js +25 -0
  108. package/dist/scan-ui/hooks/useScan.js +46 -4
  109. package/dist/scan-ui/launch.js +7 -4
  110. package/dist/scan-ui/shims.js +14 -4
  111. package/dist/scripts/detect.js +158 -0
  112. package/dist/scripts/gate.js +170 -0
  113. package/dist/service/state.js +27 -8
  114. package/dist/service/trust-refresh.js +92 -0
  115. package/dist/service/worker.js +23 -1
  116. package/dist/setup/activate-shell.js +28 -0
  117. package/dist/setup/git-hook.js +49 -4
  118. package/dist/setup/plan.js +98 -29
  119. package/dist/setup-ui/gate.js +39 -0
  120. package/dist/setup-ui/offer.js +42 -0
  121. package/dist/setup-ui/selector.js +27 -0
  122. package/dist/setup-ui/tasks.js +56 -0
  123. package/dist/setup-ui/wizard.js +225 -0
  124. package/dist/state/cooldown-held.js +66 -0
  125. package/dist/state/index.js +1 -0
  126. package/dist/state/locks.js +4 -2
  127. package/dist/state/store.js +2 -1
  128. package/dist/util/external-tool.js +25 -0
  129. package/dist/util/git.js +10 -3
  130. package/dist/util/json-file.js +24 -0
  131. package/dist/util/report-writer.js +57 -0
  132. package/dist/util/tty-prompt.js +13 -6
  133. package/dist/verify/local.js +240 -42
  134. package/dist/verify/package-check.js +86 -18
  135. package/dist/verify/preflight.js +242 -49
  136. package/dist/verify/render.js +15 -1
  137. package/npm-shrinkwrap.json +2383 -0
  138. package/package.json +14 -8
  139. package/NOTICE +0 -5
  140. package/dist/commands/completion.js +0 -116
  141. package/dist/commands/explain.js +0 -232
  142. package/dist/commands/unavailable.js +0 -11
  143. package/dist/telemetry/events.js +0 -40
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useCallback } from "react";
3
3
  import { Box, Text, useApp, useInput } from "ink";
4
+ import { EXIT_ANALYSIS_INCOMPLETE, EXIT_NOTHING_TO_SCAN } from "../commands/types.js";
4
5
  import { useScan } from "./hooks/useScan.js";
5
6
  import { Spinner } from "./components/Spinner.js";
6
7
  import { ProgressBar } from "./components/ProgressBar.js";
@@ -8,14 +9,15 @@ import { InteractiveResultsView } from "./components/InteractiveResultsView.js";
8
9
  import { ErrorView } from "./components/ErrorView.js";
9
10
  import { ProjectSelector } from "./components/ProjectSelector.js";
10
11
  import { SetupBanner } from "./components/SetupBanner.js";
11
- import { useTerminalSize } from "./hooks/useTerminalSize.js";
12
- import { scanExitCode } from "./shims.js";
12
+ import { useResizeRepaint } from "./hooks/useResizeRepaint.js";
13
+ import { effectiveScanAction, scanExitCode } from "./shims.js";
13
14
  import { leaveTui, showCursor, tuiIsActive } from "./alt-screen.js";
14
15
  import { formatResetDate } from "../install-ui/block-render.js";
15
- export const App = ({ config, userStatus, scanUsage, setupIssues = [], initialView, updateAvailable }) => {
16
+ import { accountHeaderLine } from "./shims.js";
17
+ export const App = ({ config, setupIssues = [], initialView, updateAvailable }) => {
16
18
  const { state, scanSelectedProjects, restartSelection } = useScan(config);
17
19
  const { exit } = useApp();
18
- useTerminalSize();
20
+ useResizeRepaint();
19
21
  const leaveAltScreen = useCallback(() => {
20
22
  if (tuiIsActive()) {
21
23
  leaveTui();
@@ -27,15 +29,12 @@ export const App = ({ config, userStatus, scanUsage, setupIssues = [], initialVi
27
29
  useEffect(() => () => leaveAltScreen(), [leaveAltScreen]);
28
30
  const handleResultsExit = useCallback(() => {
29
31
  if (state.phase === "results") {
30
- process.exitCode = scanExitCode(state.result.action, config.mode);
32
+ process.exitCode = scanExitCode(effectiveScanAction(state.result.action, state.decisions?.effectiveAction, config.mode), config.mode);
31
33
  }
32
34
  leaveAltScreen();
33
35
  exit();
34
36
  }, [state, config, exit, leaveAltScreen]);
35
37
  // Exit alt screen BEFORE writing messages so they appear on the main screen.
36
- // `delayMs` keeps the alt-screen panel visible for that long before tearing
37
- // down (default 0 — fire-and-exit). Used by the free_cap_reached path to
38
- // give the free_cap_reached path time to read the "sign in to unlock" panel.
39
38
  const exitWithMessage = useCallback((message, exitCode, delayMs = 0) => {
40
39
  process.exitCode = exitCode;
41
40
  if (delayMs === 0) {
@@ -51,18 +50,18 @@ export const App = ({ config, userStatus, scanUsage, setupIssues = [], initialVi
51
50
  }, [exit, leaveAltScreen]);
52
51
  useEffect(() => {
53
52
  if (state.phase === "empty") {
54
- const timer = exitWithMessage(`${state.message}\n`, 0);
53
+ const timer = exitWithMessage(`${state.message}\n`, EXIT_NOTHING_TO_SCAN);
55
54
  return () => clearTimeout(timer);
56
55
  }
57
56
  if (state.phase === "error") {
58
- const timer = exitWithMessage(`Error: ${state.error.message}\n`, 3);
57
+ const timer = exitWithMessage(`Error: ${state.error.message}\n`, EXIT_ANALYSIS_INCOMPLETE);
59
58
  return () => clearTimeout(timer);
60
59
  }
61
60
  // Reflect the verdict in the process exit code as soon as results render,
62
61
  // not only when the user dismisses the view — a piped/killed/non-TTY exit
63
62
  // must still carry the right code (an unverified scan is never a silent 0).
64
63
  if (state.phase === "results") {
65
- process.exitCode = scanExitCode(state.result.action, config.mode);
64
+ process.exitCode = scanExitCode(effectiveScanAction(state.result.action, state.decisions?.effectiveAction, config.mode), config.mode);
66
65
  }
67
66
  }, [state, config, exitWithMessage]);
68
67
  useInput((input, key) => {
@@ -91,13 +90,13 @@ export const App = ({ config, userStatus, scanUsage, setupIssues = [], initialVi
91
90
  return _jsx(Spinner, { label: `Found ${state.found} · ${path}` });
92
91
  }
93
92
  case "selecting":
94
- return (_jsx(ProjectSelector, { projects: state.projects, onConfirm: scanSelectedProjects, onCancel: () => { process.exitCode = 0; leaveAltScreen(); exit(); }, userStatus: userStatus }));
93
+ return (_jsx(ProjectSelector, { projects: state.projects, onConfirm: scanSelectedProjects, onCancel: () => { process.exitCode = 0; leaveAltScreen(); exit(); }, userStatus: accountHeaderLine() }));
95
94
  case "scanning":
96
95
  return (_jsx(ProgressBar, { value: state.done, total: state.total, label: state.batchCount > 1 && state.batchIndex >= 1
97
96
  ? `batch ${state.batchIndex}/${state.batchCount}`
98
97
  : undefined }));
99
98
  case "results":
100
- return (_jsx(InteractiveResultsView, { result: state.result, config: config, durationMs: state.durationMs, onExit: handleResultsExit, onBack: restartSelection ?? undefined, discoveredTotal: state.discoveredTotal, userStatus: userStatus, scanUsage: scanUsage, initialView: initialView }));
99
+ return (_jsx(InteractiveResultsView, { result: state.result, config: config, durationMs: state.durationMs, onExit: handleResultsExit, onBack: restartSelection ?? undefined, discoveredTotal: state.discoveredTotal, initialView: initialView, decisions: state.decisions }));
101
100
  case "empty":
102
101
  return _jsx(Text, { dimColor: true, children: state.message });
103
102
  case "error":
@@ -107,9 +106,6 @@ export const App = ({ config, userStatus, scanUsage, setupIssues = [], initialVi
107
106
  }
108
107
  }
109
108
  })();
110
- // Show the setup banner above the results — but not during empty/error/
111
- // free_cap_reached phases where it would compete with the message the user
112
- // actually needs to read.
113
109
  const showBanner = state.phase === "selecting" &&
114
110
  setupIssues.length > 0;
115
111
  // Results fill the terminal height exactly; an extra line there overflows the alt screen.
@@ -5,10 +5,12 @@ const HIDE_CURSOR = `${ESC}[?25l`;
5
5
  const SHOW_CURSOR = `${ESC}[?25h`;
6
6
  const MOUSE_1000_OFF = `${ESC}[?1000l`;
7
7
  const MOUSE_1003_OFF = `${ESC}[?1003l`;
8
- const CLEAR_HOME = `${ESC}[2J${ESC}[H`;
8
+ export const CLEAR_HOME = `${ESC}[2J${ESC}[H`;
9
9
  const CLEAR_LINE = `\r${ESC}[2K`;
10
10
  const TITLE = "Dependency Guardian";
11
11
  const TITLE_OSC = `${ESC}]0;${TITLE}\x07`;
12
+ const TITLE_PUSH = `${ESC}[22;0t`;
13
+ const TITLE_POP = `${ESC}[23;0t`;
12
14
  let tuiActive = false;
13
15
  let tuiHandle = null;
14
16
  let signalRegistrations = [];
@@ -43,7 +45,7 @@ function removeRestoreHandlers() {
43
45
  export function enterTui() {
44
46
  if (!process.stdout.isTTY || tuiActive)
45
47
  return;
46
- process.stdout.write(CLEAR_LINE + ALT_SCREEN_ON + HIDE_CURSOR + MOUSE_1000_OFF + MOUSE_1003_OFF + CLEAR_HOME + TITLE_OSC);
48
+ process.stdout.write(CLEAR_LINE + ALT_SCREEN_ON + HIDE_CURSOR + MOUSE_1000_OFF + MOUSE_1003_OFF + CLEAR_HOME + TITLE_PUSH + TITLE_OSC);
47
49
  tuiActive = true;
48
50
  installRestoreHandlers();
49
51
  if (!tuiHandle)
@@ -56,7 +58,7 @@ export function leaveTui() {
56
58
  clearInterval(tuiHandle);
57
59
  tuiHandle = null;
58
60
  }
59
- process.stdout.write(MOUSE_1003_OFF + MOUSE_1000_OFF + SHOW_CURSOR + ALT_SCREEN_OFF);
61
+ process.stdout.write(MOUSE_1003_OFF + MOUSE_1000_OFF + SHOW_CURSOR + ALT_SCREEN_OFF + TITLE_POP);
60
62
  tuiActive = false;
61
63
  removeRestoreHandlers();
62
64
  }
@@ -65,11 +67,6 @@ export function clearScreen() {
65
67
  return;
66
68
  process.stdout.write(CLEAR_HOME);
67
69
  }
68
- export function hideCursor() {
69
- if (!process.stdout.isTTY)
70
- return;
71
- process.stdout.write(HIDE_CURSOR);
72
- }
73
70
  export function showCursor() {
74
71
  if (!process.stdout.isTTY)
75
72
  return;