nexus-agents 4.1.1 → 4.1.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.
@@ -22,7 +22,7 @@ import {
22
22
  DEFAULT_TASK_TTL_MS,
23
23
  DEFAULT_TOOL_RATE_LIMITS,
24
24
  clampTaskTtl
25
- } from "./chunk-RCSHGEIL.js";
25
+ } from "./chunk-GSUC22YA.js";
26
26
  import {
27
27
  executeExpert
28
28
  } from "./chunk-4Z2Z52C7.js";
@@ -44545,7 +44545,10 @@ function buildHarnessResult(planResult, tasks) {
44545
44545
  tasks,
44546
44546
  voteIterations: planResult.iterations,
44547
44547
  qaIterations: 0,
44548
- securityPassed: false
44548
+ // Harness mode hands the tasks back for someone else to implement, so the
44549
+ // scan never ran. `securityPassed: false` alone would read as a rejection.
44550
+ securityPassed: false,
44551
+ securityRan: false
44549
44552
  };
44550
44553
  }
44551
44554
  async function runImplSecurityPhase(planResult, tasks, stages, sid, qualityGateMode) {
@@ -44560,7 +44563,9 @@ async function runImplSecurityPhase(planResult, tasks, stages, sid, qualityGateM
44560
44563
  tasks: implResult.completedTasks.length > 0 ? implResult.completedTasks : tasks,
44561
44564
  voteIterations: planResult.iterations,
44562
44565
  qaIterations: implResult.totalIterations,
44563
- securityPassed: false
44566
+ // The gate short-circuited before the scan — absence, not a verdict.
44567
+ securityPassed: false,
44568
+ securityRan: false
44564
44569
  };
44565
44570
  }
44566
44571
  const security = await withStep(
@@ -44581,7 +44586,8 @@ async function runImplSecurityPhase(planResult, tasks, stages, sid, qualityGateM
44581
44586
  tasks: implResult.completedTasks.length > 0 ? implResult.completedTasks : tasks,
44582
44587
  voteIterations: planResult.iterations,
44583
44588
  qaIterations: implResult.totalIterations,
44584
- securityPassed: security.passed
44589
+ securityPassed: security.passed,
44590
+ securityRan: true
44585
44591
  };
44586
44592
  }
44587
44593
  async function runQualityGateStage(stages, mode) {
@@ -48442,6 +48448,8 @@ async function loadAuditEvents(dir, logger59) {
48442
48448
  const entries = await fs9.readdir(dir);
48443
48449
  const auditFiles = entries.filter((name) => name.startsWith("audit-") && name.endsWith(".jsonl")).sort();
48444
48450
  const events = [];
48451
+ let skippedLines = 0;
48452
+ let unreadableFiles = 0;
48445
48453
  for (const filename of auditFiles) {
48446
48454
  const fullPath = path8.join(dir, filename);
48447
48455
  let content;
@@ -48450,6 +48458,7 @@ async function loadAuditEvents(dir, logger59) {
48450
48458
  } catch (cause) {
48451
48459
  const msg = cause instanceof Error ? cause.message : String(cause);
48452
48460
  logger59.warn("Skipping unreadable audit log file", { filename, error: msg });
48461
+ unreadableFiles++;
48453
48462
  continue;
48454
48463
  }
48455
48464
  for (const line of content.split("\n")) {
@@ -48464,14 +48473,16 @@ async function loadAuditEvents(dir, logger59) {
48464
48473
  filename,
48465
48474
  error: validated.error.message
48466
48475
  });
48476
+ skippedLines++;
48467
48477
  }
48468
48478
  } catch (cause) {
48469
48479
  const msg = cause instanceof Error ? cause.message : String(cause);
48470
48480
  logger59.warn("Skipping unparseable audit event", { filename, error: msg });
48481
+ skippedLines++;
48471
48482
  }
48472
48483
  }
48473
48484
  }
48474
- return { events, fileCount: auditFiles.length };
48485
+ return { events, fileCount: auditFiles.length, skippedLines, unreadableFiles };
48475
48486
  }
48476
48487
  async function handler2(args, ctx) {
48477
48488
  const parsed = VerifyAuditChainInputSchema.safeParse(args);
@@ -48498,12 +48509,17 @@ async function handler2(args, ctx) {
48498
48509
  message: `logDir "${resolvedDir}" is not a directory`
48499
48510
  });
48500
48511
  }
48501
- const { events, fileCount } = await loadAuditEvents(resolvedDir, ctx.logger);
48512
+ const { events, fileCount, skippedLines, unreadableFiles } = await loadAuditEvents(
48513
+ resolvedDir,
48514
+ ctx.logger
48515
+ );
48502
48516
  const verification = verifyChain(events);
48503
48517
  const response = {
48504
48518
  logDir: resolvedDir,
48505
48519
  fileCount,
48506
48520
  eventCount: events.length,
48521
+ ...skippedLines > 0 ? { skippedLines } : {},
48522
+ ...unreadableFiles > 0 ? { unreadableFiles } : {},
48507
48523
  verification
48508
48524
  };
48509
48525
  return toolSuccess(JSON.stringify(response, null, 2));
@@ -48515,7 +48531,7 @@ function registerVerifyAuditChainTool(server, deps) {
48515
48531
  "Filesystem path to the FileAuditStorage log directory. Tool reads all `audit-*.jsonl` files and verifies the combined hash chain."
48516
48532
  )
48517
48533
  };
48518
- const description = "Verify the hash chain of a persisted FileAuditStorage audit log. Reads all `audit-*.jsonl` files in the given directory, parses events, and runs `verifyChain()` to detect tampering. Returns a structured result with eventCount, fileCount, and one of three tamper signals if detected (hash_mismatch, previous_hash_mismatch, missing_hash). Read-only \u2014 never writes or deletes events.";
48534
+ const description = "Verify the hash chain of a persisted FileAuditStorage audit log. Reads all `audit-*.jsonl` files in the given directory, parses events, and runs `verifyChain()` to detect tampering. Returns a structured result with eventCount, fileCount, and one of three tamper signals if detected (hash_mismatch, previous_hash_mismatch, missing_hash). Reports skippedLines/unreadableFiles when part of the log could not be read, so a verdict over a partial log is never mistaken for a complete one. Read-only \u2014 never writes or deletes events.";
48519
48535
  const secureHandler = createSecureHandler(handler2, {
48520
48536
  toolName: "verify_audit_chain",
48521
48537
  rateLimiter: deps.rateLimiter,
@@ -49766,6 +49782,13 @@ function buildStructuredOutput(result, simulated) {
49766
49782
  ...simulated ? { simulated: true } : {},
49767
49783
  completed: result.completed,
49768
49784
  securityPassed: result.securityPassed,
49785
+ // #4772: these two are what make `completed: false` legible. Without them a
49786
+ // caller cannot tell a failed planner from a successful dry run, or a
49787
+ // security rejection from a gate that never ran — which is the whole point
49788
+ // of the fields. They were added to DevPipelineResult and then not listed
49789
+ // here, so they never reached the MCP surface.
49790
+ ...result.securityRan !== void 0 ? { securityRan: result.securityRan } : {},
49791
+ ...result.planStatus !== void 0 ? { planStatus: result.planStatus } : {},
49769
49792
  voteIterations: result.voteIterations,
49770
49793
  qaIterations: result.qaIterations,
49771
49794
  plan: result.plan,
@@ -50237,13 +50260,26 @@ function detectEngineFailure(result) {
50237
50260
  const record = result;
50238
50261
  if (record["success"] === false) {
50239
50262
  const detail = typeof record["error"] === "string" ? record["error"] : "no error message";
50240
- return `Engine reported failure: ${detail}`;
50263
+ return { message: `Engine reported failure: ${detail}` };
50241
50264
  }
50242
50265
  if (record["completed"] === false) {
50243
- return "Engine reported failure: the dev pipeline did not complete";
50266
+ return { message: describeIncompletePipeline(record), detail: record };
50244
50267
  }
50245
50268
  return null;
50246
50269
  }
50270
+ function describeIncompletePipeline(record) {
50271
+ const prefix = "Engine reported failure:";
50272
+ if (record["planStatus"] === "empty") {
50273
+ return `${prefix} the planner returned no plan, so nothing was built`;
50274
+ }
50275
+ if (record["securityRan"] === true) {
50276
+ return `${prefix} the security gate rejected the change`;
50277
+ }
50278
+ if (record["securityRan"] === false) {
50279
+ return `${prefix} the run stopped before the security gate, which never ran`;
50280
+ }
50281
+ return `${prefix} the dev pipeline did not complete`;
50282
+ }
50247
50283
  async function executeRunBody(input, logger59, trustTier, gatewayAdapters) {
50248
50284
  try {
50249
50285
  const exec2 = await executeGoal(input, {
@@ -50262,7 +50298,11 @@ async function executeRunBody(input, logger59, trustTier, gatewayAdapters) {
50262
50298
  decisionId: exec2.decisionId,
50263
50299
  strategy: exec2.strategy
50264
50300
  });
50265
- return toolStructuredError({ errorCategory: "business", message: engineFailure });
50301
+ return toolStructuredError({
50302
+ errorCategory: "business",
50303
+ message: engineFailure.message,
50304
+ ...engineFailure.detail !== void 0 ? { detail: engineFailure.detail } : {}
50305
+ });
50266
50306
  }
50267
50307
  return toolSuccess(JSON.stringify(exec2, null, 2));
50268
50308
  } catch (err2) {
@@ -54416,4 +54456,4 @@ export {
54416
54456
  shutdownFeedbackSubscriber,
54417
54457
  createEventBusBridge
54418
54458
  };
54419
- //# sourceMappingURL=chunk-UFWTULMJ.js.map
54459
+ //# sourceMappingURL=chunk-CKOUOEK2.js.map