hackmyagent 0.11.3 → 0.11.4

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/cli.js CHANGED
@@ -1686,9 +1686,18 @@ Examples:
1686
1686
  .option('--registry-key <key>', 'Registry API key (default: REGISTRY_API_KEY env)')
1687
1687
  .option('--contribute', 'Share anonymized scan findings with OpenA2A Registry (overrides config)')
1688
1688
  .option('--no-contribute', 'Do not share findings for this scan (overrides config)')
1689
+ .option('--ci', 'CI mode: suppress interactive prompts, exit non-zero on findings')
1689
1690
  .action(async (directory, options) => {
1690
1691
  try {
1691
1692
  const targetDir = directory.startsWith('/') ? directory : process.cwd() + '/' + directory;
1693
+ // CI mode: force non-interactive defaults
1694
+ if (options.ci) {
1695
+ if (!options.format && !options.json)
1696
+ options.format = 'text';
1697
+ // In CI, never prompt -- only contribute if explicitly --contribute
1698
+ if (options.contribute === undefined)
1699
+ options.contribute = false;
1700
+ }
1692
1701
  // Check if directory exists
1693
1702
  if (!require('fs').existsSync(targetDir)) {
1694
1703
  console.error(`Error: Directory '${targetDir}' does not exist.`);
@@ -2124,7 +2133,10 @@ Examples:
2124
2133
  if (process.stdout.isTTY) {
2125
2134
  console.log(`${colors.cyan}Helpful?${RESET()} Star the project: https://github.com/opena2a-org/opena2a\n`);
2126
2135
  }
2127
- // Exit with non-zero if critical/high issues remain
2136
+ // Exit with non-zero if critical/high issues remain (or any issues in --ci mode)
2137
+ if (options.ci && issues.length > 0) {
2138
+ process.exit(1);
2139
+ }
2128
2140
  const criticalOrHigh = issues.filter((f) => f.severity === 'critical' || f.severity === 'high');
2129
2141
  if (criticalOrHigh.length > 0) {
2130
2142
  process.exit(1);
@@ -2390,7 +2402,9 @@ Examples:
2390
2402
  .option('-v, --verbose', 'Show detailed finding information')
2391
2403
  .action(async (target, options) => {
2392
2404
  try {
2393
- console.log(`\nScanning ${target}...\n`);
2405
+ if (!options.json) {
2406
+ console.log(`\nScanning ${target}...\n`);
2407
+ }
2394
2408
  const scanner = new index_1.ExternalScanner();
2395
2409
  const customPorts = options.ports
2396
2410
  ? options.ports.split(',').map((p) => parseInt(p.trim(), 10))
@@ -4018,9 +4032,15 @@ Examples:
4018
4032
  .option('--registry-url <url>', 'Registry URL (default: REGISTRY_URL env)', process.env.REGISTRY_URL || 'https://api.oa2a.org')
4019
4033
  .option('--contribute', 'Share anonymized scan findings with OpenA2A Registry (overrides config)')
4020
4034
  .option('--no-contribute', 'Do not share findings for this scan (overrides config)')
4035
+ .option('--ci', 'CI mode: suppress interactive prompts, exit non-zero on findings')
4021
4036
  .action(async (directory, options) => {
4022
4037
  try {
4023
4038
  const targetDir = directory.startsWith('/') ? directory : process.cwd() + '/' + directory;
4039
+ // CI mode: force non-interactive defaults
4040
+ if (options.ci) {
4041
+ if (options.contribute === undefined)
4042
+ options.contribute = false;
4043
+ }
4024
4044
  if (!require('fs').existsSync(targetDir)) {
4025
4045
  process.stderr.write(`Error: Directory '${targetDir}' does not exist.\n`);
4026
4046
  process.exit(1);
@@ -4184,6 +4204,13 @@ Examples:
4184
4204
  // Community contribution: share anonymized findings with OpenA2A Registry
4185
4205
  const soulFormat = options.json ? 'json' : 'text';
4186
4206
  await handleSoulContribution(options.contribute, targetDir, result, options.registryUrl, soulFormat);
4207
+ // In CI mode, exit non-zero if any controls failed
4208
+ if (options.ci) {
4209
+ const failedControls = result.domains.flatMap(d => d.controls).filter(c => !c.passed);
4210
+ if (failedControls.length > 0) {
4211
+ process.exit(1);
4212
+ }
4213
+ }
4187
4214
  // Check fail threshold
4188
4215
  if (options.failBelow) {
4189
4216
  const threshold = parseInt(options.failBelow, 10);